##// END OF EJS Templates
cmdutil: remove the redundant commit during amend...
Saurabh Singh -
r34087:e8a7c1a0 default
parent child Browse files
Show More
@@ -1,3865 +1,3886 b''
1 1 # cmdutil.py - help for command processing in mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import errno
11 11 import itertools
12 12 import os
13 13 import re
14 14 import tempfile
15 15
16 16 from .i18n import _
17 17 from .node import (
18 18 hex,
19 19 nullid,
20 20 nullrev,
21 21 short,
22 22 )
23 23
24 24 from . import (
25 25 bookmarks,
26 26 changelog,
27 27 copies,
28 28 crecord as crecordmod,
29 29 dirstateguard,
30 30 encoding,
31 31 error,
32 32 formatter,
33 33 graphmod,
34 34 match as matchmod,
35 35 obsolete,
36 36 patch,
37 37 pathutil,
38 38 pycompat,
39 39 registrar,
40 40 revlog,
41 41 revset,
42 42 scmutil,
43 43 smartset,
44 44 templatekw,
45 45 templater,
46 46 util,
47 47 vfs as vfsmod,
48 48 )
49 49 stringio = util.stringio
50 50
51 51 # templates of common command options
52 52
53 53 dryrunopts = [
54 54 ('n', 'dry-run', None,
55 55 _('do not perform actions, just print output')),
56 56 ]
57 57
58 58 remoteopts = [
59 59 ('e', 'ssh', '',
60 60 _('specify ssh command to use'), _('CMD')),
61 61 ('', 'remotecmd', '',
62 62 _('specify hg command to run on the remote side'), _('CMD')),
63 63 ('', 'insecure', None,
64 64 _('do not verify server certificate (ignoring web.cacerts config)')),
65 65 ]
66 66
67 67 walkopts = [
68 68 ('I', 'include', [],
69 69 _('include names matching the given patterns'), _('PATTERN')),
70 70 ('X', 'exclude', [],
71 71 _('exclude names matching the given patterns'), _('PATTERN')),
72 72 ]
73 73
74 74 commitopts = [
75 75 ('m', 'message', '',
76 76 _('use text as commit message'), _('TEXT')),
77 77 ('l', 'logfile', '',
78 78 _('read commit message from file'), _('FILE')),
79 79 ]
80 80
81 81 commitopts2 = [
82 82 ('d', 'date', '',
83 83 _('record the specified date as commit date'), _('DATE')),
84 84 ('u', 'user', '',
85 85 _('record the specified user as committer'), _('USER')),
86 86 ]
87 87
88 88 # hidden for now
89 89 formatteropts = [
90 90 ('T', 'template', '',
91 91 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
92 92 ]
93 93
94 94 templateopts = [
95 95 ('', 'style', '',
96 96 _('display using template map file (DEPRECATED)'), _('STYLE')),
97 97 ('T', 'template', '',
98 98 _('display with template'), _('TEMPLATE')),
99 99 ]
100 100
101 101 logopts = [
102 102 ('p', 'patch', None, _('show patch')),
103 103 ('g', 'git', None, _('use git extended diff format')),
104 104 ('l', 'limit', '',
105 105 _('limit number of changes displayed'), _('NUM')),
106 106 ('M', 'no-merges', None, _('do not show merges')),
107 107 ('', 'stat', None, _('output diffstat-style summary of changes')),
108 108 ('G', 'graph', None, _("show the revision DAG")),
109 109 ] + templateopts
110 110
111 111 diffopts = [
112 112 ('a', 'text', None, _('treat all files as text')),
113 113 ('g', 'git', None, _('use git extended diff format')),
114 114 ('', 'binary', None, _('generate binary diffs in git mode (default)')),
115 115 ('', 'nodates', None, _('omit dates from diff headers'))
116 116 ]
117 117
118 118 diffwsopts = [
119 119 ('w', 'ignore-all-space', None,
120 120 _('ignore white space when comparing lines')),
121 121 ('b', 'ignore-space-change', None,
122 122 _('ignore changes in the amount of white space')),
123 123 ('B', 'ignore-blank-lines', None,
124 124 _('ignore changes whose lines are all blank')),
125 125 ('Z', 'ignore-space-at-eol', None,
126 126 _('ignore changes in whitespace at EOL')),
127 127 ]
128 128
129 129 diffopts2 = [
130 130 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
131 131 ('p', 'show-function', None, _('show which function each change is in')),
132 132 ('', 'reverse', None, _('produce a diff that undoes the changes')),
133 133 ] + diffwsopts + [
134 134 ('U', 'unified', '',
135 135 _('number of lines of context to show'), _('NUM')),
136 136 ('', 'stat', None, _('output diffstat-style summary of changes')),
137 137 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
138 138 ]
139 139
140 140 mergetoolopts = [
141 141 ('t', 'tool', '', _('specify merge tool')),
142 142 ]
143 143
144 144 similarityopts = [
145 145 ('s', 'similarity', '',
146 146 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
147 147 ]
148 148
149 149 subrepoopts = [
150 150 ('S', 'subrepos', None,
151 151 _('recurse into subrepositories'))
152 152 ]
153 153
154 154 debugrevlogopts = [
155 155 ('c', 'changelog', False, _('open changelog')),
156 156 ('m', 'manifest', False, _('open manifest')),
157 157 ('', 'dir', '', _('open directory manifest')),
158 158 ]
159 159
160 160 # special string such that everything below this line will be ingored in the
161 161 # editor text
162 162 _linebelow = "^HG: ------------------------ >8 ------------------------$"
163 163
164 164 def ishunk(x):
165 165 hunkclasses = (crecordmod.uihunk, patch.recordhunk)
166 166 return isinstance(x, hunkclasses)
167 167
168 168 def newandmodified(chunks, originalchunks):
169 169 newlyaddedandmodifiedfiles = set()
170 170 for chunk in chunks:
171 171 if ishunk(chunk) and chunk.header.isnewfile() and chunk not in \
172 172 originalchunks:
173 173 newlyaddedandmodifiedfiles.add(chunk.header.filename())
174 174 return newlyaddedandmodifiedfiles
175 175
176 176 def parsealiases(cmd):
177 177 return cmd.lstrip("^").split("|")
178 178
179 179 def setupwrapcolorwrite(ui):
180 180 # wrap ui.write so diff output can be labeled/colorized
181 181 def wrapwrite(orig, *args, **kw):
182 182 label = kw.pop('label', '')
183 183 for chunk, l in patch.difflabel(lambda: args):
184 184 orig(chunk, label=label + l)
185 185
186 186 oldwrite = ui.write
187 187 def wrap(*args, **kwargs):
188 188 return wrapwrite(oldwrite, *args, **kwargs)
189 189 setattr(ui, 'write', wrap)
190 190 return oldwrite
191 191
192 192 def filterchunks(ui, originalhunks, usecurses, testfile, operation=None):
193 193 if usecurses:
194 194 if testfile:
195 195 recordfn = crecordmod.testdecorator(testfile,
196 196 crecordmod.testchunkselector)
197 197 else:
198 198 recordfn = crecordmod.chunkselector
199 199
200 200 return crecordmod.filterpatch(ui, originalhunks, recordfn, operation)
201 201
202 202 else:
203 203 return patch.filterpatch(ui, originalhunks, operation)
204 204
205 205 def recordfilter(ui, originalhunks, operation=None):
206 206 """ Prompts the user to filter the originalhunks and return a list of
207 207 selected hunks.
208 208 *operation* is used for to build ui messages to indicate the user what
209 209 kind of filtering they are doing: reverting, committing, shelving, etc.
210 210 (see patch.filterpatch).
211 211 """
212 212 usecurses = crecordmod.checkcurses(ui)
213 213 testfile = ui.config('experimental', 'crecordtest')
214 214 oldwrite = setupwrapcolorwrite(ui)
215 215 try:
216 216 newchunks, newopts = filterchunks(ui, originalhunks, usecurses,
217 217 testfile, operation)
218 218 finally:
219 219 ui.write = oldwrite
220 220 return newchunks, newopts
221 221
222 222 def dorecord(ui, repo, commitfunc, cmdsuggest, backupall,
223 223 filterfn, *pats, **opts):
224 224 from . import merge as mergemod
225 225 opts = pycompat.byteskwargs(opts)
226 226 if not ui.interactive():
227 227 if cmdsuggest:
228 228 msg = _('running non-interactively, use %s instead') % cmdsuggest
229 229 else:
230 230 msg = _('running non-interactively')
231 231 raise error.Abort(msg)
232 232
233 233 # make sure username is set before going interactive
234 234 if not opts.get('user'):
235 235 ui.username() # raise exception, username not provided
236 236
237 237 def recordfunc(ui, repo, message, match, opts):
238 238 """This is generic record driver.
239 239
240 240 Its job is to interactively filter local changes, and
241 241 accordingly prepare working directory into a state in which the
242 242 job can be delegated to a non-interactive commit command such as
243 243 'commit' or 'qrefresh'.
244 244
245 245 After the actual job is done by non-interactive command, the
246 246 working directory is restored to its original state.
247 247
248 248 In the end we'll record interesting changes, and everything else
249 249 will be left in place, so the user can continue working.
250 250 """
251 251
252 252 checkunfinished(repo, commit=True)
253 253 wctx = repo[None]
254 254 merge = len(wctx.parents()) > 1
255 255 if merge:
256 256 raise error.Abort(_('cannot partially commit a merge '
257 257 '(use "hg commit" instead)'))
258 258
259 259 def fail(f, msg):
260 260 raise error.Abort('%s: %s' % (f, msg))
261 261
262 262 force = opts.get('force')
263 263 if not force:
264 264 vdirs = []
265 265 match.explicitdir = vdirs.append
266 266 match.bad = fail
267 267
268 268 status = repo.status(match=match)
269 269 if not force:
270 270 repo.checkcommitpatterns(wctx, vdirs, match, status, fail)
271 271 diffopts = patch.difffeatureopts(ui, opts=opts, whitespace=True)
272 272 diffopts.nodates = True
273 273 diffopts.git = True
274 274 diffopts.showfunc = True
275 275 originaldiff = patch.diff(repo, changes=status, opts=diffopts)
276 276 originalchunks = patch.parsepatch(originaldiff)
277 277
278 278 # 1. filter patch, since we are intending to apply subset of it
279 279 try:
280 280 chunks, newopts = filterfn(ui, originalchunks)
281 281 except patch.PatchError as err:
282 282 raise error.Abort(_('error parsing patch: %s') % err)
283 283 opts.update(newopts)
284 284
285 285 # We need to keep a backup of files that have been newly added and
286 286 # modified during the recording process because there is a previous
287 287 # version without the edit in the workdir
288 288 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
289 289 contenders = set()
290 290 for h in chunks:
291 291 try:
292 292 contenders.update(set(h.files()))
293 293 except AttributeError:
294 294 pass
295 295
296 296 changed = status.modified + status.added + status.removed
297 297 newfiles = [f for f in changed if f in contenders]
298 298 if not newfiles:
299 299 ui.status(_('no changes to record\n'))
300 300 return 0
301 301
302 302 modified = set(status.modified)
303 303
304 304 # 2. backup changed files, so we can restore them in the end
305 305
306 306 if backupall:
307 307 tobackup = changed
308 308 else:
309 309 tobackup = [f for f in newfiles if f in modified or f in \
310 310 newlyaddedandmodifiedfiles]
311 311 backups = {}
312 312 if tobackup:
313 313 backupdir = repo.vfs.join('record-backups')
314 314 try:
315 315 os.mkdir(backupdir)
316 316 except OSError as err:
317 317 if err.errno != errno.EEXIST:
318 318 raise
319 319 try:
320 320 # backup continues
321 321 for f in tobackup:
322 322 fd, tmpname = tempfile.mkstemp(prefix=f.replace('/', '_')+'.',
323 323 dir=backupdir)
324 324 os.close(fd)
325 325 ui.debug('backup %r as %r\n' % (f, tmpname))
326 326 util.copyfile(repo.wjoin(f), tmpname, copystat=True)
327 327 backups[f] = tmpname
328 328
329 329 fp = stringio()
330 330 for c in chunks:
331 331 fname = c.filename()
332 332 if fname in backups:
333 333 c.write(fp)
334 334 dopatch = fp.tell()
335 335 fp.seek(0)
336 336
337 337 # 2.5 optionally review / modify patch in text editor
338 338 if opts.get('review', False):
339 339 patchtext = (crecordmod.diffhelptext
340 340 + crecordmod.patchhelptext
341 341 + fp.read())
342 342 reviewedpatch = ui.edit(patchtext, "",
343 343 action="diff",
344 344 repopath=repo.path)
345 345 fp.truncate(0)
346 346 fp.write(reviewedpatch)
347 347 fp.seek(0)
348 348
349 349 [os.unlink(repo.wjoin(c)) for c in newlyaddedandmodifiedfiles]
350 350 # 3a. apply filtered patch to clean repo (clean)
351 351 if backups:
352 352 # Equivalent to hg.revert
353 353 m = scmutil.matchfiles(repo, backups.keys())
354 354 mergemod.update(repo, repo.dirstate.p1(),
355 355 False, True, matcher=m)
356 356
357 357 # 3b. (apply)
358 358 if dopatch:
359 359 try:
360 360 ui.debug('applying patch\n')
361 361 ui.debug(fp.getvalue())
362 362 patch.internalpatch(ui, repo, fp, 1, eolmode=None)
363 363 except patch.PatchError as err:
364 364 raise error.Abort(str(err))
365 365 del fp
366 366
367 367 # 4. We prepared working directory according to filtered
368 368 # patch. Now is the time to delegate the job to
369 369 # commit/qrefresh or the like!
370 370
371 371 # Make all of the pathnames absolute.
372 372 newfiles = [repo.wjoin(nf) for nf in newfiles]
373 373 return commitfunc(ui, repo, *newfiles, **opts)
374 374 finally:
375 375 # 5. finally restore backed-up files
376 376 try:
377 377 dirstate = repo.dirstate
378 378 for realname, tmpname in backups.iteritems():
379 379 ui.debug('restoring %r to %r\n' % (tmpname, realname))
380 380
381 381 if dirstate[realname] == 'n':
382 382 # without normallookup, restoring timestamp
383 383 # may cause partially committed files
384 384 # to be treated as unmodified
385 385 dirstate.normallookup(realname)
386 386
387 387 # copystat=True here and above are a hack to trick any
388 388 # editors that have f open that we haven't modified them.
389 389 #
390 390 # Also note that this racy as an editor could notice the
391 391 # file's mtime before we've finished writing it.
392 392 util.copyfile(tmpname, repo.wjoin(realname), copystat=True)
393 393 os.unlink(tmpname)
394 394 if tobackup:
395 395 os.rmdir(backupdir)
396 396 except OSError:
397 397 pass
398 398
399 399 def recordinwlock(ui, repo, message, match, opts):
400 400 with repo.wlock():
401 401 return recordfunc(ui, repo, message, match, opts)
402 402
403 403 return commit(ui, repo, recordinwlock, pats, opts)
404 404
405 405 def tersestatus(root, statlist, status, ignorefn, ignore):
406 406 """
407 407 Returns a list of statuses with directory collapsed if all the files in the
408 408 directory has the same status.
409 409 """
410 410
411 411 def numfiles(dirname):
412 412 """
413 413 Calculates the number of tracked files in a given directory which also
414 414 includes files which were removed or deleted. Considers ignored files
415 415 if ignore argument is True or 'i' is present in status argument.
416 416 """
417 417 if lencache.get(dirname):
418 418 return lencache[dirname]
419 419 if 'i' in status or ignore:
420 420 def match(localpath):
421 421 absolutepath = os.path.join(root, localpath)
422 422 if os.path.isdir(absolutepath) and isemptydir(absolutepath):
423 423 return True
424 424 return False
425 425 else:
426 426 def match(localpath):
427 427 # there can be directory whose all the files are ignored and
428 428 # hence the drectory should also be ignored while counting
429 429 # number of files or subdirs in it's parent directory. This
430 430 # checks the same.
431 431 # XXX: We need a better logic here.
432 432 if os.path.isdir(os.path.join(root, localpath)):
433 433 return isignoreddir(localpath)
434 434 else:
435 435 # XXX: there can be files which have the ignored pattern but
436 436 # are not ignored. That leads to bug in counting number of
437 437 # tracked files in the directory.
438 438 return ignorefn(localpath)
439 439 lendir = 0
440 440 abspath = os.path.join(root, dirname)
441 441 # There might be cases when a directory does not exists as the whole
442 442 # directory can be removed and/or deleted.
443 443 try:
444 444 for f in os.listdir(abspath):
445 445 localpath = os.path.join(dirname, f)
446 446 if not match(localpath):
447 447 lendir += 1
448 448 except OSError:
449 449 pass
450 450 lendir += len(absentdir.get(dirname, []))
451 451 lencache[dirname] = lendir
452 452 return lendir
453 453
454 454 def isemptydir(abspath):
455 455 """
456 456 Check whether a directory is empty or not, i.e. there is no files in the
457 457 directory and all its subdirectories.
458 458 """
459 459 for f in os.listdir(abspath):
460 460 fullpath = os.path.join(abspath, f)
461 461 if os.path.isdir(fullpath):
462 462 # recursion here
463 463 ret = isemptydir(fullpath)
464 464 if not ret:
465 465 return False
466 466 else:
467 467 return False
468 468 return True
469 469
470 470 def isignoreddir(localpath):
471 471 """Return True if `localpath` directory is ignored or contains only
472 472 ignored files and should hence be considered ignored.
473 473 """
474 474 dirpath = os.path.join(root, localpath)
475 475 if ignorefn(dirpath):
476 476 return True
477 477 for f in os.listdir(dirpath):
478 478 filepath = os.path.join(dirpath, f)
479 479 if os.path.isdir(filepath):
480 480 # recursion here
481 481 ret = isignoreddir(os.path.join(localpath, f))
482 482 if not ret:
483 483 return False
484 484 else:
485 485 if not ignorefn(os.path.join(localpath, f)):
486 486 return False
487 487 return True
488 488
489 489 def absentones(removedfiles, missingfiles):
490 490 """
491 491 Returns a dictionary of directories with files in it which are either
492 492 removed or missing (deleted) in them.
493 493 """
494 494 absentdir = {}
495 495 absentfiles = removedfiles + missingfiles
496 496 while absentfiles:
497 497 f = absentfiles.pop()
498 498 par = os.path.dirname(f)
499 499 if par == '':
500 500 continue
501 501 # we need to store files rather than number of files as some files
502 502 # or subdirectories in a directory can be counted twice. This is
503 503 # also we have used sets here.
504 504 try:
505 505 absentdir[par].add(f)
506 506 except KeyError:
507 507 absentdir[par] = set([f])
508 508 absentfiles.append(par)
509 509 return absentdir
510 510
511 511 indexes = {'m': 0, 'a': 1, 'r': 2, 'd': 3, 'u': 4, 'i': 5, 'c': 6}
512 512 # get a dictonary of directories and files which are missing as os.listdir()
513 513 # won't be able to list them.
514 514 absentdir = absentones(statlist[2], statlist[3])
515 515 finalrs = [[]] * len(indexes)
516 516 didsomethingchanged = False
517 517 # dictionary to store number of files and subdir in a directory so that we
518 518 # don't compute that again.
519 519 lencache = {}
520 520
521 521 for st in pycompat.bytestr(status):
522 522
523 523 try:
524 524 ind = indexes[st]
525 525 except KeyError:
526 526 # TODO: Need a better error message here
527 527 raise error.Abort("'%s' not recognized" % st)
528 528
529 529 sfiles = statlist[ind]
530 530 if not sfiles:
531 531 continue
532 532 pardict = {}
533 533 for a in sfiles:
534 534 par = os.path.dirname(a)
535 535 pardict.setdefault(par, []).append(a)
536 536
537 537 rs = []
538 538 newls = []
539 539 for par, files in pardict.iteritems():
540 540 lenpar = numfiles(par)
541 541 if lenpar == len(files):
542 542 newls.append(par)
543 543
544 544 if not newls:
545 545 continue
546 546
547 547 while newls:
548 548 newel = newls.pop()
549 549 if newel == '':
550 550 continue
551 551 parn = os.path.dirname(newel)
552 552 pardict[newel] = []
553 553 # Adding pycompat.ossep as newel is a directory.
554 554 pardict.setdefault(parn, []).append(newel + pycompat.ossep)
555 555 lenpar = numfiles(parn)
556 556 if lenpar == len(pardict[parn]):
557 557 newls.append(parn)
558 558
559 559 # dict.values() for Py3 compatibility
560 560 for files in pardict.values():
561 561 rs.extend(files)
562 562
563 563 rs.sort()
564 564 finalrs[ind] = rs
565 565 didsomethingchanged = True
566 566
567 567 # If nothing is changed, make sure the order of files is preserved.
568 568 if not didsomethingchanged:
569 569 return statlist
570 570
571 571 for x in xrange(len(indexes)):
572 572 if not finalrs[x]:
573 573 finalrs[x] = statlist[x]
574 574
575 575 return finalrs
576 576
577 577 def _commentlines(raw):
578 578 '''Surround lineswith a comment char and a new line'''
579 579 lines = raw.splitlines()
580 580 commentedlines = ['# %s' % line for line in lines]
581 581 return '\n'.join(commentedlines) + '\n'
582 582
583 583 def _conflictsmsg(repo):
584 584 # avoid merge cycle
585 585 from . import merge as mergemod
586 586 mergestate = mergemod.mergestate.read(repo)
587 587 if not mergestate.active():
588 588 return
589 589
590 590 m = scmutil.match(repo[None])
591 591 unresolvedlist = [f for f in mergestate.unresolved() if m(f)]
592 592 if unresolvedlist:
593 593 mergeliststr = '\n'.join(
594 594 [' %s' % os.path.relpath(
595 595 os.path.join(repo.root, path),
596 596 pycompat.getcwd()) for path in unresolvedlist])
597 597 msg = _('''Unresolved merge conflicts:
598 598
599 599 %s
600 600
601 601 To mark files as resolved: hg resolve --mark FILE''') % mergeliststr
602 602 else:
603 603 msg = _('No unresolved merge conflicts.')
604 604
605 605 return _commentlines(msg)
606 606
607 607 def _helpmessage(continuecmd, abortcmd):
608 608 msg = _('To continue: %s\n'
609 609 'To abort: %s') % (continuecmd, abortcmd)
610 610 return _commentlines(msg)
611 611
612 612 def _rebasemsg():
613 613 return _helpmessage('hg rebase --continue', 'hg rebase --abort')
614 614
615 615 def _histeditmsg():
616 616 return _helpmessage('hg histedit --continue', 'hg histedit --abort')
617 617
618 618 def _unshelvemsg():
619 619 return _helpmessage('hg unshelve --continue', 'hg unshelve --abort')
620 620
621 621 def _updatecleanmsg(dest=None):
622 622 warning = _('warning: this will discard uncommitted changes')
623 623 return 'hg update --clean %s (%s)' % (dest or '.', warning)
624 624
625 625 def _graftmsg():
626 626 # tweakdefaults requires `update` to have a rev hence the `.`
627 627 return _helpmessage('hg graft --continue', _updatecleanmsg())
628 628
629 629 def _mergemsg():
630 630 # tweakdefaults requires `update` to have a rev hence the `.`
631 631 return _helpmessage('hg commit', _updatecleanmsg())
632 632
633 633 def _bisectmsg():
634 634 msg = _('To mark the changeset good: hg bisect --good\n'
635 635 'To mark the changeset bad: hg bisect --bad\n'
636 636 'To abort: hg bisect --reset\n')
637 637 return _commentlines(msg)
638 638
639 639 def fileexistspredicate(filename):
640 640 return lambda repo: repo.vfs.exists(filename)
641 641
642 642 def _mergepredicate(repo):
643 643 return len(repo[None].parents()) > 1
644 644
645 645 STATES = (
646 646 # (state, predicate to detect states, helpful message function)
647 647 ('histedit', fileexistspredicate('histedit-state'), _histeditmsg),
648 648 ('bisect', fileexistspredicate('bisect.state'), _bisectmsg),
649 649 ('graft', fileexistspredicate('graftstate'), _graftmsg),
650 650 ('unshelve', fileexistspredicate('unshelverebasestate'), _unshelvemsg),
651 651 ('rebase', fileexistspredicate('rebasestate'), _rebasemsg),
652 652 # The merge state is part of a list that will be iterated over.
653 653 # They need to be last because some of the other unfinished states may also
654 654 # be in a merge or update state (eg. rebase, histedit, graft, etc).
655 655 # We want those to have priority.
656 656 ('merge', _mergepredicate, _mergemsg),
657 657 )
658 658
659 659 def _getrepostate(repo):
660 660 # experimental config: commands.status.skipstates
661 661 skip = set(repo.ui.configlist('commands', 'status.skipstates'))
662 662 for state, statedetectionpredicate, msgfn in STATES:
663 663 if state in skip:
664 664 continue
665 665 if statedetectionpredicate(repo):
666 666 return (state, statedetectionpredicate, msgfn)
667 667
668 668 def morestatus(repo, fm):
669 669 statetuple = _getrepostate(repo)
670 670 label = 'status.morestatus'
671 671 if statetuple:
672 672 fm.startitem()
673 673 state, statedetectionpredicate, helpfulmsg = statetuple
674 674 statemsg = _('The repository is in an unfinished *%s* state.') % state
675 675 fm.write('statemsg', '%s\n', _commentlines(statemsg), label=label)
676 676 conmsg = _conflictsmsg(repo)
677 677 if conmsg:
678 678 fm.write('conflictsmsg', '%s\n', conmsg, label=label)
679 679 if helpfulmsg:
680 680 helpmsg = helpfulmsg()
681 681 fm.write('helpmsg', '%s\n', helpmsg, label=label)
682 682
683 683 def findpossible(cmd, table, strict=False):
684 684 """
685 685 Return cmd -> (aliases, command table entry)
686 686 for each matching command.
687 687 Return debug commands (or their aliases) only if no normal command matches.
688 688 """
689 689 choice = {}
690 690 debugchoice = {}
691 691
692 692 if cmd in table:
693 693 # short-circuit exact matches, "log" alias beats "^log|history"
694 694 keys = [cmd]
695 695 else:
696 696 keys = table.keys()
697 697
698 698 allcmds = []
699 699 for e in keys:
700 700 aliases = parsealiases(e)
701 701 allcmds.extend(aliases)
702 702 found = None
703 703 if cmd in aliases:
704 704 found = cmd
705 705 elif not strict:
706 706 for a in aliases:
707 707 if a.startswith(cmd):
708 708 found = a
709 709 break
710 710 if found is not None:
711 711 if aliases[0].startswith("debug") or found.startswith("debug"):
712 712 debugchoice[found] = (aliases, table[e])
713 713 else:
714 714 choice[found] = (aliases, table[e])
715 715
716 716 if not choice and debugchoice:
717 717 choice = debugchoice
718 718
719 719 return choice, allcmds
720 720
721 721 def findcmd(cmd, table, strict=True):
722 722 """Return (aliases, command table entry) for command string."""
723 723 choice, allcmds = findpossible(cmd, table, strict)
724 724
725 725 if cmd in choice:
726 726 return choice[cmd]
727 727
728 728 if len(choice) > 1:
729 729 clist = sorted(choice)
730 730 raise error.AmbiguousCommand(cmd, clist)
731 731
732 732 if choice:
733 733 return list(choice.values())[0]
734 734
735 735 raise error.UnknownCommand(cmd, allcmds)
736 736
737 737 def findrepo(p):
738 738 while not os.path.isdir(os.path.join(p, ".hg")):
739 739 oldp, p = p, os.path.dirname(p)
740 740 if p == oldp:
741 741 return None
742 742
743 743 return p
744 744
745 745 def bailifchanged(repo, merge=True, hint=None):
746 746 """ enforce the precondition that working directory must be clean.
747 747
748 748 'merge' can be set to false if a pending uncommitted merge should be
749 749 ignored (such as when 'update --check' runs).
750 750
751 751 'hint' is the usual hint given to Abort exception.
752 752 """
753 753
754 754 if merge and repo.dirstate.p2() != nullid:
755 755 raise error.Abort(_('outstanding uncommitted merge'), hint=hint)
756 756 modified, added, removed, deleted = repo.status()[:4]
757 757 if modified or added or removed or deleted:
758 758 raise error.Abort(_('uncommitted changes'), hint=hint)
759 759 ctx = repo[None]
760 760 for s in sorted(ctx.substate):
761 761 ctx.sub(s).bailifchanged(hint=hint)
762 762
763 763 def logmessage(ui, opts):
764 764 """ get the log message according to -m and -l option """
765 765 message = opts.get('message')
766 766 logfile = opts.get('logfile')
767 767
768 768 if message and logfile:
769 769 raise error.Abort(_('options --message and --logfile are mutually '
770 770 'exclusive'))
771 771 if not message and logfile:
772 772 try:
773 773 if isstdiofilename(logfile):
774 774 message = ui.fin.read()
775 775 else:
776 776 message = '\n'.join(util.readfile(logfile).splitlines())
777 777 except IOError as inst:
778 778 raise error.Abort(_("can't read commit message '%s': %s") %
779 779 (logfile, encoding.strtolocal(inst.strerror)))
780 780 return message
781 781
782 782 def mergeeditform(ctxorbool, baseformname):
783 783 """return appropriate editform name (referencing a committemplate)
784 784
785 785 'ctxorbool' is either a ctx to be committed, or a bool indicating whether
786 786 merging is committed.
787 787
788 788 This returns baseformname with '.merge' appended if it is a merge,
789 789 otherwise '.normal' is appended.
790 790 """
791 791 if isinstance(ctxorbool, bool):
792 792 if ctxorbool:
793 793 return baseformname + ".merge"
794 794 elif 1 < len(ctxorbool.parents()):
795 795 return baseformname + ".merge"
796 796
797 797 return baseformname + ".normal"
798 798
799 799 def getcommiteditor(edit=False, finishdesc=None, extramsg=None,
800 800 editform='', **opts):
801 801 """get appropriate commit message editor according to '--edit' option
802 802
803 803 'finishdesc' is a function to be called with edited commit message
804 804 (= 'description' of the new changeset) just after editing, but
805 805 before checking empty-ness. It should return actual text to be
806 806 stored into history. This allows to change description before
807 807 storing.
808 808
809 809 'extramsg' is a extra message to be shown in the editor instead of
810 810 'Leave message empty to abort commit' line. 'HG: ' prefix and EOL
811 811 is automatically added.
812 812
813 813 'editform' is a dot-separated list of names, to distinguish
814 814 the purpose of commit text editing.
815 815
816 816 'getcommiteditor' returns 'commitforceeditor' regardless of
817 817 'edit', if one of 'finishdesc' or 'extramsg' is specified, because
818 818 they are specific for usage in MQ.
819 819 """
820 820 if edit or finishdesc or extramsg:
821 821 return lambda r, c, s: commitforceeditor(r, c, s,
822 822 finishdesc=finishdesc,
823 823 extramsg=extramsg,
824 824 editform=editform)
825 825 elif editform:
826 826 return lambda r, c, s: commiteditor(r, c, s, editform=editform)
827 827 else:
828 828 return commiteditor
829 829
830 830 def loglimit(opts):
831 831 """get the log limit according to option -l/--limit"""
832 832 limit = opts.get('limit')
833 833 if limit:
834 834 try:
835 835 limit = int(limit)
836 836 except ValueError:
837 837 raise error.Abort(_('limit must be a positive integer'))
838 838 if limit <= 0:
839 839 raise error.Abort(_('limit must be positive'))
840 840 else:
841 841 limit = None
842 842 return limit
843 843
844 844 def makefilename(repo, pat, node, desc=None,
845 845 total=None, seqno=None, revwidth=None, pathname=None):
846 846 node_expander = {
847 847 'H': lambda: hex(node),
848 848 'R': lambda: str(repo.changelog.rev(node)),
849 849 'h': lambda: short(node),
850 850 'm': lambda: re.sub('[^\w]', '_', str(desc))
851 851 }
852 852 expander = {
853 853 '%': lambda: '%',
854 854 'b': lambda: os.path.basename(repo.root),
855 855 }
856 856
857 857 try:
858 858 if node:
859 859 expander.update(node_expander)
860 860 if node:
861 861 expander['r'] = (lambda:
862 862 str(repo.changelog.rev(node)).zfill(revwidth or 0))
863 863 if total is not None:
864 864 expander['N'] = lambda: str(total)
865 865 if seqno is not None:
866 866 expander['n'] = lambda: str(seqno)
867 867 if total is not None and seqno is not None:
868 868 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
869 869 if pathname is not None:
870 870 expander['s'] = lambda: os.path.basename(pathname)
871 871 expander['d'] = lambda: os.path.dirname(pathname) or '.'
872 872 expander['p'] = lambda: pathname
873 873
874 874 newname = []
875 875 patlen = len(pat)
876 876 i = 0
877 877 while i < patlen:
878 878 c = pat[i:i + 1]
879 879 if c == '%':
880 880 i += 1
881 881 c = pat[i:i + 1]
882 882 c = expander[c]()
883 883 newname.append(c)
884 884 i += 1
885 885 return ''.join(newname)
886 886 except KeyError as inst:
887 887 raise error.Abort(_("invalid format spec '%%%s' in output filename") %
888 888 inst.args[0])
889 889
890 890 def isstdiofilename(pat):
891 891 """True if the given pat looks like a filename denoting stdin/stdout"""
892 892 return not pat or pat == '-'
893 893
894 894 class _unclosablefile(object):
895 895 def __init__(self, fp):
896 896 self._fp = fp
897 897
898 898 def close(self):
899 899 pass
900 900
901 901 def __iter__(self):
902 902 return iter(self._fp)
903 903
904 904 def __getattr__(self, attr):
905 905 return getattr(self._fp, attr)
906 906
907 907 def __enter__(self):
908 908 return self
909 909
910 910 def __exit__(self, exc_type, exc_value, exc_tb):
911 911 pass
912 912
913 913 def makefileobj(repo, pat, node=None, desc=None, total=None,
914 914 seqno=None, revwidth=None, mode='wb', modemap=None,
915 915 pathname=None):
916 916
917 917 writable = mode not in ('r', 'rb')
918 918
919 919 if isstdiofilename(pat):
920 920 if writable:
921 921 fp = repo.ui.fout
922 922 else:
923 923 fp = repo.ui.fin
924 924 return _unclosablefile(fp)
925 925 fn = makefilename(repo, pat, node, desc, total, seqno, revwidth, pathname)
926 926 if modemap is not None:
927 927 mode = modemap.get(fn, mode)
928 928 if mode == 'wb':
929 929 modemap[fn] = 'ab'
930 930 return open(fn, mode)
931 931
932 932 def openrevlog(repo, cmd, file_, opts):
933 933 """opens the changelog, manifest, a filelog or a given revlog"""
934 934 cl = opts['changelog']
935 935 mf = opts['manifest']
936 936 dir = opts['dir']
937 937 msg = None
938 938 if cl and mf:
939 939 msg = _('cannot specify --changelog and --manifest at the same time')
940 940 elif cl and dir:
941 941 msg = _('cannot specify --changelog and --dir at the same time')
942 942 elif cl or mf or dir:
943 943 if file_:
944 944 msg = _('cannot specify filename with --changelog or --manifest')
945 945 elif not repo:
946 946 msg = _('cannot specify --changelog or --manifest or --dir '
947 947 'without a repository')
948 948 if msg:
949 949 raise error.Abort(msg)
950 950
951 951 r = None
952 952 if repo:
953 953 if cl:
954 954 r = repo.unfiltered().changelog
955 955 elif dir:
956 956 if 'treemanifest' not in repo.requirements:
957 957 raise error.Abort(_("--dir can only be used on repos with "
958 958 "treemanifest enabled"))
959 959 dirlog = repo.manifestlog._revlog.dirlog(dir)
960 960 if len(dirlog):
961 961 r = dirlog
962 962 elif mf:
963 963 r = repo.manifestlog._revlog
964 964 elif file_:
965 965 filelog = repo.file(file_)
966 966 if len(filelog):
967 967 r = filelog
968 968 if not r:
969 969 if not file_:
970 970 raise error.CommandError(cmd, _('invalid arguments'))
971 971 if not os.path.isfile(file_):
972 972 raise error.Abort(_("revlog '%s' not found") % file_)
973 973 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
974 974 file_[:-2] + ".i")
975 975 return r
976 976
977 977 def copy(ui, repo, pats, opts, rename=False):
978 978 # called with the repo lock held
979 979 #
980 980 # hgsep => pathname that uses "/" to separate directories
981 981 # ossep => pathname that uses os.sep to separate directories
982 982 cwd = repo.getcwd()
983 983 targets = {}
984 984 after = opts.get("after")
985 985 dryrun = opts.get("dry_run")
986 986 wctx = repo[None]
987 987
988 988 def walkpat(pat):
989 989 srcs = []
990 990 if after:
991 991 badstates = '?'
992 992 else:
993 993 badstates = '?r'
994 994 m = scmutil.match(wctx, [pat], opts, globbed=True)
995 995 for abs in wctx.walk(m):
996 996 state = repo.dirstate[abs]
997 997 rel = m.rel(abs)
998 998 exact = m.exact(abs)
999 999 if state in badstates:
1000 1000 if exact and state == '?':
1001 1001 ui.warn(_('%s: not copying - file is not managed\n') % rel)
1002 1002 if exact and state == 'r':
1003 1003 ui.warn(_('%s: not copying - file has been marked for'
1004 1004 ' remove\n') % rel)
1005 1005 continue
1006 1006 # abs: hgsep
1007 1007 # rel: ossep
1008 1008 srcs.append((abs, rel, exact))
1009 1009 return srcs
1010 1010
1011 1011 # abssrc: hgsep
1012 1012 # relsrc: ossep
1013 1013 # otarget: ossep
1014 1014 def copyfile(abssrc, relsrc, otarget, exact):
1015 1015 abstarget = pathutil.canonpath(repo.root, cwd, otarget)
1016 1016 if '/' in abstarget:
1017 1017 # We cannot normalize abstarget itself, this would prevent
1018 1018 # case only renames, like a => A.
1019 1019 abspath, absname = abstarget.rsplit('/', 1)
1020 1020 abstarget = repo.dirstate.normalize(abspath) + '/' + absname
1021 1021 reltarget = repo.pathto(abstarget, cwd)
1022 1022 target = repo.wjoin(abstarget)
1023 1023 src = repo.wjoin(abssrc)
1024 1024 state = repo.dirstate[abstarget]
1025 1025
1026 1026 scmutil.checkportable(ui, abstarget)
1027 1027
1028 1028 # check for collisions
1029 1029 prevsrc = targets.get(abstarget)
1030 1030 if prevsrc is not None:
1031 1031 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
1032 1032 (reltarget, repo.pathto(abssrc, cwd),
1033 1033 repo.pathto(prevsrc, cwd)))
1034 1034 return
1035 1035
1036 1036 # check for overwrites
1037 1037 exists = os.path.lexists(target)
1038 1038 samefile = False
1039 1039 if exists and abssrc != abstarget:
1040 1040 if (repo.dirstate.normalize(abssrc) ==
1041 1041 repo.dirstate.normalize(abstarget)):
1042 1042 if not rename:
1043 1043 ui.warn(_("%s: can't copy - same file\n") % reltarget)
1044 1044 return
1045 1045 exists = False
1046 1046 samefile = True
1047 1047
1048 1048 if not after and exists or after and state in 'mn':
1049 1049 if not opts['force']:
1050 1050 if state in 'mn':
1051 1051 msg = _('%s: not overwriting - file already committed\n')
1052 1052 if after:
1053 1053 flags = '--after --force'
1054 1054 else:
1055 1055 flags = '--force'
1056 1056 if rename:
1057 1057 hint = _('(hg rename %s to replace the file by '
1058 1058 'recording a rename)\n') % flags
1059 1059 else:
1060 1060 hint = _('(hg copy %s to replace the file by '
1061 1061 'recording a copy)\n') % flags
1062 1062 else:
1063 1063 msg = _('%s: not overwriting - file exists\n')
1064 1064 if rename:
1065 1065 hint = _('(hg rename --after to record the rename)\n')
1066 1066 else:
1067 1067 hint = _('(hg copy --after to record the copy)\n')
1068 1068 ui.warn(msg % reltarget)
1069 1069 ui.warn(hint)
1070 1070 return
1071 1071
1072 1072 if after:
1073 1073 if not exists:
1074 1074 if rename:
1075 1075 ui.warn(_('%s: not recording move - %s does not exist\n') %
1076 1076 (relsrc, reltarget))
1077 1077 else:
1078 1078 ui.warn(_('%s: not recording copy - %s does not exist\n') %
1079 1079 (relsrc, reltarget))
1080 1080 return
1081 1081 elif not dryrun:
1082 1082 try:
1083 1083 if exists:
1084 1084 os.unlink(target)
1085 1085 targetdir = os.path.dirname(target) or '.'
1086 1086 if not os.path.isdir(targetdir):
1087 1087 os.makedirs(targetdir)
1088 1088 if samefile:
1089 1089 tmp = target + "~hgrename"
1090 1090 os.rename(src, tmp)
1091 1091 os.rename(tmp, target)
1092 1092 else:
1093 1093 util.copyfile(src, target)
1094 1094 srcexists = True
1095 1095 except IOError as inst:
1096 1096 if inst.errno == errno.ENOENT:
1097 1097 ui.warn(_('%s: deleted in working directory\n') % relsrc)
1098 1098 srcexists = False
1099 1099 else:
1100 1100 ui.warn(_('%s: cannot copy - %s\n') %
1101 1101 (relsrc, encoding.strtolocal(inst.strerror)))
1102 1102 return True # report a failure
1103 1103
1104 1104 if ui.verbose or not exact:
1105 1105 if rename:
1106 1106 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
1107 1107 else:
1108 1108 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
1109 1109
1110 1110 targets[abstarget] = abssrc
1111 1111
1112 1112 # fix up dirstate
1113 1113 scmutil.dirstatecopy(ui, repo, wctx, abssrc, abstarget,
1114 1114 dryrun=dryrun, cwd=cwd)
1115 1115 if rename and not dryrun:
1116 1116 if not after and srcexists and not samefile:
1117 1117 repo.wvfs.unlinkpath(abssrc)
1118 1118 wctx.forget([abssrc])
1119 1119
1120 1120 # pat: ossep
1121 1121 # dest ossep
1122 1122 # srcs: list of (hgsep, hgsep, ossep, bool)
1123 1123 # return: function that takes hgsep and returns ossep
1124 1124 def targetpathfn(pat, dest, srcs):
1125 1125 if os.path.isdir(pat):
1126 1126 abspfx = pathutil.canonpath(repo.root, cwd, pat)
1127 1127 abspfx = util.localpath(abspfx)
1128 1128 if destdirexists:
1129 1129 striplen = len(os.path.split(abspfx)[0])
1130 1130 else:
1131 1131 striplen = len(abspfx)
1132 1132 if striplen:
1133 1133 striplen += len(pycompat.ossep)
1134 1134 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
1135 1135 elif destdirexists:
1136 1136 res = lambda p: os.path.join(dest,
1137 1137 os.path.basename(util.localpath(p)))
1138 1138 else:
1139 1139 res = lambda p: dest
1140 1140 return res
1141 1141
1142 1142 # pat: ossep
1143 1143 # dest ossep
1144 1144 # srcs: list of (hgsep, hgsep, ossep, bool)
1145 1145 # return: function that takes hgsep and returns ossep
1146 1146 def targetpathafterfn(pat, dest, srcs):
1147 1147 if matchmod.patkind(pat):
1148 1148 # a mercurial pattern
1149 1149 res = lambda p: os.path.join(dest,
1150 1150 os.path.basename(util.localpath(p)))
1151 1151 else:
1152 1152 abspfx = pathutil.canonpath(repo.root, cwd, pat)
1153 1153 if len(abspfx) < len(srcs[0][0]):
1154 1154 # A directory. Either the target path contains the last
1155 1155 # component of the source path or it does not.
1156 1156 def evalpath(striplen):
1157 1157 score = 0
1158 1158 for s in srcs:
1159 1159 t = os.path.join(dest, util.localpath(s[0])[striplen:])
1160 1160 if os.path.lexists(t):
1161 1161 score += 1
1162 1162 return score
1163 1163
1164 1164 abspfx = util.localpath(abspfx)
1165 1165 striplen = len(abspfx)
1166 1166 if striplen:
1167 1167 striplen += len(pycompat.ossep)
1168 1168 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
1169 1169 score = evalpath(striplen)
1170 1170 striplen1 = len(os.path.split(abspfx)[0])
1171 1171 if striplen1:
1172 1172 striplen1 += len(pycompat.ossep)
1173 1173 if evalpath(striplen1) > score:
1174 1174 striplen = striplen1
1175 1175 res = lambda p: os.path.join(dest,
1176 1176 util.localpath(p)[striplen:])
1177 1177 else:
1178 1178 # a file
1179 1179 if destdirexists:
1180 1180 res = lambda p: os.path.join(dest,
1181 1181 os.path.basename(util.localpath(p)))
1182 1182 else:
1183 1183 res = lambda p: dest
1184 1184 return res
1185 1185
1186 1186 pats = scmutil.expandpats(pats)
1187 1187 if not pats:
1188 1188 raise error.Abort(_('no source or destination specified'))
1189 1189 if len(pats) == 1:
1190 1190 raise error.Abort(_('no destination specified'))
1191 1191 dest = pats.pop()
1192 1192 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
1193 1193 if not destdirexists:
1194 1194 if len(pats) > 1 or matchmod.patkind(pats[0]):
1195 1195 raise error.Abort(_('with multiple sources, destination must be an '
1196 1196 'existing directory'))
1197 1197 if util.endswithsep(dest):
1198 1198 raise error.Abort(_('destination %s is not a directory') % dest)
1199 1199
1200 1200 tfn = targetpathfn
1201 1201 if after:
1202 1202 tfn = targetpathafterfn
1203 1203 copylist = []
1204 1204 for pat in pats:
1205 1205 srcs = walkpat(pat)
1206 1206 if not srcs:
1207 1207 continue
1208 1208 copylist.append((tfn(pat, dest, srcs), srcs))
1209 1209 if not copylist:
1210 1210 raise error.Abort(_('no files to copy'))
1211 1211
1212 1212 errors = 0
1213 1213 for targetpath, srcs in copylist:
1214 1214 for abssrc, relsrc, exact in srcs:
1215 1215 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
1216 1216 errors += 1
1217 1217
1218 1218 if errors:
1219 1219 ui.warn(_('(consider using --after)\n'))
1220 1220
1221 1221 return errors != 0
1222 1222
1223 1223 ## facility to let extension process additional data into an import patch
1224 1224 # list of identifier to be executed in order
1225 1225 extrapreimport = [] # run before commit
1226 1226 extrapostimport = [] # run after commit
1227 1227 # mapping from identifier to actual import function
1228 1228 #
1229 1229 # 'preimport' are run before the commit is made and are provided the following
1230 1230 # arguments:
1231 1231 # - repo: the localrepository instance,
1232 1232 # - patchdata: data extracted from patch header (cf m.patch.patchheadermap),
1233 1233 # - extra: the future extra dictionary of the changeset, please mutate it,
1234 1234 # - opts: the import options.
1235 1235 # XXX ideally, we would just pass an ctx ready to be computed, that would allow
1236 1236 # mutation of in memory commit and more. Feel free to rework the code to get
1237 1237 # there.
1238 1238 extrapreimportmap = {}
1239 1239 # 'postimport' are run after the commit is made and are provided the following
1240 1240 # argument:
1241 1241 # - ctx: the changectx created by import.
1242 1242 extrapostimportmap = {}
1243 1243
1244 1244 def tryimportone(ui, repo, hunk, parents, opts, msgs, updatefunc):
1245 1245 """Utility function used by commands.import to import a single patch
1246 1246
1247 1247 This function is explicitly defined here to help the evolve extension to
1248 1248 wrap this part of the import logic.
1249 1249
1250 1250 The API is currently a bit ugly because it a simple code translation from
1251 1251 the import command. Feel free to make it better.
1252 1252
1253 1253 :hunk: a patch (as a binary string)
1254 1254 :parents: nodes that will be parent of the created commit
1255 1255 :opts: the full dict of option passed to the import command
1256 1256 :msgs: list to save commit message to.
1257 1257 (used in case we need to save it when failing)
1258 1258 :updatefunc: a function that update a repo to a given node
1259 1259 updatefunc(<repo>, <node>)
1260 1260 """
1261 1261 # avoid cycle context -> subrepo -> cmdutil
1262 1262 from . import context
1263 1263 extractdata = patch.extract(ui, hunk)
1264 1264 tmpname = extractdata.get('filename')
1265 1265 message = extractdata.get('message')
1266 1266 user = opts.get('user') or extractdata.get('user')
1267 1267 date = opts.get('date') or extractdata.get('date')
1268 1268 branch = extractdata.get('branch')
1269 1269 nodeid = extractdata.get('nodeid')
1270 1270 p1 = extractdata.get('p1')
1271 1271 p2 = extractdata.get('p2')
1272 1272
1273 1273 nocommit = opts.get('no_commit')
1274 1274 importbranch = opts.get('import_branch')
1275 1275 update = not opts.get('bypass')
1276 1276 strip = opts["strip"]
1277 1277 prefix = opts["prefix"]
1278 1278 sim = float(opts.get('similarity') or 0)
1279 1279 if not tmpname:
1280 1280 return (None, None, False)
1281 1281
1282 1282 rejects = False
1283 1283
1284 1284 try:
1285 1285 cmdline_message = logmessage(ui, opts)
1286 1286 if cmdline_message:
1287 1287 # pickup the cmdline msg
1288 1288 message = cmdline_message
1289 1289 elif message:
1290 1290 # pickup the patch msg
1291 1291 message = message.strip()
1292 1292 else:
1293 1293 # launch the editor
1294 1294 message = None
1295 1295 ui.debug('message:\n%s\n' % message)
1296 1296
1297 1297 if len(parents) == 1:
1298 1298 parents.append(repo[nullid])
1299 1299 if opts.get('exact'):
1300 1300 if not nodeid or not p1:
1301 1301 raise error.Abort(_('not a Mercurial patch'))
1302 1302 p1 = repo[p1]
1303 1303 p2 = repo[p2 or nullid]
1304 1304 elif p2:
1305 1305 try:
1306 1306 p1 = repo[p1]
1307 1307 p2 = repo[p2]
1308 1308 # Without any options, consider p2 only if the
1309 1309 # patch is being applied on top of the recorded
1310 1310 # first parent.
1311 1311 if p1 != parents[0]:
1312 1312 p1 = parents[0]
1313 1313 p2 = repo[nullid]
1314 1314 except error.RepoError:
1315 1315 p1, p2 = parents
1316 1316 if p2.node() == nullid:
1317 1317 ui.warn(_("warning: import the patch as a normal revision\n"
1318 1318 "(use --exact to import the patch as a merge)\n"))
1319 1319 else:
1320 1320 p1, p2 = parents
1321 1321
1322 1322 n = None
1323 1323 if update:
1324 1324 if p1 != parents[0]:
1325 1325 updatefunc(repo, p1.node())
1326 1326 if p2 != parents[1]:
1327 1327 repo.setparents(p1.node(), p2.node())
1328 1328
1329 1329 if opts.get('exact') or importbranch:
1330 1330 repo.dirstate.setbranch(branch or 'default')
1331 1331
1332 1332 partial = opts.get('partial', False)
1333 1333 files = set()
1334 1334 try:
1335 1335 patch.patch(ui, repo, tmpname, strip=strip, prefix=prefix,
1336 1336 files=files, eolmode=None, similarity=sim / 100.0)
1337 1337 except patch.PatchError as e:
1338 1338 if not partial:
1339 1339 raise error.Abort(str(e))
1340 1340 if partial:
1341 1341 rejects = True
1342 1342
1343 1343 files = list(files)
1344 1344 if nocommit:
1345 1345 if message:
1346 1346 msgs.append(message)
1347 1347 else:
1348 1348 if opts.get('exact') or p2:
1349 1349 # If you got here, you either use --force and know what
1350 1350 # you are doing or used --exact or a merge patch while
1351 1351 # being updated to its first parent.
1352 1352 m = None
1353 1353 else:
1354 1354 m = scmutil.matchfiles(repo, files or [])
1355 1355 editform = mergeeditform(repo[None], 'import.normal')
1356 1356 if opts.get('exact'):
1357 1357 editor = None
1358 1358 else:
1359 1359 editor = getcommiteditor(editform=editform, **opts)
1360 1360 extra = {}
1361 1361 for idfunc in extrapreimport:
1362 1362 extrapreimportmap[idfunc](repo, extractdata, extra, opts)
1363 1363 overrides = {}
1364 1364 if partial:
1365 1365 overrides[('ui', 'allowemptycommit')] = True
1366 1366 with repo.ui.configoverride(overrides, 'import'):
1367 1367 n = repo.commit(message, user,
1368 1368 date, match=m,
1369 1369 editor=editor, extra=extra)
1370 1370 for idfunc in extrapostimport:
1371 1371 extrapostimportmap[idfunc](repo[n])
1372 1372 else:
1373 1373 if opts.get('exact') or importbranch:
1374 1374 branch = branch or 'default'
1375 1375 else:
1376 1376 branch = p1.branch()
1377 1377 store = patch.filestore()
1378 1378 try:
1379 1379 files = set()
1380 1380 try:
1381 1381 patch.patchrepo(ui, repo, p1, store, tmpname, strip, prefix,
1382 1382 files, eolmode=None)
1383 1383 except patch.PatchError as e:
1384 1384 raise error.Abort(str(e))
1385 1385 if opts.get('exact'):
1386 1386 editor = None
1387 1387 else:
1388 1388 editor = getcommiteditor(editform='import.bypass')
1389 1389 memctx = context.memctx(repo, (p1.node(), p2.node()),
1390 1390 message,
1391 1391 files=files,
1392 1392 filectxfn=store,
1393 1393 user=user,
1394 1394 date=date,
1395 1395 branch=branch,
1396 1396 editor=editor)
1397 1397 n = memctx.commit()
1398 1398 finally:
1399 1399 store.close()
1400 1400 if opts.get('exact') and nocommit:
1401 1401 # --exact with --no-commit is still useful in that it does merge
1402 1402 # and branch bits
1403 1403 ui.warn(_("warning: can't check exact import with --no-commit\n"))
1404 1404 elif opts.get('exact') and hex(n) != nodeid:
1405 1405 raise error.Abort(_('patch is damaged or loses information'))
1406 1406 msg = _('applied to working directory')
1407 1407 if n:
1408 1408 # i18n: refers to a short changeset id
1409 1409 msg = _('created %s') % short(n)
1410 1410 return (msg, n, rejects)
1411 1411 finally:
1412 1412 os.unlink(tmpname)
1413 1413
1414 1414 # facility to let extensions include additional data in an exported patch
1415 1415 # list of identifiers to be executed in order
1416 1416 extraexport = []
1417 1417 # mapping from identifier to actual export function
1418 1418 # function as to return a string to be added to the header or None
1419 1419 # it is given two arguments (sequencenumber, changectx)
1420 1420 extraexportmap = {}
1421 1421
1422 1422 def _exportsingle(repo, ctx, match, switch_parent, rev, seqno, write, diffopts):
1423 1423 node = scmutil.binnode(ctx)
1424 1424 parents = [p.node() for p in ctx.parents() if p]
1425 1425 branch = ctx.branch()
1426 1426 if switch_parent:
1427 1427 parents.reverse()
1428 1428
1429 1429 if parents:
1430 1430 prev = parents[0]
1431 1431 else:
1432 1432 prev = nullid
1433 1433
1434 1434 write("# HG changeset patch\n")
1435 1435 write("# User %s\n" % ctx.user())
1436 1436 write("# Date %d %d\n" % ctx.date())
1437 1437 write("# %s\n" % util.datestr(ctx.date()))
1438 1438 if branch and branch != 'default':
1439 1439 write("# Branch %s\n" % branch)
1440 1440 write("# Node ID %s\n" % hex(node))
1441 1441 write("# Parent %s\n" % hex(prev))
1442 1442 if len(parents) > 1:
1443 1443 write("# Parent %s\n" % hex(parents[1]))
1444 1444
1445 1445 for headerid in extraexport:
1446 1446 header = extraexportmap[headerid](seqno, ctx)
1447 1447 if header is not None:
1448 1448 write('# %s\n' % header)
1449 1449 write(ctx.description().rstrip())
1450 1450 write("\n\n")
1451 1451
1452 1452 for chunk, label in patch.diffui(repo, prev, node, match, opts=diffopts):
1453 1453 write(chunk, label=label)
1454 1454
1455 1455 def export(repo, revs, fntemplate='hg-%h.patch', fp=None, switch_parent=False,
1456 1456 opts=None, match=None):
1457 1457 '''export changesets as hg patches
1458 1458
1459 1459 Args:
1460 1460 repo: The repository from which we're exporting revisions.
1461 1461 revs: A list of revisions to export as revision numbers.
1462 1462 fntemplate: An optional string to use for generating patch file names.
1463 1463 fp: An optional file-like object to which patches should be written.
1464 1464 switch_parent: If True, show diffs against second parent when not nullid.
1465 1465 Default is false, which always shows diff against p1.
1466 1466 opts: diff options to use for generating the patch.
1467 1467 match: If specified, only export changes to files matching this matcher.
1468 1468
1469 1469 Returns:
1470 1470 Nothing.
1471 1471
1472 1472 Side Effect:
1473 1473 "HG Changeset Patch" data is emitted to one of the following
1474 1474 destinations:
1475 1475 fp is specified: All revs are written to the specified
1476 1476 file-like object.
1477 1477 fntemplate specified: Each rev is written to a unique file named using
1478 1478 the given template.
1479 1479 Neither fp nor template specified: All revs written to repo.ui.write()
1480 1480 '''
1481 1481
1482 1482 total = len(revs)
1483 1483 revwidth = max(len(str(rev)) for rev in revs)
1484 1484 filemode = {}
1485 1485
1486 1486 write = None
1487 1487 dest = '<unnamed>'
1488 1488 if fp:
1489 1489 dest = getattr(fp, 'name', dest)
1490 1490 def write(s, **kw):
1491 1491 fp.write(s)
1492 1492 elif not fntemplate:
1493 1493 write = repo.ui.write
1494 1494
1495 1495 for seqno, rev in enumerate(revs, 1):
1496 1496 ctx = repo[rev]
1497 1497 fo = None
1498 1498 if not fp and fntemplate:
1499 1499 desc_lines = ctx.description().rstrip().split('\n')
1500 1500 desc = desc_lines[0] #Commit always has a first line.
1501 1501 fo = makefileobj(repo, fntemplate, ctx.node(), desc=desc,
1502 1502 total=total, seqno=seqno, revwidth=revwidth,
1503 1503 mode='wb', modemap=filemode)
1504 1504 dest = fo.name
1505 1505 def write(s, **kw):
1506 1506 fo.write(s)
1507 1507 if not dest.startswith('<'):
1508 1508 repo.ui.note("%s\n" % dest)
1509 1509 _exportsingle(
1510 1510 repo, ctx, match, switch_parent, rev, seqno, write, opts)
1511 1511 if fo is not None:
1512 1512 fo.close()
1513 1513
1514 1514 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
1515 1515 changes=None, stat=False, fp=None, prefix='',
1516 1516 root='', listsubrepos=False):
1517 1517 '''show diff or diffstat.'''
1518 1518 if fp is None:
1519 1519 write = ui.write
1520 1520 else:
1521 1521 def write(s, **kw):
1522 1522 fp.write(s)
1523 1523
1524 1524 if root:
1525 1525 relroot = pathutil.canonpath(repo.root, repo.getcwd(), root)
1526 1526 else:
1527 1527 relroot = ''
1528 1528 if relroot != '':
1529 1529 # XXX relative roots currently don't work if the root is within a
1530 1530 # subrepo
1531 1531 uirelroot = match.uipath(relroot)
1532 1532 relroot += '/'
1533 1533 for matchroot in match.files():
1534 1534 if not matchroot.startswith(relroot):
1535 1535 ui.warn(_('warning: %s not inside relative root %s\n') % (
1536 1536 match.uipath(matchroot), uirelroot))
1537 1537
1538 1538 if stat:
1539 1539 diffopts = diffopts.copy(context=0)
1540 1540 width = 80
1541 1541 if not ui.plain():
1542 1542 width = ui.termwidth()
1543 1543 chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
1544 1544 prefix=prefix, relroot=relroot)
1545 1545 for chunk, label in patch.diffstatui(util.iterlines(chunks),
1546 1546 width=width):
1547 1547 write(chunk, label=label)
1548 1548 else:
1549 1549 for chunk, label in patch.diffui(repo, node1, node2, match,
1550 1550 changes, diffopts, prefix=prefix,
1551 1551 relroot=relroot):
1552 1552 write(chunk, label=label)
1553 1553
1554 1554 if listsubrepos:
1555 1555 ctx1 = repo[node1]
1556 1556 ctx2 = repo[node2]
1557 1557 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
1558 1558 tempnode2 = node2
1559 1559 try:
1560 1560 if node2 is not None:
1561 1561 tempnode2 = ctx2.substate[subpath][1]
1562 1562 except KeyError:
1563 1563 # A subrepo that existed in node1 was deleted between node1 and
1564 1564 # node2 (inclusive). Thus, ctx2's substate won't contain that
1565 1565 # subpath. The best we can do is to ignore it.
1566 1566 tempnode2 = None
1567 1567 submatch = matchmod.subdirmatcher(subpath, match)
1568 1568 sub.diff(ui, diffopts, tempnode2, submatch, changes=changes,
1569 1569 stat=stat, fp=fp, prefix=prefix)
1570 1570
1571 1571 def _changesetlabels(ctx):
1572 1572 labels = ['log.changeset', 'changeset.%s' % ctx.phasestr()]
1573 1573 if ctx.obsolete():
1574 1574 labels.append('changeset.obsolete')
1575 1575 if ctx.isunstable():
1576 1576 labels.append('changeset.unstable')
1577 1577 for instability in ctx.instabilities():
1578 1578 labels.append('instability.%s' % instability)
1579 1579 return ' '.join(labels)
1580 1580
1581 1581 class changeset_printer(object):
1582 1582 '''show changeset information when templating not requested.'''
1583 1583
1584 1584 def __init__(self, ui, repo, matchfn, diffopts, buffered):
1585 1585 self.ui = ui
1586 1586 self.repo = repo
1587 1587 self.buffered = buffered
1588 1588 self.matchfn = matchfn
1589 1589 self.diffopts = diffopts
1590 1590 self.header = {}
1591 1591 self.hunk = {}
1592 1592 self.lastheader = None
1593 1593 self.footer = None
1594 1594
1595 1595 def flush(self, ctx):
1596 1596 rev = ctx.rev()
1597 1597 if rev in self.header:
1598 1598 h = self.header[rev]
1599 1599 if h != self.lastheader:
1600 1600 self.lastheader = h
1601 1601 self.ui.write(h)
1602 1602 del self.header[rev]
1603 1603 if rev in self.hunk:
1604 1604 self.ui.write(self.hunk[rev])
1605 1605 del self.hunk[rev]
1606 1606 return 1
1607 1607 return 0
1608 1608
1609 1609 def close(self):
1610 1610 if self.footer:
1611 1611 self.ui.write(self.footer)
1612 1612
1613 1613 def show(self, ctx, copies=None, matchfn=None, **props):
1614 1614 props = pycompat.byteskwargs(props)
1615 1615 if self.buffered:
1616 1616 self.ui.pushbuffer(labeled=True)
1617 1617 self._show(ctx, copies, matchfn, props)
1618 1618 self.hunk[ctx.rev()] = self.ui.popbuffer()
1619 1619 else:
1620 1620 self._show(ctx, copies, matchfn, props)
1621 1621
1622 1622 def _show(self, ctx, copies, matchfn, props):
1623 1623 '''show a single changeset or file revision'''
1624 1624 changenode = ctx.node()
1625 1625 rev = ctx.rev()
1626 1626 if self.ui.debugflag:
1627 1627 hexfunc = hex
1628 1628 else:
1629 1629 hexfunc = short
1630 1630 # as of now, wctx.node() and wctx.rev() return None, but we want to
1631 1631 # show the same values as {node} and {rev} templatekw
1632 1632 revnode = (scmutil.intrev(ctx), hexfunc(scmutil.binnode(ctx)))
1633 1633
1634 1634 if self.ui.quiet:
1635 1635 self.ui.write("%d:%s\n" % revnode, label='log.node')
1636 1636 return
1637 1637
1638 1638 date = util.datestr(ctx.date())
1639 1639
1640 1640 # i18n: column positioning for "hg log"
1641 1641 self.ui.write(_("changeset: %d:%s\n") % revnode,
1642 1642 label=_changesetlabels(ctx))
1643 1643
1644 1644 # branches are shown first before any other names due to backwards
1645 1645 # compatibility
1646 1646 branch = ctx.branch()
1647 1647 # don't show the default branch name
1648 1648 if branch != 'default':
1649 1649 # i18n: column positioning for "hg log"
1650 1650 self.ui.write(_("branch: %s\n") % branch,
1651 1651 label='log.branch')
1652 1652
1653 1653 for nsname, ns in self.repo.names.iteritems():
1654 1654 # branches has special logic already handled above, so here we just
1655 1655 # skip it
1656 1656 if nsname == 'branches':
1657 1657 continue
1658 1658 # we will use the templatename as the color name since those two
1659 1659 # should be the same
1660 1660 for name in ns.names(self.repo, changenode):
1661 1661 self.ui.write(ns.logfmt % name,
1662 1662 label='log.%s' % ns.colorname)
1663 1663 if self.ui.debugflag:
1664 1664 # i18n: column positioning for "hg log"
1665 1665 self.ui.write(_("phase: %s\n") % ctx.phasestr(),
1666 1666 label='log.phase')
1667 1667 for pctx in scmutil.meaningfulparents(self.repo, ctx):
1668 1668 label = 'log.parent changeset.%s' % pctx.phasestr()
1669 1669 # i18n: column positioning for "hg log"
1670 1670 self.ui.write(_("parent: %d:%s\n")
1671 1671 % (pctx.rev(), hexfunc(pctx.node())),
1672 1672 label=label)
1673 1673
1674 1674 if self.ui.debugflag and rev is not None:
1675 1675 mnode = ctx.manifestnode()
1676 1676 # i18n: column positioning for "hg log"
1677 1677 self.ui.write(_("manifest: %d:%s\n") %
1678 1678 (self.repo.manifestlog._revlog.rev(mnode),
1679 1679 hex(mnode)),
1680 1680 label='ui.debug log.manifest')
1681 1681 # i18n: column positioning for "hg log"
1682 1682 self.ui.write(_("user: %s\n") % ctx.user(),
1683 1683 label='log.user')
1684 1684 # i18n: column positioning for "hg log"
1685 1685 self.ui.write(_("date: %s\n") % date,
1686 1686 label='log.date')
1687 1687
1688 1688 if ctx.isunstable():
1689 1689 # i18n: column positioning for "hg log"
1690 1690 instabilities = ctx.instabilities()
1691 1691 self.ui.write(_("instability: %s\n") % ', '.join(instabilities),
1692 1692 label='log.instability')
1693 1693
1694 1694 self._exthook(ctx)
1695 1695
1696 1696 if self.ui.debugflag:
1697 1697 files = ctx.p1().status(ctx)[:3]
1698 1698 for key, value in zip([# i18n: column positioning for "hg log"
1699 1699 _("files:"),
1700 1700 # i18n: column positioning for "hg log"
1701 1701 _("files+:"),
1702 1702 # i18n: column positioning for "hg log"
1703 1703 _("files-:")], files):
1704 1704 if value:
1705 1705 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
1706 1706 label='ui.debug log.files')
1707 1707 elif ctx.files() and self.ui.verbose:
1708 1708 # i18n: column positioning for "hg log"
1709 1709 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
1710 1710 label='ui.note log.files')
1711 1711 if copies and self.ui.verbose:
1712 1712 copies = ['%s (%s)' % c for c in copies]
1713 1713 # i18n: column positioning for "hg log"
1714 1714 self.ui.write(_("copies: %s\n") % ' '.join(copies),
1715 1715 label='ui.note log.copies')
1716 1716
1717 1717 extra = ctx.extra()
1718 1718 if extra and self.ui.debugflag:
1719 1719 for key, value in sorted(extra.items()):
1720 1720 # i18n: column positioning for "hg log"
1721 1721 self.ui.write(_("extra: %s=%s\n")
1722 1722 % (key, util.escapestr(value)),
1723 1723 label='ui.debug log.extra')
1724 1724
1725 1725 description = ctx.description().strip()
1726 1726 if description:
1727 1727 if self.ui.verbose:
1728 1728 self.ui.write(_("description:\n"),
1729 1729 label='ui.note log.description')
1730 1730 self.ui.write(description,
1731 1731 label='ui.note log.description')
1732 1732 self.ui.write("\n\n")
1733 1733 else:
1734 1734 # i18n: column positioning for "hg log"
1735 1735 self.ui.write(_("summary: %s\n") %
1736 1736 description.splitlines()[0],
1737 1737 label='log.summary')
1738 1738 self.ui.write("\n")
1739 1739
1740 1740 self.showpatch(ctx, matchfn)
1741 1741
1742 1742 def _exthook(self, ctx):
1743 1743 '''empty method used by extension as a hook point
1744 1744 '''
1745 1745 pass
1746 1746
1747 1747 def showpatch(self, ctx, matchfn):
1748 1748 if not matchfn:
1749 1749 matchfn = self.matchfn
1750 1750 if matchfn:
1751 1751 stat = self.diffopts.get('stat')
1752 1752 diff = self.diffopts.get('patch')
1753 1753 diffopts = patch.diffallopts(self.ui, self.diffopts)
1754 1754 node = ctx.node()
1755 1755 prev = ctx.p1().node()
1756 1756 if stat:
1757 1757 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
1758 1758 match=matchfn, stat=True)
1759 1759 if diff:
1760 1760 if stat:
1761 1761 self.ui.write("\n")
1762 1762 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
1763 1763 match=matchfn, stat=False)
1764 1764 self.ui.write("\n")
1765 1765
1766 1766 class jsonchangeset(changeset_printer):
1767 1767 '''format changeset information.'''
1768 1768
1769 1769 def __init__(self, ui, repo, matchfn, diffopts, buffered):
1770 1770 changeset_printer.__init__(self, ui, repo, matchfn, diffopts, buffered)
1771 1771 self.cache = {}
1772 1772 self._first = True
1773 1773
1774 1774 def close(self):
1775 1775 if not self._first:
1776 1776 self.ui.write("\n]\n")
1777 1777 else:
1778 1778 self.ui.write("[]\n")
1779 1779
1780 1780 def _show(self, ctx, copies, matchfn, props):
1781 1781 '''show a single changeset or file revision'''
1782 1782 rev = ctx.rev()
1783 1783 if rev is None:
1784 1784 jrev = jnode = 'null'
1785 1785 else:
1786 1786 jrev = '%d' % rev
1787 1787 jnode = '"%s"' % hex(ctx.node())
1788 1788 j = encoding.jsonescape
1789 1789
1790 1790 if self._first:
1791 1791 self.ui.write("[\n {")
1792 1792 self._first = False
1793 1793 else:
1794 1794 self.ui.write(",\n {")
1795 1795
1796 1796 if self.ui.quiet:
1797 1797 self.ui.write(('\n "rev": %s') % jrev)
1798 1798 self.ui.write((',\n "node": %s') % jnode)
1799 1799 self.ui.write('\n }')
1800 1800 return
1801 1801
1802 1802 self.ui.write(('\n "rev": %s') % jrev)
1803 1803 self.ui.write((',\n "node": %s') % jnode)
1804 1804 self.ui.write((',\n "branch": "%s"') % j(ctx.branch()))
1805 1805 self.ui.write((',\n "phase": "%s"') % ctx.phasestr())
1806 1806 self.ui.write((',\n "user": "%s"') % j(ctx.user()))
1807 1807 self.ui.write((',\n "date": [%d, %d]') % ctx.date())
1808 1808 self.ui.write((',\n "desc": "%s"') % j(ctx.description()))
1809 1809
1810 1810 self.ui.write((',\n "bookmarks": [%s]') %
1811 1811 ", ".join('"%s"' % j(b) for b in ctx.bookmarks()))
1812 1812 self.ui.write((',\n "tags": [%s]') %
1813 1813 ", ".join('"%s"' % j(t) for t in ctx.tags()))
1814 1814 self.ui.write((',\n "parents": [%s]') %
1815 1815 ", ".join('"%s"' % c.hex() for c in ctx.parents()))
1816 1816
1817 1817 if self.ui.debugflag:
1818 1818 if rev is None:
1819 1819 jmanifestnode = 'null'
1820 1820 else:
1821 1821 jmanifestnode = '"%s"' % hex(ctx.manifestnode())
1822 1822 self.ui.write((',\n "manifest": %s') % jmanifestnode)
1823 1823
1824 1824 self.ui.write((',\n "extra": {%s}') %
1825 1825 ", ".join('"%s": "%s"' % (j(k), j(v))
1826 1826 for k, v in ctx.extra().items()))
1827 1827
1828 1828 files = ctx.p1().status(ctx)
1829 1829 self.ui.write((',\n "modified": [%s]') %
1830 1830 ", ".join('"%s"' % j(f) for f in files[0]))
1831 1831 self.ui.write((',\n "added": [%s]') %
1832 1832 ", ".join('"%s"' % j(f) for f in files[1]))
1833 1833 self.ui.write((',\n "removed": [%s]') %
1834 1834 ", ".join('"%s"' % j(f) for f in files[2]))
1835 1835
1836 1836 elif self.ui.verbose:
1837 1837 self.ui.write((',\n "files": [%s]') %
1838 1838 ", ".join('"%s"' % j(f) for f in ctx.files()))
1839 1839
1840 1840 if copies:
1841 1841 self.ui.write((',\n "copies": {%s}') %
1842 1842 ", ".join('"%s": "%s"' % (j(k), j(v))
1843 1843 for k, v in copies))
1844 1844
1845 1845 matchfn = self.matchfn
1846 1846 if matchfn:
1847 1847 stat = self.diffopts.get('stat')
1848 1848 diff = self.diffopts.get('patch')
1849 1849 diffopts = patch.difffeatureopts(self.ui, self.diffopts, git=True)
1850 1850 node, prev = ctx.node(), ctx.p1().node()
1851 1851 if stat:
1852 1852 self.ui.pushbuffer()
1853 1853 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
1854 1854 match=matchfn, stat=True)
1855 1855 self.ui.write((',\n "diffstat": "%s"')
1856 1856 % j(self.ui.popbuffer()))
1857 1857 if diff:
1858 1858 self.ui.pushbuffer()
1859 1859 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
1860 1860 match=matchfn, stat=False)
1861 1861 self.ui.write((',\n "diff": "%s"') % j(self.ui.popbuffer()))
1862 1862
1863 1863 self.ui.write("\n }")
1864 1864
1865 1865 class changeset_templater(changeset_printer):
1866 1866 '''format changeset information.'''
1867 1867
1868 1868 # Arguments before "buffered" used to be positional. Consider not
1869 1869 # adding/removing arguments before "buffered" to not break callers.
1870 1870 def __init__(self, ui, repo, tmplspec, matchfn=None, diffopts=None,
1871 1871 buffered=False):
1872 1872 diffopts = diffopts or {}
1873 1873
1874 1874 changeset_printer.__init__(self, ui, repo, matchfn, diffopts, buffered)
1875 1875 self.t = formatter.loadtemplater(ui, tmplspec,
1876 1876 cache=templatekw.defaulttempl)
1877 1877 self._counter = itertools.count()
1878 1878 self.cache = {}
1879 1879
1880 1880 self._tref = tmplspec.ref
1881 1881 self._parts = {'header': '', 'footer': '',
1882 1882 tmplspec.ref: tmplspec.ref,
1883 1883 'docheader': '', 'docfooter': '',
1884 1884 'separator': ''}
1885 1885 if tmplspec.mapfile:
1886 1886 # find correct templates for current mode, for backward
1887 1887 # compatibility with 'log -v/-q/--debug' using a mapfile
1888 1888 tmplmodes = [
1889 1889 (True, ''),
1890 1890 (self.ui.verbose, '_verbose'),
1891 1891 (self.ui.quiet, '_quiet'),
1892 1892 (self.ui.debugflag, '_debug'),
1893 1893 ]
1894 1894 for mode, postfix in tmplmodes:
1895 1895 for t in self._parts:
1896 1896 cur = t + postfix
1897 1897 if mode and cur in self.t:
1898 1898 self._parts[t] = cur
1899 1899 else:
1900 1900 partnames = [p for p in self._parts.keys() if p != tmplspec.ref]
1901 1901 m = formatter.templatepartsmap(tmplspec, self.t, partnames)
1902 1902 self._parts.update(m)
1903 1903
1904 1904 if self._parts['docheader']:
1905 1905 self.ui.write(templater.stringify(self.t(self._parts['docheader'])))
1906 1906
1907 1907 def close(self):
1908 1908 if self._parts['docfooter']:
1909 1909 if not self.footer:
1910 1910 self.footer = ""
1911 1911 self.footer += templater.stringify(self.t(self._parts['docfooter']))
1912 1912 return super(changeset_templater, self).close()
1913 1913
1914 1914 def _show(self, ctx, copies, matchfn, props):
1915 1915 '''show a single changeset or file revision'''
1916 1916 props = props.copy()
1917 1917 props.update(templatekw.keywords)
1918 1918 props['templ'] = self.t
1919 1919 props['ctx'] = ctx
1920 1920 props['repo'] = self.repo
1921 1921 props['ui'] = self.repo.ui
1922 1922 props['index'] = index = next(self._counter)
1923 1923 props['revcache'] = {'copies': copies}
1924 1924 props['cache'] = self.cache
1925 1925 props = pycompat.strkwargs(props)
1926 1926
1927 1927 # write separator, which wouldn't work well with the header part below
1928 1928 # since there's inherently a conflict between header (across items) and
1929 1929 # separator (per item)
1930 1930 if self._parts['separator'] and index > 0:
1931 1931 self.ui.write(templater.stringify(self.t(self._parts['separator'])))
1932 1932
1933 1933 # write header
1934 1934 if self._parts['header']:
1935 1935 h = templater.stringify(self.t(self._parts['header'], **props))
1936 1936 if self.buffered:
1937 1937 self.header[ctx.rev()] = h
1938 1938 else:
1939 1939 if self.lastheader != h:
1940 1940 self.lastheader = h
1941 1941 self.ui.write(h)
1942 1942
1943 1943 # write changeset metadata, then patch if requested
1944 1944 key = self._parts[self._tref]
1945 1945 self.ui.write(templater.stringify(self.t(key, **props)))
1946 1946 self.showpatch(ctx, matchfn)
1947 1947
1948 1948 if self._parts['footer']:
1949 1949 if not self.footer:
1950 1950 self.footer = templater.stringify(
1951 1951 self.t(self._parts['footer'], **props))
1952 1952
1953 1953 def logtemplatespec(tmpl, mapfile):
1954 1954 if mapfile:
1955 1955 return formatter.templatespec('changeset', tmpl, mapfile)
1956 1956 else:
1957 1957 return formatter.templatespec('', tmpl, None)
1958 1958
1959 1959 def _lookuplogtemplate(ui, tmpl, style):
1960 1960 """Find the template matching the given template spec or style
1961 1961
1962 1962 See formatter.lookuptemplate() for details.
1963 1963 """
1964 1964
1965 1965 # ui settings
1966 1966 if not tmpl and not style: # template are stronger than style
1967 1967 tmpl = ui.config('ui', 'logtemplate')
1968 1968 if tmpl:
1969 1969 return logtemplatespec(templater.unquotestring(tmpl), None)
1970 1970 else:
1971 1971 style = util.expandpath(ui.config('ui', 'style'))
1972 1972
1973 1973 if not tmpl and style:
1974 1974 mapfile = style
1975 1975 if not os.path.split(mapfile)[0]:
1976 1976 mapname = (templater.templatepath('map-cmdline.' + mapfile)
1977 1977 or templater.templatepath(mapfile))
1978 1978 if mapname:
1979 1979 mapfile = mapname
1980 1980 return logtemplatespec(None, mapfile)
1981 1981
1982 1982 if not tmpl:
1983 1983 return logtemplatespec(None, None)
1984 1984
1985 1985 return formatter.lookuptemplate(ui, 'changeset', tmpl)
1986 1986
1987 1987 def makelogtemplater(ui, repo, tmpl, buffered=False):
1988 1988 """Create a changeset_templater from a literal template 'tmpl'"""
1989 1989 spec = logtemplatespec(tmpl, None)
1990 1990 return changeset_templater(ui, repo, spec, buffered=buffered)
1991 1991
1992 1992 def show_changeset(ui, repo, opts, buffered=False):
1993 1993 """show one changeset using template or regular display.
1994 1994
1995 1995 Display format will be the first non-empty hit of:
1996 1996 1. option 'template'
1997 1997 2. option 'style'
1998 1998 3. [ui] setting 'logtemplate'
1999 1999 4. [ui] setting 'style'
2000 2000 If all of these values are either the unset or the empty string,
2001 2001 regular display via changeset_printer() is done.
2002 2002 """
2003 2003 # options
2004 2004 match = None
2005 2005 if opts.get('patch') or opts.get('stat'):
2006 2006 match = scmutil.matchall(repo)
2007 2007
2008 2008 if opts.get('template') == 'json':
2009 2009 return jsonchangeset(ui, repo, match, opts, buffered)
2010 2010
2011 2011 spec = _lookuplogtemplate(ui, opts.get('template'), opts.get('style'))
2012 2012
2013 2013 if not spec.ref and not spec.tmpl and not spec.mapfile:
2014 2014 return changeset_printer(ui, repo, match, opts, buffered)
2015 2015
2016 2016 return changeset_templater(ui, repo, spec, match, opts, buffered)
2017 2017
2018 2018 def showmarker(fm, marker, index=None):
2019 2019 """utility function to display obsolescence marker in a readable way
2020 2020
2021 2021 To be used by debug function."""
2022 2022 if index is not None:
2023 2023 fm.write('index', '%i ', index)
2024 2024 fm.write('prednode', '%s ', hex(marker.prednode()))
2025 2025 succs = marker.succnodes()
2026 2026 fm.condwrite(succs, 'succnodes', '%s ',
2027 2027 fm.formatlist(map(hex, succs), name='node'))
2028 2028 fm.write('flag', '%X ', marker.flags())
2029 2029 parents = marker.parentnodes()
2030 2030 if parents is not None:
2031 2031 fm.write('parentnodes', '{%s} ',
2032 2032 fm.formatlist(map(hex, parents), name='node', sep=', '))
2033 2033 fm.write('date', '(%s) ', fm.formatdate(marker.date()))
2034 2034 meta = marker.metadata().copy()
2035 2035 meta.pop('date', None)
2036 2036 fm.write('metadata', '{%s}', fm.formatdict(meta, fmt='%r: %r', sep=', '))
2037 2037 fm.plain('\n')
2038 2038
2039 2039 def finddate(ui, repo, date):
2040 2040 """Find the tipmost changeset that matches the given date spec"""
2041 2041
2042 2042 df = util.matchdate(date)
2043 2043 m = scmutil.matchall(repo)
2044 2044 results = {}
2045 2045
2046 2046 def prep(ctx, fns):
2047 2047 d = ctx.date()
2048 2048 if df(d[0]):
2049 2049 results[ctx.rev()] = d
2050 2050
2051 2051 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
2052 2052 rev = ctx.rev()
2053 2053 if rev in results:
2054 2054 ui.status(_("found revision %s from %s\n") %
2055 2055 (rev, util.datestr(results[rev])))
2056 2056 return '%d' % rev
2057 2057
2058 2058 raise error.Abort(_("revision matching date not found"))
2059 2059
2060 2060 def increasingwindows(windowsize=8, sizelimit=512):
2061 2061 while True:
2062 2062 yield windowsize
2063 2063 if windowsize < sizelimit:
2064 2064 windowsize *= 2
2065 2065
2066 2066 class FileWalkError(Exception):
2067 2067 pass
2068 2068
2069 2069 def walkfilerevs(repo, match, follow, revs, fncache):
2070 2070 '''Walks the file history for the matched files.
2071 2071
2072 2072 Returns the changeset revs that are involved in the file history.
2073 2073
2074 2074 Throws FileWalkError if the file history can't be walked using
2075 2075 filelogs alone.
2076 2076 '''
2077 2077 wanted = set()
2078 2078 copies = []
2079 2079 minrev, maxrev = min(revs), max(revs)
2080 2080 def filerevgen(filelog, last):
2081 2081 """
2082 2082 Only files, no patterns. Check the history of each file.
2083 2083
2084 2084 Examines filelog entries within minrev, maxrev linkrev range
2085 2085 Returns an iterator yielding (linkrev, parentlinkrevs, copied)
2086 2086 tuples in backwards order
2087 2087 """
2088 2088 cl_count = len(repo)
2089 2089 revs = []
2090 2090 for j in xrange(0, last + 1):
2091 2091 linkrev = filelog.linkrev(j)
2092 2092 if linkrev < minrev:
2093 2093 continue
2094 2094 # only yield rev for which we have the changelog, it can
2095 2095 # happen while doing "hg log" during a pull or commit
2096 2096 if linkrev >= cl_count:
2097 2097 break
2098 2098
2099 2099 parentlinkrevs = []
2100 2100 for p in filelog.parentrevs(j):
2101 2101 if p != nullrev:
2102 2102 parentlinkrevs.append(filelog.linkrev(p))
2103 2103 n = filelog.node(j)
2104 2104 revs.append((linkrev, parentlinkrevs,
2105 2105 follow and filelog.renamed(n)))
2106 2106
2107 2107 return reversed(revs)
2108 2108 def iterfiles():
2109 2109 pctx = repo['.']
2110 2110 for filename in match.files():
2111 2111 if follow:
2112 2112 if filename not in pctx:
2113 2113 raise error.Abort(_('cannot follow file not in parent '
2114 2114 'revision: "%s"') % filename)
2115 2115 yield filename, pctx[filename].filenode()
2116 2116 else:
2117 2117 yield filename, None
2118 2118 for filename_node in copies:
2119 2119 yield filename_node
2120 2120
2121 2121 for file_, node in iterfiles():
2122 2122 filelog = repo.file(file_)
2123 2123 if not len(filelog):
2124 2124 if node is None:
2125 2125 # A zero count may be a directory or deleted file, so
2126 2126 # try to find matching entries on the slow path.
2127 2127 if follow:
2128 2128 raise error.Abort(
2129 2129 _('cannot follow nonexistent file: "%s"') % file_)
2130 2130 raise FileWalkError("Cannot walk via filelog")
2131 2131 else:
2132 2132 continue
2133 2133
2134 2134 if node is None:
2135 2135 last = len(filelog) - 1
2136 2136 else:
2137 2137 last = filelog.rev(node)
2138 2138
2139 2139 # keep track of all ancestors of the file
2140 2140 ancestors = {filelog.linkrev(last)}
2141 2141
2142 2142 # iterate from latest to oldest revision
2143 2143 for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
2144 2144 if not follow:
2145 2145 if rev > maxrev:
2146 2146 continue
2147 2147 else:
2148 2148 # Note that last might not be the first interesting
2149 2149 # rev to us:
2150 2150 # if the file has been changed after maxrev, we'll
2151 2151 # have linkrev(last) > maxrev, and we still need
2152 2152 # to explore the file graph
2153 2153 if rev not in ancestors:
2154 2154 continue
2155 2155 # XXX insert 1327 fix here
2156 2156 if flparentlinkrevs:
2157 2157 ancestors.update(flparentlinkrevs)
2158 2158
2159 2159 fncache.setdefault(rev, []).append(file_)
2160 2160 wanted.add(rev)
2161 2161 if copied:
2162 2162 copies.append(copied)
2163 2163
2164 2164 return wanted
2165 2165
2166 2166 class _followfilter(object):
2167 2167 def __init__(self, repo, onlyfirst=False):
2168 2168 self.repo = repo
2169 2169 self.startrev = nullrev
2170 2170 self.roots = set()
2171 2171 self.onlyfirst = onlyfirst
2172 2172
2173 2173 def match(self, rev):
2174 2174 def realparents(rev):
2175 2175 if self.onlyfirst:
2176 2176 return self.repo.changelog.parentrevs(rev)[0:1]
2177 2177 else:
2178 2178 return filter(lambda x: x != nullrev,
2179 2179 self.repo.changelog.parentrevs(rev))
2180 2180
2181 2181 if self.startrev == nullrev:
2182 2182 self.startrev = rev
2183 2183 return True
2184 2184
2185 2185 if rev > self.startrev:
2186 2186 # forward: all descendants
2187 2187 if not self.roots:
2188 2188 self.roots.add(self.startrev)
2189 2189 for parent in realparents(rev):
2190 2190 if parent in self.roots:
2191 2191 self.roots.add(rev)
2192 2192 return True
2193 2193 else:
2194 2194 # backwards: all parents
2195 2195 if not self.roots:
2196 2196 self.roots.update(realparents(self.startrev))
2197 2197 if rev in self.roots:
2198 2198 self.roots.remove(rev)
2199 2199 self.roots.update(realparents(rev))
2200 2200 return True
2201 2201
2202 2202 return False
2203 2203
2204 2204 def walkchangerevs(repo, match, opts, prepare):
2205 2205 '''Iterate over files and the revs in which they changed.
2206 2206
2207 2207 Callers most commonly need to iterate backwards over the history
2208 2208 in which they are interested. Doing so has awful (quadratic-looking)
2209 2209 performance, so we use iterators in a "windowed" way.
2210 2210
2211 2211 We walk a window of revisions in the desired order. Within the
2212 2212 window, we first walk forwards to gather data, then in the desired
2213 2213 order (usually backwards) to display it.
2214 2214
2215 2215 This function returns an iterator yielding contexts. Before
2216 2216 yielding each context, the iterator will first call the prepare
2217 2217 function on each context in the window in forward order.'''
2218 2218
2219 2219 follow = opts.get('follow') or opts.get('follow_first')
2220 2220 revs = _logrevs(repo, opts)
2221 2221 if not revs:
2222 2222 return []
2223 2223 wanted = set()
2224 2224 slowpath = match.anypats() or ((match.isexact() or match.prefix()) and
2225 2225 opts.get('removed'))
2226 2226 fncache = {}
2227 2227 change = repo.changectx
2228 2228
2229 2229 # First step is to fill wanted, the set of revisions that we want to yield.
2230 2230 # When it does not induce extra cost, we also fill fncache for revisions in
2231 2231 # wanted: a cache of filenames that were changed (ctx.files()) and that
2232 2232 # match the file filtering conditions.
2233 2233
2234 2234 if match.always():
2235 2235 # No files, no patterns. Display all revs.
2236 2236 wanted = revs
2237 2237 elif not slowpath:
2238 2238 # We only have to read through the filelog to find wanted revisions
2239 2239
2240 2240 try:
2241 2241 wanted = walkfilerevs(repo, match, follow, revs, fncache)
2242 2242 except FileWalkError:
2243 2243 slowpath = True
2244 2244
2245 2245 # We decided to fall back to the slowpath because at least one
2246 2246 # of the paths was not a file. Check to see if at least one of them
2247 2247 # existed in history, otherwise simply return
2248 2248 for path in match.files():
2249 2249 if path == '.' or path in repo.store:
2250 2250 break
2251 2251 else:
2252 2252 return []
2253 2253
2254 2254 if slowpath:
2255 2255 # We have to read the changelog to match filenames against
2256 2256 # changed files
2257 2257
2258 2258 if follow:
2259 2259 raise error.Abort(_('can only follow copies/renames for explicit '
2260 2260 'filenames'))
2261 2261
2262 2262 # The slow path checks files modified in every changeset.
2263 2263 # This is really slow on large repos, so compute the set lazily.
2264 2264 class lazywantedset(object):
2265 2265 def __init__(self):
2266 2266 self.set = set()
2267 2267 self.revs = set(revs)
2268 2268
2269 2269 # No need to worry about locality here because it will be accessed
2270 2270 # in the same order as the increasing window below.
2271 2271 def __contains__(self, value):
2272 2272 if value in self.set:
2273 2273 return True
2274 2274 elif not value in self.revs:
2275 2275 return False
2276 2276 else:
2277 2277 self.revs.discard(value)
2278 2278 ctx = change(value)
2279 2279 matches = filter(match, ctx.files())
2280 2280 if matches:
2281 2281 fncache[value] = matches
2282 2282 self.set.add(value)
2283 2283 return True
2284 2284 return False
2285 2285
2286 2286 def discard(self, value):
2287 2287 self.revs.discard(value)
2288 2288 self.set.discard(value)
2289 2289
2290 2290 wanted = lazywantedset()
2291 2291
2292 2292 # it might be worthwhile to do this in the iterator if the rev range
2293 2293 # is descending and the prune args are all within that range
2294 2294 for rev in opts.get('prune', ()):
2295 2295 rev = repo[rev].rev()
2296 2296 ff = _followfilter(repo)
2297 2297 stop = min(revs[0], revs[-1])
2298 2298 for x in xrange(rev, stop - 1, -1):
2299 2299 if ff.match(x):
2300 2300 wanted = wanted - [x]
2301 2301
2302 2302 # Now that wanted is correctly initialized, we can iterate over the
2303 2303 # revision range, yielding only revisions in wanted.
2304 2304 def iterate():
2305 2305 if follow and match.always():
2306 2306 ff = _followfilter(repo, onlyfirst=opts.get('follow_first'))
2307 2307 def want(rev):
2308 2308 return ff.match(rev) and rev in wanted
2309 2309 else:
2310 2310 def want(rev):
2311 2311 return rev in wanted
2312 2312
2313 2313 it = iter(revs)
2314 2314 stopiteration = False
2315 2315 for windowsize in increasingwindows():
2316 2316 nrevs = []
2317 2317 for i in xrange(windowsize):
2318 2318 rev = next(it, None)
2319 2319 if rev is None:
2320 2320 stopiteration = True
2321 2321 break
2322 2322 elif want(rev):
2323 2323 nrevs.append(rev)
2324 2324 for rev in sorted(nrevs):
2325 2325 fns = fncache.get(rev)
2326 2326 ctx = change(rev)
2327 2327 if not fns:
2328 2328 def fns_generator():
2329 2329 for f in ctx.files():
2330 2330 if match(f):
2331 2331 yield f
2332 2332 fns = fns_generator()
2333 2333 prepare(ctx, fns)
2334 2334 for rev in nrevs:
2335 2335 yield change(rev)
2336 2336
2337 2337 if stopiteration:
2338 2338 break
2339 2339
2340 2340 return iterate()
2341 2341
2342 2342 def _makefollowlogfilematcher(repo, files, followfirst):
2343 2343 # When displaying a revision with --patch --follow FILE, we have
2344 2344 # to know which file of the revision must be diffed. With
2345 2345 # --follow, we want the names of the ancestors of FILE in the
2346 2346 # revision, stored in "fcache". "fcache" is populated by
2347 2347 # reproducing the graph traversal already done by --follow revset
2348 2348 # and relating revs to file names (which is not "correct" but
2349 2349 # good enough).
2350 2350 fcache = {}
2351 2351 fcacheready = [False]
2352 2352 pctx = repo['.']
2353 2353
2354 2354 def populate():
2355 2355 for fn in files:
2356 2356 fctx = pctx[fn]
2357 2357 fcache.setdefault(fctx.introrev(), set()).add(fctx.path())
2358 2358 for c in fctx.ancestors(followfirst=followfirst):
2359 2359 fcache.setdefault(c.rev(), set()).add(c.path())
2360 2360
2361 2361 def filematcher(rev):
2362 2362 if not fcacheready[0]:
2363 2363 # Lazy initialization
2364 2364 fcacheready[0] = True
2365 2365 populate()
2366 2366 return scmutil.matchfiles(repo, fcache.get(rev, []))
2367 2367
2368 2368 return filematcher
2369 2369
2370 2370 def _makenofollowlogfilematcher(repo, pats, opts):
2371 2371 '''hook for extensions to override the filematcher for non-follow cases'''
2372 2372 return None
2373 2373
2374 2374 def _makelogrevset(repo, pats, opts, revs):
2375 2375 """Return (expr, filematcher) where expr is a revset string built
2376 2376 from log options and file patterns or None. If --stat or --patch
2377 2377 are not passed filematcher is None. Otherwise it is a callable
2378 2378 taking a revision number and returning a match objects filtering
2379 2379 the files to be detailed when displaying the revision.
2380 2380 """
2381 2381 opt2revset = {
2382 2382 'no_merges': ('not merge()', None),
2383 2383 'only_merges': ('merge()', None),
2384 2384 '_ancestors': ('ancestors(%(val)s)', None),
2385 2385 '_fancestors': ('_firstancestors(%(val)s)', None),
2386 2386 '_descendants': ('descendants(%(val)s)', None),
2387 2387 '_fdescendants': ('_firstdescendants(%(val)s)', None),
2388 2388 '_matchfiles': ('_matchfiles(%(val)s)', None),
2389 2389 'date': ('date(%(val)r)', None),
2390 2390 'branch': ('branch(%(val)r)', ' or '),
2391 2391 '_patslog': ('filelog(%(val)r)', ' or '),
2392 2392 '_patsfollow': ('follow(%(val)r)', ' or '),
2393 2393 '_patsfollowfirst': ('_followfirst(%(val)r)', ' or '),
2394 2394 'keyword': ('keyword(%(val)r)', ' or '),
2395 2395 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '),
2396 2396 'user': ('user(%(val)r)', ' or '),
2397 2397 }
2398 2398
2399 2399 opts = dict(opts)
2400 2400 # follow or not follow?
2401 2401 follow = opts.get('follow') or opts.get('follow_first')
2402 2402 if opts.get('follow_first'):
2403 2403 followfirst = 1
2404 2404 else:
2405 2405 followfirst = 0
2406 2406 # --follow with FILE behavior depends on revs...
2407 2407 it = iter(revs)
2408 2408 startrev = next(it)
2409 2409 followdescendants = startrev < next(it, startrev)
2410 2410
2411 2411 # branch and only_branch are really aliases and must be handled at
2412 2412 # the same time
2413 2413 opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
2414 2414 opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']]
2415 2415 # pats/include/exclude are passed to match.match() directly in
2416 2416 # _matchfiles() revset but walkchangerevs() builds its matcher with
2417 2417 # scmutil.match(). The difference is input pats are globbed on
2418 2418 # platforms without shell expansion (windows).
2419 2419 wctx = repo[None]
2420 2420 match, pats = scmutil.matchandpats(wctx, pats, opts)
2421 2421 slowpath = match.anypats() or ((match.isexact() or match.prefix()) and
2422 2422 opts.get('removed'))
2423 2423 if not slowpath:
2424 2424 for f in match.files():
2425 2425 if follow and f not in wctx:
2426 2426 # If the file exists, it may be a directory, so let it
2427 2427 # take the slow path.
2428 2428 if os.path.exists(repo.wjoin(f)):
2429 2429 slowpath = True
2430 2430 continue
2431 2431 else:
2432 2432 raise error.Abort(_('cannot follow file not in parent '
2433 2433 'revision: "%s"') % f)
2434 2434 filelog = repo.file(f)
2435 2435 if not filelog:
2436 2436 # A zero count may be a directory or deleted file, so
2437 2437 # try to find matching entries on the slow path.
2438 2438 if follow:
2439 2439 raise error.Abort(
2440 2440 _('cannot follow nonexistent file: "%s"') % f)
2441 2441 slowpath = True
2442 2442
2443 2443 # We decided to fall back to the slowpath because at least one
2444 2444 # of the paths was not a file. Check to see if at least one of them
2445 2445 # existed in history - in that case, we'll continue down the
2446 2446 # slowpath; otherwise, we can turn off the slowpath
2447 2447 if slowpath:
2448 2448 for path in match.files():
2449 2449 if path == '.' or path in repo.store:
2450 2450 break
2451 2451 else:
2452 2452 slowpath = False
2453 2453
2454 2454 fpats = ('_patsfollow', '_patsfollowfirst')
2455 2455 fnopats = (('_ancestors', '_fancestors'),
2456 2456 ('_descendants', '_fdescendants'))
2457 2457 if slowpath:
2458 2458 # See walkchangerevs() slow path.
2459 2459 #
2460 2460 # pats/include/exclude cannot be represented as separate
2461 2461 # revset expressions as their filtering logic applies at file
2462 2462 # level. For instance "-I a -X a" matches a revision touching
2463 2463 # "a" and "b" while "file(a) and not file(b)" does
2464 2464 # not. Besides, filesets are evaluated against the working
2465 2465 # directory.
2466 2466 matchargs = ['r:', 'd:relpath']
2467 2467 for p in pats:
2468 2468 matchargs.append('p:' + p)
2469 2469 for p in opts.get('include', []):
2470 2470 matchargs.append('i:' + p)
2471 2471 for p in opts.get('exclude', []):
2472 2472 matchargs.append('x:' + p)
2473 2473 matchargs = ','.join(('%r' % p) for p in matchargs)
2474 2474 opts['_matchfiles'] = matchargs
2475 2475 if follow:
2476 2476 opts[fnopats[0][followfirst]] = '.'
2477 2477 else:
2478 2478 if follow:
2479 2479 if pats:
2480 2480 # follow() revset interprets its file argument as a
2481 2481 # manifest entry, so use match.files(), not pats.
2482 2482 opts[fpats[followfirst]] = list(match.files())
2483 2483 else:
2484 2484 op = fnopats[followdescendants][followfirst]
2485 2485 opts[op] = 'rev(%d)' % startrev
2486 2486 else:
2487 2487 opts['_patslog'] = list(pats)
2488 2488
2489 2489 filematcher = None
2490 2490 if opts.get('patch') or opts.get('stat'):
2491 2491 # When following files, track renames via a special matcher.
2492 2492 # If we're forced to take the slowpath it means we're following
2493 2493 # at least one pattern/directory, so don't bother with rename tracking.
2494 2494 if follow and not match.always() and not slowpath:
2495 2495 # _makefollowlogfilematcher expects its files argument to be
2496 2496 # relative to the repo root, so use match.files(), not pats.
2497 2497 filematcher = _makefollowlogfilematcher(repo, match.files(),
2498 2498 followfirst)
2499 2499 else:
2500 2500 filematcher = _makenofollowlogfilematcher(repo, pats, opts)
2501 2501 if filematcher is None:
2502 2502 filematcher = lambda rev: match
2503 2503
2504 2504 expr = []
2505 2505 for op, val in sorted(opts.iteritems()):
2506 2506 if not val:
2507 2507 continue
2508 2508 if op not in opt2revset:
2509 2509 continue
2510 2510 revop, andor = opt2revset[op]
2511 2511 if '%(val)' not in revop:
2512 2512 expr.append(revop)
2513 2513 else:
2514 2514 if not isinstance(val, list):
2515 2515 e = revop % {'val': val}
2516 2516 else:
2517 2517 e = '(' + andor.join((revop % {'val': v}) for v in val) + ')'
2518 2518 expr.append(e)
2519 2519
2520 2520 if expr:
2521 2521 expr = '(' + ' and '.join(expr) + ')'
2522 2522 else:
2523 2523 expr = None
2524 2524 return expr, filematcher
2525 2525
2526 2526 def _logrevs(repo, opts):
2527 2527 # Default --rev value depends on --follow but --follow behavior
2528 2528 # depends on revisions resolved from --rev...
2529 2529 follow = opts.get('follow') or opts.get('follow_first')
2530 2530 if opts.get('rev'):
2531 2531 revs = scmutil.revrange(repo, opts['rev'])
2532 2532 elif follow and repo.dirstate.p1() == nullid:
2533 2533 revs = smartset.baseset()
2534 2534 elif follow:
2535 2535 revs = repo.revs('reverse(:.)')
2536 2536 else:
2537 2537 revs = smartset.spanset(repo)
2538 2538 revs.reverse()
2539 2539 return revs
2540 2540
2541 2541 def getgraphlogrevs(repo, pats, opts):
2542 2542 """Return (revs, expr, filematcher) where revs is an iterable of
2543 2543 revision numbers, expr is a revset string built from log options
2544 2544 and file patterns or None, and used to filter 'revs'. If --stat or
2545 2545 --patch are not passed filematcher is None. Otherwise it is a
2546 2546 callable taking a revision number and returning a match objects
2547 2547 filtering the files to be detailed when displaying the revision.
2548 2548 """
2549 2549 limit = loglimit(opts)
2550 2550 revs = _logrevs(repo, opts)
2551 2551 if not revs:
2552 2552 return smartset.baseset(), None, None
2553 2553 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
2554 2554 if opts.get('rev'):
2555 2555 # User-specified revs might be unsorted, but don't sort before
2556 2556 # _makelogrevset because it might depend on the order of revs
2557 2557 if not (revs.isdescending() or revs.istopo()):
2558 2558 revs.sort(reverse=True)
2559 2559 if expr:
2560 2560 matcher = revset.match(repo.ui, expr)
2561 2561 revs = matcher(repo, revs)
2562 2562 if limit is not None:
2563 2563 limitedrevs = []
2564 2564 for idx, rev in enumerate(revs):
2565 2565 if idx >= limit:
2566 2566 break
2567 2567 limitedrevs.append(rev)
2568 2568 revs = smartset.baseset(limitedrevs)
2569 2569
2570 2570 return revs, expr, filematcher
2571 2571
2572 2572 def getlogrevs(repo, pats, opts):
2573 2573 """Return (revs, expr, filematcher) where revs is an iterable of
2574 2574 revision numbers, expr is a revset string built from log options
2575 2575 and file patterns or None, and used to filter 'revs'. If --stat or
2576 2576 --patch are not passed filematcher is None. Otherwise it is a
2577 2577 callable taking a revision number and returning a match objects
2578 2578 filtering the files to be detailed when displaying the revision.
2579 2579 """
2580 2580 limit = loglimit(opts)
2581 2581 revs = _logrevs(repo, opts)
2582 2582 if not revs:
2583 2583 return smartset.baseset([]), None, None
2584 2584 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
2585 2585 if expr:
2586 2586 matcher = revset.match(repo.ui, expr)
2587 2587 revs = matcher(repo, revs)
2588 2588 if limit is not None:
2589 2589 limitedrevs = []
2590 2590 for idx, r in enumerate(revs):
2591 2591 if limit <= idx:
2592 2592 break
2593 2593 limitedrevs.append(r)
2594 2594 revs = smartset.baseset(limitedrevs)
2595 2595
2596 2596 return revs, expr, filematcher
2597 2597
2598 2598 def _graphnodeformatter(ui, displayer):
2599 2599 spec = ui.config('ui', 'graphnodetemplate')
2600 2600 if not spec:
2601 2601 return templatekw.showgraphnode # fast path for "{graphnode}"
2602 2602
2603 2603 spec = templater.unquotestring(spec)
2604 2604 templ = formatter.maketemplater(ui, spec)
2605 2605 cache = {}
2606 2606 if isinstance(displayer, changeset_templater):
2607 2607 cache = displayer.cache # reuse cache of slow templates
2608 2608 props = templatekw.keywords.copy()
2609 2609 props['templ'] = templ
2610 2610 props['cache'] = cache
2611 2611 def formatnode(repo, ctx):
2612 2612 props['ctx'] = ctx
2613 2613 props['repo'] = repo
2614 2614 props['ui'] = repo.ui
2615 2615 props['revcache'] = {}
2616 2616 return templ.render(props)
2617 2617 return formatnode
2618 2618
2619 2619 def displaygraph(ui, repo, dag, displayer, edgefn, getrenamed=None,
2620 2620 filematcher=None):
2621 2621 formatnode = _graphnodeformatter(ui, displayer)
2622 2622 state = graphmod.asciistate()
2623 2623 styles = state['styles']
2624 2624
2625 2625 # only set graph styling if HGPLAIN is not set.
2626 2626 if ui.plain('graph'):
2627 2627 # set all edge styles to |, the default pre-3.8 behaviour
2628 2628 styles.update(dict.fromkeys(styles, '|'))
2629 2629 else:
2630 2630 edgetypes = {
2631 2631 'parent': graphmod.PARENT,
2632 2632 'grandparent': graphmod.GRANDPARENT,
2633 2633 'missing': graphmod.MISSINGPARENT
2634 2634 }
2635 2635 for name, key in edgetypes.items():
2636 2636 # experimental config: experimental.graphstyle.*
2637 2637 styles[key] = ui.config('experimental', 'graphstyle.%s' % name,
2638 2638 styles[key])
2639 2639 if not styles[key]:
2640 2640 styles[key] = None
2641 2641
2642 2642 # experimental config: experimental.graphshorten
2643 2643 state['graphshorten'] = ui.configbool('experimental', 'graphshorten')
2644 2644
2645 2645 for rev, type, ctx, parents in dag:
2646 2646 char = formatnode(repo, ctx)
2647 2647 copies = None
2648 2648 if getrenamed and ctx.rev():
2649 2649 copies = []
2650 2650 for fn in ctx.files():
2651 2651 rename = getrenamed(fn, ctx.rev())
2652 2652 if rename:
2653 2653 copies.append((fn, rename[0]))
2654 2654 revmatchfn = None
2655 2655 if filematcher is not None:
2656 2656 revmatchfn = filematcher(ctx.rev())
2657 2657 edges = edgefn(type, char, state, rev, parents)
2658 2658 firstedge = next(edges)
2659 2659 width = firstedge[2]
2660 2660 displayer.show(ctx, copies=copies, matchfn=revmatchfn,
2661 2661 _graphwidth=width)
2662 2662 lines = displayer.hunk.pop(rev).split('\n')
2663 2663 if not lines[-1]:
2664 2664 del lines[-1]
2665 2665 displayer.flush(ctx)
2666 2666 for type, char, width, coldata in itertools.chain([firstedge], edges):
2667 2667 graphmod.ascii(ui, state, type, char, lines, coldata)
2668 2668 lines = []
2669 2669 displayer.close()
2670 2670
2671 2671 def graphlog(ui, repo, pats, opts):
2672 2672 # Parameters are identical to log command ones
2673 2673 revs, expr, filematcher = getgraphlogrevs(repo, pats, opts)
2674 2674 revdag = graphmod.dagwalker(repo, revs)
2675 2675
2676 2676 getrenamed = None
2677 2677 if opts.get('copies'):
2678 2678 endrev = None
2679 2679 if opts.get('rev'):
2680 2680 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
2681 2681 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2682 2682
2683 2683 ui.pager('log')
2684 2684 displayer = show_changeset(ui, repo, opts, buffered=True)
2685 2685 displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges, getrenamed,
2686 2686 filematcher)
2687 2687
2688 2688 def checkunsupportedgraphflags(pats, opts):
2689 2689 for op in ["newest_first"]:
2690 2690 if op in opts and opts[op]:
2691 2691 raise error.Abort(_("-G/--graph option is incompatible with --%s")
2692 2692 % op.replace("_", "-"))
2693 2693
2694 2694 def graphrevs(repo, nodes, opts):
2695 2695 limit = loglimit(opts)
2696 2696 nodes.reverse()
2697 2697 if limit is not None:
2698 2698 nodes = nodes[:limit]
2699 2699 return graphmod.nodes(repo, nodes)
2700 2700
2701 2701 def add(ui, repo, match, prefix, explicitonly, **opts):
2702 2702 join = lambda f: os.path.join(prefix, f)
2703 2703 bad = []
2704 2704
2705 2705 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
2706 2706 names = []
2707 2707 wctx = repo[None]
2708 2708 cca = None
2709 2709 abort, warn = scmutil.checkportabilityalert(ui)
2710 2710 if abort or warn:
2711 2711 cca = scmutil.casecollisionauditor(ui, abort, repo.dirstate)
2712 2712
2713 2713 badmatch = matchmod.badmatch(match, badfn)
2714 2714 dirstate = repo.dirstate
2715 2715 # We don't want to just call wctx.walk here, since it would return a lot of
2716 2716 # clean files, which we aren't interested in and takes time.
2717 2717 for f in sorted(dirstate.walk(badmatch, sorted(wctx.substate),
2718 2718 True, False, full=False)):
2719 2719 exact = match.exact(f)
2720 2720 if exact or not explicitonly and f not in wctx and repo.wvfs.lexists(f):
2721 2721 if cca:
2722 2722 cca(f)
2723 2723 names.append(f)
2724 2724 if ui.verbose or not exact:
2725 2725 ui.status(_('adding %s\n') % match.rel(f))
2726 2726
2727 2727 for subpath in sorted(wctx.substate):
2728 2728 sub = wctx.sub(subpath)
2729 2729 try:
2730 2730 submatch = matchmod.subdirmatcher(subpath, match)
2731 2731 if opts.get(r'subrepos'):
2732 2732 bad.extend(sub.add(ui, submatch, prefix, False, **opts))
2733 2733 else:
2734 2734 bad.extend(sub.add(ui, submatch, prefix, True, **opts))
2735 2735 except error.LookupError:
2736 2736 ui.status(_("skipping missing subrepository: %s\n")
2737 2737 % join(subpath))
2738 2738
2739 2739 if not opts.get(r'dry_run'):
2740 2740 rejected = wctx.add(names, prefix)
2741 2741 bad.extend(f for f in rejected if f in match.files())
2742 2742 return bad
2743 2743
2744 2744 def addwebdirpath(repo, serverpath, webconf):
2745 2745 webconf[serverpath] = repo.root
2746 2746 repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root))
2747 2747
2748 2748 for r in repo.revs('filelog("path:.hgsub")'):
2749 2749 ctx = repo[r]
2750 2750 for subpath in ctx.substate:
2751 2751 ctx.sub(subpath).addwebdirpath(serverpath, webconf)
2752 2752
2753 2753 def forget(ui, repo, match, prefix, explicitonly):
2754 2754 join = lambda f: os.path.join(prefix, f)
2755 2755 bad = []
2756 2756 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
2757 2757 wctx = repo[None]
2758 2758 forgot = []
2759 2759
2760 2760 s = repo.status(match=matchmod.badmatch(match, badfn), clean=True)
2761 2761 forget = sorted(s.modified + s.added + s.deleted + s.clean)
2762 2762 if explicitonly:
2763 2763 forget = [f for f in forget if match.exact(f)]
2764 2764
2765 2765 for subpath in sorted(wctx.substate):
2766 2766 sub = wctx.sub(subpath)
2767 2767 try:
2768 2768 submatch = matchmod.subdirmatcher(subpath, match)
2769 2769 subbad, subforgot = sub.forget(submatch, prefix)
2770 2770 bad.extend([subpath + '/' + f for f in subbad])
2771 2771 forgot.extend([subpath + '/' + f for f in subforgot])
2772 2772 except error.LookupError:
2773 2773 ui.status(_("skipping missing subrepository: %s\n")
2774 2774 % join(subpath))
2775 2775
2776 2776 if not explicitonly:
2777 2777 for f in match.files():
2778 2778 if f not in repo.dirstate and not repo.wvfs.isdir(f):
2779 2779 if f not in forgot:
2780 2780 if repo.wvfs.exists(f):
2781 2781 # Don't complain if the exact case match wasn't given.
2782 2782 # But don't do this until after checking 'forgot', so
2783 2783 # that subrepo files aren't normalized, and this op is
2784 2784 # purely from data cached by the status walk above.
2785 2785 if repo.dirstate.normalize(f) in repo.dirstate:
2786 2786 continue
2787 2787 ui.warn(_('not removing %s: '
2788 2788 'file is already untracked\n')
2789 2789 % match.rel(f))
2790 2790 bad.append(f)
2791 2791
2792 2792 for f in forget:
2793 2793 if ui.verbose or not match.exact(f):
2794 2794 ui.status(_('removing %s\n') % match.rel(f))
2795 2795
2796 2796 rejected = wctx.forget(forget, prefix)
2797 2797 bad.extend(f for f in rejected if f in match.files())
2798 2798 forgot.extend(f for f in forget if f not in rejected)
2799 2799 return bad, forgot
2800 2800
2801 2801 def files(ui, ctx, m, fm, fmt, subrepos):
2802 2802 rev = ctx.rev()
2803 2803 ret = 1
2804 2804 ds = ctx.repo().dirstate
2805 2805
2806 2806 for f in ctx.matches(m):
2807 2807 if rev is None and ds[f] == 'r':
2808 2808 continue
2809 2809 fm.startitem()
2810 2810 if ui.verbose:
2811 2811 fc = ctx[f]
2812 2812 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
2813 2813 fm.data(abspath=f)
2814 2814 fm.write('path', fmt, m.rel(f))
2815 2815 ret = 0
2816 2816
2817 2817 for subpath in sorted(ctx.substate):
2818 2818 submatch = matchmod.subdirmatcher(subpath, m)
2819 2819 if (subrepos or m.exact(subpath) or any(submatch.files())):
2820 2820 sub = ctx.sub(subpath)
2821 2821 try:
2822 2822 recurse = m.exact(subpath) or subrepos
2823 2823 if sub.printfiles(ui, submatch, fm, fmt, recurse) == 0:
2824 2824 ret = 0
2825 2825 except error.LookupError:
2826 2826 ui.status(_("skipping missing subrepository: %s\n")
2827 2827 % m.abs(subpath))
2828 2828
2829 2829 return ret
2830 2830
2831 2831 def remove(ui, repo, m, prefix, after, force, subrepos, warnings=None):
2832 2832 join = lambda f: os.path.join(prefix, f)
2833 2833 ret = 0
2834 2834 s = repo.status(match=m, clean=True)
2835 2835 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2836 2836
2837 2837 wctx = repo[None]
2838 2838
2839 2839 if warnings is None:
2840 2840 warnings = []
2841 2841 warn = True
2842 2842 else:
2843 2843 warn = False
2844 2844
2845 2845 subs = sorted(wctx.substate)
2846 2846 total = len(subs)
2847 2847 count = 0
2848 2848 for subpath in subs:
2849 2849 count += 1
2850 2850 submatch = matchmod.subdirmatcher(subpath, m)
2851 2851 if subrepos or m.exact(subpath) or any(submatch.files()):
2852 2852 ui.progress(_('searching'), count, total=total, unit=_('subrepos'))
2853 2853 sub = wctx.sub(subpath)
2854 2854 try:
2855 2855 if sub.removefiles(submatch, prefix, after, force, subrepos,
2856 2856 warnings):
2857 2857 ret = 1
2858 2858 except error.LookupError:
2859 2859 warnings.append(_("skipping missing subrepository: %s\n")
2860 2860 % join(subpath))
2861 2861 ui.progress(_('searching'), None)
2862 2862
2863 2863 # warn about failure to delete explicit files/dirs
2864 2864 deleteddirs = util.dirs(deleted)
2865 2865 files = m.files()
2866 2866 total = len(files)
2867 2867 count = 0
2868 2868 for f in files:
2869 2869 def insubrepo():
2870 2870 for subpath in wctx.substate:
2871 2871 if f.startswith(subpath + '/'):
2872 2872 return True
2873 2873 return False
2874 2874
2875 2875 count += 1
2876 2876 ui.progress(_('deleting'), count, total=total, unit=_('files'))
2877 2877 isdir = f in deleteddirs or wctx.hasdir(f)
2878 2878 if (f in repo.dirstate or isdir or f == '.'
2879 2879 or insubrepo() or f in subs):
2880 2880 continue
2881 2881
2882 2882 if repo.wvfs.exists(f):
2883 2883 if repo.wvfs.isdir(f):
2884 2884 warnings.append(_('not removing %s: no tracked files\n')
2885 2885 % m.rel(f))
2886 2886 else:
2887 2887 warnings.append(_('not removing %s: file is untracked\n')
2888 2888 % m.rel(f))
2889 2889 # missing files will generate a warning elsewhere
2890 2890 ret = 1
2891 2891 ui.progress(_('deleting'), None)
2892 2892
2893 2893 if force:
2894 2894 list = modified + deleted + clean + added
2895 2895 elif after:
2896 2896 list = deleted
2897 2897 remaining = modified + added + clean
2898 2898 total = len(remaining)
2899 2899 count = 0
2900 2900 for f in remaining:
2901 2901 count += 1
2902 2902 ui.progress(_('skipping'), count, total=total, unit=_('files'))
2903 2903 warnings.append(_('not removing %s: file still exists\n')
2904 2904 % m.rel(f))
2905 2905 ret = 1
2906 2906 ui.progress(_('skipping'), None)
2907 2907 else:
2908 2908 list = deleted + clean
2909 2909 total = len(modified) + len(added)
2910 2910 count = 0
2911 2911 for f in modified:
2912 2912 count += 1
2913 2913 ui.progress(_('skipping'), count, total=total, unit=_('files'))
2914 2914 warnings.append(_('not removing %s: file is modified (use -f'
2915 2915 ' to force removal)\n') % m.rel(f))
2916 2916 ret = 1
2917 2917 for f in added:
2918 2918 count += 1
2919 2919 ui.progress(_('skipping'), count, total=total, unit=_('files'))
2920 2920 warnings.append(_("not removing %s: file has been marked for add"
2921 2921 " (use 'hg forget' to undo add)\n") % m.rel(f))
2922 2922 ret = 1
2923 2923 ui.progress(_('skipping'), None)
2924 2924
2925 2925 list = sorted(list)
2926 2926 total = len(list)
2927 2927 count = 0
2928 2928 for f in list:
2929 2929 count += 1
2930 2930 if ui.verbose or not m.exact(f):
2931 2931 ui.progress(_('deleting'), count, total=total, unit=_('files'))
2932 2932 ui.status(_('removing %s\n') % m.rel(f))
2933 2933 ui.progress(_('deleting'), None)
2934 2934
2935 2935 with repo.wlock():
2936 2936 if not after:
2937 2937 for f in list:
2938 2938 if f in added:
2939 2939 continue # we never unlink added files on remove
2940 2940 repo.wvfs.unlinkpath(f, ignoremissing=True)
2941 2941 repo[None].forget(list)
2942 2942
2943 2943 if warn:
2944 2944 for warning in warnings:
2945 2945 ui.warn(warning)
2946 2946
2947 2947 return ret
2948 2948
2949 2949 def cat(ui, repo, ctx, matcher, basefm, fntemplate, prefix, **opts):
2950 2950 err = 1
2951 2951
2952 2952 def write(path):
2953 2953 filename = None
2954 2954 if fntemplate:
2955 2955 filename = makefilename(repo, fntemplate, ctx.node(),
2956 2956 pathname=os.path.join(prefix, path))
2957 2957 with formatter.maybereopen(basefm, filename, opts) as fm:
2958 2958 data = ctx[path].data()
2959 2959 if opts.get('decode'):
2960 2960 data = repo.wwritedata(path, data)
2961 2961 fm.startitem()
2962 2962 fm.write('data', '%s', data)
2963 2963 fm.data(abspath=path, path=matcher.rel(path))
2964 2964
2965 2965 # Automation often uses hg cat on single files, so special case it
2966 2966 # for performance to avoid the cost of parsing the manifest.
2967 2967 if len(matcher.files()) == 1 and not matcher.anypats():
2968 2968 file = matcher.files()[0]
2969 2969 mfl = repo.manifestlog
2970 2970 mfnode = ctx.manifestnode()
2971 2971 try:
2972 2972 if mfnode and mfl[mfnode].find(file)[0]:
2973 2973 write(file)
2974 2974 return 0
2975 2975 except KeyError:
2976 2976 pass
2977 2977
2978 2978 for abs in ctx.walk(matcher):
2979 2979 write(abs)
2980 2980 err = 0
2981 2981
2982 2982 for subpath in sorted(ctx.substate):
2983 2983 sub = ctx.sub(subpath)
2984 2984 try:
2985 2985 submatch = matchmod.subdirmatcher(subpath, matcher)
2986 2986
2987 2987 if not sub.cat(submatch, basefm, fntemplate,
2988 2988 os.path.join(prefix, sub._path), **opts):
2989 2989 err = 0
2990 2990 except error.RepoLookupError:
2991 2991 ui.status(_("skipping missing subrepository: %s\n")
2992 2992 % os.path.join(prefix, subpath))
2993 2993
2994 2994 return err
2995 2995
2996 2996 def commit(ui, repo, commitfunc, pats, opts):
2997 2997 '''commit the specified files or all outstanding changes'''
2998 2998 date = opts.get('date')
2999 2999 if date:
3000 3000 opts['date'] = util.parsedate(date)
3001 3001 message = logmessage(ui, opts)
3002 3002 matcher = scmutil.match(repo[None], pats, opts)
3003 3003
3004 3004 dsguard = None
3005 3005 # extract addremove carefully -- this function can be called from a command
3006 3006 # that doesn't support addremove
3007 3007 if opts.get('addremove'):
3008 3008 dsguard = dirstateguard.dirstateguard(repo, 'commit')
3009 3009 with dsguard or util.nullcontextmanager():
3010 3010 if dsguard:
3011 3011 if scmutil.addremove(repo, matcher, "", opts) != 0:
3012 3012 raise error.Abort(
3013 3013 _("failed to mark all new/missing files as added/removed"))
3014 3014
3015 3015 return commitfunc(ui, repo, message, matcher, opts)
3016 3016
3017 3017 def samefile(f, ctx1, ctx2):
3018 3018 if f in ctx1.manifest():
3019 3019 a = ctx1.filectx(f)
3020 3020 if f in ctx2.manifest():
3021 3021 b = ctx2.filectx(f)
3022 3022 return (not a.cmp(b)
3023 3023 and a.flags() == b.flags())
3024 3024 else:
3025 3025 return False
3026 3026 else:
3027 3027 return f not in ctx2.manifest()
3028 3028
3029 # TODO: remove the commitfunc parameter because it is no longer used
3029 3030 def amend(ui, repo, commitfunc, old, extra, pats, opts):
3030 3031 # avoid cycle context -> subrepo -> cmdutil
3031 3032 from . import context
3032 3033
3033 3034 # amend will reuse the existing user if not specified, but the obsolete
3034 3035 # marker creation requires that the current user's name is specified.
3035 3036 if obsolete.isenabled(repo, obsolete.createmarkersopt):
3036 3037 ui.username() # raise exception if username not set
3037 3038
3038 3039 ui.note(_('amending changeset %s\n') % old)
3039 3040 base = old.p1()
3040 3041
3041 3042 with repo.wlock(), repo.lock(), repo.transaction('amend'):
3042 # See if we got a message from -m or -l, if not, open the editor
3043 # with the message of the changeset to amend
3044 message = logmessage(ui, opts)
3045 # ensure logfile does not conflict with later enforcement of the
3046 # message. potential logfile content has been processed by
3047 # `logmessage` anyway.
3048 opts.pop('logfile')
3049 # First, do a regular commit to record all changes in the working
3050 # directory (if there are any)
3051 ui.callhooks = False
3052 activebookmark = repo._bookmarks.active
3053 try:
3054 repo._bookmarks.active = None
3055 opts['message'] = 'temporary amend commit for %s' % old
3056 node = commit(ui, repo, commitfunc, pats, opts)
3057 finally:
3058 repo._bookmarks.active = activebookmark
3059 ui.callhooks = True
3060 ctx = repo[node]
3061
3062 3043 # Participating changesets:
3063 3044 #
3064 # node/ctx o - new (intermediate) commit that contains changes
3065 # | from working dir to go into amending commit
3066 # | (or a workingctx if there were no changes)
3045 # wctx o - workingctx that contains changes from working copy
3046 # | to go into amending commit
3067 3047 # |
3068 3048 # old o - changeset to amend
3069 3049 # |
3070 3050 # base o - first parent of the changeset to amend
3051 wctx = repo[None]
3071 3052
3072 3053 # Update extra dict from amended commit (e.g. to preserve graft
3073 3054 # source)
3074 3055 extra.update(old.extra())
3075 3056
3076 # Also update it from the intermediate commit or from the wctx
3077 extra.update(ctx.extra())
3057 # Also update it from the from the wctx
3058 extra.update(wctx.extra())
3059
3060 user = opts.get('user') or old.user()
3061 date = opts.get('date') or old.date()
3078 3062
3079 3063 if len(old.parents()) > 1:
3080 3064 # ctx.files() isn't reliable for merges, so fall back to the
3081 3065 # slower repo.status() method
3082 3066 files = set([fn for st in repo.status(base, old)[:3]
3083 3067 for fn in st])
3084 3068 else:
3085 3069 files = set(old.files())
3086 3070
3087 # Second, we use either the commit we just did, or if there were no
3088 # changes the parent of the working directory as the version of the
3089 # files in the final amend commit
3090 if node:
3091 ui.note(_('copying changeset %s to %s\n') % (ctx, base))
3092
3093 user = ctx.user()
3094 date = ctx.date()
3071 # add/remove the files to the working copy if the "addremove" option
3072 # was specified.
3073 matcher = scmutil.match(wctx, pats, opts)
3074 if (opts.get('addremove')
3075 and scmutil.addremove(repo, matcher, "", opts)):
3076 raise error.Abort(
3077 _("failed to mark all new/missing files as added/removed"))
3078
3079 filestoamend = set(f for f in wctx.files() if matcher(f))
3080
3081 changes = (len(filestoamend) > 0)
3082 if changes:
3095 3083 # Recompute copies (avoid recording a -> b -> a)
3096 copied = copies.pathcopies(base, ctx)
3084 copied = copies.pathcopies(base, wctx, matcher)
3097 3085 if old.p2:
3098 copied.update(copies.pathcopies(old.p2(), ctx))
3086 copied.update(copies.pathcopies(old.p2(), wctx, matcher))
3099 3087
3100 3088 # Prune files which were reverted by the updates: if old
3101 # introduced file X and our intermediate commit, node,
3102 # renamed that file, then those two files are the same and
3089 # introduced file X and the file was renamed in the working
3090 # copy, then those two files are the same and
3103 3091 # we can discard X from our list of files. Likewise if X
3104 3092 # was deleted, it's no longer relevant
3105 files.update(ctx.files())
3106 files = [f for f in files if not samefile(f, ctx, base)]
3093 files.update(filestoamend)
3094 files = [f for f in files if not samefile(f, wctx, base)]
3107 3095
3108 3096 def filectxfn(repo, ctx_, path):
3109 3097 try:
3110 fctx = ctx[path]
3098 # If the file being considered is not amongst the files
3099 # to be amended, we should return the file context from the
3100 # old changeset. This avoids issues when only some files in
3101 # the working copy are being amended but there are also
3102 # changes to other files from the old changeset.
3103 if path not in filestoamend:
3104 return old.filectx(path)
3105
3106 fctx = wctx[path]
3107
3108 # Return None for removed files.
3109 if not fctx.exists():
3110 return None
3111
3111 3112 flags = fctx.flags()
3112 3113 mctx = context.memfilectx(repo,
3113 3114 fctx.path(), fctx.data(),
3114 3115 islink='l' in flags,
3115 3116 isexec='x' in flags,
3116 3117 copied=copied.get(path))
3117 3118 return mctx
3118 3119 except KeyError:
3119 3120 return None
3120 3121 else:
3121 3122 ui.note(_('copying changeset %s to %s\n') % (old, base))
3122 3123
3123 3124 # Use version of files as in the old cset
3124 3125 def filectxfn(repo, ctx_, path):
3125 3126 try:
3126 3127 return old.filectx(path)
3127 3128 except KeyError:
3128 3129 return None
3129 3130
3130 user = opts.get('user') or old.user()
3131 date = opts.get('date') or old.date()
3131 # See if we got a message from -m or -l, if not, open the editor with
3132 # the message of the changeset to amend.
3133 message = logmessage(ui, opts)
3134
3132 3135 editform = mergeeditform(old, 'commit.amend')
3133 3136 editor = getcommiteditor(editform=editform,
3134 3137 **pycompat.strkwargs(opts))
3138
3135 3139 if not message:
3136 3140 editor = getcommiteditor(edit=True, editform=editform)
3137 3141 message = old.description()
3138 3142
3139 3143 pureextra = extra.copy()
3140 3144 extra['amend_source'] = old.hex()
3141 3145
3142 3146 new = context.memctx(repo,
3143 3147 parents=[base.node(), old.p2().node()],
3144 3148 text=message,
3145 3149 files=files,
3146 3150 filectxfn=filectxfn,
3147 3151 user=user,
3148 3152 date=date,
3149 3153 extra=extra,
3150 3154 editor=editor)
3151 3155
3152 3156 newdesc = changelog.stripdesc(new.description())
3153 if ((not node)
3157 if ((not changes)
3154 3158 and newdesc == old.description()
3155 3159 and user == old.user()
3156 3160 and date == old.date()
3157 3161 and pureextra == old.extra()):
3158 3162 # nothing changed. continuing here would create a new node
3159 3163 # anyway because of the amend_source noise.
3160 3164 #
3161 3165 # This not what we expect from amend.
3162 3166 return old.node()
3163 3167
3164 3168 if opts.get('secret'):
3165 3169 commitphase = 'secret'
3166 3170 else:
3167 3171 commitphase = old.phase()
3168 3172 overrides = {('phases', 'new-commit'): commitphase}
3169 3173 with ui.configoverride(overrides, 'amend'):
3170 3174 newid = repo.commitctx(new)
3171 3175
3172 3176 # Reroute the working copy parent to the new changeset
3173 3177 repo.setparents(newid, nullid)
3174 3178 mapping = {old.node(): (newid,)}
3175 if node:
3176 mapping[node] = ()
3177 3179 scmutil.cleanupnodes(repo, mapping, 'amend')
3178 3180
3181 # Fixing the dirstate because localrepo.commitctx does not update
3182 # it. This is rather convenient because we did not need to update
3183 # the dirstate for all the files in the new commit which commitctx
3184 # could have done if it updated the dirstate. Now, we can
3185 # selectively update the dirstate only for the amended files.
3186 dirstate = repo.dirstate
3187
3188 # Update the state of the files which were added and
3189 # and modified in the amend to "normal" in the dirstate.
3190 normalfiles = set(wctx.modified() + wctx.added()) & filestoamend
3191 for f in normalfiles:
3192 dirstate.normal(f)
3193
3194 # Update the state of files which were removed in the amend
3195 # to "removed" in the dirstate.
3196 removedfiles = set(wctx.removed()) & filestoamend
3197 for f in removedfiles:
3198 dirstate.drop(f)
3199
3179 3200 return newid
3180 3201
3181 3202 def commiteditor(repo, ctx, subs, editform=''):
3182 3203 if ctx.description():
3183 3204 return ctx.description()
3184 3205 return commitforceeditor(repo, ctx, subs, editform=editform,
3185 3206 unchangedmessagedetection=True)
3186 3207
3187 3208 def commitforceeditor(repo, ctx, subs, finishdesc=None, extramsg=None,
3188 3209 editform='', unchangedmessagedetection=False):
3189 3210 if not extramsg:
3190 3211 extramsg = _("Leave message empty to abort commit.")
3191 3212
3192 3213 forms = [e for e in editform.split('.') if e]
3193 3214 forms.insert(0, 'changeset')
3194 3215 templatetext = None
3195 3216 while forms:
3196 3217 ref = '.'.join(forms)
3197 3218 if repo.ui.config('committemplate', ref):
3198 3219 templatetext = committext = buildcommittemplate(
3199 3220 repo, ctx, subs, extramsg, ref)
3200 3221 break
3201 3222 forms.pop()
3202 3223 else:
3203 3224 committext = buildcommittext(repo, ctx, subs, extramsg)
3204 3225
3205 3226 # run editor in the repository root
3206 3227 olddir = pycompat.getcwd()
3207 3228 os.chdir(repo.root)
3208 3229
3209 3230 # make in-memory changes visible to external process
3210 3231 tr = repo.currenttransaction()
3211 3232 repo.dirstate.write(tr)
3212 3233 pending = tr and tr.writepending() and repo.root
3213 3234
3214 3235 editortext = repo.ui.edit(committext, ctx.user(), ctx.extra(),
3215 3236 editform=editform, pending=pending,
3216 3237 repopath=repo.path, action='commit')
3217 3238 text = editortext
3218 3239
3219 3240 # strip away anything below this special string (used for editors that want
3220 3241 # to display the diff)
3221 3242 stripbelow = re.search(_linebelow, text, flags=re.MULTILINE)
3222 3243 if stripbelow:
3223 3244 text = text[:stripbelow.start()]
3224 3245
3225 3246 text = re.sub("(?m)^HG:.*(\n|$)", "", text)
3226 3247 os.chdir(olddir)
3227 3248
3228 3249 if finishdesc:
3229 3250 text = finishdesc(text)
3230 3251 if not text.strip():
3231 3252 raise error.Abort(_("empty commit message"))
3232 3253 if unchangedmessagedetection and editortext == templatetext:
3233 3254 raise error.Abort(_("commit message unchanged"))
3234 3255
3235 3256 return text
3236 3257
3237 3258 def buildcommittemplate(repo, ctx, subs, extramsg, ref):
3238 3259 ui = repo.ui
3239 3260 spec = formatter.templatespec(ref, None, None)
3240 3261 t = changeset_templater(ui, repo, spec, None, {}, False)
3241 3262 t.t.cache.update((k, templater.unquotestring(v))
3242 3263 for k, v in repo.ui.configitems('committemplate'))
3243 3264
3244 3265 if not extramsg:
3245 3266 extramsg = '' # ensure that extramsg is string
3246 3267
3247 3268 ui.pushbuffer()
3248 3269 t.show(ctx, extramsg=extramsg)
3249 3270 return ui.popbuffer()
3250 3271
3251 3272 def hgprefix(msg):
3252 3273 return "\n".join(["HG: %s" % a for a in msg.split("\n") if a])
3253 3274
3254 3275 def buildcommittext(repo, ctx, subs, extramsg):
3255 3276 edittext = []
3256 3277 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
3257 3278 if ctx.description():
3258 3279 edittext.append(ctx.description())
3259 3280 edittext.append("")
3260 3281 edittext.append("") # Empty line between message and comments.
3261 3282 edittext.append(hgprefix(_("Enter commit message."
3262 3283 " Lines beginning with 'HG:' are removed.")))
3263 3284 edittext.append(hgprefix(extramsg))
3264 3285 edittext.append("HG: --")
3265 3286 edittext.append(hgprefix(_("user: %s") % ctx.user()))
3266 3287 if ctx.p2():
3267 3288 edittext.append(hgprefix(_("branch merge")))
3268 3289 if ctx.branch():
3269 3290 edittext.append(hgprefix(_("branch '%s'") % ctx.branch()))
3270 3291 if bookmarks.isactivewdirparent(repo):
3271 3292 edittext.append(hgprefix(_("bookmark '%s'") % repo._activebookmark))
3272 3293 edittext.extend([hgprefix(_("subrepo %s") % s) for s in subs])
3273 3294 edittext.extend([hgprefix(_("added %s") % f) for f in added])
3274 3295 edittext.extend([hgprefix(_("changed %s") % f) for f in modified])
3275 3296 edittext.extend([hgprefix(_("removed %s") % f) for f in removed])
3276 3297 if not added and not modified and not removed:
3277 3298 edittext.append(hgprefix(_("no files changed")))
3278 3299 edittext.append("")
3279 3300
3280 3301 return "\n".join(edittext)
3281 3302
3282 3303 def commitstatus(repo, node, branch, bheads=None, opts=None):
3283 3304 if opts is None:
3284 3305 opts = {}
3285 3306 ctx = repo[node]
3286 3307 parents = ctx.parents()
3287 3308
3288 3309 if (not opts.get('amend') and bheads and node not in bheads and not
3289 3310 [x for x in parents if x.node() in bheads and x.branch() == branch]):
3290 3311 repo.ui.status(_('created new head\n'))
3291 3312 # The message is not printed for initial roots. For the other
3292 3313 # changesets, it is printed in the following situations:
3293 3314 #
3294 3315 # Par column: for the 2 parents with ...
3295 3316 # N: null or no parent
3296 3317 # B: parent is on another named branch
3297 3318 # C: parent is a regular non head changeset
3298 3319 # H: parent was a branch head of the current branch
3299 3320 # Msg column: whether we print "created new head" message
3300 3321 # In the following, it is assumed that there already exists some
3301 3322 # initial branch heads of the current branch, otherwise nothing is
3302 3323 # printed anyway.
3303 3324 #
3304 3325 # Par Msg Comment
3305 3326 # N N y additional topo root
3306 3327 #
3307 3328 # B N y additional branch root
3308 3329 # C N y additional topo head
3309 3330 # H N n usual case
3310 3331 #
3311 3332 # B B y weird additional branch root
3312 3333 # C B y branch merge
3313 3334 # H B n merge with named branch
3314 3335 #
3315 3336 # C C y additional head from merge
3316 3337 # C H n merge with a head
3317 3338 #
3318 3339 # H H n head merge: head count decreases
3319 3340
3320 3341 if not opts.get('close_branch'):
3321 3342 for r in parents:
3322 3343 if r.closesbranch() and r.branch() == branch:
3323 3344 repo.ui.status(_('reopening closed branch head %d\n') % r)
3324 3345
3325 3346 if repo.ui.debugflag:
3326 3347 repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
3327 3348 elif repo.ui.verbose:
3328 3349 repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
3329 3350
3330 3351 def postcommitstatus(repo, pats, opts):
3331 3352 return repo.status(match=scmutil.match(repo[None], pats, opts))
3332 3353
3333 3354 def revert(ui, repo, ctx, parents, *pats, **opts):
3334 3355 parent, p2 = parents
3335 3356 node = ctx.node()
3336 3357
3337 3358 mf = ctx.manifest()
3338 3359 if node == p2:
3339 3360 parent = p2
3340 3361
3341 3362 # need all matching names in dirstate and manifest of target rev,
3342 3363 # so have to walk both. do not print errors if files exist in one
3343 3364 # but not other. in both cases, filesets should be evaluated against
3344 3365 # workingctx to get consistent result (issue4497). this means 'set:**'
3345 3366 # cannot be used to select missing files from target rev.
3346 3367
3347 3368 # `names` is a mapping for all elements in working copy and target revision
3348 3369 # The mapping is in the form:
3349 3370 # <asb path in repo> -> (<path from CWD>, <exactly specified by matcher?>)
3350 3371 names = {}
3351 3372
3352 3373 with repo.wlock():
3353 3374 ## filling of the `names` mapping
3354 3375 # walk dirstate to fill `names`
3355 3376
3356 3377 interactive = opts.get('interactive', False)
3357 3378 wctx = repo[None]
3358 3379 m = scmutil.match(wctx, pats, opts)
3359 3380
3360 3381 # we'll need this later
3361 3382 targetsubs = sorted(s for s in wctx.substate if m(s))
3362 3383
3363 3384 if not m.always():
3364 3385 matcher = matchmod.badmatch(m, lambda x, y: False)
3365 3386 for abs in wctx.walk(matcher):
3366 3387 names[abs] = m.rel(abs), m.exact(abs)
3367 3388
3368 3389 # walk target manifest to fill `names`
3369 3390
3370 3391 def badfn(path, msg):
3371 3392 if path in names:
3372 3393 return
3373 3394 if path in ctx.substate:
3374 3395 return
3375 3396 path_ = path + '/'
3376 3397 for f in names:
3377 3398 if f.startswith(path_):
3378 3399 return
3379 3400 ui.warn("%s: %s\n" % (m.rel(path), msg))
3380 3401
3381 3402 for abs in ctx.walk(matchmod.badmatch(m, badfn)):
3382 3403 if abs not in names:
3383 3404 names[abs] = m.rel(abs), m.exact(abs)
3384 3405
3385 3406 # Find status of all file in `names`.
3386 3407 m = scmutil.matchfiles(repo, names)
3387 3408
3388 3409 changes = repo.status(node1=node, match=m,
3389 3410 unknown=True, ignored=True, clean=True)
3390 3411 else:
3391 3412 changes = repo.status(node1=node, match=m)
3392 3413 for kind in changes:
3393 3414 for abs in kind:
3394 3415 names[abs] = m.rel(abs), m.exact(abs)
3395 3416
3396 3417 m = scmutil.matchfiles(repo, names)
3397 3418
3398 3419 modified = set(changes.modified)
3399 3420 added = set(changes.added)
3400 3421 removed = set(changes.removed)
3401 3422 _deleted = set(changes.deleted)
3402 3423 unknown = set(changes.unknown)
3403 3424 unknown.update(changes.ignored)
3404 3425 clean = set(changes.clean)
3405 3426 modadded = set()
3406 3427
3407 3428 # We need to account for the state of the file in the dirstate,
3408 3429 # even when we revert against something else than parent. This will
3409 3430 # slightly alter the behavior of revert (doing back up or not, delete
3410 3431 # or just forget etc).
3411 3432 if parent == node:
3412 3433 dsmodified = modified
3413 3434 dsadded = added
3414 3435 dsremoved = removed
3415 3436 # store all local modifications, useful later for rename detection
3416 3437 localchanges = dsmodified | dsadded
3417 3438 modified, added, removed = set(), set(), set()
3418 3439 else:
3419 3440 changes = repo.status(node1=parent, match=m)
3420 3441 dsmodified = set(changes.modified)
3421 3442 dsadded = set(changes.added)
3422 3443 dsremoved = set(changes.removed)
3423 3444 # store all local modifications, useful later for rename detection
3424 3445 localchanges = dsmodified | dsadded
3425 3446
3426 3447 # only take into account for removes between wc and target
3427 3448 clean |= dsremoved - removed
3428 3449 dsremoved &= removed
3429 3450 # distinct between dirstate remove and other
3430 3451 removed -= dsremoved
3431 3452
3432 3453 modadded = added & dsmodified
3433 3454 added -= modadded
3434 3455
3435 3456 # tell newly modified apart.
3436 3457 dsmodified &= modified
3437 3458 dsmodified |= modified & dsadded # dirstate added may need backup
3438 3459 modified -= dsmodified
3439 3460
3440 3461 # We need to wait for some post-processing to update this set
3441 3462 # before making the distinction. The dirstate will be used for
3442 3463 # that purpose.
3443 3464 dsadded = added
3444 3465
3445 3466 # in case of merge, files that are actually added can be reported as
3446 3467 # modified, we need to post process the result
3447 3468 if p2 != nullid:
3448 3469 mergeadd = set(dsmodified)
3449 3470 for path in dsmodified:
3450 3471 if path in mf:
3451 3472 mergeadd.remove(path)
3452 3473 dsadded |= mergeadd
3453 3474 dsmodified -= mergeadd
3454 3475
3455 3476 # if f is a rename, update `names` to also revert the source
3456 3477 cwd = repo.getcwd()
3457 3478 for f in localchanges:
3458 3479 src = repo.dirstate.copied(f)
3459 3480 # XXX should we check for rename down to target node?
3460 3481 if src and src not in names and repo.dirstate[src] == 'r':
3461 3482 dsremoved.add(src)
3462 3483 names[src] = (repo.pathto(src, cwd), True)
3463 3484
3464 3485 # determine the exact nature of the deleted changesets
3465 3486 deladded = set(_deleted)
3466 3487 for path in _deleted:
3467 3488 if path in mf:
3468 3489 deladded.remove(path)
3469 3490 deleted = _deleted - deladded
3470 3491
3471 3492 # distinguish between file to forget and the other
3472 3493 added = set()
3473 3494 for abs in dsadded:
3474 3495 if repo.dirstate[abs] != 'a':
3475 3496 added.add(abs)
3476 3497 dsadded -= added
3477 3498
3478 3499 for abs in deladded:
3479 3500 if repo.dirstate[abs] == 'a':
3480 3501 dsadded.add(abs)
3481 3502 deladded -= dsadded
3482 3503
3483 3504 # For files marked as removed, we check if an unknown file is present at
3484 3505 # the same path. If a such file exists it may need to be backed up.
3485 3506 # Making the distinction at this stage helps have simpler backup
3486 3507 # logic.
3487 3508 removunk = set()
3488 3509 for abs in removed:
3489 3510 target = repo.wjoin(abs)
3490 3511 if os.path.lexists(target):
3491 3512 removunk.add(abs)
3492 3513 removed -= removunk
3493 3514
3494 3515 dsremovunk = set()
3495 3516 for abs in dsremoved:
3496 3517 target = repo.wjoin(abs)
3497 3518 if os.path.lexists(target):
3498 3519 dsremovunk.add(abs)
3499 3520 dsremoved -= dsremovunk
3500 3521
3501 3522 # action to be actually performed by revert
3502 3523 # (<list of file>, message>) tuple
3503 3524 actions = {'revert': ([], _('reverting %s\n')),
3504 3525 'add': ([], _('adding %s\n')),
3505 3526 'remove': ([], _('removing %s\n')),
3506 3527 'drop': ([], _('removing %s\n')),
3507 3528 'forget': ([], _('forgetting %s\n')),
3508 3529 'undelete': ([], _('undeleting %s\n')),
3509 3530 'noop': (None, _('no changes needed to %s\n')),
3510 3531 'unknown': (None, _('file not managed: %s\n')),
3511 3532 }
3512 3533
3513 3534 # "constant" that convey the backup strategy.
3514 3535 # All set to `discard` if `no-backup` is set do avoid checking
3515 3536 # no_backup lower in the code.
3516 3537 # These values are ordered for comparison purposes
3517 3538 backupinteractive = 3 # do backup if interactively modified
3518 3539 backup = 2 # unconditionally do backup
3519 3540 check = 1 # check if the existing file differs from target
3520 3541 discard = 0 # never do backup
3521 3542 if opts.get('no_backup'):
3522 3543 backupinteractive = backup = check = discard
3523 3544 if interactive:
3524 3545 dsmodifiedbackup = backupinteractive
3525 3546 else:
3526 3547 dsmodifiedbackup = backup
3527 3548 tobackup = set()
3528 3549
3529 3550 backupanddel = actions['remove']
3530 3551 if not opts.get('no_backup'):
3531 3552 backupanddel = actions['drop']
3532 3553
3533 3554 disptable = (
3534 3555 # dispatch table:
3535 3556 # file state
3536 3557 # action
3537 3558 # make backup
3538 3559
3539 3560 ## Sets that results that will change file on disk
3540 3561 # Modified compared to target, no local change
3541 3562 (modified, actions['revert'], discard),
3542 3563 # Modified compared to target, but local file is deleted
3543 3564 (deleted, actions['revert'], discard),
3544 3565 # Modified compared to target, local change
3545 3566 (dsmodified, actions['revert'], dsmodifiedbackup),
3546 3567 # Added since target
3547 3568 (added, actions['remove'], discard),
3548 3569 # Added in working directory
3549 3570 (dsadded, actions['forget'], discard),
3550 3571 # Added since target, have local modification
3551 3572 (modadded, backupanddel, backup),
3552 3573 # Added since target but file is missing in working directory
3553 3574 (deladded, actions['drop'], discard),
3554 3575 # Removed since target, before working copy parent
3555 3576 (removed, actions['add'], discard),
3556 3577 # Same as `removed` but an unknown file exists at the same path
3557 3578 (removunk, actions['add'], check),
3558 3579 # Removed since targe, marked as such in working copy parent
3559 3580 (dsremoved, actions['undelete'], discard),
3560 3581 # Same as `dsremoved` but an unknown file exists at the same path
3561 3582 (dsremovunk, actions['undelete'], check),
3562 3583 ## the following sets does not result in any file changes
3563 3584 # File with no modification
3564 3585 (clean, actions['noop'], discard),
3565 3586 # Existing file, not tracked anywhere
3566 3587 (unknown, actions['unknown'], discard),
3567 3588 )
3568 3589
3569 3590 for abs, (rel, exact) in sorted(names.items()):
3570 3591 # target file to be touch on disk (relative to cwd)
3571 3592 target = repo.wjoin(abs)
3572 3593 # search the entry in the dispatch table.
3573 3594 # if the file is in any of these sets, it was touched in the working
3574 3595 # directory parent and we are sure it needs to be reverted.
3575 3596 for table, (xlist, msg), dobackup in disptable:
3576 3597 if abs not in table:
3577 3598 continue
3578 3599 if xlist is not None:
3579 3600 xlist.append(abs)
3580 3601 if dobackup:
3581 3602 # If in interactive mode, don't automatically create
3582 3603 # .orig files (issue4793)
3583 3604 if dobackup == backupinteractive:
3584 3605 tobackup.add(abs)
3585 3606 elif (backup <= dobackup or wctx[abs].cmp(ctx[abs])):
3586 3607 bakname = scmutil.origpath(ui, repo, rel)
3587 3608 ui.note(_('saving current version of %s as %s\n') %
3588 3609 (rel, bakname))
3589 3610 if not opts.get('dry_run'):
3590 3611 if interactive:
3591 3612 util.copyfile(target, bakname)
3592 3613 else:
3593 3614 util.rename(target, bakname)
3594 3615 if ui.verbose or not exact:
3595 3616 if not isinstance(msg, basestring):
3596 3617 msg = msg(abs)
3597 3618 ui.status(msg % rel)
3598 3619 elif exact:
3599 3620 ui.warn(msg % rel)
3600 3621 break
3601 3622
3602 3623 if not opts.get('dry_run'):
3603 3624 needdata = ('revert', 'add', 'undelete')
3604 3625 _revertprefetch(repo, ctx, *[actions[name][0] for name in needdata])
3605 3626 _performrevert(repo, parents, ctx, actions, interactive, tobackup)
3606 3627
3607 3628 if targetsubs:
3608 3629 # Revert the subrepos on the revert list
3609 3630 for sub in targetsubs:
3610 3631 try:
3611 3632 wctx.sub(sub).revert(ctx.substate[sub], *pats, **opts)
3612 3633 except KeyError:
3613 3634 raise error.Abort("subrepository '%s' does not exist in %s!"
3614 3635 % (sub, short(ctx.node())))
3615 3636
3616 3637 def _revertprefetch(repo, ctx, *files):
3617 3638 """Let extension changing the storage layer prefetch content"""
3618 3639 pass
3619 3640
3620 3641 def _performrevert(repo, parents, ctx, actions, interactive=False,
3621 3642 tobackup=None):
3622 3643 """function that actually perform all the actions computed for revert
3623 3644
3624 3645 This is an independent function to let extension to plug in and react to
3625 3646 the imminent revert.
3626 3647
3627 3648 Make sure you have the working directory locked when calling this function.
3628 3649 """
3629 3650 parent, p2 = parents
3630 3651 node = ctx.node()
3631 3652 excluded_files = []
3632 3653 matcher_opts = {"exclude": excluded_files}
3633 3654
3634 3655 def checkout(f):
3635 3656 fc = ctx[f]
3636 3657 repo.wwrite(f, fc.data(), fc.flags())
3637 3658
3638 3659 def doremove(f):
3639 3660 try:
3640 3661 repo.wvfs.unlinkpath(f)
3641 3662 except OSError:
3642 3663 pass
3643 3664 repo.dirstate.remove(f)
3644 3665
3645 3666 audit_path = pathutil.pathauditor(repo.root, cached=True)
3646 3667 for f in actions['forget'][0]:
3647 3668 if interactive:
3648 3669 choice = repo.ui.promptchoice(
3649 3670 _("forget added file %s (Yn)?$$ &Yes $$ &No") % f)
3650 3671 if choice == 0:
3651 3672 repo.dirstate.drop(f)
3652 3673 else:
3653 3674 excluded_files.append(repo.wjoin(f))
3654 3675 else:
3655 3676 repo.dirstate.drop(f)
3656 3677 for f in actions['remove'][0]:
3657 3678 audit_path(f)
3658 3679 if interactive:
3659 3680 choice = repo.ui.promptchoice(
3660 3681 _("remove added file %s (Yn)?$$ &Yes $$ &No") % f)
3661 3682 if choice == 0:
3662 3683 doremove(f)
3663 3684 else:
3664 3685 excluded_files.append(repo.wjoin(f))
3665 3686 else:
3666 3687 doremove(f)
3667 3688 for f in actions['drop'][0]:
3668 3689 audit_path(f)
3669 3690 repo.dirstate.remove(f)
3670 3691
3671 3692 normal = None
3672 3693 if node == parent:
3673 3694 # We're reverting to our parent. If possible, we'd like status
3674 3695 # to report the file as clean. We have to use normallookup for
3675 3696 # merges to avoid losing information about merged/dirty files.
3676 3697 if p2 != nullid:
3677 3698 normal = repo.dirstate.normallookup
3678 3699 else:
3679 3700 normal = repo.dirstate.normal
3680 3701
3681 3702 newlyaddedandmodifiedfiles = set()
3682 3703 if interactive:
3683 3704 # Prompt the user for changes to revert
3684 3705 torevert = [repo.wjoin(f) for f in actions['revert'][0]]
3685 3706 m = scmutil.match(ctx, torevert, matcher_opts)
3686 3707 diffopts = patch.difffeatureopts(repo.ui, whitespace=True)
3687 3708 diffopts.nodates = True
3688 3709 diffopts.git = True
3689 3710 operation = 'discard'
3690 3711 reversehunks = True
3691 3712 if node != parent:
3692 3713 operation = 'revert'
3693 3714 reversehunks = repo.ui.configbool('experimental',
3694 3715 'revertalternateinteractivemode')
3695 3716 if reversehunks:
3696 3717 diff = patch.diff(repo, ctx.node(), None, m, opts=diffopts)
3697 3718 else:
3698 3719 diff = patch.diff(repo, None, ctx.node(), m, opts=diffopts)
3699 3720 originalchunks = patch.parsepatch(diff)
3700 3721
3701 3722 try:
3702 3723
3703 3724 chunks, opts = recordfilter(repo.ui, originalchunks,
3704 3725 operation=operation)
3705 3726 if reversehunks:
3706 3727 chunks = patch.reversehunks(chunks)
3707 3728
3708 3729 except patch.PatchError as err:
3709 3730 raise error.Abort(_('error parsing patch: %s') % err)
3710 3731
3711 3732 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
3712 3733 if tobackup is None:
3713 3734 tobackup = set()
3714 3735 # Apply changes
3715 3736 fp = stringio()
3716 3737 for c in chunks:
3717 3738 # Create a backup file only if this hunk should be backed up
3718 3739 if ishunk(c) and c.header.filename() in tobackup:
3719 3740 abs = c.header.filename()
3720 3741 target = repo.wjoin(abs)
3721 3742 bakname = scmutil.origpath(repo.ui, repo, m.rel(abs))
3722 3743 util.copyfile(target, bakname)
3723 3744 tobackup.remove(abs)
3724 3745 c.write(fp)
3725 3746 dopatch = fp.tell()
3726 3747 fp.seek(0)
3727 3748 if dopatch:
3728 3749 try:
3729 3750 patch.internalpatch(repo.ui, repo, fp, 1, eolmode=None)
3730 3751 except patch.PatchError as err:
3731 3752 raise error.Abort(str(err))
3732 3753 del fp
3733 3754 else:
3734 3755 for f in actions['revert'][0]:
3735 3756 checkout(f)
3736 3757 if normal:
3737 3758 normal(f)
3738 3759
3739 3760 for f in actions['add'][0]:
3740 3761 # Don't checkout modified files, they are already created by the diff
3741 3762 if f not in newlyaddedandmodifiedfiles:
3742 3763 checkout(f)
3743 3764 repo.dirstate.add(f)
3744 3765
3745 3766 normal = repo.dirstate.normallookup
3746 3767 if node == parent and p2 == nullid:
3747 3768 normal = repo.dirstate.normal
3748 3769 for f in actions['undelete'][0]:
3749 3770 checkout(f)
3750 3771 normal(f)
3751 3772
3752 3773 copied = copies.pathcopies(repo[parent], ctx)
3753 3774
3754 3775 for f in actions['add'][0] + actions['undelete'][0] + actions['revert'][0]:
3755 3776 if f in copied:
3756 3777 repo.dirstate.copy(copied[f], f)
3757 3778
3758 3779 class command(registrar.command):
3759 3780 def _doregister(self, func, name, *args, **kwargs):
3760 3781 func._deprecatedregistrar = True # flag for deprecwarn in extensions.py
3761 3782 return super(command, self)._doregister(func, name, *args, **kwargs)
3762 3783
3763 3784 # a list of (ui, repo, otherpeer, opts, missing) functions called by
3764 3785 # commands.outgoing. "missing" is "missing" of the result of
3765 3786 # "findcommonoutgoing()"
3766 3787 outgoinghooks = util.hooks()
3767 3788
3768 3789 # a list of (ui, repo) functions called by commands.summary
3769 3790 summaryhooks = util.hooks()
3770 3791
3771 3792 # a list of (ui, repo, opts, changes) functions called by commands.summary.
3772 3793 #
3773 3794 # functions should return tuple of booleans below, if 'changes' is None:
3774 3795 # (whether-incomings-are-needed, whether-outgoings-are-needed)
3775 3796 #
3776 3797 # otherwise, 'changes' is a tuple of tuples below:
3777 3798 # - (sourceurl, sourcebranch, sourcepeer, incoming)
3778 3799 # - (desturl, destbranch, destpeer, outgoing)
3779 3800 summaryremotehooks = util.hooks()
3780 3801
3781 3802 # A list of state files kept by multistep operations like graft.
3782 3803 # Since graft cannot be aborted, it is considered 'clearable' by update.
3783 3804 # note: bisect is intentionally excluded
3784 3805 # (state file, clearable, allowcommit, error, hint)
3785 3806 unfinishedstates = [
3786 3807 ('graftstate', True, False, _('graft in progress'),
3787 3808 _("use 'hg graft --continue' or 'hg update' to abort")),
3788 3809 ('updatestate', True, False, _('last update was interrupted'),
3789 3810 _("use 'hg update' to get a consistent checkout"))
3790 3811 ]
3791 3812
3792 3813 def checkunfinished(repo, commit=False):
3793 3814 '''Look for an unfinished multistep operation, like graft, and abort
3794 3815 if found. It's probably good to check this right before
3795 3816 bailifchanged().
3796 3817 '''
3797 3818 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3798 3819 if commit and allowcommit:
3799 3820 continue
3800 3821 if repo.vfs.exists(f):
3801 3822 raise error.Abort(msg, hint=hint)
3802 3823
3803 3824 def clearunfinished(repo):
3804 3825 '''Check for unfinished operations (as above), and clear the ones
3805 3826 that are clearable.
3806 3827 '''
3807 3828 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3808 3829 if not clearable and repo.vfs.exists(f):
3809 3830 raise error.Abort(msg, hint=hint)
3810 3831 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3811 3832 if clearable and repo.vfs.exists(f):
3812 3833 util.unlink(repo.vfs.join(f))
3813 3834
3814 3835 afterresolvedstates = [
3815 3836 ('graftstate',
3816 3837 _('hg graft --continue')),
3817 3838 ]
3818 3839
3819 3840 def howtocontinue(repo):
3820 3841 '''Check for an unfinished operation and return the command to finish
3821 3842 it.
3822 3843
3823 3844 afterresolvedstates tuples define a .hg/{file} and the corresponding
3824 3845 command needed to finish it.
3825 3846
3826 3847 Returns a (msg, warning) tuple. 'msg' is a string and 'warning' is
3827 3848 a boolean.
3828 3849 '''
3829 3850 contmsg = _("continue: %s")
3830 3851 for f, msg in afterresolvedstates:
3831 3852 if repo.vfs.exists(f):
3832 3853 return contmsg % msg, True
3833 3854 if repo[None].dirty(missing=True, merge=False, branch=False):
3834 3855 return contmsg % _("hg commit"), False
3835 3856 return None, None
3836 3857
3837 3858 def checkafterresolved(repo):
3838 3859 '''Inform the user about the next action after completing hg resolve
3839 3860
3840 3861 If there's a matching afterresolvedstates, howtocontinue will yield
3841 3862 repo.ui.warn as the reporter.
3842 3863
3843 3864 Otherwise, it will yield repo.ui.note.
3844 3865 '''
3845 3866 msg, warning = howtocontinue(repo)
3846 3867 if msg is not None:
3847 3868 if warning:
3848 3869 repo.ui.warn("%s\n" % msg)
3849 3870 else:
3850 3871 repo.ui.note("%s\n" % msg)
3851 3872
3852 3873 def wrongtooltocontinue(repo, task):
3853 3874 '''Raise an abort suggesting how to properly continue if there is an
3854 3875 active task.
3855 3876
3856 3877 Uses howtocontinue() to find the active task.
3857 3878
3858 3879 If there's no task (repo.ui.note for 'hg commit'), it does not offer
3859 3880 a hint.
3860 3881 '''
3861 3882 after = howtocontinue(repo)
3862 3883 hint = None
3863 3884 if after[1]:
3864 3885 hint = after[0]
3865 3886 raise error.Abort(_('no %s in progress') % task, hint=hint)
@@ -1,226 +1,217 b''
1 1 #testcases obsstore-off obsstore-on
2 2
3 3 $ cat << EOF >> $HGRCPATH
4 4 > [extensions]
5 5 > amend=
6 6 > debugdrawdag=$TESTDIR/drawdag.py
7 7 > [diff]
8 8 > git=1
9 9 > EOF
10 10
11 11 #if obsstore-on
12 12 $ cat << EOF >> $HGRCPATH
13 13 > [experimental]
14 14 > stabilization=createmarkers
15 15 > EOF
16 16 #endif
17 17
18 18 Basic amend
19 19
20 20 $ hg init repo1
21 21 $ cd repo1
22 22 $ hg debugdrawdag <<'EOS'
23 23 > B
24 24 > |
25 25 > A
26 26 > EOS
27 27
28 28 $ hg update B -q
29 29 $ echo 2 >> B
30 30
31 31 $ hg amend
32 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/112478962961-af2c0941-amend.hg (glob) (obsstore-off !)
32 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/112478962961-7e959a55-amend.hg (glob) (obsstore-off !)
33 33 #if obsstore-off
34 34 $ hg log -p -G --hidden -T '{rev} {node|short} {desc}\n'
35 35 @ 1 be169c7e8dbe B
36 36 | diff --git a/B b/B
37 37 | new file mode 100644
38 38 | --- /dev/null
39 39 | +++ b/B
40 40 | @@ -0,0 +1,1 @@
41 41 | +B2
42 42 |
43 43 o 0 426bada5c675 A
44 44 diff --git a/A b/A
45 45 new file mode 100644
46 46 --- /dev/null
47 47 +++ b/A
48 48 @@ -0,0 +1,1 @@
49 49 +A
50 50 \ No newline at end of file
51 51
52 52 #else
53 53 $ hg log -p -G --hidden -T '{rev} {node|short} {desc}\n'
54 @ 3 be169c7e8dbe B
54 @ 2 be169c7e8dbe B
55 55 | diff --git a/B b/B
56 56 | new file mode 100644
57 57 | --- /dev/null
58 58 | +++ b/B
59 59 | @@ -0,0 +1,1 @@
60 60 | +B2
61 61 |
62 | x 2 edf08988b141 temporary amend commit for 112478962961
63 | | diff --git a/B b/B
64 | | --- a/B
65 | | +++ b/B
66 | | @@ -1,1 +1,1 @@
67 | | -B
68 | | \ No newline at end of file
69 | | +B2
70 | |
71 62 | x 1 112478962961 B
72 63 |/ diff --git a/B b/B
73 64 | new file mode 100644
74 65 | --- /dev/null
75 66 | +++ b/B
76 67 | @@ -0,0 +1,1 @@
77 68 | +B
78 69 | \ No newline at end of file
79 70 |
80 71 o 0 426bada5c675 A
81 72 diff --git a/A b/A
82 73 new file mode 100644
83 74 --- /dev/null
84 75 +++ b/A
85 76 @@ -0,0 +1,1 @@
86 77 +A
87 78 \ No newline at end of file
88 79
89 80 #endif
90 81
91 82 Nothing changed
92 83
93 84 $ hg amend
94 85 nothing changed
95 86 [1]
96 87
97 88 Matcher and metadata options
98 89
99 90 $ echo 3 > C
100 91 $ echo 4 > D
101 92 $ hg add C D
102 93 $ hg amend -m NEWMESSAGE -I C
103 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/be169c7e8dbe-c24d73fe-amend.hg (glob) (obsstore-off !)
94 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/be169c7e8dbe-7684ddc5-amend.hg (glob) (obsstore-off !)
104 95 $ hg log -r . -T '{node|short} {desc} {files}\n'
105 96 c7ba14d9075b NEWMESSAGE B C
106 97 $ echo 5 > E
107 98 $ rm C
108 99 $ hg amend -d '2000 1000' -u 'Foo <foo@example.com>' -A C D
109 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/c7ba14d9075b-b26ed45c-amend.hg (glob) (obsstore-off !)
100 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/c7ba14d9075b-b3e76daa-amend.hg (glob) (obsstore-off !)
110 101 $ hg log -r . -T '{node|short} {desc} {files} {author} {date}\n'
111 102 14f6c4bcc865 NEWMESSAGE B D Foo <foo@example.com> 2000.01000
112 103
113 104 Amend with editor
114 105
115 106 $ cat > $TESTTMP/prefix.sh <<'EOF'
116 107 > printf 'EDITED: ' > $TESTTMP/msg
117 108 > cat "$1" >> $TESTTMP/msg
118 109 > mv $TESTTMP/msg "$1"
119 110 > EOF
120 111 $ chmod +x $TESTTMP/prefix.sh
121 112
122 113 $ HGEDITOR="sh $TESTTMP/prefix.sh" hg amend --edit
123 114 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/14f6c4bcc865-6591f15d-amend.hg (glob) (obsstore-off !)
124 115 $ hg log -r . -T '{node|short} {desc}\n'
125 116 298f085230c3 EDITED: NEWMESSAGE
126 117 $ HGEDITOR="sh $TESTTMP/prefix.sh" hg amend -e -m MSG
127 118 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/298f085230c3-d81a6ad3-amend.hg (glob) (obsstore-off !)
128 119 $ hg log -r . -T '{node|short} {desc}\n'
129 120 974f07f28537 EDITED: MSG
130 121
131 122 $ echo FOO > $TESTTMP/msg
132 123 $ hg amend -l $TESTTMP/msg -m BAR
133 124 abort: options --message and --logfile are mutually exclusive
134 125 [255]
135 126 $ hg amend -l $TESTTMP/msg
136 127 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/974f07f28537-edb6470a-amend.hg (glob) (obsstore-off !)
137 128 $ hg log -r . -T '{node|short} {desc}\n'
138 129 507be9bdac71 FOO
139 130
140 131 Interactive mode
141 132
142 133 $ touch F G
143 134 $ hg add F G
144 135 $ cat <<EOS | hg amend -i --config ui.interactive=1
145 136 > y
146 137 > n
147 138 > EOS
148 139 diff --git a/F b/F
149 140 new file mode 100644
150 141 examine changes to 'F'? [Ynesfdaq?] y
151 142
152 143 diff --git a/G b/G
153 144 new file mode 100644
154 145 examine changes to 'G'? [Ynesfdaq?] n
155 146
156 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/507be9bdac71-7ae43d04-amend.hg (glob) (obsstore-off !)
147 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/507be9bdac71-c8077452-amend.hg (glob) (obsstore-off !)
157 148 $ hg log -r . -T '{files}\n'
158 149 B D F
159 150
160 151 Amend in the middle of a stack
161 152
162 153 $ hg init $TESTTMP/repo2
163 154 $ cd $TESTTMP/repo2
164 155 $ hg debugdrawdag <<'EOS'
165 156 > C
166 157 > |
167 158 > B
168 159 > |
169 160 > A
170 161 > EOS
171 162
172 163 $ hg update -q B
173 164 $ echo 2 >> B
174 165 $ hg amend
175 166 abort: cannot amend changeset with children
176 167 [255]
177 168
178 169 #if obsstore-on
179 170
180 171 With allowunstable, amend could work in the middle of a stack
181 172
182 173 $ cat >> $HGRCPATH <<EOF
183 174 > [experimental]
184 175 > stabilization=createmarkers, allowunstable
185 176 > EOF
186 177
187 178 $ hg amend
188 179 $ hg log -T '{rev} {node|short} {desc}\n' -G
189 @ 4 be169c7e8dbe B
180 @ 3 be169c7e8dbe B
190 181 |
191 182 | o 2 26805aba1e60 C
192 183 | |
193 184 | x 1 112478962961 B
194 185 |/
195 186 o 0 426bada5c675 A
196 187
197 188 #endif
198 189
199 190 Cannot amend public changeset
200 191
201 192 $ hg phase -r A --public
202 193 $ hg update -C -q A
203 194 $ hg amend -m AMEND
204 195 abort: cannot amend public changesets
205 196 [255]
206 197
207 198 Amend a merge changeset
208 199
209 200 $ hg init $TESTTMP/repo3
210 201 $ cd $TESTTMP/repo3
211 202 $ hg debugdrawdag <<'EOS'
212 203 > C
213 204 > /|
214 205 > A B
215 206 > EOS
216 207 $ hg update -q C
217 208 $ hg amend -m FOO
218 209 saved backup bundle to $TESTTMP/repo3/.hg/strip-backup/a35c07e8a2a4-15ff4612-amend.hg (glob) (obsstore-off !)
219 210 $ rm .hg/localtags
220 211 $ hg log -G -T '{desc}\n'
221 212 @ FOO
222 213 |\
223 214 | o B
224 215 |
225 216 o A
226 217
@@ -1,1269 +1,1268 b''
1 1 $ cat << EOF >> $HGRCPATH
2 2 > [format]
3 3 > usegeneraldelta=yes
4 4 > EOF
5 5
6 6 $ hg init
7 7
8 8 Setup:
9 9
10 10 $ echo a >> a
11 11 $ hg ci -Am 'base'
12 12 adding a
13 13
14 14 Refuse to amend public csets:
15 15
16 16 $ hg phase -r . -p
17 17 $ hg ci --amend
18 18 abort: cannot amend public changesets
19 19 [255]
20 20 $ hg phase -r . -f -d
21 21
22 22 $ echo a >> a
23 23 $ hg ci -Am 'base1'
24 24
25 25 Nothing to amend:
26 26
27 27 $ hg ci --amend -m 'base1'
28 28 nothing changed
29 29 [1]
30 30
31 31 $ cat >> $HGRCPATH <<EOF
32 32 > [hooks]
33 33 > pretxncommit.foo = sh -c "echo \\"pretxncommit \$HG_NODE\\"; hg id -r \$HG_NODE"
34 34 > EOF
35 35
36 36 Amending changeset with changes in working dir:
37 37 (and check that --message does not trigger an editor)
38 38
39 39 $ echo a >> a
40 40 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -m 'amend base1'
41 41 pretxncommit 43f1ba15f28a50abf0aae529cf8a16bfced7b149
42 42 43f1ba15f28a tip
43 saved backup bundle to $TESTTMP/.hg/strip-backup/489edb5b847d-f1bf3ab8-amend.hg (glob)
43 saved backup bundle to $TESTTMP/.hg/strip-backup/489edb5b847d-5ab4f721-amend.hg (glob)
44 44 $ echo 'pretxncommit.foo = ' >> $HGRCPATH
45 45 $ hg diff -c .
46 46 diff -r ad120869acf0 -r 43f1ba15f28a a
47 47 --- a/a Thu Jan 01 00:00:00 1970 +0000
48 48 +++ b/a Thu Jan 01 00:00:00 1970 +0000
49 49 @@ -1,1 +1,3 @@
50 50 a
51 51 +a
52 52 +a
53 53 $ hg log
54 54 changeset: 1:43f1ba15f28a
55 55 tag: tip
56 56 user: test
57 57 date: Thu Jan 01 00:00:00 1970 +0000
58 58 summary: amend base1
59 59
60 60 changeset: 0:ad120869acf0
61 61 user: test
62 62 date: Thu Jan 01 00:00:00 1970 +0000
63 63 summary: base
64 64
65 65
66 66 Check proper abort for empty message
67 67
68 68 $ cat > editor.sh << '__EOF__'
69 69 > #!/bin/sh
70 70 > echo "" > "$1"
71 71 > __EOF__
72
73 Update the existing file to ensure that the dirstate is not in pending state
74 (where the status of some files in the working copy is not known yet). This in
75 turn ensures that when the transaction is aborted due to an empty message during
76 the amend, there should be no rollback.
77 $ echo a >> a
78
72 79 $ echo b > b
73 80 $ hg add b
74 81 $ hg summary
75 82 parent: 1:43f1ba15f28a tip
76 83 amend base1
77 84 branch: default
78 commit: 1 added, 1 unknown
85 commit: 1 modified, 1 added, 1 unknown
79 86 update: (current)
80 87 phases: 2 draft
81 88 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
82 transaction abort!
83 rollback completed
84 89 abort: empty commit message
85 90 [255]
86 91 $ hg summary
87 92 parent: 1:43f1ba15f28a tip
88 93 amend base1
89 94 branch: default
90 commit: 1 added, 1 unknown
95 commit: 1 modified, 1 added, 1 unknown
91 96 update: (current)
92 97 phases: 2 draft
93 98
94 Add new file:
99 Add new file along with modified existing file:
95 100 $ hg ci --amend -m 'amend base1 new file'
96 saved backup bundle to $TESTTMP/.hg/strip-backup/43f1ba15f28a-7a3b3496-amend.hg (glob)
101 saved backup bundle to $TESTTMP/.hg/strip-backup/43f1ba15f28a-007467c2-amend.hg (glob)
97 102
98 103 Remove file that was added in amended commit:
99 104 (and test logfile option)
100 105 (and test that logfile option do not trigger an editor)
101 106
102 107 $ hg rm b
103 108 $ echo 'amend base1 remove new file' > ../logfile
104 109 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg ci --amend --logfile ../logfile
105 saved backup bundle to $TESTTMP/.hg/strip-backup/b8e3cb2b3882-0b55739a-amend.hg (glob)
110 saved backup bundle to $TESTTMP/.hg/strip-backup/c16295aaf401-1ada9901-amend.hg (glob)
106 111
107 112 $ hg cat b
108 b: no such file in rev 74609c7f506e
113 b: no such file in rev 47343646fa3d
109 114 [1]
110 115
111 116 No changes, just a different message:
112 117
113 118 $ hg ci -v --amend -m 'no changes, new message'
114 amending changeset 74609c7f506e
115 copying changeset 74609c7f506e to ad120869acf0
119 amending changeset 47343646fa3d
120 copying changeset 47343646fa3d to ad120869acf0
116 121 committing files:
117 122 a
118 123 committing manifest
119 124 committing changelog
120 125 1 changesets found
121 126 uncompressed size of bundle content:
122 127 254 (changelog)
123 128 163 (manifests)
124 129 a
125 saved backup bundle to $TESTTMP/.hg/strip-backup/74609c7f506e-1bfde511-amend.hg (glob)
129 131 a
130 saved backup bundle to $TESTTMP/.hg/strip-backup/47343646fa3d-c2758885-amend.hg (glob)
126 131 1 changesets found
127 132 uncompressed size of bundle content:
128 133 250 (changelog)
129 134 163 (manifests)
130 129 a
135 131 a
131 136 adding branch
132 137 adding changesets
133 138 adding manifests
134 139 adding file changes
135 140 added 1 changesets with 1 changes to 1 files
136 committed changeset 1:1cd866679df8
141 committed changeset 1:401431e913a1
137 142 $ hg diff -c .
138 diff -r ad120869acf0 -r 1cd866679df8 a
143 diff -r ad120869acf0 -r 401431e913a1 a
139 144 --- a/a Thu Jan 01 00:00:00 1970 +0000
140 145 +++ b/a Thu Jan 01 00:00:00 1970 +0000
141 @@ -1,1 +1,3 @@
146 @@ -1,1 +1,4 @@
142 147 a
143 148 +a
144 149 +a
150 +a
145 151 $ hg log
146 changeset: 1:1cd866679df8
152 changeset: 1:401431e913a1
147 153 tag: tip
148 154 user: test
149 155 date: Thu Jan 01 00:00:00 1970 +0000
150 156 summary: no changes, new message
151 157
152 158 changeset: 0:ad120869acf0
153 159 user: test
154 160 date: Thu Jan 01 00:00:00 1970 +0000
155 161 summary: base
156 162
157 163
158 164 Disable default date on commit so when -d isn't given, the old date is preserved:
159 165
160 166 $ echo '[defaults]' >> $HGRCPATH
161 167 $ echo 'commit=' >> $HGRCPATH
162 168
163 169 Test -u/-d:
164 170
165 171 $ cat > .hg/checkeditform.sh <<EOF
166 172 > env | grep HGEDITFORM
167 173 > true
168 174 > EOF
169 175 $ HGEDITOR="sh .hg/checkeditform.sh" hg ci --amend -u foo -d '1 0'
170 176 HGEDITFORM=commit.amend.normal
171 saved backup bundle to $TESTTMP/.hg/strip-backup/1cd866679df8-5f5bcb85-amend.hg (glob)
177 saved backup bundle to $TESTTMP/.hg/strip-backup/401431e913a1-5e8e532c-amend.hg (glob)
172 178 $ echo a >> a
173 179 $ hg ci --amend -u foo -d '1 0'
174 saved backup bundle to $TESTTMP/.hg/strip-backup/780e6f23e03d-83b10a27-amend.hg (glob)
180 saved backup bundle to $TESTTMP/.hg/strip-backup/d96b1d28ae33-677e0afb-amend.hg (glob)
175 181 $ hg log -r .
176 changeset: 1:5f357c7560ab
182 changeset: 1:a9a13940fc03
177 183 tag: tip
178 184 user: foo
179 185 date: Thu Jan 01 00:00:01 1970 +0000
180 186 summary: no changes, new message
181 187
182 188
183 189 Open editor with old commit message if a message isn't given otherwise:
184 190
185 191 $ cat > editor.sh << '__EOF__'
186 192 > #!/bin/sh
187 193 > cat $1
188 194 > echo "another precious commit message" > "$1"
189 195 > __EOF__
190 196
191 197 at first, test saving last-message.txt
192 198
193 199 $ cat > .hg/hgrc << '__EOF__'
194 200 > [hooks]
195 201 > pretxncommit.test-saving-last-message = false
196 202 > __EOF__
197 203
198 204 $ rm -f .hg/last-message.txt
199 205 $ hg commit --amend -v -m "message given from command line"
200 amending changeset 5f357c7560ab
201 copying changeset 5f357c7560ab to ad120869acf0
206 amending changeset a9a13940fc03
207 copying changeset a9a13940fc03 to ad120869acf0
202 208 committing files:
203 209 a
204 210 committing manifest
205 211 committing changelog
206 212 running hook pretxncommit.test-saving-last-message: false
207 213 transaction abort!
208 214 rollback completed
209 215 abort: pretxncommit.test-saving-last-message hook exited with status 1
210 216 [255]
211 217 $ cat .hg/last-message.txt
212 218 message given from command line (no-eol)
213 219
214 220 $ rm -f .hg/last-message.txt
215 221 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
216 amending changeset 5f357c7560ab
217 copying changeset 5f357c7560ab to ad120869acf0
222 amending changeset a9a13940fc03
223 copying changeset a9a13940fc03 to ad120869acf0
218 224 no changes, new message
219 225
220 226
221 227 HG: Enter commit message. Lines beginning with 'HG:' are removed.
222 228 HG: Leave message empty to abort commit.
223 229 HG: --
224 230 HG: user: foo
225 231 HG: branch 'default'
226 232 HG: changed a
227 233 committing files:
228 234 a
229 235 committing manifest
230 236 committing changelog
231 237 running hook pretxncommit.test-saving-last-message: false
232 238 transaction abort!
233 239 rollback completed
234 240 abort: pretxncommit.test-saving-last-message hook exited with status 1
235 241 [255]
236 242
237 243 $ cat .hg/last-message.txt
238 244 another precious commit message
239 245
240 246 $ cat > .hg/hgrc << '__EOF__'
241 247 > [hooks]
242 248 > pretxncommit.test-saving-last-message =
243 249 > __EOF__
244 250
245 251 then, test editing custom commit message
246 252
247 253 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
248 amending changeset 5f357c7560ab
249 copying changeset 5f357c7560ab to ad120869acf0
254 amending changeset a9a13940fc03
255 copying changeset a9a13940fc03 to ad120869acf0
250 256 no changes, new message
251 257
252 258
253 259 HG: Enter commit message. Lines beginning with 'HG:' are removed.
254 260 HG: Leave message empty to abort commit.
255 261 HG: --
256 262 HG: user: foo
257 263 HG: branch 'default'
258 264 HG: changed a
259 265 committing files:
260 266 a
261 267 committing manifest
262 268 committing changelog
263 269 1 changesets found
264 270 uncompressed size of bundle content:
265 271 249 (changelog)
266 272 163 (manifests)
267 131 a
268 saved backup bundle to $TESTTMP/.hg/strip-backup/5f357c7560ab-e7c84ade-amend.hg (glob)
273 133 a
274 saved backup bundle to $TESTTMP/.hg/strip-backup/a9a13940fc03-7c2e8674-amend.hg (glob)
269 275 1 changesets found
270 276 uncompressed size of bundle content:
271 277 257 (changelog)
272 278 163 (manifests)
273 131 a
279 133 a
274 280 adding branch
275 281 adding changesets
276 282 adding manifests
277 283 adding file changes
278 284 added 1 changesets with 1 changes to 1 files
279 committed changeset 1:7ab3bf440b54
285 committed changeset 1:64a124ba1b44
280 286
281 287 Same, but with changes in working dir (different code path):
282 288
283 289 $ echo a >> a
284 290 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
285 amending changeset 7ab3bf440b54
286 committing files:
287 a
288 committing manifest
289 committing changelog
290 copying changeset a0ea9b1a4c8c to ad120869acf0
291 amending changeset 64a124ba1b44
291 292 another precious commit message
292 293
293 294
294 295 HG: Enter commit message. Lines beginning with 'HG:' are removed.
295 296 HG: Leave message empty to abort commit.
296 297 HG: --
297 298 HG: user: foo
298 299 HG: branch 'default'
299 300 HG: changed a
300 301 committing files:
301 302 a
302 303 committing manifest
303 304 committing changelog
304 2 changesets found
305 uncompressed size of bundle content:
306 464 (changelog)
307 322 (manifests)
308 249 a
309 saved backup bundle to $TESTTMP/.hg/strip-backup/7ab3bf440b54-8e3b5088-amend.hg (glob)
310 305 1 changesets found
311 306 uncompressed size of bundle content:
312 307 257 (changelog)
313 308 163 (manifests)
314 309 133 a
310 saved backup bundle to $TESTTMP/.hg/strip-backup/64a124ba1b44-10374b8f-amend.hg (glob)
311 1 changesets found
312 uncompressed size of bundle content:
313 257 (changelog)
314 163 (manifests)
315 135 a
315 316 adding branch
316 317 adding changesets
317 318 adding manifests
318 319 adding file changes
319 320 added 1 changesets with 1 changes to 1 files
320 committed changeset 1:ea22a388757c
321 committed changeset 1:7892795b8e38
321 322
322 323 $ rm editor.sh
323 324 $ hg log -r .
324 changeset: 1:ea22a388757c
325 changeset: 1:7892795b8e38
325 326 tag: tip
326 327 user: foo
327 328 date: Thu Jan 01 00:00:01 1970 +0000
328 329 summary: another precious commit message
329 330
330 331
331 332 Moving bookmarks, preserve active bookmark:
332 333
333 334 $ hg book book1
334 335 $ hg book book2
335 336 $ hg ci --amend -m 'move bookmarks'
336 saved backup bundle to $TESTTMP/.hg/strip-backup/ea22a388757c-e51094db-amend.hg (glob)
337 saved backup bundle to $TESTTMP/.hg/strip-backup/7892795b8e38-3fb46217-amend.hg (glob)
337 338 $ hg book
338 book1 1:6cec5aa930e2
339 * book2 1:6cec5aa930e2
339 book1 1:8311f17e2616
340 * book2 1:8311f17e2616
340 341 $ echo a >> a
341 342 $ hg ci --amend -m 'move bookmarks'
342 saved backup bundle to $TESTTMP/.hg/strip-backup/6cec5aa930e2-e9b06de4-amend.hg (glob)
343 saved backup bundle to $TESTTMP/.hg/strip-backup/8311f17e2616-f0504fe3-amend.hg (glob)
343 344 $ hg book
344 book1 1:48bb6e53a15f
345 * book2 1:48bb6e53a15f
345 book1 1:a3b65065808c
346 * book2 1:a3b65065808c
346 347
347 348 abort does not loose bookmarks
348 349
349 350 $ cat > editor.sh << '__EOF__'
350 351 > #!/bin/sh
351 352 > echo "" > "$1"
352 353 > __EOF__
353 354 $ echo a >> a
354 355 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
355 transaction abort!
356 rollback completed
357 356 abort: empty commit message
358 357 [255]
359 358 $ hg book
360 book1 1:48bb6e53a15f
361 * book2 1:48bb6e53a15f
359 book1 1:a3b65065808c
360 * book2 1:a3b65065808c
362 361 $ hg revert -Caq
363 362 $ rm editor.sh
364 363
365 364 $ echo '[defaults]' >> $HGRCPATH
366 365 $ echo "commit=-d '0 0'" >> $HGRCPATH
367 366
368 367 Moving branches:
369 368
370 369 $ hg branch foo
371 370 marked working directory as branch foo
372 371 (branches are permanent and global, did you want a bookmark?)
373 372 $ echo a >> a
374 373 $ hg ci -m 'branch foo'
375 374 $ hg branch default -f
376 375 marked working directory as branch default
377 376 $ hg ci --amend -m 'back to default'
378 saved backup bundle to $TESTTMP/.hg/strip-backup/8ac881fbf49d-fd962fef-amend.hg (glob)
377 saved backup bundle to $TESTTMP/.hg/strip-backup/f8339a38efe1-c18453c9-amend.hg (glob)
379 378 $ hg branches
380 default 2:ce12b0b57d46
379 default 2:9c07515f2650
381 380
382 381 Close branch:
383 382
384 383 $ hg up -q 0
385 384 $ echo b >> b
386 385 $ hg branch foo
387 386 marked working directory as branch foo
388 387 (branches are permanent and global, did you want a bookmark?)
389 388 $ hg ci -Am 'fork'
390 389 adding b
391 390 $ echo b >> b
392 391 $ hg ci -mb
393 392 $ hg ci --amend --close-branch -m 'closing branch foo'
394 saved backup bundle to $TESTTMP/.hg/strip-backup/c962248fa264-6701c392-amend.hg (glob)
393 saved backup bundle to $TESTTMP/.hg/strip-backup/c962248fa264-54245dc7-amend.hg (glob)
395 394
396 395 Same thing, different code path:
397 396
398 397 $ echo b >> b
399 398 $ hg ci -m 'reopen branch'
400 399 reopening closed branch head 4
401 400 $ echo b >> b
402 401 $ hg ci --amend --close-branch
403 saved backup bundle to $TESTTMP/.hg/strip-backup/027371728205-49c0c55d-amend.hg (glob)
402 saved backup bundle to $TESTTMP/.hg/strip-backup/027371728205-b900d9fa-amend.hg (glob)
404 403 $ hg branches
405 default 2:ce12b0b57d46
404 default 2:9c07515f2650
406 405
407 406 Refuse to amend during a merge:
408 407
409 408 $ hg up -q default
410 409 $ hg merge foo
411 410 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
412 411 (branch merge, don't forget to commit)
413 412 $ hg ci --amend
414 413 abort: cannot amend while merging
415 414 [255]
416 415 $ hg ci -m 'merge'
417 416
418 417 Follow copies/renames:
419 418
420 419 $ hg mv b c
421 420 $ hg ci -m 'b -> c'
422 421 $ hg mv c d
423 422 $ hg ci --amend -m 'b -> d'
424 saved backup bundle to $TESTTMP/.hg/strip-backup/b8c6eac7f12e-adaaa8b1-amend.hg (glob)
423 saved backup bundle to $TESTTMP/.hg/strip-backup/42f3f27a067d-f23cc9f7-amend.hg (glob)
425 424 $ hg st --rev '.^' --copies d
426 425 A d
427 426 b
428 427 $ hg cp d e
429 428 $ hg ci -m 'e = d'
430 429 $ hg cp e f
431 430 $ hg ci --amend -m 'f = d'
432 saved backup bundle to $TESTTMP/.hg/strip-backup/7f9761d65613-d37aa788-amend.hg (glob)
431 saved backup bundle to $TESTTMP/.hg/strip-backup/9198f73182d5-251d584a-amend.hg (glob)
433 432 $ hg st --rev '.^' --copies f
434 433 A f
435 434 d
436 435
437 436 $ mv f f.orig
438 437 $ hg rm -A f
439 438 $ hg ci -m removef
440 439 $ hg cp a f
441 440 $ mv f.orig f
442 441 $ hg ci --amend -m replacef
443 saved backup bundle to $TESTTMP/.hg/strip-backup/9e8c5f7e3d95-90259f67-amend.hg (glob)
442 saved backup bundle to $TESTTMP/.hg/strip-backup/f0993ab6b482-eda301bf-amend.hg (glob)
444 443 $ hg st --change . --copies
445 444 $ hg log -r . --template "{file_copies}\n"
446 445
447 446
448 447 Move added file (issue3410):
449 448
450 449 $ echo g >> g
451 450 $ hg ci -Am g
452 451 adding g
453 452 $ hg mv g h
454 453 $ hg ci --amend
455 saved backup bundle to $TESTTMP/.hg/strip-backup/24aa8eacce2b-7059e0f1-amend.hg (glob)
454 saved backup bundle to $TESTTMP/.hg/strip-backup/58585e3f095c-0f5ebcda-amend.hg (glob)
456 455 $ hg st --change . --copies h
457 456 A h
458 457 $ hg log -r . --template "{file_copies}\n"
459 458
460 459
461 460 Can't rollback an amend:
462 461
463 462 $ hg rollback
464 463 no rollback information available
465 464 [1]
466 465
467 466 Preserve extra dict (issue3430):
468 467
469 468 $ hg branch a
470 469 marked working directory as branch a
471 470 (branches are permanent and global, did you want a bookmark?)
472 471 $ echo a >> a
473 472 $ hg ci -ma
474 473 $ hg ci --amend -m "a'"
475 saved backup bundle to $TESTTMP/.hg/strip-backup/3837aa2a2fdb-2be01fd1-amend.hg (glob)
474 saved backup bundle to $TESTTMP/.hg/strip-backup/39a162f1d65e-9dfe13d8-amend.hg (glob)
476 475 $ hg log -r . --template "{branch}\n"
477 476 a
478 477 $ hg ci --amend -m "a''"
479 saved backup bundle to $TESTTMP/.hg/strip-backup/c05c06be7514-ed28c4cd-amend.hg (glob)
478 saved backup bundle to $TESTTMP/.hg/strip-backup/d5ca7b1ac72b-0b4c1a34-amend.hg (glob)
480 479 $ hg log -r . --template "{branch}\n"
481 480 a
482 481
483 482 Also preserve other entries in the dict that are in the old commit,
484 483 first graft something so there's an additional entry:
485 484
486 485 $ hg up 0 -q
487 486 $ echo z > z
488 487 $ hg ci -Am 'fork'
489 488 adding z
490 489 created new head
491 490 $ hg up 11
492 491 5 files updated, 0 files merged, 1 files removed, 0 files unresolved
493 492 $ hg graft 12
494 493 grafting 12:2647734878ef "fork" (tip)
495 494 $ hg ci --amend -m 'graft amend'
496 saved backup bundle to $TESTTMP/.hg/strip-backup/bd010aea3f39-eedb103b-amend.hg (glob)
495 saved backup bundle to $TESTTMP/.hg/strip-backup/fe8c6f7957ca-25638666-amend.hg (glob)
497 496 $ hg log -r . --debug | grep extra
498 extra: amend_source=bd010aea3f39f3fb2a2f884b9ccb0471cd77398e
497 extra: amend_source=fe8c6f7957ca1665ed77496ed7a07657d469ac60
499 498 extra: branch=a
500 499 extra: source=2647734878ef0236dda712fae9c1651cf694ea8a
501 500
502 501 Preserve phase
503 502
504 503 $ hg phase '.^::.'
505 504 11: draft
506 505 13: draft
507 506 $ hg phase --secret --force .
508 507 $ hg phase '.^::.'
509 508 11: draft
510 509 13: secret
511 510 $ hg commit --amend -m 'amend for phase' -q
512 511 $ hg phase '.^::.'
513 512 11: draft
514 513 13: secret
515 514
516 515 Test amend with obsolete
517 516 ---------------------------
518 517
519 518 Enable obsolete
520 519
521 520 $ cat >> $HGRCPATH << EOF
522 521 > [experimental]
523 522 > stabilization=createmarkers,allowunstable
524 523 > EOF
525 524
526 525 Amend with no files changes
527 526
528 527 $ hg id -n
529 528 13
530 529 $ hg ci --amend -m 'babar'
531 530 $ hg id -n
532 531 14
533 532 $ hg log -Gl 3 --style=compact
534 @ 14[tip]:11 b650e6ee8614 1970-01-01 00:00 +0000 test
533 @ 14[tip]:11 682950e85999 1970-01-01 00:00 +0000 test
535 534 | babar
536 535 |
537 536 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
538 537 | | fork
539 538 | ~
540 o 11 3334b7925910 1970-01-01 00:00 +0000 test
539 o 11 0ddb275cfad1 1970-01-01 00:00 +0000 test
541 540 | a''
542 541 ~
543 542 $ hg log -Gl 4 --hidden --style=compact
544 @ 14[tip]:11 b650e6ee8614 1970-01-01 00:00 +0000 test
543 @ 14[tip]:11 682950e85999 1970-01-01 00:00 +0000 test
545 544 | babar
546 545 |
547 | x 13:11 68ff8ff97044 1970-01-01 00:00 +0000 test
546 | x 13:11 5167600b0f7a 1970-01-01 00:00 +0000 test
548 547 |/ amend for phase
549 548 |
550 549 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
551 550 | | fork
552 551 | ~
553 o 11 3334b7925910 1970-01-01 00:00 +0000 test
552 o 11 0ddb275cfad1 1970-01-01 00:00 +0000 test
554 553 | a''
555 554 ~
556 555
557 556 Amend with files changes
558 557
559 558 (note: the extra commit over 15 is a temporary junk I would be happy to get
560 559 ride of)
561 560
562 561 $ echo 'babar' >> a
563 562 $ hg commit --amend
564 563 $ hg log -Gl 6 --hidden --style=compact
565 @ 16[tip]:11 9f9e9bccf56c 1970-01-01 00:00 +0000 test
564 @ 15[tip]:11 a5b42b49b0d5 1970-01-01 00:00 +0000 test
566 565 | babar
567 566 |
568 | x 15 90fef497c56f 1970-01-01 00:00 +0000 test
569 | | temporary amend commit for b650e6ee8614
570 | |
571 | x 14:11 b650e6ee8614 1970-01-01 00:00 +0000 test
567 | x 14:11 682950e85999 1970-01-01 00:00 +0000 test
572 568 |/ babar
573 569 |
574 | x 13:11 68ff8ff97044 1970-01-01 00:00 +0000 test
570 | x 13:11 5167600b0f7a 1970-01-01 00:00 +0000 test
575 571 |/ amend for phase
576 572 |
577 573 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
578 574 | | fork
579 575 | ~
580 o 11 3334b7925910 1970-01-01 00:00 +0000 test
576 o 11 0ddb275cfad1 1970-01-01 00:00 +0000 test
581 577 | a''
578 |
579 o 10 5fa75032e226 1970-01-01 00:00 +0000 test
580 | g
582 581 ~
583 582
584 583
585 584 Test that amend does not make it easy to create obsolescence cycle
586 585 ---------------------------------------------------------------------
587 586
588 587 $ hg id -r 14 --hidden
589 b650e6ee8614 (a)
588 682950e85999 (a)
590 589 $ hg revert -ar 14 --hidden
591 590 reverting a
592 591 $ hg commit --amend
593 592 $ hg id
594 b99e5df575f7 (a) tip
593 37973c7e0b61 (a) tip
595 594
596 595 Test that rewriting leaving instability behind is allowed
597 596 ---------------------------------------------------------------------
598 597
599 598 $ hg up '.^'
600 599 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
601 600 $ echo 'b' >> a
602 601 $ hg log --style compact -r 'children(.)'
603 18[tip]:11 b99e5df575f7 1970-01-01 00:00 +0000 test
602 16[tip]:11 37973c7e0b61 1970-01-01 00:00 +0000 test
604 603 babar
605 604
606 605 $ hg commit --amend
607 606 $ hg log -r 'orphan()'
608 changeset: 18:b99e5df575f7
607 changeset: 16:37973c7e0b61
609 608 branch: a
610 parent: 11:3334b7925910
609 parent: 11:0ddb275cfad1
611 610 user: test
612 611 date: Thu Jan 01 00:00:00 1970 +0000
613 612 instability: orphan
614 613 summary: babar
615 614
616 615
617 616 Amend a merge changeset (with renames and conflicts from the second parent):
618 617
619 618 $ hg up -q default
620 619 $ hg branch -q bar
621 620 $ hg cp a aa
622 621 $ hg mv z zz
623 622 $ echo cc > cc
624 623 $ hg add cc
625 624 $ hg ci -m aazzcc
626 625 $ hg up -q default
627 626 $ echo a >> a
628 627 $ echo dd > cc
629 628 $ hg add cc
630 629 $ hg ci -m aa
631 630 $ hg merge -q bar
632 631 warning: conflicts while merging cc! (edit, then use 'hg resolve --mark')
633 632 [1]
634 633 $ hg resolve -m cc
635 634 (no more unresolved files)
636 635 $ hg ci -m 'merge bar'
637 636 $ hg log --config diff.git=1 -pr .
638 changeset: 23:163cfd7219f7
637 changeset: 20:163cfd7219f7
639 638 tag: tip
640 parent: 22:30d96aeaf27b
641 parent: 21:1aa437659d19
639 parent: 19:30d96aeaf27b
640 parent: 18:1aa437659d19
642 641 user: test
643 642 date: Thu Jan 01 00:00:00 1970 +0000
644 643 summary: merge bar
645 644
646 645 diff --git a/a b/aa
647 646 copy from a
648 647 copy to aa
649 648 diff --git a/cc b/cc
650 649 --- a/cc
651 650 +++ b/cc
652 651 @@ -1,1 +1,5 @@
653 652 +<<<<<<< working copy: 30d96aeaf27b - test: aa
654 653 dd
655 654 +=======
656 655 +cc
657 656 +>>>>>>> merge rev: 1aa437659d19 bar - test: aazzcc
658 657 diff --git a/z b/zz
659 658 rename from z
660 659 rename to zz
661 660
662 661 $ hg debugrename aa
663 662 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
664 663 $ hg debugrename zz
665 664 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
666 665 $ hg debugrename cc
667 666 cc not renamed
668 667 $ HGEDITOR="sh .hg/checkeditform.sh" hg ci --amend -m 'merge bar (amend message)' --edit
669 668 HGEDITFORM=commit.amend.merge
670 669 $ hg log --config diff.git=1 -pr .
671 changeset: 24:bca52d4ed186
670 changeset: 21:bca52d4ed186
672 671 tag: tip
673 parent: 22:30d96aeaf27b
674 parent: 21:1aa437659d19
672 parent: 19:30d96aeaf27b
673 parent: 18:1aa437659d19
675 674 user: test
676 675 date: Thu Jan 01 00:00:00 1970 +0000
677 676 summary: merge bar (amend message)
678 677
679 678 diff --git a/a b/aa
680 679 copy from a
681 680 copy to aa
682 681 diff --git a/cc b/cc
683 682 --- a/cc
684 683 +++ b/cc
685 684 @@ -1,1 +1,5 @@
686 685 +<<<<<<< working copy: 30d96aeaf27b - test: aa
687 686 dd
688 687 +=======
689 688 +cc
690 689 +>>>>>>> merge rev: 1aa437659d19 bar - test: aazzcc
691 690 diff --git a/z b/zz
692 691 rename from z
693 692 rename to zz
694 693
695 694 $ hg debugrename aa
696 695 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
697 696 $ hg debugrename zz
698 697 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
699 698 $ hg debugrename cc
700 699 cc not renamed
701 700 $ hg mv zz z
702 701 $ hg ci --amend -m 'merge bar (undo rename)'
703 702 $ hg log --config diff.git=1 -pr .
704 changeset: 26:12594a98ca3f
703 changeset: 22:12594a98ca3f
705 704 tag: tip
706 parent: 22:30d96aeaf27b
707 parent: 21:1aa437659d19
705 parent: 19:30d96aeaf27b
706 parent: 18:1aa437659d19
708 707 user: test
709 708 date: Thu Jan 01 00:00:00 1970 +0000
710 709 summary: merge bar (undo rename)
711 710
712 711 diff --git a/a b/aa
713 712 copy from a
714 713 copy to aa
715 714 diff --git a/cc b/cc
716 715 --- a/cc
717 716 +++ b/cc
718 717 @@ -1,1 +1,5 @@
719 718 +<<<<<<< working copy: 30d96aeaf27b - test: aa
720 719 dd
721 720 +=======
722 721 +cc
723 722 +>>>>>>> merge rev: 1aa437659d19 bar - test: aazzcc
724 723
725 724 $ hg debugrename z
726 725 z not renamed
727 726
728 727 Amend a merge changeset (with renames during the merge):
729 728
730 729 $ hg up -q bar
731 730 $ echo x > x
732 731 $ hg add x
733 732 $ hg ci -m x
734 733 $ hg up -q default
735 734 $ hg merge -q bar
736 735 $ hg mv aa aaa
737 736 $ echo aa >> aaa
738 737 $ hg ci -m 'merge bar again'
739 738 $ hg log --config diff.git=1 -pr .
740 changeset: 28:dffde028b388
739 changeset: 24:dffde028b388
741 740 tag: tip
742 parent: 26:12594a98ca3f
743 parent: 27:4c94d5bc65f5
741 parent: 22:12594a98ca3f
742 parent: 23:4c94d5bc65f5
744 743 user: test
745 744 date: Thu Jan 01 00:00:00 1970 +0000
746 745 summary: merge bar again
747 746
748 747 diff --git a/aa b/aa
749 748 deleted file mode 100644
750 749 --- a/aa
751 750 +++ /dev/null
752 751 @@ -1,2 +0,0 @@
753 752 -a
754 753 -a
755 754 diff --git a/aaa b/aaa
756 755 new file mode 100644
757 756 --- /dev/null
758 757 +++ b/aaa
759 758 @@ -0,0 +1,3 @@
760 759 +a
761 760 +a
762 761 +aa
763 762 diff --git a/x b/x
764 763 new file mode 100644
765 764 --- /dev/null
766 765 +++ b/x
767 766 @@ -0,0 +1,1 @@
768 767 +x
769 768
770 769 $ hg debugrename aaa
771 770 aaa renamed from aa:37d9b5d994eab34eda9c16b195ace52c7b129980
772 771 $ hg mv aaa aa
773 772 $ hg ci --amend -m 'merge bar again (undo rename)'
774 773 $ hg log --config diff.git=1 -pr .
775 changeset: 30:18e3ba160489
774 changeset: 25:18e3ba160489
776 775 tag: tip
777 parent: 26:12594a98ca3f
778 parent: 27:4c94d5bc65f5
776 parent: 22:12594a98ca3f
777 parent: 23:4c94d5bc65f5
779 778 user: test
780 779 date: Thu Jan 01 00:00:00 1970 +0000
781 780 summary: merge bar again (undo rename)
782 781
783 782 diff --git a/aa b/aa
784 783 --- a/aa
785 784 +++ b/aa
786 785 @@ -1,2 +1,3 @@
787 786 a
788 787 a
789 788 +aa
790 789 diff --git a/x b/x
791 790 new file mode 100644
792 791 --- /dev/null
793 792 +++ b/x
794 793 @@ -0,0 +1,1 @@
795 794 +x
796 795
797 796 $ hg debugrename aa
798 797 aa not renamed
799 798 $ hg debugrename -r '.^' aa
800 799 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
801 800
802 801 Amend a merge changeset (with manifest-level conflicts):
803 802
804 803 $ hg up -q bar
805 804 $ hg rm aa
806 805 $ hg ci -m 'rm aa'
807 806 $ hg up -q default
808 807 $ echo aa >> aa
809 808 $ hg ci -m aa
810 809 $ hg merge -q bar --config ui.interactive=True << EOF
811 810 > c
812 811 > EOF
813 812 local [working copy] changed aa which other [merge rev] deleted
814 813 use (c)hanged version, (d)elete, or leave (u)nresolved? c
815 814 $ hg ci -m 'merge bar (with conflicts)'
816 815 $ hg log --config diff.git=1 -pr .
817 changeset: 33:b4c3035e2544
816 changeset: 28:b4c3035e2544
818 817 tag: tip
819 parent: 32:4b216ca5ba97
820 parent: 31:67db8847a540
818 parent: 27:4b216ca5ba97
819 parent: 26:67db8847a540
821 820 user: test
822 821 date: Thu Jan 01 00:00:00 1970 +0000
823 822 summary: merge bar (with conflicts)
824 823
825 824
826 825 $ hg rm aa
827 826 $ hg ci --amend -m 'merge bar (with conflicts, amended)'
828 827 $ hg log --config diff.git=1 -pr .
829 changeset: 35:1205ed810051
828 changeset: 29:1205ed810051
830 829 tag: tip
831 parent: 32:4b216ca5ba97
832 parent: 31:67db8847a540
830 parent: 27:4b216ca5ba97
831 parent: 26:67db8847a540
833 832 user: test
834 833 date: Thu Jan 01 00:00:00 1970 +0000
835 834 summary: merge bar (with conflicts, amended)
836 835
837 836 diff --git a/aa b/aa
838 837 deleted file mode 100644
839 838 --- a/aa
840 839 +++ /dev/null
841 840 @@ -1,4 +0,0 @@
842 841 -a
843 842 -a
844 843 -aa
845 844 -aa
846 845
847 846 Issue 3445: amending with --close-branch a commit that created a new head should fail
848 847 This shouldn't be possible:
849 848
850 849 $ hg up -q default
851 850 $ hg branch closewithamend
852 851 marked working directory as branch closewithamend
853 852 $ echo foo > foo
854 853 $ hg add foo
855 854 $ hg ci -m..
856 855 $ hg ci --amend --close-branch -m 'closing'
857 856 abort: can only close branch heads
858 857 [255]
859 858
860 859 This silliness fails:
861 860
862 861 $ hg branch silliness
863 862 marked working directory as branch silliness
864 863 $ echo b >> b
865 864 $ hg ci --close-branch -m'open and close'
866 865 abort: can only close branch heads
867 866 [255]
868 867
869 868 Test that amend with --secret creates new secret changeset forcibly
870 869 ---------------------------------------------------------------------
871 870
872 871 $ hg phase '.^::.'
873 35: draft
874 36: draft
872 29: draft
873 30: draft
875 874 $ hg commit --amend --secret -m 'amend as secret' -q
876 875 $ hg phase '.^::.'
877 35: draft
878 38: secret
876 29: draft
877 31: secret
879 878
880 879 Test that amend with --edit invokes editor forcibly
881 880 ---------------------------------------------------
882 881
883 882 $ hg parents --template "{desc}\n"
884 883 amend as secret
885 884 $ HGEDITOR=cat hg commit --amend -m "editor should be suppressed"
886 885 $ hg parents --template "{desc}\n"
887 886 editor should be suppressed
888 887
889 888 $ hg status --rev '.^1::.'
890 889 A foo
891 890 $ HGEDITOR=cat hg commit --amend -m "editor should be invoked" --edit
892 891 editor should be invoked
893 892
894 893
895 894 HG: Enter commit message. Lines beginning with 'HG:' are removed.
896 895 HG: Leave message empty to abort commit.
897 896 HG: --
898 897 HG: user: test
899 898 HG: branch 'silliness'
900 899 HG: added foo
901 900 $ hg parents --template "{desc}\n"
902 901 editor should be invoked
903 902
904 903 Test that "diff()" in committemplate works correctly for amending
905 904 -----------------------------------------------------------------
906 905
907 906 $ cat >> .hg/hgrc <<EOF
908 907 > [committemplate]
909 908 > changeset.commit.amend = {desc}\n
910 909 > HG: M: {file_mods}
911 910 > HG: A: {file_adds}
912 911 > HG: R: {file_dels}
913 912 > {splitlines(diff()) % 'HG: {line}\n'}
914 913 > EOF
915 914
916 915 $ hg parents --template "M: {file_mods}\nA: {file_adds}\nR: {file_dels}\n"
917 916 M:
918 917 A: foo
919 918 R:
920 919 $ hg status -amr
921 920 $ HGEDITOR=cat hg commit --amend -e -m "expecting diff of foo"
922 921 expecting diff of foo
923 922
924 923 HG: M:
925 924 HG: A: foo
926 925 HG: R:
927 926 HG: diff -r 1205ed810051 foo
928 927 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
929 928 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
930 929 HG: @@ -0,0 +1,1 @@
931 930 HG: +foo
932 931
933 932 $ echo y > y
934 933 $ hg add y
935 934 $ HGEDITOR=cat hg commit --amend -e -m "expecting diff of foo and y"
936 935 expecting diff of foo and y
937 936
938 937 HG: M:
939 938 HG: A: foo y
940 939 HG: R:
941 940 HG: diff -r 1205ed810051 foo
942 941 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
943 942 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
944 943 HG: @@ -0,0 +1,1 @@
945 944 HG: +foo
946 945 HG: diff -r 1205ed810051 y
947 946 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
948 947 HG: +++ b/y Thu Jan 01 00:00:00 1970 +0000
949 948 HG: @@ -0,0 +1,1 @@
950 949 HG: +y
951 950
952 951 $ hg rm a
953 952 $ HGEDITOR=cat hg commit --amend -e -m "expecting diff of a, foo and y"
954 953 expecting diff of a, foo and y
955 954
956 955 HG: M:
957 956 HG: A: foo y
958 957 HG: R: a
959 958 HG: diff -r 1205ed810051 a
960 959 HG: --- a/a Thu Jan 01 00:00:00 1970 +0000
961 960 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
962 961 HG: @@ -1,2 +0,0 @@
963 962 HG: -a
964 963 HG: -a
965 964 HG: diff -r 1205ed810051 foo
966 965 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
967 966 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
968 967 HG: @@ -0,0 +1,1 @@
969 968 HG: +foo
970 969 HG: diff -r 1205ed810051 y
971 970 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
972 971 HG: +++ b/y Thu Jan 01 00:00:00 1970 +0000
973 972 HG: @@ -0,0 +1,1 @@
974 973 HG: +y
975 974
976 975 $ hg rm x
977 976 $ HGEDITOR=cat hg commit --amend -e -m "expecting diff of a, foo, x and y"
978 977 expecting diff of a, foo, x and y
979 978
980 979 HG: M:
981 980 HG: A: foo y
982 981 HG: R: a x
983 982 HG: diff -r 1205ed810051 a
984 983 HG: --- a/a Thu Jan 01 00:00:00 1970 +0000
985 984 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
986 985 HG: @@ -1,2 +0,0 @@
987 986 HG: -a
988 987 HG: -a
989 988 HG: diff -r 1205ed810051 foo
990 989 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
991 990 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
992 991 HG: @@ -0,0 +1,1 @@
993 992 HG: +foo
994 993 HG: diff -r 1205ed810051 x
995 994 HG: --- a/x Thu Jan 01 00:00:00 1970 +0000
996 995 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
997 996 HG: @@ -1,1 +0,0 @@
998 997 HG: -x
999 998 HG: diff -r 1205ed810051 y
1000 999 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1001 1000 HG: +++ b/y Thu Jan 01 00:00:00 1970 +0000
1002 1001 HG: @@ -0,0 +1,1 @@
1003 1002 HG: +y
1004 1003
1005 1004 $ echo cccc >> cc
1006 1005 $ hg status -amr
1007 1006 M cc
1008 1007 $ HGEDITOR=cat hg commit --amend -e -m "cc should be excluded" -X cc
1009 1008 cc should be excluded
1010 1009
1011 1010 HG: M:
1012 1011 HG: A: foo y
1013 1012 HG: R: a x
1014 1013 HG: diff -r 1205ed810051 a
1015 1014 HG: --- a/a Thu Jan 01 00:00:00 1970 +0000
1016 1015 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1017 1016 HG: @@ -1,2 +0,0 @@
1018 1017 HG: -a
1019 1018 HG: -a
1020 1019 HG: diff -r 1205ed810051 foo
1021 1020 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1022 1021 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
1023 1022 HG: @@ -0,0 +1,1 @@
1024 1023 HG: +foo
1025 1024 HG: diff -r 1205ed810051 x
1026 1025 HG: --- a/x Thu Jan 01 00:00:00 1970 +0000
1027 1026 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1028 1027 HG: @@ -1,1 +0,0 @@
1029 1028 HG: -x
1030 1029 HG: diff -r 1205ed810051 y
1031 1030 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1032 1031 HG: +++ b/y Thu Jan 01 00:00:00 1970 +0000
1033 1032 HG: @@ -0,0 +1,1 @@
1034 1033 HG: +y
1035 1034
1036 1035 Check for issue4405
1037 1036 -------------------
1038 1037
1039 1038 Setup the repo with a file that gets moved in a second commit.
1040 1039 $ hg init repo
1041 1040 $ cd repo
1042 1041 $ touch a0
1043 1042 $ hg add a0
1044 1043 $ hg commit -m a0
1045 1044 $ hg mv a0 a1
1046 1045 $ hg commit -m a1
1047 1046 $ hg up -q 0
1048 1047 $ hg log -G --template '{rev} {desc}'
1049 1048 o 1 a1
1050 1049 |
1051 1050 @ 0 a0
1052 1051
1053 1052
1054 1053 Now we branch the repro, but re-use the file contents, so we have a divergence
1055 1054 in the file revlog topology and the changelog topology.
1056 1055 $ hg revert --rev 1 --all
1057 1056 removing a0
1058 1057 adding a1
1059 1058 $ hg ci -qm 'a1-amend'
1060 1059 $ hg log -G --template '{rev} {desc}'
1061 1060 @ 2 a1-amend
1062 1061 |
1063 1062 | o 1 a1
1064 1063 |/
1065 1064 o 0 a0
1066 1065
1067 1066
1068 The way mercurial does amends is to create a temporary commit (rev 3) and then
1069 fold the new and old commits together into another commit (rev 4). During this
1070 process, _findlimit is called to check how far back to look for the transitive
1071 closure of file copy information, but due to the divergence of the filelog
1072 and changelog graph topologies, before _findlimit was fixed, it returned a rev
1073 which was not far enough back in this case.
1067 The way mercurial does amends is by folding the working copy and old commit
1068 together into another commit (rev 3). During this process, _findlimit is called
1069 to check how far back to look for the transitive closure of file copy
1070 information, but due to the divergence of the filelog and changelog graph
1071 topologies, before _findlimit was fixed, it returned a rev which was not far
1072 enough back in this case.
1074 1073 $ hg mv a1 a2
1075 1074 $ hg status --copies --rev 0
1076 1075 A a2
1077 1076 a0
1078 1077 R a0
1079 1078 $ hg ci --amend -q
1080 1079 $ hg log -G --template '{rev} {desc}'
1081 @ 4 a1-amend
1080 @ 3 a1-amend
1082 1081 |
1083 1082 | o 1 a1
1084 1083 |/
1085 1084 o 0 a0
1086 1085
1087 1086
1088 1087 Before the fix, the copy information was lost.
1089 1088 $ hg status --copies --rev 0
1090 1089 A a2
1091 1090 a0
1092 1091 R a0
1093 1092 $ cd ..
1094 1093
1095 1094 Check that amend properly preserve rename from directory rename (issue-4516)
1096 1095
1097 1096 If a parent of the merge renames a full directory, any files added to the old
1098 1097 directory in the other parent will be renamed to the new directory. For some
1099 1098 reason, the rename metadata was when amending such merge. This test ensure we
1100 1099 do not regress. We have a dedicated repo because it needs a setup with renamed
1101 1100 directory)
1102 1101
1103 1102 $ hg init issue4516
1104 1103 $ cd issue4516
1105 1104 $ mkdir olddirname
1106 1105 $ echo line1 > olddirname/commonfile.py
1107 1106 $ hg add olddirname/commonfile.py
1108 1107 $ hg ci -m first
1109 1108
1110 1109 $ hg branch newdirname
1111 1110 marked working directory as branch newdirname
1112 1111 (branches are permanent and global, did you want a bookmark?)
1113 1112 $ hg mv olddirname newdirname
1114 1113 moving olddirname/commonfile.py to newdirname/commonfile.py (glob)
1115 1114 $ hg ci -m rename
1116 1115
1117 1116 $ hg update default
1118 1117 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1119 1118 $ echo line1 > olddirname/newfile.py
1120 1119 $ hg add olddirname/newfile.py
1121 1120 $ hg ci -m log
1122 1121
1123 1122 $ hg up newdirname
1124 1123 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1125 1124 $ # create newdirname/newfile.py
1126 1125 $ hg merge default
1127 1126 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1128 1127 (branch merge, don't forget to commit)
1129 1128 $ hg ci -m add
1130 1129 $
1131 1130 $ hg debugrename newdirname/newfile.py
1132 1131 newdirname/newfile.py renamed from olddirname/newfile.py:690b295714aed510803d3020da9c70fca8336def (glob)
1133 1132 $ hg status -C --change .
1134 1133 A newdirname/newfile.py
1135 1134 $ hg status -C --rev 1
1136 1135 A newdirname/newfile.py
1137 1136 $ hg status -C --rev 2
1138 1137 A newdirname/commonfile.py
1139 1138 olddirname/commonfile.py
1140 1139 A newdirname/newfile.py
1141 1140 olddirname/newfile.py
1142 1141 R olddirname/commonfile.py
1143 1142 R olddirname/newfile.py
1144 1143 $ hg debugindex newdirname/newfile.py
1145 1144 rev offset length delta linkrev nodeid p1 p2
1146 1145 0 0 89 -1 3 34a4d536c0c0 000000000000 000000000000
1147 1146
1148 1147 $ echo a >> newdirname/commonfile.py
1149 1148 $ hg ci --amend -m bug
1150 1149 $ hg debugrename newdirname/newfile.py
1151 1150 newdirname/newfile.py renamed from olddirname/newfile.py:690b295714aed510803d3020da9c70fca8336def (glob)
1152 1151 $ hg debugindex newdirname/newfile.py
1153 1152 rev offset length delta linkrev nodeid p1 p2
1154 1153 0 0 89 -1 3 34a4d536c0c0 000000000000 000000000000
1155 1154
1156 1155 #if execbit
1157 1156
1158 1157 Test if amend preserves executable bit changes
1159 1158 $ chmod +x newdirname/commonfile.py
1160 1159 $ hg ci -m chmod
1161 1160 $ hg ci --amend -m "chmod amended"
1162 1161 $ hg ci --amend -m "chmod amended second time"
1163 1162 $ hg log -p --git -r .
1164 changeset: 8:b1326f52dddf
1163 changeset: 7:b1326f52dddf
1165 1164 branch: newdirname
1166 1165 tag: tip
1167 parent: 5:7fd235f7cb2f
1166 parent: 4:7fd235f7cb2f
1168 1167 user: test
1169 1168 date: Thu Jan 01 00:00:00 1970 +0000
1170 1169 summary: chmod amended second time
1171 1170
1172 1171 diff --git a/newdirname/commonfile.py b/newdirname/commonfile.py
1173 1172 old mode 100644
1174 1173 new mode 100755
1175 1174
1176 1175 #endif
1177 1176
1178 1177 Test amend with file inclusion options
1179 1178 --------------------------------------
1180 1179
1181 1180 These tests ensure that we are always amending some files that were part of the
1182 1181 pre-amend commit. We want to test that the remaining files in the pre-amend
1183 1182 commit were not changed in the amended commit. We do so by performing a diff of
1184 1183 the amended commit against its parent commit.
1185 1184 $ cd ..
1186 1185 $ hg init testfileinclusions
1187 1186 $ cd testfileinclusions
1188 1187 $ echo a > a
1189 1188 $ echo b > b
1190 1189 $ hg commit -Aqm "Adding a and b"
1191 1190
1192 1191 Only add changes to a particular file
1193 1192 $ echo a >> a
1194 1193 $ echo b >> b
1195 1194 $ hg commit --amend -I a
1196 1195 $ hg diff --git -r null -r .
1197 1196 diff --git a/a b/a
1198 1197 new file mode 100644
1199 1198 --- /dev/null
1200 1199 +++ b/a
1201 1200 @@ -0,0 +1,2 @@
1202 1201 +a
1203 1202 +a
1204 1203 diff --git a/b b/b
1205 1204 new file mode 100644
1206 1205 --- /dev/null
1207 1206 +++ b/b
1208 1207 @@ -0,0 +1,1 @@
1209 1208 +b
1210 1209
1211 1210 $ echo a >> a
1212 1211 $ hg commit --amend b
1213 1212 $ hg diff --git -r null -r .
1214 1213 diff --git a/a b/a
1215 1214 new file mode 100644
1216 1215 --- /dev/null
1217 1216 +++ b/a
1218 1217 @@ -0,0 +1,2 @@
1219 1218 +a
1220 1219 +a
1221 1220 diff --git a/b b/b
1222 1221 new file mode 100644
1223 1222 --- /dev/null
1224 1223 +++ b/b
1225 1224 @@ -0,0 +1,2 @@
1226 1225 +b
1227 1226 +b
1228 1227
1229 1228 Exclude changes to a particular file
1230 1229 $ echo b >> b
1231 1230 $ hg commit --amend -X a
1232 1231 $ hg diff --git -r null -r .
1233 1232 diff --git a/a b/a
1234 1233 new file mode 100644
1235 1234 --- /dev/null
1236 1235 +++ b/a
1237 1236 @@ -0,0 +1,2 @@
1238 1237 +a
1239 1238 +a
1240 1239 diff --git a/b b/b
1241 1240 new file mode 100644
1242 1241 --- /dev/null
1243 1242 +++ b/b
1244 1243 @@ -0,0 +1,3 @@
1245 1244 +b
1246 1245 +b
1247 1246 +b
1248 1247
1249 1248 Check the addremove flag
1250 1249 $ echo c > c
1251 1250 $ rm a
1252 1251 $ hg commit --amend -A
1253 1252 removing a
1254 1253 adding c
1255 1254 $ hg diff --git -r null -r .
1256 1255 diff --git a/b b/b
1257 1256 new file mode 100644
1258 1257 --- /dev/null
1259 1258 +++ b/b
1260 1259 @@ -0,0 +1,3 @@
1261 1260 +b
1262 1261 +b
1263 1262 +b
1264 1263 diff --git a/c b/c
1265 1264 new file mode 100644
1266 1265 --- /dev/null
1267 1266 +++ b/c
1268 1267 @@ -0,0 +1,1 @@
1269 1268 +c
@@ -1,426 +1,426 b''
1 1 #require tic
2 2
3 3 Set up a repo
4 4
5 5 $ cp $HGRCPATH $HGRCPATH.pretest
6 6 $ cat <<EOF >> $HGRCPATH
7 7 > [ui]
8 8 > interactive = true
9 9 > interface = curses
10 10 > [experimental]
11 11 > crecordtest = testModeCommands
12 12 > EOF
13 13
14 14 Record with noeol at eof (issue5268)
15 15 $ hg init noeol
16 16 $ cd noeol
17 17 $ printf '0' > a
18 18 $ printf '0\n' > b
19 19 $ hg ci -Aqm initial
20 20 $ printf '1\n0' > a
21 21 $ printf '1\n0\n' > b
22 22 $ cat <<EOF >testModeCommands
23 23 > c
24 24 > EOF
25 25 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -m "add hunks" -d "0 0"
26 26 $ cd ..
27 27
28 28 Normal repo
29 29 $ hg init a
30 30 $ cd a
31 31
32 32 Committing some changes but stopping on the way
33 33
34 34 $ echo "a" > a
35 35 $ hg add a
36 36 $ cat <<EOF >testModeCommands
37 37 > TOGGLE
38 38 > X
39 39 > EOF
40 40 $ hg commit -i -m "a" -d "0 0"
41 41 no changes to record
42 42 [1]
43 43 $ hg tip
44 44 changeset: -1:000000000000
45 45 tag: tip
46 46 user:
47 47 date: Thu Jan 01 00:00:00 1970 +0000
48 48
49 49
50 50 Committing some changes
51 51
52 52 $ cat <<EOF >testModeCommands
53 53 > X
54 54 > EOF
55 55 $ hg commit -i -m "a" -d "0 0"
56 56 $ hg tip
57 57 changeset: 0:cb9a9f314b8b
58 58 tag: tip
59 59 user: test
60 60 date: Thu Jan 01 00:00:00 1970 +0000
61 61 summary: a
62 62
63 63 Check that commit -i works with no changes
64 64 $ hg commit -i
65 65 no changes to record
66 66 [1]
67 67
68 68 Committing only one file
69 69
70 70 $ echo "a" >> a
71 71 >>> open('b', 'wb').write("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
72 72 $ hg add b
73 73 $ cat <<EOF >testModeCommands
74 74 > TOGGLE
75 75 > KEY_DOWN
76 76 > X
77 77 > EOF
78 78 $ hg commit -i -m "one file" -d "0 0"
79 79 $ hg tip
80 80 changeset: 1:fb2705a663ea
81 81 tag: tip
82 82 user: test
83 83 date: Thu Jan 01 00:00:00 1970 +0000
84 84 summary: one file
85 85
86 86 $ hg cat -r tip a
87 87 a
88 88 $ cat a
89 89 a
90 90 a
91 91
92 92 Committing only one hunk while aborting edition of hunk
93 93
94 94 - Untoggle all the hunks, go down to the second file
95 95 - unfold it
96 96 - go down to second hunk (1 for the first hunk, 1 for the first hunkline, 1 for the second hunk, 1 for the second hunklike)
97 97 - toggle the second hunk
98 98 - toggle on and off the amend mode (to check that it toggles off)
99 99 - edit the hunk and quit the editor immediately with non-zero status
100 100 - commit
101 101
102 102 $ printf "printf 'editor ran\n'; exit 1" > editor.sh
103 103 $ echo "x" > c
104 104 $ cat b >> c
105 105 $ echo "y" >> c
106 106 $ mv c b
107 107 $ cat <<EOF >testModeCommands
108 108 > A
109 109 > KEY_DOWN
110 110 > f
111 111 > KEY_DOWN
112 112 > KEY_DOWN
113 113 > KEY_DOWN
114 114 > KEY_DOWN
115 115 > TOGGLE
116 116 > a
117 117 > a
118 118 > e
119 119 > X
120 120 > EOF
121 121 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -m "one hunk" -d "0 0"
122 122 editor ran
123 123 $ rm editor.sh
124 124 $ hg tip
125 125 changeset: 2:7d10dfe755a8
126 126 tag: tip
127 127 user: test
128 128 date: Thu Jan 01 00:00:00 1970 +0000
129 129 summary: one hunk
130 130
131 131 $ hg cat -r tip b
132 132 1
133 133 2
134 134 3
135 135 4
136 136 5
137 137 6
138 138 7
139 139 8
140 140 9
141 141 10
142 142 y
143 143 $ cat b
144 144 x
145 145 1
146 146 2
147 147 3
148 148 4
149 149 5
150 150 6
151 151 7
152 152 8
153 153 9
154 154 10
155 155 y
156 156 $ hg commit -m "other hunks"
157 157 $ hg tip
158 158 changeset: 3:a6735021574d
159 159 tag: tip
160 160 user: test
161 161 date: Thu Jan 01 00:00:00 1970 +0000
162 162 summary: other hunks
163 163
164 164 $ hg cat -r tip b
165 165 x
166 166 1
167 167 2
168 168 3
169 169 4
170 170 5
171 171 6
172 172 7
173 173 8
174 174 9
175 175 10
176 176 y
177 177
178 178 Newly added files can be selected with the curses interface
179 179
180 180 $ hg update -C .
181 181 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
182 182 $ echo "hello" > x
183 183 $ hg add x
184 184 $ cat <<EOF >testModeCommands
185 185 > TOGGLE
186 186 > TOGGLE
187 187 > X
188 188 > EOF
189 189 $ hg st
190 190 A x
191 191 ? testModeCommands
192 192 $ hg commit -i -m "newly added file" -d "0 0"
193 193 $ hg st
194 194 ? testModeCommands
195 195
196 196 Amend option works
197 197 $ echo "hello world" > x
198 198 $ hg diff -c .
199 199 diff -r a6735021574d -r 2b0e9be4d336 x
200 200 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
201 201 +++ b/x Thu Jan 01 00:00:00 1970 +0000
202 202 @@ -0,0 +1,1 @@
203 203 +hello
204 204 $ cat <<EOF >testModeCommands
205 205 > a
206 206 > X
207 207 > EOF
208 208 $ hg commit -i -m "newly added file" -d "0 0"
209 saved backup bundle to $TESTTMP/a/.hg/strip-backup/2b0e9be4d336-28bbe4e2-amend.hg (glob)
209 saved backup bundle to $TESTTMP/a/.hg/strip-backup/2b0e9be4d336-3cf0bc8c-amend.hg (glob)
210 210 $ hg diff -c .
211 211 diff -r a6735021574d -r c1d239d165ae x
212 212 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
213 213 +++ b/x Thu Jan 01 00:00:00 1970 +0000
214 214 @@ -0,0 +1,1 @@
215 215 +hello world
216 216
217 217 Editing a hunk puts you back on that hunk when done editing (issue5041)
218 218 To do that, we change two lines in a file, pretend to edit the second line,
219 219 exit, toggle the line selected at the end of the edit and commit.
220 220 The first line should be recorded if we were put on the second line at the end
221 221 of the edit.
222 222
223 223 $ hg update -C .
224 224 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
225 225 $ echo "foo" > x
226 226 $ echo "hello world" >> x
227 227 $ echo "bar" >> x
228 228 $ cat <<EOF >testModeCommands
229 229 > f
230 230 > KEY_DOWN
231 231 > KEY_DOWN
232 232 > KEY_DOWN
233 233 > KEY_DOWN
234 234 > e
235 235 > TOGGLE
236 236 > X
237 237 > EOF
238 238 $ printf "printf 'editor ran\n'; exit 0" > editor.sh
239 239 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -m "edit hunk" -d "0 0"
240 240 editor ran
241 241 $ hg cat -r . x
242 242 foo
243 243 hello world
244 244
245 245 Testing the review option. The entire final filtered patch should show
246 246 up in the editor and be editable. We will unselect the second file and
247 247 the first hunk of the third file. During review, we will decide that
248 248 "lower" sounds better than "bottom", and the final commit should
249 249 reflect this edition.
250 250
251 251 $ hg update -C .
252 252 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
253 253 $ echo "top" > c
254 254 $ cat x >> c
255 255 $ echo "bottom" >> c
256 256 $ mv c x
257 257 $ echo "third a" >> a
258 258 $ echo "we will unselect this" >> b
259 259
260 260 $ cat > editor.sh <<EOF
261 261 > cat "\$1"
262 262 > cat "\$1" | sed s/bottom/lower/ > tmp
263 263 > mv tmp "\$1"
264 264 > EOF
265 265 $ cat > testModeCommands <<EOF
266 266 > KEY_DOWN
267 267 > TOGGLE
268 268 > KEY_DOWN
269 269 > f
270 270 > KEY_DOWN
271 271 > TOGGLE
272 272 > R
273 273 > EOF
274 274
275 275 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -m "review hunks" -d "0 0"
276 276 # To remove '-' lines, make them ' ' lines (context).
277 277 # To remove '+' lines, delete them.
278 278 # Lines starting with # will be removed from the patch.
279 279 #
280 280 # If the patch applies cleanly, the edited patch will immediately
281 281 # be finalised. If it does not apply cleanly, rejects files will be
282 282 # generated. You can use those when you try again.
283 283 diff --git a/a b/a
284 284 --- a/a
285 285 +++ b/a
286 286 @@ -1,2 +1,3 @@
287 287 a
288 288 a
289 289 +third a
290 290 diff --git a/x b/x
291 291 --- a/x
292 292 +++ b/x
293 293 @@ -1,2 +1,3 @@
294 294 foo
295 295 hello world
296 296 +bottom
297 297
298 298 $ hg cat -r . a
299 299 a
300 300 a
301 301 third a
302 302
303 303 $ hg cat -r . b
304 304 x
305 305 1
306 306 2
307 307 3
308 308 4
309 309 5
310 310 6
311 311 7
312 312 8
313 313 9
314 314 10
315 315 y
316 316
317 317 $ hg cat -r . x
318 318 foo
319 319 hello world
320 320 lower
321 321
322 322 Check spacemovesdown
323 323
324 324 $ cat <<EOF >> $HGRCPATH
325 325 > [experimental]
326 326 > spacemovesdown = true
327 327 > EOF
328 328 $ cat <<EOF >testModeCommands
329 329 > TOGGLE
330 330 > TOGGLE
331 331 > X
332 332 > EOF
333 333 $ hg status -q
334 334 M b
335 335 M x
336 336 $ hg commit -i -m "nothing to commit?" -d "0 0"
337 337 no changes to record
338 338 [1]
339 339
340 340 Check ui.interface logic for the chunkselector
341 341
342 342 The default interface is text
343 343 $ cp $HGRCPATH.pretest $HGRCPATH
344 344 $ chunkselectorinterface() {
345 345 > $PYTHON <<EOF
346 346 > from mercurial import hg, ui;\
347 347 > repo = hg.repository(ui.ui.load(), ".");\
348 348 > print(repo.ui.interface("chunkselector"))
349 349 > EOF
350 350 > }
351 351 $ chunkselectorinterface
352 352 text
353 353
354 354 If only the default is set, we'll use that for the feature, too
355 355 $ cp $HGRCPATH.pretest $HGRCPATH
356 356 $ cat <<EOF >> $HGRCPATH
357 357 > [ui]
358 358 > interface = curses
359 359 > EOF
360 360 $ chunkselectorinterface
361 361 curses
362 362
363 363 It is possible to override the default interface with a feature specific
364 364 interface
365 365 $ cp $HGRCPATH.pretest $HGRCPATH
366 366 $ cat <<EOF >> $HGRCPATH
367 367 > [ui]
368 368 > interface = text
369 369 > interface.chunkselector = curses
370 370 > EOF
371 371
372 372 $ chunkselectorinterface
373 373 curses
374 374
375 375 $ cp $HGRCPATH.pretest $HGRCPATH
376 376 $ cat <<EOF >> $HGRCPATH
377 377 > [ui]
378 378 > interface = curses
379 379 > interface.chunkselector = text
380 380 > EOF
381 381
382 382 $ chunkselectorinterface
383 383 text
384 384
385 385 If a bad interface name is given, we use the default value (with a nice
386 386 error message to suggest that the configuration needs to be fixed)
387 387
388 388 $ cp $HGRCPATH.pretest $HGRCPATH
389 389 $ cat <<EOF >> $HGRCPATH
390 390 > [ui]
391 391 > interface = blah
392 392 > EOF
393 393 $ chunkselectorinterface
394 394 invalid value for ui.interface: blah (using text)
395 395 text
396 396
397 397 $ cp $HGRCPATH.pretest $HGRCPATH
398 398 $ cat <<EOF >> $HGRCPATH
399 399 > [ui]
400 400 > interface = curses
401 401 > interface.chunkselector = blah
402 402 > EOF
403 403 $ chunkselectorinterface
404 404 invalid value for ui.interface.chunkselector: blah (using curses)
405 405 curses
406 406
407 407 $ cp $HGRCPATH.pretest $HGRCPATH
408 408 $ cat <<EOF >> $HGRCPATH
409 409 > [ui]
410 410 > interface = blah
411 411 > interface.chunkselector = curses
412 412 > EOF
413 413 $ chunkselectorinterface
414 414 invalid value for ui.interface: blah
415 415 curses
416 416
417 417 $ cp $HGRCPATH.pretest $HGRCPATH
418 418 $ cat <<EOF >> $HGRCPATH
419 419 > [ui]
420 420 > interface = blah
421 421 > interface.chunkselector = blah
422 422 > EOF
423 423 $ chunkselectorinterface
424 424 invalid value for ui.interface: blah
425 425 invalid value for ui.interface.chunkselector: blah (using text)
426 426 text
@@ -1,578 +1,576 b''
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 Enable obsolete
4 4
5 5 $ cat >> $HGRCPATH << EOF
6 6 > [ui]
7 7 > logtemplate= {rev}:{node|short} {desc|firstline}
8 8 > [phases]
9 9 > publish=False
10 10 > [experimental]
11 11 > stabilization=createmarkers,allowunstable
12 12 > [extensions]
13 13 > histedit=
14 14 > rebase=
15 15 > EOF
16 16
17 17 Test that histedit learns about obsolescence not stored in histedit state
18 18 $ hg init boo
19 19 $ cd boo
20 20 $ echo a > a
21 21 $ hg ci -Am a
22 22 adding a
23 23 $ echo a > b
24 24 $ echo a > c
25 25 $ echo a > c
26 26 $ hg ci -Am b
27 27 adding b
28 28 adding c
29 29 $ echo a > d
30 30 $ hg ci -Am c
31 31 adding d
32 32 $ echo "pick `hg log -r 0 -T '{node|short}'`" > plan
33 33 $ echo "pick `hg log -r 2 -T '{node|short}'`" >> plan
34 34 $ echo "edit `hg log -r 1 -T '{node|short}'`" >> plan
35 35 $ hg histedit -r 'all()' --commands plan
36 36 Editing (1b2d564fad96), you may commit or record as needed now.
37 37 (hg histedit --continue to resume)
38 38 [1]
39 39 $ hg st
40 40 A b
41 41 A c
42 42 ? plan
43 43 $ hg commit --amend b
44 44 $ hg histedit --continue
45 45 $ hg log -G
46 @ 6:46abc7c4d873 b
46 @ 5:46abc7c4d873 b
47 47 |
48 o 5:49d44ab2be1b c
48 o 4:49d44ab2be1b c
49 49 |
50 50 o 0:cb9a9f314b8b a
51 51
52 52 $ hg debugobsolete
53 53 e72d22b19f8ecf4150ab4f91d0973fd9955d3ddf 49d44ab2be1b67a79127568a67c9c99430633b48 0 (*) {'user': 'test'} (glob)
54 3e30a45cf2f719e96ab3922dfe039cfd047956ce 0 {e72d22b19f8ecf4150ab4f91d0973fd9955d3ddf} (*) {'user': 'test'} (glob)
55 54 1b2d564fad96311b45362f17c2aa855150efb35f 46abc7c4d8738e8563e577f7889e1b6db3da4199 0 (*) {'user': 'test'} (glob)
56 55 114f4176969ef342759a8a57e6bccefc4234829b 49d44ab2be1b67a79127568a67c9c99430633b48 0 (*) {'user': 'test'} (glob)
57 56
58 57 With some node gone missing during the edit.
59 58
60 59 $ echo "pick `hg log -r 0 -T '{node|short}'`" > plan
61 $ echo "pick `hg log -r 6 -T '{node|short}'`" >> plan
62 $ echo "edit `hg log -r 5 -T '{node|short}'`" >> plan
60 $ echo "pick `hg log -r 5 -T '{node|short}'`" >> plan
61 $ echo "edit `hg log -r 4 -T '{node|short}'`" >> plan
63 62 $ hg histedit -r 'all()' --commands plan
64 63 Editing (49d44ab2be1b), you may commit or record as needed now.
65 64 (hg histedit --continue to resume)
66 65 [1]
67 66 $ hg st
68 67 A b
69 68 A d
70 69 ? plan
71 70 $ hg commit --amend -X . -m XXXXXX
72 71 $ hg commit --amend -X . -m b2
73 72 $ hg --hidden --config extensions.strip= strip 'desc(XXXXXX)' --no-backup
74 73 $ hg histedit --continue
75 74 $ hg log -G
76 @ 9:273c1f3b8626 c
75 @ 8:273c1f3b8626 c
77 76 |
78 o 8:aba7da937030 b2
77 o 7:aba7da937030 b2
79 78 |
80 79 o 0:cb9a9f314b8b a
81 80
82 81 $ hg debugobsolete
83 82 e72d22b19f8ecf4150ab4f91d0973fd9955d3ddf 49d44ab2be1b67a79127568a67c9c99430633b48 0 (*) {'user': 'test'} (glob)
84 3e30a45cf2f719e96ab3922dfe039cfd047956ce 0 {e72d22b19f8ecf4150ab4f91d0973fd9955d3ddf} (*) {'user': 'test'} (glob)
85 83 1b2d564fad96311b45362f17c2aa855150efb35f 46abc7c4d8738e8563e577f7889e1b6db3da4199 0 (*) {'user': 'test'} (glob)
86 84 114f4176969ef342759a8a57e6bccefc4234829b 49d44ab2be1b67a79127568a67c9c99430633b48 0 (*) {'user': 'test'} (glob)
87 85 76f72745eac0643d16530e56e2f86e36e40631f1 2ca853e48edbd6453a0674dc0fe28a0974c51b9c 0 (*) {'user': 'test'} (glob)
88 86 2ca853e48edbd6453a0674dc0fe28a0974c51b9c aba7da93703075eec9fb1dbaf143ff2bc1c49d46 0 (*) {'user': 'test'} (glob)
89 87 49d44ab2be1b67a79127568a67c9c99430633b48 273c1f3b86267ed3ec684bb13af1fa4d6ba56e02 0 (*) {'user': 'test'} (glob)
90 88 46abc7c4d8738e8563e577f7889e1b6db3da4199 aba7da93703075eec9fb1dbaf143ff2bc1c49d46 0 (*) {'user': 'test'} (glob)
91 89 $ cd ..
92 90
93 91 Base setup for the rest of the testing
94 92 ======================================
95 93
96 94 $ hg init base
97 95 $ cd base
98 96
99 97 $ for x in a b c d e f ; do
100 98 > echo $x > $x
101 99 > hg add $x
102 100 > hg ci -m $x
103 101 > done
104 102
105 103 $ hg log --graph
106 104 @ 5:652413bf663e f
107 105 |
108 106 o 4:e860deea161a e
109 107 |
110 108 o 3:055a42cdd887 d
111 109 |
112 110 o 2:177f92b77385 c
113 111 |
114 112 o 1:d2ae7f538514 b
115 113 |
116 114 o 0:cb9a9f314b8b a
117 115
118 116
119 117 $ HGEDITOR=cat hg histedit 1
120 118 pick d2ae7f538514 1 b
121 119 pick 177f92b77385 2 c
122 120 pick 055a42cdd887 3 d
123 121 pick e860deea161a 4 e
124 122 pick 652413bf663e 5 f
125 123
126 124 # Edit history between d2ae7f538514 and 652413bf663e
127 125 #
128 126 # Commits are listed from least to most recent
129 127 #
130 128 # You can reorder changesets by reordering the lines
131 129 #
132 130 # Commands:
133 131 #
134 132 # e, edit = use commit, but stop for amending
135 133 # m, mess = edit commit message without changing commit content
136 134 # p, pick = use commit
137 135 # d, drop = remove commit from history
138 136 # f, fold = use commit, but combine it with the one above
139 137 # r, roll = like fold, but discard this commit's description and date
140 138 #
141 139 $ hg histedit 1 --commands - --verbose <<EOF | grep histedit
142 140 > pick 177f92b77385 2 c
143 141 > drop d2ae7f538514 1 b
144 142 > pick 055a42cdd887 3 d
145 143 > fold e860deea161a 4 e
146 144 > pick 652413bf663e 5 f
147 145 > EOF
148 146 [1]
149 147 $ hg log --graph --hidden
150 148 @ 10:cacdfd884a93 f
151 149 |
152 150 o 9:59d9f330561f d
153 151 |
154 152 | x 8:b558abc46d09 fold-temp-revision e860deea161a
155 153 | |
156 154 | x 7:96e494a2d553 d
157 155 |/
158 156 o 6:b346ab9a313d c
159 157 |
160 158 | x 5:652413bf663e f
161 159 | |
162 160 | x 4:e860deea161a e
163 161 | |
164 162 | x 3:055a42cdd887 d
165 163 | |
166 164 | x 2:177f92b77385 c
167 165 | |
168 166 | x 1:d2ae7f538514 b
169 167 |/
170 168 o 0:cb9a9f314b8b a
171 169
172 170 $ hg debugobsolete
173 171 d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b} (*) {'user': 'test'} (glob)
174 172 177f92b773850b59254aa5e923436f921b55483b b346ab9a313db8537ecf96fca3ca3ca984ef3bd7 0 (*) {'user': 'test'} (glob)
175 173 055a42cdd88768532f9cf79daa407fc8d138de9b 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 (*) {'user': 'test'} (glob)
176 174 e860deea161a2f77de56603b340ebbb4536308ae 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 (*) {'user': 'test'} (glob)
177 175 652413bf663ef2a641cab26574e46d5f5a64a55a cacdfd884a9321ec4e1de275ef3949fa953a1f83 0 (*) {'user': 'test'} (glob)
178 176 96e494a2d553dd05902ba1cee1d94d4cb7b8faed 0 {b346ab9a313db8537ecf96fca3ca3ca984ef3bd7} (*) {'user': 'test'} (glob)
179 177 b558abc46d09c30f57ac31e85a8a3d64d2e906e4 0 {96e494a2d553dd05902ba1cee1d94d4cb7b8faed} (*) {'user': 'test'} (glob)
180 178
181 179
182 180 Ensure hidden revision does not prevent histedit
183 181 -------------------------------------------------
184 182
185 183 create an hidden revision
186 184
187 185 $ hg histedit 6 --commands - << EOF
188 186 > pick b346ab9a313d 6 c
189 187 > drop 59d9f330561f 7 d
190 188 > pick cacdfd884a93 8 f
191 189 > EOF
192 190 $ hg log --graph
193 191 @ 11:c13eb81022ca f
194 192 |
195 193 o 6:b346ab9a313d c
196 194 |
197 195 o 0:cb9a9f314b8b a
198 196
199 197 check hidden revision are ignored (6 have hidden children 7 and 8)
200 198
201 199 $ hg histedit 6 --commands - << EOF
202 200 > pick b346ab9a313d 6 c
203 201 > pick c13eb81022ca 8 f
204 202 > EOF
205 203
206 204
207 205
208 206 Test that rewriting leaving instability behind is allowed
209 207 ---------------------------------------------------------------------
210 208
211 209 $ hg up '.^'
212 210 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
213 211 $ hg log -r 'children(.)'
214 212 11:c13eb81022ca f (no-eol)
215 213 $ hg histedit -r '.' --commands - <<EOF
216 214 > edit b346ab9a313d 6 c
217 215 > EOF
218 216 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
219 217 adding c
220 218 Editing (b346ab9a313d), you may commit or record as needed now.
221 219 (hg histedit --continue to resume)
222 220 [1]
223 221 $ echo c >> c
224 222 $ hg histedit --continue
225 223
226 224 $ hg log -r 'orphan()'
227 225 11:c13eb81022ca f (no-eol)
228 226
229 227 stabilise
230 228
231 229 $ hg rebase -r 'orphan()' -d .
232 230 rebasing 11:c13eb81022ca "f"
233 231 $ hg up tip -q
234 232
235 233 Test dropping of changeset on the top of the stack
236 234 -------------------------------------------------------
237 235
238 236 Nothing is rewritten below, the working directory parent must be change for the
239 237 dropped changeset to be hidden.
240 238
241 239 $ cd ..
242 240 $ hg clone base droplast
243 241 updating to branch default
244 242 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
245 243 $ cd droplast
246 244 $ hg histedit -r '40db8afa467b' --commands - << EOF
247 245 > pick 40db8afa467b 10 c
248 246 > drop b449568bf7fc 11 f
249 247 > EOF
250 248 $ hg log -G
251 249 @ 12:40db8afa467b c
252 250 |
253 251 o 0:cb9a9f314b8b a
254 252
255 253
256 254 With rewritten ancestors
257 255
258 256 $ echo e > e
259 257 $ hg add e
260 258 $ hg commit -m g
261 259 $ echo f > f
262 260 $ hg add f
263 261 $ hg commit -m h
264 262 $ hg histedit -r '40db8afa467b' --commands - << EOF
265 263 > pick 47a8561c0449 12 g
266 264 > pick 40db8afa467b 10 c
267 265 > drop 1b3b05f35ff0 13 h
268 266 > EOF
269 267 $ hg log -G
270 268 @ 17:ee6544123ab8 c
271 269 |
272 270 o 16:269e713e9eae g
273 271 |
274 272 o 0:cb9a9f314b8b a
275 273
276 274 $ cd ../base
277 275
278 276
279 277
280 278 Test phases support
281 279 ===========================================
282 280
283 281 Check that histedit respect immutability
284 282 -------------------------------------------
285 283
286 284 $ cat >> $HGRCPATH << EOF
287 285 > [ui]
288 286 > logtemplate= {rev}:{node|short} ({phase}) {desc|firstline}\n
289 287 > EOF
290 288
291 289 $ hg ph -pv '.^'
292 290 phase changed for 2 changesets
293 291 $ hg log -G
294 292 @ 13:b449568bf7fc (draft) f
295 293 |
296 294 o 12:40db8afa467b (public) c
297 295 |
298 296 o 0:cb9a9f314b8b (public) a
299 297
300 298 $ hg histedit -r '.~2'
301 299 abort: cannot edit public changeset: cb9a9f314b8b
302 300 (see 'hg help phases' for details)
303 301 [255]
304 302
305 303
306 304 Prepare further testing
307 305 -------------------------------------------
308 306
309 307 $ for x in g h i j k ; do
310 308 > echo $x > $x
311 309 > hg add $x
312 310 > hg ci -m $x
313 311 > done
314 312 $ hg phase --force --secret .~2
315 313 $ hg log -G
316 314 @ 18:ee118ab9fa44 (secret) k
317 315 |
318 316 o 17:3a6c53ee7f3d (secret) j
319 317 |
320 318 o 16:b605fb7503f2 (secret) i
321 319 |
322 320 o 15:7395e1ff83bd (draft) h
323 321 |
324 322 o 14:6b70183d2492 (draft) g
325 323 |
326 324 o 13:b449568bf7fc (draft) f
327 325 |
328 326 o 12:40db8afa467b (public) c
329 327 |
330 328 o 0:cb9a9f314b8b (public) a
331 329
332 330 $ cd ..
333 331
334 332 simple phase conservation
335 333 -------------------------------------------
336 334
337 335 Resulting changeset should conserve the phase of the original one whatever the
338 336 phases.new-commit option is.
339 337
340 338 New-commit as draft (default)
341 339
342 340 $ cp -R base simple-draft
343 341 $ cd simple-draft
344 342 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
345 343 > edit b449568bf7fc 11 f
346 344 > pick 6b70183d2492 12 g
347 345 > pick 7395e1ff83bd 13 h
348 346 > pick b605fb7503f2 14 i
349 347 > pick 3a6c53ee7f3d 15 j
350 348 > pick ee118ab9fa44 16 k
351 349 > EOF
352 350 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
353 351 adding f
354 352 Editing (b449568bf7fc), you may commit or record as needed now.
355 353 (hg histedit --continue to resume)
356 354 [1]
357 355 $ echo f >> f
358 356 $ hg histedit --continue
359 357 $ hg log -G
360 358 @ 24:12e89af74238 (secret) k
361 359 |
362 360 o 23:636a8687b22e (secret) j
363 361 |
364 362 o 22:ccaf0a38653f (secret) i
365 363 |
366 364 o 21:11a89d1c2613 (draft) h
367 365 |
368 366 o 20:c1dec7ca82ea (draft) g
369 367 |
370 368 o 19:087281e68428 (draft) f
371 369 |
372 370 o 12:40db8afa467b (public) c
373 371 |
374 372 o 0:cb9a9f314b8b (public) a
375 373
376 374 $ cd ..
377 375
378 376
379 377 New-commit as secret (config)
380 378
381 379 $ cp -R base simple-secret
382 380 $ cd simple-secret
383 381 $ cat >> .hg/hgrc << EOF
384 382 > [phases]
385 383 > new-commit=secret
386 384 > EOF
387 385 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
388 386 > edit b449568bf7fc 11 f
389 387 > pick 6b70183d2492 12 g
390 388 > pick 7395e1ff83bd 13 h
391 389 > pick b605fb7503f2 14 i
392 390 > pick 3a6c53ee7f3d 15 j
393 391 > pick ee118ab9fa44 16 k
394 392 > EOF
395 393 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
396 394 adding f
397 395 Editing (b449568bf7fc), you may commit or record as needed now.
398 396 (hg histedit --continue to resume)
399 397 [1]
400 398 $ echo f >> f
401 399 $ hg histedit --continue
402 400 $ hg log -G
403 401 @ 24:12e89af74238 (secret) k
404 402 |
405 403 o 23:636a8687b22e (secret) j
406 404 |
407 405 o 22:ccaf0a38653f (secret) i
408 406 |
409 407 o 21:11a89d1c2613 (draft) h
410 408 |
411 409 o 20:c1dec7ca82ea (draft) g
412 410 |
413 411 o 19:087281e68428 (draft) f
414 412 |
415 413 o 12:40db8afa467b (public) c
416 414 |
417 415 o 0:cb9a9f314b8b (public) a
418 416
419 417 $ cd ..
420 418
421 419
422 420 Changeset reordering
423 421 -------------------------------------------
424 422
425 423 If a secret changeset is put before a draft one, all descendant should be secret.
426 424 It seems more important to present the secret phase.
427 425
428 426 $ cp -R base reorder
429 427 $ cd reorder
430 428 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
431 429 > pick b449568bf7fc 11 f
432 430 > pick 3a6c53ee7f3d 15 j
433 431 > pick 6b70183d2492 12 g
434 432 > pick b605fb7503f2 14 i
435 433 > pick 7395e1ff83bd 13 h
436 434 > pick ee118ab9fa44 16 k
437 435 > EOF
438 436 $ hg log -G
439 437 @ 23:558246857888 (secret) k
440 438 |
441 439 o 22:28bd44768535 (secret) h
442 440 |
443 441 o 21:d5395202aeb9 (secret) i
444 442 |
445 443 o 20:21edda8e341b (secret) g
446 444 |
447 445 o 19:5ab64f3a4832 (secret) j
448 446 |
449 447 o 13:b449568bf7fc (draft) f
450 448 |
451 449 o 12:40db8afa467b (public) c
452 450 |
453 451 o 0:cb9a9f314b8b (public) a
454 452
455 453 $ cd ..
456 454
457 455 Changeset folding
458 456 -------------------------------------------
459 457
460 458 Folding a secret changeset with a draft one turn the result secret (again,
461 459 better safe than sorry). Folding between same phase changeset still works
462 460
463 461 Note that there is a few reordering in this series for more extensive test
464 462
465 463 $ cp -R base folding
466 464 $ cd folding
467 465 $ cat >> .hg/hgrc << EOF
468 466 > [phases]
469 467 > new-commit=secret
470 468 > EOF
471 469 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
472 470 > pick 7395e1ff83bd 13 h
473 471 > fold b449568bf7fc 11 f
474 472 > pick 6b70183d2492 12 g
475 473 > fold 3a6c53ee7f3d 15 j
476 474 > pick b605fb7503f2 14 i
477 475 > fold ee118ab9fa44 16 k
478 476 > EOF
479 477 $ hg log -G
480 478 @ 27:f9daec13fb98 (secret) i
481 479 |
482 480 o 24:49807617f46a (secret) g
483 481 |
484 482 o 21:050280826e04 (draft) h
485 483 |
486 484 o 12:40db8afa467b (public) c
487 485 |
488 486 o 0:cb9a9f314b8b (public) a
489 487
490 488 $ hg co 49807617f46a
491 489 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
492 490 $ echo wat >> wat
493 491 $ hg add wat
494 492 $ hg ci -m 'add wat'
495 493 created new head
496 494 $ hg merge f9daec13fb98
497 495 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
498 496 (branch merge, don't forget to commit)
499 497 $ hg ci -m 'merge'
500 498 $ echo not wat > wat
501 499 $ hg ci -m 'modify wat'
502 500 $ hg histedit 050280826e04
503 501 abort: cannot edit history that contains merges
504 502 [255]
505 503 $ cd ..
506 504
507 505 Check abort behavior
508 506 -------------------------------------------
509 507
510 508 We checks that abort properly clean the repository so the same histedit can be
511 509 attempted later.
512 510
513 511 $ cp -R base abort
514 512 $ cd abort
515 513 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
516 514 > pick b449568bf7fc 13 f
517 515 > pick 7395e1ff83bd 15 h
518 516 > pick 6b70183d2492 14 g
519 517 > pick b605fb7503f2 16 i
520 518 > roll 3a6c53ee7f3d 17 j
521 519 > edit ee118ab9fa44 18 k
522 520 > EOF
523 521 Editing (ee118ab9fa44), you may commit or record as needed now.
524 522 (hg histedit --continue to resume)
525 523 [1]
526 524
527 525 $ hg histedit --abort
528 526 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
529 527 saved backup bundle to $TESTTMP/abort/.hg/strip-backup/4dc06258baa6-dff4ef05-backup.hg (glob)
530 528
531 529 $ hg log -G
532 530 @ 18:ee118ab9fa44 (secret) k
533 531 |
534 532 o 17:3a6c53ee7f3d (secret) j
535 533 |
536 534 o 16:b605fb7503f2 (secret) i
537 535 |
538 536 o 15:7395e1ff83bd (draft) h
539 537 |
540 538 o 14:6b70183d2492 (draft) g
541 539 |
542 540 o 13:b449568bf7fc (draft) f
543 541 |
544 542 o 12:40db8afa467b (public) c
545 543 |
546 544 o 0:cb9a9f314b8b (public) a
547 545
548 546 $ hg histedit -r 'b449568bf7fc' --commands - << EOF --config experimental.stabilization.track-operation=1
549 547 > pick b449568bf7fc 13 f
550 548 > pick 7395e1ff83bd 15 h
551 549 > pick 6b70183d2492 14 g
552 550 > pick b605fb7503f2 16 i
553 551 > pick 3a6c53ee7f3d 17 j
554 552 > edit ee118ab9fa44 18 k
555 553 > EOF
556 554 Editing (ee118ab9fa44), you may commit or record as needed now.
557 555 (hg histedit --continue to resume)
558 556 [1]
559 557 $ hg histedit --continue --config experimental.stabilization.track-operation=1
560 558 $ hg log -G
561 559 @ 23:175d6b286a22 (secret) k
562 560 |
563 561 o 22:44ca09d59ae4 (secret) j
564 562 |
565 563 o 21:31747692a644 (secret) i
566 564 |
567 565 o 20:9985cd4f21fa (draft) g
568 566 |
569 567 o 19:4dc06258baa6 (draft) h
570 568 |
571 569 o 13:b449568bf7fc (draft) f
572 570 |
573 571 o 12:40db8afa467b (public) c
574 572 |
575 573 o 0:cb9a9f314b8b (public) a
576 574
577 575 $ hg debugobsolete --rev .
578 576 ee118ab9fa44ebb86be85996548b5517a39e5093 175d6b286a224c23f192e79a581ce83131a53fa2 0 (*) {'operation': 'histedit', 'user': 'test'} (glob)
@@ -1,2393 +1,2393 b''
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 --debug log a -T '{rev}: {desc}\n' --config extensions.largefiles=
50 50 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
51 51 updated patterns: .hglf/a, a
52 52 0: a
53 53 $ hg log a
54 54 changeset: 0:9161b9aeaf16
55 55 user: test
56 56 date: Thu Jan 01 00:00:01 1970 +0000
57 57 summary: a
58 58
59 59 $ hg log glob:a*
60 60 changeset: 3:2ca5ba701980
61 61 user: test
62 62 date: Thu Jan 01 00:00:04 1970 +0000
63 63 summary: d
64 64
65 65 changeset: 0:9161b9aeaf16
66 66 user: test
67 67 date: Thu Jan 01 00:00:01 1970 +0000
68 68 summary: a
69 69
70 70 $ hg --debug log glob:a* -T '{rev}: {desc}\n' --config extensions.largefiles=
71 71 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
72 72 updated patterns: glob:.hglf/a*, glob:a*
73 73 3: d
74 74 0: a
75 75
76 76 log on directory
77 77
78 78 $ hg log dir
79 79 changeset: 4:7e4639b4691b
80 80 tag: tip
81 81 user: test
82 82 date: Thu Jan 01 00:00:05 1970 +0000
83 83 summary: e
84 84
85 85 changeset: 2:f8954cd4dc1f
86 86 user: test
87 87 date: Thu Jan 01 00:00:03 1970 +0000
88 88 summary: c
89 89
90 90 $ hg log somethingthatdoesntexist dir
91 91 changeset: 4:7e4639b4691b
92 92 tag: tip
93 93 user: test
94 94 date: Thu Jan 01 00:00:05 1970 +0000
95 95 summary: e
96 96
97 97 changeset: 2:f8954cd4dc1f
98 98 user: test
99 99 date: Thu Jan 01 00:00:03 1970 +0000
100 100 summary: c
101 101
102 102
103 103 -f, non-existent directory
104 104
105 105 $ hg log -f dir
106 106 abort: cannot follow file not in parent revision: "dir"
107 107 [255]
108 108
109 109 -f, directory
110 110
111 111 $ hg up -q 3
112 112 $ hg log -f dir
113 113 changeset: 2:f8954cd4dc1f
114 114 user: test
115 115 date: Thu Jan 01 00:00:03 1970 +0000
116 116 summary: c
117 117
118 118 -f, directory with --patch
119 119
120 120 $ hg log -f dir -p
121 121 changeset: 2:f8954cd4dc1f
122 122 user: test
123 123 date: Thu Jan 01 00:00:03 1970 +0000
124 124 summary: c
125 125
126 126 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
127 127 --- /dev/null* (glob)
128 128 +++ b/dir/b* (glob)
129 129 @@ -0,0 +1,1 @@
130 130 +a
131 131
132 132
133 133 -f, pattern
134 134
135 135 $ hg log -f -I 'dir**' -p
136 136 changeset: 2:f8954cd4dc1f
137 137 user: test
138 138 date: Thu Jan 01 00:00:03 1970 +0000
139 139 summary: c
140 140
141 141 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
142 142 --- /dev/null* (glob)
143 143 +++ b/dir/b* (glob)
144 144 @@ -0,0 +1,1 @@
145 145 +a
146 146
147 147 $ hg up -q 4
148 148
149 149 -f, a wrong style
150 150
151 151 $ hg log -f -l1 --style something
152 152 abort: style 'something' not found
153 153 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
154 154 [255]
155 155
156 156 -f, phases style
157 157
158 158
159 159 $ hg log -f -l1 --style phases
160 160 changeset: 4:7e4639b4691b
161 161 tag: tip
162 162 phase: draft
163 163 user: test
164 164 date: Thu Jan 01 00:00:05 1970 +0000
165 165 summary: e
166 166
167 167
168 168 $ hg log -f -l1 --style phases -q
169 169 4:7e4639b4691b
170 170
171 171 -f, but no args
172 172
173 173 $ hg log -f
174 174 changeset: 4:7e4639b4691b
175 175 tag: tip
176 176 user: test
177 177 date: Thu Jan 01 00:00:05 1970 +0000
178 178 summary: e
179 179
180 180 changeset: 3:2ca5ba701980
181 181 user: test
182 182 date: Thu Jan 01 00:00:04 1970 +0000
183 183 summary: d
184 184
185 185 changeset: 2:f8954cd4dc1f
186 186 user: test
187 187 date: Thu Jan 01 00:00:03 1970 +0000
188 188 summary: c
189 189
190 190 changeset: 1:d89b0a12d229
191 191 user: test
192 192 date: Thu Jan 01 00:00:02 1970 +0000
193 193 summary: b
194 194
195 195 changeset: 0:9161b9aeaf16
196 196 user: test
197 197 date: Thu Jan 01 00:00:01 1970 +0000
198 198 summary: a
199 199
200 200
201 201 one rename
202 202
203 203 $ hg up -q 2
204 204 $ hg log -vf a
205 205 changeset: 0:9161b9aeaf16
206 206 user: test
207 207 date: Thu Jan 01 00:00:01 1970 +0000
208 208 files: a f
209 209 description:
210 210 a
211 211
212 212
213 213
214 214 many renames
215 215
216 216 $ hg up -q tip
217 217 $ hg log -vf e
218 218 changeset: 4:7e4639b4691b
219 219 tag: tip
220 220 user: test
221 221 date: Thu Jan 01 00:00:05 1970 +0000
222 222 files: dir/b e
223 223 description:
224 224 e
225 225
226 226
227 227 changeset: 2:f8954cd4dc1f
228 228 user: test
229 229 date: Thu Jan 01 00:00:03 1970 +0000
230 230 files: b dir/b f g
231 231 description:
232 232 c
233 233
234 234
235 235 changeset: 1:d89b0a12d229
236 236 user: test
237 237 date: Thu Jan 01 00:00:02 1970 +0000
238 238 files: b g
239 239 description:
240 240 b
241 241
242 242
243 243 changeset: 0:9161b9aeaf16
244 244 user: test
245 245 date: Thu Jan 01 00:00:01 1970 +0000
246 246 files: a f
247 247 description:
248 248 a
249 249
250 250
251 251
252 252
253 253 log -pf dir/b
254 254
255 255 $ hg up -q 3
256 256 $ hg log -pf dir/b
257 257 changeset: 2:f8954cd4dc1f
258 258 user: test
259 259 date: Thu Jan 01 00:00:03 1970 +0000
260 260 summary: c
261 261
262 262 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
263 263 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
264 264 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
265 265 @@ -0,0 +1,1 @@
266 266 +a
267 267
268 268 changeset: 1:d89b0a12d229
269 269 user: test
270 270 date: Thu Jan 01 00:00:02 1970 +0000
271 271 summary: b
272 272
273 273 diff -r 9161b9aeaf16 -r d89b0a12d229 b
274 274 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
275 275 +++ b/b Thu Jan 01 00:00:02 1970 +0000
276 276 @@ -0,0 +1,1 @@
277 277 +a
278 278
279 279 changeset: 0:9161b9aeaf16
280 280 user: test
281 281 date: Thu Jan 01 00:00:01 1970 +0000
282 282 summary: a
283 283
284 284 diff -r 000000000000 -r 9161b9aeaf16 a
285 285 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
286 286 +++ b/a Thu Jan 01 00:00:01 1970 +0000
287 287 @@ -0,0 +1,1 @@
288 288 +a
289 289
290 290
291 291 log -pf b inside dir
292 292
293 293 $ hg --cwd=dir log -pf b
294 294 changeset: 2:f8954cd4dc1f
295 295 user: test
296 296 date: Thu Jan 01 00:00:03 1970 +0000
297 297 summary: c
298 298
299 299 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
300 300 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
301 301 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
302 302 @@ -0,0 +1,1 @@
303 303 +a
304 304
305 305 changeset: 1:d89b0a12d229
306 306 user: test
307 307 date: Thu Jan 01 00:00:02 1970 +0000
308 308 summary: b
309 309
310 310 diff -r 9161b9aeaf16 -r d89b0a12d229 b
311 311 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
312 312 +++ b/b Thu Jan 01 00:00:02 1970 +0000
313 313 @@ -0,0 +1,1 @@
314 314 +a
315 315
316 316 changeset: 0:9161b9aeaf16
317 317 user: test
318 318 date: Thu Jan 01 00:00:01 1970 +0000
319 319 summary: a
320 320
321 321 diff -r 000000000000 -r 9161b9aeaf16 a
322 322 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
323 323 +++ b/a Thu Jan 01 00:00:01 1970 +0000
324 324 @@ -0,0 +1,1 @@
325 325 +a
326 326
327 327
328 328 log -pf, but no args
329 329
330 330 $ hg log -pf
331 331 changeset: 3:2ca5ba701980
332 332 user: test
333 333 date: Thu Jan 01 00:00:04 1970 +0000
334 334 summary: d
335 335
336 336 diff -r f8954cd4dc1f -r 2ca5ba701980 a
337 337 --- a/a Thu Jan 01 00:00:03 1970 +0000
338 338 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
339 339 @@ -1,1 +0,0 @@
340 340 -a
341 341 diff -r f8954cd4dc1f -r 2ca5ba701980 b
342 342 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
343 343 +++ b/b Thu Jan 01 00:00:04 1970 +0000
344 344 @@ -0,0 +1,1 @@
345 345 +a
346 346 diff -r f8954cd4dc1f -r 2ca5ba701980 d
347 347 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
348 348 +++ b/d Thu Jan 01 00:00:04 1970 +0000
349 349 @@ -0,0 +1,1 @@
350 350 +a
351 351 diff -r f8954cd4dc1f -r 2ca5ba701980 g
352 352 --- a/g Thu Jan 01 00:00:03 1970 +0000
353 353 +++ b/g Thu Jan 01 00:00:04 1970 +0000
354 354 @@ -1,2 +1,2 @@
355 355 f
356 356 -g
357 357 +f
358 358
359 359 changeset: 2:f8954cd4dc1f
360 360 user: test
361 361 date: Thu Jan 01 00:00:03 1970 +0000
362 362 summary: c
363 363
364 364 diff -r d89b0a12d229 -r f8954cd4dc1f b
365 365 --- a/b Thu Jan 01 00:00:02 1970 +0000
366 366 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
367 367 @@ -1,1 +0,0 @@
368 368 -a
369 369 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
370 370 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
371 371 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
372 372 @@ -0,0 +1,1 @@
373 373 +a
374 374 diff -r d89b0a12d229 -r f8954cd4dc1f f
375 375 --- a/f Thu Jan 01 00:00:02 1970 +0000
376 376 +++ b/f Thu Jan 01 00:00:03 1970 +0000
377 377 @@ -1,1 +1,2 @@
378 378 f
379 379 +f
380 380 diff -r d89b0a12d229 -r f8954cd4dc1f g
381 381 --- a/g Thu Jan 01 00:00:02 1970 +0000
382 382 +++ b/g Thu Jan 01 00:00:03 1970 +0000
383 383 @@ -1,1 +1,2 @@
384 384 f
385 385 +g
386 386
387 387 changeset: 1:d89b0a12d229
388 388 user: test
389 389 date: Thu Jan 01 00:00:02 1970 +0000
390 390 summary: b
391 391
392 392 diff -r 9161b9aeaf16 -r d89b0a12d229 b
393 393 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
394 394 +++ b/b Thu Jan 01 00:00:02 1970 +0000
395 395 @@ -0,0 +1,1 @@
396 396 +a
397 397 diff -r 9161b9aeaf16 -r d89b0a12d229 g
398 398 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
399 399 +++ b/g Thu Jan 01 00:00:02 1970 +0000
400 400 @@ -0,0 +1,1 @@
401 401 +f
402 402
403 403 changeset: 0:9161b9aeaf16
404 404 user: test
405 405 date: Thu Jan 01 00:00:01 1970 +0000
406 406 summary: a
407 407
408 408 diff -r 000000000000 -r 9161b9aeaf16 a
409 409 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
410 410 +++ b/a Thu Jan 01 00:00:01 1970 +0000
411 411 @@ -0,0 +1,1 @@
412 412 +a
413 413 diff -r 000000000000 -r 9161b9aeaf16 f
414 414 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
415 415 +++ b/f Thu Jan 01 00:00:01 1970 +0000
416 416 @@ -0,0 +1,1 @@
417 417 +f
418 418
419 419
420 420 log -vf dir/b
421 421
422 422 $ hg log -vf dir/b
423 423 changeset: 2:f8954cd4dc1f
424 424 user: test
425 425 date: Thu Jan 01 00:00:03 1970 +0000
426 426 files: b dir/b f g
427 427 description:
428 428 c
429 429
430 430
431 431 changeset: 1:d89b0a12d229
432 432 user: test
433 433 date: Thu Jan 01 00:00:02 1970 +0000
434 434 files: b g
435 435 description:
436 436 b
437 437
438 438
439 439 changeset: 0:9161b9aeaf16
440 440 user: test
441 441 date: Thu Jan 01 00:00:01 1970 +0000
442 442 files: a f
443 443 description:
444 444 a
445 445
446 446
447 447
448 448
449 449 -f and multiple filelog heads
450 450
451 451 $ hg up -q 2
452 452 $ hg log -f g --template '{rev}\n'
453 453 2
454 454 1
455 455 0
456 456 $ hg up -q tip
457 457 $ hg log -f g --template '{rev}\n'
458 458 3
459 459 2
460 460 0
461 461
462 462
463 463 log copies with --copies
464 464
465 465 $ hg log -vC --template '{rev} {file_copies}\n'
466 466 4 e (dir/b)
467 467 3 b (a)g (f)
468 468 2 dir/b (b)
469 469 1 b (a)g (f)
470 470 0
471 471
472 472 log copies switch without --copies, with old filecopy template
473 473
474 474 $ hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
475 475 4
476 476 3
477 477 2
478 478 1
479 479 0
480 480
481 481 log copies switch with --copies
482 482
483 483 $ hg log -vC --template '{rev} {file_copies_switch}\n'
484 484 4 e (dir/b)
485 485 3 b (a)g (f)
486 486 2 dir/b (b)
487 487 1 b (a)g (f)
488 488 0
489 489
490 490
491 491 log copies with hardcoded style and with --style=default
492 492
493 493 $ hg log -vC -r4
494 494 changeset: 4:7e4639b4691b
495 495 tag: tip
496 496 user: test
497 497 date: Thu Jan 01 00:00:05 1970 +0000
498 498 files: dir/b e
499 499 copies: e (dir/b)
500 500 description:
501 501 e
502 502
503 503
504 504 $ hg log -vC -r4 --style=default
505 505 changeset: 4:7e4639b4691b
506 506 tag: tip
507 507 user: test
508 508 date: Thu Jan 01 00:00:05 1970 +0000
509 509 files: dir/b e
510 510 copies: e (dir/b)
511 511 description:
512 512 e
513 513
514 514
515 515 $ hg log -vC -r4 -Tjson
516 516 [
517 517 {
518 518 "rev": 4,
519 519 "node": "7e4639b4691b9f84b81036a8d4fb218ce3c5e3a3",
520 520 "branch": "default",
521 521 "phase": "draft",
522 522 "user": "test",
523 523 "date": [5, 0],
524 524 "desc": "e",
525 525 "bookmarks": [],
526 526 "tags": ["tip"],
527 527 "parents": ["2ca5ba7019804f1f597249caddf22a64d34df0ba"],
528 528 "files": ["dir/b", "e"],
529 529 "copies": {"e": "dir/b"}
530 530 }
531 531 ]
532 532
533 533 log copies, non-linear manifest
534 534
535 535 $ hg up -C 3
536 536 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
537 537 $ hg mv dir/b e
538 538 $ echo foo > foo
539 539 $ hg ci -Ame2 -d '6 0'
540 540 adding foo
541 541 created new head
542 542 $ hg log -v --template '{rev} {file_copies}\n' -r 5
543 543 5 e (dir/b)
544 544
545 545
546 546 log copies, execute bit set
547 547
548 548 #if execbit
549 549 $ chmod +x e
550 550 $ hg ci -me3 -d '7 0'
551 551 $ hg log -v --template '{rev} {file_copies}\n' -r 6
552 552 6
553 553 #endif
554 554
555 555
556 556 log -p d
557 557
558 558 $ hg log -pv d
559 559 changeset: 3:2ca5ba701980
560 560 user: test
561 561 date: Thu Jan 01 00:00:04 1970 +0000
562 562 files: a b d g
563 563 description:
564 564 d
565 565
566 566
567 567 diff -r f8954cd4dc1f -r 2ca5ba701980 d
568 568 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
569 569 +++ b/d Thu Jan 01 00:00:04 1970 +0000
570 570 @@ -0,0 +1,1 @@
571 571 +a
572 572
573 573
574 574
575 575 log --removed file
576 576
577 577 $ hg log --removed -v a
578 578 changeset: 3:2ca5ba701980
579 579 user: test
580 580 date: Thu Jan 01 00:00:04 1970 +0000
581 581 files: a b d g
582 582 description:
583 583 d
584 584
585 585
586 586 changeset: 0:9161b9aeaf16
587 587 user: test
588 588 date: Thu Jan 01 00:00:01 1970 +0000
589 589 files: a f
590 590 description:
591 591 a
592 592
593 593
594 594
595 595 log --removed revrange file
596 596
597 597 $ hg log --removed -v -r0:2 a
598 598 changeset: 0:9161b9aeaf16
599 599 user: test
600 600 date: Thu Jan 01 00:00:01 1970 +0000
601 601 files: a f
602 602 description:
603 603 a
604 604
605 605
606 606 $ cd ..
607 607
608 608 log --follow tests
609 609
610 610 $ hg init follow
611 611 $ cd follow
612 612
613 613 $ echo base > base
614 614 $ hg ci -Ambase -d '1 0'
615 615 adding base
616 616
617 617 $ echo r1 >> base
618 618 $ hg ci -Amr1 -d '1 0'
619 619 $ echo r2 >> base
620 620 $ hg ci -Amr2 -d '1 0'
621 621
622 622 $ hg up -C 1
623 623 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
624 624 $ echo b1 > b1
625 625
626 626 log -r "follow('set:clean()')"
627 627
628 628 $ hg log -r "follow('set:clean()')"
629 629 changeset: 0:67e992f2c4f3
630 630 user: test
631 631 date: Thu Jan 01 00:00:01 1970 +0000
632 632 summary: base
633 633
634 634 changeset: 1:3d5bf5654eda
635 635 user: test
636 636 date: Thu Jan 01 00:00:01 1970 +0000
637 637 summary: r1
638 638
639 639
640 640 $ hg ci -Amb1 -d '1 0'
641 641 adding b1
642 642 created new head
643 643
644 644
645 645 log -f
646 646
647 647 $ hg log -f
648 648 changeset: 3:e62f78d544b4
649 649 tag: tip
650 650 parent: 1:3d5bf5654eda
651 651 user: test
652 652 date: Thu Jan 01 00:00:01 1970 +0000
653 653 summary: b1
654 654
655 655 changeset: 1:3d5bf5654eda
656 656 user: test
657 657 date: Thu Jan 01 00:00:01 1970 +0000
658 658 summary: r1
659 659
660 660 changeset: 0:67e992f2c4f3
661 661 user: test
662 662 date: Thu Jan 01 00:00:01 1970 +0000
663 663 summary: base
664 664
665 665
666 666 log -r follow('glob:b*')
667 667
668 668 $ hg log -r "follow('glob:b*')"
669 669 changeset: 0:67e992f2c4f3
670 670 user: test
671 671 date: Thu Jan 01 00:00:01 1970 +0000
672 672 summary: base
673 673
674 674 changeset: 1:3d5bf5654eda
675 675 user: test
676 676 date: Thu Jan 01 00:00:01 1970 +0000
677 677 summary: r1
678 678
679 679 changeset: 3:e62f78d544b4
680 680 tag: tip
681 681 parent: 1:3d5bf5654eda
682 682 user: test
683 683 date: Thu Jan 01 00:00:01 1970 +0000
684 684 summary: b1
685 685
686 686 log -f -r '1 + 4'
687 687
688 688 $ hg up -C 0
689 689 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
690 690 $ echo b2 > b2
691 691 $ hg ci -Amb2 -d '1 0'
692 692 adding b2
693 693 created new head
694 694 $ hg log -f -r '1 + 4'
695 695 changeset: 4:ddb82e70d1a1
696 696 tag: tip
697 697 parent: 0:67e992f2c4f3
698 698 user: test
699 699 date: Thu Jan 01 00:00:01 1970 +0000
700 700 summary: b2
701 701
702 702 changeset: 1:3d5bf5654eda
703 703 user: test
704 704 date: Thu Jan 01 00:00:01 1970 +0000
705 705 summary: r1
706 706
707 707 changeset: 0:67e992f2c4f3
708 708 user: test
709 709 date: Thu Jan 01 00:00:01 1970 +0000
710 710 summary: base
711 711
712 712 log -r "follow('set:grep(b2)')"
713 713
714 714 $ hg log -r "follow('set:grep(b2)')"
715 715 changeset: 4:ddb82e70d1a1
716 716 tag: tip
717 717 parent: 0:67e992f2c4f3
718 718 user: test
719 719 date: Thu Jan 01 00:00:01 1970 +0000
720 720 summary: b2
721 721
722 722 log -r "follow('set:grep(b2)', 4)"
723 723
724 724 $ hg up -qC 0
725 725 $ hg log -r "follow('set:grep(b2)', 4)"
726 726 changeset: 4:ddb82e70d1a1
727 727 tag: tip
728 728 parent: 0:67e992f2c4f3
729 729 user: test
730 730 date: Thu Jan 01 00:00:01 1970 +0000
731 731 summary: b2
732 732
733 733 $ hg up -qC 4
734 734
735 735 log -f -r null
736 736
737 737 $ hg log -f -r null
738 738 changeset: -1:000000000000
739 739 user:
740 740 date: Thu Jan 01 00:00:00 1970 +0000
741 741
742 742 $ hg log -f -r null -G
743 743 o changeset: -1:000000000000
744 744 user:
745 745 date: Thu Jan 01 00:00:00 1970 +0000
746 746
747 747
748 748
749 749 log -f with null parent
750 750
751 751 $ hg up -C null
752 752 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
753 753 $ hg log -f
754 754
755 755
756 756 log -r . with two parents
757 757
758 758 $ hg up -C 3
759 759 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
760 760 $ hg merge tip
761 761 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
762 762 (branch merge, don't forget to commit)
763 763 $ hg log -r .
764 764 changeset: 3:e62f78d544b4
765 765 parent: 1:3d5bf5654eda
766 766 user: test
767 767 date: Thu Jan 01 00:00:01 1970 +0000
768 768 summary: b1
769 769
770 770
771 771
772 772 log -r . with one parent
773 773
774 774 $ hg ci -mm12 -d '1 0'
775 775 $ hg log -r .
776 776 changeset: 5:302e9dd6890d
777 777 tag: tip
778 778 parent: 3:e62f78d544b4
779 779 parent: 4:ddb82e70d1a1
780 780 user: test
781 781 date: Thu Jan 01 00:00:01 1970 +0000
782 782 summary: m12
783 783
784 784
785 785 $ echo postm >> b1
786 786 $ hg ci -Amb1.1 -d'1 0'
787 787
788 788
789 789 log --follow-first
790 790
791 791 $ hg log --follow-first
792 792 changeset: 6:2404bbcab562
793 793 tag: tip
794 794 user: test
795 795 date: Thu Jan 01 00:00:01 1970 +0000
796 796 summary: b1.1
797 797
798 798 changeset: 5:302e9dd6890d
799 799 parent: 3:e62f78d544b4
800 800 parent: 4:ddb82e70d1a1
801 801 user: test
802 802 date: Thu Jan 01 00:00:01 1970 +0000
803 803 summary: m12
804 804
805 805 changeset: 3:e62f78d544b4
806 806 parent: 1:3d5bf5654eda
807 807 user: test
808 808 date: Thu Jan 01 00:00:01 1970 +0000
809 809 summary: b1
810 810
811 811 changeset: 1:3d5bf5654eda
812 812 user: test
813 813 date: Thu Jan 01 00:00:01 1970 +0000
814 814 summary: r1
815 815
816 816 changeset: 0:67e992f2c4f3
817 817 user: test
818 818 date: Thu Jan 01 00:00:01 1970 +0000
819 819 summary: base
820 820
821 821
822 822
823 823 log -P 2
824 824
825 825 $ hg log -P 2
826 826 changeset: 6:2404bbcab562
827 827 tag: tip
828 828 user: test
829 829 date: Thu Jan 01 00:00:01 1970 +0000
830 830 summary: b1.1
831 831
832 832 changeset: 5:302e9dd6890d
833 833 parent: 3:e62f78d544b4
834 834 parent: 4:ddb82e70d1a1
835 835 user: test
836 836 date: Thu Jan 01 00:00:01 1970 +0000
837 837 summary: m12
838 838
839 839 changeset: 4:ddb82e70d1a1
840 840 parent: 0:67e992f2c4f3
841 841 user: test
842 842 date: Thu Jan 01 00:00:01 1970 +0000
843 843 summary: b2
844 844
845 845 changeset: 3:e62f78d544b4
846 846 parent: 1:3d5bf5654eda
847 847 user: test
848 848 date: Thu Jan 01 00:00:01 1970 +0000
849 849 summary: b1
850 850
851 851
852 852
853 853 log -r tip -p --git
854 854
855 855 $ hg log -r tip -p --git
856 856 changeset: 6:2404bbcab562
857 857 tag: tip
858 858 user: test
859 859 date: Thu Jan 01 00:00:01 1970 +0000
860 860 summary: b1.1
861 861
862 862 diff --git a/b1 b/b1
863 863 --- a/b1
864 864 +++ b/b1
865 865 @@ -1,1 +1,2 @@
866 866 b1
867 867 +postm
868 868
869 869
870 870
871 871 log -r ""
872 872
873 873 $ hg log -r ''
874 874 hg: parse error: empty query
875 875 [255]
876 876
877 877 log -r <some unknown node id>
878 878
879 879 $ hg log -r 1000000000000000000000000000000000000000
880 880 abort: unknown revision '1000000000000000000000000000000000000000'!
881 881 [255]
882 882
883 883 log -k r1
884 884
885 885 $ hg log -k r1
886 886 changeset: 1:3d5bf5654eda
887 887 user: test
888 888 date: Thu Jan 01 00:00:01 1970 +0000
889 889 summary: r1
890 890
891 891 log -p -l2 --color=always
892 892
893 893 $ hg --config extensions.color= --config color.mode=ansi \
894 894 > log -p -l2 --color=always
895 895 \x1b[0;33mchangeset: 6:2404bbcab562\x1b[0m (esc)
896 896 tag: tip
897 897 user: test
898 898 date: Thu Jan 01 00:00:01 1970 +0000
899 899 summary: b1.1
900 900
901 901 \x1b[0;1mdiff -r 302e9dd6890d -r 2404bbcab562 b1\x1b[0m (esc)
902 902 \x1b[0;31;1m--- a/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
903 903 \x1b[0;32;1m+++ b/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
904 904 \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
905 905 b1
906 906 \x1b[0;32m+postm\x1b[0m (esc)
907 907
908 908 \x1b[0;33mchangeset: 5:302e9dd6890d\x1b[0m (esc)
909 909 parent: 3:e62f78d544b4
910 910 parent: 4:ddb82e70d1a1
911 911 user: test
912 912 date: Thu Jan 01 00:00:01 1970 +0000
913 913 summary: m12
914 914
915 915 \x1b[0;1mdiff -r e62f78d544b4 -r 302e9dd6890d b2\x1b[0m (esc)
916 916 \x1b[0;31;1m--- /dev/null Thu Jan 01 00:00:00 1970 +0000\x1b[0m (esc)
917 917 \x1b[0;32;1m+++ b/b2 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
918 918 \x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m (esc)
919 919 \x1b[0;32m+b2\x1b[0m (esc)
920 920
921 921
922 922
923 923 log -r tip --stat
924 924
925 925 $ hg log -r tip --stat
926 926 changeset: 6:2404bbcab562
927 927 tag: tip
928 928 user: test
929 929 date: Thu Jan 01 00:00:01 1970 +0000
930 930 summary: b1.1
931 931
932 932 b1 | 1 +
933 933 1 files changed, 1 insertions(+), 0 deletions(-)
934 934
935 935
936 936 $ cd ..
937 937
938 938 log --follow --patch FILE in repository where linkrev isn't trustworthy
939 939 (issue5376)
940 940
941 941 $ hg init follow-dup
942 942 $ cd follow-dup
943 943 $ cat <<EOF >> .hg/hgrc
944 944 > [ui]
945 945 > logtemplate = '=== {rev}: {desc}\n'
946 946 > [diff]
947 947 > nodates = True
948 948 > EOF
949 949 $ echo 0 >> a
950 950 $ hg ci -qAm 'a0'
951 951 $ echo 1 >> a
952 952 $ hg ci -m 'a1'
953 953 $ hg up -q 0
954 954 $ echo 1 >> a
955 955 $ touch b
956 956 $ hg ci -qAm 'a1 with b'
957 957 $ echo 3 >> a
958 958 $ hg ci -m 'a3'
959 959
960 960 fctx.rev() == 2, but fctx.linkrev() == 1
961 961
962 962 $ hg log -pf a
963 963 === 3: a3
964 964 diff -r 4ea02ba94d66 -r e7a6331a34f0 a
965 965 --- a/a
966 966 +++ b/a
967 967 @@ -1,2 +1,3 @@
968 968 0
969 969 1
970 970 +3
971 971
972 972 === 2: a1 with b
973 973 diff -r 49b5e81287e2 -r 4ea02ba94d66 a
974 974 --- a/a
975 975 +++ b/a
976 976 @@ -1,1 +1,2 @@
977 977 0
978 978 +1
979 979
980 980 === 0: a0
981 981 diff -r 000000000000 -r 49b5e81287e2 a
982 982 --- /dev/null
983 983 +++ b/a
984 984 @@ -0,0 +1,1 @@
985 985 +0
986 986
987 987
988 988 fctx.introrev() == 2, but fctx.linkrev() == 1
989 989
990 990 $ hg up -q 2
991 991 $ hg log -pf a
992 992 === 2: a1 with b
993 993 diff -r 49b5e81287e2 -r 4ea02ba94d66 a
994 994 --- a/a
995 995 +++ b/a
996 996 @@ -1,1 +1,2 @@
997 997 0
998 998 +1
999 999
1000 1000 === 0: a0
1001 1001 diff -r 000000000000 -r 49b5e81287e2 a
1002 1002 --- /dev/null
1003 1003 +++ b/a
1004 1004 @@ -0,0 +1,1 @@
1005 1005 +0
1006 1006
1007 1007
1008 1008 $ cd ..
1009 1009
1010 1010 Test that log should respect the order of -rREV even if multiple OR conditions
1011 1011 are specified (issue5100):
1012 1012
1013 1013 $ hg init revorder
1014 1014 $ cd revorder
1015 1015
1016 1016 $ hg branch -q b0
1017 1017 $ echo 0 >> f0
1018 1018 $ hg ci -qAm k0 -u u0
1019 1019 $ hg branch -q b1
1020 1020 $ echo 1 >> f1
1021 1021 $ hg ci -qAm k1 -u u1
1022 1022 $ hg branch -q b2
1023 1023 $ echo 2 >> f2
1024 1024 $ hg ci -qAm k2 -u u2
1025 1025
1026 1026 $ hg update -q b2
1027 1027 $ echo 3 >> f2
1028 1028 $ hg ci -qAm k2 -u u2
1029 1029 $ hg update -q b1
1030 1030 $ echo 4 >> f1
1031 1031 $ hg ci -qAm k1 -u u1
1032 1032 $ hg update -q b0
1033 1033 $ echo 5 >> f0
1034 1034 $ hg ci -qAm k0 -u u0
1035 1035
1036 1036 summary of revisions:
1037 1037
1038 1038 $ hg log -G -T '{rev} {branch} {author} {desc} {files}\n'
1039 1039 @ 5 b0 u0 k0 f0
1040 1040 |
1041 1041 | o 4 b1 u1 k1 f1
1042 1042 | |
1043 1043 | | o 3 b2 u2 k2 f2
1044 1044 | | |
1045 1045 | | o 2 b2 u2 k2 f2
1046 1046 | |/
1047 1047 | o 1 b1 u1 k1 f1
1048 1048 |/
1049 1049 o 0 b0 u0 k0 f0
1050 1050
1051 1051
1052 1052 log -b BRANCH in ascending order:
1053 1053
1054 1054 $ hg log -r0:tip -T '{rev} {branch}\n' -b b0 -b b1
1055 1055 0 b0
1056 1056 1 b1
1057 1057 4 b1
1058 1058 5 b0
1059 1059 $ hg log -r0:tip -T '{rev} {branch}\n' -b b1 -b b0
1060 1060 0 b0
1061 1061 1 b1
1062 1062 4 b1
1063 1063 5 b0
1064 1064
1065 1065 log --only-branch BRANCH in descending order:
1066 1066
1067 1067 $ hg log -rtip:0 -T '{rev} {branch}\n' --only-branch b1 --only-branch b2
1068 1068 4 b1
1069 1069 3 b2
1070 1070 2 b2
1071 1071 1 b1
1072 1072 $ hg log -rtip:0 -T '{rev} {branch}\n' --only-branch b2 --only-branch b1
1073 1073 4 b1
1074 1074 3 b2
1075 1075 2 b2
1076 1076 1 b1
1077 1077
1078 1078 log -u USER in ascending order, against compound set:
1079 1079
1080 1080 $ hg log -r'::head()' -T '{rev} {author}\n' -u u0 -u u2
1081 1081 0 u0
1082 1082 2 u2
1083 1083 3 u2
1084 1084 5 u0
1085 1085 $ hg log -r'::head()' -T '{rev} {author}\n' -u u2 -u u0
1086 1086 0 u0
1087 1087 2 u2
1088 1088 3 u2
1089 1089 5 u0
1090 1090
1091 1091 log -k TEXT in descending order, against compound set:
1092 1092
1093 1093 $ hg log -r'5 + reverse(::3)' -T '{rev} {desc}\n' -k k0 -k k1 -k k2
1094 1094 5 k0
1095 1095 3 k2
1096 1096 2 k2
1097 1097 1 k1
1098 1098 0 k0
1099 1099 $ hg log -r'5 + reverse(::3)' -T '{rev} {desc}\n' -k k2 -k k1 -k k0
1100 1100 5 k0
1101 1101 3 k2
1102 1102 2 k2
1103 1103 1 k1
1104 1104 0 k0
1105 1105
1106 1106 log FILE in ascending order, against dagrange:
1107 1107
1108 1108 $ hg log -r1:: -T '{rev} {files}\n' f1 f2
1109 1109 1 f1
1110 1110 2 f2
1111 1111 3 f2
1112 1112 4 f1
1113 1113 $ hg log -r1:: -T '{rev} {files}\n' f2 f1
1114 1114 1 f1
1115 1115 2 f2
1116 1116 3 f2
1117 1117 4 f1
1118 1118
1119 1119 $ cd ..
1120 1120
1121 1121 User
1122 1122
1123 1123 $ hg init usertest
1124 1124 $ cd usertest
1125 1125
1126 1126 $ echo a > a
1127 1127 $ hg ci -A -m "a" -u "User One <user1@example.org>"
1128 1128 adding a
1129 1129 $ echo b > b
1130 1130 $ hg ci -A -m "b" -u "User Two <user2@example.org>"
1131 1131 adding b
1132 1132
1133 1133 $ hg log -u "User One <user1@example.org>"
1134 1134 changeset: 0:29a4c94f1924
1135 1135 user: User One <user1@example.org>
1136 1136 date: Thu Jan 01 00:00:00 1970 +0000
1137 1137 summary: a
1138 1138
1139 1139 $ hg log -u "user1" -u "user2"
1140 1140 changeset: 1:e834b5e69c0e
1141 1141 tag: tip
1142 1142 user: User Two <user2@example.org>
1143 1143 date: Thu Jan 01 00:00:00 1970 +0000
1144 1144 summary: b
1145 1145
1146 1146 changeset: 0:29a4c94f1924
1147 1147 user: User One <user1@example.org>
1148 1148 date: Thu Jan 01 00:00:00 1970 +0000
1149 1149 summary: a
1150 1150
1151 1151 $ hg log -u "user3"
1152 1152
1153 1153 $ cd ..
1154 1154
1155 1155 $ hg init branches
1156 1156 $ cd branches
1157 1157
1158 1158 $ echo a > a
1159 1159 $ hg ci -A -m "commit on default"
1160 1160 adding a
1161 1161 $ hg branch test
1162 1162 marked working directory as branch test
1163 1163 (branches are permanent and global, did you want a bookmark?)
1164 1164 $ echo b > b
1165 1165 $ hg ci -A -m "commit on test"
1166 1166 adding b
1167 1167
1168 1168 $ hg up default
1169 1169 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1170 1170 $ echo c > c
1171 1171 $ hg ci -A -m "commit on default"
1172 1172 adding c
1173 1173 $ hg up test
1174 1174 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1175 1175 $ echo c > c
1176 1176 $ hg ci -A -m "commit on test"
1177 1177 adding c
1178 1178
1179 1179
1180 1180 log -b default
1181 1181
1182 1182 $ hg log -b default
1183 1183 changeset: 2:c3a4f03cc9a7
1184 1184 parent: 0:24427303d56f
1185 1185 user: test
1186 1186 date: Thu Jan 01 00:00:00 1970 +0000
1187 1187 summary: commit on default
1188 1188
1189 1189 changeset: 0:24427303d56f
1190 1190 user: test
1191 1191 date: Thu Jan 01 00:00:00 1970 +0000
1192 1192 summary: commit on default
1193 1193
1194 1194
1195 1195
1196 1196 log -b test
1197 1197
1198 1198 $ hg log -b test
1199 1199 changeset: 3:f5d8de11c2e2
1200 1200 branch: test
1201 1201 tag: tip
1202 1202 parent: 1:d32277701ccb
1203 1203 user: test
1204 1204 date: Thu Jan 01 00:00:00 1970 +0000
1205 1205 summary: commit on test
1206 1206
1207 1207 changeset: 1:d32277701ccb
1208 1208 branch: test
1209 1209 user: test
1210 1210 date: Thu Jan 01 00:00:00 1970 +0000
1211 1211 summary: commit on test
1212 1212
1213 1213
1214 1214
1215 1215 log -b dummy
1216 1216
1217 1217 $ hg log -b dummy
1218 1218 abort: unknown revision 'dummy'!
1219 1219 [255]
1220 1220
1221 1221
1222 1222 log -b .
1223 1223
1224 1224 $ hg log -b .
1225 1225 changeset: 3:f5d8de11c2e2
1226 1226 branch: test
1227 1227 tag: tip
1228 1228 parent: 1:d32277701ccb
1229 1229 user: test
1230 1230 date: Thu Jan 01 00:00:00 1970 +0000
1231 1231 summary: commit on test
1232 1232
1233 1233 changeset: 1:d32277701ccb
1234 1234 branch: test
1235 1235 user: test
1236 1236 date: Thu Jan 01 00:00:00 1970 +0000
1237 1237 summary: commit on test
1238 1238
1239 1239
1240 1240
1241 1241 log -b default -b test
1242 1242
1243 1243 $ hg log -b default -b test
1244 1244 changeset: 3:f5d8de11c2e2
1245 1245 branch: test
1246 1246 tag: tip
1247 1247 parent: 1:d32277701ccb
1248 1248 user: test
1249 1249 date: Thu Jan 01 00:00:00 1970 +0000
1250 1250 summary: commit on test
1251 1251
1252 1252 changeset: 2:c3a4f03cc9a7
1253 1253 parent: 0:24427303d56f
1254 1254 user: test
1255 1255 date: Thu Jan 01 00:00:00 1970 +0000
1256 1256 summary: commit on default
1257 1257
1258 1258 changeset: 1:d32277701ccb
1259 1259 branch: test
1260 1260 user: test
1261 1261 date: Thu Jan 01 00:00:00 1970 +0000
1262 1262 summary: commit on test
1263 1263
1264 1264 changeset: 0:24427303d56f
1265 1265 user: test
1266 1266 date: Thu Jan 01 00:00:00 1970 +0000
1267 1267 summary: commit on default
1268 1268
1269 1269
1270 1270
1271 1271 log -b default -b .
1272 1272
1273 1273 $ hg log -b default -b .
1274 1274 changeset: 3:f5d8de11c2e2
1275 1275 branch: test
1276 1276 tag: tip
1277 1277 parent: 1:d32277701ccb
1278 1278 user: test
1279 1279 date: Thu Jan 01 00:00:00 1970 +0000
1280 1280 summary: commit on test
1281 1281
1282 1282 changeset: 2:c3a4f03cc9a7
1283 1283 parent: 0:24427303d56f
1284 1284 user: test
1285 1285 date: Thu Jan 01 00:00:00 1970 +0000
1286 1286 summary: commit on default
1287 1287
1288 1288 changeset: 1:d32277701ccb
1289 1289 branch: test
1290 1290 user: test
1291 1291 date: Thu Jan 01 00:00:00 1970 +0000
1292 1292 summary: commit on test
1293 1293
1294 1294 changeset: 0:24427303d56f
1295 1295 user: test
1296 1296 date: Thu Jan 01 00:00:00 1970 +0000
1297 1297 summary: commit on default
1298 1298
1299 1299
1300 1300
1301 1301 log -b . -b test
1302 1302
1303 1303 $ hg log -b . -b test
1304 1304 changeset: 3:f5d8de11c2e2
1305 1305 branch: test
1306 1306 tag: tip
1307 1307 parent: 1:d32277701ccb
1308 1308 user: test
1309 1309 date: Thu Jan 01 00:00:00 1970 +0000
1310 1310 summary: commit on test
1311 1311
1312 1312 changeset: 1:d32277701ccb
1313 1313 branch: test
1314 1314 user: test
1315 1315 date: Thu Jan 01 00:00:00 1970 +0000
1316 1316 summary: commit on test
1317 1317
1318 1318
1319 1319
1320 1320 log -b 2
1321 1321
1322 1322 $ hg log -b 2
1323 1323 changeset: 2:c3a4f03cc9a7
1324 1324 parent: 0:24427303d56f
1325 1325 user: test
1326 1326 date: Thu Jan 01 00:00:00 1970 +0000
1327 1327 summary: commit on default
1328 1328
1329 1329 changeset: 0:24427303d56f
1330 1330 user: test
1331 1331 date: Thu Jan 01 00:00:00 1970 +0000
1332 1332 summary: commit on default
1333 1333
1334 1334 #if gettext
1335 1335
1336 1336 Test that all log names are translated (e.g. branches, bookmarks, tags):
1337 1337
1338 1338 $ hg bookmark babar -r tip
1339 1339
1340 1340 $ HGENCODING=UTF-8 LANGUAGE=de hg log -r tip
1341 1341 \xc3\x84nderung: 3:f5d8de11c2e2 (esc)
1342 1342 Zweig: test
1343 1343 Lesezeichen: babar
1344 1344 Marke: tip
1345 1345 Vorg\xc3\xa4nger: 1:d32277701ccb (esc)
1346 1346 Nutzer: test
1347 1347 Datum: Thu Jan 01 00:00:00 1970 +0000
1348 1348 Zusammenfassung: commit on test
1349 1349
1350 1350 $ hg bookmark -d babar
1351 1351
1352 1352 #endif
1353 1353
1354 1354 log -p --cwd dir (in subdir)
1355 1355
1356 1356 $ mkdir dir
1357 1357 $ hg log -p --cwd dir
1358 1358 changeset: 3:f5d8de11c2e2
1359 1359 branch: test
1360 1360 tag: tip
1361 1361 parent: 1:d32277701ccb
1362 1362 user: test
1363 1363 date: Thu Jan 01 00:00:00 1970 +0000
1364 1364 summary: commit on test
1365 1365
1366 1366 diff -r d32277701ccb -r f5d8de11c2e2 c
1367 1367 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1368 1368 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1369 1369 @@ -0,0 +1,1 @@
1370 1370 +c
1371 1371
1372 1372 changeset: 2:c3a4f03cc9a7
1373 1373 parent: 0:24427303d56f
1374 1374 user: test
1375 1375 date: Thu Jan 01 00:00:00 1970 +0000
1376 1376 summary: commit on default
1377 1377
1378 1378 diff -r 24427303d56f -r c3a4f03cc9a7 c
1379 1379 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1380 1380 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1381 1381 @@ -0,0 +1,1 @@
1382 1382 +c
1383 1383
1384 1384 changeset: 1:d32277701ccb
1385 1385 branch: test
1386 1386 user: test
1387 1387 date: Thu Jan 01 00:00:00 1970 +0000
1388 1388 summary: commit on test
1389 1389
1390 1390 diff -r 24427303d56f -r d32277701ccb b
1391 1391 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1392 1392 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1393 1393 @@ -0,0 +1,1 @@
1394 1394 +b
1395 1395
1396 1396 changeset: 0:24427303d56f
1397 1397 user: test
1398 1398 date: Thu Jan 01 00:00:00 1970 +0000
1399 1399 summary: commit on default
1400 1400
1401 1401 diff -r 000000000000 -r 24427303d56f a
1402 1402 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1403 1403 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1404 1404 @@ -0,0 +1,1 @@
1405 1405 +a
1406 1406
1407 1407
1408 1408
1409 1409 log -p -R repo
1410 1410
1411 1411 $ cd dir
1412 1412 $ hg log -p -R .. ../a
1413 1413 changeset: 0:24427303d56f
1414 1414 user: test
1415 1415 date: Thu Jan 01 00:00:00 1970 +0000
1416 1416 summary: commit on default
1417 1417
1418 1418 diff -r 000000000000 -r 24427303d56f a
1419 1419 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1420 1420 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1421 1421 @@ -0,0 +1,1 @@
1422 1422 +a
1423 1423
1424 1424
1425 1425 $ cd ../..
1426 1426
1427 1427 $ hg init follow2
1428 1428 $ cd follow2
1429 1429
1430 1430 # Build the following history:
1431 1431 # tip - o - x - o - x - x
1432 1432 # \ /
1433 1433 # o - o - o - x
1434 1434 # \ /
1435 1435 # o
1436 1436 #
1437 1437 # Where "o" is a revision containing "foo" and
1438 1438 # "x" is a revision without "foo"
1439 1439
1440 1440 $ touch init
1441 1441 $ hg ci -A -m "init, unrelated"
1442 1442 adding init
1443 1443 $ echo 'foo' > init
1444 1444 $ hg ci -m "change, unrelated"
1445 1445 $ echo 'foo' > foo
1446 1446 $ hg ci -A -m "add unrelated old foo"
1447 1447 adding foo
1448 1448 $ hg rm foo
1449 1449 $ hg ci -m "delete foo, unrelated"
1450 1450 $ echo 'related' > foo
1451 1451 $ hg ci -A -m "add foo, related"
1452 1452 adding foo
1453 1453
1454 1454 $ hg up 0
1455 1455 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1456 1456 $ touch branch
1457 1457 $ hg ci -A -m "first branch, unrelated"
1458 1458 adding branch
1459 1459 created new head
1460 1460 $ touch foo
1461 1461 $ hg ci -A -m "create foo, related"
1462 1462 adding foo
1463 1463 $ echo 'change' > foo
1464 1464 $ hg ci -m "change foo, related"
1465 1465
1466 1466 $ hg up 6
1467 1467 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1468 1468 $ echo 'change foo in branch' > foo
1469 1469 $ hg ci -m "change foo in branch, related"
1470 1470 created new head
1471 1471 $ hg merge 7
1472 1472 merging foo
1473 1473 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
1474 1474 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1475 1475 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1476 1476 [1]
1477 1477 $ echo 'merge 1' > foo
1478 1478 $ hg resolve -m foo
1479 1479 (no more unresolved files)
1480 1480 $ hg ci -m "First merge, related"
1481 1481
1482 1482 $ hg merge 4
1483 1483 merging foo
1484 1484 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
1485 1485 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
1486 1486 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1487 1487 [1]
1488 1488 $ echo 'merge 2' > foo
1489 1489 $ hg resolve -m foo
1490 1490 (no more unresolved files)
1491 1491 $ hg ci -m "Last merge, related"
1492 1492
1493 1493 $ hg log --graph
1494 1494 @ changeset: 10:4dae8563d2c5
1495 1495 |\ tag: tip
1496 1496 | | parent: 9:7b35701b003e
1497 1497 | | parent: 4:88176d361b69
1498 1498 | | user: test
1499 1499 | | date: Thu Jan 01 00:00:00 1970 +0000
1500 1500 | | summary: Last merge, related
1501 1501 | |
1502 1502 | o changeset: 9:7b35701b003e
1503 1503 | |\ parent: 8:e5416ad8a855
1504 1504 | | | parent: 7:87fe3144dcfa
1505 1505 | | | user: test
1506 1506 | | | date: Thu Jan 01 00:00:00 1970 +0000
1507 1507 | | | summary: First merge, related
1508 1508 | | |
1509 1509 | | o changeset: 8:e5416ad8a855
1510 1510 | | | parent: 6:dc6c325fe5ee
1511 1511 | | | user: test
1512 1512 | | | date: Thu Jan 01 00:00:00 1970 +0000
1513 1513 | | | summary: change foo in branch, related
1514 1514 | | |
1515 1515 | o | changeset: 7:87fe3144dcfa
1516 1516 | |/ user: test
1517 1517 | | date: Thu Jan 01 00:00:00 1970 +0000
1518 1518 | | summary: change foo, related
1519 1519 | |
1520 1520 | o changeset: 6:dc6c325fe5ee
1521 1521 | | user: test
1522 1522 | | date: Thu Jan 01 00:00:00 1970 +0000
1523 1523 | | summary: create foo, related
1524 1524 | |
1525 1525 | o changeset: 5:73db34516eb9
1526 1526 | | parent: 0:e87515fd044a
1527 1527 | | user: test
1528 1528 | | date: Thu Jan 01 00:00:00 1970 +0000
1529 1529 | | summary: first branch, unrelated
1530 1530 | |
1531 1531 o | changeset: 4:88176d361b69
1532 1532 | | user: test
1533 1533 | | date: Thu Jan 01 00:00:00 1970 +0000
1534 1534 | | summary: add foo, related
1535 1535 | |
1536 1536 o | changeset: 3:dd78ae4afb56
1537 1537 | | user: test
1538 1538 | | date: Thu Jan 01 00:00:00 1970 +0000
1539 1539 | | summary: delete foo, unrelated
1540 1540 | |
1541 1541 o | changeset: 2:c4c64aedf0f7
1542 1542 | | user: test
1543 1543 | | date: Thu Jan 01 00:00:00 1970 +0000
1544 1544 | | summary: add unrelated old foo
1545 1545 | |
1546 1546 o | changeset: 1:e5faa7440653
1547 1547 |/ user: test
1548 1548 | date: Thu Jan 01 00:00:00 1970 +0000
1549 1549 | summary: change, unrelated
1550 1550 |
1551 1551 o changeset: 0:e87515fd044a
1552 1552 user: test
1553 1553 date: Thu Jan 01 00:00:00 1970 +0000
1554 1554 summary: init, unrelated
1555 1555
1556 1556
1557 1557 $ hg --traceback log -f foo
1558 1558 changeset: 10:4dae8563d2c5
1559 1559 tag: tip
1560 1560 parent: 9:7b35701b003e
1561 1561 parent: 4:88176d361b69
1562 1562 user: test
1563 1563 date: Thu Jan 01 00:00:00 1970 +0000
1564 1564 summary: Last merge, related
1565 1565
1566 1566 changeset: 9:7b35701b003e
1567 1567 parent: 8:e5416ad8a855
1568 1568 parent: 7:87fe3144dcfa
1569 1569 user: test
1570 1570 date: Thu Jan 01 00:00:00 1970 +0000
1571 1571 summary: First merge, related
1572 1572
1573 1573 changeset: 8:e5416ad8a855
1574 1574 parent: 6:dc6c325fe5ee
1575 1575 user: test
1576 1576 date: Thu Jan 01 00:00:00 1970 +0000
1577 1577 summary: change foo in branch, related
1578 1578
1579 1579 changeset: 7:87fe3144dcfa
1580 1580 user: test
1581 1581 date: Thu Jan 01 00:00:00 1970 +0000
1582 1582 summary: change foo, related
1583 1583
1584 1584 changeset: 6:dc6c325fe5ee
1585 1585 user: test
1586 1586 date: Thu Jan 01 00:00:00 1970 +0000
1587 1587 summary: create foo, related
1588 1588
1589 1589 changeset: 4:88176d361b69
1590 1590 user: test
1591 1591 date: Thu Jan 01 00:00:00 1970 +0000
1592 1592 summary: add foo, related
1593 1593
1594 1594
1595 1595 Also check when maxrev < lastrevfilelog
1596 1596
1597 1597 $ hg --traceback log -f -r4 foo
1598 1598 changeset: 4:88176d361b69
1599 1599 user: test
1600 1600 date: Thu Jan 01 00:00:00 1970 +0000
1601 1601 summary: add foo, related
1602 1602
1603 1603 changeset: 2:c4c64aedf0f7
1604 1604 user: test
1605 1605 date: Thu Jan 01 00:00:00 1970 +0000
1606 1606 summary: add unrelated old foo
1607 1607
1608 1608 $ cd ..
1609 1609
1610 1610 Issue2383: hg log showing _less_ differences than hg diff
1611 1611
1612 1612 $ hg init issue2383
1613 1613 $ cd issue2383
1614 1614
1615 1615 Create a test repo:
1616 1616
1617 1617 $ echo a > a
1618 1618 $ hg ci -Am0
1619 1619 adding a
1620 1620 $ echo b > b
1621 1621 $ hg ci -Am1
1622 1622 adding b
1623 1623 $ hg co 0
1624 1624 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1625 1625 $ echo b > a
1626 1626 $ hg ci -m2
1627 1627 created new head
1628 1628
1629 1629 Merge:
1630 1630
1631 1631 $ hg merge
1632 1632 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1633 1633 (branch merge, don't forget to commit)
1634 1634
1635 1635 Make sure there's a file listed in the merge to trigger the bug:
1636 1636
1637 1637 $ echo c > a
1638 1638 $ hg ci -m3
1639 1639
1640 1640 Two files shown here in diff:
1641 1641
1642 1642 $ hg diff --rev 2:3
1643 1643 diff -r b09be438c43a -r 8e07aafe1edc a
1644 1644 --- a/a Thu Jan 01 00:00:00 1970 +0000
1645 1645 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1646 1646 @@ -1,1 +1,1 @@
1647 1647 -b
1648 1648 +c
1649 1649 diff -r b09be438c43a -r 8e07aafe1edc b
1650 1650 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1651 1651 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1652 1652 @@ -0,0 +1,1 @@
1653 1653 +b
1654 1654
1655 1655 Diff here should be the same:
1656 1656
1657 1657 $ hg log -vpr 3
1658 1658 changeset: 3:8e07aafe1edc
1659 1659 tag: tip
1660 1660 parent: 2:b09be438c43a
1661 1661 parent: 1:925d80f479bb
1662 1662 user: test
1663 1663 date: Thu Jan 01 00:00:00 1970 +0000
1664 1664 files: a
1665 1665 description:
1666 1666 3
1667 1667
1668 1668
1669 1669 diff -r b09be438c43a -r 8e07aafe1edc a
1670 1670 --- a/a Thu Jan 01 00:00:00 1970 +0000
1671 1671 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1672 1672 @@ -1,1 +1,1 @@
1673 1673 -b
1674 1674 +c
1675 1675 diff -r b09be438c43a -r 8e07aafe1edc b
1676 1676 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1677 1677 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1678 1678 @@ -0,0 +1,1 @@
1679 1679 +b
1680 1680
1681 1681 $ cd ..
1682 1682
1683 1683 'hg log -r rev fn' when last(filelog(fn)) != rev
1684 1684
1685 1685 $ hg init simplelog
1686 1686 $ cd simplelog
1687 1687 $ echo f > a
1688 1688 $ hg ci -Am'a' -d '0 0'
1689 1689 adding a
1690 1690 $ echo f >> a
1691 1691 $ hg ci -Am'a bis' -d '1 0'
1692 1692
1693 1693 $ hg log -r0 a
1694 1694 changeset: 0:9f758d63dcde
1695 1695 user: test
1696 1696 date: Thu Jan 01 00:00:00 1970 +0000
1697 1697 summary: a
1698 1698
1699 1699 enable obsolete to test hidden feature
1700 1700
1701 1701 $ cat >> $HGRCPATH << EOF
1702 1702 > [experimental]
1703 1703 > stabilization=createmarkers
1704 1704 > EOF
1705 1705
1706 1706 $ hg log --template='{rev}:{node}\n'
1707 1707 1:a765632148dc55d38c35c4f247c618701886cb2f
1708 1708 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1709 1709 $ hg debugobsolete a765632148dc55d38c35c4f247c618701886cb2f
1710 1710 obsoleted 1 changesets
1711 1711 $ hg up null -q
1712 1712 $ hg log --template='{rev}:{node}\n'
1713 1713 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1714 1714 $ hg log --template='{rev}:{node}\n' --hidden
1715 1715 1:a765632148dc55d38c35c4f247c618701886cb2f
1716 1716 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1717 1717 $ hg log -r a
1718 1718 abort: hidden revision 'a'!
1719 1719 (use --hidden to access hidden revisions)
1720 1720 [255]
1721 1721
1722 1722 test that parent prevent a changeset to be hidden
1723 1723
1724 1724 $ hg up 1 -q --hidden
1725 1725 $ hg log --template='{rev}:{node}\n'
1726 1726 1:a765632148dc55d38c35c4f247c618701886cb2f
1727 1727 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1728 1728
1729 1729 test that second parent prevent a changeset to be hidden too
1730 1730
1731 1731 $ hg debugsetparents 0 1 # nothing suitable to merge here
1732 1732 $ hg log --template='{rev}:{node}\n'
1733 1733 1:a765632148dc55d38c35c4f247c618701886cb2f
1734 1734 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1735 1735 $ hg debugsetparents 1
1736 1736 $ hg up -q null
1737 1737
1738 1738 bookmarks prevent a changeset being hidden
1739 1739
1740 1740 $ hg bookmark --hidden -r 1 X
1741 1741 $ hg log --template '{rev}:{node}\n'
1742 1742 1:a765632148dc55d38c35c4f247c618701886cb2f
1743 1743 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1744 1744 $ hg bookmark -d X
1745 1745
1746 1746 divergent bookmarks are not hidden
1747 1747
1748 1748 $ hg bookmark --hidden -r 1 X@foo
1749 1749 $ hg log --template '{rev}:{node}\n'
1750 1750 1:a765632148dc55d38c35c4f247c618701886cb2f
1751 1751 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1752 1752
1753 1753 test hidden revision 0 (issue5385)
1754 1754
1755 1755 $ hg bookmark -d X@foo
1756 1756 $ hg up null -q
1757 1757 $ hg debugobsolete 9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1758 1758 obsoleted 1 changesets
1759 1759 $ echo f > b
1760 1760 $ hg ci -Am'b' -d '2 0'
1761 1761 adding b
1762 1762 $ echo f >> b
1763 1763 $ hg ci -m'b bis' -d '3 0'
1764 1764 $ hg log -T'{rev}:{node}\n'
1765 1765 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
1766 1766 2:94375ec45bddd2a824535fc04855bd058c926ec0
1767 1767
1768 1768 $ hg log -T'{rev}:{node}\n' -r:
1769 1769 2:94375ec45bddd2a824535fc04855bd058c926ec0
1770 1770 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
1771 1771 $ hg log -T'{rev}:{node}\n' -r:tip
1772 1772 2:94375ec45bddd2a824535fc04855bd058c926ec0
1773 1773 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
1774 1774 $ hg log -T'{rev}:{node}\n' -r:0
1775 1775 abort: hidden revision '0'!
1776 1776 (use --hidden to access hidden revisions)
1777 1777 [255]
1778 1778 $ hg log -T'{rev}:{node}\n' -f
1779 1779 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
1780 1780 2:94375ec45bddd2a824535fc04855bd058c926ec0
1781 1781
1782 1782 clear extensions configuration
1783 1783 $ echo '[extensions]' >> $HGRCPATH
1784 1784 $ echo "obs=!" >> $HGRCPATH
1785 1785 $ cd ..
1786 1786
1787 1787 test -u/-k for problematic encoding
1788 1788 # unicode: cp932:
1789 1789 # u30A2 0x83 0x41(= 'A')
1790 1790 # u30C2 0x83 0x61(= 'a')
1791 1791
1792 1792 $ hg init problematicencoding
1793 1793 $ cd problematicencoding
1794 1794
1795 1795 $ $PYTHON > setup.sh <<EOF
1796 1796 > print(u'''
1797 1797 > echo a > text
1798 1798 > hg add text
1799 1799 > hg --encoding utf-8 commit -u '\u30A2' -m none
1800 1800 > echo b > text
1801 1801 > hg --encoding utf-8 commit -u '\u30C2' -m none
1802 1802 > echo c > text
1803 1803 > hg --encoding utf-8 commit -u none -m '\u30A2'
1804 1804 > echo d > text
1805 1805 > hg --encoding utf-8 commit -u none -m '\u30C2'
1806 1806 > '''.encode('utf-8'))
1807 1807 > EOF
1808 1808 $ sh < setup.sh
1809 1809
1810 1810 test in problematic encoding
1811 1811 $ $PYTHON > test.sh <<EOF
1812 1812 > print(u'''
1813 1813 > hg --encoding cp932 log --template '{rev}\\n' -u '\u30A2'
1814 1814 > echo ====
1815 1815 > hg --encoding cp932 log --template '{rev}\\n' -u '\u30C2'
1816 1816 > echo ====
1817 1817 > hg --encoding cp932 log --template '{rev}\\n' -k '\u30A2'
1818 1818 > echo ====
1819 1819 > hg --encoding cp932 log --template '{rev}\\n' -k '\u30C2'
1820 1820 > '''.encode('cp932'))
1821 1821 > EOF
1822 1822 $ sh < test.sh
1823 1823 0
1824 1824 ====
1825 1825 1
1826 1826 ====
1827 1827 2
1828 1828 0
1829 1829 ====
1830 1830 3
1831 1831 1
1832 1832
1833 1833 $ cd ..
1834 1834
1835 1835 test hg log on non-existent files and on directories
1836 1836 $ hg init issue1340
1837 1837 $ cd issue1340
1838 1838 $ mkdir d1; mkdir D2; mkdir D3.i; mkdir d4.hg; mkdir d5.d; mkdir .d6
1839 1839 $ echo 1 > d1/f1
1840 1840 $ echo 1 > D2/f1
1841 1841 $ echo 1 > D3.i/f1
1842 1842 $ echo 1 > d4.hg/f1
1843 1843 $ echo 1 > d5.d/f1
1844 1844 $ echo 1 > .d6/f1
1845 1845 $ hg -q add .
1846 1846 $ hg commit -m "a bunch of weird directories"
1847 1847 $ hg log -l1 d1/f1 | grep changeset
1848 1848 changeset: 0:65624cd9070a
1849 1849 $ hg log -l1 f1
1850 1850 $ hg log -l1 . | grep changeset
1851 1851 changeset: 0:65624cd9070a
1852 1852 $ hg log -l1 ./ | grep changeset
1853 1853 changeset: 0:65624cd9070a
1854 1854 $ hg log -l1 d1 | grep changeset
1855 1855 changeset: 0:65624cd9070a
1856 1856 $ hg log -l1 D2 | grep changeset
1857 1857 changeset: 0:65624cd9070a
1858 1858 $ hg log -l1 D2/f1 | grep changeset
1859 1859 changeset: 0:65624cd9070a
1860 1860 $ hg log -l1 D3.i | grep changeset
1861 1861 changeset: 0:65624cd9070a
1862 1862 $ hg log -l1 D3.i/f1 | grep changeset
1863 1863 changeset: 0:65624cd9070a
1864 1864 $ hg log -l1 d4.hg | grep changeset
1865 1865 changeset: 0:65624cd9070a
1866 1866 $ hg log -l1 d4.hg/f1 | grep changeset
1867 1867 changeset: 0:65624cd9070a
1868 1868 $ hg log -l1 d5.d | grep changeset
1869 1869 changeset: 0:65624cd9070a
1870 1870 $ hg log -l1 d5.d/f1 | grep changeset
1871 1871 changeset: 0:65624cd9070a
1872 1872 $ hg log -l1 .d6 | grep changeset
1873 1873 changeset: 0:65624cd9070a
1874 1874 $ hg log -l1 .d6/f1 | grep changeset
1875 1875 changeset: 0:65624cd9070a
1876 1876
1877 1877 issue3772: hg log -r :null showing revision 0 as well
1878 1878
1879 1879 $ hg log -r :null
1880 1880 changeset: 0:65624cd9070a
1881 1881 tag: tip
1882 1882 user: test
1883 1883 date: Thu Jan 01 00:00:00 1970 +0000
1884 1884 summary: a bunch of weird directories
1885 1885
1886 1886 changeset: -1:000000000000
1887 1887 user:
1888 1888 date: Thu Jan 01 00:00:00 1970 +0000
1889 1889
1890 1890 $ hg log -r null:null
1891 1891 changeset: -1:000000000000
1892 1892 user:
1893 1893 date: Thu Jan 01 00:00:00 1970 +0000
1894 1894
1895 1895 working-directory revision requires special treatment
1896 1896
1897 1897 clean:
1898 1898
1899 1899 $ hg log -r 'wdir()' --debug
1900 1900 changeset: 2147483647:ffffffffffffffffffffffffffffffffffffffff
1901 1901 phase: draft
1902 1902 parent: 0:65624cd9070a035fa7191a54f2b8af39f16b0c08
1903 1903 parent: -1:0000000000000000000000000000000000000000
1904 1904 user: test
1905 1905 date: [A-Za-z0-9:+ ]+ (re)
1906 1906 extra: branch=default
1907 1907
1908 1908 $ hg log -r 'wdir()' -p --stat
1909 1909 changeset: 2147483647:ffffffffffff
1910 1910 parent: 0:65624cd9070a
1911 1911 user: test
1912 1912 date: [A-Za-z0-9:+ ]+ (re)
1913 1913
1914 1914
1915 1915
1916 1916
1917 1917 dirty:
1918 1918
1919 1919 $ echo 2 >> d1/f1
1920 1920 $ echo 2 > d1/f2
1921 1921 $ hg add d1/f2
1922 1922 $ hg remove .d6/f1
1923 1923 $ hg status
1924 1924 M d1/f1
1925 1925 A d1/f2
1926 1926 R .d6/f1
1927 1927
1928 1928 $ hg log -r 'wdir()'
1929 1929 changeset: 2147483647:ffffffffffff
1930 1930 parent: 0:65624cd9070a
1931 1931 user: test
1932 1932 date: [A-Za-z0-9:+ ]+ (re)
1933 1933
1934 1934 $ hg log -r 'wdir()' -q
1935 1935 2147483647:ffffffffffff
1936 1936
1937 1937 $ hg log -r 'wdir()' --debug
1938 1938 changeset: 2147483647:ffffffffffffffffffffffffffffffffffffffff
1939 1939 phase: draft
1940 1940 parent: 0:65624cd9070a035fa7191a54f2b8af39f16b0c08
1941 1941 parent: -1:0000000000000000000000000000000000000000
1942 1942 user: test
1943 1943 date: [A-Za-z0-9:+ ]+ (re)
1944 1944 files: d1/f1
1945 1945 files+: d1/f2
1946 1946 files-: .d6/f1
1947 1947 extra: branch=default
1948 1948
1949 1949 $ hg log -r 'wdir()' -p --stat --git
1950 1950 changeset: 2147483647:ffffffffffff
1951 1951 parent: 0:65624cd9070a
1952 1952 user: test
1953 1953 date: [A-Za-z0-9:+ ]+ (re)
1954 1954
1955 1955 .d6/f1 | 1 -
1956 1956 d1/f1 | 1 +
1957 1957 d1/f2 | 1 +
1958 1958 3 files changed, 2 insertions(+), 1 deletions(-)
1959 1959
1960 1960 diff --git a/.d6/f1 b/.d6/f1
1961 1961 deleted file mode 100644
1962 1962 --- a/.d6/f1
1963 1963 +++ /dev/null
1964 1964 @@ -1,1 +0,0 @@
1965 1965 -1
1966 1966 diff --git a/d1/f1 b/d1/f1
1967 1967 --- a/d1/f1
1968 1968 +++ b/d1/f1
1969 1969 @@ -1,1 +1,2 @@
1970 1970 1
1971 1971 +2
1972 1972 diff --git a/d1/f2 b/d1/f2
1973 1973 new file mode 100644
1974 1974 --- /dev/null
1975 1975 +++ b/d1/f2
1976 1976 @@ -0,0 +1,1 @@
1977 1977 +2
1978 1978
1979 1979 $ hg log -r 'wdir()' -Tjson
1980 1980 [
1981 1981 {
1982 1982 "rev": null,
1983 1983 "node": null,
1984 1984 "branch": "default",
1985 1985 "phase": "draft",
1986 1986 "user": "test",
1987 1987 "date": [*, 0], (glob)
1988 1988 "desc": "",
1989 1989 "bookmarks": [],
1990 1990 "tags": [],
1991 1991 "parents": ["65624cd9070a035fa7191a54f2b8af39f16b0c08"]
1992 1992 }
1993 1993 ]
1994 1994
1995 1995 $ hg log -r 'wdir()' -Tjson -q
1996 1996 [
1997 1997 {
1998 1998 "rev": null,
1999 1999 "node": null
2000 2000 }
2001 2001 ]
2002 2002
2003 2003 $ hg log -r 'wdir()' -Tjson --debug
2004 2004 [
2005 2005 {
2006 2006 "rev": null,
2007 2007 "node": null,
2008 2008 "branch": "default",
2009 2009 "phase": "draft",
2010 2010 "user": "test",
2011 2011 "date": [*, 0], (glob)
2012 2012 "desc": "",
2013 2013 "bookmarks": [],
2014 2014 "tags": [],
2015 2015 "parents": ["65624cd9070a035fa7191a54f2b8af39f16b0c08"],
2016 2016 "manifest": null,
2017 2017 "extra": {"branch": "default"},
2018 2018 "modified": ["d1/f1"],
2019 2019 "added": ["d1/f2"],
2020 2020 "removed": [".d6/f1"]
2021 2021 }
2022 2022 ]
2023 2023
2024 2024 $ hg revert -aqC
2025 2025
2026 2026 Check that adding an arbitrary name shows up in log automatically
2027 2027
2028 2028 $ cat > ../names.py <<EOF
2029 2029 > """A small extension to test adding arbitrary names to a repo"""
2030 2030 > from __future__ import absolute_import
2031 2031 > from mercurial import namespaces
2032 2032 >
2033 2033 > def reposetup(ui, repo):
2034 2034 > foo = {'foo': repo[0].node()}
2035 2035 > names = lambda r: foo.keys()
2036 2036 > namemap = lambda r, name: foo.get(name)
2037 2037 > nodemap = lambda r, node: [name for name, n in foo.iteritems()
2038 2038 > if n == node]
2039 2039 > ns = namespaces.namespace(
2040 2040 > "bars", templatename="bar", logname="barlog",
2041 2041 > colorname="barcolor", listnames=names, namemap=namemap,
2042 2042 > nodemap=nodemap)
2043 2043 >
2044 2044 > repo.names.addnamespace(ns)
2045 2045 > EOF
2046 2046
2047 2047 $ hg --config extensions.names=../names.py log -r 0
2048 2048 changeset: 0:65624cd9070a
2049 2049 tag: tip
2050 2050 barlog: foo
2051 2051 user: test
2052 2052 date: Thu Jan 01 00:00:00 1970 +0000
2053 2053 summary: a bunch of weird directories
2054 2054
2055 2055 $ hg --config extensions.names=../names.py \
2056 2056 > --config extensions.color= --config color.log.barcolor=red \
2057 2057 > --color=always log -r 0
2058 2058 \x1b[0;33mchangeset: 0:65624cd9070a\x1b[0m (esc)
2059 2059 tag: tip
2060 2060 \x1b[0;31mbarlog: foo\x1b[0m (esc)
2061 2061 user: test
2062 2062 date: Thu Jan 01 00:00:00 1970 +0000
2063 2063 summary: a bunch of weird directories
2064 2064
2065 2065 $ hg --config extensions.names=../names.py log -r 0 --template '{bars}\n'
2066 2066 foo
2067 2067
2068 2068 $ cd ..
2069 2069
2070 2070 hg log -f dir across branches
2071 2071
2072 2072 $ hg init acrossbranches
2073 2073 $ cd acrossbranches
2074 2074 $ mkdir d
2075 2075 $ echo a > d/a && hg ci -Aqm a
2076 2076 $ echo b > d/a && hg ci -Aqm b
2077 2077 $ hg up -q 0
2078 2078 $ echo b > d/a && hg ci -Aqm c
2079 2079 $ hg log -f d -T '{desc}' -G
2080 2080 @ c
2081 2081 |
2082 2082 o a
2083 2083
2084 2084 Ensure that largefiles doesn't interfere with following a normal file
2085 2085 $ hg --config extensions.largefiles= log -f d -T '{desc}' -G
2086 2086 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
2087 2087 @ c
2088 2088 |
2089 2089 o a
2090 2090
2091 2091 $ hg log -f d/a -T '{desc}' -G
2092 2092 @ c
2093 2093 |
2094 2094 o a
2095 2095
2096 2096 $ cd ..
2097 2097
2098 2098 hg log -f with linkrev pointing to another branch
2099 2099 -------------------------------------------------
2100 2100
2101 2101 create history with a filerev whose linkrev points to another branch
2102 2102
2103 2103 $ hg init branchedlinkrev
2104 2104 $ cd branchedlinkrev
2105 2105 $ echo 1 > a
2106 2106 $ hg commit -Am 'content1'
2107 2107 adding a
2108 2108 $ echo 2 > a
2109 2109 $ hg commit -m 'content2'
2110 2110 $ hg up --rev 'desc(content1)'
2111 2111 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2112 2112 $ echo unrelated > unrelated
2113 2113 $ hg commit -Am 'unrelated'
2114 2114 adding unrelated
2115 2115 created new head
2116 2116 $ hg graft -r 'desc(content2)'
2117 2117 grafting 1:2294ae80ad84 "content2"
2118 2118 $ echo 3 > a
2119 2119 $ hg commit -m 'content3'
2120 2120 $ hg log -G
2121 2121 @ changeset: 4:50b9b36e9c5d
2122 2122 | tag: tip
2123 2123 | user: test
2124 2124 | date: Thu Jan 01 00:00:00 1970 +0000
2125 2125 | summary: content3
2126 2126 |
2127 2127 o changeset: 3:15b2327059e5
2128 2128 | user: test
2129 2129 | date: Thu Jan 01 00:00:00 1970 +0000
2130 2130 | summary: content2
2131 2131 |
2132 2132 o changeset: 2:2029acd1168c
2133 2133 | parent: 0:ae0a3c9f9e95
2134 2134 | user: test
2135 2135 | date: Thu Jan 01 00:00:00 1970 +0000
2136 2136 | summary: unrelated
2137 2137 |
2138 2138 | o changeset: 1:2294ae80ad84
2139 2139 |/ user: test
2140 2140 | date: Thu Jan 01 00:00:00 1970 +0000
2141 2141 | summary: content2
2142 2142 |
2143 2143 o changeset: 0:ae0a3c9f9e95
2144 2144 user: test
2145 2145 date: Thu Jan 01 00:00:00 1970 +0000
2146 2146 summary: content1
2147 2147
2148 2148
2149 2149 log -f on the file should list the graft result.
2150 2150
2151 2151 $ hg log -Gf a
2152 2152 @ changeset: 4:50b9b36e9c5d
2153 2153 | tag: tip
2154 2154 | user: test
2155 2155 | date: Thu Jan 01 00:00:00 1970 +0000
2156 2156 | summary: content3
2157 2157 |
2158 2158 o changeset: 3:15b2327059e5
2159 2159 : user: test
2160 2160 : date: Thu Jan 01 00:00:00 1970 +0000
2161 2161 : summary: content2
2162 2162 :
2163 2163 o changeset: 0:ae0a3c9f9e95
2164 2164 user: test
2165 2165 date: Thu Jan 01 00:00:00 1970 +0000
2166 2166 summary: content1
2167 2167
2168 2168
2169 2169 plain log lists the original version
2170 2170 (XXX we should probably list both)
2171 2171
2172 2172 $ hg log -G a
2173 2173 @ changeset: 4:50b9b36e9c5d
2174 2174 : tag: tip
2175 2175 : user: test
2176 2176 : date: Thu Jan 01 00:00:00 1970 +0000
2177 2177 : summary: content3
2178 2178 :
2179 2179 : o changeset: 1:2294ae80ad84
2180 2180 :/ user: test
2181 2181 : date: Thu Jan 01 00:00:00 1970 +0000
2182 2182 : summary: content2
2183 2183 :
2184 2184 o changeset: 0:ae0a3c9f9e95
2185 2185 user: test
2186 2186 date: Thu Jan 01 00:00:00 1970 +0000
2187 2187 summary: content1
2188 2188
2189 2189
2190 2190 hg log -f from the grafted changeset
2191 2191 (The bootstrap should properly take the topology in account)
2192 2192
2193 2193 $ hg up 'desc(content3)^'
2194 2194 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2195 2195 $ hg log -Gf a
2196 2196 @ changeset: 3:15b2327059e5
2197 2197 : user: test
2198 2198 : date: Thu Jan 01 00:00:00 1970 +0000
2199 2199 : summary: content2
2200 2200 :
2201 2201 o changeset: 0:ae0a3c9f9e95
2202 2202 user: test
2203 2203 date: Thu Jan 01 00:00:00 1970 +0000
2204 2204 summary: content1
2205 2205
2206 2206
2207 2207 Test that we use the first non-hidden changeset in that case.
2208 2208
2209 2209 (hide the changeset)
2210 2210
2211 2211 $ hg log -T '{node}\n' -r 1
2212 2212 2294ae80ad8447bc78383182eeac50cb049df623
2213 2213 $ hg debugobsolete 2294ae80ad8447bc78383182eeac50cb049df623
2214 2214 obsoleted 1 changesets
2215 2215 $ hg log -G
2216 2216 o changeset: 4:50b9b36e9c5d
2217 2217 | tag: tip
2218 2218 | user: test
2219 2219 | date: Thu Jan 01 00:00:00 1970 +0000
2220 2220 | summary: content3
2221 2221 |
2222 2222 @ changeset: 3:15b2327059e5
2223 2223 | user: test
2224 2224 | date: Thu Jan 01 00:00:00 1970 +0000
2225 2225 | summary: content2
2226 2226 |
2227 2227 o changeset: 2:2029acd1168c
2228 2228 | parent: 0:ae0a3c9f9e95
2229 2229 | user: test
2230 2230 | date: Thu Jan 01 00:00:00 1970 +0000
2231 2231 | summary: unrelated
2232 2232 |
2233 2233 o changeset: 0:ae0a3c9f9e95
2234 2234 user: test
2235 2235 date: Thu Jan 01 00:00:00 1970 +0000
2236 2236 summary: content1
2237 2237
2238 2238
2239 2239 Check that log on the file does not drop the file revision.
2240 2240
2241 2241 $ hg log -G a
2242 2242 o changeset: 4:50b9b36e9c5d
2243 2243 | tag: tip
2244 2244 | user: test
2245 2245 | date: Thu Jan 01 00:00:00 1970 +0000
2246 2246 | summary: content3
2247 2247 |
2248 2248 @ changeset: 3:15b2327059e5
2249 2249 : user: test
2250 2250 : date: Thu Jan 01 00:00:00 1970 +0000
2251 2251 : summary: content2
2252 2252 :
2253 2253 o changeset: 0:ae0a3c9f9e95
2254 2254 user: test
2255 2255 date: Thu Jan 01 00:00:00 1970 +0000
2256 2256 summary: content1
2257 2257
2258 2258
2259 2259 Even when a head revision is linkrev-shadowed.
2260 2260
2261 2261 $ hg log -T '{node}\n' -r 4
2262 2262 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
2263 2263 $ hg debugobsolete 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
2264 2264 obsoleted 1 changesets
2265 2265 $ hg log -G a
2266 2266 @ changeset: 3:15b2327059e5
2267 2267 : tag: tip
2268 2268 : user: test
2269 2269 : date: Thu Jan 01 00:00:00 1970 +0000
2270 2270 : summary: content2
2271 2271 :
2272 2272 o changeset: 0:ae0a3c9f9e95
2273 2273 user: test
2274 2274 date: Thu Jan 01 00:00:00 1970 +0000
2275 2275 summary: content1
2276 2276
2277 2277
2278 2278 $ cd ..
2279 2279
2280 2280 Even when the file revision is missing from some head:
2281 2281
2282 2282 $ hg init issue4490
2283 2283 $ cd issue4490
2284 2284 $ echo '[experimental]' >> .hg/hgrc
2285 2285 $ echo 'stabilization=createmarkers' >> .hg/hgrc
2286 2286 $ echo a > a
2287 2287 $ hg ci -Am0
2288 2288 adding a
2289 2289 $ echo b > b
2290 2290 $ hg ci -Am1
2291 2291 adding b
2292 2292 $ echo B > b
2293 2293 $ hg ci --amend -m 1
2294 2294 $ hg up 0
2295 2295 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2296 2296 $ echo c > c
2297 2297 $ hg ci -Am2
2298 2298 adding c
2299 2299 created new head
2300 2300 $ hg up 'head() and not .'
2301 2301 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
2302 2302 $ hg log -G
2303 o changeset: 4:db815d6d32e6
2303 o changeset: 3:db815d6d32e6
2304 2304 | tag: tip
2305 2305 | parent: 0:f7b1eb17ad24
2306 2306 | user: test
2307 2307 | date: Thu Jan 01 00:00:00 1970 +0000
2308 2308 | summary: 2
2309 2309 |
2310 | @ changeset: 3:9bc8ce7f9356
2310 | @ changeset: 2:9bc8ce7f9356
2311 2311 |/ parent: 0:f7b1eb17ad24
2312 2312 | user: test
2313 2313 | date: Thu Jan 01 00:00:00 1970 +0000
2314 2314 | summary: 1
2315 2315 |
2316 2316 o changeset: 0:f7b1eb17ad24
2317 2317 user: test
2318 2318 date: Thu Jan 01 00:00:00 1970 +0000
2319 2319 summary: 0
2320 2320
2321 2321 $ hg log -f -G b
2322 @ changeset: 3:9bc8ce7f9356
2322 @ changeset: 2:9bc8ce7f9356
2323 2323 | parent: 0:f7b1eb17ad24
2324 2324 ~ user: test
2325 2325 date: Thu Jan 01 00:00:00 1970 +0000
2326 2326 summary: 1
2327 2327
2328 2328 $ hg log -G b
2329 @ changeset: 3:9bc8ce7f9356
2329 @ changeset: 2:9bc8ce7f9356
2330 2330 | parent: 0:f7b1eb17ad24
2331 2331 ~ user: test
2332 2332 date: Thu Jan 01 00:00:00 1970 +0000
2333 2333 summary: 1
2334 2334
2335 2335 $ cd ..
2336 2336
2337 2337 Check proper report when the manifest changes but not the file issue4499
2338 2338 ------------------------------------------------------------------------
2339 2339
2340 2340 $ hg init issue4499
2341 2341 $ cd issue4499
2342 2342 $ 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
2343 2343 > echo 1 > $f;
2344 2344 > hg add $f;
2345 2345 > done
2346 2346 $ hg commit -m 'A1B1C1'
2347 2347 $ echo 2 > A
2348 2348 $ echo 2 > B
2349 2349 $ echo 2 > C
2350 2350 $ hg commit -m 'A2B2C2'
2351 2351 $ hg up 0
2352 2352 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
2353 2353 $ echo 3 > A
2354 2354 $ echo 2 > B
2355 2355 $ echo 2 > C
2356 2356 $ hg commit -m 'A3B2C2'
2357 2357 created new head
2358 2358
2359 2359 $ hg log -G
2360 2360 @ changeset: 2:fe5fc3d0eb17
2361 2361 | tag: tip
2362 2362 | parent: 0:abf4f0e38563
2363 2363 | user: test
2364 2364 | date: Thu Jan 01 00:00:00 1970 +0000
2365 2365 | summary: A3B2C2
2366 2366 |
2367 2367 | o changeset: 1:07dcc6b312c0
2368 2368 |/ user: test
2369 2369 | date: Thu Jan 01 00:00:00 1970 +0000
2370 2370 | summary: A2B2C2
2371 2371 |
2372 2372 o changeset: 0:abf4f0e38563
2373 2373 user: test
2374 2374 date: Thu Jan 01 00:00:00 1970 +0000
2375 2375 summary: A1B1C1
2376 2376
2377 2377
2378 2378 Log -f on B should reports current changesets
2379 2379
2380 2380 $ hg log -fG B
2381 2381 @ changeset: 2:fe5fc3d0eb17
2382 2382 | tag: tip
2383 2383 | parent: 0:abf4f0e38563
2384 2384 | user: test
2385 2385 | date: Thu Jan 01 00:00:00 1970 +0000
2386 2386 | summary: A3B2C2
2387 2387 |
2388 2388 o changeset: 0:abf4f0e38563
2389 2389 user: test
2390 2390 date: Thu Jan 01 00:00:00 1970 +0000
2391 2391 summary: A1B1C1
2392 2392
2393 2393 $ cd ..
@@ -1,1780 +1,1765 b''
1 1 This test file test the various templates related to obsmarkers.
2 2
3 3 Global setup
4 4 ============
5 5
6 6 $ . $TESTDIR/testlib/obsmarker-common.sh
7 7 $ cat >> $HGRCPATH <<EOF
8 8 > [ui]
9 9 > interactive = true
10 10 > [phases]
11 11 > publish=False
12 12 > [experimental]
13 13 > stabilization=all
14 14 > [templates]
15 15 > obsfatesuccessors = "{if(successors, " as ")}{join(successors, ", ")}"
16 16 > obsfateverb = "{obsfateverb(successors)}"
17 17 > obsfateusers = "{if(obsfateusers(markers), " by {join(obsfateusers(markers), ", ")}")}"
18 18 > obsfatedate = "{if(obsfatedate(markers), "{ifeq(min(obsfatedate(markers)), max(obsfatedate(markers)), " (at {min(obsfatedate(markers))|isodate})", " (between {min(obsfatedate(markers))|isodate} and {max(obsfatedate(markers))|isodate})")}")}"
19 19 > obsfate = "{obsfateverb}{obsfatesuccessors}{obsfateusers}{obsfatedate}; "
20 20 > [alias]
21 21 > tlog = log -G -T '{node|short}\
22 22 > {if(predecessors, "\n Predecessors: {predecessors}")}\
23 23 > {if(predecessors, "\n semi-colon: {join(predecessors, "; ")}")}\
24 24 > {if(predecessors, "\n json: {predecessors|json}")}\
25 25 > {if(predecessors, "\n map: {join(predecessors % "{rev}:{node}", " ")}")}\
26 26 > {if(successorssets, "\n Successors: {successorssets}")}\
27 27 > {if(successorssets, "\n multi-line: {join(successorssets, "\n multi-line: ")}")}\
28 28 > {if(successorssets, "\n json: {successorssets|json}")}\n'
29 29 > fatelog = log -G -T '{node|short}\n{if(succsandmarkers, " Obsfate: {succsandmarkers % "{obsfate}"} \n" )}'
30 30 > fatelogjson = log -G -T '{node|short}\n{if(succsandmarkers, " Obsfate: {succsandmarkers|json}\n")}'
31 31 > EOF
32 32
33 33 Test templates on amended commit
34 34 ================================
35 35
36 36 Test setup
37 37 ----------
38 38
39 39 $ hg init $TESTTMP/templates-local-amend
40 40 $ cd $TESTTMP/templates-local-amend
41 41 $ mkcommit ROOT
42 42 $ mkcommit A0
43 43 $ echo 42 >> A0
44 44 $ HGUSER=test1 hg commit --amend -m "A1" --config devel.default-date="1234567890 0"
45 45 $ HGUSER=test2 hg commit --amend -m "A2" --config devel.default-date="987654321 0"
46 46
47 47 $ hg log --hidden -G
48 @ changeset: 4:d004c8f274b9
48 @ changeset: 3:d004c8f274b9
49 49 | tag: tip
50 50 | parent: 0:ea207398892e
51 51 | user: test
52 52 | date: Thu Jan 01 00:00:00 1970 +0000
53 53 | summary: A2
54 54 |
55 | x changeset: 3:a468dc9b3633
55 | x changeset: 2:a468dc9b3633
56 56 |/ parent: 0:ea207398892e
57 57 | user: test
58 58 | date: Thu Jan 01 00:00:00 1970 +0000
59 59 | summary: A1
60 60 |
61 | x changeset: 2:f137d23bb3e1
62 | | user: test
63 | | date: Thu Jan 01 00:00:00 1970 +0000
64 | | summary: temporary amend commit for 471f378eab4c
65 | |
66 61 | x changeset: 1:471f378eab4c
67 62 |/ user: test
68 63 | date: Thu Jan 01 00:00:00 1970 +0000
69 64 | summary: A0
70 65 |
71 66 o changeset: 0:ea207398892e
72 67 user: test
73 68 date: Thu Jan 01 00:00:00 1970 +0000
74 69 summary: ROOT
75 70
76 71 Check templates
77 72 ---------------
78 73 $ hg up 'desc(A0)' --hidden
79 74 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
80 75
81 76 Predecessors template should show current revision as it is the working copy
82 77 $ hg tlog
83 78 o d004c8f274b9
84 79 | Predecessors: 1:471f378eab4c
85 80 | semi-colon: 1:471f378eab4c
86 81 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
87 82 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
88 83 | @ 471f378eab4c
89 |/ Successors: 4:d004c8f274b9
90 | multi-line: 4:d004c8f274b9
84 |/ Successors: 3:d004c8f274b9
85 | multi-line: 3:d004c8f274b9
91 86 | json: [["d004c8f274b9ec480a47a93c10dac5eee63adb78"]]
92 87 o ea207398892e
93 88
94 89 $ hg fatelog -q --traceback
95 90 o d004c8f274b9
96 91 |
97 92 | @ 471f378eab4c
98 |/ Obsfate: rewritten as 4:d004c8f274b9 by test1, test2 (between 2001-04-19 04:25 +0000 and 2009-02-13 23:31 +0000);
93 |/ Obsfate: rewritten as 3:d004c8f274b9 by test1, test2 (between 2001-04-19 04:25 +0000 and 2009-02-13 23:31 +0000);
99 94 o ea207398892e
100 95
101 96 $ hg fatelog
102 97 o d004c8f274b9
103 98 |
104 99 | @ 471f378eab4c
105 |/ Obsfate: rewritten as 4:d004c8f274b9 by test1, test2 (between 2001-04-19 04:25 +0000 and 2009-02-13 23:31 +0000);
100 |/ Obsfate: rewritten as 3:d004c8f274b9 by test1, test2 (between 2001-04-19 04:25 +0000 and 2009-02-13 23:31 +0000);
106 101 o ea207398892e
107 102
108 103 $ hg fatelog -v
109 104 o d004c8f274b9
110 105 |
111 106 | @ 471f378eab4c
112 |/ Obsfate: rewritten as 4:d004c8f274b9 by test1, test2 (between 2001-04-19 04:25 +0000 and 2009-02-13 23:31 +0000);
107 |/ Obsfate: rewritten as 3:d004c8f274b9 by test1, test2 (between 2001-04-19 04:25 +0000 and 2009-02-13 23:31 +0000);
113 108 o ea207398892e
114 109
115 110 $ hg up 'desc(A1)' --hidden
116 111 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 112
118 113 Predecessors template should show current revision as it is the working copy
119 114 $ hg tlog
120 115 o d004c8f274b9
121 | Predecessors: 3:a468dc9b3633
122 | semi-colon: 3:a468dc9b3633
116 | Predecessors: 2:a468dc9b3633
117 | semi-colon: 2:a468dc9b3633
123 118 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
124 | map: 3:a468dc9b36338b14fdb7825f55ce3df4e71517ad
119 | map: 2:a468dc9b36338b14fdb7825f55ce3df4e71517ad
125 120 | @ a468dc9b3633
126 |/ Successors: 4:d004c8f274b9
127 | multi-line: 4:d004c8f274b9
121 |/ Successors: 3:d004c8f274b9
122 | multi-line: 3:d004c8f274b9
128 123 | json: [["d004c8f274b9ec480a47a93c10dac5eee63adb78"]]
129 124 o ea207398892e
130 125
131 126 $ hg fatelog -v
132 127 o d004c8f274b9
133 128 |
134 129 | @ a468dc9b3633
135 |/ Obsfate: rewritten as 4:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000);
130 |/ Obsfate: rewritten as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000);
136 131 o ea207398892e
137 132
138 133 Predecessors template should show all the predecessors as we force their display
139 134 with --hidden
140 135 $ hg tlog --hidden
141 136 o d004c8f274b9
142 | Predecessors: 3:a468dc9b3633
143 | semi-colon: 3:a468dc9b3633
137 | Predecessors: 2:a468dc9b3633
138 | semi-colon: 2:a468dc9b3633
144 139 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
145 | map: 3:a468dc9b36338b14fdb7825f55ce3df4e71517ad
140 | map: 2:a468dc9b36338b14fdb7825f55ce3df4e71517ad
146 141 | @ a468dc9b3633
147 142 |/ Predecessors: 1:471f378eab4c
148 143 | semi-colon: 1:471f378eab4c
149 144 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
150 145 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
151 | Successors: 4:d004c8f274b9
152 | multi-line: 4:d004c8f274b9
146 | Successors: 3:d004c8f274b9
147 | multi-line: 3:d004c8f274b9
153 148 | json: [["d004c8f274b9ec480a47a93c10dac5eee63adb78"]]
154 | x f137d23bb3e1
155 | |
156 149 | x 471f378eab4c
157 |/ Successors: 3:a468dc9b3633
158 | multi-line: 3:a468dc9b3633
150 |/ Successors: 2:a468dc9b3633
151 | multi-line: 2:a468dc9b3633
159 152 | json: [["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]]
160 153 o ea207398892e
161 154
162 155 $ hg fatelog --hidden -q
163 156 o d004c8f274b9
164 157 |
165 158 | @ a468dc9b3633
166 |/ Obsfate: rewritten as 4:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000);
167 | x f137d23bb3e1
168 | | Obsfate: pruned by test1 (at 2009-02-13 23:31 +0000);
159 |/ Obsfate: rewritten as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000);
169 160 | x 471f378eab4c
170 |/ Obsfate: rewritten as 3:a468dc9b3633 by test1 (at 2009-02-13 23:31 +0000);
161 |/ Obsfate: rewritten as 2:a468dc9b3633 by test1 (at 2009-02-13 23:31 +0000);
171 162 o ea207398892e
172 163
173 164
174 165 Predecessors template shouldn't show anything as all obsolete commit are not
175 166 visible.
176 167 $ hg up 'desc(A2)'
177 168 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
178 169 $ hg tlog
179 170 @ d004c8f274b9
180 171 |
181 172 o ea207398892e
182 173
183 174 $ hg tlog --hidden
184 175 @ d004c8f274b9
185 | Predecessors: 3:a468dc9b3633
186 | semi-colon: 3:a468dc9b3633
176 | Predecessors: 2:a468dc9b3633
177 | semi-colon: 2:a468dc9b3633
187 178 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
188 | map: 3:a468dc9b36338b14fdb7825f55ce3df4e71517ad
179 | map: 2:a468dc9b36338b14fdb7825f55ce3df4e71517ad
189 180 | x a468dc9b3633
190 181 |/ Predecessors: 1:471f378eab4c
191 182 | semi-colon: 1:471f378eab4c
192 183 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
193 184 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
194 | Successors: 4:d004c8f274b9
195 | multi-line: 4:d004c8f274b9
185 | Successors: 3:d004c8f274b9
186 | multi-line: 3:d004c8f274b9
196 187 | json: [["d004c8f274b9ec480a47a93c10dac5eee63adb78"]]
197 | x f137d23bb3e1
198 | |
199 188 | x 471f378eab4c
200 |/ Successors: 3:a468dc9b3633
201 | multi-line: 3:a468dc9b3633
189 |/ Successors: 2:a468dc9b3633
190 | multi-line: 2:a468dc9b3633
202 191 | json: [["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]]
203 192 o ea207398892e
204 193
205 194 $ hg fatelog -v
206 195 @ d004c8f274b9
207 196 |
208 197 o ea207398892e
209 198
210 199
211 200 $ hg fatelog -v --hidden
212 201 @ d004c8f274b9
213 202 |
214 203 | x a468dc9b3633
215 |/ Obsfate: rewritten as 4:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000);
216 | x f137d23bb3e1
217 | | Obsfate: pruned by test1 (at 2009-02-13 23:31 +0000);
204 |/ Obsfate: rewritten as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000);
218 205 | x 471f378eab4c
219 |/ Obsfate: rewritten as 3:a468dc9b3633 by test1 (at 2009-02-13 23:31 +0000);
206 |/ Obsfate: rewritten as 2:a468dc9b3633 by test1 (at 2009-02-13 23:31 +0000);
220 207 o ea207398892e
221 208
222 209 $ hg fatelogjson --hidden
223 210 @ d004c8f274b9
224 211 |
225 212 | x a468dc9b3633
226 213 |/ Obsfate: [{"markers": [["a468dc9b36338b14fdb7825f55ce3df4e71517ad", ["d004c8f274b9ec480a47a93c10dac5eee63adb78"], 0, [["user", "test2"]], [987654321.0, 0], null]], "successors": ["d004c8f274b9ec480a47a93c10dac5eee63adb78"]}]
227 | x f137d23bb3e1
228 | | Obsfate: [{"markers": [["f137d23bb3e11dc1daeb6264fac9cb2433782e15", [], 0, [["user", "test1"]], [1234567890.0, 0], ["471f378eab4c5e25f6c77f785b27c936efb22874"]]], "successors": []}]
229 214 | x 471f378eab4c
230 215 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"], 0, [["user", "test1"]], [1234567890.0, 0], null]], "successors": ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]}]
231 216 o ea207398892e
232 217
233 218 Test templates with splitted commit
234 219 ===================================
235 220
236 221 $ hg init $TESTTMP/templates-local-split
237 222 $ cd $TESTTMP/templates-local-split
238 223 $ mkcommit ROOT
239 224 $ echo 42 >> a
240 225 $ echo 43 >> b
241 226 $ hg commit -A -m "A0"
242 227 adding a
243 228 adding b
244 229 $ hg log --hidden -G
245 230 @ changeset: 1:471597cad322
246 231 | tag: tip
247 232 | user: test
248 233 | date: Thu Jan 01 00:00:00 1970 +0000
249 234 | summary: A0
250 235 |
251 236 o changeset: 0:ea207398892e
252 237 user: test
253 238 date: Thu Jan 01 00:00:00 1970 +0000
254 239 summary: ROOT
255 240
256 241 # Simulate split
257 242 $ hg up -r "desc(ROOT)"
258 243 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
259 244 $ echo 42 >> a
260 245 $ hg commit -A -m "A0"
261 246 adding a
262 247 created new head
263 248 $ echo 43 >> b
264 249 $ hg commit -A -m "A0"
265 250 adding b
266 251 $ hg debugobsolete `getid "1"` `getid "2"` `getid "3"`
267 252 obsoleted 1 changesets
268 253
269 254 $ hg log --hidden -G
270 255 @ changeset: 3:f257fde29c7a
271 256 | tag: tip
272 257 | user: test
273 258 | date: Thu Jan 01 00:00:00 1970 +0000
274 259 | summary: A0
275 260 |
276 261 o changeset: 2:337fec4d2edc
277 262 | parent: 0:ea207398892e
278 263 | user: test
279 264 | date: Thu Jan 01 00:00:00 1970 +0000
280 265 | summary: A0
281 266 |
282 267 | x changeset: 1:471597cad322
283 268 |/ user: test
284 269 | date: Thu Jan 01 00:00:00 1970 +0000
285 270 | summary: A0
286 271 |
287 272 o changeset: 0:ea207398892e
288 273 user: test
289 274 date: Thu Jan 01 00:00:00 1970 +0000
290 275 summary: ROOT
291 276
292 277 Check templates
293 278 ---------------
294 279
295 280 $ hg up 'obsolete()' --hidden
296 281 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
297 282
298 283 Predecessors template should show current revision as it is the working copy
299 284 $ hg tlog
300 285 o f257fde29c7a
301 286 | Predecessors: 1:471597cad322
302 287 | semi-colon: 1:471597cad322
303 288 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
304 289 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
305 290 o 337fec4d2edc
306 291 | Predecessors: 1:471597cad322
307 292 | semi-colon: 1:471597cad322
308 293 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
309 294 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
310 295 | @ 471597cad322
311 296 |/ Successors: 2:337fec4d2edc 3:f257fde29c7a
312 297 | multi-line: 2:337fec4d2edc 3:f257fde29c7a
313 298 | json: [["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"]]
314 299 o ea207398892e
315 300
316 301
317 302 $ hg fatelog
318 303 o f257fde29c7a
319 304 |
320 305 o 337fec4d2edc
321 306 |
322 307 | @ 471597cad322
323 308 |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a by test (at 1970-01-01 00:00 +0000);
324 309 o ea207398892e
325 310
326 311 $ hg up f257fde29c7a
327 312 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
328 313
329 314 Predecessors template should not show a predecessor as it's not displayed in
330 315 the log
331 316 $ hg tlog
332 317 @ f257fde29c7a
333 318 |
334 319 o 337fec4d2edc
335 320 |
336 321 o ea207398892e
337 322
338 323 Predecessors template should show both predecessors as we force their display
339 324 with --hidden
340 325 $ hg tlog --hidden
341 326 @ f257fde29c7a
342 327 | Predecessors: 1:471597cad322
343 328 | semi-colon: 1:471597cad322
344 329 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
345 330 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
346 331 o 337fec4d2edc
347 332 | Predecessors: 1:471597cad322
348 333 | semi-colon: 1:471597cad322
349 334 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
350 335 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
351 336 | x 471597cad322
352 337 |/ Successors: 2:337fec4d2edc 3:f257fde29c7a
353 338 | multi-line: 2:337fec4d2edc 3:f257fde29c7a
354 339 | json: [["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"]]
355 340 o ea207398892e
356 341
357 342
358 343 $ hg fatelog --hidden
359 344 @ f257fde29c7a
360 345 |
361 346 o 337fec4d2edc
362 347 |
363 348 | x 471597cad322
364 349 |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a by test (at 1970-01-01 00:00 +0000);
365 350 o ea207398892e
366 351
367 352 $ hg fatelogjson --hidden
368 353 @ f257fde29c7a
369 354 |
370 355 o 337fec4d2edc
371 356 |
372 357 | x 471597cad322
373 358 |/ Obsfate: [{"markers": [["471597cad322d1f659bb169751be9133dad92ef3", ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"]}]
374 359 o ea207398892e
375 360
376 361 Test templates with folded commit
377 362 =================================
378 363
379 364 Test setup
380 365 ----------
381 366
382 367 $ hg init $TESTTMP/templates-local-fold
383 368 $ cd $TESTTMP/templates-local-fold
384 369 $ mkcommit ROOT
385 370 $ mkcommit A0
386 371 $ mkcommit B0
387 372 $ hg log --hidden -G
388 373 @ changeset: 2:0dec01379d3b
389 374 | tag: tip
390 375 | user: test
391 376 | date: Thu Jan 01 00:00:00 1970 +0000
392 377 | summary: B0
393 378 |
394 379 o changeset: 1:471f378eab4c
395 380 | user: test
396 381 | date: Thu Jan 01 00:00:00 1970 +0000
397 382 | summary: A0
398 383 |
399 384 o changeset: 0:ea207398892e
400 385 user: test
401 386 date: Thu Jan 01 00:00:00 1970 +0000
402 387 summary: ROOT
403 388
404 389 Simulate a fold
405 390 $ hg up -r "desc(ROOT)"
406 391 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
407 392 $ echo "A0" > A0
408 393 $ echo "B0" > B0
409 394 $ hg commit -A -m "C0"
410 395 adding A0
411 396 adding B0
412 397 created new head
413 398 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(C0)"`
414 399 obsoleted 1 changesets
415 400 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(C0)"`
416 401 obsoleted 1 changesets
417 402
418 403 $ hg log --hidden -G
419 404 @ changeset: 3:eb5a0daa2192
420 405 | tag: tip
421 406 | parent: 0:ea207398892e
422 407 | user: test
423 408 | date: Thu Jan 01 00:00:00 1970 +0000
424 409 | summary: C0
425 410 |
426 411 | x changeset: 2:0dec01379d3b
427 412 | | user: test
428 413 | | date: Thu Jan 01 00:00:00 1970 +0000
429 414 | | summary: B0
430 415 | |
431 416 | x changeset: 1:471f378eab4c
432 417 |/ user: test
433 418 | date: Thu Jan 01 00:00:00 1970 +0000
434 419 | summary: A0
435 420 |
436 421 o changeset: 0:ea207398892e
437 422 user: test
438 423 date: Thu Jan 01 00:00:00 1970 +0000
439 424 summary: ROOT
440 425
441 426 Check templates
442 427 ---------------
443 428
444 429 $ hg up 'desc(A0)' --hidden
445 430 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
446 431
447 432 Predecessors template should show current revision as it is the working copy
448 433 $ hg tlog
449 434 o eb5a0daa2192
450 435 | Predecessors: 1:471f378eab4c
451 436 | semi-colon: 1:471f378eab4c
452 437 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
453 438 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
454 439 | @ 471f378eab4c
455 440 |/ Successors: 3:eb5a0daa2192
456 441 | multi-line: 3:eb5a0daa2192
457 442 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
458 443 o ea207398892e
459 444
460 445
461 446 $ hg fatelog
462 447 o eb5a0daa2192
463 448 |
464 449 | @ 471f378eab4c
465 450 |/ Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
466 451 o ea207398892e
467 452
468 453 $ hg up 'desc(B0)' --hidden
469 454 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
470 455
471 456 Predecessors template should show both predecessors as they should be both
472 457 displayed
473 458 $ hg tlog
474 459 o eb5a0daa2192
475 460 | Predecessors: 2:0dec01379d3b 1:471f378eab4c
476 461 | semi-colon: 2:0dec01379d3b; 1:471f378eab4c
477 462 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
478 463 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5 1:471f378eab4c5e25f6c77f785b27c936efb22874
479 464 | @ 0dec01379d3b
480 465 | | Successors: 3:eb5a0daa2192
481 466 | | multi-line: 3:eb5a0daa2192
482 467 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
483 468 | x 471f378eab4c
484 469 |/ Successors: 3:eb5a0daa2192
485 470 | multi-line: 3:eb5a0daa2192
486 471 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
487 472 o ea207398892e
488 473
489 474
490 475 $ hg fatelog
491 476 o eb5a0daa2192
492 477 |
493 478 | @ 0dec01379d3b
494 479 | | Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
495 480 | x 471f378eab4c
496 481 |/ Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
497 482 o ea207398892e
498 483
499 484 $ hg up 'desc(C0)'
500 485 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
501 486
502 487 Predecessors template should not show predecessors as they are not displayed in
503 488 the log
504 489 $ hg tlog
505 490 @ eb5a0daa2192
506 491 |
507 492 o ea207398892e
508 493
509 494 Predecessors template should show both predecessors as we force their display
510 495 with --hidden
511 496 $ hg tlog --hidden
512 497 @ eb5a0daa2192
513 498 | Predecessors: 2:0dec01379d3b 1:471f378eab4c
514 499 | semi-colon: 2:0dec01379d3b; 1:471f378eab4c
515 500 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
516 501 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5 1:471f378eab4c5e25f6c77f785b27c936efb22874
517 502 | x 0dec01379d3b
518 503 | | Successors: 3:eb5a0daa2192
519 504 | | multi-line: 3:eb5a0daa2192
520 505 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
521 506 | x 471f378eab4c
522 507 |/ Successors: 3:eb5a0daa2192
523 508 | multi-line: 3:eb5a0daa2192
524 509 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
525 510 o ea207398892e
526 511
527 512
528 513 $ hg fatelog --hidden
529 514 @ eb5a0daa2192
530 515 |
531 516 | x 0dec01379d3b
532 517 | | Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
533 518 | x 471f378eab4c
534 519 |/ Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
535 520 o ea207398892e
536 521
537 522
538 523 $ hg fatelogjson --hidden
539 524 @ eb5a0daa2192
540 525 |
541 526 | x 0dec01379d3b
542 527 | | Obsfate: [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]}]
543 528 | x 471f378eab4c
544 529 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]}]
545 530 o ea207398892e
546 531
547 532
548 533 Test templates with divergence
549 534 ==============================
550 535
551 536 Test setup
552 537 ----------
553 538
554 539 $ hg init $TESTTMP/templates-local-divergence
555 540 $ cd $TESTTMP/templates-local-divergence
556 541 $ mkcommit ROOT
557 542 $ mkcommit A0
558 543 $ hg commit --amend -m "A1"
559 544 $ hg log --hidden -G
560 545 @ changeset: 2:fdf9bde5129a
561 546 | tag: tip
562 547 | parent: 0:ea207398892e
563 548 | user: test
564 549 | date: Thu Jan 01 00:00:00 1970 +0000
565 550 | summary: A1
566 551 |
567 552 | x changeset: 1:471f378eab4c
568 553 |/ user: test
569 554 | date: Thu Jan 01 00:00:00 1970 +0000
570 555 | summary: A0
571 556 |
572 557 o changeset: 0:ea207398892e
573 558 user: test
574 559 date: Thu Jan 01 00:00:00 1970 +0000
575 560 summary: ROOT
576 561
577 562 $ hg update --hidden 'desc(A0)'
578 563 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
579 564 $ hg commit --amend -m "A2"
580 565 $ hg log --hidden -G
581 566 @ changeset: 3:65b757b745b9
582 567 | tag: tip
583 568 | parent: 0:ea207398892e
584 569 | user: test
585 570 | date: Thu Jan 01 00:00:00 1970 +0000
586 571 | instability: content-divergent
587 572 | summary: A2
588 573 |
589 574 | o changeset: 2:fdf9bde5129a
590 575 |/ parent: 0:ea207398892e
591 576 | user: test
592 577 | date: Thu Jan 01 00:00:00 1970 +0000
593 578 | instability: content-divergent
594 579 | summary: A1
595 580 |
596 581 | x changeset: 1:471f378eab4c
597 582 |/ user: test
598 583 | date: Thu Jan 01 00:00:00 1970 +0000
599 584 | summary: A0
600 585 |
601 586 o changeset: 0:ea207398892e
602 587 user: test
603 588 date: Thu Jan 01 00:00:00 1970 +0000
604 589 summary: ROOT
605 590
606 591 $ hg commit --amend -m 'A3'
607 592 $ hg log --hidden -G
608 593 @ changeset: 4:019fadeab383
609 594 | tag: tip
610 595 | parent: 0:ea207398892e
611 596 | user: test
612 597 | date: Thu Jan 01 00:00:00 1970 +0000
613 598 | instability: content-divergent
614 599 | summary: A3
615 600 |
616 601 | x changeset: 3:65b757b745b9
617 602 |/ parent: 0:ea207398892e
618 603 | user: test
619 604 | date: Thu Jan 01 00:00:00 1970 +0000
620 605 | summary: A2
621 606 |
622 607 | o changeset: 2:fdf9bde5129a
623 608 |/ parent: 0:ea207398892e
624 609 | user: test
625 610 | date: Thu Jan 01 00:00:00 1970 +0000
626 611 | instability: content-divergent
627 612 | summary: A1
628 613 |
629 614 | x changeset: 1:471f378eab4c
630 615 |/ user: test
631 616 | date: Thu Jan 01 00:00:00 1970 +0000
632 617 | summary: A0
633 618 |
634 619 o changeset: 0:ea207398892e
635 620 user: test
636 621 date: Thu Jan 01 00:00:00 1970 +0000
637 622 summary: ROOT
638 623
639 624
640 625 Check templates
641 626 ---------------
642 627
643 628 $ hg up 'desc(A0)' --hidden
644 629 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
645 630
646 631 Predecessors template should show current revision as it is the working copy
647 632 $ hg tlog
648 633 o 019fadeab383
649 634 | Predecessors: 1:471f378eab4c
650 635 | semi-colon: 1:471f378eab4c
651 636 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
652 637 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
653 638 | o fdf9bde5129a
654 639 |/ Predecessors: 1:471f378eab4c
655 640 | semi-colon: 1:471f378eab4c
656 641 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
657 642 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
658 643 | @ 471f378eab4c
659 644 |/ Successors: 2:fdf9bde5129a; 4:019fadeab383
660 645 | multi-line: 2:fdf9bde5129a
661 646 | multi-line: 4:019fadeab383
662 647 | json: [["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"]]
663 648 o ea207398892e
664 649
665 650 $ hg fatelog
666 651 o 019fadeab383
667 652 |
668 653 | o fdf9bde5129a
669 654 |/
670 655 | @ 471f378eab4c
671 656 |/ Obsfate: rewritten as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000); rewritten as 4:019fadeab383 by test (at 1970-01-01 00:00 +0000);
672 657 o ea207398892e
673 658
674 659 $ hg up 'desc(A1)'
675 660 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
676 661
677 662 Predecessors template should not show predecessors as they are not displayed in
678 663 the log
679 664 $ hg tlog
680 665 o 019fadeab383
681 666 |
682 667 | @ fdf9bde5129a
683 668 |/
684 669 o ea207398892e
685 670
686 671
687 672 $ hg fatelog
688 673 o 019fadeab383
689 674 |
690 675 | @ fdf9bde5129a
691 676 |/
692 677 o ea207398892e
693 678
694 679 Predecessors template should the predecessors as we force their display with
695 680 --hidden
696 681 $ hg tlog --hidden
697 682 o 019fadeab383
698 683 | Predecessors: 3:65b757b745b9
699 684 | semi-colon: 3:65b757b745b9
700 685 | json: ["65b757b745b935093c87a2bccd877521cccffcbd"]
701 686 | map: 3:65b757b745b935093c87a2bccd877521cccffcbd
702 687 | x 65b757b745b9
703 688 |/ Predecessors: 1:471f378eab4c
704 689 | semi-colon: 1:471f378eab4c
705 690 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
706 691 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
707 692 | Successors: 4:019fadeab383
708 693 | multi-line: 4:019fadeab383
709 694 | json: [["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"]]
710 695 | @ fdf9bde5129a
711 696 |/ Predecessors: 1:471f378eab4c
712 697 | semi-colon: 1:471f378eab4c
713 698 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
714 699 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
715 700 | x 471f378eab4c
716 701 |/ Successors: 2:fdf9bde5129a; 3:65b757b745b9
717 702 | multi-line: 2:fdf9bde5129a
718 703 | multi-line: 3:65b757b745b9
719 704 | json: [["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], ["65b757b745b935093c87a2bccd877521cccffcbd"]]
720 705 o ea207398892e
721 706
722 707
723 708 $ hg fatelog --hidden
724 709 o 019fadeab383
725 710 |
726 711 | x 65b757b745b9
727 712 |/ Obsfate: rewritten as 4:019fadeab383 by test (at 1970-01-01 00:00 +0000);
728 713 | @ fdf9bde5129a
729 714 |/
730 715 | x 471f378eab4c
731 716 |/ Obsfate: rewritten as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000); rewritten as 3:65b757b745b9 by test (at 1970-01-01 00:00 +0000);
732 717 o ea207398892e
733 718
734 719
735 720 $ hg fatelogjson --hidden
736 721 o 019fadeab383
737 722 |
738 723 | x 65b757b745b9
739 724 |/ Obsfate: [{"markers": [["65b757b745b935093c87a2bccd877521cccffcbd", ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"]}]
740 725 | @ fdf9bde5129a
741 726 |/
742 727 | x 471f378eab4c
743 728 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"]}, {"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["65b757b745b935093c87a2bccd877521cccffcbd"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["65b757b745b935093c87a2bccd877521cccffcbd"]}]
744 729 o ea207398892e
745 730
746 731
747 732 Test templates with amended + folded commit
748 733 ===========================================
749 734
750 735 Test setup
751 736 ----------
752 737
753 738 $ hg init $TESTTMP/templates-local-amend-fold
754 739 $ cd $TESTTMP/templates-local-amend-fold
755 740 $ mkcommit ROOT
756 741 $ mkcommit A0
757 742 $ mkcommit B0
758 743 $ hg commit --amend -m "B1"
759 744 $ hg log --hidden -G
760 745 @ changeset: 3:b7ea6d14e664
761 746 | tag: tip
762 747 | parent: 1:471f378eab4c
763 748 | user: test
764 749 | date: Thu Jan 01 00:00:00 1970 +0000
765 750 | summary: B1
766 751 |
767 752 | x changeset: 2:0dec01379d3b
768 753 |/ user: test
769 754 | date: Thu Jan 01 00:00:00 1970 +0000
770 755 | summary: B0
771 756 |
772 757 o changeset: 1:471f378eab4c
773 758 | user: test
774 759 | date: Thu Jan 01 00:00:00 1970 +0000
775 760 | summary: A0
776 761 |
777 762 o changeset: 0:ea207398892e
778 763 user: test
779 764 date: Thu Jan 01 00:00:00 1970 +0000
780 765 summary: ROOT
781 766
782 767 # Simulate a fold
783 768 $ hg up -r "desc(ROOT)"
784 769 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
785 770 $ echo "A0" > A0
786 771 $ echo "B0" > B0
787 772 $ hg commit -A -m "C0"
788 773 adding A0
789 774 adding B0
790 775 created new head
791 776 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(C0)"`
792 777 obsoleted 1 changesets
793 778 $ hg debugobsolete `getid "desc(B1)"` `getid "desc(C0)"`
794 779 obsoleted 1 changesets
795 780
796 781 $ hg log --hidden -G
797 782 @ changeset: 4:eb5a0daa2192
798 783 | tag: tip
799 784 | parent: 0:ea207398892e
800 785 | user: test
801 786 | date: Thu Jan 01 00:00:00 1970 +0000
802 787 | summary: C0
803 788 |
804 789 | x changeset: 3:b7ea6d14e664
805 790 | | parent: 1:471f378eab4c
806 791 | | user: test
807 792 | | date: Thu Jan 01 00:00:00 1970 +0000
808 793 | | summary: B1
809 794 | |
810 795 | | x changeset: 2:0dec01379d3b
811 796 | |/ user: test
812 797 | | date: Thu Jan 01 00:00:00 1970 +0000
813 798 | | summary: B0
814 799 | |
815 800 | x changeset: 1:471f378eab4c
816 801 |/ user: test
817 802 | date: Thu Jan 01 00:00:00 1970 +0000
818 803 | summary: A0
819 804 |
820 805 o changeset: 0:ea207398892e
821 806 user: test
822 807 date: Thu Jan 01 00:00:00 1970 +0000
823 808 summary: ROOT
824 809
825 810 Check templates
826 811 ---------------
827 812
828 813 $ hg up 'desc(A0)' --hidden
829 814 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
830 815
831 816 Predecessors template should show current revision as it is the working copy
832 817 $ hg tlog
833 818 o eb5a0daa2192
834 819 | Predecessors: 1:471f378eab4c
835 820 | semi-colon: 1:471f378eab4c
836 821 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
837 822 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
838 823 | @ 471f378eab4c
839 824 |/ Successors: 4:eb5a0daa2192
840 825 | multi-line: 4:eb5a0daa2192
841 826 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
842 827 o ea207398892e
843 828
844 829
845 830 $ hg fatelog
846 831 o eb5a0daa2192
847 832 |
848 833 | @ 471f378eab4c
849 834 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
850 835 o ea207398892e
851 836
852 837 $ hg up 'desc(B0)' --hidden
853 838 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
854 839
855 840 Predecessors template should both predecessors as they are visible
856 841 $ hg tlog
857 842 o eb5a0daa2192
858 843 | Predecessors: 2:0dec01379d3b 1:471f378eab4c
859 844 | semi-colon: 2:0dec01379d3b; 1:471f378eab4c
860 845 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
861 846 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5 1:471f378eab4c5e25f6c77f785b27c936efb22874
862 847 | @ 0dec01379d3b
863 848 | | Successors: 4:eb5a0daa2192
864 849 | | multi-line: 4:eb5a0daa2192
865 850 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
866 851 | x 471f378eab4c
867 852 |/ Successors: 4:eb5a0daa2192
868 853 | multi-line: 4:eb5a0daa2192
869 854 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
870 855 o ea207398892e
871 856
872 857
873 858 $ hg fatelog
874 859 o eb5a0daa2192
875 860 |
876 861 | @ 0dec01379d3b
877 862 | | Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
878 863 | x 471f378eab4c
879 864 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
880 865 o ea207398892e
881 866
882 867 $ hg up 'desc(B1)' --hidden
883 868 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
884 869
885 870 Predecessors template should both predecessors as they are visible
886 871 $ hg tlog
887 872 o eb5a0daa2192
888 873 | Predecessors: 1:471f378eab4c 3:b7ea6d14e664
889 874 | semi-colon: 1:471f378eab4c; 3:b7ea6d14e664
890 875 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874", "b7ea6d14e664bdc8922221f7992631b50da3fb07"]
891 876 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874 3:b7ea6d14e664bdc8922221f7992631b50da3fb07
892 877 | @ b7ea6d14e664
893 878 | | Successors: 4:eb5a0daa2192
894 879 | | multi-line: 4:eb5a0daa2192
895 880 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
896 881 | x 471f378eab4c
897 882 |/ Successors: 4:eb5a0daa2192
898 883 | multi-line: 4:eb5a0daa2192
899 884 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
900 885 o ea207398892e
901 886
902 887
903 888 $ hg fatelog
904 889 o eb5a0daa2192
905 890 |
906 891 | @ b7ea6d14e664
907 892 | | Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
908 893 | x 471f378eab4c
909 894 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
910 895 o ea207398892e
911 896
912 897 $ hg up 'desc(C0)'
913 898 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
914 899
915 900 Predecessors template should show no predecessors as they are both non visible
916 901 $ hg tlog
917 902 @ eb5a0daa2192
918 903 |
919 904 o ea207398892e
920 905
921 906
922 907 $ hg fatelog
923 908 @ eb5a0daa2192
924 909 |
925 910 o ea207398892e
926 911
927 912 Predecessors template should show all predecessors as we force their display
928 913 with --hidden
929 914 $ hg tlog --hidden
930 915 @ eb5a0daa2192
931 916 | Predecessors: 1:471f378eab4c 3:b7ea6d14e664
932 917 | semi-colon: 1:471f378eab4c; 3:b7ea6d14e664
933 918 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874", "b7ea6d14e664bdc8922221f7992631b50da3fb07"]
934 919 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874 3:b7ea6d14e664bdc8922221f7992631b50da3fb07
935 920 | x b7ea6d14e664
936 921 | | Predecessors: 2:0dec01379d3b
937 922 | | semi-colon: 2:0dec01379d3b
938 923 | | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
939 924 | | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
940 925 | | Successors: 4:eb5a0daa2192
941 926 | | multi-line: 4:eb5a0daa2192
942 927 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
943 928 | | x 0dec01379d3b
944 929 | |/ Successors: 3:b7ea6d14e664
945 930 | | multi-line: 3:b7ea6d14e664
946 931 | | json: [["b7ea6d14e664bdc8922221f7992631b50da3fb07"]]
947 932 | x 471f378eab4c
948 933 |/ Successors: 4:eb5a0daa2192
949 934 | multi-line: 4:eb5a0daa2192
950 935 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
951 936 o ea207398892e
952 937
953 938
954 939 $ hg fatelog --hidden
955 940 @ eb5a0daa2192
956 941 |
957 942 | x b7ea6d14e664
958 943 | | Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
959 944 | | x 0dec01379d3b
960 945 | |/ Obsfate: rewritten as 3:b7ea6d14e664 by test (at 1970-01-01 00:00 +0000);
961 946 | x 471f378eab4c
962 947 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
963 948 o ea207398892e
964 949
965 950
966 951 $ hg fatelogjson --hidden
967 952 @ eb5a0daa2192
968 953 |
969 954 | x b7ea6d14e664
970 955 | | Obsfate: [{"markers": [["b7ea6d14e664bdc8922221f7992631b50da3fb07", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]}]
971 956 | | x 0dec01379d3b
972 957 | |/ Obsfate: [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["b7ea6d14e664bdc8922221f7992631b50da3fb07"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["b7ea6d14e664bdc8922221f7992631b50da3fb07"]}]
973 958 | x 471f378eab4c
974 959 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]}]
975 960 o ea207398892e
976 961
977 962
978 963 Test template with pushed and pulled obs markers
979 964 ================================================
980 965
981 966 Test setup
982 967 ----------
983 968
984 969 $ hg init $TESTTMP/templates-local-remote-markers-1
985 970 $ cd $TESTTMP/templates-local-remote-markers-1
986 971 $ mkcommit ROOT
987 972 $ mkcommit A0
988 973 $ hg clone $TESTTMP/templates-local-remote-markers-1 $TESTTMP/templates-local-remote-markers-2
989 974 updating to branch default
990 975 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
991 976 $ cd $TESTTMP/templates-local-remote-markers-2
992 977 $ hg log --hidden -G
993 978 @ changeset: 1:471f378eab4c
994 979 | tag: tip
995 980 | user: test
996 981 | date: Thu Jan 01 00:00:00 1970 +0000
997 982 | summary: A0
998 983 |
999 984 o changeset: 0:ea207398892e
1000 985 user: test
1001 986 date: Thu Jan 01 00:00:00 1970 +0000
1002 987 summary: ROOT
1003 988
1004 989 $ cd $TESTTMP/templates-local-remote-markers-1
1005 990 $ hg commit --amend -m "A1"
1006 991 $ hg commit --amend -m "A2"
1007 992 $ hg log --hidden -G
1008 993 @ changeset: 3:7a230b46bf61
1009 994 | tag: tip
1010 995 | parent: 0:ea207398892e
1011 996 | user: test
1012 997 | date: Thu Jan 01 00:00:00 1970 +0000
1013 998 | summary: A2
1014 999 |
1015 1000 | x changeset: 2:fdf9bde5129a
1016 1001 |/ parent: 0:ea207398892e
1017 1002 | user: test
1018 1003 | date: Thu Jan 01 00:00:00 1970 +0000
1019 1004 | summary: A1
1020 1005 |
1021 1006 | x changeset: 1:471f378eab4c
1022 1007 |/ user: test
1023 1008 | date: Thu Jan 01 00:00:00 1970 +0000
1024 1009 | summary: A0
1025 1010 |
1026 1011 o changeset: 0:ea207398892e
1027 1012 user: test
1028 1013 date: Thu Jan 01 00:00:00 1970 +0000
1029 1014 summary: ROOT
1030 1015
1031 1016 $ cd $TESTTMP/templates-local-remote-markers-2
1032 1017 $ hg pull
1033 1018 pulling from $TESTTMP/templates-local-remote-markers-1 (glob)
1034 1019 searching for changes
1035 1020 adding changesets
1036 1021 adding manifests
1037 1022 adding file changes
1038 1023 added 1 changesets with 0 changes to 1 files (+1 heads)
1039 1024 2 new obsolescence markers
1040 1025 obsoleted 1 changesets
1041 1026 (run 'hg heads' to see heads, 'hg merge' to merge)
1042 1027 $ hg log --hidden -G
1043 1028 o changeset: 2:7a230b46bf61
1044 1029 | tag: tip
1045 1030 | parent: 0:ea207398892e
1046 1031 | user: test
1047 1032 | date: Thu Jan 01 00:00:00 1970 +0000
1048 1033 | summary: A2
1049 1034 |
1050 1035 | @ changeset: 1:471f378eab4c
1051 1036 |/ user: test
1052 1037 | date: Thu Jan 01 00:00:00 1970 +0000
1053 1038 | summary: A0
1054 1039 |
1055 1040 o changeset: 0:ea207398892e
1056 1041 user: test
1057 1042 date: Thu Jan 01 00:00:00 1970 +0000
1058 1043 summary: ROOT
1059 1044
1060 1045
1061 1046 $ hg debugobsolete
1062 1047 471f378eab4c5e25f6c77f785b27c936efb22874 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1063 1048 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 7a230b46bf61e50b30308c6cfd7bd1269ef54702 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1064 1049
1065 1050 Check templates
1066 1051 ---------------
1067 1052
1068 1053 Predecessors template should show current revision as it is the working copy
1069 1054 $ hg tlog
1070 1055 o 7a230b46bf61
1071 1056 | Predecessors: 1:471f378eab4c
1072 1057 | semi-colon: 1:471f378eab4c
1073 1058 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1074 1059 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1075 1060 | @ 471f378eab4c
1076 1061 |/ Successors: 2:7a230b46bf61
1077 1062 | multi-line: 2:7a230b46bf61
1078 1063 | json: [["7a230b46bf61e50b30308c6cfd7bd1269ef54702"]]
1079 1064 o ea207398892e
1080 1065
1081 1066
1082 1067 $ hg fatelog
1083 1068 o 7a230b46bf61
1084 1069 |
1085 1070 | @ 471f378eab4c
1086 1071 |/ Obsfate: rewritten as 2:7a230b46bf61 by test (at 1970-01-01 00:00 +0000);
1087 1072 o ea207398892e
1088 1073
1089 1074 $ hg up 'desc(A2)'
1090 1075 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1091 1076
1092 1077 Predecessors template should show no predecessors as they are non visible
1093 1078 $ hg tlog
1094 1079 @ 7a230b46bf61
1095 1080 |
1096 1081 o ea207398892e
1097 1082
1098 1083
1099 1084 $ hg fatelog
1100 1085 @ 7a230b46bf61
1101 1086 |
1102 1087 o ea207398892e
1103 1088
1104 1089 Predecessors template should show all predecessors as we force their display
1105 1090 with --hidden
1106 1091 $ hg tlog --hidden
1107 1092 @ 7a230b46bf61
1108 1093 | Predecessors: 1:471f378eab4c
1109 1094 | semi-colon: 1:471f378eab4c
1110 1095 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1111 1096 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1112 1097 | x 471f378eab4c
1113 1098 |/ Successors: 2:7a230b46bf61
1114 1099 | multi-line: 2:7a230b46bf61
1115 1100 | json: [["7a230b46bf61e50b30308c6cfd7bd1269ef54702"]]
1116 1101 o ea207398892e
1117 1102
1118 1103
1119 1104 $ hg fatelog --hidden
1120 1105 @ 7a230b46bf61
1121 1106 |
1122 1107 | x 471f378eab4c
1123 1108 |/ Obsfate: rewritten as 2:7a230b46bf61 by test (at 1970-01-01 00:00 +0000);
1124 1109 o ea207398892e
1125 1110
1126 1111
1127 1112 Test template with obsmarkers cycle
1128 1113 ===================================
1129 1114
1130 1115 Test setup
1131 1116 ----------
1132 1117
1133 1118 $ hg init $TESTTMP/templates-local-cycle
1134 1119 $ cd $TESTTMP/templates-local-cycle
1135 1120 $ mkcommit ROOT
1136 1121 $ mkcommit A0
1137 1122 $ mkcommit B0
1138 1123 $ hg up -r 0
1139 1124 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1140 1125 $ mkcommit C0
1141 1126 created new head
1142 1127
1143 1128 Create the cycle
1144 1129
1145 1130 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(B0)"`
1146 1131 obsoleted 1 changesets
1147 1132 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(C0)"`
1148 1133 obsoleted 1 changesets
1149 1134 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(A0)"`
1150 1135
1151 1136 Check templates
1152 1137 ---------------
1153 1138
1154 1139 $ hg tlog
1155 1140 @ f897c6137566
1156 1141 |
1157 1142 o ea207398892e
1158 1143
1159 1144
1160 1145 $ hg fatelog
1161 1146 @ f897c6137566
1162 1147 |
1163 1148 o ea207398892e
1164 1149
1165 1150
1166 1151 $ hg up -r "desc(B0)" --hidden
1167 1152 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1168 1153 $ hg tlog
1169 1154 o f897c6137566
1170 1155 | Predecessors: 2:0dec01379d3b
1171 1156 | semi-colon: 2:0dec01379d3b
1172 1157 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1173 1158 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1174 1159 | @ 0dec01379d3b
1175 1160 | | Predecessors: 1:471f378eab4c
1176 1161 | | semi-colon: 1:471f378eab4c
1177 1162 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1178 1163 | | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1179 1164 | | Successors: 3:f897c6137566; 1:471f378eab4c
1180 1165 | | multi-line: 3:f897c6137566
1181 1166 | | multi-line: 1:471f378eab4c
1182 1167 | | json: [["f897c6137566320b081514b4c7227ecc3d384b39"], ["471f378eab4c5e25f6c77f785b27c936efb22874"]]
1183 1168 | x 471f378eab4c
1184 1169 |/ Predecessors: 2:0dec01379d3b
1185 1170 | semi-colon: 2:0dec01379d3b
1186 1171 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1187 1172 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1188 1173 | Successors: 2:0dec01379d3b
1189 1174 | multi-line: 2:0dec01379d3b
1190 1175 | json: [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]]
1191 1176 o ea207398892e
1192 1177
1193 1178
1194 1179 $ hg fatelog
1195 1180 o f897c6137566
1196 1181 |
1197 1182 | @ 0dec01379d3b
1198 1183 | | Obsfate: rewritten as 3:f897c6137566 by test (at 1970-01-01 00:00 +0000); rewritten as 1:471f378eab4c by test (at 1970-01-01 00:00 +0000);
1199 1184 | x 471f378eab4c
1200 1185 |/ Obsfate: rewritten as 2:0dec01379d3b by test (at 1970-01-01 00:00 +0000);
1201 1186 o ea207398892e
1202 1187
1203 1188
1204 1189 $ hg up -r "desc(A0)" --hidden
1205 1190 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1206 1191 $ hg tlog
1207 1192 o f897c6137566
1208 1193 | Predecessors: 1:471f378eab4c
1209 1194 | semi-colon: 1:471f378eab4c
1210 1195 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1211 1196 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1212 1197 | @ 471f378eab4c
1213 1198 |/
1214 1199 o ea207398892e
1215 1200
1216 1201
1217 1202 $ hg fatelog
1218 1203 o f897c6137566
1219 1204 |
1220 1205 | @ 471f378eab4c
1221 1206 |/ Obsfate: pruned;
1222 1207 o ea207398892e
1223 1208
1224 1209
1225 1210 $ hg up -r "desc(ROOT)" --hidden
1226 1211 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1227 1212 $ hg tlog
1228 1213 o f897c6137566
1229 1214 |
1230 1215 @ ea207398892e
1231 1216
1232 1217
1233 1218 $ hg fatelog
1234 1219 o f897c6137566
1235 1220 |
1236 1221 @ ea207398892e
1237 1222
1238 1223
1239 1224 $ hg tlog --hidden
1240 1225 o f897c6137566
1241 1226 | Predecessors: 2:0dec01379d3b
1242 1227 | semi-colon: 2:0dec01379d3b
1243 1228 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1244 1229 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1245 1230 | x 0dec01379d3b
1246 1231 | | Predecessors: 1:471f378eab4c
1247 1232 | | semi-colon: 1:471f378eab4c
1248 1233 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1249 1234 | | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1250 1235 | | Successors: 3:f897c6137566; 1:471f378eab4c
1251 1236 | | multi-line: 3:f897c6137566
1252 1237 | | multi-line: 1:471f378eab4c
1253 1238 | | json: [["f897c6137566320b081514b4c7227ecc3d384b39"], ["471f378eab4c5e25f6c77f785b27c936efb22874"]]
1254 1239 | x 471f378eab4c
1255 1240 |/ Predecessors: 2:0dec01379d3b
1256 1241 | semi-colon: 2:0dec01379d3b
1257 1242 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1258 1243 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1259 1244 | Successors: 2:0dec01379d3b
1260 1245 | multi-line: 2:0dec01379d3b
1261 1246 | json: [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]]
1262 1247 @ ea207398892e
1263 1248
1264 1249 Test template with split + divergence with cycles
1265 1250 =================================================
1266 1251
1267 1252 $ hg log -G
1268 1253 o changeset: 3:f897c6137566
1269 1254 | tag: tip
1270 1255 | parent: 0:ea207398892e
1271 1256 | user: test
1272 1257 | date: Thu Jan 01 00:00:00 1970 +0000
1273 1258 | summary: C0
1274 1259 |
1275 1260 @ changeset: 0:ea207398892e
1276 1261 user: test
1277 1262 date: Thu Jan 01 00:00:00 1970 +0000
1278 1263 summary: ROOT
1279 1264
1280 1265 $ hg up
1281 1266 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1282 1267
1283 1268 Create a commit with three files
1284 1269 $ touch A B C
1285 1270 $ hg commit -A -m "Add A,B,C" A B C
1286 1271
1287 1272 Split it
1288 1273 $ hg up 3
1289 1274 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
1290 1275 $ touch A
1291 1276 $ hg commit -A -m "Add A,B,C" A
1292 1277 created new head
1293 1278
1294 1279 $ touch B
1295 1280 $ hg commit -A -m "Add A,B,C" B
1296 1281
1297 1282 $ touch C
1298 1283 $ hg commit -A -m "Add A,B,C" C
1299 1284
1300 1285 $ hg log -G
1301 1286 @ changeset: 7:ba2ed02b0c9a
1302 1287 | tag: tip
1303 1288 | user: test
1304 1289 | date: Thu Jan 01 00:00:00 1970 +0000
1305 1290 | summary: Add A,B,C
1306 1291 |
1307 1292 o changeset: 6:4a004186e638
1308 1293 | user: test
1309 1294 | date: Thu Jan 01 00:00:00 1970 +0000
1310 1295 | summary: Add A,B,C
1311 1296 |
1312 1297 o changeset: 5:dd800401bd8c
1313 1298 | parent: 3:f897c6137566
1314 1299 | user: test
1315 1300 | date: Thu Jan 01 00:00:00 1970 +0000
1316 1301 | summary: Add A,B,C
1317 1302 |
1318 1303 | o changeset: 4:9bd10a0775e4
1319 1304 |/ user: test
1320 1305 | date: Thu Jan 01 00:00:00 1970 +0000
1321 1306 | summary: Add A,B,C
1322 1307 |
1323 1308 o changeset: 3:f897c6137566
1324 1309 | parent: 0:ea207398892e
1325 1310 | user: test
1326 1311 | date: Thu Jan 01 00:00:00 1970 +0000
1327 1312 | summary: C0
1328 1313 |
1329 1314 o changeset: 0:ea207398892e
1330 1315 user: test
1331 1316 date: Thu Jan 01 00:00:00 1970 +0000
1332 1317 summary: ROOT
1333 1318
1334 1319 $ hg debugobsolete `getid "4"` `getid "5"` `getid "6"` `getid "7"`
1335 1320 obsoleted 1 changesets
1336 1321 $ hg log -G
1337 1322 @ changeset: 7:ba2ed02b0c9a
1338 1323 | tag: tip
1339 1324 | user: test
1340 1325 | date: Thu Jan 01 00:00:00 1970 +0000
1341 1326 | summary: Add A,B,C
1342 1327 |
1343 1328 o changeset: 6:4a004186e638
1344 1329 | user: test
1345 1330 | date: Thu Jan 01 00:00:00 1970 +0000
1346 1331 | summary: Add A,B,C
1347 1332 |
1348 1333 o changeset: 5:dd800401bd8c
1349 1334 | parent: 3:f897c6137566
1350 1335 | user: test
1351 1336 | date: Thu Jan 01 00:00:00 1970 +0000
1352 1337 | summary: Add A,B,C
1353 1338 |
1354 1339 o changeset: 3:f897c6137566
1355 1340 | parent: 0:ea207398892e
1356 1341 | user: test
1357 1342 | date: Thu Jan 01 00:00:00 1970 +0000
1358 1343 | summary: C0
1359 1344 |
1360 1345 o changeset: 0:ea207398892e
1361 1346 user: test
1362 1347 date: Thu Jan 01 00:00:00 1970 +0000
1363 1348 summary: ROOT
1364 1349
1365 1350 Diverge one of the splitted commit
1366 1351
1367 1352 $ hg up 6
1368 1353 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1369 1354 $ hg commit --amend -m "Add only B"
1370 1355
1371 1356 $ hg up 6 --hidden
1372 1357 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1373 1358 $ hg commit --amend -m "Add B only"
1374 1359
1375 1360 $ hg log -G
1376 1361 @ changeset: 9:0b997eb7ceee
1377 1362 | tag: tip
1378 1363 | parent: 5:dd800401bd8c
1379 1364 | user: test
1380 1365 | date: Thu Jan 01 00:00:00 1970 +0000
1381 1366 | instability: content-divergent
1382 1367 | summary: Add B only
1383 1368 |
1384 1369 | o changeset: 8:b18bc8331526
1385 1370 |/ parent: 5:dd800401bd8c
1386 1371 | user: test
1387 1372 | date: Thu Jan 01 00:00:00 1970 +0000
1388 1373 | instability: content-divergent
1389 1374 | summary: Add only B
1390 1375 |
1391 1376 | o changeset: 7:ba2ed02b0c9a
1392 1377 | | user: test
1393 1378 | | date: Thu Jan 01 00:00:00 1970 +0000
1394 1379 | | instability: orphan, content-divergent
1395 1380 | | summary: Add A,B,C
1396 1381 | |
1397 1382 | x changeset: 6:4a004186e638
1398 1383 |/ user: test
1399 1384 | date: Thu Jan 01 00:00:00 1970 +0000
1400 1385 | summary: Add A,B,C
1401 1386 |
1402 1387 o changeset: 5:dd800401bd8c
1403 1388 | parent: 3:f897c6137566
1404 1389 | user: test
1405 1390 | date: Thu Jan 01 00:00:00 1970 +0000
1406 1391 | instability: content-divergent
1407 1392 | summary: Add A,B,C
1408 1393 |
1409 1394 o changeset: 3:f897c6137566
1410 1395 | parent: 0:ea207398892e
1411 1396 | user: test
1412 1397 | date: Thu Jan 01 00:00:00 1970 +0000
1413 1398 | summary: C0
1414 1399 |
1415 1400 o changeset: 0:ea207398892e
1416 1401 user: test
1417 1402 date: Thu Jan 01 00:00:00 1970 +0000
1418 1403 summary: ROOT
1419 1404
1420 1405
1421 1406 Check templates
1422 1407 ---------------
1423 1408
1424 1409 $ hg tlog
1425 1410 @ 0b997eb7ceee
1426 1411 | Predecessors: 6:4a004186e638
1427 1412 | semi-colon: 6:4a004186e638
1428 1413 | json: ["4a004186e63889f20cb16434fcbd72220bd1eace"]
1429 1414 | map: 6:4a004186e63889f20cb16434fcbd72220bd1eace
1430 1415 | o b18bc8331526
1431 1416 |/ Predecessors: 6:4a004186e638
1432 1417 | semi-colon: 6:4a004186e638
1433 1418 | json: ["4a004186e63889f20cb16434fcbd72220bd1eace"]
1434 1419 | map: 6:4a004186e63889f20cb16434fcbd72220bd1eace
1435 1420 | o ba2ed02b0c9a
1436 1421 | |
1437 1422 | x 4a004186e638
1438 1423 |/ Successors: 8:b18bc8331526; 9:0b997eb7ceee
1439 1424 | multi-line: 8:b18bc8331526
1440 1425 | multi-line: 9:0b997eb7ceee
1441 1426 | json: [["b18bc8331526a22cbb1801022bd1555bf291c48b"], ["0b997eb7ceeee06200a02f8aab185979092d514e"]]
1442 1427 o dd800401bd8c
1443 1428 |
1444 1429 o f897c6137566
1445 1430 |
1446 1431 o ea207398892e
1447 1432
1448 1433 $ hg fatelog
1449 1434 @ 0b997eb7ceee
1450 1435 |
1451 1436 | o b18bc8331526
1452 1437 |/
1453 1438 | o ba2ed02b0c9a
1454 1439 | |
1455 1440 | x 4a004186e638
1456 1441 |/ Obsfate: rewritten as 8:b18bc8331526 by test (at 1970-01-01 00:00 +0000); rewritten as 9:0b997eb7ceee by test (at 1970-01-01 00:00 +0000);
1457 1442 o dd800401bd8c
1458 1443 |
1459 1444 o f897c6137566
1460 1445 |
1461 1446 o ea207398892e
1462 1447
1463 1448 $ hg tlog --hidden
1464 1449 @ 0b997eb7ceee
1465 1450 | Predecessors: 6:4a004186e638
1466 1451 | semi-colon: 6:4a004186e638
1467 1452 | json: ["4a004186e63889f20cb16434fcbd72220bd1eace"]
1468 1453 | map: 6:4a004186e63889f20cb16434fcbd72220bd1eace
1469 1454 | o b18bc8331526
1470 1455 |/ Predecessors: 6:4a004186e638
1471 1456 | semi-colon: 6:4a004186e638
1472 1457 | json: ["4a004186e63889f20cb16434fcbd72220bd1eace"]
1473 1458 | map: 6:4a004186e63889f20cb16434fcbd72220bd1eace
1474 1459 | o ba2ed02b0c9a
1475 1460 | | Predecessors: 4:9bd10a0775e4
1476 1461 | | semi-colon: 4:9bd10a0775e4
1477 1462 | | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1478 1463 | | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1479 1464 | x 4a004186e638
1480 1465 |/ Predecessors: 4:9bd10a0775e4
1481 1466 | semi-colon: 4:9bd10a0775e4
1482 1467 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1483 1468 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1484 1469 | Successors: 8:b18bc8331526; 9:0b997eb7ceee
1485 1470 | multi-line: 8:b18bc8331526
1486 1471 | multi-line: 9:0b997eb7ceee
1487 1472 | json: [["b18bc8331526a22cbb1801022bd1555bf291c48b"], ["0b997eb7ceeee06200a02f8aab185979092d514e"]]
1488 1473 o dd800401bd8c
1489 1474 | Predecessors: 4:9bd10a0775e4
1490 1475 | semi-colon: 4:9bd10a0775e4
1491 1476 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1492 1477 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1493 1478 | x 9bd10a0775e4
1494 1479 |/ Successors: 5:dd800401bd8c 6:4a004186e638 7:ba2ed02b0c9a
1495 1480 | multi-line: 5:dd800401bd8c 6:4a004186e638 7:ba2ed02b0c9a
1496 1481 | json: [["dd800401bd8c79d815329277739e433e883f784e", "4a004186e63889f20cb16434fcbd72220bd1eace", "ba2ed02b0c9a56b9fdbc4e79c7e57866984d8a1f"]]
1497 1482 o f897c6137566
1498 1483 | Predecessors: 2:0dec01379d3b
1499 1484 | semi-colon: 2:0dec01379d3b
1500 1485 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1501 1486 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1502 1487 | x 0dec01379d3b
1503 1488 | | Predecessors: 1:471f378eab4c
1504 1489 | | semi-colon: 1:471f378eab4c
1505 1490 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1506 1491 | | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1507 1492 | | Successors: 3:f897c6137566; 1:471f378eab4c
1508 1493 | | multi-line: 3:f897c6137566
1509 1494 | | multi-line: 1:471f378eab4c
1510 1495 | | json: [["f897c6137566320b081514b4c7227ecc3d384b39"], ["471f378eab4c5e25f6c77f785b27c936efb22874"]]
1511 1496 | x 471f378eab4c
1512 1497 |/ Predecessors: 2:0dec01379d3b
1513 1498 | semi-colon: 2:0dec01379d3b
1514 1499 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1515 1500 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1516 1501 | Successors: 2:0dec01379d3b
1517 1502 | multi-line: 2:0dec01379d3b
1518 1503 | json: [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]]
1519 1504 o ea207398892e
1520 1505
1521 1506 $ hg fatelog --hidden
1522 1507 @ 0b997eb7ceee
1523 1508 |
1524 1509 | o b18bc8331526
1525 1510 |/
1526 1511 | o ba2ed02b0c9a
1527 1512 | |
1528 1513 | x 4a004186e638
1529 1514 |/ Obsfate: rewritten as 8:b18bc8331526 by test (at 1970-01-01 00:00 +0000); rewritten as 9:0b997eb7ceee by test (at 1970-01-01 00:00 +0000);
1530 1515 o dd800401bd8c
1531 1516 |
1532 1517 | x 9bd10a0775e4
1533 1518 |/ Obsfate: split as 5:dd800401bd8c, 6:4a004186e638, 7:ba2ed02b0c9a by test (at 1970-01-01 00:00 +0000);
1534 1519 o f897c6137566
1535 1520 |
1536 1521 | x 0dec01379d3b
1537 1522 | | Obsfate: rewritten as 3:f897c6137566 by test (at 1970-01-01 00:00 +0000); rewritten as 1:471f378eab4c by test (at 1970-01-01 00:00 +0000);
1538 1523 | x 471f378eab4c
1539 1524 |/ Obsfate: rewritten as 2:0dec01379d3b by test (at 1970-01-01 00:00 +0000);
1540 1525 o ea207398892e
1541 1526
1542 1527 $ hg fatelogjson --hidden
1543 1528 @ 0b997eb7ceee
1544 1529 |
1545 1530 | o b18bc8331526
1546 1531 |/
1547 1532 | o ba2ed02b0c9a
1548 1533 | |
1549 1534 | x 4a004186e638
1550 1535 |/ Obsfate: [{"markers": [["4a004186e63889f20cb16434fcbd72220bd1eace", ["b18bc8331526a22cbb1801022bd1555bf291c48b"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["b18bc8331526a22cbb1801022bd1555bf291c48b"]}, {"markers": [["4a004186e63889f20cb16434fcbd72220bd1eace", ["0b997eb7ceeee06200a02f8aab185979092d514e"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["0b997eb7ceeee06200a02f8aab185979092d514e"]}]
1551 1536 o dd800401bd8c
1552 1537 |
1553 1538 | x 9bd10a0775e4
1554 1539 |/ Obsfate: [{"markers": [["9bd10a0775e478708cada5f176ec6de654359ce7", ["dd800401bd8c79d815329277739e433e883f784e", "4a004186e63889f20cb16434fcbd72220bd1eace", "ba2ed02b0c9a56b9fdbc4e79c7e57866984d8a1f"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["dd800401bd8c79d815329277739e433e883f784e", "4a004186e63889f20cb16434fcbd72220bd1eace", "ba2ed02b0c9a56b9fdbc4e79c7e57866984d8a1f"]}]
1555 1540 o f897c6137566
1556 1541 |
1557 1542 | x 0dec01379d3b
1558 1543 | | Obsfate: [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["f897c6137566320b081514b4c7227ecc3d384b39"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["f897c6137566320b081514b4c7227ecc3d384b39"]}, {"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["471f378eab4c5e25f6c77f785b27c936efb22874"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["471f378eab4c5e25f6c77f785b27c936efb22874"]}]
1559 1544 | x 471f378eab4c
1560 1545 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]}]
1561 1546 o ea207398892e
1562 1547
1563 1548 $ hg up --hidden 4
1564 1549 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1565 1550 $ hg rebase -r 7 -d 8 --config extensions.rebase=
1566 1551 rebasing 7:ba2ed02b0c9a "Add A,B,C"
1567 1552 $ hg tlog
1568 1553 o eceed8f98ffc
1569 1554 | Predecessors: 4:9bd10a0775e4
1570 1555 | semi-colon: 4:9bd10a0775e4
1571 1556 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1572 1557 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1573 1558 | o 0b997eb7ceee
1574 1559 | | Predecessors: 4:9bd10a0775e4
1575 1560 | | semi-colon: 4:9bd10a0775e4
1576 1561 | | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1577 1562 | | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1578 1563 o | b18bc8331526
1579 1564 |/ Predecessors: 4:9bd10a0775e4
1580 1565 | semi-colon: 4:9bd10a0775e4
1581 1566 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1582 1567 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1583 1568 o dd800401bd8c
1584 1569 | Predecessors: 4:9bd10a0775e4
1585 1570 | semi-colon: 4:9bd10a0775e4
1586 1571 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1587 1572 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1588 1573 | @ 9bd10a0775e4
1589 1574 |/ Successors: 5:dd800401bd8c 9:0b997eb7ceee 10:eceed8f98ffc; 5:dd800401bd8c 8:b18bc8331526 10:eceed8f98ffc
1590 1575 | multi-line: 5:dd800401bd8c 9:0b997eb7ceee 10:eceed8f98ffc
1591 1576 | multi-line: 5:dd800401bd8c 8:b18bc8331526 10:eceed8f98ffc
1592 1577 | json: [["dd800401bd8c79d815329277739e433e883f784e", "0b997eb7ceeee06200a02f8aab185979092d514e", "eceed8f98ffc4186032e29a6542ab98888ebf68d"], ["dd800401bd8c79d815329277739e433e883f784e", "b18bc8331526a22cbb1801022bd1555bf291c48b", "eceed8f98ffc4186032e29a6542ab98888ebf68d"]]
1593 1578 o f897c6137566
1594 1579 |
1595 1580 o ea207398892e
1596 1581
1597 1582
1598 1583 $ hg fatelog
1599 1584 o eceed8f98ffc
1600 1585 |
1601 1586 | o 0b997eb7ceee
1602 1587 | |
1603 1588 o | b18bc8331526
1604 1589 |/
1605 1590 o dd800401bd8c
1606 1591 |
1607 1592 | @ 9bd10a0775e4
1608 1593 |/ Obsfate: split as 5:dd800401bd8c, 9:0b997eb7ceee, 10:eceed8f98ffc by test (at 1970-01-01 00:00 +0000); split as 5:dd800401bd8c, 8:b18bc8331526, 10:eceed8f98ffc by test (at 1970-01-01 00:00 +0000);
1609 1594 o f897c6137566
1610 1595 |
1611 1596 o ea207398892e
1612 1597
1613 1598 Test templates with pruned commits
1614 1599 ==================================
1615 1600
1616 1601 Test setup
1617 1602 ----------
1618 1603
1619 1604 $ hg init $TESTTMP/templates-local-prune
1620 1605 $ cd $TESTTMP/templates-local-prune
1621 1606 $ mkcommit ROOT
1622 1607 $ mkcommit A0
1623 1608 $ hg debugobsolete --record-parent `getid "."`
1624 1609 obsoleted 1 changesets
1625 1610
1626 1611 Check output
1627 1612 ------------
1628 1613
1629 1614 $ hg up "desc(A0)" --hidden
1630 1615 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1631 1616 $ hg tlog
1632 1617 @ 471f378eab4c
1633 1618 |
1634 1619 o ea207398892e
1635 1620
1636 1621 $ hg fatelog
1637 1622 @ 471f378eab4c
1638 1623 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
1639 1624 o ea207398892e
1640 1625
1641 1626 $ hg fatelog -v
1642 1627 @ 471f378eab4c
1643 1628 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
1644 1629 o ea207398892e
1645 1630
1646 1631 Test templates with multiple pruned commits
1647 1632 ===========================================
1648 1633
1649 1634 Test setup
1650 1635 ----------
1651 1636
1652 1637 $ hg init $TESTTMP/multiple-local-prune
1653 1638 $ cd $TESTTMP/multiple-local-prune
1654 1639 $ mkcommit ROOT
1655 1640 $ mkcommit A0
1656 1641 $ hg commit --amend -m "A1"
1657 1642 $ hg debugobsolete --record-parent `getid "."`
1658 1643 obsoleted 1 changesets
1659 1644
1660 1645 $ hg up -r "desc(A0)" --hidden
1661 1646 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1662 1647 $ hg commit --amend -m "A2"
1663 1648 $ hg debugobsolete --record-parent `getid "."`
1664 1649 obsoleted 1 changesets
1665 1650
1666 1651 Check output
1667 1652 ------------
1668 1653
1669 1654 $ hg up "desc(A0)" --hidden
1670 1655 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1671 1656 $ hg tlog
1672 1657 @ 471f378eab4c
1673 1658 |
1674 1659 o ea207398892e
1675 1660
1676 1661 # todo: the obsfate output is not ideal
1677 1662 $ hg fatelog
1678 1663 @ 471f378eab4c
1679 1664 | Obsfate: pruned;
1680 1665 o ea207398892e
1681 1666
1682 1667 $ hg fatelog -v --hidden
1683 1668 x 65b757b745b9
1684 1669 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
1685 1670 | x fdf9bde5129a
1686 1671 |/ Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
1687 1672 | @ 471f378eab4c
1688 1673 |/ Obsfate: rewritten as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000); rewritten as 3:65b757b745b9 by test (at 1970-01-01 00:00 +0000);
1689 1674 o ea207398892e
1690 1675
1691 1676
1692 1677 Test templates with splitted and pruned commit
1693 1678 ==============================================
1694 1679
1695 1680 $ hg init $TESTTMP/templates-local-split-prune
1696 1681 $ cd $TESTTMP/templates-local-split-prune
1697 1682 $ mkcommit ROOT
1698 1683 $ echo 42 >> a
1699 1684 $ echo 43 >> b
1700 1685 $ hg commit -A -m "A0"
1701 1686 adding a
1702 1687 adding b
1703 1688 $ hg log --hidden -G
1704 1689 @ changeset: 1:471597cad322
1705 1690 | tag: tip
1706 1691 | user: test
1707 1692 | date: Thu Jan 01 00:00:00 1970 +0000
1708 1693 | summary: A0
1709 1694 |
1710 1695 o changeset: 0:ea207398892e
1711 1696 user: test
1712 1697 date: Thu Jan 01 00:00:00 1970 +0000
1713 1698 summary: ROOT
1714 1699
1715 1700 # Simulate split
1716 1701 $ hg up -r "desc(ROOT)"
1717 1702 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1718 1703 $ echo 42 >> a
1719 1704 $ hg commit -A -m "A1"
1720 1705 adding a
1721 1706 created new head
1722 1707 $ echo 43 >> b
1723 1708 $ hg commit -A -m "A2"
1724 1709 adding b
1725 1710 $ hg debugobsolete `getid "1"` `getid "2"` `getid "3"`
1726 1711 obsoleted 1 changesets
1727 1712
1728 1713 # Simulate prune
1729 1714 $ hg debugobsolete --record-parent `getid "."`
1730 1715 obsoleted 1 changesets
1731 1716
1732 1717 $ hg log --hidden -G
1733 1718 @ changeset: 3:0d0ef4bdf70e
1734 1719 | tag: tip
1735 1720 | user: test
1736 1721 | date: Thu Jan 01 00:00:00 1970 +0000
1737 1722 | summary: A2
1738 1723 |
1739 1724 o changeset: 2:617adc3a144c
1740 1725 | parent: 0:ea207398892e
1741 1726 | user: test
1742 1727 | date: Thu Jan 01 00:00:00 1970 +0000
1743 1728 | summary: A1
1744 1729 |
1745 1730 | x changeset: 1:471597cad322
1746 1731 |/ user: test
1747 1732 | date: Thu Jan 01 00:00:00 1970 +0000
1748 1733 | summary: A0
1749 1734 |
1750 1735 o changeset: 0:ea207398892e
1751 1736 user: test
1752 1737 date: Thu Jan 01 00:00:00 1970 +0000
1753 1738 summary: ROOT
1754 1739
1755 1740 Check templates
1756 1741 ---------------
1757 1742
1758 1743 $ hg up 'desc("A0")' --hidden
1759 1744 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1760 1745
1761 1746 # todo: the obsfate output is not ideal
1762 1747 $ hg fatelog
1763 1748 o 617adc3a144c
1764 1749 |
1765 1750 | @ 471597cad322
1766 1751 |/ Obsfate: pruned;
1767 1752 o ea207398892e
1768 1753
1769 1754 $ hg up -r 'desc("A2")' --hidden
1770 1755 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1771 1756
1772 1757 $ hg fatelog --hidden
1773 1758 @ 0d0ef4bdf70e
1774 1759 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
1775 1760 o 617adc3a144c
1776 1761 |
1777 1762 | x 471597cad322
1778 1763 |/ Obsfate: split as 2:617adc3a144c, 3:0d0ef4bdf70e by test (at 1970-01-01 00:00 +0000);
1779 1764 o ea207398892e
1780 1765
@@ -1,1513 +1,1501 b''
1 1 $ cat >> $HGRCPATH << EOF
2 2 > [phases]
3 3 > # public changeset are not obsolete
4 4 > publish=false
5 5 > [ui]
6 6 > logtemplate="{rev}:{node|short} ({phase}{if(obsolete, ' *{obsolete}*')}{if(instabilities, ' {instabilities}')}) [{tags} {bookmarks}] {desc|firstline}\n"
7 7 > EOF
8 8 $ mkcommit() {
9 9 > echo "$1" > "$1"
10 10 > hg add "$1"
11 11 > hg ci -m "add $1"
12 12 > }
13 13 $ getid() {
14 14 > hg log -T "{node}\n" --hidden -r "desc('$1')"
15 15 > }
16 16
17 17 $ cat > debugkeys.py <<EOF
18 18 > def reposetup(ui, repo):
19 19 > class debugkeysrepo(repo.__class__):
20 20 > def listkeys(self, namespace):
21 21 > ui.write('listkeys %s\n' % (namespace,))
22 22 > return super(debugkeysrepo, self).listkeys(namespace)
23 23 >
24 24 > if repo.local():
25 25 > repo.__class__ = debugkeysrepo
26 26 > EOF
27 27
28 28 $ hg init tmpa
29 29 $ cd tmpa
30 30 $ mkcommit kill_me
31 31
32 32 Checking that the feature is properly disabled
33 33
34 34 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
35 35 abort: creating obsolete markers is not enabled on this repo
36 36 [255]
37 37
38 38 Enabling it
39 39
40 40 $ cat >> $HGRCPATH << EOF
41 41 > [experimental]
42 42 > stabilization=createmarkers,exchange
43 43 > EOF
44 44
45 45 Killing a single changeset without replacement
46 46
47 47 $ hg debugobsolete 0
48 48 abort: changeset references must be full hexadecimal node identifiers
49 49 [255]
50 50 $ hg debugobsolete '00'
51 51 abort: changeset references must be full hexadecimal node identifiers
52 52 [255]
53 53 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
54 54 obsoleted 1 changesets
55 55 $ hg debugobsolete
56 56 97b7c2d76b1845ed3eb988cd612611e72406cef0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'babar'}
57 57
58 58 (test that mercurial is not confused)
59 59
60 60 $ hg up null --quiet # having 0 as parent prevents it to be hidden
61 61 $ hg tip
62 62 -1:000000000000 (public) [tip ]
63 63 $ hg up --hidden tip --quiet
64 64
65 65 Killing a single changeset with itself should fail
66 66 (simple local safeguard)
67 67
68 68 $ hg debugobsolete `getid kill_me` `getid kill_me`
69 69 abort: bad obsmarker input: in-marker cycle with 97b7c2d76b1845ed3eb988cd612611e72406cef0
70 70 [255]
71 71
72 72 $ cd ..
73 73
74 74 Killing a single changeset with replacement
75 75 (and testing the format option)
76 76
77 77 $ hg init tmpb
78 78 $ cd tmpb
79 79 $ mkcommit a
80 80 $ mkcommit b
81 81 $ mkcommit original_c
82 82 $ hg up "desc('b')"
83 83 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
84 84 $ mkcommit new_c
85 85 created new head
86 86 $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden
87 87 $ hg debugobsolete --config format.obsstore-version=0 --flag 12 `getid original_c` `getid new_c` -d '121 120'
88 88 obsoleted 1 changesets
89 89 $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden
90 90 2:245bde4270cd add original_c
91 91 $ hg debugrevlog -cd
92 92 # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen
93 93 0 -1 -1 0 59 0 0 0 0 58 58 0 1 0
94 94 1 0 -1 59 118 59 59 0 0 58 116 0 1 0
95 95 2 1 -1 118 193 118 118 59 0 76 192 0 1 0
96 96 3 1 -1 193 260 193 193 59 0 66 258 0 2 0
97 97 $ hg debugobsolete
98 98 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
99 99
100 100 (check for version number of the obsstore)
101 101
102 102 $ dd bs=1 count=1 if=.hg/store/obsstore 2>/dev/null
103 103 \x00 (no-eol) (esc)
104 104
105 105 do it again (it read the obsstore before adding new changeset)
106 106
107 107 $ hg up '.^'
108 108 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
109 109 $ mkcommit new_2_c
110 110 created new head
111 111 $ hg debugobsolete -d '1337 0' `getid new_c` `getid new_2_c`
112 112 obsoleted 1 changesets
113 113 $ hg debugobsolete
114 114 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
115 115 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
116 116
117 117 Register two markers with a missing node
118 118
119 119 $ hg up '.^'
120 120 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
121 121 $ mkcommit new_3_c
122 122 created new head
123 123 $ hg debugobsolete -d '1338 0' `getid new_2_c` 1337133713371337133713371337133713371337
124 124 obsoleted 1 changesets
125 125 $ hg debugobsolete -d '1339 0' 1337133713371337133713371337133713371337 `getid new_3_c`
126 126 $ hg debugobsolete
127 127 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
128 128 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
129 129 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
130 130 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
131 131
132 132 Test the --index option of debugobsolete command
133 133 $ hg debugobsolete --index
134 134 0 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
135 135 1 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
136 136 2 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
137 137 3 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
138 138
139 139 Refuse pathological nullid successors
140 140 $ hg debugobsolete -d '9001 0' 1337133713371337133713371337133713371337 0000000000000000000000000000000000000000
141 141 transaction abort!
142 142 rollback completed
143 143 abort: bad obsolescence marker detected: invalid successors nullid
144 144 [255]
145 145
146 146 Check that graphlog detect that a changeset is obsolete:
147 147
148 148 $ hg log -G
149 149 @ 5:5601fb93a350 (draft) [tip ] add new_3_c
150 150 |
151 151 o 1:7c3bad9141dc (draft) [ ] add b
152 152 |
153 153 o 0:1f0dee641bb7 (draft) [ ] add a
154 154
155 155
156 156 check that heads does not report them
157 157
158 158 $ hg heads
159 159 5:5601fb93a350 (draft) [tip ] add new_3_c
160 160 $ hg heads --hidden
161 161 5:5601fb93a350 (draft) [tip ] add new_3_c
162 162 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c
163 163 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c
164 164 2:245bde4270cd (draft *obsolete*) [ ] add original_c
165 165
166 166
167 167 check that summary does not report them
168 168
169 169 $ hg init ../sink
170 170 $ echo '[paths]' >> .hg/hgrc
171 171 $ echo 'default=../sink' >> .hg/hgrc
172 172 $ hg summary --remote
173 173 parent: 5:5601fb93a350 tip
174 174 add new_3_c
175 175 branch: default
176 176 commit: (clean)
177 177 update: (current)
178 178 phases: 3 draft
179 179 remote: 3 outgoing
180 180
181 181 $ hg summary --remote --hidden
182 182 parent: 5:5601fb93a350 tip
183 183 add new_3_c
184 184 branch: default
185 185 commit: (clean)
186 186 update: 3 new changesets, 4 branch heads (merge)
187 187 phases: 6 draft
188 188 remote: 3 outgoing
189 189
190 190 check that various commands work well with filtering
191 191
192 192 $ hg tip
193 193 5:5601fb93a350 (draft) [tip ] add new_3_c
194 194 $ hg log -r 6
195 195 abort: unknown revision '6'!
196 196 [255]
197 197 $ hg log -r 4
198 198 abort: hidden revision '4'!
199 199 (use --hidden to access hidden revisions)
200 200 [255]
201 201 $ hg debugrevspec 'rev(6)'
202 202 $ hg debugrevspec 'rev(4)'
203 203 $ hg debugrevspec 'null'
204 204 -1
205 205
206 206 Check that public changeset are not accounted as obsolete:
207 207
208 208 $ hg --hidden phase --public 2
209 209 $ hg log -G
210 210 @ 5:5601fb93a350 (draft phase-divergent) [tip ] add new_3_c
211 211 |
212 212 | o 2:245bde4270cd (public) [ ] add original_c
213 213 |/
214 214 o 1:7c3bad9141dc (public) [ ] add b
215 215 |
216 216 o 0:1f0dee641bb7 (public) [ ] add a
217 217
218 218
219 219 And that bumped changeset are detected
220 220 --------------------------------------
221 221
222 222 If we didn't filtered obsolete changesets out, 3 and 4 would show up too. Also
223 223 note that the bumped changeset (5:5601fb93a350) is not a direct successor of
224 224 the public changeset
225 225
226 226 $ hg log --hidden -r 'phasedivergent()'
227 227 5:5601fb93a350 (draft phase-divergent) [tip ] add new_3_c
228 228
229 229 And that we can't push bumped changeset
230 230
231 231 $ hg push ../tmpa -r 0 --force #(make repo related)
232 232 pushing to ../tmpa
233 233 searching for changes
234 234 warning: repository is unrelated
235 235 adding changesets
236 236 adding manifests
237 237 adding file changes
238 238 added 1 changesets with 1 changes to 1 files (+1 heads)
239 239 $ hg push ../tmpa
240 240 pushing to ../tmpa
241 241 searching for changes
242 242 abort: push includes phase-divergent changeset: 5601fb93a350!
243 243 [255]
244 244
245 245 Fixing "bumped" situation
246 246 We need to create a clone of 5 and add a special marker with a flag
247 247
248 248 $ hg summary
249 249 parent: 5:5601fb93a350 tip (phase-divergent)
250 250 add new_3_c
251 251 branch: default
252 252 commit: (clean)
253 253 update: 1 new changesets, 2 branch heads (merge)
254 254 phases: 1 draft
255 255 phase-divergent: 1 changesets
256 256 $ hg up '5^'
257 257 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
258 258 $ hg revert -ar 5
259 259 adding new_3_c
260 260 $ hg ci -m 'add n3w_3_c'
261 261 created new head
262 262 $ hg debugobsolete -d '1338 0' --flags 1 `getid new_3_c` `getid n3w_3_c`
263 263 obsoleted 1 changesets
264 264 $ hg log -r 'phasedivergent()'
265 265 $ hg log -G
266 266 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
267 267 |
268 268 | o 2:245bde4270cd (public) [ ] add original_c
269 269 |/
270 270 o 1:7c3bad9141dc (public) [ ] add b
271 271 |
272 272 o 0:1f0dee641bb7 (public) [ ] add a
273 273
274 274
275 275 Basic exclusive testing
276 276
277 277 $ hg log -G --hidden
278 278 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
279 279 |
280 280 | x 5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c
281 281 |/
282 282 | x 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c
283 283 |/
284 284 | x 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c
285 285 |/
286 286 | o 2:245bde4270cd (public) [ ] add original_c
287 287 |/
288 288 o 1:7c3bad9141dc (public) [ ] add b
289 289 |
290 290 o 0:1f0dee641bb7 (public) [ ] add a
291 291
292 292 $ hg debugobsolete --rev 6f9641995072
293 293 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
294 294 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
295 295 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
296 296 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
297 297 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
298 298 $ hg debugobsolete --rev 6f9641995072 --exclusive
299 299 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
300 300 $ hg debugobsolete --rev 5601fb93a350 --hidden
301 301 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
302 302 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
303 303 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
304 304 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
305 305 $ hg debugobsolete --rev 5601fb93a350 --hidden --exclusive
306 306 $ hg debugobsolete --rev 5601fb93a350+6f9641995072 --hidden --exclusive
307 307 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
308 308 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
309 309 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
310 310
311 311 $ cd ..
312 312
313 313 Revision 0 is hidden
314 314 --------------------
315 315
316 316 $ hg init rev0hidden
317 317 $ cd rev0hidden
318 318
319 319 $ mkcommit kill0
320 320 $ hg up -q null
321 321 $ hg debugobsolete `getid kill0`
322 322 obsoleted 1 changesets
323 323 $ mkcommit a
324 324 $ mkcommit b
325 325
326 326 Should pick the first visible revision as "repo" node
327 327
328 328 $ hg archive ../archive-null
329 329 $ cat ../archive-null/.hg_archival.txt
330 330 repo: 1f0dee641bb7258c56bd60e93edfa2405381c41e
331 331 node: 7c3bad9141dcb46ff89abf5f61856facd56e476c
332 332 branch: default
333 333 latesttag: null
334 334 latesttagdistance: 2
335 335 changessincelatesttag: 2
336 336
337 337
338 338 $ cd ..
339 339
340 340 Exchange Test
341 341 ============================
342 342
343 343 Destination repo does not have any data
344 344 ---------------------------------------
345 345
346 346 Simple incoming test
347 347
348 348 $ hg init tmpc
349 349 $ cd tmpc
350 350 $ hg incoming ../tmpb
351 351 comparing with ../tmpb
352 352 0:1f0dee641bb7 (public) [ ] add a
353 353 1:7c3bad9141dc (public) [ ] add b
354 354 2:245bde4270cd (public) [ ] add original_c
355 355 6:6f9641995072 (draft) [tip ] add n3w_3_c
356 356
357 357 Try to pull markers
358 358 (extinct changeset are excluded but marker are pushed)
359 359
360 360 $ hg pull ../tmpb
361 361 pulling from ../tmpb
362 362 requesting all changes
363 363 adding changesets
364 364 adding manifests
365 365 adding file changes
366 366 added 4 changesets with 4 changes to 4 files (+1 heads)
367 367 5 new obsolescence markers
368 368 (run 'hg heads' to see heads, 'hg merge' to merge)
369 369 $ hg debugobsolete
370 370 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
371 371 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
372 372 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
373 373 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
374 374 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
375 375
376 376 Rollback//Transaction support
377 377
378 378 $ hg debugobsolete -d '1340 0' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
379 379 $ hg debugobsolete
380 380 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
381 381 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
382 382 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
383 383 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
384 384 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
385 385 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 (Thu Jan 01 00:22:20 1970 +0000) {'user': 'test'}
386 386 $ hg rollback -n
387 387 repository tip rolled back to revision 3 (undo debugobsolete)
388 388 $ hg rollback
389 389 repository tip rolled back to revision 3 (undo debugobsolete)
390 390 $ hg debugobsolete
391 391 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
392 392 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
393 393 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
394 394 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
395 395 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
396 396
397 397 $ cd ..
398 398
399 399 Try to push markers
400 400
401 401 $ hg init tmpd
402 402 $ hg -R tmpb push tmpd
403 403 pushing to tmpd
404 404 searching for changes
405 405 adding changesets
406 406 adding manifests
407 407 adding file changes
408 408 added 4 changesets with 4 changes to 4 files (+1 heads)
409 409 5 new obsolescence markers
410 410 $ hg -R tmpd debugobsolete | sort
411 411 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
412 412 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
413 413 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
414 414 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
415 415 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
416 416
417 417 Check obsolete keys are exchanged only if source has an obsolete store
418 418
419 419 $ hg init empty
420 420 $ hg --config extensions.debugkeys=debugkeys.py -R empty push tmpd
421 421 pushing to tmpd
422 422 listkeys phases
423 423 listkeys bookmarks
424 424 no changes found
425 425 listkeys phases
426 426 [1]
427 427
428 428 clone support
429 429 (markers are copied and extinct changesets are included to allow hardlinks)
430 430
431 431 $ hg clone tmpb clone-dest
432 432 updating to branch default
433 433 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
434 434 $ hg -R clone-dest log -G --hidden
435 435 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
436 436 |
437 437 | x 5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c
438 438 |/
439 439 | x 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c
440 440 |/
441 441 | x 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c
442 442 |/
443 443 | o 2:245bde4270cd (public) [ ] add original_c
444 444 |/
445 445 o 1:7c3bad9141dc (public) [ ] add b
446 446 |
447 447 o 0:1f0dee641bb7 (public) [ ] add a
448 448
449 449 $ hg -R clone-dest debugobsolete
450 450 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
451 451 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
452 452 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
453 453 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
454 454 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
455 455
456 456
457 457 Destination repo have existing data
458 458 ---------------------------------------
459 459
460 460 On pull
461 461
462 462 $ hg init tmpe
463 463 $ cd tmpe
464 464 $ hg debugobsolete -d '1339 0' 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00
465 465 $ hg pull ../tmpb
466 466 pulling from ../tmpb
467 467 requesting all changes
468 468 adding changesets
469 469 adding manifests
470 470 adding file changes
471 471 added 4 changesets with 4 changes to 4 files (+1 heads)
472 472 5 new obsolescence markers
473 473 (run 'hg heads' to see heads, 'hg merge' to merge)
474 474 $ hg debugobsolete
475 475 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
476 476 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
477 477 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
478 478 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
479 479 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
480 480 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
481 481
482 482
483 483 On push
484 484
485 485 $ hg push ../tmpc
486 486 pushing to ../tmpc
487 487 searching for changes
488 488 no changes found
489 489 1 new obsolescence markers
490 490 [1]
491 491 $ hg -R ../tmpc debugobsolete
492 492 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
493 493 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
494 494 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
495 495 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
496 496 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
497 497 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
498 498
499 499 detect outgoing obsolete and unstable
500 500 ---------------------------------------
501 501
502 502
503 503 $ hg log -G
504 504 o 3:6f9641995072 (draft) [tip ] add n3w_3_c
505 505 |
506 506 | o 2:245bde4270cd (public) [ ] add original_c
507 507 |/
508 508 o 1:7c3bad9141dc (public) [ ] add b
509 509 |
510 510 o 0:1f0dee641bb7 (public) [ ] add a
511 511
512 512 $ hg up 'desc("n3w_3_c")'
513 513 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
514 514 $ mkcommit original_d
515 515 $ mkcommit original_e
516 516 $ hg debugobsolete --record-parents `getid original_d` -d '0 0'
517 517 obsoleted 1 changesets
518 518 $ hg debugobsolete | grep `getid original_d`
519 519 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
520 520 $ hg log -r 'obsolete()'
521 521 4:94b33453f93b (draft *obsolete*) [ ] add original_d
522 522 $ hg summary
523 523 parent: 5:cda648ca50f5 tip (orphan)
524 524 add original_e
525 525 branch: default
526 526 commit: (clean)
527 527 update: 1 new changesets, 2 branch heads (merge)
528 528 phases: 3 draft
529 529 orphan: 1 changesets
530 530 $ hg log -G -r '::orphan()'
531 531 @ 5:cda648ca50f5 (draft orphan) [tip ] add original_e
532 532 |
533 533 x 4:94b33453f93b (draft *obsolete*) [ ] add original_d
534 534 |
535 535 o 3:6f9641995072 (draft) [ ] add n3w_3_c
536 536 |
537 537 o 1:7c3bad9141dc (public) [ ] add b
538 538 |
539 539 o 0:1f0dee641bb7 (public) [ ] add a
540 540
541 541
542 542 refuse to push obsolete changeset
543 543
544 544 $ hg push ../tmpc/ -r 'desc("original_d")'
545 545 pushing to ../tmpc/
546 546 searching for changes
547 547 abort: push includes obsolete changeset: 94b33453f93b!
548 548 [255]
549 549
550 550 refuse to push unstable changeset
551 551
552 552 $ hg push ../tmpc/
553 553 pushing to ../tmpc/
554 554 searching for changes
555 555 abort: push includes orphan changeset: cda648ca50f5!
556 556 [255]
557 557
558 558 Test that extinct changeset are properly detected
559 559
560 560 $ hg log -r 'extinct()'
561 561
562 562 Don't try to push extinct changeset
563 563
564 564 $ hg init ../tmpf
565 565 $ hg out ../tmpf
566 566 comparing with ../tmpf
567 567 searching for changes
568 568 0:1f0dee641bb7 (public) [ ] add a
569 569 1:7c3bad9141dc (public) [ ] add b
570 570 2:245bde4270cd (public) [ ] add original_c
571 571 3:6f9641995072 (draft) [ ] add n3w_3_c
572 572 4:94b33453f93b (draft *obsolete*) [ ] add original_d
573 573 5:cda648ca50f5 (draft orphan) [tip ] add original_e
574 574 $ hg push ../tmpf -f # -f because be push unstable too
575 575 pushing to ../tmpf
576 576 searching for changes
577 577 adding changesets
578 578 adding manifests
579 579 adding file changes
580 580 added 6 changesets with 6 changes to 6 files (+1 heads)
581 581 7 new obsolescence markers
582 582
583 583 no warning displayed
584 584
585 585 $ hg push ../tmpf
586 586 pushing to ../tmpf
587 587 searching for changes
588 588 no changes found
589 589 [1]
590 590
591 591 Do not warn about new head when the new head is a successors of a remote one
592 592
593 593 $ hg log -G
594 594 @ 5:cda648ca50f5 (draft orphan) [tip ] add original_e
595 595 |
596 596 x 4:94b33453f93b (draft *obsolete*) [ ] add original_d
597 597 |
598 598 o 3:6f9641995072 (draft) [ ] add n3w_3_c
599 599 |
600 600 | o 2:245bde4270cd (public) [ ] add original_c
601 601 |/
602 602 o 1:7c3bad9141dc (public) [ ] add b
603 603 |
604 604 o 0:1f0dee641bb7 (public) [ ] add a
605 605
606 606 $ hg up -q 'desc(n3w_3_c)'
607 607 $ mkcommit obsolete_e
608 608 created new head
609 609 $ hg debugobsolete `getid 'original_e'` `getid 'obsolete_e'` \
610 610 > -u 'test <test@example.net>'
611 611 obsoleted 1 changesets
612 612 $ hg outgoing ../tmpf # parasite hg outgoing testin
613 613 comparing with ../tmpf
614 614 searching for changes
615 615 6:3de5eca88c00 (draft) [tip ] add obsolete_e
616 616 $ hg push ../tmpf
617 617 pushing to ../tmpf
618 618 searching for changes
619 619 adding changesets
620 620 adding manifests
621 621 adding file changes
622 622 added 1 changesets with 1 changes to 1 files (+1 heads)
623 623 1 new obsolescence markers
624 624 obsoleted 1 changesets
625 625
626 626 test relevance computation
627 627 ---------------------------------------
628 628
629 629 Checking simple case of "marker relevance".
630 630
631 631
632 632 Reminder of the repo situation
633 633
634 634 $ hg log --hidden --graph
635 635 @ 6:3de5eca88c00 (draft) [tip ] add obsolete_e
636 636 |
637 637 | x 5:cda648ca50f5 (draft *obsolete*) [ ] add original_e
638 638 | |
639 639 | x 4:94b33453f93b (draft *obsolete*) [ ] add original_d
640 640 |/
641 641 o 3:6f9641995072 (draft) [ ] add n3w_3_c
642 642 |
643 643 | o 2:245bde4270cd (public) [ ] add original_c
644 644 |/
645 645 o 1:7c3bad9141dc (public) [ ] add b
646 646 |
647 647 o 0:1f0dee641bb7 (public) [ ] add a
648 648
649 649
650 650 List of all markers
651 651
652 652 $ hg debugobsolete
653 653 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
654 654 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
655 655 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
656 656 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
657 657 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
658 658 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
659 659 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
660 660 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test <test@example.net>'} (glob)
661 661
662 662 List of changesets with no chain
663 663
664 664 $ hg debugobsolete --hidden --rev ::2
665 665
666 666 List of changesets that are included on marker chain
667 667
668 668 $ hg debugobsolete --hidden --rev 6
669 669 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test <test@example.net>'} (glob)
670 670
671 671 List of changesets with a longer chain, (including a pruned children)
672 672
673 673 $ hg debugobsolete --hidden --rev 3
674 674 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
675 675 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
676 676 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
677 677 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
678 678 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
679 679 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
680 680 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
681 681
682 682 List of both
683 683
684 684 $ hg debugobsolete --hidden --rev 3::6
685 685 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
686 686 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
687 687 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
688 688 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
689 689 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
690 690 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
691 691 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test <test@example.net>'} (glob)
692 692 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
693 693
694 694 List of all markers in JSON
695 695
696 696 $ hg debugobsolete -Tjson
697 697 [
698 698 {
699 699 "date": [1339.0, 0],
700 700 "flag": 0,
701 701 "metadata": {"user": "test"},
702 702 "prednode": "1339133913391339133913391339133913391339",
703 703 "succnodes": ["ca819180edb99ed25ceafb3e9584ac287e240b00"]
704 704 },
705 705 {
706 706 "date": [1339.0, 0],
707 707 "flag": 0,
708 708 "metadata": {"user": "test"},
709 709 "prednode": "1337133713371337133713371337133713371337",
710 710 "succnodes": ["5601fb93a350734d935195fee37f4054c529ff39"]
711 711 },
712 712 {
713 713 "date": [121.0, 120],
714 714 "flag": 12,
715 715 "metadata": {"user": "test"},
716 716 "prednode": "245bde4270cd1072a27757984f9cda8ba26f08ca",
717 717 "succnodes": ["cdbce2fbb16313928851e97e0d85413f3f7eb77f"]
718 718 },
719 719 {
720 720 "date": [1338.0, 0],
721 721 "flag": 1,
722 722 "metadata": {"user": "test"},
723 723 "prednode": "5601fb93a350734d935195fee37f4054c529ff39",
724 724 "succnodes": ["6f96419950729f3671185b847352890f074f7557"]
725 725 },
726 726 {
727 727 "date": [1338.0, 0],
728 728 "flag": 0,
729 729 "metadata": {"user": "test"},
730 730 "prednode": "ca819180edb99ed25ceafb3e9584ac287e240b00",
731 731 "succnodes": ["1337133713371337133713371337133713371337"]
732 732 },
733 733 {
734 734 "date": [1337.0, 0],
735 735 "flag": 0,
736 736 "metadata": {"user": "test"},
737 737 "prednode": "cdbce2fbb16313928851e97e0d85413f3f7eb77f",
738 738 "succnodes": ["ca819180edb99ed25ceafb3e9584ac287e240b00"]
739 739 },
740 740 {
741 741 "date": [0.0, 0],
742 742 "flag": 0,
743 743 "metadata": {"user": "test"},
744 744 "parentnodes": ["6f96419950729f3671185b847352890f074f7557"],
745 745 "prednode": "94b33453f93bdb8d457ef9b770851a618bf413e1",
746 746 "succnodes": []
747 747 },
748 748 {
749 749 "date": *, (glob)
750 750 "flag": 0,
751 751 "metadata": {"user": "test <test@example.net>"},
752 752 "prednode": "cda648ca50f50482b7055c0b0c4c117bba6733d9",
753 753 "succnodes": ["3de5eca88c00aa039da7399a220f4a5221faa585"]
754 754 }
755 755 ]
756 756
757 757 Template keywords
758 758
759 759 $ hg debugobsolete -r6 -T '{succnodes % "{node|short}"} {date|shortdate}\n'
760 760 3de5eca88c00 ????-??-?? (glob)
761 761 $ hg debugobsolete -r6 -T '{join(metadata % "{key}={value}", " ")}\n'
762 762 user=test <test@example.net>
763 763 $ hg debugobsolete -r6 -T '{metadata}\n'
764 764 'user': 'test <test@example.net>'
765 765 $ hg debugobsolete -r6 -T '{flag} {get(metadata, "user")}\n'
766 766 0 test <test@example.net>
767 767
768 768 Test the debug output for exchange
769 769 ----------------------------------
770 770
771 771 $ hg pull ../tmpb --config 'experimental.obsmarkers-exchange-debug=True' # bundle2
772 772 pulling from ../tmpb
773 773 searching for changes
774 774 no changes found
775 775 obsmarker-exchange: 346 bytes received
776 776
777 777 check hgweb does not explode
778 778 ====================================
779 779
780 780 $ hg unbundle $TESTDIR/bundles/hgweb+obs.hg
781 781 adding changesets
782 782 adding manifests
783 783 adding file changes
784 784 added 62 changesets with 63 changes to 9 files (+60 heads)
785 785 (run 'hg heads .' to see heads, 'hg merge' to merge)
786 786 $ for node in `hg log -r 'desc(babar_)' --template '{node}\n'`;
787 787 > do
788 788 > hg debugobsolete $node
789 789 > done
790 790 obsoleted 1 changesets
791 791 obsoleted 1 changesets
792 792 obsoleted 1 changesets
793 793 obsoleted 1 changesets
794 794 obsoleted 1 changesets
795 795 obsoleted 1 changesets
796 796 obsoleted 1 changesets
797 797 obsoleted 1 changesets
798 798 obsoleted 1 changesets
799 799 obsoleted 1 changesets
800 800 obsoleted 1 changesets
801 801 obsoleted 1 changesets
802 802 obsoleted 1 changesets
803 803 obsoleted 1 changesets
804 804 obsoleted 1 changesets
805 805 obsoleted 1 changesets
806 806 obsoleted 1 changesets
807 807 obsoleted 1 changesets
808 808 obsoleted 1 changesets
809 809 obsoleted 1 changesets
810 810 obsoleted 1 changesets
811 811 obsoleted 1 changesets
812 812 obsoleted 1 changesets
813 813 obsoleted 1 changesets
814 814 obsoleted 1 changesets
815 815 obsoleted 1 changesets
816 816 obsoleted 1 changesets
817 817 obsoleted 1 changesets
818 818 obsoleted 1 changesets
819 819 obsoleted 1 changesets
820 820 obsoleted 1 changesets
821 821 obsoleted 1 changesets
822 822 obsoleted 1 changesets
823 823 obsoleted 1 changesets
824 824 obsoleted 1 changesets
825 825 obsoleted 1 changesets
826 826 obsoleted 1 changesets
827 827 obsoleted 1 changesets
828 828 obsoleted 1 changesets
829 829 obsoleted 1 changesets
830 830 obsoleted 1 changesets
831 831 obsoleted 1 changesets
832 832 obsoleted 1 changesets
833 833 obsoleted 1 changesets
834 834 obsoleted 1 changesets
835 835 obsoleted 1 changesets
836 836 obsoleted 1 changesets
837 837 obsoleted 1 changesets
838 838 obsoleted 1 changesets
839 839 obsoleted 1 changesets
840 840 obsoleted 1 changesets
841 841 obsoleted 1 changesets
842 842 obsoleted 1 changesets
843 843 obsoleted 1 changesets
844 844 obsoleted 1 changesets
845 845 obsoleted 1 changesets
846 846 obsoleted 1 changesets
847 847 obsoleted 1 changesets
848 848 obsoleted 1 changesets
849 849 obsoleted 1 changesets
850 850 $ hg up tip
851 851 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
852 852
853 853 #if serve
854 854
855 855 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
856 856 $ cat hg.pid >> $DAEMON_PIDS
857 857
858 858 check changelog view
859 859
860 860 $ get-with-headers.py --headeronly localhost:$HGPORT 'shortlog/'
861 861 200 Script output follows
862 862
863 863 check graph view
864 864
865 865 $ get-with-headers.py --headeronly localhost:$HGPORT 'graph'
866 866 200 Script output follows
867 867
868 868 check filelog view
869 869
870 870 $ get-with-headers.py --headeronly localhost:$HGPORT 'log/'`hg log -r . -T "{node}"`/'babar'
871 871 200 Script output follows
872 872
873 873 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/68'
874 874 200 Script output follows
875 875 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/67'
876 876 404 Not Found
877 877 [1]
878 878
879 879 check that web.view config option:
880 880
881 881 $ killdaemons.py hg.pid
882 882 $ cat >> .hg/hgrc << EOF
883 883 > [web]
884 884 > view=all
885 885 > EOF
886 886 $ wait
887 887 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
888 888 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/67'
889 889 200 Script output follows
890 890 $ killdaemons.py hg.pid
891 891
892 892 Checking _enable=False warning if obsolete marker exists
893 893
894 894 $ echo '[experimental]' >> $HGRCPATH
895 895 $ echo "stabilization=" >> $HGRCPATH
896 896 $ hg log -r tip
897 897 obsolete feature not enabled but 68 markers found!
898 898 68:c15e9edfca13 (draft) [tip ] add celestine
899 899
900 900 reenable for later test
901 901
902 902 $ echo '[experimental]' >> $HGRCPATH
903 903 $ echo "stabilization=createmarkers,exchange" >> $HGRCPATH
904 904
905 905 $ rm hg.pid access.log errors.log
906 906 #endif
907 907
908 908 Several troubles on the same changeset (create an unstable and bumped changeset)
909 909
910 910 $ hg debugobsolete `getid obsolete_e`
911 911 obsoleted 1 changesets
912 912 $ hg debugobsolete `getid original_c` `getid babar`
913 913 $ hg log --config ui.logtemplate= -r 'phasedivergent() and orphan()'
914 914 changeset: 7:50c51b361e60
915 915 user: test
916 916 date: Thu Jan 01 00:00:00 1970 +0000
917 917 instability: orphan, phase-divergent
918 918 summary: add babar
919 919
920 920
921 921 test the "obsolete" templatekw
922 922
923 923 $ hg log -r 'obsolete()'
924 924 6:3de5eca88c00 (draft *obsolete*) [ ] add obsolete_e
925 925
926 926 test the "troubles" templatekw
927 927
928 928 $ hg log -r 'phasedivergent() and orphan()'
929 929 7:50c51b361e60 (draft orphan phase-divergent) [ ] add babar
930 930
931 931 test the default cmdline template
932 932
933 933 $ hg log -T default -r 'phasedivergent()'
934 934 changeset: 7:50c51b361e60
935 935 user: test
936 936 date: Thu Jan 01 00:00:00 1970 +0000
937 937 instability: orphan, phase-divergent
938 938 summary: add babar
939 939
940 940 $ hg log -T default -r 'obsolete()'
941 941 changeset: 6:3de5eca88c00
942 942 parent: 3:6f9641995072
943 943 user: test
944 944 date: Thu Jan 01 00:00:00 1970 +0000
945 945 summary: add obsolete_e
946 946
947 947
948 948 test the obsolete labels
949 949
950 950 $ hg log --config ui.logtemplate= --color=debug -r 'phasedivergent()'
951 951 [log.changeset changeset.draft changeset.unstable instability.orphan instability.phase-divergent|changeset: 7:50c51b361e60]
952 952 [log.user|user: test]
953 953 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
954 954 [log.instability|instability: orphan, phase-divergent]
955 955 [log.summary|summary: add babar]
956 956
957 957
958 958 $ hg log -T default -r 'phasedivergent()' --color=debug
959 959 [log.changeset changeset.draft changeset.unstable instability.orphaninstability.phase-divergent|changeset: 7:50c51b361e60]
960 960 [log.user|user: test]
961 961 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
962 962 [log.instability|instability: orphan, phase-divergent]
963 963 [log.summary|summary: add babar]
964 964
965 965
966 966 $ hg log --config ui.logtemplate= --color=debug -r "obsolete()"
967 967 [log.changeset changeset.draft changeset.obsolete|changeset: 6:3de5eca88c00]
968 968 [log.parent changeset.draft|parent: 3:6f9641995072]
969 969 [log.user|user: test]
970 970 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
971 971 [log.summary|summary: add obsolete_e]
972 972
973 973
974 974 $ hg log -T default -r 'obsolete()' --color=debug
975 975 [log.changeset changeset.draft changeset.obsolete|changeset: 6:3de5eca88c00]
976 976 [log.parent changeset.draft|parent: 3:6f9641995072]
977 977 [log.user|user: test]
978 978 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
979 979 [log.summary|summary: add obsolete_e]
980 980
981 981
982 982 test summary output
983 983
984 984 $ hg up -r 'phasedivergent() and orphan()'
985 985 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
986 986 $ hg summary
987 987 parent: 7:50c51b361e60 (orphan, phase-divergent)
988 988 add babar
989 989 branch: default
990 990 commit: (clean)
991 991 update: 2 new changesets (update)
992 992 phases: 4 draft
993 993 orphan: 2 changesets
994 994 phase-divergent: 1 changesets
995 995 $ hg up -r 'obsolete()'
996 996 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
997 997 $ hg summary
998 998 parent: 6:3de5eca88c00 (obsolete)
999 999 add obsolete_e
1000 1000 branch: default
1001 1001 commit: (clean)
1002 1002 update: 3 new changesets (update)
1003 1003 phases: 4 draft
1004 1004 orphan: 2 changesets
1005 1005 phase-divergent: 1 changesets
1006 1006
1007 1007 Test incoming/outcoming with changesets obsoleted remotely, known locally
1008 1008 ===============================================================================
1009 1009
1010 1010 This test issue 3805
1011 1011
1012 1012 $ hg init repo-issue3805
1013 1013 $ cd repo-issue3805
1014 1014 $ echo "base" > base
1015 1015 $ hg ci -Am "base"
1016 1016 adding base
1017 1017 $ echo "foo" > foo
1018 1018 $ hg ci -Am "A"
1019 1019 adding foo
1020 1020 $ hg clone . ../other-issue3805
1021 1021 updating to branch default
1022 1022 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1023 1023 $ echo "bar" >> foo
1024 1024 $ hg ci --amend
1025 1025 $ cd ../other-issue3805
1026 1026 $ hg log -G
1027 1027 @ 1:29f0c6921ddd (draft) [tip ] A
1028 1028 |
1029 1029 o 0:d20a80d4def3 (draft) [ ] base
1030 1030
1031 1031 $ hg log -G -R ../repo-issue3805
1032 @ 3:323a9c3ddd91 (draft) [tip ] A
1032 @ 2:323a9c3ddd91 (draft) [tip ] A
1033 1033 |
1034 1034 o 0:d20a80d4def3 (draft) [ ] base
1035 1035
1036 1036 $ hg incoming
1037 1037 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
1038 1038 searching for changes
1039 3:323a9c3ddd91 (draft) [tip ] A
1039 2:323a9c3ddd91 (draft) [tip ] A
1040 1040 $ hg incoming --bundle ../issue3805.hg
1041 1041 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
1042 1042 searching for changes
1043 3:323a9c3ddd91 (draft) [tip ] A
1043 2:323a9c3ddd91 (draft) [tip ] A
1044 1044 $ hg outgoing
1045 1045 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
1046 1046 searching for changes
1047 1047 1:29f0c6921ddd (draft) [tip ] A
1048 1048
1049 1049 #if serve
1050 1050
1051 1051 $ hg serve -R ../repo-issue3805 -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1052 1052 $ cat hg.pid >> $DAEMON_PIDS
1053 1053
1054 1054 $ hg incoming http://localhost:$HGPORT
1055 1055 comparing with http://localhost:$HGPORT/
1056 1056 searching for changes
1057 1057 2:323a9c3ddd91 (draft) [tip ] A
1058 1058 $ hg outgoing http://localhost:$HGPORT
1059 1059 comparing with http://localhost:$HGPORT/
1060 1060 searching for changes
1061 1061 1:29f0c6921ddd (draft) [tip ] A
1062 1062
1063 1063 $ killdaemons.py
1064 1064
1065 1065 #endif
1066 1066
1067 1067 This test issue 3814
1068 1068
1069 1069 (nothing to push but locally hidden changeset)
1070 1070
1071 1071 $ cd ..
1072 1072 $ hg init repo-issue3814
1073 1073 $ cd repo-issue3805
1074 1074 $ hg push -r 323a9c3ddd91 ../repo-issue3814
1075 1075 pushing to ../repo-issue3814
1076 1076 searching for changes
1077 1077 adding changesets
1078 1078 adding manifests
1079 1079 adding file changes
1080 1080 added 2 changesets with 2 changes to 2 files
1081 2 new obsolescence markers
1081 1 new obsolescence markers
1082 1082 $ hg out ../repo-issue3814
1083 1083 comparing with ../repo-issue3814
1084 1084 searching for changes
1085 1085 no changes found
1086 1086 [1]
1087 1087
1088 1088 Test that a local tag blocks a changeset from being hidden
1089 1089
1090 1090 $ hg tag -l visible -r 1 --hidden
1091 1091 $ hg log -G
1092 @ 3:323a9c3ddd91 (draft) [tip ] A
1092 @ 2:323a9c3ddd91 (draft) [tip ] A
1093 1093 |
1094 1094 | x 1:29f0c6921ddd (draft *obsolete*) [visible ] A
1095 1095 |/
1096 1096 o 0:d20a80d4def3 (draft) [ ] base
1097 1097
1098 1098 Test that removing a local tag does not cause some commands to fail
1099 1099
1100 1100 $ hg tag -l -r tip tiptag
1101 1101 $ hg tags
1102 tiptag 3:323a9c3ddd91
1103 tip 3:323a9c3ddd91
1102 tiptag 2:323a9c3ddd91
1103 tip 2:323a9c3ddd91
1104 1104 visible 1:29f0c6921ddd
1105 1105 $ hg --config extensions.strip= strip -r tip --no-backup
1106 1106 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1107 1107 $ hg tags
1108 1108 visible 1:29f0c6921ddd
1109 1109 tip 1:29f0c6921ddd
1110 1110
1111 1111 Test bundle overlay onto hidden revision
1112 1112
1113 1113 $ cd ..
1114 1114 $ hg init repo-bundleoverlay
1115 1115 $ cd repo-bundleoverlay
1116 1116 $ echo "A" > foo
1117 1117 $ hg ci -Am "A"
1118 1118 adding foo
1119 1119 $ echo "B" >> foo
1120 1120 $ hg ci -m "B"
1121 1121 $ hg up 0
1122 1122 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1123 1123 $ echo "C" >> foo
1124 1124 $ hg ci -m "C"
1125 1125 created new head
1126 1126 $ hg log -G
1127 1127 @ 2:c186d7714947 (draft) [tip ] C
1128 1128 |
1129 1129 | o 1:44526ebb0f98 (draft) [ ] B
1130 1130 |/
1131 1131 o 0:4b34ecfb0d56 (draft) [ ] A
1132 1132
1133 1133
1134 1134 $ hg clone -r1 . ../other-bundleoverlay
1135 1135 adding changesets
1136 1136 adding manifests
1137 1137 adding file changes
1138 1138 added 2 changesets with 2 changes to 1 files
1139 1139 updating to branch default
1140 1140 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1141 1141 $ cd ../other-bundleoverlay
1142 1142 $ echo "B+" >> foo
1143 1143 $ hg ci --amend -m "B+"
1144 1144 $ hg log -G --hidden
1145 @ 3:b7d587542d40 (draft) [tip ] B+
1145 @ 2:b7d587542d40 (draft) [tip ] B+
1146 1146 |
1147 | x 2:eb95e9297e18 (draft *obsolete*) [ ] temporary amend commit for 44526ebb0f98
1148 | |
1149 1147 | x 1:44526ebb0f98 (draft *obsolete*) [ ] B
1150 1148 |/
1151 1149 o 0:4b34ecfb0d56 (draft) [ ] A
1152 1150
1153 1151
1154 1152 $ hg incoming ../repo-bundleoverlay --bundle ../bundleoverlay.hg
1155 1153 comparing with ../repo-bundleoverlay
1156 1154 searching for changes
1157 1155 1:44526ebb0f98 (draft) [ ] B
1158 1156 2:c186d7714947 (draft) [tip ] C
1159 1157 $ hg log -G -R ../bundleoverlay.hg
1160 o 4:c186d7714947 (draft) [tip ] C
1158 o 3:c186d7714947 (draft) [tip ] C
1161 1159 |
1162 | @ 3:b7d587542d40 (draft) [ ] B+
1160 | @ 2:b7d587542d40 (draft) [ ] B+
1163 1161 |/
1164 1162 o 0:4b34ecfb0d56 (draft) [ ] A
1165 1163
1166 1164
1167 1165 #if serve
1168 1166
1169 1167 Test issue 4506
1170 1168
1171 1169 $ cd ..
1172 1170 $ hg init repo-issue4506
1173 1171 $ cd repo-issue4506
1174 1172 $ echo "0" > foo
1175 1173 $ hg add foo
1176 1174 $ hg ci -m "content-0"
1177 1175
1178 1176 $ hg up null
1179 1177 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1180 1178 $ echo "1" > bar
1181 1179 $ hg add bar
1182 1180 $ hg ci -m "content-1"
1183 1181 created new head
1184 1182 $ hg up 0
1185 1183 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1186 1184 $ hg graft 1
1187 1185 grafting 1:1c9eddb02162 "content-1" (tip)
1188 1186
1189 1187 $ hg debugobsolete `hg log -r1 -T'{node}'` `hg log -r2 -T'{node}'`
1190 1188 obsoleted 1 changesets
1191 1189
1192 1190 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1193 1191 $ cat hg.pid >> $DAEMON_PIDS
1194 1192
1195 1193 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/1'
1196 1194 404 Not Found
1197 1195 [1]
1198 1196 $ get-with-headers.py --headeronly localhost:$HGPORT 'file/tip/bar'
1199 1197 200 Script output follows
1200 1198 $ get-with-headers.py --headeronly localhost:$HGPORT 'annotate/tip/bar'
1201 1199 200 Script output follows
1202 1200
1203 1201 $ killdaemons.py
1204 1202
1205 1203 #endif
1206 1204
1207 1205 Test heads computation on pending index changes with obsolescence markers
1208 1206 $ cd ..
1209 1207 $ cat >$TESTTMP/test_extension.py << EOF
1210 1208 > from __future__ import absolute_import
1211 1209 > from mercurial.i18n import _
1212 1210 > from mercurial import cmdutil, registrar
1213 1211 >
1214 1212 > cmdtable = {}
1215 1213 > command = registrar.command(cmdtable)
1216 1214 > @command(b"amendtransient",[], _('hg amendtransient [rev]'))
1217 1215 > def amend(ui, repo, *pats, **opts):
1218 1216 > def commitfunc(ui, repo, message, match, opts):
1219 1217 > return repo.commit(message, repo['.'].user(), repo['.'].date(), match)
1220 1218 > opts['message'] = 'Test'
1221 1219 > opts['logfile'] = None
1222 1220 > cmdutil.amend(ui, repo, commitfunc, repo['.'], {}, pats, opts)
1223 1221 > ui.write('%s\n' % repo.changelog.headrevs())
1224 1222 > EOF
1225 1223 $ cat >> $HGRCPATH << EOF
1226 1224 > [extensions]
1227 1225 > testextension=$TESTTMP/test_extension.py
1228 1226 > EOF
1229 1227 $ hg init repo-issue-nativerevs-pending-changes
1230 1228 $ cd repo-issue-nativerevs-pending-changes
1231 1229 $ mkcommit a
1232 1230 $ mkcommit b
1233 1231 $ hg up ".^"
1234 1232 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1235 1233 $ echo aa > a
1236 1234 $ hg amendtransient
1237 [1, 3]
1235 [1, 2]
1238 1236
1239 1237 Test cache consistency for the visible filter
1240 1238 1) We want to make sure that the cached filtered revs are invalidated when
1241 1239 bookmarks change
1242 1240 $ cd ..
1243 1241 $ cat >$TESTTMP/test_extension.py << EOF
1244 1242 > from __future__ import absolute_import, print_function
1245 1243 > import weakref
1246 1244 > from mercurial import (
1247 1245 > bookmarks,
1248 1246 > cmdutil,
1249 1247 > extensions,
1250 1248 > repoview,
1251 1249 > )
1252 1250 > def _bookmarkchanged(orig, bkmstoreinst, *args, **kwargs):
1253 1251 > reporef = weakref.ref(bkmstoreinst._repo)
1254 1252 > def trhook(tr):
1255 1253 > repo = reporef()
1256 1254 > hidden1 = repoview.computehidden(repo)
1257 1255 > hidden = repoview.filterrevs(repo, 'visible')
1258 1256 > if sorted(hidden1) != sorted(hidden):
1259 1257 > print("cache inconsistency")
1260 1258 > bkmstoreinst._repo.currenttransaction().addpostclose('test_extension', trhook)
1261 1259 > orig(bkmstoreinst, *args, **kwargs)
1262 1260 > def extsetup(ui):
1263 1261 > extensions.wrapfunction(bookmarks.bmstore, '_recordchange',
1264 1262 > _bookmarkchanged)
1265 1263 > EOF
1266 1264
1267 1265 $ hg init repo-cache-inconsistency
1268 1266 $ cd repo-issue-nativerevs-pending-changes
1269 1267 $ mkcommit a
1270 1268 a already tracked!
1271 1269 $ mkcommit b
1272 1270 $ hg id
1273 1271 13bedc178fce tip
1274 1272 $ echo "hello" > b
1275 1273 $ hg commit --amend -m "message"
1276 1274 $ hg book bookb -r 13bedc178fce --hidden
1277 1275 $ hg log -r 13bedc178fce
1278 5:13bedc178fce (draft *obsolete*) [ bookb] add b
1276 4:13bedc178fce (draft *obsolete*) [ bookb] add b
1279 1277 $ hg book -d bookb
1280 1278 $ hg log -r 13bedc178fce
1281 1279 abort: hidden revision '13bedc178fce'!
1282 1280 (use --hidden to access hidden revisions)
1283 1281 [255]
1284 1282
1285 1283 Empty out the test extension, as it isn't compatible with later parts
1286 1284 of the test.
1287 1285 $ echo > $TESTTMP/test_extension.py
1288 1286
1289 1287 Test ability to pull changeset with locally applying obsolescence markers
1290 1288 (issue4945)
1291 1289
1292 1290 $ cd ..
1293 1291 $ hg init issue4845
1294 1292 $ cd issue4845
1295 1293
1296 1294 $ echo foo > f0
1297 1295 $ hg add f0
1298 1296 $ hg ci -m '0'
1299 1297 $ echo foo > f1
1300 1298 $ hg add f1
1301 1299 $ hg ci -m '1'
1302 1300 $ echo foo > f2
1303 1301 $ hg add f2
1304 1302 $ hg ci -m '2'
1305 1303
1306 1304 $ echo bar > f2
1307 1305 $ hg commit --amend --config experimetnal.stabilization=createmarkers
1308 1306 $ hg log -G
1309 @ 4:b0551702f918 (draft) [tip ] 2
1307 @ 3:b0551702f918 (draft) [tip ] 2
1310 1308 |
1311 1309 o 1:e016b03fd86f (draft) [ ] 1
1312 1310 |
1313 1311 o 0:a78f55e5508c (draft) [ ] 0
1314 1312
1315 1313 $ hg log -G --hidden
1316 @ 4:b0551702f918 (draft) [tip ] 2
1314 @ 3:b0551702f918 (draft) [tip ] 2
1317 1315 |
1318 | x 3:f27abbcc1f77 (draft *obsolete*) [ ] temporary amend commit for e008cf283490
1319 | |
1320 1316 | x 2:e008cf283490 (draft *obsolete*) [ ] 2
1321 1317 |/
1322 1318 o 1:e016b03fd86f (draft) [ ] 1
1323 1319 |
1324 1320 o 0:a78f55e5508c (draft) [ ] 0
1325 1321
1326 1322
1327 1323 $ hg strip --hidden -r 2 --config extensions.strip= --config devel.strip-obsmarkers=no
1328 saved backup bundle to $TESTTMP/tmpe/issue4845/.hg/strip-backup/e008cf283490-39c978dc-backup.hg (glob)
1324 saved backup bundle to $TESTTMP/tmpe/issue4845/.hg/strip-backup/e008cf283490-ede36964-backup.hg (glob)
1329 1325 $ hg debugobsolete
1330 1326 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (*) {'user': 'test'} (glob)
1331 f27abbcc1f77fb409cf9160482fe619541e2d605 0 {e008cf2834908e5d6b0f792a9d4b0e2272260fb8} (*) {'user': 'test'} (glob)
1332 1327 $ hg log -G
1333 1328 @ 2:b0551702f918 (draft) [tip ] 2
1334 1329 |
1335 1330 o 1:e016b03fd86f (draft) [ ] 1
1336 1331 |
1337 1332 o 0:a78f55e5508c (draft) [ ] 0
1338 1333
1339 1334 $ hg log -G --hidden
1340 1335 @ 2:b0551702f918 (draft) [tip ] 2
1341 1336 |
1342 1337 o 1:e016b03fd86f (draft) [ ] 1
1343 1338 |
1344 1339 o 0:a78f55e5508c (draft) [ ] 0
1345 1340
1346 1341 $ hg debugbundle .hg/strip-backup/e008cf283490-*-backup.hg
1347 1342 Stream params: {Compression: BZ}
1348 changegroup -- {nbchanges: 2, version: 02}
1343 changegroup -- {nbchanges: 1, version: 02}
1349 1344 e008cf2834908e5d6b0f792a9d4b0e2272260fb8
1350 f27abbcc1f77fb409cf9160482fe619541e2d605
1351 obsmarkers -- {}
1352 version: 1 (70 bytes)
1353 f27abbcc1f77fb409cf9160482fe619541e2d605 0 {e008cf2834908e5d6b0f792a9d4b0e2272260fb8} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1354 1345 phase-heads -- {}
1355 f27abbcc1f77fb409cf9160482fe619541e2d605 draft
1346 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 draft
1356 1347
1357 1348 $ hg pull .hg/strip-backup/e008cf283490-*-backup.hg
1358 pulling from .hg/strip-backup/e008cf283490-39c978dc-backup.hg
1349 pulling from .hg/strip-backup/e008cf283490-ede36964-backup.hg
1359 1350 searching for changes
1360 1351 no changes found
1361 1352 $ hg debugobsolete
1362 1353 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (*) {'user': 'test'} (glob)
1363 f27abbcc1f77fb409cf9160482fe619541e2d605 0 {e008cf2834908e5d6b0f792a9d4b0e2272260fb8} (*) {'user': 'test'} (glob)
1364 1354 $ hg log -G
1365 1355 @ 2:b0551702f918 (draft) [tip ] 2
1366 1356 |
1367 1357 o 1:e016b03fd86f (draft) [ ] 1
1368 1358 |
1369 1359 o 0:a78f55e5508c (draft) [ ] 0
1370 1360
1371 1361 $ hg log -G --hidden
1372 1362 @ 2:b0551702f918 (draft) [tip ] 2
1373 1363 |
1374 1364 o 1:e016b03fd86f (draft) [ ] 1
1375 1365 |
1376 1366 o 0:a78f55e5508c (draft) [ ] 0
1377 1367
1378 1368
1379 1369 Testing that strip remove markers:
1380 1370
1381 1371 $ hg strip -r 1 --config extensions.strip=
1382 1372 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1383 1373 saved backup bundle to $TESTTMP/tmpe/issue4845/.hg/strip-backup/e016b03fd86f-65ede734-backup.hg (glob)
1384 1374 $ hg debugobsolete
1385 1375 $ hg log -G
1386 1376 @ 0:a78f55e5508c (draft) [tip ] 0
1387 1377
1388 1378 $ hg log -G --hidden
1389 1379 @ 0:a78f55e5508c (draft) [tip ] 0
1390 1380
1391 1381 $ hg debugbundle .hg/strip-backup/e016b03fd86f-*-backup.hg
1392 1382 Stream params: {Compression: BZ}
1393 1383 changegroup -- {nbchanges: 2, version: 02}
1394 1384 e016b03fd86fcccc54817d120b90b751aaf367d6
1395 1385 b0551702f918510f01ae838ab03a463054c67b46
1396 1386 obsmarkers -- {}
1397 version: 1 (139 bytes)
1387 version: 1 (70 bytes)
1398 1388 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1399 f27abbcc1f77fb409cf9160482fe619541e2d605 0 {e008cf2834908e5d6b0f792a9d4b0e2272260fb8} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1400 1389 phase-heads -- {}
1401 1390 b0551702f918510f01ae838ab03a463054c67b46 draft
1402 1391
1403 1392 $ hg unbundle .hg/strip-backup/e016b03fd86f-*-backup.hg
1404 1393 adding changesets
1405 1394 adding manifests
1406 1395 adding file changes
1407 1396 added 2 changesets with 2 changes to 2 files
1408 2 new obsolescence markers
1397 1 new obsolescence markers
1409 1398 (run 'hg update' to get a working copy)
1410 1399 $ hg debugobsolete | sort
1411 1400 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (*) {'user': 'test'} (glob)
1412 f27abbcc1f77fb409cf9160482fe619541e2d605 0 {e008cf2834908e5d6b0f792a9d4b0e2272260fb8} (*) {'user': 'test'} (glob)
1413 1401 $ hg log -G
1414 1402 o 2:b0551702f918 (draft) [tip ] 2
1415 1403 |
1416 1404 o 1:e016b03fd86f (draft) [ ] 1
1417 1405 |
1418 1406 @ 0:a78f55e5508c (draft) [ ] 0
1419 1407
1420 1408 $ hg log -G --hidden
1421 1409 o 2:b0551702f918 (draft) [tip ] 2
1422 1410 |
1423 1411 o 1:e016b03fd86f (draft) [ ] 1
1424 1412 |
1425 1413 @ 0:a78f55e5508c (draft) [ ] 0
1426 1414
1427 1415 Test that 'hg debugobsolete --index --rev' can show indices of obsmarkers when
1428 1416 only a subset of those are displayed (because of --rev option)
1429 1417 $ hg init doindexrev
1430 1418 $ cd doindexrev
1431 1419 $ echo a > a
1432 1420 $ hg ci -Am a
1433 1421 adding a
1434 1422 $ hg ci --amend -m aa
1435 1423 $ echo b > b
1436 1424 $ hg ci -Am b
1437 1425 adding b
1438 1426 $ hg ci --amend -m bb
1439 1427 $ echo c > c
1440 1428 $ hg ci -Am c
1441 1429 adding c
1442 1430 $ hg ci --amend -m cc
1443 1431 $ echo d > d
1444 1432 $ hg ci -Am d
1445 1433 adding d
1446 1434 $ hg ci --amend -m dd --config experimental.stabilization.track-operation=1
1447 1435 $ hg debugobsolete --index --rev "3+7"
1448 1436 1 6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1 d27fb9b066076fd921277a4b9e8b9cb48c95bc6a 0 \(.*\) {'user': 'test'} (re)
1449 1437 3 4715cf767440ed891755448016c2b8cf70760c30 7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d 0 \(.*\) {'operation': 'amend', 'user': 'test'} (re)
1450 1438 $ hg debugobsolete --index --rev "3+7" -Tjson
1451 1439 [
1452 1440 {
1453 1441 "date": [0.0, 0],
1454 1442 "flag": 0,
1455 1443 "index": 1,
1456 1444 "metadata": {"user": "test"},
1457 1445 "prednode": "6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1",
1458 1446 "succnodes": ["d27fb9b066076fd921277a4b9e8b9cb48c95bc6a"]
1459 1447 },
1460 1448 {
1461 1449 "date": [0.0, 0],
1462 1450 "flag": 0,
1463 1451 "index": 3,
1464 1452 "metadata": {"operation": "amend", "user": "test"},
1465 1453 "prednode": "4715cf767440ed891755448016c2b8cf70760c30",
1466 1454 "succnodes": ["7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d"]
1467 1455 }
1468 1456 ]
1469 1457
1470 1458 Test the --delete option of debugobsolete command
1471 1459 $ hg debugobsolete --index
1472 1460 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b f9bd49731b0b175e42992a3c8fa6c678b2bc11f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1473 1461 1 6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1 d27fb9b066076fd921277a4b9e8b9cb48c95bc6a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1474 1462 2 1ab51af8f9b41ef8c7f6f3312d4706d870b1fb74 29346082e4a9e27042b62d2da0e2de211c027621 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1475 1463 3 4715cf767440ed891755448016c2b8cf70760c30 7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1476 1464 $ hg debugobsolete --delete 1 --delete 3
1477 1465 deleted 2 obsolescence markers
1478 1466 $ hg debugobsolete
1479 1467 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b f9bd49731b0b175e42992a3c8fa6c678b2bc11f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1480 1468 1ab51af8f9b41ef8c7f6f3312d4706d870b1fb74 29346082e4a9e27042b62d2da0e2de211c027621 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1481 1469
1482 1470 Test adding changeset after obsmarkers affecting it
1483 1471 (eg: during pull, or unbundle)
1484 1472
1485 1473 $ mkcommit e
1486 1474 $ hg bundle -r . --base .~1 ../bundle-2.hg
1487 1475 1 changesets found
1488 1476 $ getid .
1489 1477 $ hg --config extensions.strip= strip -r .
1490 1478 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1491 1479 saved backup bundle to $TESTTMP/tmpe/issue4845/doindexrev/.hg/strip-backup/9bc153528424-ee80edd4-backup.hg (glob)
1492 1480 $ hg debugobsolete 9bc153528424ea266d13e57f9ff0d799dfe61e4b
1493 1481 $ hg unbundle ../bundle-2.hg
1494 1482 adding changesets
1495 1483 adding manifests
1496 1484 adding file changes
1497 1485 added 1 changesets with 1 changes to 1 files
1498 1486 (run 'hg update' to get a working copy)
1499 1487 $ hg log -G
1500 1488 @ 7:7ae79c5d60f0 (draft) [tip ] dd
1501 1489 |
1502 1490 | o 6:4715cf767440 (draft) [ ] d
1503 1491 |/
1504 1492 o 5:29346082e4a9 (draft) [ ] cc
1505 1493 |
1506 1494 o 3:d27fb9b06607 (draft) [ ] bb
1507 1495 |
1508 1496 | o 2:6fdef60fcbab (draft) [ ] b
1509 1497 |/
1510 1498 o 1:f9bd49731b0b (draft) [ ] aa
1511 1499
1512 1500
1513 1501 $ cd ..
@@ -1,1269 +1,1269 b''
1 1 ==========================
2 2 Test rebase with obsolete
3 3 ==========================
4 4
5 5 Enable obsolete
6 6
7 7 $ cat >> $HGRCPATH << EOF
8 8 > [ui]
9 9 > logtemplate= {rev}:{node|short} {desc|firstline}
10 10 > [experimental]
11 11 > stabilization=createmarkers,allowunstable
12 12 > [phases]
13 13 > publish=False
14 14 > [extensions]
15 15 > rebase=
16 16 > drawdag=$TESTDIR/drawdag.py
17 17 > EOF
18 18
19 19 Setup rebase canonical repo
20 20
21 21 $ hg init base
22 22 $ cd base
23 23 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
24 24 adding changesets
25 25 adding manifests
26 26 adding file changes
27 27 added 8 changesets with 7 changes to 7 files (+2 heads)
28 28 (run 'hg heads' to see heads, 'hg merge' to merge)
29 29 $ hg up tip
30 30 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
31 31 $ hg log -G
32 32 @ 7:02de42196ebe H
33 33 |
34 34 | o 6:eea13746799a G
35 35 |/|
36 36 o | 5:24b6387c8c8c F
37 37 | |
38 38 | o 4:9520eea781bc E
39 39 |/
40 40 | o 3:32af7686d403 D
41 41 | |
42 42 | o 2:5fddd98957c8 C
43 43 | |
44 44 | o 1:42ccdea3bb16 B
45 45 |/
46 46 o 0:cd010b8cd998 A
47 47
48 48 $ cd ..
49 49
50 50 simple rebase
51 51 ---------------------------------
52 52
53 53 $ hg clone base simple
54 54 updating to branch default
55 55 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
56 56 $ cd simple
57 57 $ hg up 32af7686d403
58 58 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
59 59 $ hg rebase -d eea13746799a
60 60 rebasing 1:42ccdea3bb16 "B"
61 61 rebasing 2:5fddd98957c8 "C"
62 62 rebasing 3:32af7686d403 "D"
63 63 $ hg log -G
64 64 @ 10:8eeb3c33ad33 D
65 65 |
66 66 o 9:2327fea05063 C
67 67 |
68 68 o 8:e4e5be0395b2 B
69 69 |
70 70 | o 7:02de42196ebe H
71 71 | |
72 72 o | 6:eea13746799a G
73 73 |\|
74 74 | o 5:24b6387c8c8c F
75 75 | |
76 76 o | 4:9520eea781bc E
77 77 |/
78 78 o 0:cd010b8cd998 A
79 79
80 80 $ hg log --hidden -G
81 81 @ 10:8eeb3c33ad33 D
82 82 |
83 83 o 9:2327fea05063 C
84 84 |
85 85 o 8:e4e5be0395b2 B
86 86 |
87 87 | o 7:02de42196ebe H
88 88 | |
89 89 o | 6:eea13746799a G
90 90 |\|
91 91 | o 5:24b6387c8c8c F
92 92 | |
93 93 o | 4:9520eea781bc E
94 94 |/
95 95 | x 3:32af7686d403 D
96 96 | |
97 97 | x 2:5fddd98957c8 C
98 98 | |
99 99 | x 1:42ccdea3bb16 B
100 100 |/
101 101 o 0:cd010b8cd998 A
102 102
103 103 $ hg debugobsolete
104 104 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 e4e5be0395b2cbd471ed22a26b1b6a1a0658a794 0 (*) {'user': 'test'} (glob)
105 105 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 2327fea05063f39961b14cb69435a9898dc9a245 0 (*) {'user': 'test'} (glob)
106 106 32af7686d403cf45b5d95f2d70cebea587ac806a 8eeb3c33ad33d452c89e5dcf611c347f978fb42b 0 (*) {'user': 'test'} (glob)
107 107
108 108
109 109 $ cd ..
110 110
111 111 empty changeset
112 112 ---------------------------------
113 113
114 114 $ hg clone base empty
115 115 updating to branch default
116 116 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 117 $ cd empty
118 118 $ hg up eea13746799a
119 119 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
120 120
121 121 We make a copy of both the first changeset in the rebased and some other in the
122 122 set.
123 123
124 124 $ hg graft 42ccdea3bb16 32af7686d403
125 125 grafting 1:42ccdea3bb16 "B"
126 126 grafting 3:32af7686d403 "D"
127 127 $ hg rebase -s 42ccdea3bb16 -d .
128 128 rebasing 1:42ccdea3bb16 "B"
129 129 note: rebase of 1:42ccdea3bb16 created no changes to commit
130 130 rebasing 2:5fddd98957c8 "C"
131 131 rebasing 3:32af7686d403 "D"
132 132 note: rebase of 3:32af7686d403 created no changes to commit
133 133 $ hg log -G
134 134 o 10:5ae4c968c6ac C
135 135 |
136 136 @ 9:08483444fef9 D
137 137 |
138 138 o 8:8877864f1edb B
139 139 |
140 140 | o 7:02de42196ebe H
141 141 | |
142 142 o | 6:eea13746799a G
143 143 |\|
144 144 | o 5:24b6387c8c8c F
145 145 | |
146 146 o | 4:9520eea781bc E
147 147 |/
148 148 o 0:cd010b8cd998 A
149 149
150 150 $ hg log --hidden -G
151 151 o 10:5ae4c968c6ac C
152 152 |
153 153 @ 9:08483444fef9 D
154 154 |
155 155 o 8:8877864f1edb B
156 156 |
157 157 | o 7:02de42196ebe H
158 158 | |
159 159 o | 6:eea13746799a G
160 160 |\|
161 161 | o 5:24b6387c8c8c F
162 162 | |
163 163 o | 4:9520eea781bc E
164 164 |/
165 165 | x 3:32af7686d403 D
166 166 | |
167 167 | x 2:5fddd98957c8 C
168 168 | |
169 169 | x 1:42ccdea3bb16 B
170 170 |/
171 171 o 0:cd010b8cd998 A
172 172
173 173 $ hg debugobsolete
174 174 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (*) {'user': 'test'} (glob)
175 175 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (*) {'user': 'test'} (glob)
176 176 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (*) {'user': 'test'} (glob)
177 177
178 178
179 179 More complex case where part of the rebase set were already rebased
180 180
181 181 $ hg rebase --rev 'desc(D)' --dest 'desc(H)'
182 182 rebasing 9:08483444fef9 "D"
183 183 $ hg debugobsolete
184 184 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (*) {'user': 'test'} (glob)
185 185 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (*) {'user': 'test'} (glob)
186 186 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (*) {'user': 'test'} (glob)
187 187 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (*) {'user': 'test'} (glob)
188 188 $ hg log -G
189 189 @ 11:4596109a6a43 D
190 190 |
191 191 | o 10:5ae4c968c6ac C
192 192 | |
193 193 | x 9:08483444fef9 D
194 194 | |
195 195 | o 8:8877864f1edb B
196 196 | |
197 197 o | 7:02de42196ebe H
198 198 | |
199 199 | o 6:eea13746799a G
200 200 |/|
201 201 o | 5:24b6387c8c8c F
202 202 | |
203 203 | o 4:9520eea781bc E
204 204 |/
205 205 o 0:cd010b8cd998 A
206 206
207 207 $ hg rebase --source 'desc(B)' --dest 'tip' --config experimental.rebaseskipobsolete=True
208 208 rebasing 8:8877864f1edb "B"
209 209 note: not rebasing 9:08483444fef9 "D", already in destination as 11:4596109a6a43 "D" (tip)
210 210 rebasing 10:5ae4c968c6ac "C"
211 211 $ hg debugobsolete
212 212 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (*) {'user': 'test'} (glob)
213 213 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (*) {'user': 'test'} (glob)
214 214 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (*) {'user': 'test'} (glob)
215 215 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (*) {'user': 'test'} (glob)
216 216 8877864f1edb05d0e07dc4ba77b67a80a7b86672 462a34d07e599b87ea08676a449373fe4e2e1347 0 (*) {'user': 'test'} (glob)
217 217 5ae4c968c6aca831df823664e706c9d4aa34473d 98f6af4ee9539e14da4465128f894c274900b6e5 0 (*) {'user': 'test'} (glob)
218 218 $ hg log --rev 'contentdivergent()'
219 219 $ hg log -G
220 220 o 13:98f6af4ee953 C
221 221 |
222 222 o 12:462a34d07e59 B
223 223 |
224 224 @ 11:4596109a6a43 D
225 225 |
226 226 o 7:02de42196ebe H
227 227 |
228 228 | o 6:eea13746799a G
229 229 |/|
230 230 o | 5:24b6387c8c8c F
231 231 | |
232 232 | o 4:9520eea781bc E
233 233 |/
234 234 o 0:cd010b8cd998 A
235 235
236 236 $ hg log --style default --debug -r 4596109a6a4328c398bde3a4a3b6737cfade3003
237 237 changeset: 11:4596109a6a4328c398bde3a4a3b6737cfade3003
238 238 phase: draft
239 239 parent: 7:02de42196ebee42ef284b6780a87cdc96e8eaab6
240 240 parent: -1:0000000000000000000000000000000000000000
241 241 manifest: 11:a91006e3a02f1edf631f7018e6e5684cf27dd905
242 242 user: Nicolas Dumazet <nicdumz.commits@gmail.com>
243 243 date: Sat Apr 30 15:24:48 2011 +0200
244 244 files+: D
245 245 extra: branch=default
246 246 extra: rebase_source=08483444fef91d6224f6655ee586a65d263ad34c
247 247 extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
248 248 description:
249 249 D
250 250
251 251
252 252 $ hg up -qr 'desc(G)'
253 253 $ hg graft 4596109a6a4328c398bde3a4a3b6737cfade3003
254 254 grafting 11:4596109a6a43 "D"
255 255 $ hg up -qr 'desc(E)'
256 256 $ hg rebase -s tip -d .
257 257 rebasing 14:9e36056a46e3 "D" (tip)
258 258 $ hg log --style default --debug -r tip
259 259 changeset: 15:627d4614809036ba22b9e7cb31638ddc06ab99ab
260 260 tag: tip
261 261 phase: draft
262 262 parent: 4:9520eea781bcca16c1e15acc0ba14335a0e8e5ba
263 263 parent: -1:0000000000000000000000000000000000000000
264 264 manifest: 15:648e8ede73ae3e497d093d3a4c8fcc2daa864f42
265 265 user: Nicolas Dumazet <nicdumz.commits@gmail.com>
266 266 date: Sat Apr 30 15:24:48 2011 +0200
267 267 files+: D
268 268 extra: branch=default
269 269 extra: intermediate-source=4596109a6a4328c398bde3a4a3b6737cfade3003
270 270 extra: rebase_source=9e36056a46e37c9776168c7375734eebc70e294f
271 271 extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
272 272 description:
273 273 D
274 274
275 275
276 276 Start rebase from a commit that is obsolete but not hidden only because it's
277 277 a working copy parent. We should be moved back to the starting commit as usual
278 278 even though it is hidden (until we're moved there).
279 279
280 280 $ hg --hidden up -qr 'first(hidden())'
281 281 $ hg rebase --rev 13 --dest 15
282 282 rebasing 13:98f6af4ee953 "C"
283 283 $ hg log -G
284 284 o 16:294a2b93eb4d C
285 285 |
286 286 o 15:627d46148090 D
287 287 |
288 288 | o 12:462a34d07e59 B
289 289 | |
290 290 | o 11:4596109a6a43 D
291 291 | |
292 292 | o 7:02de42196ebe H
293 293 | |
294 294 +---o 6:eea13746799a G
295 295 | |/
296 296 | o 5:24b6387c8c8c F
297 297 | |
298 298 o | 4:9520eea781bc E
299 299 |/
300 300 | @ 1:42ccdea3bb16 B
301 301 |/
302 302 o 0:cd010b8cd998 A
303 303
304 304
305 305 $ cd ..
306 306
307 307 collapse rebase
308 308 ---------------------------------
309 309
310 310 $ hg clone base collapse
311 311 updating to branch default
312 312 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
313 313 $ cd collapse
314 314 $ hg rebase -s 42ccdea3bb16 -d eea13746799a --collapse
315 315 rebasing 1:42ccdea3bb16 "B"
316 316 rebasing 2:5fddd98957c8 "C"
317 317 rebasing 3:32af7686d403 "D"
318 318 $ hg log -G
319 319 o 8:4dc2197e807b Collapsed revision
320 320 |
321 321 | @ 7:02de42196ebe H
322 322 | |
323 323 o | 6:eea13746799a G
324 324 |\|
325 325 | o 5:24b6387c8c8c F
326 326 | |
327 327 o | 4:9520eea781bc E
328 328 |/
329 329 o 0:cd010b8cd998 A
330 330
331 331 $ hg log --hidden -G
332 332 o 8:4dc2197e807b Collapsed revision
333 333 |
334 334 | @ 7:02de42196ebe H
335 335 | |
336 336 o | 6:eea13746799a G
337 337 |\|
338 338 | o 5:24b6387c8c8c F
339 339 | |
340 340 o | 4:9520eea781bc E
341 341 |/
342 342 | x 3:32af7686d403 D
343 343 | |
344 344 | x 2:5fddd98957c8 C
345 345 | |
346 346 | x 1:42ccdea3bb16 B
347 347 |/
348 348 o 0:cd010b8cd998 A
349 349
350 350 $ hg id --debug -r tip
351 351 4dc2197e807bae9817f09905b50ab288be2dbbcf tip
352 352 $ hg debugobsolete
353 353 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (*) {'user': 'test'} (glob)
354 354 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (*) {'user': 'test'} (glob)
355 355 32af7686d403cf45b5d95f2d70cebea587ac806a 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (*) {'user': 'test'} (glob)
356 356
357 357 $ cd ..
358 358
359 359 Rebase set has hidden descendants
360 360 ---------------------------------
361 361
362 362 We rebase a changeset which has a hidden changeset. The hidden changeset must
363 363 not be rebased.
364 364
365 365 $ hg clone base hidden
366 366 updating to branch default
367 367 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
368 368 $ cd hidden
369 369 $ hg rebase -s 5fddd98957c8 -d eea13746799a
370 370 rebasing 2:5fddd98957c8 "C"
371 371 rebasing 3:32af7686d403 "D"
372 372 $ hg rebase -s 42ccdea3bb16 -d 02de42196ebe
373 373 rebasing 1:42ccdea3bb16 "B"
374 374 $ hg log -G
375 375 o 10:7c6027df6a99 B
376 376 |
377 377 | o 9:cf44d2f5a9f4 D
378 378 | |
379 379 | o 8:e273c5e7d2d2 C
380 380 | |
381 381 @ | 7:02de42196ebe H
382 382 | |
383 383 | o 6:eea13746799a G
384 384 |/|
385 385 o | 5:24b6387c8c8c F
386 386 | |
387 387 | o 4:9520eea781bc E
388 388 |/
389 389 o 0:cd010b8cd998 A
390 390
391 391 $ hg log --hidden -G
392 392 o 10:7c6027df6a99 B
393 393 |
394 394 | o 9:cf44d2f5a9f4 D
395 395 | |
396 396 | o 8:e273c5e7d2d2 C
397 397 | |
398 398 @ | 7:02de42196ebe H
399 399 | |
400 400 | o 6:eea13746799a G
401 401 |/|
402 402 o | 5:24b6387c8c8c F
403 403 | |
404 404 | o 4:9520eea781bc E
405 405 |/
406 406 | x 3:32af7686d403 D
407 407 | |
408 408 | x 2:5fddd98957c8 C
409 409 | |
410 410 | x 1:42ccdea3bb16 B
411 411 |/
412 412 o 0:cd010b8cd998 A
413 413
414 414 $ hg debugobsolete
415 415 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b e273c5e7d2d29df783dce9f9eaa3ac4adc69c15d 0 (*) {'user': 'test'} (glob)
416 416 32af7686d403cf45b5d95f2d70cebea587ac806a cf44d2f5a9f4297a62be94cbdd3dff7c7dc54258 0 (*) {'user': 'test'} (glob)
417 417 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 7c6027df6a99d93f461868e5433f63bde20b6dfb 0 (*) {'user': 'test'} (glob)
418 418
419 419 Test that rewriting leaving instability behind is allowed
420 420 ---------------------------------------------------------------------
421 421
422 422 $ hg log -r 'children(8)'
423 423 9:cf44d2f5a9f4 D (no-eol)
424 424 $ hg rebase -r 8
425 425 rebasing 8:e273c5e7d2d2 "C"
426 426 $ hg log -G
427 427 o 11:0d8f238b634c C
428 428 |
429 429 o 10:7c6027df6a99 B
430 430 |
431 431 | o 9:cf44d2f5a9f4 D
432 432 | |
433 433 | x 8:e273c5e7d2d2 C
434 434 | |
435 435 @ | 7:02de42196ebe H
436 436 | |
437 437 | o 6:eea13746799a G
438 438 |/|
439 439 o | 5:24b6387c8c8c F
440 440 | |
441 441 | o 4:9520eea781bc E
442 442 |/
443 443 o 0:cd010b8cd998 A
444 444
445 445
446 446
447 447 Test multiple root handling
448 448 ------------------------------------
449 449
450 450 $ hg rebase --dest 4 --rev '7+11+9'
451 451 rebasing 9:cf44d2f5a9f4 "D"
452 452 rebasing 7:02de42196ebe "H"
453 453 rebasing 11:0d8f238b634c "C" (tip)
454 454 $ hg log -G
455 455 o 14:1e8370e38cca C
456 456 |
457 457 @ 13:bfe264faf697 H
458 458 |
459 459 | o 12:102b4c1d889b D
460 460 |/
461 461 | o 10:7c6027df6a99 B
462 462 | |
463 463 | x 7:02de42196ebe H
464 464 | |
465 465 +---o 6:eea13746799a G
466 466 | |/
467 467 | o 5:24b6387c8c8c F
468 468 | |
469 469 o | 4:9520eea781bc E
470 470 |/
471 471 o 0:cd010b8cd998 A
472 472
473 473 $ cd ..
474 474
475 475 Detach both parents
476 476
477 477 $ hg init double-detach
478 478 $ cd double-detach
479 479
480 480 $ hg debugdrawdag <<EOF
481 481 > F
482 482 > /|
483 483 > C E
484 484 > | |
485 485 > B D G
486 486 > \|/
487 487 > A
488 488 > EOF
489 489
490 490 $ hg rebase -d G -r 'B + D + F'
491 491 rebasing 1:112478962961 "B" (B)
492 492 rebasing 2:b18e25de2cf5 "D" (D)
493 493 rebasing 6:f15c3adaf214 "F" (F tip)
494 494 abort: cannot rebase 6:f15c3adaf214 without moving at least one of its parents
495 495 [255]
496 496
497 497 $ cd ..
498 498
499 499 test on rebase dropping a merge
500 500
501 501 (setup)
502 502
503 503 $ hg init dropmerge
504 504 $ cd dropmerge
505 505 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
506 506 adding changesets
507 507 adding manifests
508 508 adding file changes
509 509 added 8 changesets with 7 changes to 7 files (+2 heads)
510 510 (run 'hg heads' to see heads, 'hg merge' to merge)
511 511 $ hg up 3
512 512 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
513 513 $ hg merge 7
514 514 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
515 515 (branch merge, don't forget to commit)
516 516 $ hg ci -m 'M'
517 517 $ echo I > I
518 518 $ hg add I
519 519 $ hg ci -m I
520 520 $ hg log -G
521 521 @ 9:4bde274eefcf I
522 522 |
523 523 o 8:53a6a128b2b7 M
524 524 |\
525 525 | o 7:02de42196ebe H
526 526 | |
527 527 | | o 6:eea13746799a G
528 528 | |/|
529 529 | o | 5:24b6387c8c8c F
530 530 | | |
531 531 | | o 4:9520eea781bc E
532 532 | |/
533 533 o | 3:32af7686d403 D
534 534 | |
535 535 o | 2:5fddd98957c8 C
536 536 | |
537 537 o | 1:42ccdea3bb16 B
538 538 |/
539 539 o 0:cd010b8cd998 A
540 540
541 541 (actual test)
542 542
543 543 $ hg rebase --dest 6 --rev '((desc(H) + desc(D))::) - desc(M)'
544 544 rebasing 3:32af7686d403 "D"
545 545 rebasing 7:02de42196ebe "H"
546 546 rebasing 9:4bde274eefcf "I" (tip)
547 547 $ hg log -G
548 548 @ 12:acd174b7ab39 I
549 549 |
550 550 o 11:6c11a6218c97 H
551 551 |
552 552 | o 10:b5313c85b22e D
553 553 |/
554 554 | o 8:53a6a128b2b7 M
555 555 | |\
556 556 | | x 7:02de42196ebe H
557 557 | | |
558 558 o---+ 6:eea13746799a G
559 559 | | |
560 560 | | o 5:24b6387c8c8c F
561 561 | | |
562 562 o---+ 4:9520eea781bc E
563 563 / /
564 564 x | 3:32af7686d403 D
565 565 | |
566 566 o | 2:5fddd98957c8 C
567 567 | |
568 568 o | 1:42ccdea3bb16 B
569 569 |/
570 570 o 0:cd010b8cd998 A
571 571
572 572
573 573 Test hidden changesets in the rebase set (issue4504)
574 574
575 575 $ hg up --hidden 9
576 576 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
577 577 $ echo J > J
578 578 $ hg add J
579 579 $ hg commit -m J
580 580 $ hg debugobsolete `hg log --rev . -T '{node}'`
581 581 obsoleted 1 changesets
582 582
583 583 $ hg rebase --rev .~1::. --dest 'max(desc(D))' --traceback --config experimental.rebaseskipobsolete=off
584 584 rebasing 9:4bde274eefcf "I"
585 585 rebasing 13:06edfc82198f "J" (tip)
586 586 $ hg log -G
587 587 @ 15:5ae8a643467b J
588 588 |
589 589 o 14:9ad579b4a5de I
590 590 |
591 591 | o 12:acd174b7ab39 I
592 592 | |
593 593 | o 11:6c11a6218c97 H
594 594 | |
595 595 o | 10:b5313c85b22e D
596 596 |/
597 597 | o 8:53a6a128b2b7 M
598 598 | |\
599 599 | | x 7:02de42196ebe H
600 600 | | |
601 601 o---+ 6:eea13746799a G
602 602 | | |
603 603 | | o 5:24b6387c8c8c F
604 604 | | |
605 605 o---+ 4:9520eea781bc E
606 606 / /
607 607 x | 3:32af7686d403 D
608 608 | |
609 609 o | 2:5fddd98957c8 C
610 610 | |
611 611 o | 1:42ccdea3bb16 B
612 612 |/
613 613 o 0:cd010b8cd998 A
614 614
615 615 $ hg up 14 -C
616 616 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
617 617 $ echo "K" > K
618 618 $ hg add K
619 619 $ hg commit --amend -m "K"
620 620 $ echo "L" > L
621 621 $ hg add L
622 622 $ hg commit -m "L"
623 623 $ hg up '.^'
624 624 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
625 625 $ echo "M" > M
626 626 $ hg add M
627 627 $ hg commit --amend -m "M"
628 628 $ hg log -G
629 @ 20:bfaedf8eb73b M
629 @ 18:bfaedf8eb73b M
630 630 |
631 | o 18:97219452e4bd L
631 | o 17:97219452e4bd L
632 632 | |
633 | x 17:fc37a630c901 K
633 | x 16:fc37a630c901 K
634 634 |/
635 635 | o 15:5ae8a643467b J
636 636 | |
637 637 | x 14:9ad579b4a5de I
638 638 |/
639 639 | o 12:acd174b7ab39 I
640 640 | |
641 641 | o 11:6c11a6218c97 H
642 642 | |
643 643 o | 10:b5313c85b22e D
644 644 |/
645 645 | o 8:53a6a128b2b7 M
646 646 | |\
647 647 | | x 7:02de42196ebe H
648 648 | | |
649 649 o---+ 6:eea13746799a G
650 650 | | |
651 651 | | o 5:24b6387c8c8c F
652 652 | | |
653 653 o---+ 4:9520eea781bc E
654 654 / /
655 655 x | 3:32af7686d403 D
656 656 | |
657 657 o | 2:5fddd98957c8 C
658 658 | |
659 659 o | 1:42ccdea3bb16 B
660 660 |/
661 661 o 0:cd010b8cd998 A
662 662
663 $ hg rebase -s 14 -d 18 --config experimental.rebaseskipobsolete=True
664 note: not rebasing 14:9ad579b4a5de "I", already in destination as 17:fc37a630c901 "K"
663 $ hg rebase -s 14 -d 17 --config experimental.rebaseskipobsolete=True
664 note: not rebasing 14:9ad579b4a5de "I", already in destination as 16:fc37a630c901 "K"
665 665 rebasing 15:5ae8a643467b "J"
666 666
667 667 $ cd ..
668 668
669 669 Skip obsolete changeset even with multiple hops
670 670 -----------------------------------------------
671 671
672 672 setup
673 673
674 674 $ hg init obsskip
675 675 $ cd obsskip
676 676 $ cat << EOF >> .hg/hgrc
677 677 > [experimental]
678 678 > rebaseskipobsolete = True
679 679 > [extensions]
680 680 > strip =
681 681 > EOF
682 682 $ echo A > A
683 683 $ hg add A
684 684 $ hg commit -m A
685 685 $ echo B > B
686 686 $ hg add B
687 687 $ hg commit -m B0
688 688 $ hg commit --amend -m B1
689 689 $ hg commit --amend -m B2
690 690 $ hg up --hidden 'desc(B0)'
691 691 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
692 692 $ echo C > C
693 693 $ hg add C
694 694 $ hg commit -m C
695 695
696 696 Rebase finds its way in a chain of marker
697 697
698 698 $ hg rebase -d 'desc(B2)'
699 699 note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 3:261e70097290 "B2"
700 700 rebasing 4:212cb178bcbb "C" (tip)
701 701
702 702 Even when the chain include missing node
703 703
704 704 $ hg up --hidden 'desc(B0)'
705 705 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
706 706 $ echo D > D
707 707 $ hg add D
708 708 $ hg commit -m D
709 709 $ hg --hidden strip -r 'desc(B1)'
710 710 saved backup bundle to $TESTTMP/obsskip/.hg/strip-backup/86f6414ccda7-b1c452ee-backup.hg (glob)
711 711
712 712 $ hg rebase -d 'desc(B2)'
713 713 note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 2:261e70097290 "B2"
714 714 rebasing 5:1a79b7535141 "D" (tip)
715 715 $ hg up 4
716 716 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
717 717 $ echo "O" > O
718 718 $ hg add O
719 719 $ hg commit -m O
720 720 $ echo "P" > P
721 721 $ hg add P
722 722 $ hg commit -m P
723 723 $ hg log -G
724 724 @ 8:8d47583e023f P
725 725 |
726 726 o 7:360bbaa7d3ce O
727 727 |
728 728 | o 6:9c48361117de D
729 729 | |
730 730 o | 4:ff2c4d47b71d C
731 731 |/
732 732 o 2:261e70097290 B2
733 733 |
734 734 o 0:4a2df7238c3b A
735 735
736 736 $ hg debugobsolete `hg log -r 7 -T '{node}\n'` --config experimental.stabilization=all
737 737 obsoleted 1 changesets
738 738 $ hg rebase -d 6 -r "4::"
739 739 rebasing 4:ff2c4d47b71d "C"
740 740 note: not rebasing 7:360bbaa7d3ce "O", it has no successor
741 741 rebasing 8:8d47583e023f "P" (tip)
742 742
743 743 If all the changeset to be rebased are obsolete and present in the destination, we
744 744 should display a friendly error message
745 745
746 746 $ hg log -G
747 747 @ 10:121d9e3bc4c6 P
748 748 |
749 749 o 9:4be60e099a77 C
750 750 |
751 751 o 6:9c48361117de D
752 752 |
753 753 o 2:261e70097290 B2
754 754 |
755 755 o 0:4a2df7238c3b A
756 756
757 757
758 758 $ hg up 9
759 759 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
760 760 $ echo "non-relevant change" > nonrelevant
761 761 $ hg add nonrelevant
762 762 $ hg commit -m nonrelevant
763 763 created new head
764 764 $ hg debugobsolete `hg log -r 11 -T '{node}\n'` --config experimental.stabilization=all
765 765 obsoleted 1 changesets
766 766 $ hg rebase -r . -d 10
767 767 note: not rebasing 11:f44da1f4954c "nonrelevant" (tip), it has no successor
768 768
769 769 If a rebase is going to create divergence, it should abort
770 770
771 771 $ hg log -G
772 772 @ 10:121d9e3bc4c6 P
773 773 |
774 774 o 9:4be60e099a77 C
775 775 |
776 776 o 6:9c48361117de D
777 777 |
778 778 o 2:261e70097290 B2
779 779 |
780 780 o 0:4a2df7238c3b A
781 781
782 782
783 783 $ hg up 9
784 784 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
785 785 $ echo "john" > doe
786 786 $ hg add doe
787 787 $ hg commit -m "john doe"
788 788 created new head
789 789 $ hg up 10
790 790 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
791 791 $ echo "foo" > bar
792 792 $ hg add bar
793 793 $ hg commit --amend -m "10'"
794 794 $ hg up 10 --hidden
795 795 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
796 796 $ echo "bar" > foo
797 797 $ hg add foo
798 798 $ hg commit -m "bar foo"
799 799 $ hg log -G
800 @ 15:73568ab6879d bar foo
800 @ 14:73568ab6879d bar foo
801 801 |
802 | o 14:77d874d096a2 10'
802 | o 13:77d874d096a2 10'
803 803 | |
804 804 | | o 12:3eb461388009 john doe
805 805 | |/
806 806 x | 10:121d9e3bc4c6 P
807 807 |/
808 808 o 9:4be60e099a77 C
809 809 |
810 810 o 6:9c48361117de D
811 811 |
812 812 o 2:261e70097290 B2
813 813 |
814 814 o 0:4a2df7238c3b A
815 815
816 816 $ hg summary
817 parent: 15:73568ab6879d tip (orphan)
817 parent: 14:73568ab6879d tip (orphan)
818 818 bar foo
819 819 branch: default
820 820 commit: (clean)
821 821 update: 2 new changesets, 3 branch heads (merge)
822 822 phases: 8 draft
823 823 orphan: 1 changesets
824 824 $ hg rebase -s 10 -d 12
825 825 abort: this rebase will cause divergences from: 121d9e3bc4c6
826 826 (to force the rebase please set experimental.allowdivergence=True)
827 827 [255]
828 828 $ hg log -G
829 @ 15:73568ab6879d bar foo
829 @ 14:73568ab6879d bar foo
830 830 |
831 | o 14:77d874d096a2 10'
831 | o 13:77d874d096a2 10'
832 832 | |
833 833 | | o 12:3eb461388009 john doe
834 834 | |/
835 835 x | 10:121d9e3bc4c6 P
836 836 |/
837 837 o 9:4be60e099a77 C
838 838 |
839 839 o 6:9c48361117de D
840 840 |
841 841 o 2:261e70097290 B2
842 842 |
843 843 o 0:4a2df7238c3b A
844 844
845 845 With experimental.allowdivergence=True, rebase can create divergence
846 846
847 847 $ hg rebase -s 10 -d 12 --config experimental.allowdivergence=True
848 848 rebasing 10:121d9e3bc4c6 "P"
849 rebasing 15:73568ab6879d "bar foo" (tip)
849 rebasing 14:73568ab6879d "bar foo" (tip)
850 850 $ hg summary
851 parent: 17:61bd55f69bc4 tip
851 parent: 16:61bd55f69bc4 tip
852 852 bar foo
853 853 branch: default
854 854 commit: (clean)
855 855 update: 1 new changesets, 2 branch heads (merge)
856 856 phases: 8 draft
857 857 content-divergent: 2 changesets
858 858
859 859 rebase --continue + skipped rev because their successors are in destination
860 860 we make a change in trunk and work on conflicting changes to make rebase abort.
861 861
862 $ hg log -G -r 17::
863 @ 17:61bd55f69bc4 bar foo
862 $ hg log -G -r 16::
863 @ 16:61bd55f69bc4 bar foo
864 864 |
865 865 ~
866 866
867 867 Create the two changes in trunk
868 868 $ printf "a" > willconflict
869 869 $ hg add willconflict
870 870 $ hg commit -m "willconflict first version"
871 871
872 872 $ printf "dummy" > C
873 873 $ hg commit -m "dummy change successor"
874 874
875 875 Create the changes that we will rebase
876 $ hg update -C 17 -q
876 $ hg update -C 16 -q
877 877 $ printf "b" > willconflict
878 878 $ hg add willconflict
879 879 $ hg commit -m "willconflict second version"
880 880 created new head
881 881 $ printf "dummy" > K
882 882 $ hg add K
883 883 $ hg commit -m "dummy change"
884 884 $ printf "dummy" > L
885 885 $ hg add L
886 886 $ hg commit -m "dummy change"
887 $ hg debugobsolete `hg log -r ".^" -T '{node}'` `hg log -r 19 -T '{node}'` --config experimental.stabilization=all
887 $ hg debugobsolete `hg log -r ".^" -T '{node}'` `hg log -r 18 -T '{node}'` --config experimental.stabilization=all
888 888 obsoleted 1 changesets
889 889
890 $ hg log -G -r 17::
891 @ 22:7bdc8a87673d dummy change
890 $ hg log -G -r 16::
891 @ 21:7bdc8a87673d dummy change
892 892 |
893 x 21:8b31da3c4919 dummy change
893 x 20:8b31da3c4919 dummy change
894 894 |
895 o 20:b82fb57ea638 willconflict second version
895 o 19:b82fb57ea638 willconflict second version
896 896 |
897 | o 19:601db7a18f51 dummy change successor
897 | o 18:601db7a18f51 dummy change successor
898 898 | |
899 | o 18:357ddf1602d5 willconflict first version
899 | o 17:357ddf1602d5 willconflict first version
900 900 |/
901 o 17:61bd55f69bc4 bar foo
901 o 16:61bd55f69bc4 bar foo
902 902 |
903 903 ~
904 $ hg rebase -r ".^^ + .^ + ." -d 19
905 rebasing 20:b82fb57ea638 "willconflict second version"
904 $ hg rebase -r ".^^ + .^ + ." -d 18
905 rebasing 19:b82fb57ea638 "willconflict second version"
906 906 merging willconflict
907 907 warning: conflicts while merging willconflict! (edit, then use 'hg resolve --mark')
908 908 unresolved conflicts (see hg resolve, then hg rebase --continue)
909 909 [1]
910 910
911 911 $ hg resolve --mark willconflict
912 912 (no more unresolved files)
913 913 continue: hg rebase --continue
914 914 $ hg rebase --continue
915 rebasing 20:b82fb57ea638 "willconflict second version"
916 note: not rebasing 21:8b31da3c4919 "dummy change", already in destination as 19:601db7a18f51 "dummy change successor"
917 rebasing 22:7bdc8a87673d "dummy change" (tip)
915 rebasing 19:b82fb57ea638 "willconflict second version"
916 note: not rebasing 20:8b31da3c4919 "dummy change", already in destination as 18:601db7a18f51 "dummy change successor"
917 rebasing 21:7bdc8a87673d "dummy change" (tip)
918 918 $ cd ..
919 919
920 920 Rebase merge where successor of one parent is equal to destination (issue5198)
921 921
922 922 $ hg init p1-succ-is-dest
923 923 $ cd p1-succ-is-dest
924 924
925 925 $ hg debugdrawdag <<EOF
926 926 > F
927 927 > /|
928 928 > E D B # replace: D -> B
929 929 > \|/
930 930 > A
931 931 > EOF
932 932
933 933 $ hg rebase -d B -s D
934 934 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
935 935 rebasing 4:66f1a38021c9 "F" (F tip)
936 936 $ hg log -G
937 937 o 5:50e9d60b99c6 F
938 938 |\
939 939 | | x 4:66f1a38021c9 F
940 940 | |/|
941 941 | o | 3:7fb047a69f22 E
942 942 | | |
943 943 | | x 2:b18e25de2cf5 D
944 944 | |/
945 945 o | 1:112478962961 B
946 946 |/
947 947 o 0:426bada5c675 A
948 948
949 949 $ cd ..
950 950
951 951 Rebase merge where successor of other parent is equal to destination
952 952
953 953 $ hg init p2-succ-is-dest
954 954 $ cd p2-succ-is-dest
955 955
956 956 $ hg debugdrawdag <<EOF
957 957 > F
958 958 > /|
959 959 > E D B # replace: E -> B
960 960 > \|/
961 961 > A
962 962 > EOF
963 963
964 964 $ hg rebase -d B -s E
965 965 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
966 966 rebasing 4:66f1a38021c9 "F" (F tip)
967 967 $ hg log -G
968 968 o 5:aae1787dacee F
969 969 |\
970 970 | | x 4:66f1a38021c9 F
971 971 | |/|
972 972 | | x 3:7fb047a69f22 E
973 973 | | |
974 974 | o | 2:b18e25de2cf5 D
975 975 | |/
976 976 o / 1:112478962961 B
977 977 |/
978 978 o 0:426bada5c675 A
979 979
980 980 $ cd ..
981 981
982 982 Rebase merge where successor of one parent is ancestor of destination
983 983
984 984 $ hg init p1-succ-in-dest
985 985 $ cd p1-succ-in-dest
986 986
987 987 $ hg debugdrawdag <<EOF
988 988 > F C
989 989 > /| |
990 990 > E D B # replace: D -> B
991 991 > \|/
992 992 > A
993 993 > EOF
994 994
995 995 $ hg rebase -d C -s D
996 996 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
997 997 rebasing 5:66f1a38021c9 "F" (F tip)
998 998
999 999 $ hg log -G
1000 1000 o 6:0913febf6439 F
1001 1001 |\
1002 1002 +---x 5:66f1a38021c9 F
1003 1003 | | |
1004 1004 | o | 4:26805aba1e60 C
1005 1005 | | |
1006 1006 o | | 3:7fb047a69f22 E
1007 1007 | | |
1008 1008 +---x 2:b18e25de2cf5 D
1009 1009 | |
1010 1010 | o 1:112478962961 B
1011 1011 |/
1012 1012 o 0:426bada5c675 A
1013 1013
1014 1014 $ cd ..
1015 1015
1016 1016 Rebase merge where successor of other parent is ancestor of destination
1017 1017
1018 1018 $ hg init p2-succ-in-dest
1019 1019 $ cd p2-succ-in-dest
1020 1020
1021 1021 $ hg debugdrawdag <<EOF
1022 1022 > F C
1023 1023 > /| |
1024 1024 > E D B # replace: E -> B
1025 1025 > \|/
1026 1026 > A
1027 1027 > EOF
1028 1028
1029 1029 $ hg rebase -d C -s E
1030 1030 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1031 1031 rebasing 5:66f1a38021c9 "F" (F tip)
1032 1032 $ hg log -G
1033 1033 o 6:c6ab0cc6d220 F
1034 1034 |\
1035 1035 +---x 5:66f1a38021c9 F
1036 1036 | | |
1037 1037 | o | 4:26805aba1e60 C
1038 1038 | | |
1039 1039 | | x 3:7fb047a69f22 E
1040 1040 | | |
1041 1041 o---+ 2:b18e25de2cf5 D
1042 1042 / /
1043 1043 o / 1:112478962961 B
1044 1044 |/
1045 1045 o 0:426bada5c675 A
1046 1046
1047 1047 $ cd ..
1048 1048
1049 1049 Rebase merge where successor of one parent is ancestor of destination
1050 1050
1051 1051 $ hg init p1-succ-in-dest-b
1052 1052 $ cd p1-succ-in-dest-b
1053 1053
1054 1054 $ hg debugdrawdag <<EOF
1055 1055 > F C
1056 1056 > /| |
1057 1057 > E D B # replace: E -> B
1058 1058 > \|/
1059 1059 > A
1060 1060 > EOF
1061 1061
1062 1062 $ hg rebase -d C -b F
1063 1063 rebasing 2:b18e25de2cf5 "D" (D)
1064 1064 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1065 1065 rebasing 5:66f1a38021c9 "F" (F tip)
1066 1066 note: rebase of 5:66f1a38021c9 created no changes to commit
1067 1067 $ hg log -G
1068 1068 o 6:8f47515dda15 D
1069 1069 |
1070 1070 | x 5:66f1a38021c9 F
1071 1071 | |\
1072 1072 o | | 4:26805aba1e60 C
1073 1073 | | |
1074 1074 | | x 3:7fb047a69f22 E
1075 1075 | | |
1076 1076 | x | 2:b18e25de2cf5 D
1077 1077 | |/
1078 1078 o / 1:112478962961 B
1079 1079 |/
1080 1080 o 0:426bada5c675 A
1081 1081
1082 1082 $ cd ..
1083 1083
1084 1084 Rebase merge where successor of other parent is ancestor of destination
1085 1085
1086 1086 $ hg init p2-succ-in-dest-b
1087 1087 $ cd p2-succ-in-dest-b
1088 1088
1089 1089 $ hg debugdrawdag <<EOF
1090 1090 > F C
1091 1091 > /| |
1092 1092 > E D B # replace: D -> B
1093 1093 > \|/
1094 1094 > A
1095 1095 > EOF
1096 1096
1097 1097 $ hg rebase -d C -b F
1098 1098 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1099 1099 rebasing 3:7fb047a69f22 "E" (E)
1100 1100 rebasing 5:66f1a38021c9 "F" (F tip)
1101 1101 note: rebase of 5:66f1a38021c9 created no changes to commit
1102 1102
1103 1103 $ hg log -G
1104 1104 o 6:533690786a86 E
1105 1105 |
1106 1106 | x 5:66f1a38021c9 F
1107 1107 | |\
1108 1108 o | | 4:26805aba1e60 C
1109 1109 | | |
1110 1110 | | x 3:7fb047a69f22 E
1111 1111 | | |
1112 1112 | x | 2:b18e25de2cf5 D
1113 1113 | |/
1114 1114 o / 1:112478962961 B
1115 1115 |/
1116 1116 o 0:426bada5c675 A
1117 1117
1118 1118 $ cd ..
1119 1119
1120 1120 Rebase merge where both parents have successors in destination
1121 1121
1122 1122 $ hg init p12-succ-in-dest
1123 1123 $ cd p12-succ-in-dest
1124 1124 $ hg debugdrawdag <<'EOS'
1125 1125 > E F
1126 1126 > /| /| # replace: A -> C
1127 1127 > A B C D # replace: B -> D
1128 1128 > | |
1129 1129 > X Y
1130 1130 > EOS
1131 1131 $ hg rebase -r A+B+E -d F
1132 1132 note: not rebasing 4:a3d17304151f "A" (A), already in destination as 0:96cc3511f894 "C" (C)
1133 1133 note: not rebasing 5:b23a2cc00842 "B" (B), already in destination as 1:058c1e1fb10a "D" (D)
1134 1134 rebasing 7:dac5d11c5a7d "E" (E tip)
1135 1135 abort: rebasing 7:dac5d11c5a7d will include unwanted changes from 3:59c792af609c, 5:b23a2cc00842 or 2:ba2b7fa7166d, 4:a3d17304151f
1136 1136 [255]
1137 1137 $ cd ..
1138 1138
1139 1139 Rebase a non-clean merge. One parent has successor in destination, the other
1140 1140 parent moves as requested.
1141 1141
1142 1142 $ hg init p1-succ-p2-move
1143 1143 $ cd p1-succ-p2-move
1144 1144 $ hg debugdrawdag <<'EOS'
1145 1145 > D Z
1146 1146 > /| | # replace: A -> C
1147 1147 > A B C # D/D = D
1148 1148 > EOS
1149 1149 $ hg rebase -r A+B+D -d Z
1150 1150 note: not rebasing 0:426bada5c675 "A" (A), already in destination as 2:96cc3511f894 "C" (C)
1151 1151 rebasing 1:fc2b737bb2e5 "B" (B)
1152 1152 rebasing 3:b8ed089c80ad "D" (D)
1153 1153
1154 1154 $ rm .hg/localtags
1155 1155 $ hg log -G
1156 1156 o 6:e4f78693cc88 D
1157 1157 |
1158 1158 o 5:76840d832e98 B
1159 1159 |
1160 1160 o 4:50e41c1f3950 Z
1161 1161 |
1162 1162 o 2:96cc3511f894 C
1163 1163
1164 1164 $ hg files -r tip
1165 1165 B
1166 1166 C
1167 1167 D
1168 1168 Z
1169 1169
1170 1170 $ cd ..
1171 1171
1172 1172 $ hg init p1-move-p2-succ
1173 1173 $ cd p1-move-p2-succ
1174 1174 $ hg debugdrawdag <<'EOS'
1175 1175 > D Z
1176 1176 > /| | # replace: B -> C
1177 1177 > A B C # D/D = D
1178 1178 > EOS
1179 1179 $ hg rebase -r B+A+D -d Z
1180 1180 rebasing 0:426bada5c675 "A" (A)
1181 1181 note: not rebasing 1:fc2b737bb2e5 "B" (B), already in destination as 2:96cc3511f894 "C" (C)
1182 1182 rebasing 3:b8ed089c80ad "D" (D)
1183 1183
1184 1184 $ rm .hg/localtags
1185 1185 $ hg log -G
1186 1186 o 6:1b355ed94d82 D
1187 1187 |
1188 1188 o 5:a81a74d764a6 A
1189 1189 |
1190 1190 o 4:50e41c1f3950 Z
1191 1191 |
1192 1192 o 2:96cc3511f894 C
1193 1193
1194 1194 $ hg files -r tip
1195 1195 A
1196 1196 C
1197 1197 D
1198 1198 Z
1199 1199
1200 1200 $ cd ..
1201 1201
1202 1202 Test that bookmark is moved and working dir is updated when all changesets have
1203 1203 equivalents in destination
1204 1204 $ hg init rbsrepo && cd rbsrepo
1205 1205 $ echo "[experimental]" > .hg/hgrc
1206 1206 $ echo "stabilization=all" >> .hg/hgrc
1207 1207 $ echo "rebaseskipobsolete=on" >> .hg/hgrc
1208 1208 $ echo root > root && hg ci -Am root
1209 1209 adding root
1210 1210 $ echo a > a && hg ci -Am a
1211 1211 adding a
1212 1212 $ hg up 0
1213 1213 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1214 1214 $ echo b > b && hg ci -Am b
1215 1215 adding b
1216 1216 created new head
1217 1217 $ hg rebase -r 2 -d 1
1218 1218 rebasing 2:1e9a3c00cbe9 "b" (tip)
1219 1219 $ hg log -r . # working dir is at rev 3 (successor of 2)
1220 1220 3:be1832deae9a b (no-eol)
1221 1221 $ hg book -r 2 mybook --hidden # rev 2 has a bookmark on it now
1222 1222 $ hg up 2 && hg log -r . # working dir is at rev 2 again
1223 1223 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1224 1224 2:1e9a3c00cbe9 b (no-eol)
1225 1225 $ hg rebase -r 2 -d 3 --config experimental.stabilization.track-operation=1
1226 1226 note: not rebasing 2:1e9a3c00cbe9 "b" (mybook), already in destination as 3:be1832deae9a "b" (tip)
1227 1227 Check that working directory and bookmark was updated to rev 3 although rev 2
1228 1228 was skipped
1229 1229 $ hg log -r .
1230 1230 3:be1832deae9a b (no-eol)
1231 1231 $ hg bookmarks
1232 1232 mybook 3:be1832deae9a
1233 1233 $ hg debugobsolete --rev tip
1234 1234 1e9a3c00cbe90d236ac05ef61efcc5e40b7412bc be1832deae9ac531caa7438b8dcf6055a122cd8e 0 (*) {'user': 'test'} (glob)
1235 1235
1236 1236 Obsoleted working parent and bookmark could be moved if an ancestor of working
1237 1237 parent gets moved:
1238 1238
1239 1239 $ hg init $TESTTMP/ancestor-wd-move
1240 1240 $ cd $TESTTMP/ancestor-wd-move
1241 1241 $ hg debugdrawdag <<'EOS'
1242 1242 > E D1 # rebase: D1 -> D2
1243 1243 > | |
1244 1244 > | C
1245 1245 > D2 |
1246 1246 > | B
1247 1247 > |/
1248 1248 > A
1249 1249 > EOS
1250 1250 $ hg update D1 -q
1251 1251 $ hg bookmark book -i
1252 1252 $ hg rebase -r B+D1 -d E
1253 1253 rebasing 1:112478962961 "B" (B)
1254 1254 note: not rebasing 5:15ecf15e0114 "D1" (D1 tip book), already in destination as 2:0807738e0be9 "D2" (D2)
1255 1255 $ hg log -G -T '{desc} {bookmarks}'
1256 1256 @ B book
1257 1257 |
1258 1258 | x D1
1259 1259 | |
1260 1260 o | E
1261 1261 | |
1262 1262 | o C
1263 1263 | |
1264 1264 o | D2
1265 1265 | |
1266 1266 | x B
1267 1267 |/
1268 1268 o A
1269 1269
@@ -1,869 +1,869 b''
1 1 #require killdaemons
2 2
3 3 $ cat << EOF >> $HGRCPATH
4 4 > [format]
5 5 > usegeneraldelta=yes
6 6 > [ui]
7 7 > ssh=$PYTHON "$TESTDIR/dummyssh"
8 8 > EOF
9 9
10 10 Set up repo
11 11
12 12 $ hg --config experimental.treemanifest=True init repo
13 13 $ cd repo
14 14
15 15 Requirements get set on init
16 16
17 17 $ grep treemanifest .hg/requires
18 18 treemanifest
19 19
20 20 Without directories, looks like any other repo
21 21
22 22 $ echo 0 > a
23 23 $ echo 0 > b
24 24 $ hg ci -Aqm initial
25 25 $ hg debugdata -m 0
26 26 a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
27 27 b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
28 28
29 29 Submanifest is stored in separate revlog
30 30
31 31 $ mkdir dir1
32 32 $ echo 1 > dir1/a
33 33 $ echo 1 > dir1/b
34 34 $ echo 1 > e
35 35 $ hg ci -Aqm 'add dir1'
36 36 $ hg debugdata -m 1
37 37 a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
38 38 b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
39 39 dir1\x008b3ffd73f901e83304c83d33132c8e774ceac44et (esc)
40 40 e\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
41 41 $ hg debugdata --dir dir1 0
42 42 a\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
43 43 b\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
44 44
45 45 Can add nested directories
46 46
47 47 $ mkdir dir1/dir1
48 48 $ echo 2 > dir1/dir1/a
49 49 $ echo 2 > dir1/dir1/b
50 50 $ mkdir dir1/dir2
51 51 $ echo 2 > dir1/dir2/a
52 52 $ echo 2 > dir1/dir2/b
53 53 $ hg ci -Aqm 'add dir1/dir1'
54 54 $ hg files -r .
55 55 a
56 56 b
57 57 dir1/a (glob)
58 58 dir1/b (glob)
59 59 dir1/dir1/a (glob)
60 60 dir1/dir1/b (glob)
61 61 dir1/dir2/a (glob)
62 62 dir1/dir2/b (glob)
63 63 e
64 64
65 65 The manifest command works
66 66
67 67 $ hg manifest
68 68 a
69 69 b
70 70 dir1/a
71 71 dir1/b
72 72 dir1/dir1/a
73 73 dir1/dir1/b
74 74 dir1/dir2/a
75 75 dir1/dir2/b
76 76 e
77 77
78 78 Revision is not created for unchanged directory
79 79
80 80 $ mkdir dir2
81 81 $ echo 3 > dir2/a
82 82 $ hg add dir2
83 83 adding dir2/a (glob)
84 84 $ hg debugindex --dir dir1 > before
85 85 $ hg ci -qm 'add dir2'
86 86 $ hg debugindex --dir dir1 > after
87 87 $ diff before after
88 88 $ rm before after
89 89
90 90 Removing directory does not create an revlog entry
91 91
92 92 $ hg rm dir1/dir1
93 93 removing dir1/dir1/a (glob)
94 94 removing dir1/dir1/b (glob)
95 95 $ hg debugindex --dir dir1/dir1 > before
96 96 $ hg ci -qm 'remove dir1/dir1'
97 97 $ hg debugindex --dir dir1/dir1 > after
98 98 $ diff before after
99 99 $ rm before after
100 100
101 101 Check that hg files (calls treemanifest.walk()) works
102 102 without loading all directory revlogs
103 103
104 104 $ hg co 'desc("add dir2")'
105 105 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
106 106 $ mv .hg/store/meta/dir2 .hg/store/meta/dir2-backup
107 107 $ hg files -r . dir1
108 108 dir1/a (glob)
109 109 dir1/b (glob)
110 110 dir1/dir1/a (glob)
111 111 dir1/dir1/b (glob)
112 112 dir1/dir2/a (glob)
113 113 dir1/dir2/b (glob)
114 114
115 115 Check that status between revisions works (calls treemanifest.matches())
116 116 without loading all directory revlogs
117 117
118 118 $ hg status --rev 'desc("add dir1")' --rev . dir1
119 119 A dir1/dir1/a
120 120 A dir1/dir1/b
121 121 A dir1/dir2/a
122 122 A dir1/dir2/b
123 123 $ mv .hg/store/meta/dir2-backup .hg/store/meta/dir2
124 124
125 125 Merge creates 2-parent revision of directory revlog
126 126
127 127 $ echo 5 > dir1/a
128 128 $ hg ci -Aqm 'modify dir1/a'
129 129 $ hg co '.^'
130 130 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
131 131 $ echo 6 > dir1/b
132 132 $ hg ci -Aqm 'modify dir1/b'
133 133 $ hg merge 'desc("modify dir1/a")'
134 134 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
135 135 (branch merge, don't forget to commit)
136 136 $ hg ci -m 'conflict-free merge involving dir1/'
137 137 $ cat dir1/a
138 138 5
139 139 $ cat dir1/b
140 140 6
141 141 $ hg debugindex --dir dir1
142 142 rev offset length delta linkrev nodeid p1 p2
143 143 0 0 54 -1 1 8b3ffd73f901 000000000000 000000000000
144 144 1 54 68 0 2 68e9d057c5a8 8b3ffd73f901 000000000000
145 145 2 122 12 1 4 4698198d2624 68e9d057c5a8 000000000000
146 146 3 134 55 1 5 44844058ccce 68e9d057c5a8 000000000000
147 147 4 189 55 1 6 bf3d9b744927 68e9d057c5a8 000000000000
148 148 5 244 55 4 7 dde7c0af2a03 bf3d9b744927 44844058ccce
149 149
150 150 Merge keeping directory from parent 1 does not create revlog entry. (Note that
151 151 dir1's manifest does change, but only because dir1/a's filelog changes.)
152 152
153 153 $ hg co 'desc("add dir2")'
154 154 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
155 155 $ echo 8 > dir2/a
156 156 $ hg ci -m 'modify dir2/a'
157 157 created new head
158 158
159 159 $ hg debugindex --dir dir2 > before
160 160 $ hg merge 'desc("modify dir1/a")'
161 161 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 162 (branch merge, don't forget to commit)
163 163 $ hg revert -r 'desc("modify dir2/a")' .
164 164 reverting dir1/a (glob)
165 165 $ hg ci -m 'merge, keeping parent 1'
166 166 $ hg debugindex --dir dir2 > after
167 167 $ diff before after
168 168 $ rm before after
169 169
170 170 Merge keeping directory from parent 2 does not create revlog entry. (Note that
171 171 dir2's manifest does change, but only because dir2/a's filelog changes.)
172 172
173 173 $ hg co 'desc("modify dir2/a")'
174 174 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
175 175 $ hg debugindex --dir dir1 > before
176 176 $ hg merge 'desc("modify dir1/a")'
177 177 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
178 178 (branch merge, don't forget to commit)
179 179 $ hg revert -r 'desc("modify dir1/a")' .
180 180 reverting dir2/a (glob)
181 181 $ hg ci -m 'merge, keeping parent 2'
182 182 created new head
183 183 $ hg debugindex --dir dir1 > after
184 184 $ diff before after
185 185 $ rm before after
186 186
187 187 Create flat source repo for tests with mixed flat/tree manifests
188 188
189 189 $ cd ..
190 190 $ hg init repo-flat
191 191 $ cd repo-flat
192 192
193 193 Create a few commits with flat manifest
194 194
195 195 $ echo 0 > a
196 196 $ echo 0 > b
197 197 $ echo 0 > e
198 198 $ for d in dir1 dir1/dir1 dir1/dir2 dir2
199 199 > do
200 200 > mkdir $d
201 201 > echo 0 > $d/a
202 202 > echo 0 > $d/b
203 203 > done
204 204 $ hg ci -Aqm initial
205 205
206 206 $ echo 1 > a
207 207 $ echo 1 > dir1/a
208 208 $ echo 1 > dir1/dir1/a
209 209 $ hg ci -Aqm 'modify on branch 1'
210 210
211 211 $ hg co 0
212 212 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
213 213 $ echo 2 > b
214 214 $ echo 2 > dir1/b
215 215 $ echo 2 > dir1/dir1/b
216 216 $ hg ci -Aqm 'modify on branch 2'
217 217
218 218 $ hg merge 1
219 219 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 220 (branch merge, don't forget to commit)
221 221 $ hg ci -m 'merge of flat manifests to new flat manifest'
222 222
223 223 $ hg serve -p $HGPORT -d --pid-file=hg.pid --errorlog=errors.log
224 224 $ cat hg.pid >> $DAEMON_PIDS
225 225
226 226 Create clone with tree manifests enabled
227 227
228 228 $ cd ..
229 229 $ hg clone --config experimental.treemanifest=1 \
230 230 > http://localhost:$HGPORT repo-mixed -r 1
231 231 adding changesets
232 232 adding manifests
233 233 adding file changes
234 234 added 2 changesets with 14 changes to 11 files
235 235 updating to branch default
236 236 11 files updated, 0 files merged, 0 files removed, 0 files unresolved
237 237 $ cd repo-mixed
238 238 $ test -d .hg/store/meta
239 239 [1]
240 240 $ grep treemanifest .hg/requires
241 241 treemanifest
242 242
243 243 Should be possible to push updates from flat to tree manifest repo
244 244
245 245 $ hg -R ../repo-flat push ssh://user@dummy/repo-mixed
246 246 pushing to ssh://user@dummy/repo-mixed
247 247 searching for changes
248 248 remote: adding changesets
249 249 remote: adding manifests
250 250 remote: adding file changes
251 251 remote: added 2 changesets with 3 changes to 3 files
252 252
253 253 Commit should store revlog per directory
254 254
255 255 $ hg co 1
256 256 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
257 257 $ echo 3 > a
258 258 $ echo 3 > dir1/a
259 259 $ echo 3 > dir1/dir1/a
260 260 $ hg ci -m 'first tree'
261 261 created new head
262 262 $ find .hg/store/meta | sort
263 263 .hg/store/meta
264 264 .hg/store/meta/dir1
265 265 .hg/store/meta/dir1/00manifest.i
266 266 .hg/store/meta/dir1/dir1
267 267 .hg/store/meta/dir1/dir1/00manifest.i
268 268 .hg/store/meta/dir1/dir2
269 269 .hg/store/meta/dir1/dir2/00manifest.i
270 270 .hg/store/meta/dir2
271 271 .hg/store/meta/dir2/00manifest.i
272 272
273 273 Merge of two trees
274 274
275 275 $ hg co 2
276 276 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
277 277 $ hg merge 1
278 278 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
279 279 (branch merge, don't forget to commit)
280 280 $ hg ci -m 'merge of flat manifests to new tree manifest'
281 281 created new head
282 282 $ hg diff -r 3
283 283
284 284 Parent of tree root manifest should be flat manifest, and two for merge
285 285
286 286 $ hg debugindex -m
287 287 rev offset length delta linkrev nodeid p1 p2
288 288 0 0 80 -1 0 40536115ed9e 000000000000 000000000000
289 289 1 80 83 0 1 f3376063c255 40536115ed9e 000000000000
290 290 2 163 89 0 2 5d9b9da231a2 40536115ed9e 000000000000
291 291 3 252 83 2 3 d17d663cbd8a 5d9b9da231a2 f3376063c255
292 292 4 335 124 1 4 51e32a8c60ee f3376063c255 000000000000
293 293 5 459 126 2 5 cc5baa78b230 5d9b9da231a2 f3376063c255
294 294
295 295
296 296 Status across flat/tree boundary should work
297 297
298 298 $ hg status --rev '.^' --rev .
299 299 M a
300 300 M dir1/a
301 301 M dir1/dir1/a
302 302
303 303
304 304 Turning off treemanifest config has no effect
305 305
306 306 $ hg debugindex --dir dir1
307 307 rev offset length delta linkrev nodeid p1 p2
308 308 0 0 127 -1 4 064927a0648a 000000000000 000000000000
309 309 1 127 111 0 5 25ecb8cb8618 000000000000 000000000000
310 310 $ echo 2 > dir1/a
311 311 $ hg --config experimental.treemanifest=False ci -qm 'modify dir1/a'
312 312 $ hg debugindex --dir dir1
313 313 rev offset length delta linkrev nodeid p1 p2
314 314 0 0 127 -1 4 064927a0648a 000000000000 000000000000
315 315 1 127 111 0 5 25ecb8cb8618 000000000000 000000000000
316 316 2 238 55 1 6 5b16163a30c6 25ecb8cb8618 000000000000
317 317
318 318 Stripping and recovering changes should work
319 319
320 320 $ hg st --change tip
321 321 M dir1/a
322 322 $ hg --config extensions.strip= strip tip
323 323 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
324 324 saved backup bundle to $TESTTMP/repo-mixed/.hg/strip-backup/51cfd7b1e13b-78a2f3ed-backup.hg (glob)
325 325 $ hg debugindex --dir dir1
326 326 rev offset length delta linkrev nodeid p1 p2
327 327 0 0 127 -1 4 064927a0648a 000000000000 000000000000
328 328 1 127 111 0 5 25ecb8cb8618 000000000000 000000000000
329 329 $ hg incoming .hg/strip-backup/*
330 330 comparing with .hg/strip-backup/*-backup.hg (glob)
331 331 searching for changes
332 332 changeset: 6:51cfd7b1e13b
333 333 tag: tip
334 334 user: test
335 335 date: Thu Jan 01 00:00:00 1970 +0000
336 336 summary: modify dir1/a
337 337
338 338 $ hg pull .hg/strip-backup/*
339 339 pulling from .hg/strip-backup/51cfd7b1e13b-78a2f3ed-backup.hg
340 340 searching for changes
341 341 adding changesets
342 342 adding manifests
343 343 adding file changes
344 344 added 1 changesets with 1 changes to 1 files
345 345 (run 'hg update' to get a working copy)
346 346 $ hg --config extensions.strip= strip tip
347 347 saved backup bundle to $TESTTMP/repo-mixed/.hg/strip-backup/*-backup.hg (glob)
348 348 $ hg unbundle -q .hg/strip-backup/*
349 349 $ hg debugindex --dir dir1
350 350 rev offset length delta linkrev nodeid p1 p2
351 351 0 0 127 -1 4 064927a0648a 000000000000 000000000000
352 352 1 127 111 0 5 25ecb8cb8618 000000000000 000000000000
353 353 2 238 55 1 6 5b16163a30c6 25ecb8cb8618 000000000000
354 354 $ hg st --change tip
355 355 M dir1/a
356 356
357 357 Shelving and unshelving should work
358 358
359 359 $ echo foo >> dir1/a
360 360 $ hg --config extensions.shelve= shelve
361 361 shelved as default
362 362 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
363 363 $ hg --config extensions.shelve= unshelve
364 364 unshelving change 'default'
365 365 $ hg diff --nodates
366 366 diff -r 708a273da119 dir1/a
367 367 --- a/dir1/a
368 368 +++ b/dir1/a
369 369 @@ -1,1 +1,2 @@
370 370 1
371 371 +foo
372 372
373 373 Pushing from treemanifest repo to an empty repo makes that a treemanifest repo
374 374
375 375 $ cd ..
376 376 $ hg init empty-repo
377 377 $ cat << EOF >> empty-repo/.hg/hgrc
378 378 > [experimental]
379 379 > changegroup3=yes
380 380 > EOF
381 381 $ grep treemanifest empty-repo/.hg/requires
382 382 [1]
383 383 $ hg push -R repo -r 0 empty-repo
384 384 pushing to empty-repo
385 385 searching for changes
386 386 adding changesets
387 387 adding manifests
388 388 adding file changes
389 389 added 1 changesets with 2 changes to 2 files
390 390 $ grep treemanifest empty-repo/.hg/requires
391 391 treemanifest
392 392
393 393 Pushing to an empty repo works
394 394
395 395 $ hg --config experimental.treemanifest=1 init clone
396 396 $ grep treemanifest clone/.hg/requires
397 397 treemanifest
398 398 $ hg push -R repo clone
399 399 pushing to clone
400 400 searching for changes
401 401 adding changesets
402 402 adding manifests
403 403 adding file changes
404 404 added 11 changesets with 15 changes to 10 files (+3 heads)
405 405 $ grep treemanifest clone/.hg/requires
406 406 treemanifest
407 407 $ hg -R clone verify
408 408 checking changesets
409 409 checking manifests
410 410 checking directory manifests
411 411 crosschecking files in changesets and manifests
412 412 checking files
413 413 10 files, 11 changesets, 15 total revisions
414 414
415 415 Create deeper repo with tree manifests.
416 416
417 417 $ hg --config experimental.treemanifest=True init deeprepo
418 418 $ cd deeprepo
419 419
420 420 $ mkdir .A
421 421 $ mkdir b
422 422 $ mkdir b/bar
423 423 $ mkdir b/bar/orange
424 424 $ mkdir b/bar/orange/fly
425 425 $ mkdir b/foo
426 426 $ mkdir b/foo/apple
427 427 $ mkdir b/foo/apple/bees
428 428
429 429 $ touch .A/one.txt
430 430 $ touch .A/two.txt
431 431 $ touch b/bar/fruits.txt
432 432 $ touch b/bar/orange/fly/gnat.py
433 433 $ touch b/bar/orange/fly/housefly.txt
434 434 $ touch b/foo/apple/bees/flower.py
435 435 $ touch c.txt
436 436 $ touch d.py
437 437
438 438 $ hg ci -Aqm 'initial'
439 439
440 440 $ echo >> .A/one.txt
441 441 $ echo >> .A/two.txt
442 442 $ echo >> b/bar/fruits.txt
443 443 $ echo >> b/bar/orange/fly/gnat.py
444 444 $ echo >> b/bar/orange/fly/housefly.txt
445 445 $ echo >> b/foo/apple/bees/flower.py
446 446 $ echo >> c.txt
447 447 $ echo >> d.py
448 448 $ hg ci -Aqm 'second'
449 449
450 450 We'll see that visitdir works by removing some treemanifest revlogs and running
451 451 the files command with various parameters.
452 452
453 453 Test files from the root.
454 454
455 455 $ hg files -r .
456 456 .A/one.txt (glob)
457 457 .A/two.txt (glob)
458 458 b/bar/fruits.txt (glob)
459 459 b/bar/orange/fly/gnat.py (glob)
460 460 b/bar/orange/fly/housefly.txt (glob)
461 461 b/foo/apple/bees/flower.py (glob)
462 462 c.txt
463 463 d.py
464 464
465 465 Excludes with a glob should not exclude everything from the glob's root
466 466
467 467 $ hg files -r . -X 'b/fo?' b
468 468 b/bar/fruits.txt (glob)
469 469 b/bar/orange/fly/gnat.py (glob)
470 470 b/bar/orange/fly/housefly.txt (glob)
471 471 $ cp -R .hg/store .hg/store-copy
472 472
473 473 Test files for a subdirectory.
474 474
475 475 $ rm -r .hg/store/meta/~2e_a
476 476 $ hg files -r . b
477 477 b/bar/fruits.txt (glob)
478 478 b/bar/orange/fly/gnat.py (glob)
479 479 b/bar/orange/fly/housefly.txt (glob)
480 480 b/foo/apple/bees/flower.py (glob)
481 481 $ hg diff -r '.^' -r . --stat b
482 482 b/bar/fruits.txt | 1 +
483 483 b/bar/orange/fly/gnat.py | 1 +
484 484 b/bar/orange/fly/housefly.txt | 1 +
485 485 b/foo/apple/bees/flower.py | 1 +
486 486 4 files changed, 4 insertions(+), 0 deletions(-)
487 487 $ cp -R .hg/store-copy/. .hg/store
488 488
489 489 Test files with just includes and excludes.
490 490
491 491 $ rm -r .hg/store/meta/~2e_a
492 492 $ rm -r .hg/store/meta/b/bar/orange/fly
493 493 $ rm -r .hg/store/meta/b/foo/apple/bees
494 494 $ hg files -r . -I path:b/bar -X path:b/bar/orange/fly -I path:b/foo -X path:b/foo/apple/bees
495 495 b/bar/fruits.txt (glob)
496 496 $ hg diff -r '.^' -r . --stat -I path:b/bar -X path:b/bar/orange/fly -I path:b/foo -X path:b/foo/apple/bees
497 497 b/bar/fruits.txt | 1 +
498 498 1 files changed, 1 insertions(+), 0 deletions(-)
499 499 $ cp -R .hg/store-copy/. .hg/store
500 500
501 501 Test files for a subdirectory, excluding a directory within it.
502 502
503 503 $ rm -r .hg/store/meta/~2e_a
504 504 $ rm -r .hg/store/meta/b/foo
505 505 $ hg files -r . -X path:b/foo b
506 506 b/bar/fruits.txt (glob)
507 507 b/bar/orange/fly/gnat.py (glob)
508 508 b/bar/orange/fly/housefly.txt (glob)
509 509 $ hg diff -r '.^' -r . --stat -X path:b/foo b
510 510 b/bar/fruits.txt | 1 +
511 511 b/bar/orange/fly/gnat.py | 1 +
512 512 b/bar/orange/fly/housefly.txt | 1 +
513 513 3 files changed, 3 insertions(+), 0 deletions(-)
514 514 $ cp -R .hg/store-copy/. .hg/store
515 515
516 516 Test files for a sub directory, including only a directory within it, and
517 517 including an unrelated directory.
518 518
519 519 $ rm -r .hg/store/meta/~2e_a
520 520 $ rm -r .hg/store/meta/b/foo
521 521 $ hg files -r . -I path:b/bar/orange -I path:a b
522 522 b/bar/orange/fly/gnat.py (glob)
523 523 b/bar/orange/fly/housefly.txt (glob)
524 524 $ hg diff -r '.^' -r . --stat -I path:b/bar/orange -I path:a b
525 525 b/bar/orange/fly/gnat.py | 1 +
526 526 b/bar/orange/fly/housefly.txt | 1 +
527 527 2 files changed, 2 insertions(+), 0 deletions(-)
528 528 $ cp -R .hg/store-copy/. .hg/store
529 529
530 530 Test files for a pattern, including a directory, and excluding a directory
531 531 within that.
532 532
533 533 $ rm -r .hg/store/meta/~2e_a
534 534 $ rm -r .hg/store/meta/b/foo
535 535 $ rm -r .hg/store/meta/b/bar/orange
536 536 $ hg files -r . glob:**.txt -I path:b/bar -X path:b/bar/orange
537 537 b/bar/fruits.txt (glob)
538 538 $ hg diff -r '.^' -r . --stat glob:**.txt -I path:b/bar -X path:b/bar/orange
539 539 b/bar/fruits.txt | 1 +
540 540 1 files changed, 1 insertions(+), 0 deletions(-)
541 541 $ cp -R .hg/store-copy/. .hg/store
542 542
543 543 Add some more changes to the deep repo
544 544 $ echo narf >> b/bar/fruits.txt
545 545 $ hg ci -m narf
546 546 $ echo troz >> b/bar/orange/fly/gnat.py
547 547 $ hg ci -m troz
548 548
549 549 Verify works
550 550 $ hg verify
551 551 checking changesets
552 552 checking manifests
553 553 checking directory manifests
554 554 crosschecking files in changesets and manifests
555 555 checking files
556 556 8 files, 4 changesets, 18 total revisions
557 557
558 558 Dirlogs are included in fncache
559 559 $ grep meta/.A/00manifest.i .hg/store/fncache
560 560 meta/.A/00manifest.i
561 561
562 562 Rebuilt fncache includes dirlogs
563 563 $ rm .hg/store/fncache
564 564 $ hg debugrebuildfncache
565 565 adding data/.A/one.txt.i
566 566 adding data/.A/two.txt.i
567 567 adding data/b/bar/fruits.txt.i
568 568 adding data/b/bar/orange/fly/gnat.py.i
569 569 adding data/b/bar/orange/fly/housefly.txt.i
570 570 adding data/b/foo/apple/bees/flower.py.i
571 571 adding data/c.txt.i
572 572 adding data/d.py.i
573 573 adding meta/.A/00manifest.i
574 574 adding meta/b/00manifest.i
575 575 adding meta/b/bar/00manifest.i
576 576 adding meta/b/bar/orange/00manifest.i
577 577 adding meta/b/bar/orange/fly/00manifest.i
578 578 adding meta/b/foo/00manifest.i
579 579 adding meta/b/foo/apple/00manifest.i
580 580 adding meta/b/foo/apple/bees/00manifest.i
581 581 16 items added, 0 removed from fncache
582 582
583 583 Finish first server
584 584 $ killdaemons.py
585 585
586 586 Back up the recently added revlogs
587 587 $ cp -R .hg/store .hg/store-newcopy
588 588
589 589 Verify reports missing dirlog
590 590 $ rm .hg/store/meta/b/00manifest.*
591 591 $ hg verify
592 592 checking changesets
593 593 checking manifests
594 594 checking directory manifests
595 595 0: empty or missing b/
596 596 b/@0: parent-directory manifest refers to unknown revision 67688a370455
597 597 b/@1: parent-directory manifest refers to unknown revision f065da70369e
598 598 b/@2: parent-directory manifest refers to unknown revision ac0d30948e0b
599 599 b/@3: parent-directory manifest refers to unknown revision 367152e6af28
600 600 warning: orphan revlog 'meta/b/bar/00manifest.i'
601 601 warning: orphan revlog 'meta/b/bar/orange/00manifest.i'
602 602 warning: orphan revlog 'meta/b/bar/orange/fly/00manifest.i'
603 603 warning: orphan revlog 'meta/b/foo/00manifest.i'
604 604 warning: orphan revlog 'meta/b/foo/apple/00manifest.i'
605 605 warning: orphan revlog 'meta/b/foo/apple/bees/00manifest.i'
606 606 crosschecking files in changesets and manifests
607 607 b/bar/fruits.txt@0: in changeset but not in manifest
608 608 b/bar/orange/fly/gnat.py@0: in changeset but not in manifest
609 609 b/bar/orange/fly/housefly.txt@0: in changeset but not in manifest
610 610 b/foo/apple/bees/flower.py@0: in changeset but not in manifest
611 611 checking files
612 612 8 files, 4 changesets, 18 total revisions
613 613 6 warnings encountered!
614 614 9 integrity errors encountered!
615 615 (first damaged changeset appears to be 0)
616 616 [1]
617 617 $ cp -R .hg/store-newcopy/. .hg/store
618 618
619 619 Verify reports missing dirlog entry
620 620 $ mv -f .hg/store-copy/meta/b/00manifest.* .hg/store/meta/b/
621 621 $ hg verify
622 622 checking changesets
623 623 checking manifests
624 624 checking directory manifests
625 625 b/@2: parent-directory manifest refers to unknown revision ac0d30948e0b
626 626 b/@3: parent-directory manifest refers to unknown revision 367152e6af28
627 627 b/bar/@?: rev 2 points to unexpected changeset 2
628 628 b/bar/@?: 44d7e1146e0d not in parent-directory manifest
629 629 b/bar/@?: rev 3 points to unexpected changeset 3
630 630 b/bar/@?: 70b10c6b17b7 not in parent-directory manifest
631 631 b/bar/orange/@?: rev 2 points to unexpected changeset 3
632 632 (expected None)
633 633 b/bar/orange/fly/@?: rev 2 points to unexpected changeset 3
634 634 (expected None)
635 635 crosschecking files in changesets and manifests
636 636 checking files
637 637 8 files, 4 changesets, 18 total revisions
638 638 2 warnings encountered!
639 639 8 integrity errors encountered!
640 640 (first damaged changeset appears to be 2)
641 641 [1]
642 642 $ cp -R .hg/store-newcopy/. .hg/store
643 643
644 644 Test cloning a treemanifest repo over http.
645 645 $ hg serve -p $HGPORT -d --pid-file=hg.pid --errorlog=errors.log
646 646 $ cat hg.pid >> $DAEMON_PIDS
647 647 $ cd ..
648 648 We can clone even with the knob turned off and we'll get a treemanifest repo.
649 649 $ hg clone --config experimental.treemanifest=False \
650 650 > --config experimental.changegroup3=True \
651 651 > http://localhost:$HGPORT deepclone
652 652 requesting all changes
653 653 adding changesets
654 654 adding manifests
655 655 adding file changes
656 656 added 4 changesets with 18 changes to 8 files
657 657 updating to branch default
658 658 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
659 659 No server errors.
660 660 $ cat deeprepo/errors.log
661 661 requires got updated to include treemanifest
662 662 $ cat deepclone/.hg/requires | grep treemanifest
663 663 treemanifest
664 664 Tree manifest revlogs exist.
665 665 $ find deepclone/.hg/store/meta | sort
666 666 deepclone/.hg/store/meta
667 667 deepclone/.hg/store/meta/b
668 668 deepclone/.hg/store/meta/b/00manifest.i
669 669 deepclone/.hg/store/meta/b/bar
670 670 deepclone/.hg/store/meta/b/bar/00manifest.i
671 671 deepclone/.hg/store/meta/b/bar/orange
672 672 deepclone/.hg/store/meta/b/bar/orange/00manifest.i
673 673 deepclone/.hg/store/meta/b/bar/orange/fly
674 674 deepclone/.hg/store/meta/b/bar/orange/fly/00manifest.i
675 675 deepclone/.hg/store/meta/b/foo
676 676 deepclone/.hg/store/meta/b/foo/00manifest.i
677 677 deepclone/.hg/store/meta/b/foo/apple
678 678 deepclone/.hg/store/meta/b/foo/apple/00manifest.i
679 679 deepclone/.hg/store/meta/b/foo/apple/bees
680 680 deepclone/.hg/store/meta/b/foo/apple/bees/00manifest.i
681 681 deepclone/.hg/store/meta/~2e_a
682 682 deepclone/.hg/store/meta/~2e_a/00manifest.i
683 683 Verify passes.
684 684 $ cd deepclone
685 685 $ hg verify
686 686 checking changesets
687 687 checking manifests
688 688 checking directory manifests
689 689 crosschecking files in changesets and manifests
690 690 checking files
691 691 8 files, 4 changesets, 18 total revisions
692 692 $ cd ..
693 693
694 694 Create clones using old repo formats to use in later tests
695 695 $ hg clone --config format.usestore=False \
696 696 > --config experimental.changegroup3=True \
697 697 > http://localhost:$HGPORT deeprepo-basicstore
698 698 requesting all changes
699 699 adding changesets
700 700 adding manifests
701 701 adding file changes
702 702 added 4 changesets with 18 changes to 8 files
703 703 updating to branch default
704 704 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
705 705 $ cd deeprepo-basicstore
706 706 $ grep store .hg/requires
707 707 [1]
708 708 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --errorlog=errors.log
709 709 $ cat hg.pid >> $DAEMON_PIDS
710 710 $ cd ..
711 711 $ hg clone --config format.usefncache=False \
712 712 > --config experimental.changegroup3=True \
713 713 > http://localhost:$HGPORT deeprepo-encodedstore
714 714 requesting all changes
715 715 adding changesets
716 716 adding manifests
717 717 adding file changes
718 718 added 4 changesets with 18 changes to 8 files
719 719 updating to branch default
720 720 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
721 721 $ cd deeprepo-encodedstore
722 722 $ grep fncache .hg/requires
723 723 [1]
724 724 $ hg serve -p $HGPORT2 -d --pid-file=hg.pid --errorlog=errors.log
725 725 $ cat hg.pid >> $DAEMON_PIDS
726 726 $ cd ..
727 727
728 728 Local clone with basicstore
729 729 $ hg clone -U deeprepo-basicstore local-clone-basicstore
730 730 $ hg -R local-clone-basicstore verify
731 731 checking changesets
732 732 checking manifests
733 733 checking directory manifests
734 734 crosschecking files in changesets and manifests
735 735 checking files
736 736 8 files, 4 changesets, 18 total revisions
737 737
738 738 Local clone with encodedstore
739 739 $ hg clone -U deeprepo-encodedstore local-clone-encodedstore
740 740 $ hg -R local-clone-encodedstore verify
741 741 checking changesets
742 742 checking manifests
743 743 checking directory manifests
744 744 crosschecking files in changesets and manifests
745 745 checking files
746 746 8 files, 4 changesets, 18 total revisions
747 747
748 748 Local clone with fncachestore
749 749 $ hg clone -U deeprepo local-clone-fncachestore
750 750 $ hg -R local-clone-fncachestore verify
751 751 checking changesets
752 752 checking manifests
753 753 checking directory manifests
754 754 crosschecking files in changesets and manifests
755 755 checking files
756 756 8 files, 4 changesets, 18 total revisions
757 757
758 758 Stream clone with basicstore
759 759 $ hg clone --config experimental.changegroup3=True --uncompressed -U \
760 760 > http://localhost:$HGPORT1 stream-clone-basicstore
761 761 streaming all changes
762 762 18 files to transfer, * of data (glob)
763 763 transferred * in * seconds (*) (glob)
764 764 searching for changes
765 765 no changes found
766 766 $ hg -R stream-clone-basicstore verify
767 767 checking changesets
768 768 checking manifests
769 769 checking directory manifests
770 770 crosschecking files in changesets and manifests
771 771 checking files
772 772 8 files, 4 changesets, 18 total revisions
773 773
774 774 Stream clone with encodedstore
775 775 $ hg clone --config experimental.changegroup3=True --uncompressed -U \
776 776 > http://localhost:$HGPORT2 stream-clone-encodedstore
777 777 streaming all changes
778 778 18 files to transfer, * of data (glob)
779 779 transferred * in * seconds (*) (glob)
780 780 searching for changes
781 781 no changes found
782 782 $ hg -R stream-clone-encodedstore verify
783 783 checking changesets
784 784 checking manifests
785 785 checking directory manifests
786 786 crosschecking files in changesets and manifests
787 787 checking files
788 788 8 files, 4 changesets, 18 total revisions
789 789
790 790 Stream clone with fncachestore
791 791 $ hg clone --config experimental.changegroup3=True --uncompressed -U \
792 792 > http://localhost:$HGPORT stream-clone-fncachestore
793 793 streaming all changes
794 794 18 files to transfer, * of data (glob)
795 795 transferred * in * seconds (*) (glob)
796 796 searching for changes
797 797 no changes found
798 798 $ hg -R stream-clone-fncachestore verify
799 799 checking changesets
800 800 checking manifests
801 801 checking directory manifests
802 802 crosschecking files in changesets and manifests
803 803 checking files
804 804 8 files, 4 changesets, 18 total revisions
805 805
806 806 Packed bundle
807 807 $ hg -R deeprepo debugcreatestreamclonebundle repo-packed.hg
808 808 writing 5330 bytes for 18 files
809 809 bundle requirements: generaldelta, revlogv1, treemanifest
810 810 $ hg debugbundle --spec repo-packed.hg
811 811 none-packed1;requirements%3Dgeneraldelta%2Crevlogv1%2Ctreemanifest
812 812
813 813 Bundle with changegroup2 is not supported
814 814
815 815 $ hg -R deeprepo bundle --all -t v2 deeprepo.bundle
816 816 abort: repository does not support bundle version 02
817 817 [255]
818 818
819 819 Pull does not include changegroup for manifest the client already has from
820 820 other branch
821 821
822 822 $ mkdir grafted-dir-repo
823 823 $ cd grafted-dir-repo
824 824 $ hg --config experimental.treemanifest=1 init
825 825 $ mkdir dir
826 826 $ echo a > dir/file
827 827 $ echo a > file
828 828 $ hg ci -Am initial
829 829 adding dir/file
830 830 adding file
831 831 $ echo b > dir/file
832 832 $ hg ci -m updated
833 833 $ hg co '.^'
834 834 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
835 835 $ hg revert -r tip dir/
836 836 reverting dir/file (glob)
837 837 $ echo b > file # to make sure root manifest is sent
838 838 $ hg ci -m grafted
839 839 created new head
840 840 $ cd ..
841 841
842 842 $ hg --config experimental.treemanifest=1 clone --pull -r 1 \
843 843 > grafted-dir-repo grafted-dir-repo-clone
844 844 adding changesets
845 845 adding manifests
846 846 adding file changes
847 847 added 2 changesets with 3 changes to 2 files
848 848 updating to branch default
849 849 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
850 850 $ cd grafted-dir-repo-clone
851 851 $ hg pull -r 2
852 852 pulling from $TESTTMP/grafted-dir-repo (glob)
853 853 searching for changes
854 854 adding changesets
855 855 adding manifests
856 856 adding file changes
857 857 added 1 changesets with 1 changes to 1 files (+1 heads)
858 858 (run 'hg heads' to see heads, 'hg merge' to merge)
859 859
860 860 Committing a empty commit does not duplicate root treemanifest
861 861 $ echo z >> z
862 862 $ hg commit -Aqm 'pre-empty commit'
863 863 $ hg rm z
864 864 $ hg commit --amend -m 'empty commit'
865 saved backup bundle to $TESTTMP/grafted-dir-repo-clone/.hg/strip-backup/cb99d5717cea-de37743b-amend.hg (glob)
865 saved backup bundle to $TESTTMP/grafted-dir-repo-clone/.hg/strip-backup/cb99d5717cea-9e3b6b02-amend.hg (glob)
866 866 $ hg log -r 'tip + tip^' -T '{manifest}\n'
867 867 1:678d3574b88c
868 868 1:678d3574b88c
869 869 $ hg --config extensions.strip= strip -r . -q
General Comments 0
You need to be logged in to leave comments. Login now