##// END OF EJS Templates
largefiles: specify where .orig files are kept...
Christian Delahousse -
r26944:ef5bab63 default
parent child Browse files
Show More
@@ -1,550 +1,552 b''
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, errno
12 12 import shutil
13 13
14 14 from mercurial import util, match as match_, hg, node, context, error, \
15 15 cmdutil, scmutil, commands
16 16 from mercurial.i18n import _
17 17 from mercurial.lock import release
18 18
19 19 from hgext.convert import convcmd
20 20 from hgext.convert import filemap
21 21
22 22 import lfutil
23 23 import basestore
24 24
25 25 # -- Commands ----------------------------------------------------------
26 26
27 27 cmdtable = {}
28 28 command = cmdutil.command(cmdtable)
29 29
30 30 @command('lfconvert',
31 31 [('s', 'size', '',
32 32 _('minimum size (MB) for files to be converted as largefiles'), 'SIZE'),
33 33 ('', 'to-normal', False,
34 34 _('convert from a largefiles repo to a normal repo')),
35 35 ],
36 36 _('hg lfconvert SOURCE DEST [FILE ...]'),
37 37 norepo=True,
38 38 inferrepo=True)
39 39 def lfconvert(ui, src, dest, *pats, **opts):
40 40 '''convert a normal repository to a largefiles repository
41 41
42 42 Convert repository SOURCE to a new repository DEST, identical to
43 43 SOURCE except that certain files will be converted as largefiles:
44 44 specifically, any file that matches any PATTERN *or* whose size is
45 45 above the minimum size threshold is converted as a largefile. The
46 46 size used to determine whether or not to track a file as a
47 47 largefile is the size of the first version of the file. The
48 48 minimum size can be specified either with --size or in
49 49 configuration as ``largefiles.size``.
50 50
51 51 After running this command you will need to make sure that
52 52 largefiles is enabled anywhere you intend to push the new
53 53 repository.
54 54
55 55 Use --to-normal to convert largefiles back to normal files; after
56 56 this, the DEST repository can be used without largefiles at all.'''
57 57
58 58 if opts['to_normal']:
59 59 tolfile = False
60 60 else:
61 61 tolfile = True
62 62 size = lfutil.getminsize(ui, True, opts.get('size'), default=None)
63 63
64 64 if not hg.islocal(src):
65 65 raise error.Abort(_('%s is not a local Mercurial repo') % src)
66 66 if not hg.islocal(dest):
67 67 raise error.Abort(_('%s is not a local Mercurial repo') % dest)
68 68
69 69 rsrc = hg.repository(ui, src)
70 70 ui.status(_('initializing destination %s\n') % dest)
71 71 rdst = hg.repository(ui, dest, create=True)
72 72
73 73 success = False
74 74 dstwlock = dstlock = None
75 75 try:
76 76 # Get a list of all changesets in the source. The easy way to do this
77 77 # is to simply walk the changelog, using changelog.nodesbetween().
78 78 # Take a look at mercurial/revlog.py:639 for more details.
79 79 # Use a generator instead of a list to decrease memory usage
80 80 ctxs = (rsrc[ctx] for ctx in rsrc.changelog.nodesbetween(None,
81 81 rsrc.heads())[0])
82 82 revmap = {node.nullid: node.nullid}
83 83 if tolfile:
84 84 # Lock destination to prevent modification while it is converted to.
85 85 # Don't need to lock src because we are just reading from its
86 86 # history which can't change.
87 87 dstwlock = rdst.wlock()
88 88 dstlock = rdst.lock()
89 89
90 90 lfiles = set()
91 91 normalfiles = set()
92 92 if not pats:
93 93 pats = ui.configlist(lfutil.longname, 'patterns', default=[])
94 94 if pats:
95 95 matcher = match_.match(rsrc.root, '', list(pats))
96 96 else:
97 97 matcher = None
98 98
99 99 lfiletohash = {}
100 100 for ctx in ctxs:
101 101 ui.progress(_('converting revisions'), ctx.rev(),
102 102 unit=_('revision'), total=rsrc['tip'].rev())
103 103 _lfconvert_addchangeset(rsrc, rdst, ctx, revmap,
104 104 lfiles, normalfiles, matcher, size, lfiletohash)
105 105 ui.progress(_('converting revisions'), None)
106 106
107 107 if os.path.exists(rdst.wjoin(lfutil.shortname)):
108 108 shutil.rmtree(rdst.wjoin(lfutil.shortname))
109 109
110 110 for f in lfiletohash.keys():
111 111 if os.path.isfile(rdst.wjoin(f)):
112 112 os.unlink(rdst.wjoin(f))
113 113 try:
114 114 os.removedirs(os.path.dirname(rdst.wjoin(f)))
115 115 except OSError:
116 116 pass
117 117
118 118 # If there were any files converted to largefiles, add largefiles
119 119 # to the destination repository's requirements.
120 120 if lfiles:
121 121 rdst.requirements.add('largefiles')
122 122 rdst._writerequirements()
123 123 else:
124 124 class lfsource(filemap.filemap_source):
125 125 def __init__(self, ui, source):
126 126 super(lfsource, self).__init__(ui, source, None)
127 127 self.filemapper.rename[lfutil.shortname] = '.'
128 128
129 129 def getfile(self, name, rev):
130 130 realname, realrev = rev
131 131 f = super(lfsource, self).getfile(name, rev)
132 132
133 133 if (not realname.startswith(lfutil.shortnameslash)
134 134 or f[0] is None):
135 135 return f
136 136
137 137 # Substitute in the largefile data for the hash
138 138 hash = f[0].strip()
139 139 path = lfutil.findfile(rsrc, hash)
140 140
141 141 if path is None:
142 142 raise error.Abort(_("missing largefile for '%s' in %s")
143 143 % (realname, realrev))
144 144 fp = open(path, 'rb')
145 145
146 146 try:
147 147 return (fp.read(), f[1])
148 148 finally:
149 149 fp.close()
150 150
151 151 class converter(convcmd.converter):
152 152 def __init__(self, ui, source, dest, revmapfile, opts):
153 153 src = lfsource(ui, source)
154 154
155 155 super(converter, self).__init__(ui, src, dest, revmapfile,
156 156 opts)
157 157
158 158 found, missing = downloadlfiles(ui, rsrc)
159 159 if missing != 0:
160 160 raise error.Abort(_("all largefiles must be present locally"))
161 161
162 162 orig = convcmd.converter
163 163 convcmd.converter = converter
164 164
165 165 try:
166 166 convcmd.convert(ui, src, dest)
167 167 finally:
168 168 convcmd.converter = orig
169 169 success = True
170 170 finally:
171 171 if tolfile:
172 172 rdst.dirstate.clear()
173 173 release(dstlock, dstwlock)
174 174 if not success:
175 175 # we failed, remove the new directory
176 176 shutil.rmtree(rdst.root)
177 177
178 178 def _lfconvert_addchangeset(rsrc, rdst, ctx, revmap, lfiles, normalfiles,
179 179 matcher, size, lfiletohash):
180 180 # Convert src parents to dst parents
181 181 parents = _convertparents(ctx, revmap)
182 182
183 183 # Generate list of changed files
184 184 files = _getchangedfiles(ctx, parents)
185 185
186 186 dstfiles = []
187 187 for f in files:
188 188 if f not in lfiles and f not in normalfiles:
189 189 islfile = _islfile(f, ctx, matcher, size)
190 190 # If this file was renamed or copied then copy
191 191 # the largefile-ness of its predecessor
192 192 if f in ctx.manifest():
193 193 fctx = ctx.filectx(f)
194 194 renamed = fctx.renamed()
195 195 renamedlfile = renamed and renamed[0] in lfiles
196 196 islfile |= renamedlfile
197 197 if 'l' in fctx.flags():
198 198 if renamedlfile:
199 199 raise error.Abort(
200 200 _('renamed/copied largefile %s becomes symlink')
201 201 % f)
202 202 islfile = False
203 203 if islfile:
204 204 lfiles.add(f)
205 205 else:
206 206 normalfiles.add(f)
207 207
208 208 if f in lfiles:
209 209 dstfiles.append(lfutil.standin(f))
210 210 # largefile in manifest if it has not been removed/renamed
211 211 if f in ctx.manifest():
212 212 fctx = ctx.filectx(f)
213 213 if 'l' in fctx.flags():
214 214 renamed = fctx.renamed()
215 215 if renamed and renamed[0] in lfiles:
216 216 raise error.Abort(_('largefile %s becomes symlink') % f)
217 217
218 218 # largefile was modified, update standins
219 219 m = util.sha1('')
220 220 m.update(ctx[f].data())
221 221 hash = m.hexdigest()
222 222 if f not in lfiletohash or lfiletohash[f] != hash:
223 223 rdst.wwrite(f, ctx[f].data(), ctx[f].flags())
224 224 executable = 'x' in ctx[f].flags()
225 225 lfutil.writestandin(rdst, lfutil.standin(f), hash,
226 226 executable)
227 227 lfiletohash[f] = hash
228 228 else:
229 229 # normal file
230 230 dstfiles.append(f)
231 231
232 232 def getfilectx(repo, memctx, f):
233 233 if lfutil.isstandin(f):
234 234 # if the file isn't in the manifest then it was removed
235 235 # or renamed, raise IOError to indicate this
236 236 srcfname = lfutil.splitstandin(f)
237 237 try:
238 238 fctx = ctx.filectx(srcfname)
239 239 except error.LookupError:
240 240 return None
241 241 renamed = fctx.renamed()
242 242 if renamed:
243 243 # standin is always a largefile because largefile-ness
244 244 # doesn't change after rename or copy
245 245 renamed = lfutil.standin(renamed[0])
246 246
247 247 return context.memfilectx(repo, f, lfiletohash[srcfname] + '\n',
248 248 'l' in fctx.flags(), 'x' in fctx.flags(),
249 249 renamed)
250 250 else:
251 251 return _getnormalcontext(repo, ctx, f, revmap)
252 252
253 253 # Commit
254 254 _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
255 255
256 256 def _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap):
257 257 mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
258 258 getfilectx, ctx.user(), ctx.date(), ctx.extra())
259 259 ret = rdst.commitctx(mctx)
260 260 lfutil.copyalltostore(rdst, ret)
261 261 rdst.setparents(ret)
262 262 revmap[ctx.node()] = rdst.changelog.tip()
263 263
264 264 # Generate list of changed files
265 265 def _getchangedfiles(ctx, parents):
266 266 files = set(ctx.files())
267 267 if node.nullid not in parents:
268 268 mc = ctx.manifest()
269 269 mp1 = ctx.parents()[0].manifest()
270 270 mp2 = ctx.parents()[1].manifest()
271 271 files |= (set(mp1) | set(mp2)) - set(mc)
272 272 for f in mc:
273 273 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
274 274 files.add(f)
275 275 return files
276 276
277 277 # Convert src parents to dst parents
278 278 def _convertparents(ctx, revmap):
279 279 parents = []
280 280 for p in ctx.parents():
281 281 parents.append(revmap[p.node()])
282 282 while len(parents) < 2:
283 283 parents.append(node.nullid)
284 284 return parents
285 285
286 286 # Get memfilectx for a normal file
287 287 def _getnormalcontext(repo, ctx, f, revmap):
288 288 try:
289 289 fctx = ctx.filectx(f)
290 290 except error.LookupError:
291 291 return None
292 292 renamed = fctx.renamed()
293 293 if renamed:
294 294 renamed = renamed[0]
295 295
296 296 data = fctx.data()
297 297 if f == '.hgtags':
298 298 data = _converttags (repo.ui, revmap, data)
299 299 return context.memfilectx(repo, f, data, 'l' in fctx.flags(),
300 300 'x' in fctx.flags(), renamed)
301 301
302 302 # Remap tag data using a revision map
303 303 def _converttags(ui, revmap, data):
304 304 newdata = []
305 305 for line in data.splitlines():
306 306 try:
307 307 id, name = line.split(' ', 1)
308 308 except ValueError:
309 309 ui.warn(_('skipping incorrectly formatted tag %s\n')
310 310 % line)
311 311 continue
312 312 try:
313 313 newid = node.bin(id)
314 314 except TypeError:
315 315 ui.warn(_('skipping incorrectly formatted id %s\n')
316 316 % id)
317 317 continue
318 318 try:
319 319 newdata.append('%s %s\n' % (node.hex(revmap[newid]),
320 320 name))
321 321 except KeyError:
322 322 ui.warn(_('no mapping for id %s\n') % id)
323 323 continue
324 324 return ''.join(newdata)
325 325
326 326 def _islfile(file, ctx, matcher, size):
327 327 '''Return true if file should be considered a largefile, i.e.
328 328 matcher matches it or it is larger than size.'''
329 329 # never store special .hg* files as largefiles
330 330 if file == '.hgtags' or file == '.hgignore' or file == '.hgsigs':
331 331 return False
332 332 if matcher and matcher(file):
333 333 return True
334 334 try:
335 335 return ctx.filectx(file).size() >= size * 1024 * 1024
336 336 except error.LookupError:
337 337 return False
338 338
339 339 def uploadlfiles(ui, rsrc, rdst, files):
340 340 '''upload largefiles to the central store'''
341 341
342 342 if not files:
343 343 return
344 344
345 345 store = basestore._openstore(rsrc, rdst, put=True)
346 346
347 347 at = 0
348 348 ui.debug("sending statlfile command for %d largefiles\n" % len(files))
349 349 retval = store.exists(files)
350 350 files = filter(lambda h: not retval[h], files)
351 351 ui.debug("%d largefiles need to be uploaded\n" % len(files))
352 352
353 353 for hash in files:
354 354 ui.progress(_('uploading largefiles'), at, unit='largefile',
355 355 total=len(files))
356 356 source = lfutil.findfile(rsrc, hash)
357 357 if not source:
358 358 raise error.Abort(_('largefile %s missing from store'
359 359 ' (needs to be uploaded)') % hash)
360 360 # XXX check for errors here
361 361 store.put(source, hash)
362 362 at += 1
363 363 ui.progress(_('uploading largefiles'), None)
364 364
365 365 def verifylfiles(ui, repo, all=False, contents=False):
366 366 '''Verify that every largefile revision in the current changeset
367 367 exists in the central store. With --contents, also verify that
368 368 the contents of each local largefile file revision are correct (SHA-1 hash
369 369 matches the revision ID). With --all, check every changeset in
370 370 this repository.'''
371 371 if all:
372 372 revs = repo.revs('all()')
373 373 else:
374 374 revs = ['.']
375 375
376 376 store = basestore._openstore(repo)
377 377 return store.verify(revs, contents=contents)
378 378
379 379 def cachelfiles(ui, repo, node, filelist=None):
380 380 '''cachelfiles ensures that all largefiles needed by the specified revision
381 381 are present in the repository's largefile cache.
382 382
383 383 returns a tuple (cached, missing). cached is the list of files downloaded
384 384 by this operation; missing is the list of files that were needed but could
385 385 not be found.'''
386 386 lfiles = lfutil.listlfiles(repo, node)
387 387 if filelist:
388 388 lfiles = set(lfiles) & set(filelist)
389 389 toget = []
390 390
391 391 for lfile in lfiles:
392 392 try:
393 393 expectedhash = repo[node][lfutil.standin(lfile)].data().strip()
394 394 except IOError as err:
395 395 if err.errno == errno.ENOENT:
396 396 continue # node must be None and standin wasn't found in wctx
397 397 raise
398 398 if not lfutil.findfile(repo, expectedhash):
399 399 toget.append((lfile, expectedhash))
400 400
401 401 if toget:
402 402 store = basestore._openstore(repo)
403 403 ret = store.get(toget)
404 404 return ret
405 405
406 406 return ([], [])
407 407
408 408 def downloadlfiles(ui, repo, rev=None):
409 409 matchfn = scmutil.match(repo[None],
410 410 [repo.wjoin(lfutil.shortname)], {})
411 411 def prepare(ctx, fns):
412 412 pass
413 413 totalsuccess = 0
414 414 totalmissing = 0
415 415 if rev != []: # walkchangerevs on empty list would return all revs
416 416 for ctx in cmdutil.walkchangerevs(repo, matchfn, {'rev' : rev},
417 417 prepare):
418 418 success, missing = cachelfiles(ui, repo, ctx.node())
419 419 totalsuccess += len(success)
420 420 totalmissing += len(missing)
421 421 ui.status(_("%d additional largefiles cached\n") % totalsuccess)
422 422 if totalmissing > 0:
423 423 ui.status(_("%d largefiles failed to download\n") % totalmissing)
424 424 return totalsuccess, totalmissing
425 425
426 426 def updatelfiles(ui, repo, filelist=None, printmessage=None,
427 427 normallookup=False):
428 428 '''Update largefiles according to standins in the working directory
429 429
430 430 If ``printmessage`` is other than ``None``, it means "print (or
431 431 ignore, for false) message forcibly".
432 432 '''
433 433 statuswriter = lfutil.getstatuswriter(ui, repo, printmessage)
434 434 wlock = repo.wlock()
435 435 try:
436 436 lfdirstate = lfutil.openlfdirstate(ui, repo)
437 437 lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate)
438 438
439 439 if filelist is not None:
440 440 filelist = set(filelist)
441 441 lfiles = [f for f in lfiles if f in filelist]
442 442
443 443 update = {}
444 444 updated, removed = 0, 0
445 445 for lfile in lfiles:
446 446 abslfile = repo.wjoin(lfile)
447 abslfileorig = cmdutil.origpath(ui, repo, abslfile)
447 448 absstandin = repo.wjoin(lfutil.standin(lfile))
449 absstandinorig = cmdutil.origpath(ui, repo, absstandin)
448 450 if os.path.exists(absstandin):
449 if (os.path.exists(absstandin + '.orig') and
451 if (os.path.exists(absstandinorig) and
450 452 os.path.exists(abslfile)):
451 shutil.copyfile(abslfile, abslfile + '.orig')
452 util.unlinkpath(absstandin + '.orig')
453 shutil.copyfile(abslfile, abslfileorig)
454 util.unlinkpath(absstandinorig)
453 455 expecthash = lfutil.readstandin(repo, lfile)
454 456 if expecthash != '':
455 457 if lfile not in repo[None]: # not switched to normal file
456 458 util.unlinkpath(abslfile, ignoremissing=True)
457 459 # use normallookup() to allocate an entry in largefiles
458 460 # dirstate to prevent lfilesrepo.status() from reporting
459 461 # missing files as removed.
460 462 lfdirstate.normallookup(lfile)
461 463 update[lfile] = expecthash
462 464 else:
463 465 # Remove lfiles for which the standin is deleted, unless the
464 466 # lfile is added to the repository again. This happens when a
465 467 # largefile is converted back to a normal file: the standin
466 468 # disappears, but a new (normal) file appears as the lfile.
467 469 if (os.path.exists(abslfile) and
468 470 repo.dirstate.normalize(lfile) not in repo[None]):
469 471 util.unlinkpath(abslfile)
470 472 removed += 1
471 473
472 474 # largefile processing might be slow and be interrupted - be prepared
473 475 lfdirstate.write()
474 476
475 477 if lfiles:
476 478 statuswriter(_('getting changed largefiles\n'))
477 479 cachelfiles(ui, repo, None, lfiles)
478 480
479 481 for lfile in lfiles:
480 482 update1 = 0
481 483
482 484 expecthash = update.get(lfile)
483 485 if expecthash:
484 486 if not lfutil.copyfromcache(repo, expecthash, lfile):
485 487 # failed ... but already removed and set to normallookup
486 488 continue
487 489 # Synchronize largefile dirstate to the last modified
488 490 # time of the file
489 491 lfdirstate.normal(lfile)
490 492 update1 = 1
491 493
492 494 # copy the state of largefile standin from the repository's
493 495 # dirstate to its state in the lfdirstate.
494 496 abslfile = repo.wjoin(lfile)
495 497 absstandin = repo.wjoin(lfutil.standin(lfile))
496 498 if os.path.exists(absstandin):
497 499 mode = os.stat(absstandin).st_mode
498 500 if mode != os.stat(abslfile).st_mode:
499 501 os.chmod(abslfile, mode)
500 502 update1 = 1
501 503
502 504 updated += update1
503 505
504 506 lfutil.synclfdirstate(repo, lfdirstate, lfile, normallookup)
505 507
506 508 lfdirstate.write()
507 509 if lfiles:
508 510 statuswriter(_('%d largefiles updated, %d removed\n') % (updated,
509 511 removed))
510 512 finally:
511 513 wlock.release()
512 514
513 515 @command('lfpull',
514 516 [('r', 'rev', [], _('pull largefiles for these revisions'))
515 517 ] + commands.remoteopts,
516 518 _('-r REV... [-e CMD] [--remotecmd CMD] [SOURCE]'))
517 519 def lfpull(ui, repo, source="default", **opts):
518 520 """pull largefiles for the specified revisions from the specified source
519 521
520 522 Pull largefiles that are referenced from local changesets but missing
521 523 locally, pulling from a remote repository to the local cache.
522 524
523 525 If SOURCE is omitted, the 'default' path will be used.
524 526 See :hg:`help urls` for more information.
525 527
526 528 .. container:: verbose
527 529
528 530 Some examples:
529 531
530 532 - pull largefiles for all branch heads::
531 533
532 534 hg lfpull -r "head() and not closed()"
533 535
534 536 - pull largefiles on the default branch::
535 537
536 538 hg lfpull -r "branch(default)"
537 539 """
538 540 repo.lfpullsource = source
539 541
540 542 revs = opts.get('rev', [])
541 543 if not revs:
542 544 raise error.Abort(_('no revisions specified'))
543 545 revs = scmutil.revrange(repo, revs)
544 546
545 547 numcached = 0
546 548 for rev in revs:
547 549 ui.note(_('pulling largefiles for revision %s\n') % rev)
548 550 (cached, missing) = cachelfiles(ui, repo, rev)
549 551 numcached += len(cached)
550 552 ui.status(_("%d largefiles cached\n") % numcached)
@@ -1,1089 +1,1101 b''
1 1 This file contains testcases that tend to be related to special cases or less
2 2 common commands affecting largefile.
3 3
4 4 Each sections should be independent of each others.
5 5
6 6 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
7 7 $ mkdir "${USERCACHE}"
8 8 $ cat >> $HGRCPATH <<EOF
9 9 > [extensions]
10 10 > largefiles=
11 11 > purge=
12 12 > rebase=
13 13 > transplant=
14 14 > [phases]
15 15 > publish=False
16 16 > [largefiles]
17 17 > minsize=2
18 18 > patterns=glob:**.dat
19 19 > usercache=${USERCACHE}
20 20 > [hooks]
21 21 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
22 22 > EOF
23 23
24 24
25 25
26 26 Test copies and moves from a directory other than root (issue3516)
27 27 =========================================================================
28 28
29 29 $ hg init lf_cpmv
30 30 $ cd lf_cpmv
31 31 $ mkdir dira
32 32 $ mkdir dira/dirb
33 33 $ touch dira/dirb/largefile
34 34 $ hg add --large dira/dirb/largefile
35 35 $ hg commit -m "added"
36 36 Invoking status precommit hook
37 37 A dira/dirb/largefile
38 38 $ cd dira
39 39 $ hg cp dirb/largefile foo/largefile
40 40
41 41 TODO: Ideally, this should mention the largefile, not the standin
42 42 $ hg log -T '{rev}\n' --stat 'set:clean()'
43 43 0
44 44 .hglf/dira/dirb/largefile | 1 +
45 45 1 files changed, 1 insertions(+), 0 deletions(-)
46 46
47 47 $ hg ci -m "deep copy"
48 48 Invoking status precommit hook
49 49 A dira/foo/largefile
50 50 $ find . | sort
51 51 .
52 52 ./dirb
53 53 ./dirb/largefile
54 54 ./foo
55 55 ./foo/largefile
56 56 $ hg mv foo/largefile baz/largefile
57 57 $ hg ci -m "moved"
58 58 Invoking status precommit hook
59 59 A dira/baz/largefile
60 60 R dira/foo/largefile
61 61 $ find . | sort
62 62 .
63 63 ./baz
64 64 ./baz/largefile
65 65 ./dirb
66 66 ./dirb/largefile
67 67 $ cd ..
68 68 $ hg mv dira dirc
69 69 moving .hglf/dira/baz/largefile to .hglf/dirc/baz/largefile (glob)
70 70 moving .hglf/dira/dirb/largefile to .hglf/dirc/dirb/largefile (glob)
71 71 $ find * | sort
72 72 dirc
73 73 dirc/baz
74 74 dirc/baz/largefile
75 75 dirc/dirb
76 76 dirc/dirb/largefile
77 77
78 78 $ hg clone -q . ../fetch
79 79 $ hg --config extensions.fetch= fetch ../fetch
80 80 abort: uncommitted changes
81 81 [255]
82 82 $ hg up -qC
83 83 $ cd ..
84 84
85 85 Clone a local repository owned by another user
86 86 ===================================================
87 87
88 88 #if unix-permissions
89 89
90 90 We have to simulate that here by setting $HOME and removing write permissions
91 91 $ ORIGHOME="$HOME"
92 92 $ mkdir alice
93 93 $ HOME="`pwd`/alice"
94 94 $ cd alice
95 95 $ hg init pubrepo
96 96 $ cd pubrepo
97 97 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
98 98 $ hg add --large a-large-file
99 99 $ hg commit -m "Add a large file"
100 100 Invoking status precommit hook
101 101 A a-large-file
102 102 $ cd ..
103 103 $ chmod -R a-w pubrepo
104 104 $ cd ..
105 105 $ mkdir bob
106 106 $ HOME="`pwd`/bob"
107 107 $ cd bob
108 108 $ hg clone --pull ../alice/pubrepo pubrepo
109 109 requesting all changes
110 110 adding changesets
111 111 adding manifests
112 112 adding file changes
113 113 added 1 changesets with 1 changes to 1 files
114 114 updating to branch default
115 115 getting changed largefiles
116 116 1 largefiles updated, 0 removed
117 117 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
118 118 $ cd ..
119 119 $ chmod -R u+w alice/pubrepo
120 120 $ HOME="$ORIGHOME"
121 121
122 122 #endif
123 123
124 124
125 125 Symlink to a large largefile should behave the same as a symlink to a normal file
126 126 =====================================================================================
127 127
128 128 #if symlink
129 129
130 130 $ hg init largesymlink
131 131 $ cd largesymlink
132 132 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
133 133 $ hg add --large largefile
134 134 $ hg commit -m "commit a large file"
135 135 Invoking status precommit hook
136 136 A largefile
137 137 $ ln -s largefile largelink
138 138 $ hg add largelink
139 139 $ hg commit -m "commit a large symlink"
140 140 Invoking status precommit hook
141 141 A largelink
142 142 $ rm -f largelink
143 143 $ hg up >/dev/null
144 144 $ test -f largelink
145 145 [1]
146 146 $ test -L largelink
147 147 [1]
148 148 $ rm -f largelink # make next part of the test independent of the previous
149 149 $ hg up -C >/dev/null
150 150 $ test -f largelink
151 151 $ test -L largelink
152 152 $ cd ..
153 153
154 154 #endif
155 155
156 156
157 157 test for pattern matching on 'hg status':
158 158 ==============================================
159 159
160 160
161 161 to boost performance, largefiles checks whether specified patterns are
162 162 related to largefiles in working directory (NOT to STANDIN) or not.
163 163
164 164 $ hg init statusmatch
165 165 $ cd statusmatch
166 166
167 167 $ mkdir -p a/b/c/d
168 168 $ echo normal > a/b/c/d/e.normal.txt
169 169 $ hg add a/b/c/d/e.normal.txt
170 170 $ echo large > a/b/c/d/e.large.txt
171 171 $ hg add --large a/b/c/d/e.large.txt
172 172 $ mkdir -p a/b/c/x
173 173 $ echo normal > a/b/c/x/y.normal.txt
174 174 $ hg add a/b/c/x/y.normal.txt
175 175 $ hg commit -m 'add files'
176 176 Invoking status precommit hook
177 177 A a/b/c/d/e.large.txt
178 178 A a/b/c/d/e.normal.txt
179 179 A a/b/c/x/y.normal.txt
180 180
181 181 (1) no pattern: no performance boost
182 182 $ hg status -A
183 183 C a/b/c/d/e.large.txt
184 184 C a/b/c/d/e.normal.txt
185 185 C a/b/c/x/y.normal.txt
186 186
187 187 (2) pattern not related to largefiles: performance boost
188 188 $ hg status -A a/b/c/x
189 189 C a/b/c/x/y.normal.txt
190 190
191 191 (3) pattern related to largefiles: no performance boost
192 192 $ hg status -A a/b/c/d
193 193 C a/b/c/d/e.large.txt
194 194 C a/b/c/d/e.normal.txt
195 195
196 196 (4) pattern related to STANDIN (not to largefiles): performance boost
197 197 $ hg status -A .hglf/a
198 198 C .hglf/a/b/c/d/e.large.txt
199 199
200 200 (5) mixed case: no performance boost
201 201 $ hg status -A a/b/c/x a/b/c/d
202 202 C a/b/c/d/e.large.txt
203 203 C a/b/c/d/e.normal.txt
204 204 C a/b/c/x/y.normal.txt
205 205
206 206 verify that largefiles doesn't break filesets
207 207
208 208 $ hg log --rev . --exclude "set:binary()"
209 209 changeset: 0:41bd42f10efa
210 210 tag: tip
211 211 user: test
212 212 date: Thu Jan 01 00:00:00 1970 +0000
213 213 summary: add files
214 214
215 215 verify that large files in subrepos handled properly
216 216 $ hg init subrepo
217 217 $ echo "subrepo = subrepo" > .hgsub
218 218 $ hg add .hgsub
219 219 $ hg ci -m "add subrepo"
220 220 Invoking status precommit hook
221 221 A .hgsub
222 222 ? .hgsubstate
223 223 $ echo "rev 1" > subrepo/large.txt
224 224 $ hg add --large subrepo/large.txt
225 225 $ hg sum
226 226 parent: 1:8ee150ea2e9c tip
227 227 add subrepo
228 228 branch: default
229 229 commit: 1 subrepos
230 230 update: (current)
231 231 phases: 2 draft
232 232 $ hg st
233 233 $ hg st -S
234 234 A subrepo/large.txt
235 235 $ hg ci -S -m "commit top repo"
236 236 committing subrepository subrepo
237 237 Invoking status precommit hook
238 238 A large.txt
239 239 Invoking status precommit hook
240 240 M .hgsubstate
241 241 # No differences
242 242 $ hg st -S
243 243 $ hg sum
244 244 parent: 2:ce4cd0c527a6 tip
245 245 commit top repo
246 246 branch: default
247 247 commit: (clean)
248 248 update: (current)
249 249 phases: 3 draft
250 250 $ echo "rev 2" > subrepo/large.txt
251 251 $ hg st -S
252 252 M subrepo/large.txt
253 253 $ hg sum
254 254 parent: 2:ce4cd0c527a6 tip
255 255 commit top repo
256 256 branch: default
257 257 commit: 1 subrepos
258 258 update: (current)
259 259 phases: 3 draft
260 260 $ hg ci -m "this commit should fail without -S"
261 261 abort: uncommitted changes in subrepository 'subrepo'
262 262 (use --subrepos for recursive commit)
263 263 [255]
264 264
265 265 Add a normal file to the subrepo, then test archiving
266 266
267 267 $ echo 'normal file' > subrepo/normal.txt
268 268 $ touch large.dat
269 269 $ mv subrepo/large.txt subrepo/renamed-large.txt
270 270 $ hg addremove -S --dry-run
271 271 adding large.dat as a largefile
272 272 removing subrepo/large.txt
273 273 adding subrepo/normal.txt
274 274 adding subrepo/renamed-large.txt
275 275 $ hg status -S
276 276 ! subrepo/large.txt
277 277 ? large.dat
278 278 ? subrepo/normal.txt
279 279 ? subrepo/renamed-large.txt
280 280
281 281 $ hg addremove --dry-run subrepo
282 282 removing subrepo/large.txt (glob)
283 283 adding subrepo/normal.txt (glob)
284 284 adding subrepo/renamed-large.txt (glob)
285 285 $ hg status -S
286 286 ! subrepo/large.txt
287 287 ? large.dat
288 288 ? subrepo/normal.txt
289 289 ? subrepo/renamed-large.txt
290 290 $ cd ..
291 291
292 292 $ hg -R statusmatch addremove --dry-run statusmatch/subrepo
293 293 removing statusmatch/subrepo/large.txt (glob)
294 294 adding statusmatch/subrepo/normal.txt (glob)
295 295 adding statusmatch/subrepo/renamed-large.txt (glob)
296 296 $ hg -R statusmatch status -S
297 297 ! subrepo/large.txt
298 298 ? large.dat
299 299 ? subrepo/normal.txt
300 300 ? subrepo/renamed-large.txt
301 301
302 302 $ hg -R statusmatch addremove --dry-run -S
303 303 adding large.dat as a largefile
304 304 removing subrepo/large.txt
305 305 adding subrepo/normal.txt
306 306 adding subrepo/renamed-large.txt
307 307 $ cd statusmatch
308 308
309 309 $ mv subrepo/renamed-large.txt subrepo/large.txt
310 310 $ hg addremove subrepo
311 311 adding subrepo/normal.txt (glob)
312 312 $ hg forget subrepo/normal.txt
313 313
314 314 $ hg addremove -S
315 315 adding large.dat as a largefile
316 316 adding subrepo/normal.txt
317 317 $ rm large.dat
318 318
319 319 $ hg addremove subrepo
320 320 $ hg addremove -S
321 321 removing large.dat
322 322
323 323 Lock in subrepo, otherwise the change isn't archived
324 324
325 325 $ hg ci -S -m "add normal file to top level"
326 326 committing subrepository subrepo
327 327 Invoking status precommit hook
328 328 M large.txt
329 329 A normal.txt
330 330 Invoking status precommit hook
331 331 M .hgsubstate
332 332 $ hg archive -S ../lf_subrepo_archive
333 333 $ find ../lf_subrepo_archive | sort
334 334 ../lf_subrepo_archive
335 335 ../lf_subrepo_archive/.hg_archival.txt
336 336 ../lf_subrepo_archive/.hgsub
337 337 ../lf_subrepo_archive/.hgsubstate
338 338 ../lf_subrepo_archive/a
339 339 ../lf_subrepo_archive/a/b
340 340 ../lf_subrepo_archive/a/b/c
341 341 ../lf_subrepo_archive/a/b/c/d
342 342 ../lf_subrepo_archive/a/b/c/d/e.large.txt
343 343 ../lf_subrepo_archive/a/b/c/d/e.normal.txt
344 344 ../lf_subrepo_archive/a/b/c/x
345 345 ../lf_subrepo_archive/a/b/c/x/y.normal.txt
346 346 ../lf_subrepo_archive/subrepo
347 347 ../lf_subrepo_archive/subrepo/large.txt
348 348 ../lf_subrepo_archive/subrepo/normal.txt
349 349 $ cat ../lf_subrepo_archive/.hg_archival.txt
350 350 repo: 41bd42f10efa43698cc02052ea0977771cba506d
351 351 node: d56a95e6522858bc08a724c4fe2bdee066d1c30b
352 352 branch: default
353 353 latesttag: null
354 354 latesttagdistance: 4
355 355 changessincelatesttag: 4
356 356
357 357 Test update with subrepos.
358 358
359 359 $ hg update 0
360 360 getting changed largefiles
361 361 0 largefiles updated, 1 removed
362 362 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
363 363 $ hg status -S
364 364 $ hg update tip
365 365 getting changed largefiles
366 366 1 largefiles updated, 0 removed
367 367 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
368 368 $ hg status -S
369 369 # modify a large file
370 370 $ echo "modified" > subrepo/large.txt
371 371 $ hg st -S
372 372 M subrepo/large.txt
373 373 # update -C should revert the change.
374 374 $ hg update -C
375 375 getting changed largefiles
376 376 1 largefiles updated, 0 removed
377 377 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
378 378 $ hg status -S
379 379
380 380 $ hg forget -v subrepo/large.txt
381 381 removing subrepo/large.txt (glob)
382 382
383 383 Test reverting a forgotten file
384 384 $ hg revert -R subrepo subrepo/large.txt
385 385 $ hg status -SA subrepo/large.txt
386 386 C subrepo/large.txt
387 387
388 388 $ hg rm -v subrepo/large.txt
389 389 removing subrepo/large.txt (glob)
390 390 $ hg revert -R subrepo subrepo/large.txt
391 391 $ rm subrepo/large.txt
392 392 $ hg addremove -S
393 393 removing subrepo/large.txt
394 394 $ hg st -S
395 395 R subrepo/large.txt
396 396
397 397 Test archiving a revision that references a subrepo that is not yet
398 398 cloned (see test-subrepo-recursion.t):
399 399
400 400 $ hg clone -U . ../empty
401 401 $ cd ../empty
402 402 $ hg archive --subrepos -r tip ../archive.tar.gz
403 403 cloning subrepo subrepo from $TESTTMP/statusmatch/subrepo
404 404 $ cd ..
405 405
406 406
407 407
408 408
409 409
410 410
411 411 Test addremove, forget and others
412 412 ==============================================
413 413
414 414 Test that addremove picks up largefiles prior to the initial commit (issue3541)
415 415
416 416 $ hg init addrm2
417 417 $ cd addrm2
418 418 $ touch large.dat
419 419 $ touch large2.dat
420 420 $ touch normal
421 421 $ hg add --large large.dat
422 422 $ hg addremove -v
423 423 adding large2.dat as a largefile
424 424 adding normal
425 425
426 426 Test that forgetting all largefiles reverts to islfilesrepo() == False
427 427 (addremove will add *.dat as normal files now)
428 428 $ hg forget large.dat
429 429 $ hg forget large2.dat
430 430 $ hg addremove -v
431 431 adding large.dat
432 432 adding large2.dat
433 433
434 434 Test commit's addremove option prior to the first commit
435 435 $ hg forget large.dat
436 436 $ hg forget large2.dat
437 437 $ hg add --large large.dat
438 438 $ hg ci -Am "commit"
439 439 adding large2.dat as a largefile
440 440 Invoking status precommit hook
441 441 A large.dat
442 442 A large2.dat
443 443 A normal
444 444 $ find .hglf | sort
445 445 .hglf
446 446 .hglf/large.dat
447 447 .hglf/large2.dat
448 448
449 449 Test actions on largefiles using relative paths from subdir
450 450
451 451 $ mkdir sub
452 452 $ cd sub
453 453 $ echo anotherlarge > anotherlarge
454 454 $ hg add --large anotherlarge
455 455 $ hg st
456 456 A sub/anotherlarge
457 457 $ hg st anotherlarge
458 458 A anotherlarge
459 459 $ hg commit -m anotherlarge anotherlarge
460 460 Invoking status precommit hook
461 461 A sub/anotherlarge
462 462 $ hg log anotherlarge
463 463 changeset: 1:9627a577c5e9
464 464 tag: tip
465 465 user: test
466 466 date: Thu Jan 01 00:00:00 1970 +0000
467 467 summary: anotherlarge
468 468
469 469 $ hg --debug log -T '{rev}: {desc}\n' ../sub/anotherlarge
470 470 updated patterns: ['../.hglf/sub/../sub/anotherlarge', '../sub/anotherlarge']
471 471 1: anotherlarge
472 472
473 473 $ hg log -G anotherlarge
474 474 @ changeset: 1:9627a577c5e9
475 475 | tag: tip
476 476 | user: test
477 477 | date: Thu Jan 01 00:00:00 1970 +0000
478 478 | summary: anotherlarge
479 479 |
480 480
481 481 $ hg log glob:another*
482 482 changeset: 1:9627a577c5e9
483 483 tag: tip
484 484 user: test
485 485 date: Thu Jan 01 00:00:00 1970 +0000
486 486 summary: anotherlarge
487 487
488 488 $ hg --debug log -T '{rev}: {desc}\n' -G glob:another*
489 489 updated patterns: ['glob:../.hglf/sub/another*', 'glob:another*']
490 490 @ 1: anotherlarge
491 491 |
492 492
493 493 #if no-msys
494 494 $ hg --debug log -T '{rev}: {desc}\n' 'glob:../.hglf/sub/another*' # no-msys
495 495 updated patterns: ['glob:../.hglf/sub/another*']
496 496 1: anotherlarge
497 497
498 498 $ hg --debug log -G -T '{rev}: {desc}\n' 'glob:../.hglf/sub/another*' # no-msys
499 499 updated patterns: ['glob:../.hglf/sub/another*']
500 500 @ 1: anotherlarge
501 501 |
502 502 #endif
503 503
504 504 $ echo more >> anotherlarge
505 505 $ hg st .
506 506 M anotherlarge
507 507 $ hg cat anotherlarge
508 508 anotherlarge
509 509 $ hg revert anotherlarge
510 510 $ hg st
511 511 ? sub/anotherlarge.orig
512
513 Test orig files go where we want them
514 $ echo moremore >> anotherlarge
515 $ hg revert anotherlarge -v --config 'ui.origbackuppath=.hg/origbackups'
516 creating directory: $TESTTMP/addrm2/.hg/origbackups/.hglf/sub
517 saving current version of ../.hglf/sub/anotherlarge as $TESTTMP/addrm2/.hg/origbackups/.hglf/sub/anotherlarge.orig
518 reverting ../.hglf/sub/anotherlarge (glob)
519 creating directory: $TESTTMP/addrm2/.hg/origbackups/sub
520 found 90c622cf65cebe75c5842f9136c459333faf392e in store
521 found 90c622cf65cebe75c5842f9136c459333faf392e in store
522 $ ls ../.hg/origbackups/sub
523 anotherlarge.orig
512 524 $ cd ..
513 525
514 526 Test glob logging from the root dir
515 527 $ hg log glob:**another*
516 528 changeset: 1:9627a577c5e9
517 529 tag: tip
518 530 user: test
519 531 date: Thu Jan 01 00:00:00 1970 +0000
520 532 summary: anotherlarge
521 533
522 534 $ hg log -G glob:**another*
523 535 @ changeset: 1:9627a577c5e9
524 536 | tag: tip
525 537 | user: test
526 538 | date: Thu Jan 01 00:00:00 1970 +0000
527 539 | summary: anotherlarge
528 540 |
529 541
530 542 $ cd ..
531 543
532 544 Log from outer space
533 545 $ hg --debug log -R addrm2 -T '{rev}: {desc}\n' 'addrm2/sub/anotherlarge'
534 546 updated patterns: ['addrm2/.hglf/sub/anotherlarge', 'addrm2/sub/anotherlarge']
535 547 1: anotherlarge
536 548 $ hg --debug log -R addrm2 -T '{rev}: {desc}\n' 'addrm2/.hglf/sub/anotherlarge'
537 549 updated patterns: ['addrm2/.hglf/sub/anotherlarge']
538 550 1: anotherlarge
539 551
540 552
541 553 Check error message while exchange
542 554 =========================================================
543 555
544 556 issue3651: summary/outgoing with largefiles shows "no remote repo"
545 557 unexpectedly
546 558
547 559 $ mkdir issue3651
548 560 $ cd issue3651
549 561
550 562 $ hg init src
551 563 $ echo a > src/a
552 564 $ hg -R src add --large src/a
553 565 $ hg -R src commit -m '#0'
554 566 Invoking status precommit hook
555 567 A a
556 568
557 569 check messages when no remote repository is specified:
558 570 "no remote repo" route for "hg outgoing --large" is not tested here,
559 571 because it can't be reproduced easily.
560 572
561 573 $ hg init clone1
562 574 $ hg -R clone1 -q pull src
563 575 $ hg -R clone1 -q update
564 576 $ hg -R clone1 paths | grep default
565 577 [1]
566 578
567 579 $ hg -R clone1 summary --large
568 580 parent: 0:fc0bd45326d3 tip
569 581 #0
570 582 branch: default
571 583 commit: (clean)
572 584 update: (current)
573 585 phases: 1 draft
574 586 largefiles: (no remote repo)
575 587
576 588 check messages when there is no files to upload:
577 589
578 590 $ hg -q clone src clone2
579 591 $ hg -R clone2 paths | grep default
580 592 default = $TESTTMP/issue3651/src (glob)
581 593
582 594 $ hg -R clone2 summary --large
583 595 parent: 0:fc0bd45326d3 tip
584 596 #0
585 597 branch: default
586 598 commit: (clean)
587 599 update: (current)
588 600 phases: 1 draft
589 601 largefiles: (no files to upload)
590 602 $ hg -R clone2 outgoing --large
591 603 comparing with $TESTTMP/issue3651/src (glob)
592 604 searching for changes
593 605 no changes found
594 606 largefiles: no files to upload
595 607 [1]
596 608
597 609 $ hg -R clone2 outgoing --large --graph --template "{rev}"
598 610 comparing with $TESTTMP/issue3651/src (glob)
599 611 searching for changes
600 612 no changes found
601 613 largefiles: no files to upload
602 614
603 615 check messages when there are files to upload:
604 616
605 617 $ echo b > clone2/b
606 618 $ hg -R clone2 add --large clone2/b
607 619 $ hg -R clone2 commit -m '#1'
608 620 Invoking status precommit hook
609 621 A b
610 622 $ hg -R clone2 summary --large
611 623 parent: 1:1acbe71ce432 tip
612 624 #1
613 625 branch: default
614 626 commit: (clean)
615 627 update: (current)
616 628 phases: 2 draft
617 629 largefiles: 1 entities for 1 files to upload
618 630 $ hg -R clone2 outgoing --large
619 631 comparing with $TESTTMP/issue3651/src (glob)
620 632 searching for changes
621 633 changeset: 1:1acbe71ce432
622 634 tag: tip
623 635 user: test
624 636 date: Thu Jan 01 00:00:00 1970 +0000
625 637 summary: #1
626 638
627 639 largefiles to upload (1 entities):
628 640 b
629 641
630 642 $ hg -R clone2 outgoing --large --graph --template "{rev}"
631 643 comparing with $TESTTMP/issue3651/src (glob)
632 644 searching for changes
633 645 @ 1
634 646
635 647 largefiles to upload (1 entities):
636 648 b
637 649
638 650
639 651 $ cp clone2/b clone2/b1
640 652 $ cp clone2/b clone2/b2
641 653 $ hg -R clone2 add --large clone2/b1 clone2/b2
642 654 $ hg -R clone2 commit -m '#2: add largefiles referring same entity'
643 655 Invoking status precommit hook
644 656 A b1
645 657 A b2
646 658 $ hg -R clone2 summary --large
647 659 parent: 2:6095d0695d70 tip
648 660 #2: add largefiles referring same entity
649 661 branch: default
650 662 commit: (clean)
651 663 update: (current)
652 664 phases: 3 draft
653 665 largefiles: 1 entities for 3 files to upload
654 666 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n"
655 667 comparing with $TESTTMP/issue3651/src (glob)
656 668 searching for changes
657 669 1:1acbe71ce432
658 670 2:6095d0695d70
659 671 largefiles to upload (1 entities):
660 672 b
661 673 b1
662 674 b2
663 675
664 676 $ hg -R clone2 cat -r 1 clone2/.hglf/b
665 677 89e6c98d92887913cadf06b2adb97f26cde4849b
666 678 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n" --debug --config progress.debug=true
667 679 comparing with $TESTTMP/issue3651/src (glob)
668 680 query 1; heads
669 681 searching for changes
670 682 all remote heads known locally
671 683 1:1acbe71ce432
672 684 2:6095d0695d70
673 685 finding outgoing largefiles: 0/2 revision (0.00%)
674 686 finding outgoing largefiles: 1/2 revision (50.00%)
675 687 largefiles to upload (1 entities):
676 688 b
677 689 89e6c98d92887913cadf06b2adb97f26cde4849b
678 690 b1
679 691 89e6c98d92887913cadf06b2adb97f26cde4849b
680 692 b2
681 693 89e6c98d92887913cadf06b2adb97f26cde4849b
682 694
683 695
684 696 $ echo bbb > clone2/b
685 697 $ hg -R clone2 commit -m '#3: add new largefile entity as existing file'
686 698 Invoking status precommit hook
687 699 M b
688 700 $ echo bbbb > clone2/b
689 701 $ hg -R clone2 commit -m '#4: add new largefile entity as existing file'
690 702 Invoking status precommit hook
691 703 M b
692 704 $ cp clone2/b1 clone2/b
693 705 $ hg -R clone2 commit -m '#5: refer existing largefile entity again'
694 706 Invoking status precommit hook
695 707 M b
696 708 $ hg -R clone2 summary --large
697 709 parent: 5:036794ea641c tip
698 710 #5: refer existing largefile entity again
699 711 branch: default
700 712 commit: (clean)
701 713 update: (current)
702 714 phases: 6 draft
703 715 largefiles: 3 entities for 3 files to upload
704 716 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n"
705 717 comparing with $TESTTMP/issue3651/src (glob)
706 718 searching for changes
707 719 1:1acbe71ce432
708 720 2:6095d0695d70
709 721 3:7983dce246cc
710 722 4:233f12ada4ae
711 723 5:036794ea641c
712 724 largefiles to upload (3 entities):
713 725 b
714 726 b1
715 727 b2
716 728
717 729 $ hg -R clone2 cat -r 3 clone2/.hglf/b
718 730 c801c9cfe94400963fcb683246217d5db77f9a9a
719 731 $ hg -R clone2 cat -r 4 clone2/.hglf/b
720 732 13f9ed0898e315bf59dc2973fec52037b6f441a2
721 733 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n" --debug --config progress.debug=true
722 734 comparing with $TESTTMP/issue3651/src (glob)
723 735 query 1; heads
724 736 searching for changes
725 737 all remote heads known locally
726 738 1:1acbe71ce432
727 739 2:6095d0695d70
728 740 3:7983dce246cc
729 741 4:233f12ada4ae
730 742 5:036794ea641c
731 743 finding outgoing largefiles: 0/5 revision (0.00%)
732 744 finding outgoing largefiles: 1/5 revision (20.00%)
733 745 finding outgoing largefiles: 2/5 revision (40.00%)
734 746 finding outgoing largefiles: 3/5 revision (60.00%)
735 747 finding outgoing largefiles: 4/5 revision (80.00%)
736 748 largefiles to upload (3 entities):
737 749 b
738 750 13f9ed0898e315bf59dc2973fec52037b6f441a2
739 751 89e6c98d92887913cadf06b2adb97f26cde4849b
740 752 c801c9cfe94400963fcb683246217d5db77f9a9a
741 753 b1
742 754 89e6c98d92887913cadf06b2adb97f26cde4849b
743 755 b2
744 756 89e6c98d92887913cadf06b2adb97f26cde4849b
745 757
746 758
747 759 Pushing revision #1 causes uploading entity 89e6c98d9288, which is
748 760 shared also by largefiles b1, b2 in revision #2 and b in revision #5.
749 761
750 762 Then, entity 89e6c98d9288 is not treated as "outgoing entity" at "hg
751 763 summary" and "hg outgoing", even though files in outgoing revision #2
752 764 and #5 refer it.
753 765
754 766 $ hg -R clone2 push -r 1 -q
755 767 $ hg -R clone2 summary --large
756 768 parent: 5:036794ea641c tip
757 769 #5: refer existing largefile entity again
758 770 branch: default
759 771 commit: (clean)
760 772 update: (current)
761 773 phases: 6 draft
762 774 largefiles: 2 entities for 1 files to upload
763 775 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n"
764 776 comparing with $TESTTMP/issue3651/src (glob)
765 777 searching for changes
766 778 2:6095d0695d70
767 779 3:7983dce246cc
768 780 4:233f12ada4ae
769 781 5:036794ea641c
770 782 largefiles to upload (2 entities):
771 783 b
772 784
773 785 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n" --debug --config progress.debug=true
774 786 comparing with $TESTTMP/issue3651/src (glob)
775 787 query 1; heads
776 788 searching for changes
777 789 all remote heads known locally
778 790 2:6095d0695d70
779 791 3:7983dce246cc
780 792 4:233f12ada4ae
781 793 5:036794ea641c
782 794 finding outgoing largefiles: 0/4 revision (0.00%)
783 795 finding outgoing largefiles: 1/4 revision (25.00%)
784 796 finding outgoing largefiles: 2/4 revision (50.00%)
785 797 finding outgoing largefiles: 3/4 revision (75.00%)
786 798 largefiles to upload (2 entities):
787 799 b
788 800 13f9ed0898e315bf59dc2973fec52037b6f441a2
789 801 c801c9cfe94400963fcb683246217d5db77f9a9a
790 802
791 803
792 804 $ cd ..
793 805
794 806 merge action 'd' for 'local renamed directory to d2/g' which has no filename
795 807 ==================================================================================
796 808
797 809 $ hg init merge-action
798 810 $ cd merge-action
799 811 $ touch l
800 812 $ hg add --large l
801 813 $ mkdir d1
802 814 $ touch d1/f
803 815 $ hg ci -Aqm0
804 816 Invoking status precommit hook
805 817 A d1/f
806 818 A l
807 819 $ echo > d1/f
808 820 $ touch d1/g
809 821 $ hg ci -Aqm1
810 822 Invoking status precommit hook
811 823 M d1/f
812 824 A d1/g
813 825 $ hg up -qr0
814 826 $ hg mv d1 d2
815 827 moving d1/f to d2/f (glob)
816 828 $ hg ci -qm2
817 829 Invoking status precommit hook
818 830 A d2/f
819 831 R d1/f
820 832 $ hg merge
821 833 merging d2/f and d1/f to d2/f
822 834 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
823 835 (branch merge, don't forget to commit)
824 836 $ cd ..
825 837
826 838
827 839 Merge conflicts:
828 840 =====================
829 841
830 842 $ hg init merge
831 843 $ cd merge
832 844 $ echo 0 > f-different
833 845 $ echo 0 > f-same
834 846 $ echo 0 > f-unchanged-1
835 847 $ echo 0 > f-unchanged-2
836 848 $ hg add --large *
837 849 $ hg ci -m0
838 850 Invoking status precommit hook
839 851 A f-different
840 852 A f-same
841 853 A f-unchanged-1
842 854 A f-unchanged-2
843 855 $ echo tmp1 > f-unchanged-1
844 856 $ echo tmp1 > f-unchanged-2
845 857 $ echo tmp1 > f-same
846 858 $ hg ci -m1
847 859 Invoking status precommit hook
848 860 M f-same
849 861 M f-unchanged-1
850 862 M f-unchanged-2
851 863 $ echo 2 > f-different
852 864 $ echo 0 > f-unchanged-1
853 865 $ echo 1 > f-unchanged-2
854 866 $ echo 1 > f-same
855 867 $ hg ci -m2
856 868 Invoking status precommit hook
857 869 M f-different
858 870 M f-same
859 871 M f-unchanged-1
860 872 M f-unchanged-2
861 873 $ hg up -qr0
862 874 $ echo tmp2 > f-unchanged-1
863 875 $ echo tmp2 > f-unchanged-2
864 876 $ echo tmp2 > f-same
865 877 $ hg ci -m3
866 878 Invoking status precommit hook
867 879 M f-same
868 880 M f-unchanged-1
869 881 M f-unchanged-2
870 882 created new head
871 883 $ echo 1 > f-different
872 884 $ echo 1 > f-unchanged-1
873 885 $ echo 0 > f-unchanged-2
874 886 $ echo 1 > f-same
875 887 $ hg ci -m4
876 888 Invoking status precommit hook
877 889 M f-different
878 890 M f-same
879 891 M f-unchanged-1
880 892 M f-unchanged-2
881 893 $ hg merge
882 894 largefile f-different has a merge conflict
883 895 ancestor was 09d2af8dd22201dd8d48e5dcfcaed281ff9422c7
884 896 keep (l)ocal e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e or
885 897 take (o)ther 7448d8798a4380162d4b56f9b452e2f6f9e24e7a? l
886 898 getting changed largefiles
887 899 1 largefiles updated, 0 removed
888 900 0 files updated, 4 files merged, 0 files removed, 0 files unresolved
889 901 (branch merge, don't forget to commit)
890 902 $ cat f-different
891 903 1
892 904 $ cat f-same
893 905 1
894 906 $ cat f-unchanged-1
895 907 1
896 908 $ cat f-unchanged-2
897 909 1
898 910 $ cd ..
899 911
900 912 Test largefile insulation (do not enabled a side effect
901 913 ========================================================
902 914
903 915 Check whether "largefiles" feature is supported only in repositories
904 916 enabling largefiles extension.
905 917
906 918 $ mkdir individualenabling
907 919 $ cd individualenabling
908 920
909 921 $ hg init enabledlocally
910 922 $ echo large > enabledlocally/large
911 923 $ hg -R enabledlocally add --large enabledlocally/large
912 924 $ hg -R enabledlocally commit -m '#0'
913 925 Invoking status precommit hook
914 926 A large
915 927
916 928 $ hg init notenabledlocally
917 929 $ echo large > notenabledlocally/large
918 930 $ hg -R notenabledlocally add --large notenabledlocally/large
919 931 $ hg -R notenabledlocally commit -m '#0'
920 932 Invoking status precommit hook
921 933 A large
922 934
923 935 $ cat >> $HGRCPATH <<EOF
924 936 > [extensions]
925 937 > # disable globally
926 938 > largefiles=!
927 939 > EOF
928 940 $ cat >> enabledlocally/.hg/hgrc <<EOF
929 941 > [extensions]
930 942 > # enable locally
931 943 > largefiles=
932 944 > EOF
933 945 $ hg -R enabledlocally root
934 946 $TESTTMP/individualenabling/enabledlocally (glob)
935 947 $ hg -R notenabledlocally root
936 948 abort: repository requires features unknown to this Mercurial: largefiles!
937 949 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
938 950 [255]
939 951
940 952 $ hg init push-dst
941 953 $ hg -R enabledlocally push push-dst
942 954 pushing to push-dst
943 955 abort: required features are not supported in the destination: largefiles
944 956 [255]
945 957
946 958 $ hg init pull-src
947 959 $ hg -R pull-src pull enabledlocally
948 960 pulling from enabledlocally
949 961 abort: required features are not supported in the destination: largefiles
950 962 [255]
951 963
952 964 $ hg clone enabledlocally clone-dst
953 965 abort: repository requires features unknown to this Mercurial: largefiles!
954 966 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
955 967 [255]
956 968 $ test -d clone-dst
957 969 [1]
958 970 $ hg clone --pull enabledlocally clone-pull-dst
959 971 abort: required features are not supported in the destination: largefiles
960 972 [255]
961 973 $ test -d clone-pull-dst
962 974 [1]
963 975
964 976 #if serve
965 977
966 978 Test largefiles specific peer setup, when largefiles is enabled
967 979 locally (issue4109)
968 980
969 981 $ hg showconfig extensions | grep largefiles
970 982 extensions.largefiles=!
971 983 $ mkdir -p $TESTTMP/individualenabling/usercache
972 984
973 985 $ hg serve -R enabledlocally -d -p $HGPORT --pid-file hg.pid
974 986 $ cat hg.pid >> $DAEMON_PIDS
975 987
976 988 $ hg init pull-dst
977 989 $ cat > pull-dst/.hg/hgrc <<EOF
978 990 > [extensions]
979 991 > # enable locally
980 992 > largefiles=
981 993 > [largefiles]
982 994 > # ignore system cache to force largefiles specific wire proto access
983 995 > usercache=$TESTTMP/individualenabling/usercache
984 996 > EOF
985 997 $ hg -R pull-dst -q pull -u http://localhost:$HGPORT
986 998
987 999 $ killdaemons.py
988 1000 #endif
989 1001
990 1002 Test overridden functions work correctly even for repos disabling
991 1003 largefiles (issue4547)
992 1004
993 1005 $ hg showconfig extensions | grep largefiles
994 1006 extensions.largefiles=!
995 1007
996 1008 (test updating implied by clone)
997 1009
998 1010 $ hg init enabled-but-no-largefiles
999 1011 $ echo normal1 > enabled-but-no-largefiles/normal1
1000 1012 $ hg -R enabled-but-no-largefiles add enabled-but-no-largefiles/normal1
1001 1013 $ hg -R enabled-but-no-largefiles commit -m '#0@enabled-but-no-largefiles'
1002 1014 Invoking status precommit hook
1003 1015 A normal1
1004 1016 $ cat >> enabled-but-no-largefiles/.hg/hgrc <<EOF
1005 1017 > [extensions]
1006 1018 > # enable locally
1007 1019 > largefiles=
1008 1020 > EOF
1009 1021 $ hg clone -q enabled-but-no-largefiles no-largefiles
1010 1022
1011 1023 $ echo normal2 > enabled-but-no-largefiles/normal2
1012 1024 $ hg -R enabled-but-no-largefiles add enabled-but-no-largefiles/normal2
1013 1025 $ hg -R enabled-but-no-largefiles commit -m '#1@enabled-but-no-largefiles'
1014 1026 Invoking status precommit hook
1015 1027 A normal2
1016 1028
1017 1029 $ echo normal3 > no-largefiles/normal3
1018 1030 $ hg -R no-largefiles add no-largefiles/normal3
1019 1031 $ hg -R no-largefiles commit -m '#1@no-largefiles'
1020 1032 Invoking status precommit hook
1021 1033 A normal3
1022 1034
1023 1035 $ hg -R no-largefiles -q pull --rebase
1024 1036 Invoking status precommit hook
1025 1037 A normal3
1026 1038
1027 1039 (test reverting)
1028 1040
1029 1041 $ hg init subrepo-root
1030 1042 $ cat >> subrepo-root/.hg/hgrc <<EOF
1031 1043 > [extensions]
1032 1044 > # enable locally
1033 1045 > largefiles=
1034 1046 > EOF
1035 1047 $ echo large > subrepo-root/large
1036 1048 $ hg -R subrepo-root add --large subrepo-root/large
1037 1049 $ hg clone -q no-largefiles subrepo-root/no-largefiles
1038 1050 $ cat > subrepo-root/.hgsub <<EOF
1039 1051 > no-largefiles = no-largefiles
1040 1052 > EOF
1041 1053 $ hg -R subrepo-root add subrepo-root/.hgsub
1042 1054 $ hg -R subrepo-root commit -m '#0'
1043 1055 Invoking status precommit hook
1044 1056 A .hgsub
1045 1057 A large
1046 1058 ? .hgsubstate
1047 1059 $ echo dirty >> subrepo-root/large
1048 1060 $ echo dirty >> subrepo-root/no-largefiles/normal1
1049 1061 $ hg -R subrepo-root status -S
1050 1062 M large
1051 1063 M no-largefiles/normal1
1052 1064 $ hg -R subrepo-root revert --all
1053 1065 reverting subrepo-root/.hglf/large (glob)
1054 1066 reverting subrepo no-largefiles
1055 1067 reverting subrepo-root/no-largefiles/normal1 (glob)
1056 1068
1057 1069 $ cd ..
1058 1070
1059 1071
1060 1072 Test "pull --rebase" when rebase is enabled before largefiles (issue3861)
1061 1073 =========================================================================
1062 1074
1063 1075 $ hg showconfig extensions | grep largefiles
1064 1076 extensions.largefiles=!
1065 1077
1066 1078 $ mkdir issue3861
1067 1079 $ cd issue3861
1068 1080 $ hg init src
1069 1081 $ hg clone -q src dst
1070 1082 $ echo a > src/a
1071 1083 $ hg -R src commit -Aqm "#0"
1072 1084 Invoking status precommit hook
1073 1085 A a
1074 1086
1075 1087 $ cat >> dst/.hg/hgrc <<EOF
1076 1088 > [extensions]
1077 1089 > largefiles=
1078 1090 > EOF
1079 1091 $ hg -R dst pull --rebase
1080 1092 pulling from $TESTTMP/issue3861/src (glob)
1081 1093 requesting all changes
1082 1094 adding changesets
1083 1095 adding manifests
1084 1096 adding file changes
1085 1097 added 1 changesets with 1 changes to 1 files
1086 1098 nothing to rebase - working directory parent is already an ancestor of destination bf5e395ced2c
1087 1099 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1088 1100
1089 1101 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now