##// END OF EJS Templates
merge with stable
Matt Mackall -
r15909:8435fa20 merge default
parent child Browse files
Show More
@@ -1,500 +1,500 b''
1 # Copyright 2009-2010 Gregory P. Ward
1 # Copyright 2009-2010 Gregory P. Ward
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 # Copyright 2010-2011 Fog Creek Software
3 # Copyright 2010-2011 Fog Creek Software
4 # Copyright 2010-2011 Unity Technologies
4 # Copyright 2010-2011 Unity Technologies
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 '''High-level command function for lfconvert, plus the cmdtable.'''
9 '''High-level command function for lfconvert, plus the cmdtable.'''
10
10
11 import os
11 import os
12 import shutil
12 import shutil
13
13
14 from mercurial import util, match as match_, hg, node, context, error
14 from mercurial import util, match as match_, hg, node, context, error
15 from mercurial.i18n import _
15 from mercurial.i18n import _
16
16
17 import lfutil
17 import lfutil
18 import basestore
18 import basestore
19
19
20 # -- Commands ----------------------------------------------------------
20 # -- Commands ----------------------------------------------------------
21
21
22 def lfconvert(ui, src, dest, *pats, **opts):
22 def lfconvert(ui, src, dest, *pats, **opts):
23 '''convert a normal repository to a largefiles repository
23 '''convert a normal repository to a largefiles repository
24
24
25 Convert repository SOURCE to a new repository DEST, identical to
25 Convert repository SOURCE to a new repository DEST, identical to
26 SOURCE except that certain files will be converted as largefiles:
26 SOURCE except that certain files will be converted as largefiles:
27 specifically, any file that matches any PATTERN *or* whose size is
27 specifically, any file that matches any PATTERN *or* whose size is
28 above the minimum size threshold is converted as a largefile. The
28 above the minimum size threshold is converted as a largefile. The
29 size used to determine whether or not to track a file as a
29 size used to determine whether or not to track a file as a
30 largefile is the size of the first version of the file. The
30 largefile is the size of the first version of the file. The
31 minimum size can be specified either with --size or in
31 minimum size can be specified either with --size or in
32 configuration as ``largefiles.size``.
32 configuration as ``largefiles.size``.
33
33
34 After running this command you will need to make sure that
34 After running this command you will need to make sure that
35 largefiles is enabled anywhere you intend to push the new
35 largefiles is enabled anywhere you intend to push the new
36 repository.
36 repository.
37
37
38 Use --to-normal to convert largefiles back to normal files; after
38 Use --to-normal to convert largefiles back to normal files; after
39 this, the DEST repository can be used without largefiles at all.'''
39 this, the DEST repository can be used without largefiles at all.'''
40
40
41 if opts['to_normal']:
41 if opts['to_normal']:
42 tolfile = False
42 tolfile = False
43 else:
43 else:
44 tolfile = True
44 tolfile = True
45 size = lfutil.getminsize(ui, True, opts.get('size'), default=None)
45 size = lfutil.getminsize(ui, True, opts.get('size'), default=None)
46
46
47 if not hg.islocal(src):
47 if not hg.islocal(src):
48 raise util.Abort(_('%s is not a local Mercurial repo') % src)
48 raise util.Abort(_('%s is not a local Mercurial repo') % src)
49 if not hg.islocal(dest):
49 if not hg.islocal(dest):
50 raise util.Abort(_('%s is not a local Mercurial repo') % dest)
50 raise util.Abort(_('%s is not a local Mercurial repo') % dest)
51
51
52 rsrc = hg.repository(ui, src)
52 rsrc = hg.repository(ui, src)
53 ui.status(_('initializing destination %s\n') % dest)
53 ui.status(_('initializing destination %s\n') % dest)
54 rdst = hg.repository(ui, dest, create=True)
54 rdst = hg.repository(ui, dest, create=True)
55
55
56 success = False
56 success = False
57 try:
57 try:
58 # Lock destination to prevent modification while it is converted to.
58 # Lock destination to prevent modification while it is converted to.
59 # Don't need to lock src because we are just reading from its history
59 # Don't need to lock src because we are just reading from its history
60 # which can't change.
60 # which can't change.
61 dst_lock = rdst.lock()
61 dst_lock = rdst.lock()
62
62
63 # Get a list of all changesets in the source. The easy way to do this
63 # Get a list of all changesets in the source. The easy way to do this
64 # is to simply walk the changelog, using changelog.nodesbewteen().
64 # is to simply walk the changelog, using changelog.nodesbewteen().
65 # Take a look at mercurial/revlog.py:639 for more details.
65 # Take a look at mercurial/revlog.py:639 for more details.
66 # Use a generator instead of a list to decrease memory usage
66 # Use a generator instead of a list to decrease memory usage
67 ctxs = (rsrc[ctx] for ctx in rsrc.changelog.nodesbetween(None,
67 ctxs = (rsrc[ctx] for ctx in rsrc.changelog.nodesbetween(None,
68 rsrc.heads())[0])
68 rsrc.heads())[0])
69 revmap = {node.nullid: node.nullid}
69 revmap = {node.nullid: node.nullid}
70 if tolfile:
70 if tolfile:
71 lfiles = set()
71 lfiles = set()
72 normalfiles = set()
72 normalfiles = set()
73 if not pats:
73 if not pats:
74 pats = ui.configlist(lfutil.longname, 'patterns', default=[])
74 pats = ui.configlist(lfutil.longname, 'patterns', default=[])
75 if pats:
75 if pats:
76 matcher = match_.match(rsrc.root, '', list(pats))
76 matcher = match_.match(rsrc.root, '', list(pats))
77 else:
77 else:
78 matcher = None
78 matcher = None
79
79
80 lfiletohash = {}
80 lfiletohash = {}
81 for ctx in ctxs:
81 for ctx in ctxs:
82 ui.progress(_('converting revisions'), ctx.rev(),
82 ui.progress(_('converting revisions'), ctx.rev(),
83 unit=_('revision'), total=rsrc['tip'].rev())
83 unit=_('revision'), total=rsrc['tip'].rev())
84 _lfconvert_addchangeset(rsrc, rdst, ctx, revmap,
84 _lfconvert_addchangeset(rsrc, rdst, ctx, revmap,
85 lfiles, normalfiles, matcher, size, lfiletohash)
85 lfiles, normalfiles, matcher, size, lfiletohash)
86 ui.progress(_('converting revisions'), None)
86 ui.progress(_('converting revisions'), None)
87
87
88 if os.path.exists(rdst.wjoin(lfutil.shortname)):
88 if os.path.exists(rdst.wjoin(lfutil.shortname)):
89 shutil.rmtree(rdst.wjoin(lfutil.shortname))
89 shutil.rmtree(rdst.wjoin(lfutil.shortname))
90
90
91 for f in lfiletohash.keys():
91 for f in lfiletohash.keys():
92 if os.path.isfile(rdst.wjoin(f)):
92 if os.path.isfile(rdst.wjoin(f)):
93 os.unlink(rdst.wjoin(f))
93 os.unlink(rdst.wjoin(f))
94 try:
94 try:
95 os.removedirs(os.path.dirname(rdst.wjoin(f)))
95 os.removedirs(os.path.dirname(rdst.wjoin(f)))
96 except OSError:
96 except OSError:
97 pass
97 pass
98
98
99 # If there were any files converted to largefiles, add largefiles
99 # If there were any files converted to largefiles, add largefiles
100 # to the destination repository's requirements.
100 # to the destination repository's requirements.
101 if lfiles:
101 if lfiles:
102 rdst.requirements.add('largefiles')
102 rdst.requirements.add('largefiles')
103 rdst._writerequirements()
103 rdst._writerequirements()
104 else:
104 else:
105 for ctx in ctxs:
105 for ctx in ctxs:
106 ui.progress(_('converting revisions'), ctx.rev(),
106 ui.progress(_('converting revisions'), ctx.rev(),
107 unit=_('revision'), total=rsrc['tip'].rev())
107 unit=_('revision'), total=rsrc['tip'].rev())
108 _addchangeset(ui, rsrc, rdst, ctx, revmap)
108 _addchangeset(ui, rsrc, rdst, ctx, revmap)
109
109
110 ui.progress(_('converting revisions'), None)
110 ui.progress(_('converting revisions'), None)
111 success = True
111 success = True
112 finally:
112 finally:
113 if not success:
113 if not success:
114 # we failed, remove the new directory
114 # we failed, remove the new directory
115 shutil.rmtree(rdst.root)
115 shutil.rmtree(rdst.root)
116 dst_lock.release()
116 dst_lock.release()
117
117
118 def _addchangeset(ui, rsrc, rdst, ctx, revmap):
118 def _addchangeset(ui, rsrc, rdst, ctx, revmap):
119 # Convert src parents to dst parents
119 # Convert src parents to dst parents
120 parents = _convertparents(ctx, revmap)
120 parents = _convertparents(ctx, revmap)
121
121
122 # Generate list of changed files
122 # Generate list of changed files
123 files = _getchangedfiles(ctx, parents)
123 files = _getchangedfiles(ctx, parents)
124
124
125 def getfilectx(repo, memctx, f):
125 def getfilectx(repo, memctx, f):
126 if lfutil.standin(f) in files:
126 if lfutil.standin(f) in files:
127 # if the file isn't in the manifest then it was removed
127 # if the file isn't in the manifest then it was removed
128 # or renamed, raise IOError to indicate this
128 # or renamed, raise IOError to indicate this
129 try:
129 try:
130 fctx = ctx.filectx(lfutil.standin(f))
130 fctx = ctx.filectx(lfutil.standin(f))
131 except error.LookupError:
131 except error.LookupError:
132 raise IOError()
132 raise IOError()
133 renamed = fctx.renamed()
133 renamed = fctx.renamed()
134 if renamed:
134 if renamed:
135 renamed = lfutil.splitstandin(renamed[0])
135 renamed = lfutil.splitstandin(renamed[0])
136
136
137 hash = fctx.data().strip()
137 hash = fctx.data().strip()
138 path = lfutil.findfile(rsrc, hash)
138 path = lfutil.findfile(rsrc, hash)
139 ### TODO: What if the file is not cached?
139 ### TODO: What if the file is not cached?
140 data = ''
140 data = ''
141 fd = None
141 fd = None
142 try:
142 try:
143 fd = open(path, 'rb')
143 fd = open(path, 'rb')
144 data = fd.read()
144 data = fd.read()
145 finally:
145 finally:
146 if fd:
146 if fd:
147 fd.close()
147 fd.close()
148 return context.memfilectx(f, data, 'l' in fctx.flags(),
148 return context.memfilectx(f, data, 'l' in fctx.flags(),
149 'x' in fctx.flags(), renamed)
149 'x' in fctx.flags(), renamed)
150 else:
150 else:
151 return _getnormalcontext(repo.ui, ctx, f, revmap)
151 return _getnormalcontext(repo.ui, ctx, f, revmap)
152
152
153 dstfiles = []
153 dstfiles = []
154 for file in files:
154 for file in files:
155 if lfutil.isstandin(file):
155 if lfutil.isstandin(file):
156 dstfiles.append(lfutil.splitstandin(file))
156 dstfiles.append(lfutil.splitstandin(file))
157 else:
157 else:
158 dstfiles.append(file)
158 dstfiles.append(file)
159 # Commit
159 # Commit
160 _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
160 _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
161
161
162 def _lfconvert_addchangeset(rsrc, rdst, ctx, revmap, lfiles, normalfiles,
162 def _lfconvert_addchangeset(rsrc, rdst, ctx, revmap, lfiles, normalfiles,
163 matcher, size, lfiletohash):
163 matcher, size, lfiletohash):
164 # Convert src parents to dst parents
164 # Convert src parents to dst parents
165 parents = _convertparents(ctx, revmap)
165 parents = _convertparents(ctx, revmap)
166
166
167 # Generate list of changed files
167 # Generate list of changed files
168 files = _getchangedfiles(ctx, parents)
168 files = _getchangedfiles(ctx, parents)
169
169
170 dstfiles = []
170 dstfiles = []
171 for f in files:
171 for f in files:
172 if f not in lfiles and f not in normalfiles:
172 if f not in lfiles and f not in normalfiles:
173 islfile = _islfile(f, ctx, matcher, size)
173 islfile = _islfile(f, ctx, matcher, size)
174 # If this file was renamed or copied then copy
174 # If this file was renamed or copied then copy
175 # the lfileness of its predecessor
175 # the lfileness of its predecessor
176 if f in ctx.manifest():
176 if f in ctx.manifest():
177 fctx = ctx.filectx(f)
177 fctx = ctx.filectx(f)
178 renamed = fctx.renamed()
178 renamed = fctx.renamed()
179 renamedlfile = renamed and renamed[0] in lfiles
179 renamedlfile = renamed and renamed[0] in lfiles
180 islfile |= renamedlfile
180 islfile |= renamedlfile
181 if 'l' in fctx.flags():
181 if 'l' in fctx.flags():
182 if renamedlfile:
182 if renamedlfile:
183 raise util.Abort(
183 raise util.Abort(
184 _('renamed/copied largefile %s becomes symlink')
184 _('renamed/copied largefile %s becomes symlink')
185 % f)
185 % f)
186 islfile = False
186 islfile = False
187 if islfile:
187 if islfile:
188 lfiles.add(f)
188 lfiles.add(f)
189 else:
189 else:
190 normalfiles.add(f)
190 normalfiles.add(f)
191
191
192 if f in lfiles:
192 if f in lfiles:
193 dstfiles.append(lfutil.standin(f))
193 dstfiles.append(lfutil.standin(f))
194 # largefile in manifest if it has not been removed/renamed
194 # largefile in manifest if it has not been removed/renamed
195 if f in ctx.manifest():
195 if f in ctx.manifest():
196 fctx = ctx.filectx(f)
196 fctx = ctx.filectx(f)
197 if 'l' in fctx.flags():
197 if 'l' in fctx.flags():
198 renamed = fctx.renamed()
198 renamed = fctx.renamed()
199 if renamed and renamed[0] in lfiles:
199 if renamed and renamed[0] in lfiles:
200 raise util.Abort(_('largefile %s becomes symlink') % f)
200 raise util.Abort(_('largefile %s becomes symlink') % f)
201
201
202 # largefile was modified, update standins
202 # largefile was modified, update standins
203 fullpath = rdst.wjoin(f)
203 fullpath = rdst.wjoin(f)
204 util.makedirs(os.path.dirname(fullpath))
204 util.makedirs(os.path.dirname(fullpath))
205 m = util.sha1('')
205 m = util.sha1('')
206 m.update(ctx[f].data())
206 m.update(ctx[f].data())
207 hash = m.hexdigest()
207 hash = m.hexdigest()
208 if f not in lfiletohash or lfiletohash[f] != hash:
208 if f not in lfiletohash or lfiletohash[f] != hash:
209 try:
209 try:
210 fd = open(fullpath, 'wb')
210 fd = open(fullpath, 'wb')
211 fd.write(ctx[f].data())
211 fd.write(ctx[f].data())
212 finally:
212 finally:
213 if fd:
213 if fd:
214 fd.close()
214 fd.close()
215 executable = 'x' in ctx[f].flags()
215 executable = 'x' in ctx[f].flags()
216 os.chmod(fullpath, lfutil.getmode(executable))
216 os.chmod(fullpath, lfutil.getmode(executable))
217 lfutil.writestandin(rdst, lfutil.standin(f), hash,
217 lfutil.writestandin(rdst, lfutil.standin(f), hash,
218 executable)
218 executable)
219 lfiletohash[f] = hash
219 lfiletohash[f] = hash
220 else:
220 else:
221 # normal file
221 # normal file
222 dstfiles.append(f)
222 dstfiles.append(f)
223
223
224 def getfilectx(repo, memctx, f):
224 def getfilectx(repo, memctx, f):
225 if lfutil.isstandin(f):
225 if lfutil.isstandin(f):
226 # if the file isn't in the manifest then it was removed
226 # if the file isn't in the manifest then it was removed
227 # or renamed, raise IOError to indicate this
227 # or renamed, raise IOError to indicate this
228 srcfname = lfutil.splitstandin(f)
228 srcfname = lfutil.splitstandin(f)
229 try:
229 try:
230 fctx = ctx.filectx(srcfname)
230 fctx = ctx.filectx(srcfname)
231 except error.LookupError:
231 except error.LookupError:
232 raise IOError()
232 raise IOError()
233 renamed = fctx.renamed()
233 renamed = fctx.renamed()
234 if renamed:
234 if renamed:
235 # standin is always a largefile because largefile-ness
235 # standin is always a largefile because largefile-ness
236 # doesn't change after rename or copy
236 # doesn't change after rename or copy
237 renamed = lfutil.standin(renamed[0])
237 renamed = lfutil.standin(renamed[0])
238
238
239 return context.memfilectx(f, lfiletohash[srcfname] + '\n', 'l' in
239 return context.memfilectx(f, lfiletohash[srcfname] + '\n', 'l' in
240 fctx.flags(), 'x' in fctx.flags(), renamed)
240 fctx.flags(), 'x' in fctx.flags(), renamed)
241 else:
241 else:
242 return _getnormalcontext(repo.ui, ctx, f, revmap)
242 return _getnormalcontext(repo.ui, ctx, f, revmap)
243
243
244 # Commit
244 # Commit
245 _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
245 _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
246
246
247 def _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap):
247 def _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap):
248 mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
248 mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
249 getfilectx, ctx.user(), ctx.date(), ctx.extra())
249 getfilectx, ctx.user(), ctx.date(), ctx.extra())
250 ret = rdst.commitctx(mctx)
250 ret = rdst.commitctx(mctx)
251 rdst.dirstate.setparents(ret)
251 rdst.dirstate.setparents(ret)
252 revmap[ctx.node()] = rdst.changelog.tip()
252 revmap[ctx.node()] = rdst.changelog.tip()
253
253
254 # Generate list of changed files
254 # Generate list of changed files
255 def _getchangedfiles(ctx, parents):
255 def _getchangedfiles(ctx, parents):
256 files = set(ctx.files())
256 files = set(ctx.files())
257 if node.nullid not in parents:
257 if node.nullid not in parents:
258 mc = ctx.manifest()
258 mc = ctx.manifest()
259 mp1 = ctx.parents()[0].manifest()
259 mp1 = ctx.parents()[0].manifest()
260 mp2 = ctx.parents()[1].manifest()
260 mp2 = ctx.parents()[1].manifest()
261 files |= (set(mp1) | set(mp2)) - set(mc)
261 files |= (set(mp1) | set(mp2)) - set(mc)
262 for f in mc:
262 for f in mc:
263 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
263 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
264 files.add(f)
264 files.add(f)
265 return files
265 return files
266
266
267 # Convert src parents to dst parents
267 # Convert src parents to dst parents
268 def _convertparents(ctx, revmap):
268 def _convertparents(ctx, revmap):
269 parents = []
269 parents = []
270 for p in ctx.parents():
270 for p in ctx.parents():
271 parents.append(revmap[p.node()])
271 parents.append(revmap[p.node()])
272 while len(parents) < 2:
272 while len(parents) < 2:
273 parents.append(node.nullid)
273 parents.append(node.nullid)
274 return parents
274 return parents
275
275
276 # Get memfilectx for a normal file
276 # Get memfilectx for a normal file
277 def _getnormalcontext(ui, ctx, f, revmap):
277 def _getnormalcontext(ui, ctx, f, revmap):
278 try:
278 try:
279 fctx = ctx.filectx(f)
279 fctx = ctx.filectx(f)
280 except error.LookupError:
280 except error.LookupError:
281 raise IOError()
281 raise IOError()
282 renamed = fctx.renamed()
282 renamed = fctx.renamed()
283 if renamed:
283 if renamed:
284 renamed = renamed[0]
284 renamed = renamed[0]
285
285
286 data = fctx.data()
286 data = fctx.data()
287 if f == '.hgtags':
287 if f == '.hgtags':
288 data = _converttags (ui, revmap, data)
288 data = _converttags (ui, revmap, data)
289 return context.memfilectx(f, data, 'l' in fctx.flags(),
289 return context.memfilectx(f, data, 'l' in fctx.flags(),
290 'x' in fctx.flags(), renamed)
290 'x' in fctx.flags(), renamed)
291
291
292 # Remap tag data using a revision map
292 # Remap tag data using a revision map
293 def _converttags(ui, revmap, data):
293 def _converttags(ui, revmap, data):
294 newdata = []
294 newdata = []
295 for line in data.splitlines():
295 for line in data.splitlines():
296 try:
296 try:
297 id, name = line.split(' ', 1)
297 id, name = line.split(' ', 1)
298 except ValueError:
298 except ValueError:
299 ui.warn(_('skipping incorrectly formatted tag %s\n'
299 ui.warn(_('skipping incorrectly formatted tag %s\n'
300 % line))
300 % line))
301 continue
301 continue
302 try:
302 try:
303 newid = node.bin(id)
303 newid = node.bin(id)
304 except TypeError:
304 except TypeError:
305 ui.warn(_('skipping incorrectly formatted id %s\n'
305 ui.warn(_('skipping incorrectly formatted id %s\n'
306 % id))
306 % id))
307 continue
307 continue
308 try:
308 try:
309 newdata.append('%s %s\n' % (node.hex(revmap[newid]),
309 newdata.append('%s %s\n' % (node.hex(revmap[newid]),
310 name))
310 name))
311 except KeyError:
311 except KeyError:
312 ui.warn(_('no mapping for id %s\n' % id))
312 ui.warn(_('no mapping for id %s\n' % id))
313 continue
313 continue
314 return ''.join(newdata)
314 return ''.join(newdata)
315
315
316 def _islfile(file, ctx, matcher, size):
316 def _islfile(file, ctx, matcher, size):
317 '''Return true if file should be considered a largefile, i.e.
317 '''Return true if file should be considered a largefile, i.e.
318 matcher matches it or it is larger than size.'''
318 matcher matches it or it is larger than size.'''
319 # never store special .hg* files as largefiles
319 # never store special .hg* files as largefiles
320 if file == '.hgtags' or file == '.hgignore' or file == '.hgsigs':
320 if file == '.hgtags' or file == '.hgignore' or file == '.hgsigs':
321 return False
321 return False
322 if matcher and matcher(file):
322 if matcher and matcher(file):
323 return True
323 return True
324 try:
324 try:
325 return ctx.filectx(file).size() >= size * 1024 * 1024
325 return ctx.filectx(file).size() >= size * 1024 * 1024
326 except error.LookupError:
326 except error.LookupError:
327 return False
327 return False
328
328
329 def uploadlfiles(ui, rsrc, rdst, files):
329 def uploadlfiles(ui, rsrc, rdst, files):
330 '''upload largefiles to the central store'''
330 '''upload largefiles to the central store'''
331
331
332 if not files:
332 if not files:
333 return
333 return
334
334
335 store = basestore._openstore(rsrc, rdst, put=True)
335 store = basestore._openstore(rsrc, rdst, put=True)
336
336
337 at = 0
337 at = 0
338 files = filter(lambda h: not store.exists(h), files)
338 files = filter(lambda h: not store.exists(h), files)
339 for hash in files:
339 for hash in files:
340 ui.progress(_('uploading largefiles'), at, unit='largefile',
340 ui.progress(_('uploading largefiles'), at, unit='largefile',
341 total=len(files))
341 total=len(files))
342 source = lfutil.findfile(rsrc, hash)
342 source = lfutil.findfile(rsrc, hash)
343 if not source:
343 if not source:
344 raise util.Abort(_('largefile %s missing from store'
344 raise util.Abort(_('largefile %s missing from store'
345 ' (needs to be uploaded)') % hash)
345 ' (needs to be uploaded)') % hash)
346 # XXX check for errors here
346 # XXX check for errors here
347 store.put(source, hash)
347 store.put(source, hash)
348 at += 1
348 at += 1
349 ui.progress(_('uploading largefiles'), None)
349 ui.progress(_('uploading largefiles'), None)
350
350
351 def verifylfiles(ui, repo, all=False, contents=False):
351 def verifylfiles(ui, repo, all=False, contents=False):
352 '''Verify that every big file revision in the current changeset
352 '''Verify that every big file revision in the current changeset
353 exists in the central store. With --contents, also verify that
353 exists in the central store. With --contents, also verify that
354 the contents of each big file revision are correct (SHA-1 hash
354 the contents of each big file revision are correct (SHA-1 hash
355 matches the revision ID). With --all, check every changeset in
355 matches the revision ID). With --all, check every changeset in
356 this repository.'''
356 this repository.'''
357 if all:
357 if all:
358 # Pass a list to the function rather than an iterator because we know a
358 # Pass a list to the function rather than an iterator because we know a
359 # list will work.
359 # list will work.
360 revs = range(len(repo))
360 revs = range(len(repo))
361 else:
361 else:
362 revs = ['.']
362 revs = ['.']
363
363
364 store = basestore._openstore(repo)
364 store = basestore._openstore(repo)
365 return store.verify(revs, contents=contents)
365 return store.verify(revs, contents=contents)
366
366
367 def cachelfiles(ui, repo, node):
367 def cachelfiles(ui, repo, node):
368 '''cachelfiles ensures that all largefiles needed by the specified revision
368 '''cachelfiles ensures that all largefiles needed by the specified revision
369 are present in the repository's largefile cache.
369 are present in the repository's largefile cache.
370
370
371 returns a tuple (cached, missing). cached is the list of files downloaded
371 returns a tuple (cached, missing). cached is the list of files downloaded
372 by this operation; missing is the list of files that were needed but could
372 by this operation; missing is the list of files that were needed but could
373 not be found.'''
373 not be found.'''
374 lfiles = lfutil.listlfiles(repo, node)
374 lfiles = lfutil.listlfiles(repo, node)
375 toget = []
375 toget = []
376
376
377 for lfile in lfiles:
377 for lfile in lfiles:
378 # If we are mid-merge, then we have to trust the standin that is in the
378 # If we are mid-merge, then we have to trust the standin that is in the
379 # working copy to have the correct hashvalue. This is because the
379 # working copy to have the correct hashvalue. This is because the
380 # original hg.merge() already updated the standin as part of the normal
380 # original hg.merge() already updated the standin as part of the normal
381 # merge process -- we just have to udpate the largefile to match.
381 # merge process -- we just have to udpate the largefile to match.
382 if (getattr(repo, "_ismerging", False) and
382 if (getattr(repo, "_ismerging", False) and
383 os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
383 os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
384 expectedhash = lfutil.readstandin(repo, lfile)
384 expectedhash = lfutil.readstandin(repo, lfile)
385 else:
385 else:
386 expectedhash = repo[node][lfutil.standin(lfile)].data().strip()
386 expectedhash = repo[node][lfutil.standin(lfile)].data().strip()
387
387
388 # if it exists and its hash matches, it might have been locally
388 # if it exists and its hash matches, it might have been locally
389 # modified before updating and the user chose 'local'. in this case,
389 # modified before updating and the user chose 'local'. in this case,
390 # it will not be in any store, so don't look for it.
390 # it will not be in any store, so don't look for it.
391 if ((not os.path.exists(repo.wjoin(lfile)) or
391 if ((not os.path.exists(repo.wjoin(lfile)) or
392 expectedhash != lfutil.hashfile(repo.wjoin(lfile))) and
392 expectedhash != lfutil.hashfile(repo.wjoin(lfile))) and
393 not lfutil.findfile(repo, expectedhash)):
393 not lfutil.findfile(repo, expectedhash)):
394 toget.append((lfile, expectedhash))
394 toget.append((lfile, expectedhash))
395
395
396 if toget:
396 if toget:
397 store = basestore._openstore(repo)
397 store = basestore._openstore(repo)
398 ret = store.get(toget)
398 ret = store.get(toget)
399 return ret
399 return ret
400
400
401 return ([], [])
401 return ([], [])
402
402
403 def updatelfiles(ui, repo, filelist=None, printmessage=True):
403 def updatelfiles(ui, repo, filelist=None, printmessage=True):
404 wlock = repo.wlock()
404 wlock = repo.wlock()
405 try:
405 try:
406 lfdirstate = lfutil.openlfdirstate(ui, repo)
406 lfdirstate = lfutil.openlfdirstate(ui, repo)
407 lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate)
407 lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate)
408
408
409 if filelist is not None:
409 if filelist is not None:
410 lfiles = [f for f in lfiles if f in filelist]
410 lfiles = [f for f in lfiles if f in filelist]
411
411
412 printed = False
412 printed = False
413 if printmessage and lfiles:
413 if printmessage and lfiles:
414 ui.status(_('getting changed largefiles\n'))
414 ui.status(_('getting changed largefiles\n'))
415 printed = True
415 printed = True
416 cachelfiles(ui, repo, '.')
416 cachelfiles(ui, repo, '.')
417
417
418 updated, removed = 0, 0
418 updated, removed = 0, 0
419 for i in map(lambda f: _updatelfile(repo, lfdirstate, f), lfiles):
419 for i in map(lambda f: _updatelfile(repo, lfdirstate, f), lfiles):
420 # increment the appropriate counter according to _updatelfile's
420 # increment the appropriate counter according to _updatelfile's
421 # return value
421 # return value
422 updated += i > 0 and i or 0
422 updated += i > 0 and i or 0
423 removed -= i < 0 and i or 0
423 removed -= i < 0 and i or 0
424 if printmessage and (removed or updated) and not printed:
424 if printmessage and (removed or updated) and not printed:
425 ui.status(_('getting changed largefiles\n'))
425 ui.status(_('getting changed largefiles\n'))
426 printed = True
426 printed = True
427
427
428 lfdirstate.write()
428 lfdirstate.write()
429 if printed and printmessage:
429 if printed and printmessage:
430 ui.status(_('%d largefiles updated, %d removed\n') % (updated,
430 ui.status(_('%d largefiles updated, %d removed\n') % (updated,
431 removed))
431 removed))
432 finally:
432 finally:
433 wlock.release()
433 wlock.release()
434
434
435 def _updatelfile(repo, lfdirstate, lfile):
435 def _updatelfile(repo, lfdirstate, lfile):
436 '''updates a single largefile and copies the state of its standin from
436 '''updates a single largefile and copies the state of its standin from
437 the repository's dirstate to its state in the lfdirstate.
437 the repository's dirstate to its state in the lfdirstate.
438
438
439 returns 1 if the file was modified, -1 if the file was removed, 0 if the
439 returns 1 if the file was modified, -1 if the file was removed, 0 if the
440 file was unchanged, and None if the needed largefile was missing from the
440 file was unchanged, and None if the needed largefile was missing from the
441 cache.'''
441 cache.'''
442 ret = 0
442 ret = 0
443 abslfile = repo.wjoin(lfile)
443 abslfile = repo.wjoin(lfile)
444 absstandin = repo.wjoin(lfutil.standin(lfile))
444 absstandin = repo.wjoin(lfutil.standin(lfile))
445 if os.path.exists(absstandin):
445 if os.path.exists(absstandin):
446 if os.path.exists(absstandin+'.orig'):
446 if os.path.exists(absstandin+'.orig'):
447 shutil.copyfile(abslfile, abslfile+'.orig')
447 shutil.copyfile(abslfile, abslfile+'.orig')
448 expecthash = lfutil.readstandin(repo, lfile)
448 expecthash = lfutil.readstandin(repo, lfile)
449 if (expecthash != '' and
449 if (expecthash != '' and
450 (not os.path.exists(abslfile) or
450 (not os.path.exists(abslfile) or
451 expecthash != lfutil.hashfile(abslfile))):
451 expecthash != lfutil.hashfile(abslfile))):
452 if not lfutil.copyfromcache(repo, expecthash, lfile):
452 if not lfutil.copyfromcache(repo, expecthash, lfile):
453 # use normallookup() to allocate entry in largefiles dirstate,
453 # use normallookup() to allocate entry in largefiles dirstate,
454 # because lack of it misleads lfiles_repo.status() into
454 # because lack of it misleads lfiles_repo.status() into
455 # recognition that such cache missing files are REMOVED.
455 # recognition that such cache missing files are REMOVED.
456 lfdirstate.normallookup(lfile)
456 lfdirstate.normallookup(lfile)
457 return None # don't try to set the mode
457 return None # don't try to set the mode
458 ret = 1
458 ret = 1
459 mode = os.stat(absstandin).st_mode
459 mode = os.stat(absstandin).st_mode
460 if mode != os.stat(abslfile).st_mode:
460 if mode != os.stat(abslfile).st_mode:
461 os.chmod(abslfile, mode)
461 os.chmod(abslfile, mode)
462 ret = 1
462 ret = 1
463 else:
463 else:
464 # Remove lfiles for which the standin is deleted, unless the
464 # Remove lfiles for which the standin is deleted, unless the
465 # lfile is added to the repository again. This happens when a
465 # lfile is added to the repository again. This happens when a
466 # largefile is converted back to a normal file: the standin
466 # largefile is converted back to a normal file: the standin
467 # disappears, but a new (normal) file appears as the lfile.
467 # disappears, but a new (normal) file appears as the lfile.
468 if os.path.exists(abslfile) and lfile not in repo[None]:
468 if os.path.exists(abslfile) and lfile not in repo[None]:
469 os.unlink(abslfile)
469 util.unlinkpath(abslfile)
470 ret = -1
470 ret = -1
471 state = repo.dirstate[lfutil.standin(lfile)]
471 state = repo.dirstate[lfutil.standin(lfile)]
472 if state == 'n':
472 if state == 'n':
473 # When rebasing, we need to synchronize the standin and the largefile,
473 # When rebasing, we need to synchronize the standin and the largefile,
474 # because otherwise the largefile will get reverted. But for commit's
474 # because otherwise the largefile will get reverted. But for commit's
475 # sake, we have to mark the file as unclean.
475 # sake, we have to mark the file as unclean.
476 if getattr(repo, "_isrebasing", False):
476 if getattr(repo, "_isrebasing", False):
477 lfdirstate.normallookup(lfile)
477 lfdirstate.normallookup(lfile)
478 else:
478 else:
479 lfdirstate.normal(lfile)
479 lfdirstate.normal(lfile)
480 elif state == 'r':
480 elif state == 'r':
481 lfdirstate.remove(lfile)
481 lfdirstate.remove(lfile)
482 elif state == 'a':
482 elif state == 'a':
483 lfdirstate.add(lfile)
483 lfdirstate.add(lfile)
484 elif state == '?':
484 elif state == '?':
485 lfdirstate.drop(lfile)
485 lfdirstate.drop(lfile)
486 return ret
486 return ret
487
487
488 # -- hg commands declarations ------------------------------------------------
488 # -- hg commands declarations ------------------------------------------------
489
489
490 cmdtable = {
490 cmdtable = {
491 'lfconvert': (lfconvert,
491 'lfconvert': (lfconvert,
492 [('s', 'size', '',
492 [('s', 'size', '',
493 _('minimum size (MB) for files to be converted '
493 _('minimum size (MB) for files to be converted '
494 'as largefiles'),
494 'as largefiles'),
495 'SIZE'),
495 'SIZE'),
496 ('', 'to-normal', False,
496 ('', 'to-normal', False,
497 _('convert from a largefiles repo to a normal repo')),
497 _('convert from a largefiles repo to a normal repo')),
498 ],
498 ],
499 _('hg lfconvert SOURCE DEST [FILE ...]')),
499 _('hg lfconvert SOURCE DEST [FILE ...]')),
500 }
500 }
@@ -1,915 +1,923 b''
1 $ "$TESTDIR/hghave" symlink unix-permissions serve || exit 80
1 $ "$TESTDIR/hghave" symlink unix-permissions serve || exit 80
2 $ USERCACHE=`pwd`/cache; export USERCACHE
2 $ USERCACHE=`pwd`/cache; export USERCACHE
3 $ mkdir -p ${USERCACHE}
3 $ mkdir -p ${USERCACHE}
4 $ cat >> $HGRCPATH <<EOF
4 $ cat >> $HGRCPATH <<EOF
5 > [extensions]
5 > [extensions]
6 > largefiles=
6 > largefiles=
7 > purge=
7 > purge=
8 > rebase=
8 > rebase=
9 > transplant=
9 > transplant=
10 > [phases]
10 > [phases]
11 > publish=False
11 > publish=False
12 > [largefiles]
12 > [largefiles]
13 > minsize=2
13 > minsize=2
14 > patterns=glob:**.dat
14 > patterns=glob:**.dat
15 > usercache=${USERCACHE}
15 > usercache=${USERCACHE}
16 > [hooks]
16 > [hooks]
17 > precommit=echo "Invoking status precommit hook"; hg status
17 > precommit=echo "Invoking status precommit hook"; hg status
18 > EOF
18 > EOF
19
19
20 Create the repo with a couple of revisions of both large and normal
20 Create the repo with a couple of revisions of both large and normal
21 files, testing that status correctly shows largefiles and that summary output
21 files, testing that status correctly shows largefiles and that summary output
22 is correct.
22 is correct.
23
23
24 $ hg init a
24 $ hg init a
25 $ cd a
25 $ cd a
26 $ mkdir sub
26 $ mkdir sub
27 $ echo normal1 > normal1
27 $ echo normal1 > normal1
28 $ echo normal2 > sub/normal2
28 $ echo normal2 > sub/normal2
29 $ echo large1 > large1
29 $ echo large1 > large1
30 $ echo large2 > sub/large2
30 $ echo large2 > sub/large2
31 $ hg add normal1 sub/normal2
31 $ hg add normal1 sub/normal2
32 $ hg add --large large1 sub/large2
32 $ hg add --large large1 sub/large2
33 $ hg commit -m "add files"
33 $ hg commit -m "add files"
34 Invoking status precommit hook
34 Invoking status precommit hook
35 A large1
35 A large1
36 A normal1
36 A normal1
37 A sub/large2
37 A sub/large2
38 A sub/normal2
38 A sub/normal2
39 $ echo normal11 > normal1
39 $ echo normal11 > normal1
40 $ echo normal22 > sub/normal2
40 $ echo normal22 > sub/normal2
41 $ echo large11 > large1
41 $ echo large11 > large1
42 $ echo large22 > sub/large2
42 $ echo large22 > sub/large2
43 $ hg commit -m "edit files"
43 $ hg commit -m "edit files"
44 Invoking status precommit hook
44 Invoking status precommit hook
45 M large1
45 M large1
46 M normal1
46 M normal1
47 M sub/large2
47 M sub/large2
48 M sub/normal2
48 M sub/normal2
49 $ hg sum --large
49 $ hg sum --large
50 parent: 1:ce8896473775 tip
50 parent: 1:ce8896473775 tip
51 edit files
51 edit files
52 branch: default
52 branch: default
53 commit: (clean)
53 commit: (clean)
54 update: (current)
54 update: (current)
55 largefiles: No remote repo
55 largefiles: No remote repo
56
56
57 Commit preserved largefile contents.
57 Commit preserved largefile contents.
58
58
59 $ cat normal1
59 $ cat normal1
60 normal11
60 normal11
61 $ cat large1
61 $ cat large1
62 large11
62 large11
63 $ cat sub/normal2
63 $ cat sub/normal2
64 normal22
64 normal22
65 $ cat sub/large2
65 $ cat sub/large2
66 large22
66 large22
67
67
68 Remove both largefiles and normal files.
68 Remove both largefiles and normal files.
69
69
70 $ hg remove normal1 large1
70 $ hg remove normal1 large1
71 $ hg commit -m "remove files"
71 $ hg commit -m "remove files"
72 Invoking status precommit hook
72 Invoking status precommit hook
73 R large1
73 R large1
74 R normal1
74 R normal1
75 $ ls
75 $ ls
76 sub
76 sub
77 $ echo "testlargefile" > large1-test
77 $ echo "testlargefile" > large1-test
78 $ hg add --large large1-test
78 $ hg add --large large1-test
79 $ hg st
79 $ hg st
80 A large1-test
80 A large1-test
81 $ hg rm large1-test
81 $ hg rm large1-test
82 not removing large1-test: file has been marked for add (use forget to undo)
82 not removing large1-test: file has been marked for add (use forget to undo)
83 $ hg st
83 $ hg st
84 A large1-test
84 A large1-test
85 $ hg forget large1-test
85 $ hg forget large1-test
86 $ hg st
86 $ hg st
87 ? large1-test
87 ? large1-test
88 $ rm large1-test
88 $ rm large1-test
89
89
90 Copy both largefiles and normal files (testing that status output is correct).
90 Copy both largefiles and normal files (testing that status output is correct).
91
91
92 $ hg cp sub/normal2 normal1
92 $ hg cp sub/normal2 normal1
93 $ hg cp sub/large2 large1
93 $ hg cp sub/large2 large1
94 $ hg commit -m "copy files"
94 $ hg commit -m "copy files"
95 Invoking status precommit hook
95 Invoking status precommit hook
96 A large1
96 A large1
97 A normal1
97 A normal1
98 $ cat normal1
98 $ cat normal1
99 normal22
99 normal22
100 $ cat large1
100 $ cat large1
101 large22
101 large22
102
102
103 Test moving largefiles and verify that normal files are also unaffected.
103 Test moving largefiles and verify that normal files are also unaffected.
104
104
105 $ hg mv normal1 normal3
105 $ hg mv normal1 normal3
106 $ hg mv large1 large3
106 $ hg mv large1 large3
107 $ hg mv sub/normal2 sub/normal4
107 $ hg mv sub/normal2 sub/normal4
108 $ hg mv sub/large2 sub/large4
108 $ hg mv sub/large2 sub/large4
109 $ hg commit -m "move files"
109 $ hg commit -m "move files"
110 Invoking status precommit hook
110 Invoking status precommit hook
111 A large3
111 A large3
112 A normal3
112 A normal3
113 A sub/large4
113 A sub/large4
114 A sub/normal4
114 A sub/normal4
115 R large1
115 R large1
116 R normal1
116 R normal1
117 R sub/large2
117 R sub/large2
118 R sub/normal2
118 R sub/normal2
119 $ cat normal3
119 $ cat normal3
120 normal22
120 normal22
121 $ cat large3
121 $ cat large3
122 large22
122 large22
123 $ cat sub/normal4
123 $ cat sub/normal4
124 normal22
124 normal22
125 $ cat sub/large4
125 $ cat sub/large4
126 large22
126 large22
127
127
128 Test archiving the various revisions. These hit corner cases known with
128 Test archiving the various revisions. These hit corner cases known with
129 archiving.
129 archiving.
130
130
131 $ hg archive -r 0 ../archive0
131 $ hg archive -r 0 ../archive0
132 $ hg archive -r 1 ../archive1
132 $ hg archive -r 1 ../archive1
133 $ hg archive -r 2 ../archive2
133 $ hg archive -r 2 ../archive2
134 $ hg archive -r 3 ../archive3
134 $ hg archive -r 3 ../archive3
135 $ hg archive -r 4 ../archive4
135 $ hg archive -r 4 ../archive4
136 $ cd ../archive0
136 $ cd ../archive0
137 $ cat normal1
137 $ cat normal1
138 normal1
138 normal1
139 $ cat large1
139 $ cat large1
140 large1
140 large1
141 $ cat sub/normal2
141 $ cat sub/normal2
142 normal2
142 normal2
143 $ cat sub/large2
143 $ cat sub/large2
144 large2
144 large2
145 $ cd ../archive1
145 $ cd ../archive1
146 $ cat normal1
146 $ cat normal1
147 normal11
147 normal11
148 $ cat large1
148 $ cat large1
149 large11
149 large11
150 $ cat sub/normal2
150 $ cat sub/normal2
151 normal22
151 normal22
152 $ cat sub/large2
152 $ cat sub/large2
153 large22
153 large22
154 $ cd ../archive2
154 $ cd ../archive2
155 $ ls
155 $ ls
156 sub
156 sub
157 $ cat sub/normal2
157 $ cat sub/normal2
158 normal22
158 normal22
159 $ cat sub/large2
159 $ cat sub/large2
160 large22
160 large22
161 $ cd ../archive3
161 $ cd ../archive3
162 $ cat normal1
162 $ cat normal1
163 normal22
163 normal22
164 $ cat large1
164 $ cat large1
165 large22
165 large22
166 $ cat sub/normal2
166 $ cat sub/normal2
167 normal22
167 normal22
168 $ cat sub/large2
168 $ cat sub/large2
169 large22
169 large22
170 $ cd ../archive4
170 $ cd ../archive4
171 $ cat normal3
171 $ cat normal3
172 normal22
172 normal22
173 $ cat large3
173 $ cat large3
174 large22
174 large22
175 $ cat sub/normal4
175 $ cat sub/normal4
176 normal22
176 normal22
177 $ cat sub/large4
177 $ cat sub/large4
178 large22
178 large22
179
179
180 Commit corner case: specify files to commit.
180 Commit corner case: specify files to commit.
181
181
182 $ cd ../a
182 $ cd ../a
183 $ echo normal3 > normal3
183 $ echo normal3 > normal3
184 $ echo large3 > large3
184 $ echo large3 > large3
185 $ echo normal4 > sub/normal4
185 $ echo normal4 > sub/normal4
186 $ echo large4 > sub/large4
186 $ echo large4 > sub/large4
187 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
187 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
188 Invoking status precommit hook
188 Invoking status precommit hook
189 M large3
189 M large3
190 M normal3
190 M normal3
191 M sub/large4
191 M sub/large4
192 M sub/normal4
192 M sub/normal4
193 $ cat normal3
193 $ cat normal3
194 normal3
194 normal3
195 $ cat large3
195 $ cat large3
196 large3
196 large3
197 $ cat sub/normal4
197 $ cat sub/normal4
198 normal4
198 normal4
199 $ cat sub/large4
199 $ cat sub/large4
200 large4
200 large4
201
201
202 One more commit corner case: commit from a subdirectory.
202 One more commit corner case: commit from a subdirectory.
203
203
204 $ cd ../a
204 $ cd ../a
205 $ echo normal33 > normal3
205 $ echo normal33 > normal3
206 $ echo large33 > large3
206 $ echo large33 > large3
207 $ echo normal44 > sub/normal4
207 $ echo normal44 > sub/normal4
208 $ echo large44 > sub/large4
208 $ echo large44 > sub/large4
209 $ cd sub
209 $ cd sub
210 $ hg commit -m "edit files yet again"
210 $ hg commit -m "edit files yet again"
211 Invoking status precommit hook
211 Invoking status precommit hook
212 M large3
212 M large3
213 M normal3
213 M normal3
214 M sub/large4
214 M sub/large4
215 M sub/normal4
215 M sub/normal4
216 $ cat ../normal3
216 $ cat ../normal3
217 normal33
217 normal33
218 $ cat ../large3
218 $ cat ../large3
219 large33
219 large33
220 $ cat normal4
220 $ cat normal4
221 normal44
221 normal44
222 $ cat large4
222 $ cat large4
223 large44
223 large44
224
224
225 Committing standins is not allowed.
225 Committing standins is not allowed.
226
226
227 $ cd ..
227 $ cd ..
228 $ echo large3 > large3
228 $ echo large3 > large3
229 $ hg commit .hglf/large3 -m "try to commit standin"
229 $ hg commit .hglf/large3 -m "try to commit standin"
230 abort: file ".hglf/large3" is a largefile standin
230 abort: file ".hglf/large3" is a largefile standin
231 (commit the largefile itself instead)
231 (commit the largefile itself instead)
232 [255]
232 [255]
233
233
234 Corner cases for adding largefiles.
234 Corner cases for adding largefiles.
235
235
236 $ echo large5 > large5
236 $ echo large5 > large5
237 $ hg add --large large5
237 $ hg add --large large5
238 $ hg add --large large5
238 $ hg add --large large5
239 large5 already a largefile
239 large5 already a largefile
240 $ mkdir sub2
240 $ mkdir sub2
241 $ echo large6 > sub2/large6
241 $ echo large6 > sub2/large6
242 $ echo large7 > sub2/large7
242 $ echo large7 > sub2/large7
243 $ hg add --large sub2
243 $ hg add --large sub2
244 adding sub2/large6 as a largefile (glob)
244 adding sub2/large6 as a largefile (glob)
245 adding sub2/large7 as a largefile (glob)
245 adding sub2/large7 as a largefile (glob)
246 $ hg st
246 $ hg st
247 M large3
247 M large3
248 A large5
248 A large5
249 A sub2/large6
249 A sub2/large6
250 A sub2/large7
250 A sub2/large7
251
251
252 Config settings (pattern **.dat, minsize 2 MB) are respected.
252 Config settings (pattern **.dat, minsize 2 MB) are respected.
253
253
254 $ echo testdata > test.dat
254 $ echo testdata > test.dat
255 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
255 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
256 $ hg add
256 $ hg add
257 adding reallylarge as a largefile
257 adding reallylarge as a largefile
258 adding test.dat as a largefile
258 adding test.dat as a largefile
259
259
260 Test that minsize and --lfsize handle float values;
260 Test that minsize and --lfsize handle float values;
261 also tests that --lfsize overrides largefiles.minsize.
261 also tests that --lfsize overrides largefiles.minsize.
262 (0.250 MB = 256 kB = 262144 B)
262 (0.250 MB = 256 kB = 262144 B)
263
263
264 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
264 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
265 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
265 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
266 $ hg --config largefiles.minsize=.25 add
266 $ hg --config largefiles.minsize=.25 add
267 adding ratherlarge as a largefile
267 adding ratherlarge as a largefile
268 adding medium
268 adding medium
269 $ hg forget medium
269 $ hg forget medium
270 $ hg --config largefiles.minsize=.25 add --lfsize=.125
270 $ hg --config largefiles.minsize=.25 add --lfsize=.125
271 adding medium as a largefile
271 adding medium as a largefile
272 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
272 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
273 $ hg --config largefiles.minsize=.25 add --lfsize=.125
273 $ hg --config largefiles.minsize=.25 add --lfsize=.125
274 adding notlarge
274 adding notlarge
275 $ hg forget notlarge
275 $ hg forget notlarge
276
276
277 Test forget on largefiles.
277 Test forget on largefiles.
278
278
279 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
279 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
280 $ hg commit -m "add/edit more largefiles"
280 $ hg commit -m "add/edit more largefiles"
281 Invoking status precommit hook
281 Invoking status precommit hook
282 A sub2/large6
282 A sub2/large6
283 A sub2/large7
283 A sub2/large7
284 R large3
284 R large3
285 ? large5
285 ? large5
286 ? medium
286 ? medium
287 ? notlarge
287 ? notlarge
288 ? ratherlarge
288 ? ratherlarge
289 ? reallylarge
289 ? reallylarge
290 ? test.dat
290 ? test.dat
291 $ hg st
291 $ hg st
292 ? large3
292 ? large3
293 ? large5
293 ? large5
294 ? medium
294 ? medium
295 ? notlarge
295 ? notlarge
296 ? ratherlarge
296 ? ratherlarge
297 ? reallylarge
297 ? reallylarge
298 ? test.dat
298 ? test.dat
299
299
300 Purge with largefiles: verify that largefiles are still in the working
300 Purge with largefiles: verify that largefiles are still in the working
301 dir after a purge.
301 dir after a purge.
302
302
303 $ hg purge --all
303 $ hg purge --all
304 $ cat sub/large4
304 $ cat sub/large4
305 large44
305 large44
306 $ cat sub2/large6
306 $ cat sub2/large6
307 large6
307 large6
308 $ cat sub2/large7
308 $ cat sub2/large7
309 large7
309 large7
310
310
311 Test addremove: verify that files that should be added as largfiles are added as
311 Test addremove: verify that files that should be added as largfiles are added as
312 such and that already-existing largfiles are not added as normal files by
312 such and that already-existing largfiles are not added as normal files by
313 accident.
313 accident.
314
314
315 $ rm normal3
315 $ rm normal3
316 $ rm sub/large4
316 $ rm sub/large4
317 $ echo "testing addremove with patterns" > testaddremove.dat
317 $ echo "testing addremove with patterns" > testaddremove.dat
318 $ echo "normaladdremove" > normaladdremove
318 $ echo "normaladdremove" > normaladdremove
319 $ hg addremove
319 $ hg addremove
320 removing sub/large4
320 removing sub/large4
321 adding testaddremove.dat as a largefile
321 adding testaddremove.dat as a largefile
322 removing normal3
322 removing normal3
323 adding normaladdremove
323 adding normaladdremove
324
324
325 Clone a largefiles repo.
325 Clone a largefiles repo.
326
326
327 $ hg clone . ../b
327 $ hg clone . ../b
328 updating to branch default
328 updating to branch default
329 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
330 getting changed largefiles
330 getting changed largefiles
331 3 largefiles updated, 0 removed
331 3 largefiles updated, 0 removed
332 $ cd ../b
332 $ cd ../b
333 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
333 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
334 7:daea875e9014 add/edit more largefiles
334 7:daea875e9014 add/edit more largefiles
335 6:4355d653f84f edit files yet again
335 6:4355d653f84f edit files yet again
336 5:9d5af5072dbd edit files again
336 5:9d5af5072dbd edit files again
337 4:74c02385b94c move files
337 4:74c02385b94c move files
338 3:9e8fbc4bce62 copy files
338 3:9e8fbc4bce62 copy files
339 2:51a0ae4d5864 remove files
339 2:51a0ae4d5864 remove files
340 1:ce8896473775 edit files
340 1:ce8896473775 edit files
341 0:30d30fe6a5be add files
341 0:30d30fe6a5be add files
342 $ cat normal3
342 $ cat normal3
343 normal33
343 normal33
344 $ cat sub/normal4
344 $ cat sub/normal4
345 normal44
345 normal44
346 $ cat sub/large4
346 $ cat sub/large4
347 large44
347 large44
348 $ cat sub2/large6
348 $ cat sub2/large6
349 large6
349 large6
350 $ cat sub2/large7
350 $ cat sub2/large7
351 large7
351 large7
352 $ cd ..
352 $ cd ..
353 $ hg clone a -r 3 c
353 $ hg clone a -r 3 c
354 adding changesets
354 adding changesets
355 adding manifests
355 adding manifests
356 adding file changes
356 adding file changes
357 added 4 changesets with 10 changes to 4 files
357 added 4 changesets with 10 changes to 4 files
358 updating to branch default
358 updating to branch default
359 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
359 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
360 getting changed largefiles
360 getting changed largefiles
361 2 largefiles updated, 0 removed
361 2 largefiles updated, 0 removed
362 $ cd c
362 $ cd c
363 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
363 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
364 3:9e8fbc4bce62 copy files
364 3:9e8fbc4bce62 copy files
365 2:51a0ae4d5864 remove files
365 2:51a0ae4d5864 remove files
366 1:ce8896473775 edit files
366 1:ce8896473775 edit files
367 0:30d30fe6a5be add files
367 0:30d30fe6a5be add files
368 $ cat normal1
368 $ cat normal1
369 normal22
369 normal22
370 $ cat large1
370 $ cat large1
371 large22
371 large22
372 $ cat sub/normal2
372 $ cat sub/normal2
373 normal22
373 normal22
374 $ cat sub/large2
374 $ cat sub/large2
375 large22
375 large22
376
376
377 Old revisions of a clone have correct largefiles content (this also
377 Old revisions of a clone have correct largefiles content (this also
378 tests update).
378 tests update).
379
379
380 $ hg update -r 1
380 $ hg update -r 1
381 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
381 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
382 getting changed largefiles
382 getting changed largefiles
383 1 largefiles updated, 0 removed
383 1 largefiles updated, 0 removed
384 $ cat large1
384 $ cat large1
385 large11
385 large11
386 $ cat sub/large2
386 $ cat sub/large2
387 large22
387 large22
388
388
389 Rebasing between two repositories does not revert largefiles to old
389 Rebasing between two repositories does not revert largefiles to old
390 revisions (this was a very bad bug that took a lot of work to fix).
390 revisions (this was a very bad bug that took a lot of work to fix).
391
391
392 $ cd ..
392 $ cd ..
393 $ hg clone a d
393 $ hg clone a d
394 updating to branch default
394 updating to branch default
395 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
395 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
396 getting changed largefiles
396 getting changed largefiles
397 3 largefiles updated, 0 removed
397 3 largefiles updated, 0 removed
398 $ cd b
398 $ cd b
399 $ echo large4-modified > sub/large4
399 $ echo large4-modified > sub/large4
400 $ echo normal3-modified > normal3
400 $ echo normal3-modified > normal3
401 $ hg commit -m "modify normal file and largefile in repo b"
401 $ hg commit -m "modify normal file and largefile in repo b"
402 Invoking status precommit hook
402 Invoking status precommit hook
403 M normal3
403 M normal3
404 M sub/large4
404 M sub/large4
405 $ cd ../d
405 $ cd ../d
406 $ echo large6-modified > sub2/large6
406 $ echo large6-modified > sub2/large6
407 $ echo normal4-modified > sub/normal4
407 $ echo normal4-modified > sub/normal4
408 $ hg commit -m "modify normal file largefile in repo d"
408 $ hg commit -m "modify normal file largefile in repo d"
409 Invoking status precommit hook
409 Invoking status precommit hook
410 M sub/normal4
410 M sub/normal4
411 M sub2/large6
411 M sub2/large6
412 $ cd ..
412 $ cd ..
413 $ hg clone d e
413 $ hg clone d e
414 updating to branch default
414 updating to branch default
415 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
415 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
416 getting changed largefiles
416 getting changed largefiles
417 3 largefiles updated, 0 removed
417 3 largefiles updated, 0 removed
418 $ cd d
418 $ cd d
419 $ hg pull --rebase ../b
419 $ hg pull --rebase ../b
420 pulling from ../b
420 pulling from ../b
421 searching for changes
421 searching for changes
422 adding changesets
422 adding changesets
423 adding manifests
423 adding manifests
424 adding file changes
424 adding file changes
425 added 1 changesets with 2 changes to 2 files (+1 heads)
425 added 1 changesets with 2 changes to 2 files (+1 heads)
426 getting changed largefiles
426 getting changed largefiles
427 1 largefiles updated, 0 removed
427 1 largefiles updated, 0 removed
428 Invoking status precommit hook
428 Invoking status precommit hook
429 M sub/normal4
429 M sub/normal4
430 M sub2/large6
430 M sub2/large6
431 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg
431 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg
432 nothing to rebase
432 nothing to rebase
433 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
433 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
434 9:598410d3eb9a modify normal file largefile in repo d
434 9:598410d3eb9a modify normal file largefile in repo d
435 8:a381d2c8c80e modify normal file and largefile in repo b
435 8:a381d2c8c80e modify normal file and largefile in repo b
436 7:daea875e9014 add/edit more largefiles
436 7:daea875e9014 add/edit more largefiles
437 6:4355d653f84f edit files yet again
437 6:4355d653f84f edit files yet again
438 5:9d5af5072dbd edit files again
438 5:9d5af5072dbd edit files again
439 4:74c02385b94c move files
439 4:74c02385b94c move files
440 3:9e8fbc4bce62 copy files
440 3:9e8fbc4bce62 copy files
441 2:51a0ae4d5864 remove files
441 2:51a0ae4d5864 remove files
442 1:ce8896473775 edit files
442 1:ce8896473775 edit files
443 0:30d30fe6a5be add files
443 0:30d30fe6a5be add files
444 $ cat normal3
444 $ cat normal3
445 normal3-modified
445 normal3-modified
446 $ cat sub/normal4
446 $ cat sub/normal4
447 normal4-modified
447 normal4-modified
448 $ cat sub/large4
448 $ cat sub/large4
449 large4-modified
449 large4-modified
450 $ cat sub2/large6
450 $ cat sub2/large6
451 large6-modified
451 large6-modified
452 $ cat sub2/large7
452 $ cat sub2/large7
453 large7
453 large7
454 $ cd ../e
454 $ cd ../e
455 $ hg pull ../b
455 $ hg pull ../b
456 pulling from ../b
456 pulling from ../b
457 searching for changes
457 searching for changes
458 adding changesets
458 adding changesets
459 adding manifests
459 adding manifests
460 adding file changes
460 adding file changes
461 added 1 changesets with 2 changes to 2 files (+1 heads)
461 added 1 changesets with 2 changes to 2 files (+1 heads)
462 (run 'hg heads' to see heads, 'hg merge' to merge)
462 (run 'hg heads' to see heads, 'hg merge' to merge)
463 $ hg rebase
463 $ hg rebase
464 getting changed largefiles
464 getting changed largefiles
465 1 largefiles updated, 0 removed
465 1 largefiles updated, 0 removed
466 Invoking status precommit hook
466 Invoking status precommit hook
467 M sub/normal4
467 M sub/normal4
468 M sub2/large6
468 M sub2/large6
469 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg
469 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg
470 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
470 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
471 9:598410d3eb9a modify normal file largefile in repo d
471 9:598410d3eb9a modify normal file largefile in repo d
472 8:a381d2c8c80e modify normal file and largefile in repo b
472 8:a381d2c8c80e modify normal file and largefile in repo b
473 7:daea875e9014 add/edit more largefiles
473 7:daea875e9014 add/edit more largefiles
474 6:4355d653f84f edit files yet again
474 6:4355d653f84f edit files yet again
475 5:9d5af5072dbd edit files again
475 5:9d5af5072dbd edit files again
476 4:74c02385b94c move files
476 4:74c02385b94c move files
477 3:9e8fbc4bce62 copy files
477 3:9e8fbc4bce62 copy files
478 2:51a0ae4d5864 remove files
478 2:51a0ae4d5864 remove files
479 1:ce8896473775 edit files
479 1:ce8896473775 edit files
480 0:30d30fe6a5be add files
480 0:30d30fe6a5be add files
481 $ cat normal3
481 $ cat normal3
482 normal3-modified
482 normal3-modified
483 $ cat sub/normal4
483 $ cat sub/normal4
484 normal4-modified
484 normal4-modified
485 $ cat sub/large4
485 $ cat sub/large4
486 large4-modified
486 large4-modified
487 $ cat sub2/large6
487 $ cat sub2/large6
488 large6-modified
488 large6-modified
489 $ cat sub2/large7
489 $ cat sub2/large7
490 large7
490 large7
491
491
492 Rollback on largefiles.
492 Rollback on largefiles.
493
493
494 $ echo large4-modified-again > sub/large4
494 $ echo large4-modified-again > sub/large4
495 $ hg commit -m "Modify large4 again"
495 $ hg commit -m "Modify large4 again"
496 Invoking status precommit hook
496 Invoking status precommit hook
497 M sub/large4
497 M sub/large4
498 $ hg rollback
498 $ hg rollback
499 repository tip rolled back to revision 9 (undo commit)
499 repository tip rolled back to revision 9 (undo commit)
500 working directory now based on revision 9
500 working directory now based on revision 9
501 $ hg st
501 $ hg st
502 M sub/large4
502 M sub/large4
503 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
503 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
504 9:598410d3eb9a modify normal file largefile in repo d
504 9:598410d3eb9a modify normal file largefile in repo d
505 8:a381d2c8c80e modify normal file and largefile in repo b
505 8:a381d2c8c80e modify normal file and largefile in repo b
506 7:daea875e9014 add/edit more largefiles
506 7:daea875e9014 add/edit more largefiles
507 6:4355d653f84f edit files yet again
507 6:4355d653f84f edit files yet again
508 5:9d5af5072dbd edit files again
508 5:9d5af5072dbd edit files again
509 4:74c02385b94c move files
509 4:74c02385b94c move files
510 3:9e8fbc4bce62 copy files
510 3:9e8fbc4bce62 copy files
511 2:51a0ae4d5864 remove files
511 2:51a0ae4d5864 remove files
512 1:ce8896473775 edit files
512 1:ce8896473775 edit files
513 0:30d30fe6a5be add files
513 0:30d30fe6a5be add files
514 $ cat sub/large4
514 $ cat sub/large4
515 large4-modified-again
515 large4-modified-again
516
516
517 "update --check" refuses to update with uncommitted changes.
517 "update --check" refuses to update with uncommitted changes.
518 $ hg update --check 8
518 $ hg update --check 8
519 abort: uncommitted local changes
519 abort: uncommitted local changes
520 [255]
520 [255]
521
521
522 "update --clean" leaves correct largefiles in working copy.
522 "update --clean" leaves correct largefiles in working copy.
523
523
524 $ hg update --clean
524 $ hg update --clean
525 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
525 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
526 getting changed largefiles
526 getting changed largefiles
527 1 largefiles updated, 0 removed
527 1 largefiles updated, 0 removed
528 $ cat normal3
528 $ cat normal3
529 normal3-modified
529 normal3-modified
530 $ cat sub/normal4
530 $ cat sub/normal4
531 normal4-modified
531 normal4-modified
532 $ cat sub/large4
532 $ cat sub/large4
533 large4-modified
533 large4-modified
534 $ cat sub2/large6
534 $ cat sub2/large6
535 large6-modified
535 large6-modified
536 $ cat sub2/large7
536 $ cat sub2/large7
537 large7
537 large7
538
538
539 Now "update check" is happy.
539 Now "update check" is happy.
540 $ hg update --check 8
540 $ hg update --check 8
541 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
541 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
542 getting changed largefiles
542 getting changed largefiles
543 1 largefiles updated, 0 removed
543 1 largefiles updated, 0 removed
544 $ hg update --check
544 $ hg update --check
545 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
545 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
546 getting changed largefiles
546 getting changed largefiles
547 1 largefiles updated, 0 removed
547 1 largefiles updated, 0 removed
548
548
549 Test removing empty largefiles directories on update
550 $ test -d sub2 && echo "sub2 exists"
551 sub2 exists
552 $ hg update -q null
553 $ test -d sub2 && echo "error: sub2 should not exist anymore"
554 [1]
555 $ hg update -q
556
549 "revert" works on largefiles (and normal files too).
557 "revert" works on largefiles (and normal files too).
550 $ echo hack3 >> normal3
558 $ echo hack3 >> normal3
551 $ echo hack4 >> sub/normal4
559 $ echo hack4 >> sub/normal4
552 $ echo hack4 >> sub/large4
560 $ echo hack4 >> sub/large4
553 $ hg rm sub2/large6
561 $ hg rm sub2/large6
554 $ echo new >> sub2/large8
562 $ echo new >> sub2/large8
555 $ hg add --large sub2/large8
563 $ hg add --large sub2/large8
556 # XXX we don't really want to report that we're reverting the standin;
564 # XXX we don't really want to report that we're reverting the standin;
557 # that's just an implementation detail. But I don't see an obvious fix. ;-(
565 # that's just an implementation detail. But I don't see an obvious fix. ;-(
558 $ hg revert sub
566 $ hg revert sub
559 reverting .hglf/sub/large4 (glob)
567 reverting .hglf/sub/large4 (glob)
560 reverting sub/normal4 (glob)
568 reverting sub/normal4 (glob)
561 $ hg status
569 $ hg status
562 M normal3
570 M normal3
563 A sub2/large8
571 A sub2/large8
564 R sub2/large6
572 R sub2/large6
565 ? sub/large4.orig
573 ? sub/large4.orig
566 ? sub/normal4.orig
574 ? sub/normal4.orig
567 $ cat sub/normal4
575 $ cat sub/normal4
568 normal4-modified
576 normal4-modified
569 $ cat sub/large4
577 $ cat sub/large4
570 large4-modified
578 large4-modified
571 $ hg revert -a --no-backup
579 $ hg revert -a --no-backup
572 undeleting .hglf/sub2/large6 (glob)
580 undeleting .hglf/sub2/large6 (glob)
573 forgetting .hglf/sub2/large8 (glob)
581 forgetting .hglf/sub2/large8 (glob)
574 reverting normal3
582 reverting normal3
575 $ hg status
583 $ hg status
576 ? sub/large4.orig
584 ? sub/large4.orig
577 ? sub/normal4.orig
585 ? sub/normal4.orig
578 ? sub2/large8
586 ? sub2/large8
579 $ cat normal3
587 $ cat normal3
580 normal3-modified
588 normal3-modified
581 $ cat sub2/large6
589 $ cat sub2/large6
582 large6-modified
590 large6-modified
583 $ rm sub/*.orig sub2/large8
591 $ rm sub/*.orig sub2/large8
584
592
585 revert some files to an older revision
593 revert some files to an older revision
586 $ hg revert --no-backup -r 8 sub2
594 $ hg revert --no-backup -r 8 sub2
587 reverting .hglf/sub2/large6 (glob)
595 reverting .hglf/sub2/large6 (glob)
588 $ cat sub2/large6
596 $ cat sub2/large6
589 large6
597 large6
590 $ hg revert --no-backup sub2
598 $ hg revert --no-backup sub2
591 reverting .hglf/sub2/large6 (glob)
599 reverting .hglf/sub2/large6 (glob)
592 $ hg status
600 $ hg status
593
601
594 "verify --large" actually verifies largefiles
602 "verify --large" actually verifies largefiles
595
603
596 $ hg verify --large
604 $ hg verify --large
597 checking changesets
605 checking changesets
598 checking manifests
606 checking manifests
599 crosschecking files in changesets and manifests
607 crosschecking files in changesets and manifests
600 checking files
608 checking files
601 10 files, 10 changesets, 28 total revisions
609 10 files, 10 changesets, 28 total revisions
602 searching 1 changesets for largefiles
610 searching 1 changesets for largefiles
603 verified existence of 3 revisions of 3 largefiles
611 verified existence of 3 revisions of 3 largefiles
604
612
605 Merging does not revert to old versions of largefiles (this has also
613 Merging does not revert to old versions of largefiles (this has also
606 been very problematic).
614 been very problematic).
607
615
608 $ cd ..
616 $ cd ..
609 $ hg clone -r 7 e f
617 $ hg clone -r 7 e f
610 adding changesets
618 adding changesets
611 adding manifests
619 adding manifests
612 adding file changes
620 adding file changes
613 added 8 changesets with 24 changes to 10 files
621 added 8 changesets with 24 changes to 10 files
614 updating to branch default
622 updating to branch default
615 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
623 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
616 getting changed largefiles
624 getting changed largefiles
617 3 largefiles updated, 0 removed
625 3 largefiles updated, 0 removed
618 $ cd f
626 $ cd f
619 $ echo "large4-merge-test" > sub/large4
627 $ echo "large4-merge-test" > sub/large4
620 $ hg commit -m "Modify large4 to test merge"
628 $ hg commit -m "Modify large4 to test merge"
621 Invoking status precommit hook
629 Invoking status precommit hook
622 M sub/large4
630 M sub/large4
623 $ hg pull ../e
631 $ hg pull ../e
624 pulling from ../e
632 pulling from ../e
625 searching for changes
633 searching for changes
626 adding changesets
634 adding changesets
627 adding manifests
635 adding manifests
628 adding file changes
636 adding file changes
629 added 2 changesets with 4 changes to 4 files (+1 heads)
637 added 2 changesets with 4 changes to 4 files (+1 heads)
630 (run 'hg heads' to see heads, 'hg merge' to merge)
638 (run 'hg heads' to see heads, 'hg merge' to merge)
631 $ hg merge
639 $ hg merge
632 merging sub/large4
640 merging sub/large4
633 largefile sub/large4 has a merge conflict
641 largefile sub/large4 has a merge conflict
634 keep (l)ocal or take (o)ther? l
642 keep (l)ocal or take (o)ther? l
635 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
643 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
636 (branch merge, don't forget to commit)
644 (branch merge, don't forget to commit)
637 getting changed largefiles
645 getting changed largefiles
638 1 largefiles updated, 0 removed
646 1 largefiles updated, 0 removed
639 $ hg commit -m "Merge repos e and f"
647 $ hg commit -m "Merge repos e and f"
640 Invoking status precommit hook
648 Invoking status precommit hook
641 M normal3
649 M normal3
642 M sub/normal4
650 M sub/normal4
643 M sub2/large6
651 M sub2/large6
644 $ cat normal3
652 $ cat normal3
645 normal3-modified
653 normal3-modified
646 $ cat sub/normal4
654 $ cat sub/normal4
647 normal4-modified
655 normal4-modified
648 $ cat sub/large4
656 $ cat sub/large4
649 large4-merge-test
657 large4-merge-test
650 $ cat sub2/large6
658 $ cat sub2/large6
651 large6-modified
659 large6-modified
652 $ cat sub2/large7
660 $ cat sub2/large7
653 large7
661 large7
654
662
655 Test status after merging with a branch that introduces a new largefile:
663 Test status after merging with a branch that introduces a new largefile:
656
664
657 $ echo large > large
665 $ echo large > large
658 $ hg add --large large
666 $ hg add --large large
659 $ hg commit -m 'add largefile'
667 $ hg commit -m 'add largefile'
660 Invoking status precommit hook
668 Invoking status precommit hook
661 A large
669 A large
662 $ hg update -q ".^"
670 $ hg update -q ".^"
663 $ echo change >> normal3
671 $ echo change >> normal3
664 $ hg commit -m 'some change'
672 $ hg commit -m 'some change'
665 Invoking status precommit hook
673 Invoking status precommit hook
666 M normal3
674 M normal3
667 created new head
675 created new head
668 $ hg merge
676 $ hg merge
669 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
677 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
670 (branch merge, don't forget to commit)
678 (branch merge, don't forget to commit)
671 getting changed largefiles
679 getting changed largefiles
672 1 largefiles updated, 0 removed
680 1 largefiles updated, 0 removed
673 $ hg status
681 $ hg status
674 M large
682 M large
675
683
676 Test that a normal file and a largefile with the same name and path cannot
684 Test that a normal file and a largefile with the same name and path cannot
677 coexist.
685 coexist.
678
686
679 $ rm sub2/large7
687 $ rm sub2/large7
680 $ echo "largeasnormal" > sub2/large7
688 $ echo "largeasnormal" > sub2/large7
681 $ hg add sub2/large7
689 $ hg add sub2/large7
682 sub2/large7 already a largefile
690 sub2/large7 already a largefile
683
691
684 Test that transplanting a largefile change works correctly.
692 Test that transplanting a largefile change works correctly.
685
693
686 $ cd ..
694 $ cd ..
687 $ hg clone -r 8 d g
695 $ hg clone -r 8 d g
688 adding changesets
696 adding changesets
689 adding manifests
697 adding manifests
690 adding file changes
698 adding file changes
691 added 9 changesets with 26 changes to 10 files
699 added 9 changesets with 26 changes to 10 files
692 updating to branch default
700 updating to branch default
693 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
701 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
694 getting changed largefiles
702 getting changed largefiles
695 3 largefiles updated, 0 removed
703 3 largefiles updated, 0 removed
696 $ cd g
704 $ cd g
697 $ hg transplant -s ../d 598410d3eb9a
705 $ hg transplant -s ../d 598410d3eb9a
698 searching for changes
706 searching for changes
699 searching for changes
707 searching for changes
700 adding changesets
708 adding changesets
701 adding manifests
709 adding manifests
702 adding file changes
710 adding file changes
703 added 1 changesets with 2 changes to 2 files
711 added 1 changesets with 2 changes to 2 files
704 getting changed largefiles
712 getting changed largefiles
705 1 largefiles updated, 0 removed
713 1 largefiles updated, 0 removed
706 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
714 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
707 9:598410d3eb9a modify normal file largefile in repo d
715 9:598410d3eb9a modify normal file largefile in repo d
708 8:a381d2c8c80e modify normal file and largefile in repo b
716 8:a381d2c8c80e modify normal file and largefile in repo b
709 7:daea875e9014 add/edit more largefiles
717 7:daea875e9014 add/edit more largefiles
710 6:4355d653f84f edit files yet again
718 6:4355d653f84f edit files yet again
711 5:9d5af5072dbd edit files again
719 5:9d5af5072dbd edit files again
712 4:74c02385b94c move files
720 4:74c02385b94c move files
713 3:9e8fbc4bce62 copy files
721 3:9e8fbc4bce62 copy files
714 2:51a0ae4d5864 remove files
722 2:51a0ae4d5864 remove files
715 1:ce8896473775 edit files
723 1:ce8896473775 edit files
716 0:30d30fe6a5be add files
724 0:30d30fe6a5be add files
717 $ cat normal3
725 $ cat normal3
718 normal3-modified
726 normal3-modified
719 $ cat sub/normal4
727 $ cat sub/normal4
720 normal4-modified
728 normal4-modified
721 $ cat sub/large4
729 $ cat sub/large4
722 large4-modified
730 large4-modified
723 $ cat sub2/large6
731 $ cat sub2/large6
724 large6-modified
732 large6-modified
725 $ cat sub2/large7
733 $ cat sub2/large7
726 large7
734 large7
727
735
728 Test that renaming a largefile results in correct output for status
736 Test that renaming a largefile results in correct output for status
729
737
730 $ hg rename sub/large4 large4-renamed
738 $ hg rename sub/large4 large4-renamed
731 $ hg commit -m "test rename output"
739 $ hg commit -m "test rename output"
732 Invoking status precommit hook
740 Invoking status precommit hook
733 A large4-renamed
741 A large4-renamed
734 R sub/large4
742 R sub/large4
735 $ cat large4-renamed
743 $ cat large4-renamed
736 large4-modified
744 large4-modified
737 $ cd sub2
745 $ cd sub2
738 $ hg rename large6 large6-renamed
746 $ hg rename large6 large6-renamed
739 $ hg st
747 $ hg st
740 A sub2/large6-renamed
748 A sub2/large6-renamed
741 R sub2/large6
749 R sub2/large6
742 $ cd ../..
750 $ cd ../..
743
751
744 vanilla clients not locked out from largefiles servers on vanilla repos
752 vanilla clients not locked out from largefiles servers on vanilla repos
745 $ mkdir r1
753 $ mkdir r1
746 $ cd r1
754 $ cd r1
747 $ hg init
755 $ hg init
748 $ echo c1 > f1
756 $ echo c1 > f1
749 $ hg add f1
757 $ hg add f1
750 $ hg commit -m "m1"
758 $ hg commit -m "m1"
751 Invoking status precommit hook
759 Invoking status precommit hook
752 A f1
760 A f1
753 $ cd ..
761 $ cd ..
754 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
762 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
755 $ cat hg.pid >> $DAEMON_PIDS
763 $ cat hg.pid >> $DAEMON_PIDS
756 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
764 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
757 requesting all changes
765 requesting all changes
758 adding changesets
766 adding changesets
759 adding manifests
767 adding manifests
760 adding file changes
768 adding file changes
761 added 1 changesets with 1 changes to 1 files
769 added 1 changesets with 1 changes to 1 files
762 updating to branch default
770 updating to branch default
763 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
771 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
764
772
765 largefiles clients still work with vanilla servers
773 largefiles clients still work with vanilla servers
766 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
774 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
767 $ cat hg.pid >> $DAEMON_PIDS
775 $ cat hg.pid >> $DAEMON_PIDS
768 $ hg clone http://localhost:$HGPORT1 r3
776 $ hg clone http://localhost:$HGPORT1 r3
769 requesting all changes
777 requesting all changes
770 adding changesets
778 adding changesets
771 adding manifests
779 adding manifests
772 adding file changes
780 adding file changes
773 added 1 changesets with 1 changes to 1 files
781 added 1 changesets with 1 changes to 1 files
774 updating to branch default
782 updating to branch default
775 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
783 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
776
784
777 vanilla clients locked out from largefiles http repos
785 vanilla clients locked out from largefiles http repos
778 $ mkdir r4
786 $ mkdir r4
779 $ cd r4
787 $ cd r4
780 $ hg init
788 $ hg init
781 $ echo c1 > f1
789 $ echo c1 > f1
782 $ hg add --large f1
790 $ hg add --large f1
783 $ hg commit -m "m1"
791 $ hg commit -m "m1"
784 Invoking status precommit hook
792 Invoking status precommit hook
785 A f1
793 A f1
786 $ cd ..
794 $ cd ..
787 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
795 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
788 $ cat hg.pid >> $DAEMON_PIDS
796 $ cat hg.pid >> $DAEMON_PIDS
789 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
797 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
790 abort: remote error:
798 abort: remote error:
791
799
792 This repository uses the largefiles extension.
800 This repository uses the largefiles extension.
793
801
794 Please enable it in your Mercurial config file.
802 Please enable it in your Mercurial config file.
795 [255]
803 [255]
796
804
797 used all HGPORTs, kill all daemons
805 used all HGPORTs, kill all daemons
798 $ "$TESTDIR/killdaemons.py"
806 $ "$TESTDIR/killdaemons.py"
799
807
800 vanilla clients locked out from largefiles ssh repos
808 vanilla clients locked out from largefiles ssh repos
801 $ hg --config extensions.largefiles=! clone -e "python $TESTDIR/dummyssh" ssh://user@dummy/r4 r5
809 $ hg --config extensions.largefiles=! clone -e "python $TESTDIR/dummyssh" ssh://user@dummy/r4 r5
802 abort: remote error:
810 abort: remote error:
803
811
804 This repository uses the largefiles extension.
812 This repository uses the largefiles extension.
805
813
806 Please enable it in your Mercurial config file.
814 Please enable it in your Mercurial config file.
807 [255]
815 [255]
808
816
809 largefiles clients refuse to push largefiles repos to vanilla servers
817 largefiles clients refuse to push largefiles repos to vanilla servers
810 $ mkdir r6
818 $ mkdir r6
811 $ cd r6
819 $ cd r6
812 $ hg init
820 $ hg init
813 $ echo c1 > f1
821 $ echo c1 > f1
814 $ hg add f1
822 $ hg add f1
815 $ hg commit -m "m1"
823 $ hg commit -m "m1"
816 Invoking status precommit hook
824 Invoking status precommit hook
817 A f1
825 A f1
818 $ cat >> .hg/hgrc <<!
826 $ cat >> .hg/hgrc <<!
819 > [web]
827 > [web]
820 > push_ssl = false
828 > push_ssl = false
821 > allow_push = *
829 > allow_push = *
822 > !
830 > !
823 $ cd ..
831 $ cd ..
824 $ hg clone r6 r7
832 $ hg clone r6 r7
825 updating to branch default
833 updating to branch default
826 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
834 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
827 $ cd r7
835 $ cd r7
828 $ echo c2 > f2
836 $ echo c2 > f2
829 $ hg add --large f2
837 $ hg add --large f2
830 $ hg commit -m "m2"
838 $ hg commit -m "m2"
831 Invoking status precommit hook
839 Invoking status precommit hook
832 A f2
840 A f2
833 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
841 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
834 $ cat ../hg.pid >> $DAEMON_PIDS
842 $ cat ../hg.pid >> $DAEMON_PIDS
835 $ hg push http://localhost:$HGPORT
843 $ hg push http://localhost:$HGPORT
836 pushing to http://localhost:$HGPORT/
844 pushing to http://localhost:$HGPORT/
837 searching for changes
845 searching for changes
838 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
846 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
839 [255]
847 [255]
840 $ cd ..
848 $ cd ..
841
849
842 putlfile errors are shown (issue3123)
850 putlfile errors are shown (issue3123)
843 Corrupt the cached largefile in r7
851 Corrupt the cached largefile in r7
844 $ echo corruption > $USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8
852 $ echo corruption > $USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8
845 $ hg init empty
853 $ hg init empty
846 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
854 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
847 > --config 'web.allow_push=*' --config web.push_ssl=False
855 > --config 'web.allow_push=*' --config web.push_ssl=False
848 $ cat hg.pid >> $DAEMON_PIDS
856 $ cat hg.pid >> $DAEMON_PIDS
849 $ hg push -R r7 http://localhost:$HGPORT1
857 $ hg push -R r7 http://localhost:$HGPORT1
850 pushing to http://localhost:$HGPORT1/
858 pushing to http://localhost:$HGPORT1/
851 searching for changes
859 searching for changes
852 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
860 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
853 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/
861 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/
854 [255]
862 [255]
855 $ rm -rf empty
863 $ rm -rf empty
856
864
857 Clone a local repository owned by another user
865 Clone a local repository owned by another user
858 We have to simulate that here by setting $HOME and removing write permissions
866 We have to simulate that here by setting $HOME and removing write permissions
859 $ ORIGHOME="$HOME"
867 $ ORIGHOME="$HOME"
860 $ mkdir alice
868 $ mkdir alice
861 $ HOME="`pwd`/alice"
869 $ HOME="`pwd`/alice"
862 $ cd alice
870 $ cd alice
863 $ hg init pubrepo
871 $ hg init pubrepo
864 $ cd pubrepo
872 $ cd pubrepo
865 $ dd if=/dev/urandom bs=1k count=11k > a-large-file 2> /dev/null
873 $ dd if=/dev/urandom bs=1k count=11k > a-large-file 2> /dev/null
866 $ hg add --large a-large-file
874 $ hg add --large a-large-file
867 $ hg commit -m "Add a large file"
875 $ hg commit -m "Add a large file"
868 Invoking status precommit hook
876 Invoking status precommit hook
869 A a-large-file
877 A a-large-file
870 $ cd ..
878 $ cd ..
871 $ chmod -R a-w pubrepo
879 $ chmod -R a-w pubrepo
872 $ cd ..
880 $ cd ..
873 $ mkdir bob
881 $ mkdir bob
874 $ HOME="`pwd`/bob"
882 $ HOME="`pwd`/bob"
875 $ cd bob
883 $ cd bob
876 $ hg clone --pull ../alice/pubrepo pubrepo
884 $ hg clone --pull ../alice/pubrepo pubrepo
877 requesting all changes
885 requesting all changes
878 adding changesets
886 adding changesets
879 adding manifests
887 adding manifests
880 adding file changes
888 adding file changes
881 added 1 changesets with 1 changes to 1 files
889 added 1 changesets with 1 changes to 1 files
882 updating to branch default
890 updating to branch default
883 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
891 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
884 getting changed largefiles
892 getting changed largefiles
885 1 largefiles updated, 0 removed
893 1 largefiles updated, 0 removed
886 $ cd ..
894 $ cd ..
887 $ chmod -R u+w alice/pubrepo
895 $ chmod -R u+w alice/pubrepo
888 $ HOME="$ORIGHOME"
896 $ HOME="$ORIGHOME"
889
897
890 Symlink to a large largefile should behave the same as a symlink to a normal file
898 Symlink to a large largefile should behave the same as a symlink to a normal file
891 $ hg init largesymlink
899 $ hg init largesymlink
892 $ cd largesymlink
900 $ cd largesymlink
893 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
901 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
894 $ hg add --large largefile
902 $ hg add --large largefile
895 $ hg commit -m "commit a large file"
903 $ hg commit -m "commit a large file"
896 Invoking status precommit hook
904 Invoking status precommit hook
897 A largefile
905 A largefile
898 $ ln -s largefile largelink
906 $ ln -s largefile largelink
899 $ hg add largelink
907 $ hg add largelink
900 $ hg commit -m "commit a large symlink"
908 $ hg commit -m "commit a large symlink"
901 Invoking status precommit hook
909 Invoking status precommit hook
902 A largelink
910 A largelink
903 $ rm -f largelink
911 $ rm -f largelink
904 $ hg up >/dev/null
912 $ hg up >/dev/null
905 $ test -f largelink
913 $ test -f largelink
906 [1]
914 [1]
907 $ test -L largelink
915 $ test -L largelink
908 [1]
916 [1]
909 $ rm -f largelink # make next part of the test independent of the previous
917 $ rm -f largelink # make next part of the test independent of the previous
910 $ hg up -C >/dev/null
918 $ hg up -C >/dev/null
911 $ test -f largelink
919 $ test -f largelink
912 $ test -L largelink
920 $ test -L largelink
913 $ cd ..
921 $ cd ..
914
922
915
923
General Comments 0
You need to be logged in to leave comments. Login now