##// END OF EJS Templates
largefiles: include 'largefiles' in converted repository requirements
Eli Carter -
r15303:07811b3b stable
parent child Browse files
Show More
@@ -1,481 +1,486
1 1 # Copyright 2009-2010 Gregory P. Ward
2 2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 3 # Copyright 2010-2011 Fog Creek Software
4 4 # Copyright 2010-2011 Unity Technologies
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 '''High-level command function for lfconvert, plus the cmdtable.'''
10 10
11 11 import os
12 12 import shutil
13 13
14 14 from mercurial import util, match as match_, hg, node, context, error
15 15 from mercurial.i18n import _
16 16
17 17 import lfutil
18 18 import basestore
19 19
20 20 # -- Commands ----------------------------------------------------------
21 21
22 22 def lfconvert(ui, src, dest, *pats, **opts):
23 23 '''convert a normal repository to a largefiles repository
24 24
25 25 Convert repository SOURCE to a new repository DEST, identical to
26 26 SOURCE except that certain files will be converted as largefiles:
27 27 specifically, any file that matches any PATTERN *or* whose size is
28 28 above the minimum size threshold is converted as a largefile. The
29 29 size used to determine whether or not to track a file as a
30 30 largefile is the size of the first version of the file. The
31 31 minimum size can be specified either with --size or in
32 32 configuration as ``largefiles.size``.
33 33
34 34 After running this command you will need to make sure that
35 35 largefiles is enabled anywhere you intend to push the new
36 36 repository.
37 37
38 38 Use --tonormal to convert largefiles back to normal files; after
39 39 this, the DEST repository can be used without largefiles at all.'''
40 40
41 41 if opts['tonormal']:
42 42 tolfile = False
43 43 else:
44 44 tolfile = True
45 45 size = lfutil.getminsize(ui, True, opts.get('size'), default=None)
46 46 try:
47 47 rsrc = hg.repository(ui, src)
48 48 if not rsrc.local():
49 49 raise util.Abort(_('%s is not a local Mercurial repo') % src)
50 50 except error.RepoError, err:
51 51 ui.traceback()
52 52 raise util.Abort(err.args[0])
53 53 if os.path.exists(dest):
54 54 if not os.path.isdir(dest):
55 55 raise util.Abort(_('destination %s already exists') % dest)
56 56 elif os.listdir(dest):
57 57 raise util.Abort(_('destination %s is not empty') % dest)
58 58 try:
59 59 ui.status(_('initializing destination %s\n') % dest)
60 60 rdst = hg.repository(ui, dest, create=True)
61 61 if not rdst.local():
62 62 raise util.Abort(_('%s is not a local Mercurial repo') % dest)
63 63 except error.RepoError:
64 64 ui.traceback()
65 65 raise util.Abort(_('%s is not a repo') % dest)
66 66
67 67 success = False
68 68 try:
69 69 # Lock destination to prevent modification while it is converted to.
70 70 # Don't need to lock src because we are just reading from its history
71 71 # which can't change.
72 72 dst_lock = rdst.lock()
73 73
74 74 # Get a list of all changesets in the source. The easy way to do this
75 75 # is to simply walk the changelog, using changelog.nodesbewteen().
76 76 # Take a look at mercurial/revlog.py:639 for more details.
77 77 # Use a generator instead of a list to decrease memory usage
78 78 ctxs = (rsrc[ctx] for ctx in rsrc.changelog.nodesbetween(None,
79 79 rsrc.heads())[0])
80 80 revmap = {node.nullid: node.nullid}
81 81 if tolfile:
82 82 lfiles = set()
83 83 normalfiles = set()
84 84 if not pats:
85 85 pats = ui.config(lfutil.longname, 'patterns', default=())
86 86 if pats:
87 87 pats = pats.split(' ')
88 88 if pats:
89 89 matcher = match_.match(rsrc.root, '', list(pats))
90 90 else:
91 91 matcher = None
92 92
93 93 lfiletohash = {}
94 94 for ctx in ctxs:
95 95 ui.progress(_('converting revisions'), ctx.rev(),
96 96 unit=_('revision'), total=rsrc['tip'].rev())
97 97 _lfconvert_addchangeset(rsrc, rdst, ctx, revmap,
98 98 lfiles, normalfiles, matcher, size, lfiletohash)
99 99 ui.progress(_('converting revisions'), None)
100 100
101 101 if os.path.exists(rdst.wjoin(lfutil.shortname)):
102 102 shutil.rmtree(rdst.wjoin(lfutil.shortname))
103 103
104 104 for f in lfiletohash.keys():
105 105 if os.path.isfile(rdst.wjoin(f)):
106 106 os.unlink(rdst.wjoin(f))
107 107 try:
108 108 os.removedirs(os.path.dirname(rdst.wjoin(f)))
109 109 except OSError:
110 110 pass
111 111
112 # If there were any files converted to largefiles, add largefiles
113 # to the destination repository's requirements.
114 if lfiles:
115 rdst.requirements.add('largefiles')
116 rdst._writerequirements()
112 117 else:
113 118 for ctx in ctxs:
114 119 ui.progress(_('converting revisions'), ctx.rev(),
115 120 unit=_('revision'), total=rsrc['tip'].rev())
116 121 _addchangeset(ui, rsrc, rdst, ctx, revmap)
117 122
118 123 ui.progress(_('converting revisions'), None)
119 124 success = True
120 125 finally:
121 126 if not success:
122 127 # we failed, remove the new directory
123 128 shutil.rmtree(rdst.root)
124 129 dst_lock.release()
125 130
126 131 def _addchangeset(ui, rsrc, rdst, ctx, revmap):
127 132 # Convert src parents to dst parents
128 133 parents = []
129 134 for p in ctx.parents():
130 135 parents.append(revmap[p.node()])
131 136 while len(parents) < 2:
132 137 parents.append(node.nullid)
133 138
134 139 # Generate list of changed files
135 140 files = set(ctx.files())
136 141 if node.nullid not in parents:
137 142 mc = ctx.manifest()
138 143 mp1 = ctx.parents()[0].manifest()
139 144 mp2 = ctx.parents()[1].manifest()
140 145 files |= (set(mp1) | set(mp2)) - set(mc)
141 146 for f in mc:
142 147 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
143 148 files.add(f)
144 149
145 150 def getfilectx(repo, memctx, f):
146 151 if lfutil.standin(f) in files:
147 152 # if the file isn't in the manifest then it was removed
148 153 # or renamed, raise IOError to indicate this
149 154 try:
150 155 fctx = ctx.filectx(lfutil.standin(f))
151 156 except error.LookupError:
152 157 raise IOError()
153 158 renamed = fctx.renamed()
154 159 if renamed:
155 160 renamed = lfutil.splitstandin(renamed[0])
156 161
157 162 hash = fctx.data().strip()
158 163 path = lfutil.findfile(rsrc, hash)
159 164 ### TODO: What if the file is not cached?
160 165 data = ''
161 166 fd = None
162 167 try:
163 168 fd = open(path, 'rb')
164 169 data = fd.read()
165 170 finally:
166 171 if fd:
167 172 fd.close()
168 173 return context.memfilectx(f, data, 'l' in fctx.flags(),
169 174 'x' in fctx.flags(), renamed)
170 175 else:
171 176 try:
172 177 fctx = ctx.filectx(f)
173 178 except error.LookupError:
174 179 raise IOError()
175 180 renamed = fctx.renamed()
176 181 if renamed:
177 182 renamed = renamed[0]
178 183 data = fctx.data()
179 184 if f == '.hgtags':
180 185 newdata = []
181 186 for line in data.splitlines():
182 187 id, name = line.split(' ', 1)
183 188 newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]),
184 189 name))
185 190 data = ''.join(newdata)
186 191 return context.memfilectx(f, data, 'l' in fctx.flags(),
187 192 'x' in fctx.flags(), renamed)
188 193
189 194 dstfiles = []
190 195 for file in files:
191 196 if lfutil.isstandin(file):
192 197 dstfiles.append(lfutil.splitstandin(file))
193 198 else:
194 199 dstfiles.append(file)
195 200 # Commit
196 201 mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
197 202 getfilectx, ctx.user(), ctx.date(), ctx.extra())
198 203 ret = rdst.commitctx(mctx)
199 204 rdst.dirstate.setparents(ret)
200 205 revmap[ctx.node()] = rdst.changelog.tip()
201 206
202 207 def _lfconvert_addchangeset(rsrc, rdst, ctx, revmap, lfiles, normalfiles,
203 208 matcher, size, lfiletohash):
204 209 # Convert src parents to dst parents
205 210 parents = []
206 211 for p in ctx.parents():
207 212 parents.append(revmap[p.node()])
208 213 while len(parents) < 2:
209 214 parents.append(node.nullid)
210 215
211 216 # Generate list of changed files
212 217 files = set(ctx.files())
213 218 if node.nullid not in parents:
214 219 mc = ctx.manifest()
215 220 mp1 = ctx.parents()[0].manifest()
216 221 mp2 = ctx.parents()[1].manifest()
217 222 files |= (set(mp1) | set(mp2)) - set(mc)
218 223 for f in mc:
219 224 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
220 225 files.add(f)
221 226
222 227 dstfiles = []
223 228 for f in files:
224 229 if f not in lfiles and f not in normalfiles:
225 230 islfile = _islfile(f, ctx, matcher, size)
226 231 # If this file was renamed or copied then copy
227 232 # the lfileness of its predecessor
228 233 if f in ctx.manifest():
229 234 fctx = ctx.filectx(f)
230 235 renamed = fctx.renamed()
231 236 renamedlfile = renamed and renamed[0] in lfiles
232 237 islfile |= renamedlfile
233 238 if 'l' in fctx.flags():
234 239 if renamedlfile:
235 240 raise util.Abort(
236 241 _('Renamed/copied largefile %s becomes symlink')
237 242 % f)
238 243 islfile = False
239 244 if islfile:
240 245 lfiles.add(f)
241 246 else:
242 247 normalfiles.add(f)
243 248
244 249 if f in lfiles:
245 250 dstfiles.append(lfutil.standin(f))
246 251 # largefile in manifest if it has not been removed/renamed
247 252 if f in ctx.manifest():
248 253 if 'l' in ctx.filectx(f).flags():
249 254 if renamed and renamed[0] in lfiles:
250 255 raise util.Abort(_('largefile %s becomes symlink') % f)
251 256
252 257 # largefile was modified, update standins
253 258 fullpath = rdst.wjoin(f)
254 259 lfutil.createdir(os.path.dirname(fullpath))
255 260 m = util.sha1('')
256 261 m.update(ctx[f].data())
257 262 hash = m.hexdigest()
258 263 if f not in lfiletohash or lfiletohash[f] != hash:
259 264 try:
260 265 fd = open(fullpath, 'wb')
261 266 fd.write(ctx[f].data())
262 267 finally:
263 268 if fd:
264 269 fd.close()
265 270 executable = 'x' in ctx[f].flags()
266 271 os.chmod(fullpath, lfutil.getmode(executable))
267 272 lfutil.writestandin(rdst, lfutil.standin(f), hash,
268 273 executable)
269 274 lfiletohash[f] = hash
270 275 else:
271 276 # normal file
272 277 dstfiles.append(f)
273 278
274 279 def getfilectx(repo, memctx, f):
275 280 if lfutil.isstandin(f):
276 281 # if the file isn't in the manifest then it was removed
277 282 # or renamed, raise IOError to indicate this
278 283 srcfname = lfutil.splitstandin(f)
279 284 try:
280 285 fctx = ctx.filectx(srcfname)
281 286 except error.LookupError:
282 287 raise IOError()
283 288 renamed = fctx.renamed()
284 289 if renamed:
285 290 # standin is always a largefile because largefile-ness
286 291 # doesn't change after rename or copy
287 292 renamed = lfutil.standin(renamed[0])
288 293
289 294 return context.memfilectx(f, lfiletohash[srcfname], 'l' in
290 295 fctx.flags(), 'x' in fctx.flags(), renamed)
291 296 else:
292 297 try:
293 298 fctx = ctx.filectx(f)
294 299 except error.LookupError:
295 300 raise IOError()
296 301 renamed = fctx.renamed()
297 302 if renamed:
298 303 renamed = renamed[0]
299 304
300 305 data = fctx.data()
301 306 if f == '.hgtags':
302 307 newdata = []
303 308 for line in data.splitlines():
304 309 id, name = line.split(' ', 1)
305 310 newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]),
306 311 name))
307 312 data = ''.join(newdata)
308 313 return context.memfilectx(f, data, 'l' in fctx.flags(),
309 314 'x' in fctx.flags(), renamed)
310 315
311 316 # Commit
312 317 mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
313 318 getfilectx, ctx.user(), ctx.date(), ctx.extra())
314 319 ret = rdst.commitctx(mctx)
315 320 rdst.dirstate.setparents(ret)
316 321 revmap[ctx.node()] = rdst.changelog.tip()
317 322
318 323 def _islfile(file, ctx, matcher, size):
319 324 '''Return true if file should be considered a largefile, i.e.
320 325 matcher matches it or it is larger than size.'''
321 326 # never store special .hg* files as largefiles
322 327 if file == '.hgtags' or file == '.hgignore' or file == '.hgsigs':
323 328 return False
324 329 if matcher and matcher(file):
325 330 return True
326 331 try:
327 332 return ctx.filectx(file).size() >= size * 1024 * 1024
328 333 except error.LookupError:
329 334 return False
330 335
331 336 def uploadlfiles(ui, rsrc, rdst, files):
332 337 '''upload largefiles to the central store'''
333 338
334 339 # Don't upload locally. All largefiles are in the system wide cache
335 340 # so the other repo can just get them from there.
336 341 if not files or rdst.local():
337 342 return
338 343
339 344 store = basestore._openstore(rsrc, rdst, put=True)
340 345
341 346 at = 0
342 347 files = filter(lambda h: not store.exists(h), files)
343 348 for hash in files:
344 349 ui.progress(_('uploading largefiles'), at, unit='largefile',
345 350 total=len(files))
346 351 source = lfutil.findfile(rsrc, hash)
347 352 if not source:
348 353 raise util.Abort(_('largefile %s missing from store'
349 354 ' (needs to be uploaded)') % hash)
350 355 # XXX check for errors here
351 356 store.put(source, hash)
352 357 at += 1
353 358 ui.progress(_('uploading largefiles'), None)
354 359
355 360 def verifylfiles(ui, repo, all=False, contents=False):
356 361 '''Verify that every big file revision in the current changeset
357 362 exists in the central store. With --contents, also verify that
358 363 the contents of each big file revision are correct (SHA-1 hash
359 364 matches the revision ID). With --all, check every changeset in
360 365 this repository.'''
361 366 if all:
362 367 # Pass a list to the function rather than an iterator because we know a
363 368 # list will work.
364 369 revs = range(len(repo))
365 370 else:
366 371 revs = ['.']
367 372
368 373 store = basestore._openstore(repo)
369 374 return store.verify(revs, contents=contents)
370 375
371 376 def cachelfiles(ui, repo, node):
372 377 '''cachelfiles ensures that all largefiles needed by the specified revision
373 378 are present in the repository's largefile cache.
374 379
375 380 returns a tuple (cached, missing). cached is the list of files downloaded
376 381 by this operation; missing is the list of files that were needed but could
377 382 not be found.'''
378 383 lfiles = lfutil.listlfiles(repo, node)
379 384 toget = []
380 385
381 386 for lfile in lfiles:
382 387 expectedhash = repo[node][lfutil.standin(lfile)].data().strip()
383 388 # if it exists and its hash matches, it might have been locally
384 389 # modified before updating and the user chose 'local'. in this case,
385 390 # it will not be in any store, so don't look for it.
386 391 if ((not os.path.exists(repo.wjoin(lfile)) or
387 392 expectedhash != lfutil.hashfile(repo.wjoin(lfile))) and
388 393 not lfutil.findfile(repo, expectedhash)):
389 394 toget.append((lfile, expectedhash))
390 395
391 396 if toget:
392 397 store = basestore._openstore(repo)
393 398 ret = store.get(toget)
394 399 return ret
395 400
396 401 return ([], [])
397 402
398 403 def updatelfiles(ui, repo, filelist=None, printmessage=True):
399 404 wlock = repo.wlock()
400 405 try:
401 406 lfdirstate = lfutil.openlfdirstate(ui, repo)
402 407 lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate)
403 408
404 409 if filelist is not None:
405 410 lfiles = [f for f in lfiles if f in filelist]
406 411
407 412 printed = False
408 413 if printmessage and lfiles:
409 414 ui.status(_('getting changed largefiles\n'))
410 415 printed = True
411 416 cachelfiles(ui, repo, '.')
412 417
413 418 updated, removed = 0, 0
414 419 for i in map(lambda f: _updatelfile(repo, lfdirstate, f), lfiles):
415 420 # increment the appropriate counter according to _updatelfile's
416 421 # return value
417 422 updated += i > 0 and i or 0
418 423 removed -= i < 0 and i or 0
419 424 if printmessage and (removed or updated) and not printed:
420 425 ui.status(_('getting changed largefiles\n'))
421 426 printed = True
422 427
423 428 lfdirstate.write()
424 429 if printed and printmessage:
425 430 ui.status(_('%d largefiles updated, %d removed\n') % (updated,
426 431 removed))
427 432 finally:
428 433 wlock.release()
429 434
430 435 def _updatelfile(repo, lfdirstate, lfile):
431 436 '''updates a single largefile and copies the state of its standin from
432 437 the repository's dirstate to its state in the lfdirstate.
433 438
434 439 returns 1 if the file was modified, -1 if the file was removed, 0 if the
435 440 file was unchanged, and None if the needed largefile was missing from the
436 441 cache.'''
437 442 ret = 0
438 443 abslfile = repo.wjoin(lfile)
439 444 absstandin = repo.wjoin(lfutil.standin(lfile))
440 445 if os.path.exists(absstandin):
441 446 if os.path.exists(absstandin+'.orig'):
442 447 shutil.copyfile(abslfile, abslfile+'.orig')
443 448 expecthash = lfutil.readstandin(repo, lfile)
444 449 if (expecthash != '' and
445 450 (not os.path.exists(abslfile) or
446 451 expecthash != lfutil.hashfile(abslfile))):
447 452 if not lfutil.copyfromcache(repo, expecthash, lfile):
448 453 return None # don't try to set the mode or update the dirstate
449 454 ret = 1
450 455 mode = os.stat(absstandin).st_mode
451 456 if mode != os.stat(abslfile).st_mode:
452 457 os.chmod(abslfile, mode)
453 458 ret = 1
454 459 else:
455 460 if os.path.exists(abslfile):
456 461 os.unlink(abslfile)
457 462 ret = -1
458 463 state = repo.dirstate[lfutil.standin(lfile)]
459 464 if state == 'n':
460 465 lfdirstate.normal(lfile)
461 466 elif state == 'r':
462 467 lfdirstate.remove(lfile)
463 468 elif state == 'a':
464 469 lfdirstate.add(lfile)
465 470 elif state == '?':
466 471 lfdirstate.drop(lfile)
467 472 return ret
468 473
469 474 # -- hg commands declarations ------------------------------------------------
470 475
471 476 cmdtable = {
472 477 'lfconvert': (lfconvert,
473 478 [('s', 'size', '',
474 479 _('minimum size (MB) for files to be converted '
475 480 'as largefiles'),
476 481 'SIZE'),
477 482 ('', 'tonormal', False,
478 483 _('convert from a largefiles repo to a normal repo')),
479 484 ],
480 485 _('hg lfconvert SOURCE DEST [FILE ...]')),
481 486 }
@@ -1,663 +1,687
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > largefiles=
4 4 > purge=
5 5 > rebase=
6 6 > [largefiles]
7 7 > size=2
8 8 > patterns=glob:**.dat
9 9 > EOF
10 10
11 11 Create the repo with a couple of revisions of both large and normal
12 12 files (testing that status correctly shows largefiles.
13 13
14 14 $ hg init a
15 15 $ cd a
16 16 $ mkdir sub
17 17 $ echo normal1 > normal1
18 18 $ echo normal2 > sub/normal2
19 19 $ echo large1 > large1
20 20 $ echo large2 > sub/large2
21 21 $ hg add normal1 sub/normal2
22 22 $ hg add --large large1 sub/large2
23 23 $ hg commit -m "add files"
24 24 $ echo normal11 > normal1
25 25 $ echo normal22 > sub/normal2
26 26 $ echo large11 > large1
27 27 $ echo large22 > sub/large2
28 28 $ hg st
29 29 M large1
30 30 M normal1
31 31 M sub/large2
32 32 M sub/normal2
33 33 $ hg commit -m "edit files"
34 34
35 35 Verify that committing new versions of largefiles results in correct
36 36 largefile contents, and also that non-largefiles are not affected
37 37 badly.
38 38
39 39 $ cat normal1
40 40 normal11
41 41 $ cat large1
42 42 large11
43 43 $ cat sub/normal2
44 44 normal22
45 45 $ cat sub/large2
46 46 large22
47 47
48 48 Verify removing largefiles and normal files works on largefile repos.
49 49
50 50 $ hg remove normal1 large1
51 51 $ hg commit -m "remove files"
52 52 $ ls
53 53 sub
54 54
55 55 Test copying largefiles.
56 56
57 57 $ hg cp sub/normal2 normal1
58 58 $ hg cp sub/large2 large1
59 59 $ hg commit -m "copy files"
60 60 $ cat normal1
61 61 normal22
62 62 $ cat large1
63 63 large22
64 64
65 65 Test moving largefiles and verify that normal files are also unaffected.
66 66
67 67 $ hg mv normal1 normal3
68 68 $ hg mv large1 large3
69 69 $ hg mv sub/normal2 sub/normal4
70 70 $ hg mv sub/large2 sub/large4
71 71 $ hg commit -m "move files"
72 72 $ cat normal3
73 73 normal22
74 74 $ cat large3
75 75 large22
76 76 $ cat sub/normal4
77 77 normal22
78 78 $ cat sub/large4
79 79 large22
80 80
81 81 Test archiving the various revisions. These hit corner cases known with
82 82 archiving.
83 83
84 84 $ hg archive -r 0 ../archive0
85 85 $ hg archive -r 1 ../archive1
86 86 $ hg archive -r 2 ../archive2
87 87 $ hg archive -r 3 ../archive3
88 88 $ hg archive -r 4 ../archive4
89 89 $ cd ../archive0
90 90 $ cat normal1
91 91 normal1
92 92 $ cat large1
93 93 large1
94 94 $ cat sub/normal2
95 95 normal2
96 96 $ cat sub/large2
97 97 large2
98 98 $ cd ../archive1
99 99 $ cat normal1
100 100 normal11
101 101 $ cat large1
102 102 large11
103 103 $ cat sub/normal2
104 104 normal22
105 105 $ cat sub/large2
106 106 large22
107 107 $ cd ../archive2
108 108 $ ls
109 109 sub
110 110 $ cat sub/normal2
111 111 normal22
112 112 $ cat sub/large2
113 113 large22
114 114 $ cd ../archive3
115 115 $ cat normal1
116 116 normal22
117 117 $ cat large1
118 118 large22
119 119 $ cat sub/normal2
120 120 normal22
121 121 $ cat sub/large2
122 122 large22
123 123 $ cd ../archive4
124 124 $ cat normal3
125 125 normal22
126 126 $ cat large3
127 127 large22
128 128 $ cat sub/normal4
129 129 normal22
130 130 $ cat sub/large4
131 131 large22
132 132
133 133 Test a separate commit corner case (specifying files to commit) and check
134 134 that the commited files have the right value.
135 135
136 136 $ cd ../a
137 137 $ echo normal3 > normal3
138 138 $ echo large3 > large3
139 139 $ echo normal4 > sub/normal4
140 140 $ echo large4 > sub/large4
141 141 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
142 142 $ cat normal3
143 143 normal3
144 144 $ cat large3
145 145 large3
146 146 $ cat sub/normal4
147 147 normal4
148 148 $ cat sub/large4
149 149 large4
150 150
151 151 Test one more commit corner case that has been known to break (comitting from
152 152 a sub-directory of the repo).
153 153
154 154 $ cd ../a
155 155 $ echo normal33 > normal3
156 156 $ echo large33 > large3
157 157 $ echo normal44 > sub/normal4
158 158 $ echo large44 > sub/large4
159 159 $ cd sub
160 160 $ hg commit -m "edit files yet again"
161 161 $ cat ../normal3
162 162 normal33
163 163 $ cat ../large3
164 164 large33
165 165 $ cat normal4
166 166 normal44
167 167 $ cat large4
168 168 large44
169 169
170 170 Check that committing standins is not allowed.
171 171
172 172 $ cd ..
173 173 $ echo large3 > large3
174 174 $ hg commit .hglf/large3 -m "try to commit standin"
175 175 abort: file ".hglf/large3" is a largefile standin
176 176 (commit the largefile itself instead)
177 177 [255]
178 178
179 179 Test some cornercases for adding largefiles.
180 180
181 181 $ echo large5 > large5
182 182 $ hg add --large large5
183 183 $ hg add --large large5
184 184 large5 already a largefile
185 185 $ mkdir sub2
186 186 $ echo large6 > sub2/large6
187 187 $ echo large7 > sub2/large7
188 188 $ hg add --large sub2
189 189 adding sub2/large6 as a largefile
190 190 adding sub2/large7 as a largefile
191 191 $ hg st
192 192 M large3
193 193 A large5
194 194 A sub2/large6
195 195 A sub2/large7
196 196
197 197 Test that files get added as largefiles based on .hgrc settings
198 198
199 199 $ echo testdata > test.dat
200 200 $ dd bs=3145728 count=1 if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
201 201 $ hg add
202 202 adding reallylarge as a largefile
203 203 adding test.dat as a largefile
204 204 $ dd bs=1048576 count=1 if=/dev/zero of=reallylarge2 > /dev/null 2> /dev/null
205 205
206 206 Test that specifying the --lsize command on the comand-line works
207 207
208 208 $ hg add --lfsize 1
209 209 adding reallylarge2 as a largefile
210 210
211 211 Test forget on largefiles.
212 212
213 213 $ hg forget large3 large5 test.dat reallylarge reallylarge2
214 214 $ hg st
215 215 A sub2/large6
216 216 A sub2/large7
217 217 R large3
218 218 ? large5
219 219 ? reallylarge
220 220 ? reallylarge2
221 221 ? test.dat
222 222 $ hg commit -m "add/edit more largefiles"
223 223 $ hg st
224 224 ? large3
225 225 ? large5
226 226 ? reallylarge
227 227 ? reallylarge2
228 228 ? test.dat
229 229
230 230 Test purge with largefiles (verify that largefiles get populated in the
231 231 working copy correctly after a purge)
232 232
233 233 $ hg purge --all
234 234 $ cat sub/large4
235 235 large44
236 236 $ cat sub2/large6
237 237 large6
238 238 $ cat sub2/large7
239 239 large7
240 240
241 241 Test cloning a largefiles repo.
242 242
243 243 $ cd ..
244 244 $ hg clone a b
245 245 updating to branch default
246 246 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
247 247 getting changed largefiles
248 248 3 largefiles updated, 0 removed
249 249 $ cd b
250 250 $ hg log
251 251 changeset: 7:daea875e9014
252 252 tag: tip
253 253 user: test
254 254 date: Thu Jan 01 00:00:00 1970 +0000
255 255 summary: add/edit more largefiles
256 256
257 257 changeset: 6:4355d653f84f
258 258 user: test
259 259 date: Thu Jan 01 00:00:00 1970 +0000
260 260 summary: edit files yet again
261 261
262 262 changeset: 5:9d5af5072dbd
263 263 user: test
264 264 date: Thu Jan 01 00:00:00 1970 +0000
265 265 summary: edit files again
266 266
267 267 changeset: 4:74c02385b94c
268 268 user: test
269 269 date: Thu Jan 01 00:00:00 1970 +0000
270 270 summary: move files
271 271
272 272 changeset: 3:9e8fbc4bce62
273 273 user: test
274 274 date: Thu Jan 01 00:00:00 1970 +0000
275 275 summary: copy files
276 276
277 277 changeset: 2:51a0ae4d5864
278 278 user: test
279 279 date: Thu Jan 01 00:00:00 1970 +0000
280 280 summary: remove files
281 281
282 282 changeset: 1:ce8896473775
283 283 user: test
284 284 date: Thu Jan 01 00:00:00 1970 +0000
285 285 summary: edit files
286 286
287 287 changeset: 0:30d30fe6a5be
288 288 user: test
289 289 date: Thu Jan 01 00:00:00 1970 +0000
290 290 summary: add files
291 291
292 292 $ cat normal3
293 293 normal33
294 294 $ cat sub/normal4
295 295 normal44
296 296 $ cat sub/large4
297 297 large44
298 298 $ cat sub2/large6
299 299 large6
300 300 $ cat sub2/large7
301 301 large7
302 302 $ cd ..
303 303 $ hg clone a -r 3 c
304 304 adding changesets
305 305 adding manifests
306 306 adding file changes
307 307 added 4 changesets with 10 changes to 4 files
308 308 updating to branch default
309 309 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
310 310 getting changed largefiles
311 311 2 largefiles updated, 0 removed
312 312 $ cd c
313 313 $ hg log
314 314 changeset: 3:9e8fbc4bce62
315 315 tag: tip
316 316 user: test
317 317 date: Thu Jan 01 00:00:00 1970 +0000
318 318 summary: copy files
319 319
320 320 changeset: 2:51a0ae4d5864
321 321 user: test
322 322 date: Thu Jan 01 00:00:00 1970 +0000
323 323 summary: remove files
324 324
325 325 changeset: 1:ce8896473775
326 326 user: test
327 327 date: Thu Jan 01 00:00:00 1970 +0000
328 328 summary: edit files
329 329
330 330 changeset: 0:30d30fe6a5be
331 331 user: test
332 332 date: Thu Jan 01 00:00:00 1970 +0000
333 333 summary: add files
334 334
335 335 $ cat normal1
336 336 normal22
337 337 $ cat large1
338 338 large22
339 339 $ cat sub/normal2
340 340 normal22
341 341 $ cat sub/large2
342 342 large22
343 343
344 344 Test that old revisions of a clone have correct largefiles content. This also
345 345 tests update.
346 346
347 347 $ hg update -r 1
348 348 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
349 349 getting changed largefiles
350 350 1 largefiles updated, 0 removed
351 351 $ cat large1
352 352 large11
353 353 $ cat sub/large2
354 354 large22
355 355
356 356 Test that rebasing between two repositories does not revert largefiles to old
357 357 revisions (this was a very bad bug that took a lot of work to fix).
358 358
359 359 $ cd ..
360 360 $ hg clone a d
361 361 updating to branch default
362 362 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
363 363 getting changed largefiles
364 364 3 largefiles updated, 0 removed
365 365 $ cd b
366 366 $ echo large4-modified > sub/large4
367 367 $ echo normal3-modified > normal3
368 368 $ hg commit -m "modify normal file and largefile in repo b"
369 369 $ cd ../d
370 370 $ echo large6-modified > sub2/large6
371 371 $ echo normal4-modified > sub/normal4
372 372 $ hg commit -m "modify normal file largefile in repo d"
373 373 $ cd ..
374 374 $ hg clone d e
375 375 updating to branch default
376 376 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 377 getting changed largefiles
378 378 3 largefiles updated, 0 removed
379 379 $ cd d
380 380 $ hg pull --rebase ../b
381 381 pulling from ../b
382 382 searching for changes
383 383 adding changesets
384 384 adding manifests
385 385 adding file changes
386 386 added 1 changesets with 2 changes to 2 files (+1 heads)
387 387 getting changed largefiles
388 388 1 largefiles updated, 0 removed
389 389 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg
390 390 nothing to rebase
391 391 $ hg log
392 392 changeset: 9:598410d3eb9a
393 393 tag: tip
394 394 user: test
395 395 date: Thu Jan 01 00:00:00 1970 +0000
396 396 summary: modify normal file largefile in repo d
397 397
398 398 changeset: 8:a381d2c8c80e
399 399 user: test
400 400 date: Thu Jan 01 00:00:00 1970 +0000
401 401 summary: modify normal file and largefile in repo b
402 402
403 403 changeset: 7:daea875e9014
404 404 user: test
405 405 date: Thu Jan 01 00:00:00 1970 +0000
406 406 summary: add/edit more largefiles
407 407
408 408 changeset: 6:4355d653f84f
409 409 user: test
410 410 date: Thu Jan 01 00:00:00 1970 +0000
411 411 summary: edit files yet again
412 412
413 413 changeset: 5:9d5af5072dbd
414 414 user: test
415 415 date: Thu Jan 01 00:00:00 1970 +0000
416 416 summary: edit files again
417 417
418 418 changeset: 4:74c02385b94c
419 419 user: test
420 420 date: Thu Jan 01 00:00:00 1970 +0000
421 421 summary: move files
422 422
423 423 changeset: 3:9e8fbc4bce62
424 424 user: test
425 425 date: Thu Jan 01 00:00:00 1970 +0000
426 426 summary: copy files
427 427
428 428 changeset: 2:51a0ae4d5864
429 429 user: test
430 430 date: Thu Jan 01 00:00:00 1970 +0000
431 431 summary: remove files
432 432
433 433 changeset: 1:ce8896473775
434 434 user: test
435 435 date: Thu Jan 01 00:00:00 1970 +0000
436 436 summary: edit files
437 437
438 438 changeset: 0:30d30fe6a5be
439 439 user: test
440 440 date: Thu Jan 01 00:00:00 1970 +0000
441 441 summary: add files
442 442
443 443 $ cat normal3
444 444 normal3-modified
445 445 $ cat sub/normal4
446 446 normal4-modified
447 447 $ cat sub/large4
448 448 large4-modified
449 449 $ cat sub2/large6
450 450 large6-modified
451 451 $ cat sub2/large7
452 452 large7
453 453 $ cd ../e
454 454 $ hg pull ../b
455 455 pulling from ../b
456 456 searching for changes
457 457 adding changesets
458 458 adding manifests
459 459 adding file changes
460 460 added 1 changesets with 2 changes to 2 files (+1 heads)
461 461 (run 'hg heads' to see heads, 'hg merge' to merge)
462 462 $ hg rebase
463 463 getting changed largefiles
464 464 1 largefiles updated, 0 removed
465 465 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg
466 466 $ hg log
467 467 changeset: 9:598410d3eb9a
468 468 tag: tip
469 469 user: test
470 470 date: Thu Jan 01 00:00:00 1970 +0000
471 471 summary: modify normal file largefile in repo d
472 472
473 473 changeset: 8:a381d2c8c80e
474 474 user: test
475 475 date: Thu Jan 01 00:00:00 1970 +0000
476 476 summary: modify normal file and largefile in repo b
477 477
478 478 changeset: 7:daea875e9014
479 479 user: test
480 480 date: Thu Jan 01 00:00:00 1970 +0000
481 481 summary: add/edit more largefiles
482 482
483 483 changeset: 6:4355d653f84f
484 484 user: test
485 485 date: Thu Jan 01 00:00:00 1970 +0000
486 486 summary: edit files yet again
487 487
488 488 changeset: 5:9d5af5072dbd
489 489 user: test
490 490 date: Thu Jan 01 00:00:00 1970 +0000
491 491 summary: edit files again
492 492
493 493 changeset: 4:74c02385b94c
494 494 user: test
495 495 date: Thu Jan 01 00:00:00 1970 +0000
496 496 summary: move files
497 497
498 498 changeset: 3:9e8fbc4bce62
499 499 user: test
500 500 date: Thu Jan 01 00:00:00 1970 +0000
501 501 summary: copy files
502 502
503 503 changeset: 2:51a0ae4d5864
504 504 user: test
505 505 date: Thu Jan 01 00:00:00 1970 +0000
506 506 summary: remove files
507 507
508 508 changeset: 1:ce8896473775
509 509 user: test
510 510 date: Thu Jan 01 00:00:00 1970 +0000
511 511 summary: edit files
512 512
513 513 changeset: 0:30d30fe6a5be
514 514 user: test
515 515 date: Thu Jan 01 00:00:00 1970 +0000
516 516 summary: add files
517 517
518 518 $ cat normal3
519 519 normal3-modified
520 520 $ cat sub/normal4
521 521 normal4-modified
522 522 $ cat sub/large4
523 523 large4-modified
524 524 $ cat sub2/large6
525 525 large6-modified
526 526 $ cat sub2/large7
527 527 large7
528 528
529 529 Test rollback on largefiles
530 530
531 531 $ echo large4-modified-again > sub/large4
532 532 $ hg commit -m "Modify large4 again"
533 533 $ hg rollback
534 534 repository tip rolled back to revision 9 (undo commit)
535 535 working directory now based on revision 9
536 536 $ hg st
537 537 M sub/large4
538 538 $ hg log
539 539 changeset: 9:598410d3eb9a
540 540 tag: tip
541 541 user: test
542 542 date: Thu Jan 01 00:00:00 1970 +0000
543 543 summary: modify normal file largefile in repo d
544 544
545 545 changeset: 8:a381d2c8c80e
546 546 user: test
547 547 date: Thu Jan 01 00:00:00 1970 +0000
548 548 summary: modify normal file and largefile in repo b
549 549
550 550 changeset: 7:daea875e9014
551 551 user: test
552 552 date: Thu Jan 01 00:00:00 1970 +0000
553 553 summary: add/edit more largefiles
554 554
555 555 changeset: 6:4355d653f84f
556 556 user: test
557 557 date: Thu Jan 01 00:00:00 1970 +0000
558 558 summary: edit files yet again
559 559
560 560 changeset: 5:9d5af5072dbd
561 561 user: test
562 562 date: Thu Jan 01 00:00:00 1970 +0000
563 563 summary: edit files again
564 564
565 565 changeset: 4:74c02385b94c
566 566 user: test
567 567 date: Thu Jan 01 00:00:00 1970 +0000
568 568 summary: move files
569 569
570 570 changeset: 3:9e8fbc4bce62
571 571 user: test
572 572 date: Thu Jan 01 00:00:00 1970 +0000
573 573 summary: copy files
574 574
575 575 changeset: 2:51a0ae4d5864
576 576 user: test
577 577 date: Thu Jan 01 00:00:00 1970 +0000
578 578 summary: remove files
579 579
580 580 changeset: 1:ce8896473775
581 581 user: test
582 582 date: Thu Jan 01 00:00:00 1970 +0000
583 583 summary: edit files
584 584
585 585 changeset: 0:30d30fe6a5be
586 586 user: test
587 587 date: Thu Jan 01 00:00:00 1970 +0000
588 588 summary: add files
589 589
590 590 $ cat sub/large4
591 591 large4-modified-again
592 592
593 593 Test that `update --clean` leaves correct largefiles in working copy.
594 594
595 595 $ hg update --clean
596 596 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
597 597 getting changed largefiles
598 598 1 largefiles updated, 0 removed
599 599 $ cat normal3
600 600 normal3-modified
601 601 $ cat sub/normal4
602 602 normal4-modified
603 603 $ cat sub/large4
604 604 large4-modified
605 605 $ cat sub2/large6
606 606 large6-modified
607 607 $ cat sub2/large7
608 608 large7
609 609
610 610 Test that verify --large actaully verifies largefiles
611 611
612 612 $ hg verify --large
613 613 checking changesets
614 614 checking manifests
615 615 crosschecking files in changesets and manifests
616 616 checking files
617 617 10 files, 10 changesets, 28 total revisions
618 618 searching 1 changesets for largefiles
619 619 verified existence of 3 revisions of 3 largefiles
620 620
621 621 Test that merging does not revert to old versions of largefiles (this has
622 622 also been very problematic).
623 623
624 624 $ cd ..
625 625 $ hg clone -r 7 e f
626 626 adding changesets
627 627 adding manifests
628 628 adding file changes
629 629 added 8 changesets with 24 changes to 10 files
630 630 updating to branch default
631 631 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
632 632 getting changed largefiles
633 633 3 largefiles updated, 0 removed
634 634 $ cd f
635 635 $ echo "large4-merge-test" > sub/large4
636 636 $ hg commit -m "Modify large4 to test merge"
637 637 $ hg pull ../e
638 638 pulling from ../e
639 639 searching for changes
640 640 adding changesets
641 641 adding manifests
642 642 adding file changes
643 643 added 2 changesets with 4 changes to 4 files (+1 heads)
644 644 (run 'hg heads' to see heads, 'hg merge' to merge)
645 645 $ hg merge
646 646 merging sub/large4
647 647 largefile sub/large4 has a merge conflict
648 648 keep (l)ocal or take (o)ther? l
649 649 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
650 650 (branch merge, don't forget to commit)
651 651 getting changed largefiles
652 652 1 largefiles updated, 0 removed
653 653 $ hg commit -m "Merge repos e and f"
654 654 $ cat normal3
655 655 normal3-modified
656 656 $ cat sub/normal4
657 657 normal4-modified
658 658 $ cat sub/large4
659 659 large4-merge-test
660 660 $ cat sub2/large6
661 661 large6-modified
662 662 $ cat sub2/large7
663 663 large7
664 $ cd ..
665
666 Verify that lfconvert adds 'largefiles' to .hg/requires
667 $ hg init bigfile-repo
668 $ cd bigfile-repo
669 $ dd if=/dev/zero bs=1k count=23k > a-large-file 2> /dev/null
670 $ hg addremove
671 adding a-large-file
672 a-large-file: up to 72 MB of RAM may be required to manage this file
673 (use 'hg revert a-large-file' to cancel the pending addition)
674 $ hg commit -m "Commit file without making it be a largefile"
675 $ find .hg/largefiles
676 .hg/largefiles
677 $ cd ..
678 $ hg lfconvert --size 10 bigfile-repo largefiles-repo
679 initializing destination largefiles-repo
680 $ cat largefiles-repo/.hg/requires
681 largefiles
682 revlogv1
683 fncache
684 store
685 dotencode
686 $ rm -rf bigfile-repo largefiles-repo
687
General Comments 0
You need to be logged in to leave comments. Login now