##// END OF EJS Templates
largefiles: teach log to handle patterns...
Matt Harbison -
r24206:13c1e66f default
parent child Browse files
Show More
@@ -1,1365 +1,1378
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 '''Overridden Mercurial commands and functions for the largefiles extension'''
10 10
11 11 import os
12 12 import copy
13 13
14 14 from mercurial import hg, util, cmdutil, scmutil, match as match_, \
15 15 archival, pathutil, revset
16 16 from mercurial.i18n import _
17 17 from mercurial.node import hex
18 18
19 19 import lfutil
20 20 import lfcommands
21 21 import basestore
22 22
23 23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
24 24
25 25 def composelargefilematcher(match, manifest):
26 26 '''create a matcher that matches only the largefiles in the original
27 27 matcher'''
28 28 m = copy.copy(match)
29 29 lfile = lambda f: lfutil.standin(f) in manifest
30 30 m._files = filter(lfile, m._files)
31 31 m._fmap = set(m._files)
32 32 m._always = False
33 33 origmatchfn = m.matchfn
34 34 m.matchfn = lambda f: lfile(f) and origmatchfn(f)
35 35 return m
36 36
37 37 def composenormalfilematcher(match, manifest, exclude=None):
38 38 excluded = set()
39 39 if exclude is not None:
40 40 excluded.update(exclude)
41 41
42 42 m = copy.copy(match)
43 43 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
44 44 manifest or f in excluded)
45 45 m._files = filter(notlfile, m._files)
46 46 m._fmap = set(m._files)
47 47 m._always = False
48 48 origmatchfn = m.matchfn
49 49 m.matchfn = lambda f: notlfile(f) and origmatchfn(f)
50 50 return m
51 51
52 52 def installnormalfilesmatchfn(manifest):
53 53 '''installmatchfn with a matchfn that ignores all largefiles'''
54 54 def overridematch(ctx, pats=[], opts={}, globbed=False,
55 55 default='relpath'):
56 56 match = oldmatch(ctx, pats, opts, globbed, default)
57 57 return composenormalfilematcher(match, manifest)
58 58 oldmatch = installmatchfn(overridematch)
59 59
60 60 def installmatchfn(f):
61 61 '''monkey patch the scmutil module with a custom match function.
62 62 Warning: it is monkey patching the _module_ on runtime! Not thread safe!'''
63 63 oldmatch = scmutil.match
64 64 setattr(f, 'oldmatch', oldmatch)
65 65 scmutil.match = f
66 66 return oldmatch
67 67
68 68 def restorematchfn():
69 69 '''restores scmutil.match to what it was before installmatchfn
70 70 was called. no-op if scmutil.match is its original function.
71 71
72 72 Note that n calls to installmatchfn will require n calls to
73 73 restore the original matchfn.'''
74 74 scmutil.match = getattr(scmutil.match, 'oldmatch')
75 75
76 76 def installmatchandpatsfn(f):
77 77 oldmatchandpats = scmutil.matchandpats
78 78 setattr(f, 'oldmatchandpats', oldmatchandpats)
79 79 scmutil.matchandpats = f
80 80 return oldmatchandpats
81 81
82 82 def restorematchandpatsfn():
83 83 '''restores scmutil.matchandpats to what it was before
84 84 installmatchandpatsfn was called. No-op if scmutil.matchandpats
85 85 is its original function.
86 86
87 87 Note that n calls to installmatchandpatsfn will require n calls
88 88 to restore the original matchfn.'''
89 89 scmutil.matchandpats = getattr(scmutil.matchandpats, 'oldmatchandpats',
90 90 scmutil.matchandpats)
91 91
92 92 def addlargefiles(ui, repo, isaddremove, matcher, **opts):
93 93 large = opts.get('large')
94 94 lfsize = lfutil.getminsize(
95 95 ui, lfutil.islfilesrepo(repo), opts.get('lfsize'))
96 96
97 97 lfmatcher = None
98 98 if lfutil.islfilesrepo(repo):
99 99 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
100 100 if lfpats:
101 101 lfmatcher = match_.match(repo.root, '', list(lfpats))
102 102
103 103 lfnames = []
104 104 m = copy.copy(matcher)
105 105 m.bad = lambda x, y: None
106 106 wctx = repo[None]
107 107 for f in repo.walk(m):
108 108 exact = m.exact(f)
109 109 lfile = lfutil.standin(f) in wctx
110 110 nfile = f in wctx
111 111 exists = lfile or nfile
112 112
113 113 # addremove in core gets fancy with the name, add doesn't
114 114 if isaddremove:
115 115 name = m.uipath(f)
116 116 else:
117 117 name = m.rel(f)
118 118
119 119 # Don't warn the user when they attempt to add a normal tracked file.
120 120 # The normal add code will do that for us.
121 121 if exact and exists:
122 122 if lfile:
123 123 ui.warn(_('%s already a largefile\n') % name)
124 124 continue
125 125
126 126 if (exact or not exists) and not lfutil.isstandin(f):
127 127 # In case the file was removed previously, but not committed
128 128 # (issue3507)
129 129 if not repo.wvfs.exists(f):
130 130 continue
131 131
132 132 abovemin = (lfsize and
133 133 repo.wvfs.lstat(f).st_size >= lfsize * 1024 * 1024)
134 134 if large or abovemin or (lfmatcher and lfmatcher(f)):
135 135 lfnames.append(f)
136 136 if ui.verbose or not exact:
137 137 ui.status(_('adding %s as a largefile\n') % name)
138 138
139 139 bad = []
140 140
141 141 # Need to lock, otherwise there could be a race condition between
142 142 # when standins are created and added to the repo.
143 143 wlock = repo.wlock()
144 144 try:
145 145 if not opts.get('dry_run'):
146 146 standins = []
147 147 lfdirstate = lfutil.openlfdirstate(ui, repo)
148 148 for f in lfnames:
149 149 standinname = lfutil.standin(f)
150 150 lfutil.writestandin(repo, standinname, hash='',
151 151 executable=lfutil.getexecutable(repo.wjoin(f)))
152 152 standins.append(standinname)
153 153 if lfdirstate[f] == 'r':
154 154 lfdirstate.normallookup(f)
155 155 else:
156 156 lfdirstate.add(f)
157 157 lfdirstate.write()
158 158 bad += [lfutil.splitstandin(f)
159 159 for f in repo[None].add(standins)
160 160 if f in m.files()]
161 161
162 162 added = [f for f in lfnames if f not in bad]
163 163 finally:
164 164 wlock.release()
165 165 return added, bad
166 166
167 167 def removelargefiles(ui, repo, isaddremove, matcher, **opts):
168 168 after = opts.get('after')
169 169 m = composelargefilematcher(matcher, repo[None].manifest())
170 170 try:
171 171 repo.lfstatus = True
172 172 s = repo.status(match=m, clean=not isaddremove)
173 173 finally:
174 174 repo.lfstatus = False
175 175 manifest = repo[None].manifest()
176 176 modified, added, deleted, clean = [[f for f in list
177 177 if lfutil.standin(f) in manifest]
178 178 for list in (s.modified, s.added,
179 179 s.deleted, s.clean)]
180 180
181 181 def warn(files, msg):
182 182 for f in files:
183 183 ui.warn(msg % m.rel(f))
184 184 return int(len(files) > 0)
185 185
186 186 result = 0
187 187
188 188 if after:
189 189 remove = deleted
190 190 result = warn(modified + added + clean,
191 191 _('not removing %s: file still exists\n'))
192 192 else:
193 193 remove = deleted + clean
194 194 result = warn(modified, _('not removing %s: file is modified (use -f'
195 195 ' to force removal)\n'))
196 196 result = warn(added, _('not removing %s: file has been marked for add'
197 197 ' (use forget to undo)\n')) or result
198 198
199 199 # Need to lock because standin files are deleted then removed from the
200 200 # repository and we could race in-between.
201 201 wlock = repo.wlock()
202 202 try:
203 203 lfdirstate = lfutil.openlfdirstate(ui, repo)
204 204 for f in sorted(remove):
205 205 if ui.verbose or not m.exact(f):
206 206 # addremove in core gets fancy with the name, remove doesn't
207 207 if isaddremove:
208 208 name = m.uipath(f)
209 209 else:
210 210 name = m.rel(f)
211 211 ui.status(_('removing %s\n') % name)
212 212
213 213 if not opts.get('dry_run'):
214 214 if not after:
215 215 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
216 216
217 217 if opts.get('dry_run'):
218 218 return result
219 219
220 220 remove = [lfutil.standin(f) for f in remove]
221 221 # If this is being called by addremove, let the original addremove
222 222 # function handle this.
223 223 if not isaddremove:
224 224 for f in remove:
225 225 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
226 226 repo[None].forget(remove)
227 227
228 228 for f in remove:
229 229 lfutil.synclfdirstate(repo, lfdirstate, lfutil.splitstandin(f),
230 230 False)
231 231
232 232 lfdirstate.write()
233 233 finally:
234 234 wlock.release()
235 235
236 236 return result
237 237
238 238 # For overriding mercurial.hgweb.webcommands so that largefiles will
239 239 # appear at their right place in the manifests.
240 240 def decodepath(orig, path):
241 241 return lfutil.splitstandin(path) or path
242 242
243 243 # -- Wrappers: modify existing commands --------------------------------
244 244
245 245 def overrideadd(orig, ui, repo, *pats, **opts):
246 246 if opts.get('normal') and opts.get('large'):
247 247 raise util.Abort(_('--normal cannot be used with --large'))
248 248 return orig(ui, repo, *pats, **opts)
249 249
250 250 def cmdutiladd(orig, ui, repo, matcher, prefix, explicitonly, **opts):
251 251 # The --normal flag short circuits this override
252 252 if opts.get('normal'):
253 253 return orig(ui, repo, matcher, prefix, explicitonly, **opts)
254 254
255 255 ladded, lbad = addlargefiles(ui, repo, False, matcher, **opts)
256 256 normalmatcher = composenormalfilematcher(matcher, repo[None].manifest(),
257 257 ladded)
258 258 bad = orig(ui, repo, normalmatcher, prefix, explicitonly, **opts)
259 259
260 260 bad.extend(f for f in lbad)
261 261 return bad
262 262
263 263 def cmdutilremove(orig, ui, repo, matcher, prefix, after, force, subrepos):
264 264 normalmatcher = composenormalfilematcher(matcher, repo[None].manifest())
265 265 result = orig(ui, repo, normalmatcher, prefix, after, force, subrepos)
266 266 return removelargefiles(ui, repo, False, matcher, after=after,
267 267 force=force) or result
268 268
269 269 def overridestatusfn(orig, repo, rev2, **opts):
270 270 try:
271 271 repo._repo.lfstatus = True
272 272 return orig(repo, rev2, **opts)
273 273 finally:
274 274 repo._repo.lfstatus = False
275 275
276 276 def overridestatus(orig, ui, repo, *pats, **opts):
277 277 try:
278 278 repo.lfstatus = True
279 279 return orig(ui, repo, *pats, **opts)
280 280 finally:
281 281 repo.lfstatus = False
282 282
283 283 def overridedirty(orig, repo, ignoreupdate=False):
284 284 try:
285 285 repo._repo.lfstatus = True
286 286 return orig(repo, ignoreupdate)
287 287 finally:
288 288 repo._repo.lfstatus = False
289 289
290 290 def overridelog(orig, ui, repo, *pats, **opts):
291 291 def overridematchandpats(ctx, pats=[], opts={}, globbed=False,
292 292 default='relpath'):
293 293 """Matcher that merges root directory with .hglf, suitable for log.
294 294 It is still possible to match .hglf directly.
295 295 For any listed files run log on the standin too.
296 296 matchfn tries both the given filename and with .hglf stripped.
297 297 """
298 298 matchandpats = oldmatchandpats(ctx, pats, opts, globbed, default)
299 299 m, p = copy.copy(matchandpats)
300 300
301 301 if m.always():
302 302 # We want to match everything anyway, so there's no benefit trying
303 303 # to add standins.
304 304 return matchandpats
305 305
306 306 pats = set(p)
307 # TODO: handling of patterns in both cases below
307
308 def fixpats(pat, tostandin=lfutil.standin):
309 kindpat = match_._patsplit(pat, None)
310
311 if kindpat[0] is not None:
312 return kindpat[0] + ':' + tostandin(kindpat[1])
313 return tostandin(kindpat[1])
314
308 315 if m._cwd:
309 316 if os.path.isabs(m._cwd):
310 317 # TODO: handle largefile magic when invoked from other cwd
311 318 return matchandpats
312 319 back = (m._cwd.count('/') + 1) * '../'
313 pats.update(back + lfutil.standin(m._cwd + '/' + f) for f in p)
320
321 def tostandin(f):
322 return back + lfutil.standin(m._cwd + '/' + f)
323
324 pats.update(fixpats(f, tostandin) for f in p)
314 325 else:
315 pats.update(lfutil.standin(f) for f in p)
326 pats.update(fixpats(f) for f in p)
316 327
317 328 for i in range(0, len(m._files)):
329 # Don't add '.hglf' to m.files, since that is already covered by '.'
330 if m._files[i] == '.':
331 continue
318 332 standin = lfutil.standin(m._files[i])
319 333 # If the "standin" is a directory, append instead of replace to
320 334 # support naming a directory on the command line with only
321 335 # largefiles. The original directory is kept to support normal
322 336 # files.
323 337 if standin in repo[ctx.node()]:
324 338 m._files[i] = standin
325 339 elif m._files[i] not in repo[ctx.node()] \
326 340 and repo.wvfs.isdir(standin):
327 341 m._files.append(standin)
328 pats.add(standin)
329 342
330 343 m._fmap = set(m._files)
331 344 m._always = False
332 345 origmatchfn = m.matchfn
333 346 def lfmatchfn(f):
334 347 lf = lfutil.splitstandin(f)
335 348 if lf is not None and origmatchfn(lf):
336 349 return True
337 350 r = origmatchfn(f)
338 351 return r
339 352 m.matchfn = lfmatchfn
340 353
341 354 return m, pats
342 355
343 356 # For hg log --patch, the match object is used in two different senses:
344 357 # (1) to determine what revisions should be printed out, and
345 358 # (2) to determine what files to print out diffs for.
346 359 # The magic matchandpats override should be used for case (1) but not for
347 360 # case (2).
348 361 def overridemakelogfilematcher(repo, pats, opts):
349 362 pctx = repo[None]
350 363 match, pats = oldmatchandpats(pctx, pats, opts)
351 364 return lambda rev: match
352 365
353 366 oldmatchandpats = installmatchandpatsfn(overridematchandpats)
354 367 oldmakelogfilematcher = cmdutil._makenofollowlogfilematcher
355 368 setattr(cmdutil, '_makenofollowlogfilematcher', overridemakelogfilematcher)
356 369
357 370 try:
358 371 return orig(ui, repo, *pats, **opts)
359 372 finally:
360 373 restorematchandpatsfn()
361 374 setattr(cmdutil, '_makenofollowlogfilematcher', oldmakelogfilematcher)
362 375
363 376 def overrideverify(orig, ui, repo, *pats, **opts):
364 377 large = opts.pop('large', False)
365 378 all = opts.pop('lfa', False)
366 379 contents = opts.pop('lfc', False)
367 380
368 381 result = orig(ui, repo, *pats, **opts)
369 382 if large or all or contents:
370 383 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
371 384 return result
372 385
373 386 def overridedebugstate(orig, ui, repo, *pats, **opts):
374 387 large = opts.pop('large', False)
375 388 if large:
376 389 class fakerepo(object):
377 390 dirstate = lfutil.openlfdirstate(ui, repo)
378 391 orig(ui, fakerepo, *pats, **opts)
379 392 else:
380 393 orig(ui, repo, *pats, **opts)
381 394
382 395 # Override needs to refresh standins so that update's normal merge
383 396 # will go through properly. Then the other update hook (overriding repo.update)
384 397 # will get the new files. Filemerge is also overridden so that the merge
385 398 # will merge standins correctly.
386 399 def overrideupdate(orig, ui, repo, *pats, **opts):
387 400 # Need to lock between the standins getting updated and their
388 401 # largefiles getting updated
389 402 wlock = repo.wlock()
390 403 try:
391 404 if opts['check']:
392 405 lfdirstate = lfutil.openlfdirstate(ui, repo)
393 406 unsure, s = lfdirstate.status(
394 407 match_.always(repo.root, repo.getcwd()),
395 408 [], False, False, False)
396 409
397 410 mod = len(s.modified) > 0
398 411 for lfile in unsure:
399 412 standin = lfutil.standin(lfile)
400 413 if repo['.'][standin].data().strip() != \
401 414 lfutil.hashfile(repo.wjoin(lfile)):
402 415 mod = True
403 416 else:
404 417 lfdirstate.normal(lfile)
405 418 lfdirstate.write()
406 419 if mod:
407 420 raise util.Abort(_('uncommitted changes'))
408 421 return orig(ui, repo, *pats, **opts)
409 422 finally:
410 423 wlock.release()
411 424
412 425 # Before starting the manifest merge, merge.updates will call
413 426 # _checkunknownfile to check if there are any files in the merged-in
414 427 # changeset that collide with unknown files in the working copy.
415 428 #
416 429 # The largefiles are seen as unknown, so this prevents us from merging
417 430 # in a file 'foo' if we already have a largefile with the same name.
418 431 #
419 432 # The overridden function filters the unknown files by removing any
420 433 # largefiles. This makes the merge proceed and we can then handle this
421 434 # case further in the overridden calculateupdates function below.
422 435 def overridecheckunknownfile(origfn, repo, wctx, mctx, f, f2=None):
423 436 if lfutil.standin(repo.dirstate.normalize(f)) in wctx:
424 437 return False
425 438 return origfn(repo, wctx, mctx, f, f2)
426 439
427 440 # The manifest merge handles conflicts on the manifest level. We want
428 441 # to handle changes in largefile-ness of files at this level too.
429 442 #
430 443 # The strategy is to run the original calculateupdates and then process
431 444 # the action list it outputs. There are two cases we need to deal with:
432 445 #
433 446 # 1. Normal file in p1, largefile in p2. Here the largefile is
434 447 # detected via its standin file, which will enter the working copy
435 448 # with a "get" action. It is not "merge" since the standin is all
436 449 # Mercurial is concerned with at this level -- the link to the
437 450 # existing normal file is not relevant here.
438 451 #
439 452 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
440 453 # since the largefile will be present in the working copy and
441 454 # different from the normal file in p2. Mercurial therefore
442 455 # triggers a merge action.
443 456 #
444 457 # In both cases, we prompt the user and emit new actions to either
445 458 # remove the standin (if the normal file was kept) or to remove the
446 459 # normal file and get the standin (if the largefile was kept). The
447 460 # default prompt answer is to use the largefile version since it was
448 461 # presumably changed on purpose.
449 462 #
450 463 # Finally, the merge.applyupdates function will then take care of
451 464 # writing the files into the working copy and lfcommands.updatelfiles
452 465 # will update the largefiles.
453 466 def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force,
454 467 partial, acceptremote, followcopies):
455 468 overwrite = force and not branchmerge
456 469 actions, diverge, renamedelete = origfn(
457 470 repo, p1, p2, pas, branchmerge, force, partial, acceptremote,
458 471 followcopies)
459 472
460 473 if overwrite:
461 474 return actions, diverge, renamedelete
462 475
463 476 # Convert to dictionary with filename as key and action as value.
464 477 lfiles = set()
465 478 for f in actions:
466 479 splitstandin = f and lfutil.splitstandin(f)
467 480 if splitstandin in p1:
468 481 lfiles.add(splitstandin)
469 482 elif lfutil.standin(f) in p1:
470 483 lfiles.add(f)
471 484
472 485 for lfile in lfiles:
473 486 standin = lfutil.standin(lfile)
474 487 (lm, largs, lmsg) = actions.get(lfile, (None, None, None))
475 488 (sm, sargs, smsg) = actions.get(standin, (None, None, None))
476 489 if sm in ('g', 'dc') and lm != 'r':
477 490 # Case 1: normal file in the working copy, largefile in
478 491 # the second parent
479 492 usermsg = _('remote turned local normal file %s into a largefile\n'
480 493 'use (l)argefile or keep (n)ormal file?'
481 494 '$$ &Largefile $$ &Normal file') % lfile
482 495 if repo.ui.promptchoice(usermsg, 0) == 0: # pick remote largefile
483 496 actions[lfile] = ('r', None, 'replaced by standin')
484 497 actions[standin] = ('g', sargs, 'replaces standin')
485 498 else: # keep local normal file
486 499 actions[lfile] = ('k', None, 'replaces standin')
487 500 if branchmerge:
488 501 actions[standin] = ('k', None, 'replaced by non-standin')
489 502 else:
490 503 actions[standin] = ('r', None, 'replaced by non-standin')
491 504 elif lm in ('g', 'dc') and sm != 'r':
492 505 # Case 2: largefile in the working copy, normal file in
493 506 # the second parent
494 507 usermsg = _('remote turned local largefile %s into a normal file\n'
495 508 'keep (l)argefile or use (n)ormal file?'
496 509 '$$ &Largefile $$ &Normal file') % lfile
497 510 if repo.ui.promptchoice(usermsg, 0) == 0: # keep local largefile
498 511 if branchmerge:
499 512 # largefile can be restored from standin safely
500 513 actions[lfile] = ('k', None, 'replaced by standin')
501 514 actions[standin] = ('k', None, 'replaces standin')
502 515 else:
503 516 # "lfile" should be marked as "removed" without
504 517 # removal of itself
505 518 actions[lfile] = ('lfmr', None,
506 519 'forget non-standin largefile')
507 520
508 521 # linear-merge should treat this largefile as 're-added'
509 522 actions[standin] = ('a', None, 'keep standin')
510 523 else: # pick remote normal file
511 524 actions[lfile] = ('g', largs, 'replaces standin')
512 525 actions[standin] = ('r', None, 'replaced by non-standin')
513 526
514 527 return actions, diverge, renamedelete
515 528
516 529 def mergerecordupdates(orig, repo, actions, branchmerge):
517 530 if 'lfmr' in actions:
518 531 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
519 532 for lfile, args, msg in actions['lfmr']:
520 533 # this should be executed before 'orig', to execute 'remove'
521 534 # before all other actions
522 535 repo.dirstate.remove(lfile)
523 536 # make sure lfile doesn't get synclfdirstate'd as normal
524 537 lfdirstate.add(lfile)
525 538 lfdirstate.write()
526 539
527 540 return orig(repo, actions, branchmerge)
528 541
529 542
530 543 # Override filemerge to prompt the user about how they wish to merge
531 544 # largefiles. This will handle identical edits without prompting the user.
532 545 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca, labels=None):
533 546 if not lfutil.isstandin(orig):
534 547 return origfn(repo, mynode, orig, fcd, fco, fca, labels=labels)
535 548
536 549 ahash = fca.data().strip().lower()
537 550 dhash = fcd.data().strip().lower()
538 551 ohash = fco.data().strip().lower()
539 552 if (ohash != ahash and
540 553 ohash != dhash and
541 554 (dhash == ahash or
542 555 repo.ui.promptchoice(
543 556 _('largefile %s has a merge conflict\nancestor was %s\n'
544 557 'keep (l)ocal %s or\ntake (o)ther %s?'
545 558 '$$ &Local $$ &Other') %
546 559 (lfutil.splitstandin(orig), ahash, dhash, ohash),
547 560 0) == 1)):
548 561 repo.wwrite(fcd.path(), fco.data(), fco.flags())
549 562 return 0
550 563
551 564 # Copy first changes the matchers to match standins instead of
552 565 # largefiles. Then it overrides util.copyfile in that function it
553 566 # checks if the destination largefile already exists. It also keeps a
554 567 # list of copied files so that the largefiles can be copied and the
555 568 # dirstate updated.
556 569 def overridecopy(orig, ui, repo, pats, opts, rename=False):
557 570 # doesn't remove largefile on rename
558 571 if len(pats) < 2:
559 572 # this isn't legal, let the original function deal with it
560 573 return orig(ui, repo, pats, opts, rename)
561 574
562 575 # This could copy both lfiles and normal files in one command,
563 576 # but we don't want to do that. First replace their matcher to
564 577 # only match normal files and run it, then replace it to just
565 578 # match largefiles and run it again.
566 579 nonormalfiles = False
567 580 nolfiles = False
568 581 installnormalfilesmatchfn(repo[None].manifest())
569 582 try:
570 583 try:
571 584 result = orig(ui, repo, pats, opts, rename)
572 585 except util.Abort, e:
573 586 if str(e) != _('no files to copy'):
574 587 raise e
575 588 else:
576 589 nonormalfiles = True
577 590 result = 0
578 591 finally:
579 592 restorematchfn()
580 593
581 594 # The first rename can cause our current working directory to be removed.
582 595 # In that case there is nothing left to copy/rename so just quit.
583 596 try:
584 597 repo.getcwd()
585 598 except OSError:
586 599 return result
587 600
588 601 def makestandin(relpath):
589 602 path = pathutil.canonpath(repo.root, repo.getcwd(), relpath)
590 603 return os.path.join(repo.wjoin(lfutil.standin(path)))
591 604
592 605 fullpats = scmutil.expandpats(pats)
593 606 dest = fullpats[-1]
594 607
595 608 if os.path.isdir(dest):
596 609 if not os.path.isdir(makestandin(dest)):
597 610 os.makedirs(makestandin(dest))
598 611
599 612 try:
600 613 try:
601 614 # When we call orig below it creates the standins but we don't add
602 615 # them to the dir state until later so lock during that time.
603 616 wlock = repo.wlock()
604 617
605 618 manifest = repo[None].manifest()
606 619 def overridematch(ctx, pats=[], opts={}, globbed=False,
607 620 default='relpath'):
608 621 newpats = []
609 622 # The patterns were previously mangled to add the standin
610 623 # directory; we need to remove that now
611 624 for pat in pats:
612 625 if match_.patkind(pat) is None and lfutil.shortname in pat:
613 626 newpats.append(pat.replace(lfutil.shortname, ''))
614 627 else:
615 628 newpats.append(pat)
616 629 match = oldmatch(ctx, newpats, opts, globbed, default)
617 630 m = copy.copy(match)
618 631 lfile = lambda f: lfutil.standin(f) in manifest
619 632 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
620 633 m._fmap = set(m._files)
621 634 origmatchfn = m.matchfn
622 635 m.matchfn = lambda f: (lfutil.isstandin(f) and
623 636 (f in manifest) and
624 637 origmatchfn(lfutil.splitstandin(f)) or
625 638 None)
626 639 return m
627 640 oldmatch = installmatchfn(overridematch)
628 641 listpats = []
629 642 for pat in pats:
630 643 if match_.patkind(pat) is not None:
631 644 listpats.append(pat)
632 645 else:
633 646 listpats.append(makestandin(pat))
634 647
635 648 try:
636 649 origcopyfile = util.copyfile
637 650 copiedfiles = []
638 651 def overridecopyfile(src, dest):
639 652 if (lfutil.shortname in src and
640 653 dest.startswith(repo.wjoin(lfutil.shortname))):
641 654 destlfile = dest.replace(lfutil.shortname, '')
642 655 if not opts['force'] and os.path.exists(destlfile):
643 656 raise IOError('',
644 657 _('destination largefile already exists'))
645 658 copiedfiles.append((src, dest))
646 659 origcopyfile(src, dest)
647 660
648 661 util.copyfile = overridecopyfile
649 662 result += orig(ui, repo, listpats, opts, rename)
650 663 finally:
651 664 util.copyfile = origcopyfile
652 665
653 666 lfdirstate = lfutil.openlfdirstate(ui, repo)
654 667 for (src, dest) in copiedfiles:
655 668 if (lfutil.shortname in src and
656 669 dest.startswith(repo.wjoin(lfutil.shortname))):
657 670 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
658 671 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
659 672 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
660 673 if not os.path.isdir(destlfiledir):
661 674 os.makedirs(destlfiledir)
662 675 if rename:
663 676 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
664 677
665 678 # The file is gone, but this deletes any empty parent
666 679 # directories as a side-effect.
667 680 util.unlinkpath(repo.wjoin(srclfile), True)
668 681 lfdirstate.remove(srclfile)
669 682 else:
670 683 util.copyfile(repo.wjoin(srclfile),
671 684 repo.wjoin(destlfile))
672 685
673 686 lfdirstate.add(destlfile)
674 687 lfdirstate.write()
675 688 except util.Abort, e:
676 689 if str(e) != _('no files to copy'):
677 690 raise e
678 691 else:
679 692 nolfiles = True
680 693 finally:
681 694 restorematchfn()
682 695 wlock.release()
683 696
684 697 if nolfiles and nonormalfiles:
685 698 raise util.Abort(_('no files to copy'))
686 699
687 700 return result
688 701
689 702 # When the user calls revert, we have to be careful to not revert any
690 703 # changes to other largefiles accidentally. This means we have to keep
691 704 # track of the largefiles that are being reverted so we only pull down
692 705 # the necessary largefiles.
693 706 #
694 707 # Standins are only updated (to match the hash of largefiles) before
695 708 # commits. Update the standins then run the original revert, changing
696 709 # the matcher to hit standins instead of largefiles. Based on the
697 710 # resulting standins update the largefiles.
698 711 def overriderevert(orig, ui, repo, *pats, **opts):
699 712 # Because we put the standins in a bad state (by updating them)
700 713 # and then return them to a correct state we need to lock to
701 714 # prevent others from changing them in their incorrect state.
702 715 wlock = repo.wlock()
703 716 try:
704 717 lfdirstate = lfutil.openlfdirstate(ui, repo)
705 718 s = lfutil.lfdirstatestatus(lfdirstate, repo)
706 719 lfdirstate.write()
707 720 for lfile in s.modified:
708 721 lfutil.updatestandin(repo, lfutil.standin(lfile))
709 722 for lfile in s.deleted:
710 723 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
711 724 os.unlink(repo.wjoin(lfutil.standin(lfile)))
712 725
713 726 oldstandins = lfutil.getstandinsstate(repo)
714 727
715 728 def overridematch(ctx, pats=[], opts={}, globbed=False,
716 729 default='relpath'):
717 730 match = oldmatch(ctx, pats, opts, globbed, default)
718 731 m = copy.copy(match)
719 732
720 733 # revert supports recursing into subrepos, and though largefiles
721 734 # currently doesn't work correctly in that case, this match is
722 735 # called, so the lfdirstate above may not be the correct one for
723 736 # this invocation of match.
724 737 lfdirstate = lfutil.openlfdirstate(ctx._repo.ui, ctx._repo, False)
725 738
726 739 def tostandin(f):
727 740 if lfutil.standin(f) in ctx:
728 741 return lfutil.standin(f)
729 742 elif lfutil.standin(f) in repo[None] or lfdirstate[f] == 'r':
730 743 return None
731 744 return f
732 745 m._files = [tostandin(f) for f in m._files]
733 746 m._files = [f for f in m._files if f is not None]
734 747 m._fmap = set(m._files)
735 748 origmatchfn = m.matchfn
736 749 def matchfn(f):
737 750 if lfutil.isstandin(f):
738 751 return (origmatchfn(lfutil.splitstandin(f)) and
739 752 (f in repo[None] or f in ctx))
740 753 return origmatchfn(f)
741 754 m.matchfn = matchfn
742 755 return m
743 756 oldmatch = installmatchfn(overridematch)
744 757 try:
745 758 orig(ui, repo, *pats, **opts)
746 759 finally:
747 760 restorematchfn()
748 761
749 762 newstandins = lfutil.getstandinsstate(repo)
750 763 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
751 764 # lfdirstate should be 'normallookup'-ed for updated files,
752 765 # because reverting doesn't touch dirstate for 'normal' files
753 766 # when target revision is explicitly specified: in such case,
754 767 # 'n' and valid timestamp in dirstate doesn't ensure 'clean'
755 768 # of target (standin) file.
756 769 lfcommands.updatelfiles(ui, repo, filelist, printmessage=False,
757 770 normallookup=True)
758 771
759 772 finally:
760 773 wlock.release()
761 774
762 775 # after pulling changesets, we need to take some extra care to get
763 776 # largefiles updated remotely
764 777 def overridepull(orig, ui, repo, source=None, **opts):
765 778 revsprepull = len(repo)
766 779 if not source:
767 780 source = 'default'
768 781 repo.lfpullsource = source
769 782 result = orig(ui, repo, source, **opts)
770 783 revspostpull = len(repo)
771 784 lfrevs = opts.get('lfrev', [])
772 785 if opts.get('all_largefiles'):
773 786 lfrevs.append('pulled()')
774 787 if lfrevs and revspostpull > revsprepull:
775 788 numcached = 0
776 789 repo.firstpulled = revsprepull # for pulled() revset expression
777 790 try:
778 791 for rev in scmutil.revrange(repo, lfrevs):
779 792 ui.note(_('pulling largefiles for revision %s\n') % rev)
780 793 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev)
781 794 numcached += len(cached)
782 795 finally:
783 796 del repo.firstpulled
784 797 ui.status(_("%d largefiles cached\n") % numcached)
785 798 return result
786 799
787 800 def pulledrevsetsymbol(repo, subset, x):
788 801 """``pulled()``
789 802 Changesets that just has been pulled.
790 803
791 804 Only available with largefiles from pull --lfrev expressions.
792 805
793 806 .. container:: verbose
794 807
795 808 Some examples:
796 809
797 810 - pull largefiles for all new changesets::
798 811
799 812 hg pull -lfrev "pulled()"
800 813
801 814 - pull largefiles for all new branch heads::
802 815
803 816 hg pull -lfrev "head(pulled()) and not closed()"
804 817
805 818 """
806 819
807 820 try:
808 821 firstpulled = repo.firstpulled
809 822 except AttributeError:
810 823 raise util.Abort(_("pulled() only available in --lfrev"))
811 824 return revset.baseset([r for r in subset if r >= firstpulled])
812 825
813 826 def overrideclone(orig, ui, source, dest=None, **opts):
814 827 d = dest
815 828 if d is None:
816 829 d = hg.defaultdest(source)
817 830 if opts.get('all_largefiles') and not hg.islocal(d):
818 831 raise util.Abort(_(
819 832 '--all-largefiles is incompatible with non-local destination %s') %
820 833 d)
821 834
822 835 return orig(ui, source, dest, **opts)
823 836
824 837 def hgclone(orig, ui, opts, *args, **kwargs):
825 838 result = orig(ui, opts, *args, **kwargs)
826 839
827 840 if result is not None:
828 841 sourcerepo, destrepo = result
829 842 repo = destrepo.local()
830 843
831 844 # If largefiles is required for this repo, permanently enable it locally
832 845 if 'largefiles' in repo.requirements:
833 846 fp = repo.vfs('hgrc', 'a', text=True)
834 847 try:
835 848 fp.write('\n[extensions]\nlargefiles=\n')
836 849 finally:
837 850 fp.close()
838 851
839 852 # Caching is implicitly limited to 'rev' option, since the dest repo was
840 853 # truncated at that point. The user may expect a download count with
841 854 # this option, so attempt whether or not this is a largefile repo.
842 855 if opts.get('all_largefiles'):
843 856 success, missing = lfcommands.downloadlfiles(ui, repo, None)
844 857
845 858 if missing != 0:
846 859 return None
847 860
848 861 return result
849 862
850 863 def overriderebase(orig, ui, repo, **opts):
851 864 if not util.safehasattr(repo, '_largefilesenabled'):
852 865 return orig(ui, repo, **opts)
853 866
854 867 resuming = opts.get('continue')
855 868 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
856 869 repo._lfstatuswriters.append(lambda *msg, **opts: None)
857 870 try:
858 871 return orig(ui, repo, **opts)
859 872 finally:
860 873 repo._lfstatuswriters.pop()
861 874 repo._lfcommithooks.pop()
862 875
863 876 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
864 877 prefix='', mtime=None, subrepos=None):
865 878 # No need to lock because we are only reading history and
866 879 # largefile caches, neither of which are modified.
867 880 lfcommands.cachelfiles(repo.ui, repo, node)
868 881
869 882 if kind not in archival.archivers:
870 883 raise util.Abort(_("unknown archive type '%s'") % kind)
871 884
872 885 ctx = repo[node]
873 886
874 887 if kind == 'files':
875 888 if prefix:
876 889 raise util.Abort(
877 890 _('cannot give prefix when archiving to files'))
878 891 else:
879 892 prefix = archival.tidyprefix(dest, kind, prefix)
880 893
881 894 def write(name, mode, islink, getdata):
882 895 if matchfn and not matchfn(name):
883 896 return
884 897 data = getdata()
885 898 if decode:
886 899 data = repo.wwritedata(name, data)
887 900 archiver.addfile(prefix + name, mode, islink, data)
888 901
889 902 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
890 903
891 904 if repo.ui.configbool("ui", "archivemeta", True):
892 905 def metadata():
893 906 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
894 907 hex(repo.changelog.node(0)), hex(node), ctx.branch())
895 908
896 909 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
897 910 if repo.tagtype(t) == 'global')
898 911 if not tags:
899 912 repo.ui.pushbuffer()
900 913 opts = {'template': '{latesttag}\n{latesttagdistance}',
901 914 'style': '', 'patch': None, 'git': None}
902 915 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
903 916 ltags, dist = repo.ui.popbuffer().split('\n')
904 917 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
905 918 tags += 'latesttagdistance: %s\n' % dist
906 919
907 920 return base + tags
908 921
909 922 write('.hg_archival.txt', 0644, False, metadata)
910 923
911 924 for f in ctx:
912 925 ff = ctx.flags(f)
913 926 getdata = ctx[f].data
914 927 if lfutil.isstandin(f):
915 928 path = lfutil.findfile(repo, getdata().strip())
916 929 if path is None:
917 930 raise util.Abort(
918 931 _('largefile %s not found in repo store or system cache')
919 932 % lfutil.splitstandin(f))
920 933 f = lfutil.splitstandin(f)
921 934
922 935 def getdatafn():
923 936 fd = None
924 937 try:
925 938 fd = open(path, 'rb')
926 939 return fd.read()
927 940 finally:
928 941 if fd:
929 942 fd.close()
930 943
931 944 getdata = getdatafn
932 945 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
933 946
934 947 if subrepos:
935 948 for subpath in sorted(ctx.substate):
936 949 sub = ctx.sub(subpath)
937 950 submatch = match_.narrowmatcher(subpath, matchfn)
938 951 sub.archive(archiver, prefix, submatch)
939 952
940 953 archiver.done()
941 954
942 955 def hgsubrepoarchive(orig, repo, archiver, prefix, match=None):
943 956 repo._get(repo._state + ('hg',))
944 957 rev = repo._state[1]
945 958 ctx = repo._repo[rev]
946 959
947 960 lfcommands.cachelfiles(repo.ui, repo._repo, ctx.node())
948 961
949 962 def write(name, mode, islink, getdata):
950 963 # At this point, the standin has been replaced with the largefile name,
951 964 # so the normal matcher works here without the lfutil variants.
952 965 if match and not match(f):
953 966 return
954 967 data = getdata()
955 968
956 969 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
957 970
958 971 for f in ctx:
959 972 ff = ctx.flags(f)
960 973 getdata = ctx[f].data
961 974 if lfutil.isstandin(f):
962 975 path = lfutil.findfile(repo._repo, getdata().strip())
963 976 if path is None:
964 977 raise util.Abort(
965 978 _('largefile %s not found in repo store or system cache')
966 979 % lfutil.splitstandin(f))
967 980 f = lfutil.splitstandin(f)
968 981
969 982 def getdatafn():
970 983 fd = None
971 984 try:
972 985 fd = open(os.path.join(prefix, path), 'rb')
973 986 return fd.read()
974 987 finally:
975 988 if fd:
976 989 fd.close()
977 990
978 991 getdata = getdatafn
979 992
980 993 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
981 994
982 995 for subpath in sorted(ctx.substate):
983 996 sub = ctx.sub(subpath)
984 997 submatch = match_.narrowmatcher(subpath, match)
985 998 sub.archive(archiver, os.path.join(prefix, repo._path) + '/', submatch)
986 999
987 1000 # If a largefile is modified, the change is not reflected in its
988 1001 # standin until a commit. cmdutil.bailifchanged() raises an exception
989 1002 # if the repo has uncommitted changes. Wrap it to also check if
990 1003 # largefiles were changed. This is used by bisect, backout and fetch.
991 1004 def overridebailifchanged(orig, repo):
992 1005 orig(repo)
993 1006 repo.lfstatus = True
994 1007 s = repo.status()
995 1008 repo.lfstatus = False
996 1009 if s.modified or s.added or s.removed or s.deleted:
997 1010 raise util.Abort(_('uncommitted changes'))
998 1011
999 1012 def cmdutilforget(orig, ui, repo, match, prefix, explicitonly):
1000 1013 normalmatcher = composenormalfilematcher(match, repo[None].manifest())
1001 1014 bad, forgot = orig(ui, repo, normalmatcher, prefix, explicitonly)
1002 1015 m = composelargefilematcher(match, repo[None].manifest())
1003 1016
1004 1017 try:
1005 1018 repo.lfstatus = True
1006 1019 s = repo.status(match=m, clean=True)
1007 1020 finally:
1008 1021 repo.lfstatus = False
1009 1022 forget = sorted(s.modified + s.added + s.deleted + s.clean)
1010 1023 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
1011 1024
1012 1025 for f in forget:
1013 1026 if lfutil.standin(f) not in repo.dirstate and not \
1014 1027 repo.wvfs.isdir(lfutil.standin(f)):
1015 1028 ui.warn(_('not removing %s: file is already untracked\n')
1016 1029 % m.rel(f))
1017 1030 bad.append(f)
1018 1031
1019 1032 for f in forget:
1020 1033 if ui.verbose or not m.exact(f):
1021 1034 ui.status(_('removing %s\n') % m.rel(f))
1022 1035
1023 1036 # Need to lock because standin files are deleted then removed from the
1024 1037 # repository and we could race in-between.
1025 1038 wlock = repo.wlock()
1026 1039 try:
1027 1040 lfdirstate = lfutil.openlfdirstate(ui, repo)
1028 1041 for f in forget:
1029 1042 if lfdirstate[f] == 'a':
1030 1043 lfdirstate.drop(f)
1031 1044 else:
1032 1045 lfdirstate.remove(f)
1033 1046 lfdirstate.write()
1034 1047 standins = [lfutil.standin(f) for f in forget]
1035 1048 for f in standins:
1036 1049 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1037 1050 rejected = repo[None].forget(standins)
1038 1051 finally:
1039 1052 wlock.release()
1040 1053
1041 1054 bad.extend(f for f in rejected if f in m.files())
1042 1055 forgot.extend(f for f in forget if f not in rejected)
1043 1056 return bad, forgot
1044 1057
1045 1058 def _getoutgoings(repo, other, missing, addfunc):
1046 1059 """get pairs of filename and largefile hash in outgoing revisions
1047 1060 in 'missing'.
1048 1061
1049 1062 largefiles already existing on 'other' repository are ignored.
1050 1063
1051 1064 'addfunc' is invoked with each unique pairs of filename and
1052 1065 largefile hash value.
1053 1066 """
1054 1067 knowns = set()
1055 1068 lfhashes = set()
1056 1069 def dedup(fn, lfhash):
1057 1070 k = (fn, lfhash)
1058 1071 if k not in knowns:
1059 1072 knowns.add(k)
1060 1073 lfhashes.add(lfhash)
1061 1074 lfutil.getlfilestoupload(repo, missing, dedup)
1062 1075 if lfhashes:
1063 1076 lfexists = basestore._openstore(repo, other).exists(lfhashes)
1064 1077 for fn, lfhash in knowns:
1065 1078 if not lfexists[lfhash]: # lfhash doesn't exist on "other"
1066 1079 addfunc(fn, lfhash)
1067 1080
1068 1081 def outgoinghook(ui, repo, other, opts, missing):
1069 1082 if opts.pop('large', None):
1070 1083 lfhashes = set()
1071 1084 if ui.debugflag:
1072 1085 toupload = {}
1073 1086 def addfunc(fn, lfhash):
1074 1087 if fn not in toupload:
1075 1088 toupload[fn] = []
1076 1089 toupload[fn].append(lfhash)
1077 1090 lfhashes.add(lfhash)
1078 1091 def showhashes(fn):
1079 1092 for lfhash in sorted(toupload[fn]):
1080 1093 ui.debug(' %s\n' % (lfhash))
1081 1094 else:
1082 1095 toupload = set()
1083 1096 def addfunc(fn, lfhash):
1084 1097 toupload.add(fn)
1085 1098 lfhashes.add(lfhash)
1086 1099 def showhashes(fn):
1087 1100 pass
1088 1101 _getoutgoings(repo, other, missing, addfunc)
1089 1102
1090 1103 if not toupload:
1091 1104 ui.status(_('largefiles: no files to upload\n'))
1092 1105 else:
1093 1106 ui.status(_('largefiles to upload (%d entities):\n')
1094 1107 % (len(lfhashes)))
1095 1108 for file in sorted(toupload):
1096 1109 ui.status(lfutil.splitstandin(file) + '\n')
1097 1110 showhashes(file)
1098 1111 ui.status('\n')
1099 1112
1100 1113 def summaryremotehook(ui, repo, opts, changes):
1101 1114 largeopt = opts.get('large', False)
1102 1115 if changes is None:
1103 1116 if largeopt:
1104 1117 return (False, True) # only outgoing check is needed
1105 1118 else:
1106 1119 return (False, False)
1107 1120 elif largeopt:
1108 1121 url, branch, peer, outgoing = changes[1]
1109 1122 if peer is None:
1110 1123 # i18n: column positioning for "hg summary"
1111 1124 ui.status(_('largefiles: (no remote repo)\n'))
1112 1125 return
1113 1126
1114 1127 toupload = set()
1115 1128 lfhashes = set()
1116 1129 def addfunc(fn, lfhash):
1117 1130 toupload.add(fn)
1118 1131 lfhashes.add(lfhash)
1119 1132 _getoutgoings(repo, peer, outgoing.missing, addfunc)
1120 1133
1121 1134 if not toupload:
1122 1135 # i18n: column positioning for "hg summary"
1123 1136 ui.status(_('largefiles: (no files to upload)\n'))
1124 1137 else:
1125 1138 # i18n: column positioning for "hg summary"
1126 1139 ui.status(_('largefiles: %d entities for %d files to upload\n')
1127 1140 % (len(lfhashes), len(toupload)))
1128 1141
1129 1142 def overridesummary(orig, ui, repo, *pats, **opts):
1130 1143 try:
1131 1144 repo.lfstatus = True
1132 1145 orig(ui, repo, *pats, **opts)
1133 1146 finally:
1134 1147 repo.lfstatus = False
1135 1148
1136 1149 def scmutiladdremove(orig, repo, matcher, prefix, opts={}, dry_run=None,
1137 1150 similarity=None):
1138 1151 if not lfutil.islfilesrepo(repo):
1139 1152 return orig(repo, matcher, prefix, opts, dry_run, similarity)
1140 1153 # Get the list of missing largefiles so we can remove them
1141 1154 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1142 1155 unsure, s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [],
1143 1156 False, False, False)
1144 1157
1145 1158 # Call into the normal remove code, but the removing of the standin, we want
1146 1159 # to have handled by original addremove. Monkey patching here makes sure
1147 1160 # we don't remove the standin in the largefiles code, preventing a very
1148 1161 # confused state later.
1149 1162 if s.deleted:
1150 1163 m = copy.copy(matcher)
1151 1164
1152 1165 # The m._files and m._map attributes are not changed to the deleted list
1153 1166 # because that affects the m.exact() test, which in turn governs whether
1154 1167 # or not the file name is printed, and how. Simply limit the original
1155 1168 # matches to those in the deleted status list.
1156 1169 matchfn = m.matchfn
1157 1170 m.matchfn = lambda f: f in s.deleted and matchfn(f)
1158 1171
1159 1172 removelargefiles(repo.ui, repo, True, m, **opts)
1160 1173 # Call into the normal add code, and any files that *should* be added as
1161 1174 # largefiles will be
1162 1175 added, bad = addlargefiles(repo.ui, repo, True, matcher, **opts)
1163 1176 # Now that we've handled largefiles, hand off to the original addremove
1164 1177 # function to take care of the rest. Make sure it doesn't do anything with
1165 1178 # largefiles by passing a matcher that will ignore them.
1166 1179 matcher = composenormalfilematcher(matcher, repo[None].manifest(), added)
1167 1180 return orig(repo, matcher, prefix, opts, dry_run, similarity)
1168 1181
1169 1182 # Calling purge with --all will cause the largefiles to be deleted.
1170 1183 # Override repo.status to prevent this from happening.
1171 1184 def overridepurge(orig, ui, repo, *dirs, **opts):
1172 1185 # XXX Monkey patching a repoview will not work. The assigned attribute will
1173 1186 # be set on the unfiltered repo, but we will only lookup attributes in the
1174 1187 # unfiltered repo if the lookup in the repoview object itself fails. As the
1175 1188 # monkey patched method exists on the repoview class the lookup will not
1176 1189 # fail. As a result, the original version will shadow the monkey patched
1177 1190 # one, defeating the monkey patch.
1178 1191 #
1179 1192 # As a work around we use an unfiltered repo here. We should do something
1180 1193 # cleaner instead.
1181 1194 repo = repo.unfiltered()
1182 1195 oldstatus = repo.status
1183 1196 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1184 1197 clean=False, unknown=False, listsubrepos=False):
1185 1198 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1186 1199 listsubrepos)
1187 1200 lfdirstate = lfutil.openlfdirstate(ui, repo)
1188 1201 unknown = [f for f in r.unknown if lfdirstate[f] == '?']
1189 1202 ignored = [f for f in r.ignored if lfdirstate[f] == '?']
1190 1203 return scmutil.status(r.modified, r.added, r.removed, r.deleted,
1191 1204 unknown, ignored, r.clean)
1192 1205 repo.status = overridestatus
1193 1206 orig(ui, repo, *dirs, **opts)
1194 1207 repo.status = oldstatus
1195 1208 def overriderollback(orig, ui, repo, **opts):
1196 1209 wlock = repo.wlock()
1197 1210 try:
1198 1211 before = repo.dirstate.parents()
1199 1212 orphans = set(f for f in repo.dirstate
1200 1213 if lfutil.isstandin(f) and repo.dirstate[f] != 'r')
1201 1214 result = orig(ui, repo, **opts)
1202 1215 after = repo.dirstate.parents()
1203 1216 if before == after:
1204 1217 return result # no need to restore standins
1205 1218
1206 1219 pctx = repo['.']
1207 1220 for f in repo.dirstate:
1208 1221 if lfutil.isstandin(f):
1209 1222 orphans.discard(f)
1210 1223 if repo.dirstate[f] == 'r':
1211 1224 repo.wvfs.unlinkpath(f, ignoremissing=True)
1212 1225 elif f in pctx:
1213 1226 fctx = pctx[f]
1214 1227 repo.wwrite(f, fctx.data(), fctx.flags())
1215 1228 else:
1216 1229 # content of standin is not so important in 'a',
1217 1230 # 'm' or 'n' (coming from the 2nd parent) cases
1218 1231 lfutil.writestandin(repo, f, '', False)
1219 1232 for standin in orphans:
1220 1233 repo.wvfs.unlinkpath(standin, ignoremissing=True)
1221 1234
1222 1235 lfdirstate = lfutil.openlfdirstate(ui, repo)
1223 1236 orphans = set(lfdirstate)
1224 1237 lfiles = lfutil.listlfiles(repo)
1225 1238 for file in lfiles:
1226 1239 lfutil.synclfdirstate(repo, lfdirstate, file, True)
1227 1240 orphans.discard(file)
1228 1241 for lfile in orphans:
1229 1242 lfdirstate.drop(lfile)
1230 1243 lfdirstate.write()
1231 1244 finally:
1232 1245 wlock.release()
1233 1246 return result
1234 1247
1235 1248 def overridetransplant(orig, ui, repo, *revs, **opts):
1236 1249 resuming = opts.get('continue')
1237 1250 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
1238 1251 repo._lfstatuswriters.append(lambda *msg, **opts: None)
1239 1252 try:
1240 1253 result = orig(ui, repo, *revs, **opts)
1241 1254 finally:
1242 1255 repo._lfstatuswriters.pop()
1243 1256 repo._lfcommithooks.pop()
1244 1257 return result
1245 1258
1246 1259 def overridecat(orig, ui, repo, file1, *pats, **opts):
1247 1260 ctx = scmutil.revsingle(repo, opts.get('rev'))
1248 1261 err = 1
1249 1262 notbad = set()
1250 1263 m = scmutil.match(ctx, (file1,) + pats, opts)
1251 1264 origmatchfn = m.matchfn
1252 1265 def lfmatchfn(f):
1253 1266 if origmatchfn(f):
1254 1267 return True
1255 1268 lf = lfutil.splitstandin(f)
1256 1269 if lf is None:
1257 1270 return False
1258 1271 notbad.add(lf)
1259 1272 return origmatchfn(lf)
1260 1273 m.matchfn = lfmatchfn
1261 1274 origbadfn = m.bad
1262 1275 def lfbadfn(f, msg):
1263 1276 if not f in notbad:
1264 1277 origbadfn(f, msg)
1265 1278 m.bad = lfbadfn
1266 1279 for f in ctx.walk(m):
1267 1280 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1268 1281 pathname=f)
1269 1282 lf = lfutil.splitstandin(f)
1270 1283 if lf is None or origmatchfn(f):
1271 1284 # duplicating unreachable code from commands.cat
1272 1285 data = ctx[f].data()
1273 1286 if opts.get('decode'):
1274 1287 data = repo.wwritedata(f, data)
1275 1288 fp.write(data)
1276 1289 else:
1277 1290 hash = lfutil.readstandin(repo, lf, ctx.rev())
1278 1291 if not lfutil.inusercache(repo.ui, hash):
1279 1292 store = basestore._openstore(repo)
1280 1293 success, missing = store.get([(lf, hash)])
1281 1294 if len(success) != 1:
1282 1295 raise util.Abort(
1283 1296 _('largefile %s is not in cache and could not be '
1284 1297 'downloaded') % lf)
1285 1298 path = lfutil.usercachepath(repo.ui, hash)
1286 1299 fpin = open(path, "rb")
1287 1300 for chunk in util.filechunkiter(fpin, 128 * 1024):
1288 1301 fp.write(chunk)
1289 1302 fpin.close()
1290 1303 fp.close()
1291 1304 err = 0
1292 1305 return err
1293 1306
1294 1307 def mergeupdate(orig, repo, node, branchmerge, force, partial,
1295 1308 *args, **kwargs):
1296 1309 wlock = repo.wlock()
1297 1310 try:
1298 1311 # branch | | |
1299 1312 # merge | force | partial | action
1300 1313 # -------+-------+---------+--------------
1301 1314 # x | x | x | linear-merge
1302 1315 # o | x | x | branch-merge
1303 1316 # x | o | x | overwrite (as clean update)
1304 1317 # o | o | x | force-branch-merge (*1)
1305 1318 # x | x | o | (*)
1306 1319 # o | x | o | (*)
1307 1320 # x | o | o | overwrite (as revert)
1308 1321 # o | o | o | (*)
1309 1322 #
1310 1323 # (*) don't care
1311 1324 # (*1) deprecated, but used internally (e.g: "rebase --collapse")
1312 1325
1313 1326 linearmerge = not branchmerge and not force and not partial
1314 1327
1315 1328 if linearmerge or (branchmerge and force and not partial):
1316 1329 # update standins for linear-merge or force-branch-merge,
1317 1330 # because largefiles in the working directory may be modified
1318 1331 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1319 1332 unsure, s = lfdirstate.status(match_.always(repo.root,
1320 1333 repo.getcwd()),
1321 1334 [], False, False, False)
1322 1335 pctx = repo['.']
1323 1336 for lfile in unsure + s.modified:
1324 1337 lfileabs = repo.wvfs.join(lfile)
1325 1338 if not os.path.exists(lfileabs):
1326 1339 continue
1327 1340 lfhash = lfutil.hashrepofile(repo, lfile)
1328 1341 standin = lfutil.standin(lfile)
1329 1342 lfutil.writestandin(repo, standin, lfhash,
1330 1343 lfutil.getexecutable(lfileabs))
1331 1344 if (standin in pctx and
1332 1345 lfhash == lfutil.readstandin(repo, lfile, '.')):
1333 1346 lfdirstate.normal(lfile)
1334 1347 for lfile in s.added:
1335 1348 lfutil.updatestandin(repo, lfutil.standin(lfile))
1336 1349 lfdirstate.write()
1337 1350
1338 1351 if linearmerge:
1339 1352 # Only call updatelfiles on the standins that have changed
1340 1353 # to save time
1341 1354 oldstandins = lfutil.getstandinsstate(repo)
1342 1355
1343 1356 result = orig(repo, node, branchmerge, force, partial, *args, **kwargs)
1344 1357
1345 1358 filelist = None
1346 1359 if linearmerge:
1347 1360 newstandins = lfutil.getstandinsstate(repo)
1348 1361 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1349 1362
1350 1363 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1351 1364 normallookup=partial, checked=linearmerge)
1352 1365
1353 1366 return result
1354 1367 finally:
1355 1368 wlock.release()
1356 1369
1357 1370 def scmutilmarktouched(orig, repo, files, *args, **kwargs):
1358 1371 result = orig(repo, files, *args, **kwargs)
1359 1372
1360 1373 filelist = [lfutil.splitstandin(f) for f in files if lfutil.isstandin(f)]
1361 1374 if filelist:
1362 1375 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1363 1376 printmessage=False, normallookup=True)
1364 1377
1365 1378 return result
@@ -1,1021 +1,1053
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 $ hg ci -m "deep copy"
41 41 Invoking status precommit hook
42 42 A dira/foo/largefile
43 43 $ find . | sort
44 44 .
45 45 ./dirb
46 46 ./dirb/largefile
47 47 ./foo
48 48 ./foo/largefile
49 49 $ hg mv foo/largefile baz/largefile
50 50 $ hg ci -m "moved"
51 51 Invoking status precommit hook
52 52 A dira/baz/largefile
53 53 R dira/foo/largefile
54 54 $ find . | sort
55 55 .
56 56 ./baz
57 57 ./baz/largefile
58 58 ./dirb
59 59 ./dirb/largefile
60 60 $ cd ..
61 61 $ hg mv dira dirc
62 62 moving .hglf/dira/baz/largefile to .hglf/dirc/baz/largefile (glob)
63 63 moving .hglf/dira/dirb/largefile to .hglf/dirc/dirb/largefile (glob)
64 64 $ find * | sort
65 65 dirc
66 66 dirc/baz
67 67 dirc/baz/largefile
68 68 dirc/dirb
69 69 dirc/dirb/largefile
70 70
71 71 $ hg clone -q . ../fetch
72 72 $ hg --config extensions.fetch= fetch ../fetch
73 73 abort: uncommitted changes
74 74 [255]
75 75 $ hg up -qC
76 76 $ cd ..
77 77
78 78 Clone a local repository owned by another user
79 79 ===================================================
80 80
81 81 #if unix-permissions
82 82
83 83 We have to simulate that here by setting $HOME and removing write permissions
84 84 $ ORIGHOME="$HOME"
85 85 $ mkdir alice
86 86 $ HOME="`pwd`/alice"
87 87 $ cd alice
88 88 $ hg init pubrepo
89 89 $ cd pubrepo
90 90 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
91 91 $ hg add --large a-large-file
92 92 $ hg commit -m "Add a large file"
93 93 Invoking status precommit hook
94 94 A a-large-file
95 95 $ cd ..
96 96 $ chmod -R a-w pubrepo
97 97 $ cd ..
98 98 $ mkdir bob
99 99 $ HOME="`pwd`/bob"
100 100 $ cd bob
101 101 $ hg clone --pull ../alice/pubrepo pubrepo
102 102 requesting all changes
103 103 adding changesets
104 104 adding manifests
105 105 adding file changes
106 106 added 1 changesets with 1 changes to 1 files
107 107 updating to branch default
108 108 getting changed largefiles
109 109 1 largefiles updated, 0 removed
110 110 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
111 111 $ cd ..
112 112 $ chmod -R u+w alice/pubrepo
113 113 $ HOME="$ORIGHOME"
114 114
115 115 #endif
116 116
117 117
118 118 Symlink to a large largefile should behave the same as a symlink to a normal file
119 119 =====================================================================================
120 120
121 121 #if symlink
122 122
123 123 $ hg init largesymlink
124 124 $ cd largesymlink
125 125 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
126 126 $ hg add --large largefile
127 127 $ hg commit -m "commit a large file"
128 128 Invoking status precommit hook
129 129 A largefile
130 130 $ ln -s largefile largelink
131 131 $ hg add largelink
132 132 $ hg commit -m "commit a large symlink"
133 133 Invoking status precommit hook
134 134 A largelink
135 135 $ rm -f largelink
136 136 $ hg up >/dev/null
137 137 $ test -f largelink
138 138 [1]
139 139 $ test -L largelink
140 140 [1]
141 141 $ rm -f largelink # make next part of the test independent of the previous
142 142 $ hg up -C >/dev/null
143 143 $ test -f largelink
144 144 $ test -L largelink
145 145 $ cd ..
146 146
147 147 #endif
148 148
149 149
150 150 test for pattern matching on 'hg status':
151 151 ==============================================
152 152
153 153
154 154 to boost performance, largefiles checks whether specified patterns are
155 155 related to largefiles in working directory (NOT to STANDIN) or not.
156 156
157 157 $ hg init statusmatch
158 158 $ cd statusmatch
159 159
160 160 $ mkdir -p a/b/c/d
161 161 $ echo normal > a/b/c/d/e.normal.txt
162 162 $ hg add a/b/c/d/e.normal.txt
163 163 $ echo large > a/b/c/d/e.large.txt
164 164 $ hg add --large a/b/c/d/e.large.txt
165 165 $ mkdir -p a/b/c/x
166 166 $ echo normal > a/b/c/x/y.normal.txt
167 167 $ hg add a/b/c/x/y.normal.txt
168 168 $ hg commit -m 'add files'
169 169 Invoking status precommit hook
170 170 A a/b/c/d/e.large.txt
171 171 A a/b/c/d/e.normal.txt
172 172 A a/b/c/x/y.normal.txt
173 173
174 174 (1) no pattern: no performance boost
175 175 $ hg status -A
176 176 C a/b/c/d/e.large.txt
177 177 C a/b/c/d/e.normal.txt
178 178 C a/b/c/x/y.normal.txt
179 179
180 180 (2) pattern not related to largefiles: performance boost
181 181 $ hg status -A a/b/c/x
182 182 C a/b/c/x/y.normal.txt
183 183
184 184 (3) pattern related to largefiles: no performance boost
185 185 $ hg status -A a/b/c/d
186 186 C a/b/c/d/e.large.txt
187 187 C a/b/c/d/e.normal.txt
188 188
189 189 (4) pattern related to STANDIN (not to largefiles): performance boost
190 190 $ hg status -A .hglf/a
191 191 C .hglf/a/b/c/d/e.large.txt
192 192
193 193 (5) mixed case: no performance boost
194 194 $ hg status -A a/b/c/x a/b/c/d
195 195 C a/b/c/d/e.large.txt
196 196 C a/b/c/d/e.normal.txt
197 197 C a/b/c/x/y.normal.txt
198 198
199 199 verify that largefiles doesn't break filesets
200 200
201 201 $ hg log --rev . --exclude "set:binary()"
202 202 changeset: 0:41bd42f10efa
203 203 tag: tip
204 204 user: test
205 205 date: Thu Jan 01 00:00:00 1970 +0000
206 206 summary: add files
207 207
208 208 verify that large files in subrepos handled properly
209 209 $ hg init subrepo
210 210 $ echo "subrepo = subrepo" > .hgsub
211 211 $ hg add .hgsub
212 212 $ hg ci -m "add subrepo"
213 213 Invoking status precommit hook
214 214 A .hgsub
215 215 ? .hgsubstate
216 216 $ echo "rev 1" > subrepo/large.txt
217 217 $ hg add --large subrepo/large.txt
218 218 $ hg sum
219 219 parent: 1:8ee150ea2e9c tip
220 220 add subrepo
221 221 branch: default
222 222 commit: 1 subrepos
223 223 update: (current)
224 224 $ hg st
225 225 $ hg st -S
226 226 A subrepo/large.txt
227 227 $ hg ci -S -m "commit top repo"
228 228 committing subrepository subrepo
229 229 Invoking status precommit hook
230 230 A large.txt
231 231 Invoking status precommit hook
232 232 M .hgsubstate
233 233 # No differences
234 234 $ hg st -S
235 235 $ hg sum
236 236 parent: 2:ce4cd0c527a6 tip
237 237 commit top repo
238 238 branch: default
239 239 commit: (clean)
240 240 update: (current)
241 241 $ echo "rev 2" > subrepo/large.txt
242 242 $ hg st -S
243 243 M subrepo/large.txt
244 244 $ hg sum
245 245 parent: 2:ce4cd0c527a6 tip
246 246 commit top repo
247 247 branch: default
248 248 commit: 1 subrepos
249 249 update: (current)
250 250 $ hg ci -m "this commit should fail without -S"
251 251 abort: uncommitted changes in subrepo subrepo
252 252 (use --subrepos for recursive commit)
253 253 [255]
254 254
255 255 Add a normal file to the subrepo, then test archiving
256 256
257 257 $ echo 'normal file' > subrepo/normal.txt
258 258 $ touch large.dat
259 259 $ mv subrepo/large.txt subrepo/renamed-large.txt
260 260 $ hg addremove -S --dry-run
261 261 adding large.dat as a largefile
262 262 removing subrepo/large.txt
263 263 adding subrepo/normal.txt
264 264 adding subrepo/renamed-large.txt
265 265 $ hg status -S
266 266 ! subrepo/large.txt
267 267 ? large.dat
268 268 ? subrepo/normal.txt
269 269 ? subrepo/renamed-large.txt
270 270
271 271 $ hg addremove --dry-run subrepo
272 272 removing subrepo/large.txt (glob)
273 273 adding subrepo/normal.txt (glob)
274 274 adding subrepo/renamed-large.txt (glob)
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 $ cd ..
281 281
282 282 $ hg -R statusmatch addremove --dry-run statusmatch/subrepo
283 283 removing statusmatch/subrepo/large.txt (glob)
284 284 adding statusmatch/subrepo/normal.txt (glob)
285 285 adding statusmatch/subrepo/renamed-large.txt (glob)
286 286 $ hg -R statusmatch status -S
287 287 ! subrepo/large.txt
288 288 ? large.dat
289 289 ? subrepo/normal.txt
290 290 ? subrepo/renamed-large.txt
291 291
292 292 $ hg -R statusmatch addremove --dry-run -S
293 293 adding large.dat as a largefile
294 294 removing subrepo/large.txt
295 295 adding subrepo/normal.txt
296 296 adding subrepo/renamed-large.txt
297 297 $ cd statusmatch
298 298
299 299 $ mv subrepo/renamed-large.txt subrepo/large.txt
300 300 $ hg addremove subrepo
301 301 adding subrepo/normal.txt (glob)
302 302 $ hg forget subrepo/normal.txt
303 303
304 304 $ hg addremove -S
305 305 adding large.dat as a largefile
306 306 adding subrepo/normal.txt
307 307 $ rm large.dat
308 308
309 309 $ hg addremove subrepo
310 310 $ hg addremove -S
311 311 removing large.dat
312 312
313 313 Lock in subrepo, otherwise the change isn't archived
314 314
315 315 $ hg ci -S -m "add normal file to top level"
316 316 committing subrepository subrepo
317 317 Invoking status precommit hook
318 318 M large.txt
319 319 A normal.txt
320 320 Invoking status precommit hook
321 321 M .hgsubstate
322 322 $ hg archive -S ../lf_subrepo_archive
323 323 $ find ../lf_subrepo_archive | sort
324 324 ../lf_subrepo_archive
325 325 ../lf_subrepo_archive/.hg_archival.txt
326 326 ../lf_subrepo_archive/.hgsub
327 327 ../lf_subrepo_archive/.hgsubstate
328 328 ../lf_subrepo_archive/a
329 329 ../lf_subrepo_archive/a/b
330 330 ../lf_subrepo_archive/a/b/c
331 331 ../lf_subrepo_archive/a/b/c/d
332 332 ../lf_subrepo_archive/a/b/c/d/e.large.txt
333 333 ../lf_subrepo_archive/a/b/c/d/e.normal.txt
334 334 ../lf_subrepo_archive/a/b/c/x
335 335 ../lf_subrepo_archive/a/b/c/x/y.normal.txt
336 336 ../lf_subrepo_archive/subrepo
337 337 ../lf_subrepo_archive/subrepo/large.txt
338 338 ../lf_subrepo_archive/subrepo/normal.txt
339 339
340 340 Test update with subrepos.
341 341
342 342 $ hg update 0
343 343 getting changed largefiles
344 344 0 largefiles updated, 1 removed
345 345 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
346 346 $ hg status -S
347 347 $ hg update tip
348 348 getting changed largefiles
349 349 1 largefiles updated, 0 removed
350 350 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
351 351 $ hg status -S
352 352 # modify a large file
353 353 $ echo "modified" > subrepo/large.txt
354 354 $ hg st -S
355 355 M subrepo/large.txt
356 356 # update -C should revert the change.
357 357 $ hg update -C
358 358 getting changed largefiles
359 359 1 largefiles updated, 0 removed
360 360 getting changed largefiles
361 361 0 largefiles updated, 0 removed
362 362 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
363 363 $ hg status -S
364 364
365 365 $ hg forget -v subrepo/large.txt
366 366 removing subrepo/large.txt (glob)
367 367
368 368 Test reverting a forgotten file
369 369 $ hg revert -R subrepo subrepo/large.txt
370 370 $ hg status -SA subrepo/large.txt
371 371 C subrepo/large.txt
372 372
373 373 $ hg rm -v subrepo/large.txt
374 374 removing subrepo/large.txt (glob)
375 375 $ hg revert -R subrepo subrepo/large.txt
376 376 $ rm subrepo/large.txt
377 377 $ hg addremove -S
378 378 removing subrepo/large.txt
379 379 $ hg st -S
380 380 R subrepo/large.txt
381 381
382 382 Test archiving a revision that references a subrepo that is not yet
383 383 cloned (see test-subrepo-recursion.t):
384 384
385 385 $ hg clone -U . ../empty
386 386 $ cd ../empty
387 387 $ hg archive --subrepos -r tip ../archive.tar.gz
388 388 cloning subrepo subrepo from $TESTTMP/statusmatch/subrepo
389 389 $ cd ..
390 390
391 391
392 392
393 393
394 394
395 395
396 396 Test addremove, forget and others
397 397 ==============================================
398 398
399 399 Test that addremove picks up largefiles prior to the initial commit (issue3541)
400 400
401 401 $ hg init addrm2
402 402 $ cd addrm2
403 403 $ touch large.dat
404 404 $ touch large2.dat
405 405 $ touch normal
406 406 $ hg add --large large.dat
407 407 $ hg addremove -v
408 408 adding large2.dat as a largefile
409 409 adding normal
410 410
411 411 Test that forgetting all largefiles reverts to islfilesrepo() == False
412 412 (addremove will add *.dat as normal files now)
413 413 $ hg forget large.dat
414 414 $ hg forget large2.dat
415 415 $ hg addremove -v
416 416 adding large.dat
417 417 adding large2.dat
418 418
419 419 Test commit's addremove option prior to the first commit
420 420 $ hg forget large.dat
421 421 $ hg forget large2.dat
422 422 $ hg add --large large.dat
423 423 $ hg ci -Am "commit"
424 424 adding large2.dat as a largefile
425 425 Invoking status precommit hook
426 426 A large.dat
427 427 A large2.dat
428 428 A normal
429 429 $ find .hglf | sort
430 430 .hglf
431 431 .hglf/large.dat
432 432 .hglf/large2.dat
433 433
434 434 Test actions on largefiles using relative paths from subdir
435 435
436 436 $ mkdir sub
437 437 $ cd sub
438 438 $ echo anotherlarge > anotherlarge
439 439 $ hg add --large anotherlarge
440 440 $ hg st
441 441 A sub/anotherlarge
442 442 $ hg st anotherlarge
443 443 A anotherlarge
444 444 $ hg commit -m anotherlarge anotherlarge
445 445 Invoking status precommit hook
446 446 A sub/anotherlarge
447 447 $ hg log anotherlarge
448 448 changeset: 1:9627a577c5e9
449 449 tag: tip
450 450 user: test
451 451 date: Thu Jan 01 00:00:00 1970 +0000
452 452 summary: anotherlarge
453 453
454 454 $ hg log -G anotherlarge
455 455 @ changeset: 1:9627a577c5e9
456 456 | tag: tip
457 457 | user: test
458 458 | date: Thu Jan 01 00:00:00 1970 +0000
459 459 | summary: anotherlarge
460 460 |
461
462 $ hg log glob:another*
463 changeset: 1:9627a577c5e9
464 tag: tip
465 user: test
466 date: Thu Jan 01 00:00:00 1970 +0000
467 summary: anotherlarge
468
469 $ hg log -G glob:another*
470 @ changeset: 1:9627a577c5e9
471 | tag: tip
472 | user: test
473 | date: Thu Jan 01 00:00:00 1970 +0000
474 | summary: anotherlarge
475 |
476
461 477 $ echo more >> anotherlarge
462 478 $ hg st .
463 479 M anotherlarge
464 480 $ hg cat anotherlarge
465 481 anotherlarge
466 482 $ hg revert anotherlarge
467 483 $ hg st
468 484 ? sub/anotherlarge.orig
469 485 $ cd ..
470 486
487 Test glob logging from the root dir
488 $ hg log glob:**another*
489 changeset: 1:9627a577c5e9
490 tag: tip
491 user: test
492 date: Thu Jan 01 00:00:00 1970 +0000
493 summary: anotherlarge
494
495 $ hg log -G glob:**another*
496 @ changeset: 1:9627a577c5e9
497 | tag: tip
498 | user: test
499 | date: Thu Jan 01 00:00:00 1970 +0000
500 | summary: anotherlarge
501 |
502
471 503 $ cd ..
472 504
473 505 Check error message while exchange
474 506 =========================================================
475 507
476 508 issue3651: summary/outgoing with largefiles shows "no remote repo"
477 509 unexpectedly
478 510
479 511 $ mkdir issue3651
480 512 $ cd issue3651
481 513
482 514 $ hg init src
483 515 $ echo a > src/a
484 516 $ hg -R src add --large src/a
485 517 $ hg -R src commit -m '#0'
486 518 Invoking status precommit hook
487 519 A a
488 520
489 521 check messages when no remote repository is specified:
490 522 "no remote repo" route for "hg outgoing --large" is not tested here,
491 523 because it can't be reproduced easily.
492 524
493 525 $ hg init clone1
494 526 $ hg -R clone1 -q pull src
495 527 $ hg -R clone1 -q update
496 528 $ hg -R clone1 paths | grep default
497 529 [1]
498 530
499 531 $ hg -R clone1 summary --large
500 532 parent: 0:fc0bd45326d3 tip
501 533 #0
502 534 branch: default
503 535 commit: (clean)
504 536 update: (current)
505 537 largefiles: (no remote repo)
506 538
507 539 check messages when there is no files to upload:
508 540
509 541 $ hg -q clone src clone2
510 542 $ hg -R clone2 paths | grep default
511 543 default = $TESTTMP/issue3651/src (glob)
512 544
513 545 $ hg -R clone2 summary --large
514 546 parent: 0:fc0bd45326d3 tip
515 547 #0
516 548 branch: default
517 549 commit: (clean)
518 550 update: (current)
519 551 largefiles: (no files to upload)
520 552 $ hg -R clone2 outgoing --large
521 553 comparing with $TESTTMP/issue3651/src (glob)
522 554 searching for changes
523 555 no changes found
524 556 largefiles: no files to upload
525 557 [1]
526 558
527 559 $ hg -R clone2 outgoing --large --graph --template "{rev}"
528 560 comparing with $TESTTMP/issue3651/src (glob)
529 561 searching for changes
530 562 no changes found
531 563 largefiles: no files to upload
532 564
533 565 check messages when there are files to upload:
534 566
535 567 $ echo b > clone2/b
536 568 $ hg -R clone2 add --large clone2/b
537 569 $ hg -R clone2 commit -m '#1'
538 570 Invoking status precommit hook
539 571 A b
540 572 $ hg -R clone2 summary --large
541 573 parent: 1:1acbe71ce432 tip
542 574 #1
543 575 branch: default
544 576 commit: (clean)
545 577 update: (current)
546 578 largefiles: 1 entities for 1 files to upload
547 579 $ hg -R clone2 outgoing --large
548 580 comparing with $TESTTMP/issue3651/src (glob)
549 581 searching for changes
550 582 changeset: 1:1acbe71ce432
551 583 tag: tip
552 584 user: test
553 585 date: Thu Jan 01 00:00:00 1970 +0000
554 586 summary: #1
555 587
556 588 largefiles to upload (1 entities):
557 589 b
558 590
559 591 $ hg -R clone2 outgoing --large --graph --template "{rev}"
560 592 comparing with $TESTTMP/issue3651/src (glob)
561 593 searching for changes
562 594 @ 1
563 595
564 596 largefiles to upload (1 entities):
565 597 b
566 598
567 599
568 600 $ cp clone2/b clone2/b1
569 601 $ cp clone2/b clone2/b2
570 602 $ hg -R clone2 add --large clone2/b1 clone2/b2
571 603 $ hg -R clone2 commit -m '#2: add largefiles referring same entity'
572 604 Invoking status precommit hook
573 605 A b1
574 606 A b2
575 607 $ hg -R clone2 summary --large
576 608 parent: 2:6095d0695d70 tip
577 609 #2: add largefiles referring same entity
578 610 branch: default
579 611 commit: (clean)
580 612 update: (current)
581 613 largefiles: 1 entities for 3 files to upload
582 614 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n"
583 615 comparing with $TESTTMP/issue3651/src (glob)
584 616 searching for changes
585 617 1:1acbe71ce432
586 618 2:6095d0695d70
587 619 largefiles to upload (1 entities):
588 620 b
589 621 b1
590 622 b2
591 623
592 624 $ hg -R clone2 cat -r 1 clone2/.hglf/b
593 625 89e6c98d92887913cadf06b2adb97f26cde4849b
594 626 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n" --debug
595 627 comparing with $TESTTMP/issue3651/src (glob)
596 628 query 1; heads
597 629 searching for changes
598 630 all remote heads known locally
599 631 1:1acbe71ce432
600 632 2:6095d0695d70
601 633 finding outgoing largefiles: 0/2 revision (0.00%)
602 634 finding outgoing largefiles: 1/2 revision (50.00%)
603 635 largefiles to upload (1 entities):
604 636 b
605 637 89e6c98d92887913cadf06b2adb97f26cde4849b
606 638 b1
607 639 89e6c98d92887913cadf06b2adb97f26cde4849b
608 640 b2
609 641 89e6c98d92887913cadf06b2adb97f26cde4849b
610 642
611 643
612 644 $ echo bbb > clone2/b
613 645 $ hg -R clone2 commit -m '#3: add new largefile entity as existing file'
614 646 Invoking status precommit hook
615 647 M b
616 648 $ echo bbbb > clone2/b
617 649 $ hg -R clone2 commit -m '#4: add new largefile entity as existing file'
618 650 Invoking status precommit hook
619 651 M b
620 652 $ cp clone2/b1 clone2/b
621 653 $ hg -R clone2 commit -m '#5: refer existing largefile entity again'
622 654 Invoking status precommit hook
623 655 M b
624 656 $ hg -R clone2 summary --large
625 657 parent: 5:036794ea641c tip
626 658 #5: refer existing largefile entity again
627 659 branch: default
628 660 commit: (clean)
629 661 update: (current)
630 662 largefiles: 3 entities for 3 files to upload
631 663 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n"
632 664 comparing with $TESTTMP/issue3651/src (glob)
633 665 searching for changes
634 666 1:1acbe71ce432
635 667 2:6095d0695d70
636 668 3:7983dce246cc
637 669 4:233f12ada4ae
638 670 5:036794ea641c
639 671 largefiles to upload (3 entities):
640 672 b
641 673 b1
642 674 b2
643 675
644 676 $ hg -R clone2 cat -r 3 clone2/.hglf/b
645 677 c801c9cfe94400963fcb683246217d5db77f9a9a
646 678 $ hg -R clone2 cat -r 4 clone2/.hglf/b
647 679 13f9ed0898e315bf59dc2973fec52037b6f441a2
648 680 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n" --debug
649 681 comparing with $TESTTMP/issue3651/src (glob)
650 682 query 1; heads
651 683 searching for changes
652 684 all remote heads known locally
653 685 1:1acbe71ce432
654 686 2:6095d0695d70
655 687 3:7983dce246cc
656 688 4:233f12ada4ae
657 689 5:036794ea641c
658 690 finding outgoing largefiles: 0/5 revision (0.00%)
659 691 finding outgoing largefiles: 1/5 revision (20.00%)
660 692 finding outgoing largefiles: 2/5 revision (40.00%)
661 693 finding outgoing largefiles: 3/5 revision (60.00%)
662 694 finding outgoing largefiles: 4/5 revision (80.00%)
663 695 largefiles to upload (3 entities):
664 696 b
665 697 13f9ed0898e315bf59dc2973fec52037b6f441a2
666 698 89e6c98d92887913cadf06b2adb97f26cde4849b
667 699 c801c9cfe94400963fcb683246217d5db77f9a9a
668 700 b1
669 701 89e6c98d92887913cadf06b2adb97f26cde4849b
670 702 b2
671 703 89e6c98d92887913cadf06b2adb97f26cde4849b
672 704
673 705
674 706 Pushing revision #1 causes uploading entity 89e6c98d9288, which is
675 707 shared also by largefiles b1, b2 in revision #2 and b in revision #5.
676 708
677 709 Then, entity 89e6c98d9288 is not treated as "outgoing entity" at "hg
678 710 summary" and "hg outgoing", even though files in outgoing revision #2
679 711 and #5 refer it.
680 712
681 713 $ hg -R clone2 push -r 1 -q
682 714 $ hg -R clone2 summary --large
683 715 parent: 5:036794ea641c tip
684 716 #5: refer existing largefile entity again
685 717 branch: default
686 718 commit: (clean)
687 719 update: (current)
688 720 largefiles: 2 entities for 1 files to upload
689 721 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n"
690 722 comparing with $TESTTMP/issue3651/src (glob)
691 723 searching for changes
692 724 2:6095d0695d70
693 725 3:7983dce246cc
694 726 4:233f12ada4ae
695 727 5:036794ea641c
696 728 largefiles to upload (2 entities):
697 729 b
698 730
699 731 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n" --debug
700 732 comparing with $TESTTMP/issue3651/src (glob)
701 733 query 1; heads
702 734 searching for changes
703 735 all remote heads known locally
704 736 2:6095d0695d70
705 737 3:7983dce246cc
706 738 4:233f12ada4ae
707 739 5:036794ea641c
708 740 finding outgoing largefiles: 0/4 revision (0.00%)
709 741 finding outgoing largefiles: 1/4 revision (25.00%)
710 742 finding outgoing largefiles: 2/4 revision (50.00%)
711 743 finding outgoing largefiles: 3/4 revision (75.00%)
712 744 largefiles to upload (2 entities):
713 745 b
714 746 13f9ed0898e315bf59dc2973fec52037b6f441a2
715 747 c801c9cfe94400963fcb683246217d5db77f9a9a
716 748
717 749
718 750 $ cd ..
719 751
720 752 merge action 'd' for 'local renamed directory to d2/g' which has no filename
721 753 ==================================================================================
722 754
723 755 $ hg init merge-action
724 756 $ cd merge-action
725 757 $ touch l
726 758 $ hg add --large l
727 759 $ mkdir d1
728 760 $ touch d1/f
729 761 $ hg ci -Aqm0
730 762 Invoking status precommit hook
731 763 A d1/f
732 764 A l
733 765 $ echo > d1/f
734 766 $ touch d1/g
735 767 $ hg ci -Aqm1
736 768 Invoking status precommit hook
737 769 M d1/f
738 770 A d1/g
739 771 $ hg up -qr0
740 772 $ hg mv d1 d2
741 773 moving d1/f to d2/f (glob)
742 774 $ hg ci -qm2
743 775 Invoking status precommit hook
744 776 A d2/f
745 777 R d1/f
746 778 $ hg merge
747 779 merging d2/f and d1/f to d2/f
748 780 getting changed largefiles
749 781 0 largefiles updated, 0 removed
750 782 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
751 783 (branch merge, don't forget to commit)
752 784 $ cd ..
753 785
754 786
755 787 Merge conflicts:
756 788 =====================
757 789
758 790 $ hg init merge
759 791 $ cd merge
760 792 $ echo 0 > f-different
761 793 $ echo 0 > f-same
762 794 $ echo 0 > f-unchanged-1
763 795 $ echo 0 > f-unchanged-2
764 796 $ hg add --large *
765 797 $ hg ci -m0
766 798 Invoking status precommit hook
767 799 A f-different
768 800 A f-same
769 801 A f-unchanged-1
770 802 A f-unchanged-2
771 803 $ echo tmp1 > f-unchanged-1
772 804 $ echo tmp1 > f-unchanged-2
773 805 $ echo tmp1 > f-same
774 806 $ hg ci -m1
775 807 Invoking status precommit hook
776 808 M f-same
777 809 M f-unchanged-1
778 810 M f-unchanged-2
779 811 $ echo 2 > f-different
780 812 $ echo 0 > f-unchanged-1
781 813 $ echo 1 > f-unchanged-2
782 814 $ echo 1 > f-same
783 815 $ hg ci -m2
784 816 Invoking status precommit hook
785 817 M f-different
786 818 M f-same
787 819 M f-unchanged-1
788 820 M f-unchanged-2
789 821 $ hg up -qr0
790 822 $ echo tmp2 > f-unchanged-1
791 823 $ echo tmp2 > f-unchanged-2
792 824 $ echo tmp2 > f-same
793 825 $ hg ci -m3
794 826 Invoking status precommit hook
795 827 M f-same
796 828 M f-unchanged-1
797 829 M f-unchanged-2
798 830 created new head
799 831 $ echo 1 > f-different
800 832 $ echo 1 > f-unchanged-1
801 833 $ echo 0 > f-unchanged-2
802 834 $ echo 1 > f-same
803 835 $ hg ci -m4
804 836 Invoking status precommit hook
805 837 M f-different
806 838 M f-same
807 839 M f-unchanged-1
808 840 M f-unchanged-2
809 841 $ hg merge
810 842 largefile f-different has a merge conflict
811 843 ancestor was 09d2af8dd22201dd8d48e5dcfcaed281ff9422c7
812 844 keep (l)ocal e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e or
813 845 take (o)ther 7448d8798a4380162d4b56f9b452e2f6f9e24e7a? l
814 846 getting changed largefiles
815 847 1 largefiles updated, 0 removed
816 848 0 files updated, 4 files merged, 0 files removed, 0 files unresolved
817 849 (branch merge, don't forget to commit)
818 850 $ cat f-different
819 851 1
820 852 $ cat f-same
821 853 1
822 854 $ cat f-unchanged-1
823 855 1
824 856 $ cat f-unchanged-2
825 857 1
826 858 $ cd ..
827 859
828 860 Test largefile insulation (do not enabled a side effect
829 861 ========================================================
830 862
831 863 Check whether "largefiles" feature is supported only in repositories
832 864 enabling largefiles extension.
833 865
834 866 $ mkdir individualenabling
835 867 $ cd individualenabling
836 868
837 869 $ hg init enabledlocally
838 870 $ echo large > enabledlocally/large
839 871 $ hg -R enabledlocally add --large enabledlocally/large
840 872 $ hg -R enabledlocally commit -m '#0'
841 873 Invoking status precommit hook
842 874 A large
843 875
844 876 $ hg init notenabledlocally
845 877 $ echo large > notenabledlocally/large
846 878 $ hg -R notenabledlocally add --large notenabledlocally/large
847 879 $ hg -R notenabledlocally commit -m '#0'
848 880 Invoking status precommit hook
849 881 A large
850 882
851 883 $ cat >> $HGRCPATH <<EOF
852 884 > [extensions]
853 885 > # disable globally
854 886 > largefiles=!
855 887 > EOF
856 888 $ cat >> enabledlocally/.hg/hgrc <<EOF
857 889 > [extensions]
858 890 > # enable locally
859 891 > largefiles=
860 892 > EOF
861 893 $ hg -R enabledlocally root
862 894 $TESTTMP/individualenabling/enabledlocally (glob)
863 895 $ hg -R notenabledlocally root
864 896 abort: repository requires features unknown to this Mercurial: largefiles!
865 897 (see http://mercurial.selenic.com/wiki/MissingRequirement for more information)
866 898 [255]
867 899
868 900 $ hg init push-dst
869 901 $ hg -R enabledlocally push push-dst
870 902 pushing to push-dst
871 903 abort: required features are not supported in the destination: largefiles
872 904 [255]
873 905
874 906 $ hg init pull-src
875 907 $ hg -R pull-src pull enabledlocally
876 908 pulling from enabledlocally
877 909 abort: required features are not supported in the destination: largefiles
878 910 [255]
879 911
880 912 $ hg clone enabledlocally clone-dst
881 913 abort: repository requires features unknown to this Mercurial: largefiles!
882 914 (see http://mercurial.selenic.com/wiki/MissingRequirement for more information)
883 915 [255]
884 916 $ test -d clone-dst
885 917 [1]
886 918 $ hg clone --pull enabledlocally clone-pull-dst
887 919 abort: required features are not supported in the destination: largefiles
888 920 [255]
889 921 $ test -d clone-pull-dst
890 922 [1]
891 923
892 924 #if serve
893 925
894 926 Test largefiles specific peer setup, when largefiles is enabled
895 927 locally (issue4109)
896 928
897 929 $ hg showconfig extensions | grep largefiles
898 930 extensions.largefiles=!
899 931 $ mkdir -p $TESTTMP/individualenabling/usercache
900 932
901 933 $ hg serve -R enabledlocally -d -p $HGPORT --pid-file hg.pid
902 934 $ cat hg.pid >> $DAEMON_PIDS
903 935
904 936 $ hg init pull-dst
905 937 $ cat > pull-dst/.hg/hgrc <<EOF
906 938 > [extensions]
907 939 > # enable locally
908 940 > largefiles=
909 941 > [largefiles]
910 942 > # ignore system cache to force largefiles specific wire proto access
911 943 > usercache=$TESTTMP/individualenabling/usercache
912 944 > EOF
913 945 $ hg -R pull-dst -q pull -u http://localhost:$HGPORT
914 946
915 947 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
916 948 #endif
917 949
918 950 Test overridden functions work correctly even for repos disabling
919 951 largefiles (issue4547)
920 952
921 953 $ hg showconfig extensions | grep largefiles
922 954 extensions.largefiles=!
923 955
924 956 (test updating implied by clone)
925 957
926 958 $ hg init enabled-but-no-largefiles
927 959 $ echo normal1 > enabled-but-no-largefiles/normal1
928 960 $ hg -R enabled-but-no-largefiles add enabled-but-no-largefiles/normal1
929 961 $ hg -R enabled-but-no-largefiles commit -m '#0@enabled-but-no-largefiles'
930 962 Invoking status precommit hook
931 963 A normal1
932 964 $ cat >> enabled-but-no-largefiles/.hg/hgrc <<EOF
933 965 > [extensions]
934 966 > # enable locally
935 967 > largefiles=
936 968 > EOF
937 969 $ hg clone -q enabled-but-no-largefiles no-largefiles
938 970
939 971 (test rebasing implied by pull: precommit while rebasing unexpectedly
940 972 shows "normal3" as "?", because lfdirstate isn't yet written out at
941 973 that time)
942 974
943 975 $ echo normal2 > enabled-but-no-largefiles/normal2
944 976 $ hg -R enabled-but-no-largefiles add enabled-but-no-largefiles/normal2
945 977 $ hg -R enabled-but-no-largefiles commit -m '#1@enabled-but-no-largefiles'
946 978 Invoking status precommit hook
947 979 A normal2
948 980
949 981 $ echo normal3 > no-largefiles/normal3
950 982 $ hg -R no-largefiles add no-largefiles/normal3
951 983 $ hg -R no-largefiles commit -m '#1@no-largefiles'
952 984 Invoking status precommit hook
953 985 A normal3
954 986
955 987 $ hg -R no-largefiles -q pull --rebase
956 988 Invoking status precommit hook
957 989 ? normal3
958 990
959 991 (test reverting)
960 992
961 993 $ hg init subrepo-root
962 994 $ cat >> subrepo-root/.hg/hgrc <<EOF
963 995 > [extensions]
964 996 > # enable locally
965 997 > largefiles=
966 998 > EOF
967 999 $ echo large > subrepo-root/large
968 1000 $ hg -R subrepo-root add --large subrepo-root/large
969 1001 $ hg clone -q no-largefiles subrepo-root/no-largefiles
970 1002 $ cat > subrepo-root/.hgsub <<EOF
971 1003 > no-largefiles = no-largefiles
972 1004 > EOF
973 1005 $ hg -R subrepo-root add subrepo-root/.hgsub
974 1006 $ hg -R subrepo-root commit -m '#0'
975 1007 Invoking status precommit hook
976 1008 A .hgsub
977 1009 A large
978 1010 ? .hgsubstate
979 1011 $ echo dirty >> subrepo-root/large
980 1012 $ echo dirty >> subrepo-root/no-largefiles/normal1
981 1013 $ hg -R subrepo-root status -S
982 1014 M large
983 1015 M no-largefiles/normal1
984 1016 $ hg -R subrepo-root revert --all
985 1017 reverting subrepo-root/.hglf/large (glob)
986 1018 reverting subrepo no-largefiles
987 1019 reverting subrepo-root/no-largefiles/normal1 (glob)
988 1020
989 1021 $ cd ..
990 1022
991 1023
992 1024 Test "pull --rebase" when rebase is enabled before largefiles (issue3861)
993 1025 =========================================================================
994 1026
995 1027 $ hg showconfig extensions | grep largefiles
996 1028 extensions.largefiles=!
997 1029
998 1030 $ mkdir issue3861
999 1031 $ cd issue3861
1000 1032 $ hg init src
1001 1033 $ hg clone -q src dst
1002 1034 $ echo a > src/a
1003 1035 $ hg -R src commit -Aqm "#0"
1004 1036 Invoking status precommit hook
1005 1037 A a
1006 1038
1007 1039 $ cat >> dst/.hg/hgrc <<EOF
1008 1040 > [extensions]
1009 1041 > largefiles=
1010 1042 > EOF
1011 1043 $ hg -R dst pull --rebase
1012 1044 pulling from $TESTTMP/issue3861/src (glob)
1013 1045 requesting all changes
1014 1046 adding changesets
1015 1047 adding manifests
1016 1048 adding file changes
1017 1049 added 1 changesets with 1 changes to 1 files
1018 1050 nothing to rebase - working directory parent is already an ancestor of destination bf5e395ced2c
1019 1051 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1020 1052
1021 1053 $ cd ..
@@ -1,1972 +1,1994
1 1 Log on empty repository: checking consistency
2 2
3 3 $ hg init empty
4 4 $ cd empty
5 5 $ hg log
6 6 $ hg log -r 1
7 7 abort: unknown revision '1'!
8 8 [255]
9 9 $ hg log -r -1:0
10 10 abort: unknown revision '-1'!
11 11 [255]
12 12 $ hg log -r 'branch(name)'
13 13 abort: unknown revision 'name'!
14 14 [255]
15 15 $ hg log -r null -q
16 16 -1:000000000000
17 17
18 18 The g is crafted to have 2 filelog topological heads in a linear
19 19 changeset graph
20 20
21 21 $ hg init a
22 22 $ cd a
23 23 $ echo a > a
24 24 $ echo f > f
25 25 $ hg ci -Ama -d '1 0'
26 26 adding a
27 27 adding f
28 28
29 29 $ hg cp a b
30 30 $ hg cp f g
31 31 $ hg ci -mb -d '2 0'
32 32
33 33 $ mkdir dir
34 34 $ hg mv b dir
35 35 $ echo g >> g
36 36 $ echo f >> f
37 37 $ hg ci -mc -d '3 0'
38 38
39 39 $ hg mv a b
40 40 $ hg cp -f f g
41 41 $ echo a > d
42 42 $ hg add d
43 43 $ hg ci -md -d '4 0'
44 44
45 45 $ hg mv dir/b e
46 46 $ hg ci -me -d '5 0'
47 47
48 48 Make sure largefiles doesn't interfere with logging a regular file
49 49 $ hg log a --config extensions.largefiles=
50 50 changeset: 0:9161b9aeaf16
51 51 user: test
52 52 date: Thu Jan 01 00:00:01 1970 +0000
53 53 summary: a
54 54
55 55 $ hg log a
56 56 changeset: 0:9161b9aeaf16
57 57 user: test
58 58 date: Thu Jan 01 00:00:01 1970 +0000
59 59 summary: a
60 60
61 $ hg log glob:a*
62 changeset: 3:2ca5ba701980
63 user: test
64 date: Thu Jan 01 00:00:04 1970 +0000
65 summary: d
66
67 changeset: 0:9161b9aeaf16
68 user: test
69 date: Thu Jan 01 00:00:01 1970 +0000
70 summary: a
71
72 $ hg log glob:a* --config extensions.largefiles=
73 changeset: 3:2ca5ba701980
74 user: test
75 date: Thu Jan 01 00:00:04 1970 +0000
76 summary: d
77
78 changeset: 0:9161b9aeaf16
79 user: test
80 date: Thu Jan 01 00:00:01 1970 +0000
81 summary: a
82
61 83 log on directory
62 84
63 85 $ hg log dir
64 86 changeset: 4:7e4639b4691b
65 87 tag: tip
66 88 user: test
67 89 date: Thu Jan 01 00:00:05 1970 +0000
68 90 summary: e
69 91
70 92 changeset: 2:f8954cd4dc1f
71 93 user: test
72 94 date: Thu Jan 01 00:00:03 1970 +0000
73 95 summary: c
74 96
75 97 $ hg log somethingthatdoesntexist dir
76 98 changeset: 4:7e4639b4691b
77 99 tag: tip
78 100 user: test
79 101 date: Thu Jan 01 00:00:05 1970 +0000
80 102 summary: e
81 103
82 104 changeset: 2:f8954cd4dc1f
83 105 user: test
84 106 date: Thu Jan 01 00:00:03 1970 +0000
85 107 summary: c
86 108
87 109
88 110 -f, non-existent directory
89 111
90 112 $ hg log -f dir
91 113 abort: cannot follow file not in parent revision: "dir"
92 114 [255]
93 115
94 116 -f, directory
95 117
96 118 $ hg up -q 3
97 119 $ hg log -f dir
98 120 changeset: 2:f8954cd4dc1f
99 121 user: test
100 122 date: Thu Jan 01 00:00:03 1970 +0000
101 123 summary: c
102 124
103 125 -f, directory with --patch
104 126
105 127 $ hg log -f dir -p
106 128 changeset: 2:f8954cd4dc1f
107 129 user: test
108 130 date: Thu Jan 01 00:00:03 1970 +0000
109 131 summary: c
110 132
111 133 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
112 134 --- /dev/null* (glob)
113 135 +++ b/dir/b* (glob)
114 136 @@ -0,0 +1,1 @@
115 137 +a
116 138
117 139
118 140 -f, pattern
119 141
120 142 $ hg log -f -I 'dir**' -p
121 143 changeset: 2:f8954cd4dc1f
122 144 user: test
123 145 date: Thu Jan 01 00:00:03 1970 +0000
124 146 summary: c
125 147
126 148 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
127 149 --- /dev/null* (glob)
128 150 +++ b/dir/b* (glob)
129 151 @@ -0,0 +1,1 @@
130 152 +a
131 153
132 154 $ hg up -q 4
133 155
134 156 -f, a wrong style
135 157
136 158 $ hg log -f -l1 --style something
137 159 abort: style 'something' not found
138 160 (available styles: bisect, changelog, compact, default, phases, xml)
139 161 [255]
140 162
141 163 -f, phases style
142 164
143 165
144 166 $ hg log -f -l1 --style phases
145 167 changeset: 4:7e4639b4691b
146 168 tag: tip
147 169 phase: draft
148 170 user: test
149 171 date: Thu Jan 01 00:00:05 1970 +0000
150 172 summary: e
151 173
152 174
153 175 -f, but no args
154 176
155 177 $ hg log -f
156 178 changeset: 4:7e4639b4691b
157 179 tag: tip
158 180 user: test
159 181 date: Thu Jan 01 00:00:05 1970 +0000
160 182 summary: e
161 183
162 184 changeset: 3:2ca5ba701980
163 185 user: test
164 186 date: Thu Jan 01 00:00:04 1970 +0000
165 187 summary: d
166 188
167 189 changeset: 2:f8954cd4dc1f
168 190 user: test
169 191 date: Thu Jan 01 00:00:03 1970 +0000
170 192 summary: c
171 193
172 194 changeset: 1:d89b0a12d229
173 195 user: test
174 196 date: Thu Jan 01 00:00:02 1970 +0000
175 197 summary: b
176 198
177 199 changeset: 0:9161b9aeaf16
178 200 user: test
179 201 date: Thu Jan 01 00:00:01 1970 +0000
180 202 summary: a
181 203
182 204
183 205 one rename
184 206
185 207 $ hg up -q 2
186 208 $ hg log -vf a
187 209 changeset: 0:9161b9aeaf16
188 210 user: test
189 211 date: Thu Jan 01 00:00:01 1970 +0000
190 212 files: a f
191 213 description:
192 214 a
193 215
194 216
195 217
196 218 many renames
197 219
198 220 $ hg up -q tip
199 221 $ hg log -vf e
200 222 changeset: 4:7e4639b4691b
201 223 tag: tip
202 224 user: test
203 225 date: Thu Jan 01 00:00:05 1970 +0000
204 226 files: dir/b e
205 227 description:
206 228 e
207 229
208 230
209 231 changeset: 2:f8954cd4dc1f
210 232 user: test
211 233 date: Thu Jan 01 00:00:03 1970 +0000
212 234 files: b dir/b f g
213 235 description:
214 236 c
215 237
216 238
217 239 changeset: 1:d89b0a12d229
218 240 user: test
219 241 date: Thu Jan 01 00:00:02 1970 +0000
220 242 files: b g
221 243 description:
222 244 b
223 245
224 246
225 247 changeset: 0:9161b9aeaf16
226 248 user: test
227 249 date: Thu Jan 01 00:00:01 1970 +0000
228 250 files: a f
229 251 description:
230 252 a
231 253
232 254
233 255
234 256
235 257 log -pf dir/b
236 258
237 259 $ hg up -q 3
238 260 $ hg log -pf dir/b
239 261 changeset: 2:f8954cd4dc1f
240 262 user: test
241 263 date: Thu Jan 01 00:00:03 1970 +0000
242 264 summary: c
243 265
244 266 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
245 267 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
246 268 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
247 269 @@ -0,0 +1,1 @@
248 270 +a
249 271
250 272 changeset: 1:d89b0a12d229
251 273 user: test
252 274 date: Thu Jan 01 00:00:02 1970 +0000
253 275 summary: b
254 276
255 277 diff -r 9161b9aeaf16 -r d89b0a12d229 b
256 278 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
257 279 +++ b/b Thu Jan 01 00:00:02 1970 +0000
258 280 @@ -0,0 +1,1 @@
259 281 +a
260 282
261 283 changeset: 0:9161b9aeaf16
262 284 user: test
263 285 date: Thu Jan 01 00:00:01 1970 +0000
264 286 summary: a
265 287
266 288 diff -r 000000000000 -r 9161b9aeaf16 a
267 289 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
268 290 +++ b/a Thu Jan 01 00:00:01 1970 +0000
269 291 @@ -0,0 +1,1 @@
270 292 +a
271 293
272 294
273 295 log -pf b inside dir
274 296
275 297 $ hg --cwd=dir log -pf b
276 298 changeset: 2:f8954cd4dc1f
277 299 user: test
278 300 date: Thu Jan 01 00:00:03 1970 +0000
279 301 summary: c
280 302
281 303 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
282 304 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
283 305 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
284 306 @@ -0,0 +1,1 @@
285 307 +a
286 308
287 309 changeset: 1:d89b0a12d229
288 310 user: test
289 311 date: Thu Jan 01 00:00:02 1970 +0000
290 312 summary: b
291 313
292 314 diff -r 9161b9aeaf16 -r d89b0a12d229 b
293 315 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
294 316 +++ b/b Thu Jan 01 00:00:02 1970 +0000
295 317 @@ -0,0 +1,1 @@
296 318 +a
297 319
298 320 changeset: 0:9161b9aeaf16
299 321 user: test
300 322 date: Thu Jan 01 00:00:01 1970 +0000
301 323 summary: a
302 324
303 325 diff -r 000000000000 -r 9161b9aeaf16 a
304 326 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
305 327 +++ b/a Thu Jan 01 00:00:01 1970 +0000
306 328 @@ -0,0 +1,1 @@
307 329 +a
308 330
309 331
310 332 log -pf, but no args
311 333
312 334 $ hg log -pf
313 335 changeset: 3:2ca5ba701980
314 336 user: test
315 337 date: Thu Jan 01 00:00:04 1970 +0000
316 338 summary: d
317 339
318 340 diff -r f8954cd4dc1f -r 2ca5ba701980 a
319 341 --- a/a Thu Jan 01 00:00:03 1970 +0000
320 342 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
321 343 @@ -1,1 +0,0 @@
322 344 -a
323 345 diff -r f8954cd4dc1f -r 2ca5ba701980 b
324 346 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
325 347 +++ b/b Thu Jan 01 00:00:04 1970 +0000
326 348 @@ -0,0 +1,1 @@
327 349 +a
328 350 diff -r f8954cd4dc1f -r 2ca5ba701980 d
329 351 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
330 352 +++ b/d Thu Jan 01 00:00:04 1970 +0000
331 353 @@ -0,0 +1,1 @@
332 354 +a
333 355 diff -r f8954cd4dc1f -r 2ca5ba701980 g
334 356 --- a/g Thu Jan 01 00:00:03 1970 +0000
335 357 +++ b/g Thu Jan 01 00:00:04 1970 +0000
336 358 @@ -1,2 +1,2 @@
337 359 f
338 360 -g
339 361 +f
340 362
341 363 changeset: 2:f8954cd4dc1f
342 364 user: test
343 365 date: Thu Jan 01 00:00:03 1970 +0000
344 366 summary: c
345 367
346 368 diff -r d89b0a12d229 -r f8954cd4dc1f b
347 369 --- a/b Thu Jan 01 00:00:02 1970 +0000
348 370 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
349 371 @@ -1,1 +0,0 @@
350 372 -a
351 373 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
352 374 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
353 375 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
354 376 @@ -0,0 +1,1 @@
355 377 +a
356 378 diff -r d89b0a12d229 -r f8954cd4dc1f f
357 379 --- a/f Thu Jan 01 00:00:02 1970 +0000
358 380 +++ b/f Thu Jan 01 00:00:03 1970 +0000
359 381 @@ -1,1 +1,2 @@
360 382 f
361 383 +f
362 384 diff -r d89b0a12d229 -r f8954cd4dc1f g
363 385 --- a/g Thu Jan 01 00:00:02 1970 +0000
364 386 +++ b/g Thu Jan 01 00:00:03 1970 +0000
365 387 @@ -1,1 +1,2 @@
366 388 f
367 389 +g
368 390
369 391 changeset: 1:d89b0a12d229
370 392 user: test
371 393 date: Thu Jan 01 00:00:02 1970 +0000
372 394 summary: b
373 395
374 396 diff -r 9161b9aeaf16 -r d89b0a12d229 b
375 397 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
376 398 +++ b/b Thu Jan 01 00:00:02 1970 +0000
377 399 @@ -0,0 +1,1 @@
378 400 +a
379 401 diff -r 9161b9aeaf16 -r d89b0a12d229 g
380 402 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
381 403 +++ b/g Thu Jan 01 00:00:02 1970 +0000
382 404 @@ -0,0 +1,1 @@
383 405 +f
384 406
385 407 changeset: 0:9161b9aeaf16
386 408 user: test
387 409 date: Thu Jan 01 00:00:01 1970 +0000
388 410 summary: a
389 411
390 412 diff -r 000000000000 -r 9161b9aeaf16 a
391 413 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
392 414 +++ b/a Thu Jan 01 00:00:01 1970 +0000
393 415 @@ -0,0 +1,1 @@
394 416 +a
395 417 diff -r 000000000000 -r 9161b9aeaf16 f
396 418 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
397 419 +++ b/f Thu Jan 01 00:00:01 1970 +0000
398 420 @@ -0,0 +1,1 @@
399 421 +f
400 422
401 423
402 424 log -vf dir/b
403 425
404 426 $ hg log -vf dir/b
405 427 changeset: 2:f8954cd4dc1f
406 428 user: test
407 429 date: Thu Jan 01 00:00:03 1970 +0000
408 430 files: b dir/b f g
409 431 description:
410 432 c
411 433
412 434
413 435 changeset: 1:d89b0a12d229
414 436 user: test
415 437 date: Thu Jan 01 00:00:02 1970 +0000
416 438 files: b g
417 439 description:
418 440 b
419 441
420 442
421 443 changeset: 0:9161b9aeaf16
422 444 user: test
423 445 date: Thu Jan 01 00:00:01 1970 +0000
424 446 files: a f
425 447 description:
426 448 a
427 449
428 450
429 451
430 452
431 453 -f and multiple filelog heads
432 454
433 455 $ hg up -q 2
434 456 $ hg log -f g --template '{rev}\n'
435 457 2
436 458 1
437 459 0
438 460 $ hg up -q tip
439 461 $ hg log -f g --template '{rev}\n'
440 462 3
441 463 2
442 464 0
443 465
444 466
445 467 log copies with --copies
446 468
447 469 $ hg log -vC --template '{rev} {file_copies}\n'
448 470 4 e (dir/b)
449 471 3 b (a)g (f)
450 472 2 dir/b (b)
451 473 1 b (a)g (f)
452 474 0
453 475
454 476 log copies switch without --copies, with old filecopy template
455 477
456 478 $ hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
457 479 4
458 480 3
459 481 2
460 482 1
461 483 0
462 484
463 485 log copies switch with --copies
464 486
465 487 $ hg log -vC --template '{rev} {file_copies_switch}\n'
466 488 4 e (dir/b)
467 489 3 b (a)g (f)
468 490 2 dir/b (b)
469 491 1 b (a)g (f)
470 492 0
471 493
472 494
473 495 log copies with hardcoded style and with --style=default
474 496
475 497 $ hg log -vC -r4
476 498 changeset: 4:7e4639b4691b
477 499 tag: tip
478 500 user: test
479 501 date: Thu Jan 01 00:00:05 1970 +0000
480 502 files: dir/b e
481 503 copies: e (dir/b)
482 504 description:
483 505 e
484 506
485 507
486 508 $ hg log -vC -r4 --style=default
487 509 changeset: 4:7e4639b4691b
488 510 tag: tip
489 511 user: test
490 512 date: Thu Jan 01 00:00:05 1970 +0000
491 513 files: dir/b e
492 514 copies: e (dir/b)
493 515 description:
494 516 e
495 517
496 518
497 519 $ hg log -vC -r4 -Tjson
498 520 [
499 521 {
500 522 "rev": 4,
501 523 "node": "7e4639b4691b9f84b81036a8d4fb218ce3c5e3a3",
502 524 "branch": "default",
503 525 "phase": "draft",
504 526 "user": "test",
505 527 "date": [5, 0],
506 528 "desc": "e",
507 529 "bookmarks": [],
508 530 "tags": ["tip"],
509 531 "parents": ["2ca5ba7019804f1f597249caddf22a64d34df0ba"],
510 532 "files": ["dir/b", "e"],
511 533 "copies": {"e": "dir/b"}
512 534 }
513 535 ]
514 536
515 537 log copies, non-linear manifest
516 538
517 539 $ hg up -C 3
518 540 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
519 541 $ hg mv dir/b e
520 542 $ echo foo > foo
521 543 $ hg ci -Ame2 -d '6 0'
522 544 adding foo
523 545 created new head
524 546 $ hg log -v --template '{rev} {file_copies}\n' -r 5
525 547 5 e (dir/b)
526 548
527 549
528 550 log copies, execute bit set
529 551
530 552 #if execbit
531 553 $ chmod +x e
532 554 $ hg ci -me3 -d '7 0'
533 555 $ hg log -v --template '{rev} {file_copies}\n' -r 6
534 556 6
535 557 #endif
536 558
537 559
538 560 log -p d
539 561
540 562 $ hg log -pv d
541 563 changeset: 3:2ca5ba701980
542 564 user: test
543 565 date: Thu Jan 01 00:00:04 1970 +0000
544 566 files: a b d g
545 567 description:
546 568 d
547 569
548 570
549 571 diff -r f8954cd4dc1f -r 2ca5ba701980 d
550 572 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
551 573 +++ b/d Thu Jan 01 00:00:04 1970 +0000
552 574 @@ -0,0 +1,1 @@
553 575 +a
554 576
555 577
556 578
557 579 log --removed file
558 580
559 581 $ hg log --removed -v a
560 582 changeset: 3:2ca5ba701980
561 583 user: test
562 584 date: Thu Jan 01 00:00:04 1970 +0000
563 585 files: a b d g
564 586 description:
565 587 d
566 588
567 589
568 590 changeset: 0:9161b9aeaf16
569 591 user: test
570 592 date: Thu Jan 01 00:00:01 1970 +0000
571 593 files: a f
572 594 description:
573 595 a
574 596
575 597
576 598
577 599 log --removed revrange file
578 600
579 601 $ hg log --removed -v -r0:2 a
580 602 changeset: 0:9161b9aeaf16
581 603 user: test
582 604 date: Thu Jan 01 00:00:01 1970 +0000
583 605 files: a f
584 606 description:
585 607 a
586 608
587 609
588 610 $ cd ..
589 611
590 612 log --follow tests
591 613
592 614 $ hg init follow
593 615 $ cd follow
594 616
595 617 $ echo base > base
596 618 $ hg ci -Ambase -d '1 0'
597 619 adding base
598 620
599 621 $ echo r1 >> base
600 622 $ hg ci -Amr1 -d '1 0'
601 623 $ echo r2 >> base
602 624 $ hg ci -Amr2 -d '1 0'
603 625
604 626 $ hg up -C 1
605 627 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
606 628 $ echo b1 > b1
607 629 $ hg ci -Amb1 -d '1 0'
608 630 adding b1
609 631 created new head
610 632
611 633
612 634 log -f
613 635
614 636 $ hg log -f
615 637 changeset: 3:e62f78d544b4
616 638 tag: tip
617 639 parent: 1:3d5bf5654eda
618 640 user: test
619 641 date: Thu Jan 01 00:00:01 1970 +0000
620 642 summary: b1
621 643
622 644 changeset: 1:3d5bf5654eda
623 645 user: test
624 646 date: Thu Jan 01 00:00:01 1970 +0000
625 647 summary: r1
626 648
627 649 changeset: 0:67e992f2c4f3
628 650 user: test
629 651 date: Thu Jan 01 00:00:01 1970 +0000
630 652 summary: base
631 653
632 654
633 655
634 656 log -f -r '1 + 4'
635 657
636 658 $ hg up -C 0
637 659 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
638 660 $ echo b2 > b2
639 661 $ hg ci -Amb2 -d '1 0'
640 662 adding b2
641 663 created new head
642 664 $ hg log -f -r '1 + 4'
643 665 changeset: 4:ddb82e70d1a1
644 666 tag: tip
645 667 parent: 0:67e992f2c4f3
646 668 user: test
647 669 date: Thu Jan 01 00:00:01 1970 +0000
648 670 summary: b2
649 671
650 672 changeset: 1:3d5bf5654eda
651 673 user: test
652 674 date: Thu Jan 01 00:00:01 1970 +0000
653 675 summary: r1
654 676
655 677 changeset: 0:67e992f2c4f3
656 678 user: test
657 679 date: Thu Jan 01 00:00:01 1970 +0000
658 680 summary: base
659 681
660 682 log -f -r null
661 683
662 684 $ hg log -f -r null
663 685 changeset: -1:000000000000
664 686 user:
665 687 date: Thu Jan 01 00:00:00 1970 +0000
666 688
667 689 $ hg log -f -r null -G
668 690 o changeset: -1:000000000000
669 691 user:
670 692 date: Thu Jan 01 00:00:00 1970 +0000
671 693
672 694
673 695
674 696 log -f with null parent
675 697
676 698 $ hg up -C null
677 699 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
678 700 $ hg log -f
679 701
680 702
681 703 log -r . with two parents
682 704
683 705 $ hg up -C 3
684 706 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
685 707 $ hg merge tip
686 708 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
687 709 (branch merge, don't forget to commit)
688 710 $ hg log -r .
689 711 changeset: 3:e62f78d544b4
690 712 parent: 1:3d5bf5654eda
691 713 user: test
692 714 date: Thu Jan 01 00:00:01 1970 +0000
693 715 summary: b1
694 716
695 717
696 718
697 719 log -r . with one parent
698 720
699 721 $ hg ci -mm12 -d '1 0'
700 722 $ hg log -r .
701 723 changeset: 5:302e9dd6890d
702 724 tag: tip
703 725 parent: 3:e62f78d544b4
704 726 parent: 4:ddb82e70d1a1
705 727 user: test
706 728 date: Thu Jan 01 00:00:01 1970 +0000
707 729 summary: m12
708 730
709 731
710 732 $ echo postm >> b1
711 733 $ hg ci -Amb1.1 -d'1 0'
712 734
713 735
714 736 log --follow-first
715 737
716 738 $ hg log --follow-first
717 739 changeset: 6:2404bbcab562
718 740 tag: tip
719 741 user: test
720 742 date: Thu Jan 01 00:00:01 1970 +0000
721 743 summary: b1.1
722 744
723 745 changeset: 5:302e9dd6890d
724 746 parent: 3:e62f78d544b4
725 747 parent: 4:ddb82e70d1a1
726 748 user: test
727 749 date: Thu Jan 01 00:00:01 1970 +0000
728 750 summary: m12
729 751
730 752 changeset: 3:e62f78d544b4
731 753 parent: 1:3d5bf5654eda
732 754 user: test
733 755 date: Thu Jan 01 00:00:01 1970 +0000
734 756 summary: b1
735 757
736 758 changeset: 1:3d5bf5654eda
737 759 user: test
738 760 date: Thu Jan 01 00:00:01 1970 +0000
739 761 summary: r1
740 762
741 763 changeset: 0:67e992f2c4f3
742 764 user: test
743 765 date: Thu Jan 01 00:00:01 1970 +0000
744 766 summary: base
745 767
746 768
747 769
748 770 log -P 2
749 771
750 772 $ hg log -P 2
751 773 changeset: 6:2404bbcab562
752 774 tag: tip
753 775 user: test
754 776 date: Thu Jan 01 00:00:01 1970 +0000
755 777 summary: b1.1
756 778
757 779 changeset: 5:302e9dd6890d
758 780 parent: 3:e62f78d544b4
759 781 parent: 4:ddb82e70d1a1
760 782 user: test
761 783 date: Thu Jan 01 00:00:01 1970 +0000
762 784 summary: m12
763 785
764 786 changeset: 4:ddb82e70d1a1
765 787 parent: 0:67e992f2c4f3
766 788 user: test
767 789 date: Thu Jan 01 00:00:01 1970 +0000
768 790 summary: b2
769 791
770 792 changeset: 3:e62f78d544b4
771 793 parent: 1:3d5bf5654eda
772 794 user: test
773 795 date: Thu Jan 01 00:00:01 1970 +0000
774 796 summary: b1
775 797
776 798
777 799
778 800 log -r tip -p --git
779 801
780 802 $ hg log -r tip -p --git
781 803 changeset: 6:2404bbcab562
782 804 tag: tip
783 805 user: test
784 806 date: Thu Jan 01 00:00:01 1970 +0000
785 807 summary: b1.1
786 808
787 809 diff --git a/b1 b/b1
788 810 --- a/b1
789 811 +++ b/b1
790 812 @@ -1,1 +1,2 @@
791 813 b1
792 814 +postm
793 815
794 816
795 817
796 818 log -r ""
797 819
798 820 $ hg log -r ''
799 821 hg: parse error: empty query
800 822 [255]
801 823
802 824 log -r <some unknown node id>
803 825
804 826 $ hg log -r 1000000000000000000000000000000000000000
805 827 abort: unknown revision '1000000000000000000000000000000000000000'!
806 828 [255]
807 829
808 830 log -k r1
809 831
810 832 $ hg log -k r1
811 833 changeset: 1:3d5bf5654eda
812 834 user: test
813 835 date: Thu Jan 01 00:00:01 1970 +0000
814 836 summary: r1
815 837
816 838 log -p -l2 --color=always
817 839
818 840 $ hg --config extensions.color= --config color.mode=ansi \
819 841 > log -p -l2 --color=always
820 842 \x1b[0;33mchangeset: 6:2404bbcab562\x1b[0m (esc)
821 843 tag: tip
822 844 user: test
823 845 date: Thu Jan 01 00:00:01 1970 +0000
824 846 summary: b1.1
825 847
826 848 \x1b[0;1mdiff -r 302e9dd6890d -r 2404bbcab562 b1\x1b[0m (esc)
827 849 \x1b[0;31;1m--- a/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
828 850 \x1b[0;32;1m+++ b/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
829 851 \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
830 852 b1
831 853 \x1b[0;32m+postm\x1b[0m (esc)
832 854
833 855 \x1b[0;33mchangeset: 5:302e9dd6890d\x1b[0m (esc)
834 856 parent: 3:e62f78d544b4
835 857 parent: 4:ddb82e70d1a1
836 858 user: test
837 859 date: Thu Jan 01 00:00:01 1970 +0000
838 860 summary: m12
839 861
840 862 \x1b[0;1mdiff -r e62f78d544b4 -r 302e9dd6890d b2\x1b[0m (esc)
841 863 \x1b[0;31;1m--- /dev/null Thu Jan 01 00:00:00 1970 +0000\x1b[0m (esc)
842 864 \x1b[0;32;1m+++ b/b2 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
843 865 \x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m (esc)
844 866 \x1b[0;32m+b2\x1b[0m (esc)
845 867
846 868
847 869
848 870 log -r tip --stat
849 871
850 872 $ hg log -r tip --stat
851 873 changeset: 6:2404bbcab562
852 874 tag: tip
853 875 user: test
854 876 date: Thu Jan 01 00:00:01 1970 +0000
855 877 summary: b1.1
856 878
857 879 b1 | 1 +
858 880 1 files changed, 1 insertions(+), 0 deletions(-)
859 881
860 882
861 883 $ cd ..
862 884
863 885
864 886 User
865 887
866 888 $ hg init usertest
867 889 $ cd usertest
868 890
869 891 $ echo a > a
870 892 $ hg ci -A -m "a" -u "User One <user1@example.org>"
871 893 adding a
872 894 $ echo b > b
873 895 $ hg ci -A -m "b" -u "User Two <user2@example.org>"
874 896 adding b
875 897
876 898 $ hg log -u "User One <user1@example.org>"
877 899 changeset: 0:29a4c94f1924
878 900 user: User One <user1@example.org>
879 901 date: Thu Jan 01 00:00:00 1970 +0000
880 902 summary: a
881 903
882 904 $ hg log -u "user1" -u "user2"
883 905 changeset: 1:e834b5e69c0e
884 906 tag: tip
885 907 user: User Two <user2@example.org>
886 908 date: Thu Jan 01 00:00:00 1970 +0000
887 909 summary: b
888 910
889 911 changeset: 0:29a4c94f1924
890 912 user: User One <user1@example.org>
891 913 date: Thu Jan 01 00:00:00 1970 +0000
892 914 summary: a
893 915
894 916 $ hg log -u "user3"
895 917
896 918 $ cd ..
897 919
898 920 $ hg init branches
899 921 $ cd branches
900 922
901 923 $ echo a > a
902 924 $ hg ci -A -m "commit on default"
903 925 adding a
904 926 $ hg branch test
905 927 marked working directory as branch test
906 928 (branches are permanent and global, did you want a bookmark?)
907 929 $ echo b > b
908 930 $ hg ci -A -m "commit on test"
909 931 adding b
910 932
911 933 $ hg up default
912 934 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
913 935 $ echo c > c
914 936 $ hg ci -A -m "commit on default"
915 937 adding c
916 938 $ hg up test
917 939 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
918 940 $ echo c > c
919 941 $ hg ci -A -m "commit on test"
920 942 adding c
921 943
922 944
923 945 log -b default
924 946
925 947 $ hg log -b default
926 948 changeset: 2:c3a4f03cc9a7
927 949 parent: 0:24427303d56f
928 950 user: test
929 951 date: Thu Jan 01 00:00:00 1970 +0000
930 952 summary: commit on default
931 953
932 954 changeset: 0:24427303d56f
933 955 user: test
934 956 date: Thu Jan 01 00:00:00 1970 +0000
935 957 summary: commit on default
936 958
937 959
938 960
939 961 log -b test
940 962
941 963 $ hg log -b test
942 964 changeset: 3:f5d8de11c2e2
943 965 branch: test
944 966 tag: tip
945 967 parent: 1:d32277701ccb
946 968 user: test
947 969 date: Thu Jan 01 00:00:00 1970 +0000
948 970 summary: commit on test
949 971
950 972 changeset: 1:d32277701ccb
951 973 branch: test
952 974 user: test
953 975 date: Thu Jan 01 00:00:00 1970 +0000
954 976 summary: commit on test
955 977
956 978
957 979
958 980 log -b dummy
959 981
960 982 $ hg log -b dummy
961 983 abort: unknown revision 'dummy'!
962 984 [255]
963 985
964 986
965 987 log -b .
966 988
967 989 $ hg log -b .
968 990 changeset: 3:f5d8de11c2e2
969 991 branch: test
970 992 tag: tip
971 993 parent: 1:d32277701ccb
972 994 user: test
973 995 date: Thu Jan 01 00:00:00 1970 +0000
974 996 summary: commit on test
975 997
976 998 changeset: 1:d32277701ccb
977 999 branch: test
978 1000 user: test
979 1001 date: Thu Jan 01 00:00:00 1970 +0000
980 1002 summary: commit on test
981 1003
982 1004
983 1005
984 1006 log -b default -b test
985 1007
986 1008 $ hg log -b default -b test
987 1009 changeset: 3:f5d8de11c2e2
988 1010 branch: test
989 1011 tag: tip
990 1012 parent: 1:d32277701ccb
991 1013 user: test
992 1014 date: Thu Jan 01 00:00:00 1970 +0000
993 1015 summary: commit on test
994 1016
995 1017 changeset: 2:c3a4f03cc9a7
996 1018 parent: 0:24427303d56f
997 1019 user: test
998 1020 date: Thu Jan 01 00:00:00 1970 +0000
999 1021 summary: commit on default
1000 1022
1001 1023 changeset: 1:d32277701ccb
1002 1024 branch: test
1003 1025 user: test
1004 1026 date: Thu Jan 01 00:00:00 1970 +0000
1005 1027 summary: commit on test
1006 1028
1007 1029 changeset: 0:24427303d56f
1008 1030 user: test
1009 1031 date: Thu Jan 01 00:00:00 1970 +0000
1010 1032 summary: commit on default
1011 1033
1012 1034
1013 1035
1014 1036 log -b default -b .
1015 1037
1016 1038 $ hg log -b default -b .
1017 1039 changeset: 3:f5d8de11c2e2
1018 1040 branch: test
1019 1041 tag: tip
1020 1042 parent: 1:d32277701ccb
1021 1043 user: test
1022 1044 date: Thu Jan 01 00:00:00 1970 +0000
1023 1045 summary: commit on test
1024 1046
1025 1047 changeset: 2:c3a4f03cc9a7
1026 1048 parent: 0:24427303d56f
1027 1049 user: test
1028 1050 date: Thu Jan 01 00:00:00 1970 +0000
1029 1051 summary: commit on default
1030 1052
1031 1053 changeset: 1:d32277701ccb
1032 1054 branch: test
1033 1055 user: test
1034 1056 date: Thu Jan 01 00:00:00 1970 +0000
1035 1057 summary: commit on test
1036 1058
1037 1059 changeset: 0:24427303d56f
1038 1060 user: test
1039 1061 date: Thu Jan 01 00:00:00 1970 +0000
1040 1062 summary: commit on default
1041 1063
1042 1064
1043 1065
1044 1066 log -b . -b test
1045 1067
1046 1068 $ hg log -b . -b test
1047 1069 changeset: 3:f5d8de11c2e2
1048 1070 branch: test
1049 1071 tag: tip
1050 1072 parent: 1:d32277701ccb
1051 1073 user: test
1052 1074 date: Thu Jan 01 00:00:00 1970 +0000
1053 1075 summary: commit on test
1054 1076
1055 1077 changeset: 1:d32277701ccb
1056 1078 branch: test
1057 1079 user: test
1058 1080 date: Thu Jan 01 00:00:00 1970 +0000
1059 1081 summary: commit on test
1060 1082
1061 1083
1062 1084
1063 1085 log -b 2
1064 1086
1065 1087 $ hg log -b 2
1066 1088 changeset: 2:c3a4f03cc9a7
1067 1089 parent: 0:24427303d56f
1068 1090 user: test
1069 1091 date: Thu Jan 01 00:00:00 1970 +0000
1070 1092 summary: commit on default
1071 1093
1072 1094 changeset: 0:24427303d56f
1073 1095 user: test
1074 1096 date: Thu Jan 01 00:00:00 1970 +0000
1075 1097 summary: commit on default
1076 1098
1077 1099 #if gettext
1078 1100
1079 1101 Test that all log names are translated (e.g. branches, bookmarks, tags):
1080 1102
1081 1103 $ hg bookmark babar -r tip
1082 1104
1083 1105 $ HGENCODING=UTF-8 LANGUAGE=de hg log -r tip
1084 1106 \xc3\x84nderung: 3:f5d8de11c2e2 (esc)
1085 1107 Zweig: test
1086 1108 Lesezeichen: babar
1087 1109 Marke: tip
1088 1110 Vorg\xc3\xa4nger: 1:d32277701ccb (esc)
1089 1111 Nutzer: test
1090 1112 Datum: Thu Jan 01 00:00:00 1970 +0000
1091 1113 Zusammenfassung: commit on test
1092 1114
1093 1115 $ hg bookmark -d babar
1094 1116
1095 1117 #endif
1096 1118
1097 1119 log -p --cwd dir (in subdir)
1098 1120
1099 1121 $ mkdir dir
1100 1122 $ hg log -p --cwd dir
1101 1123 changeset: 3:f5d8de11c2e2
1102 1124 branch: test
1103 1125 tag: tip
1104 1126 parent: 1:d32277701ccb
1105 1127 user: test
1106 1128 date: Thu Jan 01 00:00:00 1970 +0000
1107 1129 summary: commit on test
1108 1130
1109 1131 diff -r d32277701ccb -r f5d8de11c2e2 c
1110 1132 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1111 1133 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1112 1134 @@ -0,0 +1,1 @@
1113 1135 +c
1114 1136
1115 1137 changeset: 2:c3a4f03cc9a7
1116 1138 parent: 0:24427303d56f
1117 1139 user: test
1118 1140 date: Thu Jan 01 00:00:00 1970 +0000
1119 1141 summary: commit on default
1120 1142
1121 1143 diff -r 24427303d56f -r c3a4f03cc9a7 c
1122 1144 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1123 1145 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1124 1146 @@ -0,0 +1,1 @@
1125 1147 +c
1126 1148
1127 1149 changeset: 1:d32277701ccb
1128 1150 branch: test
1129 1151 user: test
1130 1152 date: Thu Jan 01 00:00:00 1970 +0000
1131 1153 summary: commit on test
1132 1154
1133 1155 diff -r 24427303d56f -r d32277701ccb b
1134 1156 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1135 1157 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1136 1158 @@ -0,0 +1,1 @@
1137 1159 +b
1138 1160
1139 1161 changeset: 0:24427303d56f
1140 1162 user: test
1141 1163 date: Thu Jan 01 00:00:00 1970 +0000
1142 1164 summary: commit on default
1143 1165
1144 1166 diff -r 000000000000 -r 24427303d56f a
1145 1167 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1146 1168 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1147 1169 @@ -0,0 +1,1 @@
1148 1170 +a
1149 1171
1150 1172
1151 1173
1152 1174 log -p -R repo
1153 1175
1154 1176 $ cd dir
1155 1177 $ hg log -p -R .. ../a
1156 1178 changeset: 0:24427303d56f
1157 1179 user: test
1158 1180 date: Thu Jan 01 00:00:00 1970 +0000
1159 1181 summary: commit on default
1160 1182
1161 1183 diff -r 000000000000 -r 24427303d56f a
1162 1184 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1163 1185 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1164 1186 @@ -0,0 +1,1 @@
1165 1187 +a
1166 1188
1167 1189
1168 1190 $ cd ../..
1169 1191
1170 1192 $ hg init follow2
1171 1193 $ cd follow2
1172 1194
1173 1195 # Build the following history:
1174 1196 # tip - o - x - o - x - x
1175 1197 # \ /
1176 1198 # o - o - o - x
1177 1199 # \ /
1178 1200 # o
1179 1201 #
1180 1202 # Where "o" is a revision containing "foo" and
1181 1203 # "x" is a revision without "foo"
1182 1204
1183 1205 $ touch init
1184 1206 $ hg ci -A -m "init, unrelated"
1185 1207 adding init
1186 1208 $ echo 'foo' > init
1187 1209 $ hg ci -m "change, unrelated"
1188 1210 $ echo 'foo' > foo
1189 1211 $ hg ci -A -m "add unrelated old foo"
1190 1212 adding foo
1191 1213 $ hg rm foo
1192 1214 $ hg ci -m "delete foo, unrelated"
1193 1215 $ echo 'related' > foo
1194 1216 $ hg ci -A -m "add foo, related"
1195 1217 adding foo
1196 1218
1197 1219 $ hg up 0
1198 1220 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1199 1221 $ touch branch
1200 1222 $ hg ci -A -m "first branch, unrelated"
1201 1223 adding branch
1202 1224 created new head
1203 1225 $ touch foo
1204 1226 $ hg ci -A -m "create foo, related"
1205 1227 adding foo
1206 1228 $ echo 'change' > foo
1207 1229 $ hg ci -m "change foo, related"
1208 1230
1209 1231 $ hg up 6
1210 1232 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1211 1233 $ echo 'change foo in branch' > foo
1212 1234 $ hg ci -m "change foo in branch, related"
1213 1235 created new head
1214 1236 $ hg merge 7
1215 1237 merging foo
1216 1238 warning: conflicts during merge.
1217 1239 merging foo incomplete! (edit conflicts, then use 'hg resolve --mark')
1218 1240 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1219 1241 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1220 1242 [1]
1221 1243 $ echo 'merge 1' > foo
1222 1244 $ hg resolve -m foo
1223 1245 (no more unresolved files)
1224 1246 $ hg ci -m "First merge, related"
1225 1247
1226 1248 $ hg merge 4
1227 1249 merging foo
1228 1250 warning: conflicts during merge.
1229 1251 merging foo incomplete! (edit conflicts, then use 'hg resolve --mark')
1230 1252 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
1231 1253 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1232 1254 [1]
1233 1255 $ echo 'merge 2' > foo
1234 1256 $ hg resolve -m foo
1235 1257 (no more unresolved files)
1236 1258 $ hg ci -m "Last merge, related"
1237 1259
1238 1260 $ hg log --graph
1239 1261 @ changeset: 10:4dae8563d2c5
1240 1262 |\ tag: tip
1241 1263 | | parent: 9:7b35701b003e
1242 1264 | | parent: 4:88176d361b69
1243 1265 | | user: test
1244 1266 | | date: Thu Jan 01 00:00:00 1970 +0000
1245 1267 | | summary: Last merge, related
1246 1268 | |
1247 1269 | o changeset: 9:7b35701b003e
1248 1270 | |\ parent: 8:e5416ad8a855
1249 1271 | | | parent: 7:87fe3144dcfa
1250 1272 | | | user: test
1251 1273 | | | date: Thu Jan 01 00:00:00 1970 +0000
1252 1274 | | | summary: First merge, related
1253 1275 | | |
1254 1276 | | o changeset: 8:e5416ad8a855
1255 1277 | | | parent: 6:dc6c325fe5ee
1256 1278 | | | user: test
1257 1279 | | | date: Thu Jan 01 00:00:00 1970 +0000
1258 1280 | | | summary: change foo in branch, related
1259 1281 | | |
1260 1282 | o | changeset: 7:87fe3144dcfa
1261 1283 | |/ user: test
1262 1284 | | date: Thu Jan 01 00:00:00 1970 +0000
1263 1285 | | summary: change foo, related
1264 1286 | |
1265 1287 | o changeset: 6:dc6c325fe5ee
1266 1288 | | user: test
1267 1289 | | date: Thu Jan 01 00:00:00 1970 +0000
1268 1290 | | summary: create foo, related
1269 1291 | |
1270 1292 | o changeset: 5:73db34516eb9
1271 1293 | | parent: 0:e87515fd044a
1272 1294 | | user: test
1273 1295 | | date: Thu Jan 01 00:00:00 1970 +0000
1274 1296 | | summary: first branch, unrelated
1275 1297 | |
1276 1298 o | changeset: 4:88176d361b69
1277 1299 | | user: test
1278 1300 | | date: Thu Jan 01 00:00:00 1970 +0000
1279 1301 | | summary: add foo, related
1280 1302 | |
1281 1303 o | changeset: 3:dd78ae4afb56
1282 1304 | | user: test
1283 1305 | | date: Thu Jan 01 00:00:00 1970 +0000
1284 1306 | | summary: delete foo, unrelated
1285 1307 | |
1286 1308 o | changeset: 2:c4c64aedf0f7
1287 1309 | | user: test
1288 1310 | | date: Thu Jan 01 00:00:00 1970 +0000
1289 1311 | | summary: add unrelated old foo
1290 1312 | |
1291 1313 o | changeset: 1:e5faa7440653
1292 1314 |/ user: test
1293 1315 | date: Thu Jan 01 00:00:00 1970 +0000
1294 1316 | summary: change, unrelated
1295 1317 |
1296 1318 o changeset: 0:e87515fd044a
1297 1319 user: test
1298 1320 date: Thu Jan 01 00:00:00 1970 +0000
1299 1321 summary: init, unrelated
1300 1322
1301 1323
1302 1324 $ hg --traceback log -f foo
1303 1325 changeset: 10:4dae8563d2c5
1304 1326 tag: tip
1305 1327 parent: 9:7b35701b003e
1306 1328 parent: 4:88176d361b69
1307 1329 user: test
1308 1330 date: Thu Jan 01 00:00:00 1970 +0000
1309 1331 summary: Last merge, related
1310 1332
1311 1333 changeset: 9:7b35701b003e
1312 1334 parent: 8:e5416ad8a855
1313 1335 parent: 7:87fe3144dcfa
1314 1336 user: test
1315 1337 date: Thu Jan 01 00:00:00 1970 +0000
1316 1338 summary: First merge, related
1317 1339
1318 1340 changeset: 8:e5416ad8a855
1319 1341 parent: 6:dc6c325fe5ee
1320 1342 user: test
1321 1343 date: Thu Jan 01 00:00:00 1970 +0000
1322 1344 summary: change foo in branch, related
1323 1345
1324 1346 changeset: 7:87fe3144dcfa
1325 1347 user: test
1326 1348 date: Thu Jan 01 00:00:00 1970 +0000
1327 1349 summary: change foo, related
1328 1350
1329 1351 changeset: 6:dc6c325fe5ee
1330 1352 user: test
1331 1353 date: Thu Jan 01 00:00:00 1970 +0000
1332 1354 summary: create foo, related
1333 1355
1334 1356 changeset: 4:88176d361b69
1335 1357 user: test
1336 1358 date: Thu Jan 01 00:00:00 1970 +0000
1337 1359 summary: add foo, related
1338 1360
1339 1361
1340 1362 Also check when maxrev < lastrevfilelog
1341 1363
1342 1364 $ hg --traceback log -f -r4 foo
1343 1365 changeset: 4:88176d361b69
1344 1366 user: test
1345 1367 date: Thu Jan 01 00:00:00 1970 +0000
1346 1368 summary: add foo, related
1347 1369
1348 1370 changeset: 2:c4c64aedf0f7
1349 1371 user: test
1350 1372 date: Thu Jan 01 00:00:00 1970 +0000
1351 1373 summary: add unrelated old foo
1352 1374
1353 1375 $ cd ..
1354 1376
1355 1377 Issue2383: hg log showing _less_ differences than hg diff
1356 1378
1357 1379 $ hg init issue2383
1358 1380 $ cd issue2383
1359 1381
1360 1382 Create a test repo:
1361 1383
1362 1384 $ echo a > a
1363 1385 $ hg ci -Am0
1364 1386 adding a
1365 1387 $ echo b > b
1366 1388 $ hg ci -Am1
1367 1389 adding b
1368 1390 $ hg co 0
1369 1391 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1370 1392 $ echo b > a
1371 1393 $ hg ci -m2
1372 1394 created new head
1373 1395
1374 1396 Merge:
1375 1397
1376 1398 $ hg merge
1377 1399 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1378 1400 (branch merge, don't forget to commit)
1379 1401
1380 1402 Make sure there's a file listed in the merge to trigger the bug:
1381 1403
1382 1404 $ echo c > a
1383 1405 $ hg ci -m3
1384 1406
1385 1407 Two files shown here in diff:
1386 1408
1387 1409 $ hg diff --rev 2:3
1388 1410 diff -r b09be438c43a -r 8e07aafe1edc a
1389 1411 --- a/a Thu Jan 01 00:00:00 1970 +0000
1390 1412 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1391 1413 @@ -1,1 +1,1 @@
1392 1414 -b
1393 1415 +c
1394 1416 diff -r b09be438c43a -r 8e07aafe1edc b
1395 1417 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1396 1418 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1397 1419 @@ -0,0 +1,1 @@
1398 1420 +b
1399 1421
1400 1422 Diff here should be the same:
1401 1423
1402 1424 $ hg log -vpr 3
1403 1425 changeset: 3:8e07aafe1edc
1404 1426 tag: tip
1405 1427 parent: 2:b09be438c43a
1406 1428 parent: 1:925d80f479bb
1407 1429 user: test
1408 1430 date: Thu Jan 01 00:00:00 1970 +0000
1409 1431 files: a
1410 1432 description:
1411 1433 3
1412 1434
1413 1435
1414 1436 diff -r b09be438c43a -r 8e07aafe1edc a
1415 1437 --- a/a Thu Jan 01 00:00:00 1970 +0000
1416 1438 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1417 1439 @@ -1,1 +1,1 @@
1418 1440 -b
1419 1441 +c
1420 1442 diff -r b09be438c43a -r 8e07aafe1edc b
1421 1443 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1422 1444 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1423 1445 @@ -0,0 +1,1 @@
1424 1446 +b
1425 1447
1426 1448 $ cd ..
1427 1449
1428 1450 'hg log -r rev fn' when last(filelog(fn)) != rev
1429 1451
1430 1452 $ hg init simplelog
1431 1453 $ cd simplelog
1432 1454 $ echo f > a
1433 1455 $ hg ci -Am'a' -d '0 0'
1434 1456 adding a
1435 1457 $ echo f >> a
1436 1458 $ hg ci -Am'a bis' -d '1 0'
1437 1459
1438 1460 $ hg log -r0 a
1439 1461 changeset: 0:9f758d63dcde
1440 1462 user: test
1441 1463 date: Thu Jan 01 00:00:00 1970 +0000
1442 1464 summary: a
1443 1465
1444 1466 enable obsolete to test hidden feature
1445 1467
1446 1468 $ cat >> $HGRCPATH << EOF
1447 1469 > [experimental]
1448 1470 > evolution=createmarkers
1449 1471 > EOF
1450 1472
1451 1473 $ hg log --template='{rev}:{node}\n'
1452 1474 1:a765632148dc55d38c35c4f247c618701886cb2f
1453 1475 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1454 1476 $ hg debugobsolete a765632148dc55d38c35c4f247c618701886cb2f
1455 1477 $ hg up null -q
1456 1478 $ hg log --template='{rev}:{node}\n'
1457 1479 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1458 1480 $ hg log --template='{rev}:{node}\n' --hidden
1459 1481 1:a765632148dc55d38c35c4f247c618701886cb2f
1460 1482 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1461 1483 $ hg log -r a
1462 1484 abort: hidden revision 'a'!
1463 1485 (use --hidden to access hidden revisions)
1464 1486 [255]
1465 1487
1466 1488 test that parent prevent a changeset to be hidden
1467 1489
1468 1490 $ hg up 1 -q --hidden
1469 1491 $ hg log --template='{rev}:{node}\n'
1470 1492 1:a765632148dc55d38c35c4f247c618701886cb2f
1471 1493 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1472 1494
1473 1495 test that second parent prevent a changeset to be hidden too
1474 1496
1475 1497 $ hg debugsetparents 0 1 # nothing suitable to merge here
1476 1498 $ hg log --template='{rev}:{node}\n'
1477 1499 1:a765632148dc55d38c35c4f247c618701886cb2f
1478 1500 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1479 1501 $ hg debugsetparents 1
1480 1502 $ hg up -q null
1481 1503
1482 1504 bookmarks prevent a changeset being hidden
1483 1505
1484 1506 $ hg bookmark --hidden -r 1 X
1485 1507 $ hg log --template '{rev}:{node}\n'
1486 1508 1:a765632148dc55d38c35c4f247c618701886cb2f
1487 1509 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1488 1510 $ hg bookmark -d X
1489 1511
1490 1512 divergent bookmarks are not hidden
1491 1513
1492 1514 $ hg bookmark --hidden -r 1 X@foo
1493 1515 $ hg log --template '{rev}:{node}\n'
1494 1516 1:a765632148dc55d38c35c4f247c618701886cb2f
1495 1517 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1496 1518
1497 1519 clear extensions configuration
1498 1520 $ echo '[extensions]' >> $HGRCPATH
1499 1521 $ echo "obs=!" >> $HGRCPATH
1500 1522 $ cd ..
1501 1523
1502 1524 test -u/-k for problematic encoding
1503 1525 # unicode: cp932:
1504 1526 # u30A2 0x83 0x41(= 'A')
1505 1527 # u30C2 0x83 0x61(= 'a')
1506 1528
1507 1529 $ hg init problematicencoding
1508 1530 $ cd problematicencoding
1509 1531
1510 1532 $ python > setup.sh <<EOF
1511 1533 > print u'''
1512 1534 > echo a > text
1513 1535 > hg add text
1514 1536 > hg --encoding utf-8 commit -u '\u30A2' -m none
1515 1537 > echo b > text
1516 1538 > hg --encoding utf-8 commit -u '\u30C2' -m none
1517 1539 > echo c > text
1518 1540 > hg --encoding utf-8 commit -u none -m '\u30A2'
1519 1541 > echo d > text
1520 1542 > hg --encoding utf-8 commit -u none -m '\u30C2'
1521 1543 > '''.encode('utf-8')
1522 1544 > EOF
1523 1545 $ sh < setup.sh
1524 1546
1525 1547 test in problematic encoding
1526 1548 $ python > test.sh <<EOF
1527 1549 > print u'''
1528 1550 > hg --encoding cp932 log --template '{rev}\\n' -u '\u30A2'
1529 1551 > echo ====
1530 1552 > hg --encoding cp932 log --template '{rev}\\n' -u '\u30C2'
1531 1553 > echo ====
1532 1554 > hg --encoding cp932 log --template '{rev}\\n' -k '\u30A2'
1533 1555 > echo ====
1534 1556 > hg --encoding cp932 log --template '{rev}\\n' -k '\u30C2'
1535 1557 > '''.encode('cp932')
1536 1558 > EOF
1537 1559 $ sh < test.sh
1538 1560 0
1539 1561 ====
1540 1562 1
1541 1563 ====
1542 1564 2
1543 1565 0
1544 1566 ====
1545 1567 3
1546 1568 1
1547 1569
1548 1570 $ cd ..
1549 1571
1550 1572 test hg log on non-existent files and on directories
1551 1573 $ hg init issue1340
1552 1574 $ cd issue1340
1553 1575 $ mkdir d1; mkdir D2; mkdir D3.i; mkdir d4.hg; mkdir d5.d; mkdir .d6
1554 1576 $ echo 1 > d1/f1
1555 1577 $ echo 1 > D2/f1
1556 1578 $ echo 1 > D3.i/f1
1557 1579 $ echo 1 > d4.hg/f1
1558 1580 $ echo 1 > d5.d/f1
1559 1581 $ echo 1 > .d6/f1
1560 1582 $ hg -q add .
1561 1583 $ hg commit -m "a bunch of weird directories"
1562 1584 $ hg log -l1 d1/f1 | grep changeset
1563 1585 changeset: 0:65624cd9070a
1564 1586 $ hg log -l1 f1
1565 1587 $ hg log -l1 . | grep changeset
1566 1588 changeset: 0:65624cd9070a
1567 1589 $ hg log -l1 ./ | grep changeset
1568 1590 changeset: 0:65624cd9070a
1569 1591 $ hg log -l1 d1 | grep changeset
1570 1592 changeset: 0:65624cd9070a
1571 1593 $ hg log -l1 D2 | grep changeset
1572 1594 changeset: 0:65624cd9070a
1573 1595 $ hg log -l1 D2/f1 | grep changeset
1574 1596 changeset: 0:65624cd9070a
1575 1597 $ hg log -l1 D3.i | grep changeset
1576 1598 changeset: 0:65624cd9070a
1577 1599 $ hg log -l1 D3.i/f1 | grep changeset
1578 1600 changeset: 0:65624cd9070a
1579 1601 $ hg log -l1 d4.hg | grep changeset
1580 1602 changeset: 0:65624cd9070a
1581 1603 $ hg log -l1 d4.hg/f1 | grep changeset
1582 1604 changeset: 0:65624cd9070a
1583 1605 $ hg log -l1 d5.d | grep changeset
1584 1606 changeset: 0:65624cd9070a
1585 1607 $ hg log -l1 d5.d/f1 | grep changeset
1586 1608 changeset: 0:65624cd9070a
1587 1609 $ hg log -l1 .d6 | grep changeset
1588 1610 changeset: 0:65624cd9070a
1589 1611 $ hg log -l1 .d6/f1 | grep changeset
1590 1612 changeset: 0:65624cd9070a
1591 1613
1592 1614 issue3772: hg log -r :null showing revision 0 as well
1593 1615
1594 1616 $ hg log -r :null
1595 1617 changeset: 0:65624cd9070a
1596 1618 tag: tip
1597 1619 user: test
1598 1620 date: Thu Jan 01 00:00:00 1970 +0000
1599 1621 summary: a bunch of weird directories
1600 1622
1601 1623 changeset: -1:000000000000
1602 1624 user:
1603 1625 date: Thu Jan 01 00:00:00 1970 +0000
1604 1626
1605 1627 $ hg log -r null:null
1606 1628 changeset: -1:000000000000
1607 1629 user:
1608 1630 date: Thu Jan 01 00:00:00 1970 +0000
1609 1631
1610 1632 Check that adding an arbitrary name shows up in log automatically
1611 1633
1612 1634 $ cat > ../names.py <<EOF
1613 1635 > """A small extension to test adding arbitrary names to a repo"""
1614 1636 > from mercurial.namespaces import namespace
1615 1637 >
1616 1638 > def reposetup(ui, repo):
1617 1639 > foo = {'foo': repo[0].node()}
1618 1640 > names = lambda r: foo.keys()
1619 1641 > namemap = lambda r, name: foo.get(name)
1620 1642 > nodemap = lambda r, node: [name for name, n in foo.iteritems()
1621 1643 > if n == node]
1622 1644 > ns = namespace("bars", templatename="bar", logname="barlog",
1623 1645 > colorname="barcolor", listnames=names, namemap=namemap,
1624 1646 > nodemap=nodemap)
1625 1647 >
1626 1648 > repo.names.addnamespace(ns)
1627 1649 > EOF
1628 1650
1629 1651 $ hg --config extensions.names=../names.py log -r 0
1630 1652 changeset: 0:65624cd9070a
1631 1653 tag: tip
1632 1654 barlog: foo
1633 1655 user: test
1634 1656 date: Thu Jan 01 00:00:00 1970 +0000
1635 1657 summary: a bunch of weird directories
1636 1658
1637 1659 $ hg --config extensions.names=../names.py \
1638 1660 > --config extensions.color= --config color.log.barcolor=red \
1639 1661 > --color=always log -r 0
1640 1662 \x1b[0;33mchangeset: 0:65624cd9070a\x1b[0m (esc)
1641 1663 tag: tip
1642 1664 \x1b[0;31mbarlog: foo\x1b[0m (esc)
1643 1665 user: test
1644 1666 date: Thu Jan 01 00:00:00 1970 +0000
1645 1667 summary: a bunch of weird directories
1646 1668
1647 1669 $ hg --config extensions.names=../names.py log -r 0 --template '{bars}\n'
1648 1670 foo
1649 1671
1650 1672 $ cd ..
1651 1673
1652 1674 hg log -f dir across branches
1653 1675
1654 1676 $ hg init acrossbranches
1655 1677 $ cd acrossbranches
1656 1678 $ mkdir d
1657 1679 $ echo a > d/a && hg ci -Aqm a
1658 1680 $ echo b > d/a && hg ci -Aqm b
1659 1681 $ hg up -q 0
1660 1682 $ echo b > d/a && hg ci -Aqm c
1661 1683 $ hg log -f d -T '{desc}' -G
1662 1684 @ c
1663 1685 |
1664 1686 o a
1665 1687
1666 1688 Ensure that largefiles doesn't interfere with following a normal file
1667 1689 $ hg --config extensions.largefiles= log -f d -T '{desc}' -G
1668 1690 @ c
1669 1691 |
1670 1692 o a
1671 1693
1672 1694 $ hg log -f d/a -T '{desc}' -G
1673 1695 @ c
1674 1696 |
1675 1697 o a
1676 1698
1677 1699 $ cd ..
1678 1700
1679 1701 hg log -f with linkrev pointing to another branch
1680 1702 -------------------------------------------------
1681 1703
1682 1704 create history with a filerev whose linkrev points to another branch
1683 1705
1684 1706 $ hg init branchedlinkrev
1685 1707 $ cd branchedlinkrev
1686 1708 $ echo 1 > a
1687 1709 $ hg commit -Am 'content1'
1688 1710 adding a
1689 1711 $ echo 2 > a
1690 1712 $ hg commit -m 'content2'
1691 1713 $ hg up --rev 'desc(content1)'
1692 1714 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1693 1715 $ echo unrelated > unrelated
1694 1716 $ hg commit -Am 'unrelated'
1695 1717 adding unrelated
1696 1718 created new head
1697 1719 $ hg graft -r 'desc(content2)'
1698 1720 grafting 1:2294ae80ad84 "content2"
1699 1721 $ echo 3 > a
1700 1722 $ hg commit -m 'content3'
1701 1723 $ hg log -G
1702 1724 @ changeset: 4:50b9b36e9c5d
1703 1725 | tag: tip
1704 1726 | user: test
1705 1727 | date: Thu Jan 01 00:00:00 1970 +0000
1706 1728 | summary: content3
1707 1729 |
1708 1730 o changeset: 3:15b2327059e5
1709 1731 | user: test
1710 1732 | date: Thu Jan 01 00:00:00 1970 +0000
1711 1733 | summary: content2
1712 1734 |
1713 1735 o changeset: 2:2029acd1168c
1714 1736 | parent: 0:ae0a3c9f9e95
1715 1737 | user: test
1716 1738 | date: Thu Jan 01 00:00:00 1970 +0000
1717 1739 | summary: unrelated
1718 1740 |
1719 1741 | o changeset: 1:2294ae80ad84
1720 1742 |/ user: test
1721 1743 | date: Thu Jan 01 00:00:00 1970 +0000
1722 1744 | summary: content2
1723 1745 |
1724 1746 o changeset: 0:ae0a3c9f9e95
1725 1747 user: test
1726 1748 date: Thu Jan 01 00:00:00 1970 +0000
1727 1749 summary: content1
1728 1750
1729 1751
1730 1752 log -f on the file should list the graft result.
1731 1753
1732 1754 $ hg log -Gf a
1733 1755 @ changeset: 4:50b9b36e9c5d
1734 1756 | tag: tip
1735 1757 | user: test
1736 1758 | date: Thu Jan 01 00:00:00 1970 +0000
1737 1759 | summary: content3
1738 1760 |
1739 1761 o changeset: 3:15b2327059e5
1740 1762 | user: test
1741 1763 | date: Thu Jan 01 00:00:00 1970 +0000
1742 1764 | summary: content2
1743 1765 |
1744 1766 o changeset: 0:ae0a3c9f9e95
1745 1767 user: test
1746 1768 date: Thu Jan 01 00:00:00 1970 +0000
1747 1769 summary: content1
1748 1770
1749 1771
1750 1772 plain log lists the original version
1751 1773 (XXX we should probably list both)
1752 1774
1753 1775 $ hg log -G a
1754 1776 @ changeset: 4:50b9b36e9c5d
1755 1777 | tag: tip
1756 1778 | user: test
1757 1779 | date: Thu Jan 01 00:00:00 1970 +0000
1758 1780 | summary: content3
1759 1781 |
1760 1782 | o changeset: 1:2294ae80ad84
1761 1783 |/ user: test
1762 1784 | date: Thu Jan 01 00:00:00 1970 +0000
1763 1785 | summary: content2
1764 1786 |
1765 1787 o changeset: 0:ae0a3c9f9e95
1766 1788 user: test
1767 1789 date: Thu Jan 01 00:00:00 1970 +0000
1768 1790 summary: content1
1769 1791
1770 1792
1771 1793 hg log -f from the grafted changeset
1772 1794 (The bootstrap should properly take the topology in account)
1773 1795
1774 1796 $ hg up 'desc(content3)^'
1775 1797 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1776 1798 $ hg log -Gf a
1777 1799 @ changeset: 3:15b2327059e5
1778 1800 | user: test
1779 1801 | date: Thu Jan 01 00:00:00 1970 +0000
1780 1802 | summary: content2
1781 1803 |
1782 1804 o changeset: 0:ae0a3c9f9e95
1783 1805 user: test
1784 1806 date: Thu Jan 01 00:00:00 1970 +0000
1785 1807 summary: content1
1786 1808
1787 1809
1788 1810 Test that we use the first non-hidden changeset in that case.
1789 1811
1790 1812 (hide the changeset)
1791 1813
1792 1814 $ hg log -T '{node}\n' -r 1
1793 1815 2294ae80ad8447bc78383182eeac50cb049df623
1794 1816 $ hg debugobsolete 2294ae80ad8447bc78383182eeac50cb049df623
1795 1817 $ hg log -G
1796 1818 o changeset: 4:50b9b36e9c5d
1797 1819 | tag: tip
1798 1820 | user: test
1799 1821 | date: Thu Jan 01 00:00:00 1970 +0000
1800 1822 | summary: content3
1801 1823 |
1802 1824 @ changeset: 3:15b2327059e5
1803 1825 | user: test
1804 1826 | date: Thu Jan 01 00:00:00 1970 +0000
1805 1827 | summary: content2
1806 1828 |
1807 1829 o changeset: 2:2029acd1168c
1808 1830 | parent: 0:ae0a3c9f9e95
1809 1831 | user: test
1810 1832 | date: Thu Jan 01 00:00:00 1970 +0000
1811 1833 | summary: unrelated
1812 1834 |
1813 1835 o changeset: 0:ae0a3c9f9e95
1814 1836 user: test
1815 1837 date: Thu Jan 01 00:00:00 1970 +0000
1816 1838 summary: content1
1817 1839
1818 1840
1819 1841 Check that log on the file does not drop the file revision.
1820 1842
1821 1843 $ hg log -G a
1822 1844 o changeset: 4:50b9b36e9c5d
1823 1845 | tag: tip
1824 1846 | user: test
1825 1847 | date: Thu Jan 01 00:00:00 1970 +0000
1826 1848 | summary: content3
1827 1849 |
1828 1850 @ changeset: 3:15b2327059e5
1829 1851 | user: test
1830 1852 | date: Thu Jan 01 00:00:00 1970 +0000
1831 1853 | summary: content2
1832 1854 |
1833 1855 o changeset: 0:ae0a3c9f9e95
1834 1856 user: test
1835 1857 date: Thu Jan 01 00:00:00 1970 +0000
1836 1858 summary: content1
1837 1859
1838 1860
1839 1861 Even when a head revision is linkrev-shadowed.
1840 1862
1841 1863 $ hg log -T '{node}\n' -r 4
1842 1864 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
1843 1865 $ hg debugobsolete 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
1844 1866 $ hg log -G a
1845 1867 @ changeset: 3:15b2327059e5
1846 1868 | tag: tip
1847 1869 | user: test
1848 1870 | date: Thu Jan 01 00:00:00 1970 +0000
1849 1871 | summary: content2
1850 1872 |
1851 1873 o changeset: 0:ae0a3c9f9e95
1852 1874 user: test
1853 1875 date: Thu Jan 01 00:00:00 1970 +0000
1854 1876 summary: content1
1855 1877
1856 1878
1857 1879 $ cd ..
1858 1880
1859 1881 Even when the file revision is missing from some head:
1860 1882
1861 1883 $ hg init issue4490
1862 1884 $ cd issue4490
1863 1885 $ echo '[experimental]' >> .hg/hgrc
1864 1886 $ echo 'evolution=createmarkers' >> .hg/hgrc
1865 1887 $ echo a > a
1866 1888 $ hg ci -Am0
1867 1889 adding a
1868 1890 $ echo b > b
1869 1891 $ hg ci -Am1
1870 1892 adding b
1871 1893 $ echo B > b
1872 1894 $ hg ci --amend -m 1
1873 1895 $ hg up 0
1874 1896 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1875 1897 $ echo c > c
1876 1898 $ hg ci -Am2
1877 1899 adding c
1878 1900 created new head
1879 1901 $ hg up 'head() and not .'
1880 1902 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1881 1903 $ hg log -G
1882 1904 o changeset: 4:db815d6d32e6
1883 1905 | tag: tip
1884 1906 | parent: 0:f7b1eb17ad24
1885 1907 | user: test
1886 1908 | date: Thu Jan 01 00:00:00 1970 +0000
1887 1909 | summary: 2
1888 1910 |
1889 1911 | @ changeset: 3:9bc8ce7f9356
1890 1912 |/ parent: 0:f7b1eb17ad24
1891 1913 | user: test
1892 1914 | date: Thu Jan 01 00:00:00 1970 +0000
1893 1915 | summary: 1
1894 1916 |
1895 1917 o changeset: 0:f7b1eb17ad24
1896 1918 user: test
1897 1919 date: Thu Jan 01 00:00:00 1970 +0000
1898 1920 summary: 0
1899 1921
1900 1922 $ hg log -f -G b
1901 1923 @ changeset: 3:9bc8ce7f9356
1902 1924 | parent: 0:f7b1eb17ad24
1903 1925 | user: test
1904 1926 | date: Thu Jan 01 00:00:00 1970 +0000
1905 1927 | summary: 1
1906 1928 |
1907 1929 $ hg log -G b
1908 1930 @ changeset: 3:9bc8ce7f9356
1909 1931 | parent: 0:f7b1eb17ad24
1910 1932 | user: test
1911 1933 | date: Thu Jan 01 00:00:00 1970 +0000
1912 1934 | summary: 1
1913 1935 |
1914 1936 $ cd ..
1915 1937
1916 1938 Check proper report when the manifest changes but not the file issue4499
1917 1939 ------------------------------------------------------------------------
1918 1940
1919 1941 $ hg init issue4499
1920 1942 $ cd issue4499
1921 1943 $ for f in A B C D F E G H I J K L M N O P Q R S T U; do
1922 1944 > echo 1 > $f;
1923 1945 > hg add $f;
1924 1946 > done
1925 1947 $ hg commit -m 'A1B1C1'
1926 1948 $ echo 2 > A
1927 1949 $ echo 2 > B
1928 1950 $ echo 2 > C
1929 1951 $ hg commit -m 'A2B2C2'
1930 1952 $ hg up 0
1931 1953 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1932 1954 $ echo 3 > A
1933 1955 $ echo 2 > B
1934 1956 $ echo 2 > C
1935 1957 $ hg commit -m 'A3B2C2'
1936 1958 created new head
1937 1959
1938 1960 $ hg log -G
1939 1961 @ changeset: 2:fe5fc3d0eb17
1940 1962 | tag: tip
1941 1963 | parent: 0:abf4f0e38563
1942 1964 | user: test
1943 1965 | date: Thu Jan 01 00:00:00 1970 +0000
1944 1966 | summary: A3B2C2
1945 1967 |
1946 1968 | o changeset: 1:07dcc6b312c0
1947 1969 |/ user: test
1948 1970 | date: Thu Jan 01 00:00:00 1970 +0000
1949 1971 | summary: A2B2C2
1950 1972 |
1951 1973 o changeset: 0:abf4f0e38563
1952 1974 user: test
1953 1975 date: Thu Jan 01 00:00:00 1970 +0000
1954 1976 summary: A1B1C1
1955 1977
1956 1978
1957 1979 Log -f on B should reports current changesets
1958 1980
1959 1981 $ hg log -fG B
1960 1982 @ changeset: 2:fe5fc3d0eb17
1961 1983 | tag: tip
1962 1984 | parent: 0:abf4f0e38563
1963 1985 | user: test
1964 1986 | date: Thu Jan 01 00:00:00 1970 +0000
1965 1987 | summary: A3B2C2
1966 1988 |
1967 1989 o changeset: 0:abf4f0e38563
1968 1990 user: test
1969 1991 date: Thu Jan 01 00:00:00 1970 +0000
1970 1992 summary: A1B1C1
1971 1993
1972 1994 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now