# HG changeset patch # User Pierre-Yves David # Date 1577391810 -3600 # Node ID c5efcbbd0dc46d82cf019c0aa3ca47838519ad70 # Parent 7cc3d96eb58947049ca8106ca26f671a8453d88d# Parent 1015a1dbaf7c436d3a26fe03dae480c0aa49f866 branching: merge with stable diff -r 1015a1dbaf7c -r c5efcbbd0dc4 .gitlab-ci.yml --- a/.gitlab-ci.yml Thu Dec 26 12:22:49 2019 +0700 +++ b/.gitlab-ci.yml Thu Dec 26 21:23:30 2019 +0100 @@ -34,3 +34,14 @@ - hg_rev=$(tests/testlib/map-hg-rev.sh "$(hg log -r . -T '{branch}')") - hg -R /ci/repos/mercurial/ update "$hg_rev" - (cd tests; python3 /ci/repos/mercurial/tests/run-tests.py --color=always --pure) + +doc: + image: octobus/ci-py2-evolve-doc + script: + - cd docs/ + - make + variables: + LANG: en_us.UTF-8 + artifacts: + paths: + - html/* diff -r 1015a1dbaf7c -r c5efcbbd0dc4 CHANGELOG --- a/CHANGELOG Thu Dec 26 12:22:49 2019 +0700 +++ b/CHANGELOG Thu Dec 26 21:23:30 2019 +0100 @@ -1,6 +1,15 @@ Changelog ========= +9.3.0 - in progress +------------------- + + * exchange: dropped more bundle-1 related dead code + * help: categorizing evolve and topic commands + * obslog: make templatable + * compat: cleanup some compatibility code for mercurial < 4.5 + * compat: compatibility with some changes of the upcoming Mercurial 5.3 + 9.2.2 - in progress ------------------- diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/evolve/__init__.py --- a/hgext3rd/evolve/__init__.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/evolve/__init__.py Thu Dec 26 21:23:30 2019 +0100 @@ -465,7 +465,8 @@ _alias, statuscmd = cmdutil.findcmd(b'status', commands.table) pstatusopts = [o for o in statuscmd[1] if o[1] != b'rev'] - @eh.command(b'pstatus', pstatusopts) + @eh.command(b'pstatus', pstatusopts, + **compat.helpcategorykwargs('CATEGORY_WORKING_DIRECTORY')) def pstatus(ui, repo, *args, **kwargs): """show status combining committed and uncommited changes @@ -480,7 +481,8 @@ _alias, diffcmd = cmdutil.findcmd(b'diff', commands.table) pdiffopts = [o for o in diffcmd[1] if o[1] != b'rev'] - @eh.command(b'pdiff', pdiffopts) + @eh.command(b'pdiff', pdiffopts, + **compat.helpcategorykwargs('CATEGORY_WORKING_DIRECTORY')) def pdiff(ui, repo, *args, **kwargs): """show diff combining committed and uncommited changes @@ -947,7 +949,7 @@ def _findprevtarget(repo, displayer, movebookmark=False, topic=True): target = bookmark = None wkctx = repo[None] - p1 = wkctx.parents()[0] + p1 = wkctx.p1() parents = p1.parents() currenttopic = _getcurrenttopic(repo) @@ -989,7 +991,8 @@ (b'n', b'dry-run', False, _(b'do not perform actions, just print what would be done'))], b'[OPTION]...', - helpbasic=True) + helpbasic=True, + **compat.helpcategorykwargs('CATEGORY_WORKING_DIRECTORY')) def cmdprevious(ui, repo, **opts): """update to parent revision @@ -1023,15 +1026,14 @@ target, bookmark = _findprevtarget(repo, displayer, opts.get('move_bookmark'), topic) if target is not None: - backup = repo.ui.backupconfig(b'_internal', b'keep-topic') - try: - if topic and _getcurrenttopic(repo) != _gettopic(target): - repo.ui.setconfig(b'_internal', b'keep-topic', b'yes', - source=b'topic-extension') + configoverride = util.nullcontextmanager() + if topic and _getcurrenttopic(repo) != _gettopic(target): + configoverride = repo.ui.configoverride({ + (b'_internal', b'keep-topic'): b'yes' + }, source=b'topic-extension') + with configoverride: _prevupdate(repo, displayer, target, bookmark, dryrunopt, mergeopt) - finally: - repo.ui.restoreconfig(backup) return 0 else: return 1 @@ -1048,7 +1050,8 @@ (b'n', b'dry-run', False, _(b'do not perform actions, just print what would be done'))], b'[OPTION]...', - helpbasic=True) + helpbasic=True, + **compat.helpcategorykwargs('CATEGORY_WORKING_DIRECTORY')) def cmdnext(ui, repo, **opts): """update to next child revision @@ -1339,8 +1342,16 @@ if entry[0] == b"evolution": break else: - help.helptable.append(([b"evolution"], _(b"Safely Rewriting History"), - _helploader)) + if util.safehasattr(help, 'TOPIC_CATEGORY_CONCEPTS'): + help.helptable.append(([b"evolution"], + _(b"Safely Rewriting History"), + _helploader, + help.TOPIC_CATEGORY_CONCEPTS)) + else: + # hg <= 4.7 (c303d65d2e34) + help.helptable.append(([b"evolution"], + _(b"Safely Rewriting History"), + _helploader)) help.helptable.sort() evolvestateversion = 0 diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/evolve/cmdrewrite.py --- a/hgext3rd/evolve/cmdrewrite.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/evolve/cmdrewrite.py Thu Dec 26 21:23:30 2019 +0100 @@ -109,7 +109,8 @@ (b'n', b'note', b'', _(b'store a note on amend'), _(b'TEXT')), ] + walkopts + commitopts + commitopts2 + commitopts3 + interactiveopt, _(b'[OPTION]... [FILE]...'), - helpbasic=True) + helpbasic=True, + **compat.helpcategorykwargs('CATEGORY_COMMITTING')) def amend(ui, repo, *pats, **opts): """combine a changeset with updates and replace it with a new one @@ -291,8 +292,10 @@ def _touchedbetween(repo, source, dest, match=None): touched = set() - for files in repo.status(source, dest, match=match)[:3]: - touched.update(files) + st = repo.status(source, dest, match=match) + touched.update(st.modified) + touched.update(st.added) + touched.update(st.removed) return touched def _commitfiltered(repo, ctx, match, target=None, message=None, user=None, @@ -364,8 +367,8 @@ # and considering only the files which are changed between oldctx and # ctx, and the status of what changed between oldctx and ctx will help # us in defining the exact behavior - m, a, r = repo.status(oldctx, ctx, match=match)[:3] - for f in m: + st = repo.status(oldctx, ctx, match=match) + for f in st.modified: # These are files which are modified between oldctx and ctx which # contains two cases: 1) Were modified in oldctx and some # modifications are uncommitted @@ -381,7 +384,7 @@ continue ds.normallookup(f) - for f in a: + for f in st.added: # These are the files which are added between oldctx and ctx(new # one), which means the files which were removed in oldctx # but uncommitted completely while making the ctx @@ -394,7 +397,7 @@ continue ds.remove(f) - for f in r: + for f in st.removed: # These are files which are removed between oldctx and ctx, which # means the files which were added in oldctx and were completely # uncommitted in ctx. If a added file is partially uncommitted, that @@ -408,21 +411,21 @@ continue ds.add(f) else: - m, a, r = repo.status(oldctx.p1(), oldctx, match=match)[:3] - for f in m: + st = repo.status(oldctx.p1(), oldctx, match=match) + for f in st.modified: if ds[f] == b'r': # modified + removed -> removed continue ds.normallookup(f) - for f in a: + for f in st.added: if ds[f] == b'r': # added + removed -> unknown ds.drop(f) elif ds[f] != b'a': ds.add(f) - for f in r: + for f in st.removed: if ds[f] == b'a': # removed + added -> normal ds.normallookup(f) @@ -434,8 +437,8 @@ if interactive: # Interactive had different meaning of the variables so restoring the # original meaning to use them - m, a, r = repo.status(oldctx.p1(), oldctx, match=match)[:3] - for f in (m + a): + st = repo.status(oldctx.p1(), oldctx, match=match) + for f in (st.modified + st.added): src = oldctx[f].renamed() if src: oldcopies[f] = src[0] @@ -456,7 +459,8 @@ (b'', b'revert', False, _(b'discard working directory changes after uncommit')), (b'n', b'note', b'', _(b'store a note on uncommit'), _(b'TEXT')), ] + commands.walkopts + commitopts + commitopts2 + commitopts3, - _(b'[OPTION]... [FILE]...')) + _(b'[OPTION]... [FILE]...'), + **compat.helpcategorykwargs('CATEGORY_CHANGE_MANAGEMENT')) def uncommit(ui, repo, *pats, **opts): """move changes from parent revision to working directory @@ -692,7 +696,8 @@ (b'n', b'note', b'', _(b'store a note on fold'), _(b'TEXT')), ] + commitopts + commitopts2 + commitopts3, _(b'hg fold [OPTION]... [-r] REV...'), - helpbasic=True) + helpbasic=True, + **compat.helpcategorykwargs('CATEGORY_CHANGE_MANAGEMENT')) def fold(ui, repo, *revs, **opts): """fold multiple revisions into a single one @@ -822,7 +827,8 @@ (b'', b'fold', None, _(b"also fold specified revisions into one")), (b'n', b'note', b'', _(b'store a note on metaedit'), _(b'TEXT')), ] + commitopts + commitopts2 + commitopts3, - _(b'hg metaedit [OPTION]... [[-r] REV]...')) + _(b'hg metaedit [OPTION]... [[-r] REV]...'), + **compat.helpcategorykwargs('CATEGORY_CHANGE_MANAGEMENT')) def metaedit(ui, repo, *revs, **opts): """edit commit information @@ -980,7 +986,8 @@ (b'B', b'bookmark', [], _(b"remove revs only reachable from given" b" bookmark"), _(b'BOOKMARK'))] + metadataopts, _(b'[OPTION]... [-r] REV...'), - helpbasic=True) + helpbasic=True, + **compat.helpcategorykwargs('CATEGORY_CHANGE_MANAGEMENT')) # XXX -U --noupdate option to prevent wc update and or bookmarks update ? def cmdprune(ui, repo, *revs, **opts): """mark changesets as obsolete or succeeded by another changeset @@ -1090,7 +1097,7 @@ newnode = wdp while newnode in precs or newnode.obsolete(): - newnode = newnode.parents()[0] + newnode = newnode.p1() else: # no need to update anywhere as wdp is not related to revs # being pruned @@ -1174,7 +1181,8 @@ (b'n', b'note', b'', _(b"store a note on split"), _(b'TEXT')), ] + commitopts + commitopts2 + commitopts3, _(b'hg split [OPTION]... [-r REV] [FILE]...'), - helpbasic=True) + helpbasic=True, + **compat.helpcategorykwargs('CATEGORY_CHANGE_MANAGEMENT')) def cmdsplit(ui, repo, *pats, **opts): """split a changeset into smaller changesets @@ -1230,8 +1238,8 @@ rewriteutil.presplitupdate(repo, ui, prev, ctx) def haschanges(matcher=None): - modified, added, removed, deleted = repo.status(match=matcher)[:4] - return modified or added or removed or deleted + st = repo.status(match=matcher) + return st.modified or st.added or st.removed or st.deleted msg = (b"HG: This is the original pre-split commit message. " b"Edit it as appropriate.\n\n") msg += ctx.description() @@ -1294,10 +1302,12 @@ ui.status(_(b'discarding remaining changes\n')) target = newcommits[0] if pats: - status = repo.status(match=matcher)[:4] + status = repo.status(match=matcher) dirty = set() - for i in status: - dirty.update(i) + dirty.update(status.modified) + dirty.update(status.added) + dirty.update(status.removed) + dirty.update(status.deleted) dirty = sorted(dirty) cmdutil.revert(ui, repo, repo[target], (target, node.nullid), *dirty) @@ -1349,7 +1359,8 @@ b'mark the new revision as successor of the old one potentially creating ' b'divergence')], # allow to choose the seed ? - _(b'[OPTION]... [-r] REV...')) + _(b'[OPTION]... [-r] REV...'), + **compat.helpcategorykwargs('CATEGORY_CHANGE_MANAGEMENT')) def touch(ui, repo, *revs, **opts): """create successors identical to their predecessors but the changeset ID @@ -1450,7 +1461,8 @@ (b'c', b'continue', False, b'continue interrupted pick'), (b'a', b'abort', False, b'abort interrupted pick'), ] + mergetoolopts, - _(b'[OPTION]... [-r] REV')) + _(b'[OPTION]... [-r] REV'), + **compat.helpcategorykwargs('CATEGORY_CHANGE_MANAGEMENT')) def cmdpick(ui, repo, *revs, **opts): """move a commit on the top of working directory parent and updates to it.""" diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/evolve/compat.py --- a/hgext3rd/evolve/compat.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/evolve/compat.py Thu Dec 26 21:23:30 2019 +0100 @@ -17,6 +17,7 @@ obsolete, obsutil, pycompat, + registrar, repair, scmutil, util, @@ -523,6 +524,15 @@ return sorted(operations) +# help category compatibility +# hg <= 4.7 (c303d65d2e34) +def helpcategorykwargs(categoryname): + """Backwards-compatible specification of the helpategory argument.""" + category = getattr(registrar.command, categoryname, None) + if not category: + return {} + return {'helpcategory': category} + # nodemap.get and index.[has_node|rev|get_rev] # hg <= 5.3 (02802fa87b74) def getgetrev(cl): diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/evolve/evolvecmd.py --- a/hgext3rd/evolve/evolvecmd.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/evolve/evolvecmd.py Thu Dec 26 21:23:30 2019 +0100 @@ -16,7 +16,6 @@ cmdutil, commands, context, - copies, error, encoding, hg, @@ -62,7 +61,7 @@ returns a tuple (bool, newnode) where, bool: a boolean value indicating whether the instability was solved newnode: if bool is True, then the newnode of the resultant commit - formed. newnode can be node, when resolution led to no new + formed. newnode can be None, when resolution led to no new commit. If bool is False, this is ".". """ tr = repo.currenttransaction() @@ -125,11 +124,11 @@ obs = pctx newer = obsutil.successorssets(repo, obs.node()) # search of a parent which is not killed, but also isn't the orig - while not newer or newer == [()] or newer[0][0] == orig.node(): + while not newer or newer[0][0] == orig.node(): ui.debug(b"stabilize target %s is plain dead," b" trying to stabilize on its parent\n" % obs) - obs = obs.parents()[0] + obs = obs.p1() newer = obsutil.successorssets(repo, obs.node()) if len(newer) > 1: msg = _(b"skipping %s: divergent rewriting. can't choose " @@ -179,8 +178,8 @@ if progresscb: progresscb() with state.saver(evolvestate, {b'current': orig.node()}): - newid = relocate(repo, orig, target, evolvestate, pctx, - keepbranch, b'orphan') + newid = _relocate(repo, orig, target, evolvestate, pctx, + keepbranch, b'orphan') return (True, newid) def _solvephasedivergence(ui, repo, bumped, evolvestate, displayer, @@ -238,8 +237,8 @@ _(b'rebasing to destination parent: %s\n') % prec.p1()) with state.saver(evolvestate, {b'current': bumped.hex(), b'precursor': prec.hex()}): - newnode = relocate(repo, bumped, prec.p1(), evolvestate, - category=b'phasedivergent') + newnode = _relocate(repo, bumped, prec.p1(), evolvestate, + category=b'phasedivergent') if newnode is not None: new = repo[newnode] obsolete.createmarkers(repo, [(bumped, (new,))], @@ -299,17 +298,9 @@ repo.dirstate.setparents(newid, nodemod.nullid) return (True, replacementnode) -def _solvedivergent(ui, repo, divergent, evolvestate, displayer, dryrun=False, - confirm=False, progresscb=None): - """tries to solve content-divergence of a changeset - - returns a tuple (bool, newnode) where, - bool: a boolean value indicating whether the instability was solved - newnode: if bool is True, then the newnode of the resultant commit - formed. newnode can be node, when resolution led to no new - commit. If bool is False, this is ".". - """ - repo = repo.unfiltered() +def _prepcontentdivresolution(ui, repo, divergent, other, evolvestate): + """ if relocation required, decide which divergent cset will be relocated + to the other side""" divergent = repo[divergent.rev()] evolvestate[b'divergent'] = divergent.node() evolvestate[b'orig-divergent'] = divergent.node() @@ -319,32 +310,15 @@ # strip that relocated commit. However if `--all` is passed, we need to # reset this value for each content-divergence resolution which we are doing # below. - evolvestate[b'relocated'] = None - evolvestate[b'relocating'] = False + evolvestate[b'relocated-other'] = None + evolvestate[b'relocating-other'] = False + evolvestate[b'relocated-div'] = None + evolvestate[b'relocating-div'] = False + evolvestate[b'relocation-req'] = False # in case or relocation we get a new other node, we need to store the old # other for purposes like `--abort` or `--stop` evolvestate[b'old-other'] = None - base, others = divergentdata(divergent) - - # we don't handle split in content-divergence yet - if len(others) > 1: - othersstr = b"[%s]" % (b','.join([bytes(i) for i in others])) - msg = _(b"skipping %s: %s with a changeset that got split" - b" into multiple ones:\n" - b"|[%s]\n" - b"| This is not handled by automatic evolution yet\n" - b"| You have to fallback to manual handling with commands " - b"such as:\n" - b"| - hg touch -D\n" - b"| - hg prune\n" - b"| \n" - b"| You should contact your local evolution Guru for help.\n" - ) % (divergent, TROUBLES['CONTENTDIVERGENT'], othersstr) - ui.write_err(msg) - return (False, b".") - other = others[0] - evolvestate[b'other-divergent'] = other.node() - evolvestate[b'base'] = base.node() + evolvestate[b'old-divergent'] = None def swapnodes(div, other): div, other = other, div @@ -363,6 +337,7 @@ else: publicdiv = divergent evolvestate[b'public-divergent'] = publicdiv.node() + # we don't handle merge content-divergent changesets yet if len(other.parents()) > 1: msg = _(b"skipping %s: %s changeset can't be " @@ -374,32 +349,32 @@ ui.write_err(hint) return (False, b".") - otherp1 = other.p1().rev() - divp1 = divergent.p1().rev() + otherp1 = succsotherp1 = other.p1().rev() + divp1 = succsdivp1 = divergent.p1().rev() # finding single successors of otherp1 and divp1 try: - otherp1 = utility._singlesuccessor(repo, other.p1()) + succsotherp1 = utility._singlesuccessor(repo, other.p1()) except utility.MultipleSuccessorsError: pass try: - divp1 = utility._singlesuccessor(repo, divergent.p1()) + succsdivp1 = utility._singlesuccessor(repo, divergent.p1()) except utility.MultipleSuccessorsError: pass # the changeset on which resolution changeset will be based on - resolutionparent = repo[divp1].node() + resolutionparent = repo[succsdivp1].node() # the nullrev has to be handled specially because -1 is overloaded to both # mean nullrev (this meaning is used for the result of changectx.rev(), as # called above) and the tipmost revision (this meaning is used for the %d # format specifier, as used below) - if nodemod.nullrev in (otherp1, divp1): - # nullrev is the only possible ancestor if otherp1 or divp1 is nullrev + if nodemod.nullrev in (succsotherp1, succsdivp1): + # nullrev is the only possible ancestor if succsotherp1 or succsdivp1 is nullrev gca = [nodemod.nullrev] else: - gca = repo.revs(b"ancestor(%d, %d)" % (otherp1, divp1)) + gca = repo.revs(b"ancestor(%d, %d)" % (succsotherp1, succsdivp1)) # divonly: non-obsolete csets which are topological ancestor of "divergent" # but not "other" divonly = repo.revs(b"only(%d, %d) - obsolete()" % (divergent.rev(), @@ -427,32 +402,31 @@ # for 2) we will relocate one which is behind to the parent of ahead one and # then solve the content-divergence the way we solve 1) # for 3) and 4), we still have to decide - if otherp1 in gca and divp1 in gca: - if otherp1 == other.p1().rev() and divp1 == divergent.p1().rev(): - # both are on the same parents + if otherp1 == divp1: + # both are on the same parents + pass + elif succsotherp1 in gca and succsdivp1 in gca: + # both are not on the same parent but have same parents's succs. + if otheronly and divonly: + # case: we have visible csets on both side diverging from + # tca of "divergent" and "other". We still need to decide what + # to do in this case pass + if otheronly: + relocatereq = True + if not haspubdiv: + # can't swap when public divergence, as public can't move + divergent, other = swapnodes(divergent, other) + resolutionparent = repo[succsotherp1].node() + elif divonly: + relocatereq = True else: - # both are not on the same parent but have same parents's succs. - if otheronly and divonly: - # case: we have visible csets on both side diverging from - # tca of "divergent" and "other". We still need to decide what - # to do in this case - pass - if otheronly: - relocatereq = True - if not haspubdiv: - # can't swap when public divergence, as public can't move - divergent, other = swapnodes(divergent, other) - resolutionparent = repo[otherp1].node() - elif divonly: - relocatereq = True - else: - # no extra cset on either side; so not considering relocation - pass - elif otherp1 in gca and divp1 not in gca: + # no extra cset on either side; so not considering relocation + pass + elif succsotherp1 in gca and succsdivp1 not in gca: relocatereq = True pass - elif divp1 in gca and otherp1 not in gca: + elif succsdivp1 in gca and succsotherp1 not in gca: relocatereq = True # When public branch is behind to the mutable branch, for now we @@ -481,6 +455,52 @@ ui.write_err(hint) return (False, b".") + return (True, divergent, other, resolutionparent, relocatereq) + +def _solvedivergent(ui, repo, divergent, evolvestate, displayer, dryrun=False, + confirm=False, progresscb=None): + """tries to solve content-divergence of a changeset + + returns a tuple (bool, newnode) where, + bool: a boolean value indicating whether the instability was solved + newnode: if bool is True, then the newnode of the resultant commit + formed. newnode can be node, when resolution led to no new + commit. If bool is False, this is ".". + """ + repo = repo.unfiltered() + base, others = divergentdata(divergent) + + # we don't handle split in content-divergence yet + if len(others) > 1: + othersstr = b"[%s]" % (b','.join([bytes(i) for i in others])) + msg = _(b"skipping %s: %s with a changeset that got split" + b" into multiple ones:\n" + b"|[%s]\n" + b"| This is not handled by automatic evolution yet\n" + b"| You have to fallback to manual handling with commands " + b"such as:\n" + b"| - hg touch -D\n" + b"| - hg prune\n" + b"| \n" + b"| You should contact your local evolution Guru for help.\n" + ) % (divergent, TROUBLES['CONTENTDIVERGENT'], othersstr) + ui.write_err(msg) + return (False, b".") + other = others[0] + evolvestate[b'other-divergent'] = other.node() + evolvestate[b'base'] = base.node() + + # setup everything before merging two content-divergent csets + datatoproceed = _prepcontentdivresolution(ui, repo, divergent, other, + evolvestate) + if not datatoproceed[0]: + return (False, b".") + divergent, other, resolutionparent, relocatereq = datatoproceed[1:] + + if relocatereq: + evolvestate['relocation-req'] = True + evolvestate[b'resolutionparent'] = resolutionparent + if not ui.quiet or confirm: ui.write(_(b'merge:'), label=b'evolve.operation') displayer.show(divergent) @@ -501,19 +521,26 @@ % divergent)) return (False, b".") + if relocatereq: + evolvestate[b'relocation-req'] = True + evolvestate[b'resolutionparent'] = resolutionparent try: succsdivp1 = utility._singlesuccessor(repo, divergent.p1()) except utility.MultipleSuccessorsError: - msg = _(b"ambiguous orphan resolution parent for %b") + msg = _(b"ambiguous orphan resolution parent for %s") raise error.Abort(msg % divergent.hex()[:12]) # relocate divergent cset to its obsolete parent's successsor if succsdivp1 != divergent.p1().rev(): + evolvestate[b'relocating-div'] = True ui.status(_(b'rebasing "divergent" content-divergent changeset %s on' b' %s\n' % (divergent, repo[succsdivp1]))) with state.saver(evolvestate, {b'current': divergent.node()}): - newdivergent = relocate(repo, divergent, repo[succsdivp1], - evolvestate, keepbranch=True) + newdivergent = _relocate(repo, divergent, repo[succsdivp1], + evolvestate, keepbranch=True) + evolvestate[b'old-divergent'] = divergent.node() divergent = repo[newdivergent] + evolvestate[b'relocating-div'] = False + evolvestate[b'relocated-div'] = divergent.node() evolvestate[b'temprevs'].append(divergent.node()) evolvestate[b'divergent'] = divergent.node() @@ -521,22 +548,21 @@ if relocatereq and other == divergent.p1(): relocatereq = False - evolvestate[b'resolutionparent'] = resolutionparent # relocate the other divergent if required if relocatereq: # relocating will help us understand during the time of conflicts that # whether conflicts occur at reloacting or they occured at merging # content divergent changesets - evolvestate[b'relocating'] = True + evolvestate[b'relocating-other'] = True ui.status(_(b'rebasing "other" content-divergent changeset %s on' b' %s\n' % (other, divergent.p1()))) with state.saver(evolvestate, {b'current': other.node()}): - newother = relocate(repo, other, divergent.p1(), evolvestate, - keepbranch=True) + newother = _relocate(repo, other, divergent.p1(), evolvestate, + keepbranch=True) evolvestate[b'old-other'] = other.node() other = repo[newother] - evolvestate[b'relocating'] = False - evolvestate[b'relocated'] = other.node() + evolvestate[b'relocating-other'] = False + evolvestate[b'relocated-other'] = other.node() evolvestate[b'temprevs'].append(other.node()) evolvestate[b'other-divergent'] = other.node() @@ -544,9 +570,11 @@ evolvestate) res, newnode = _completecontentdivergent(ui, repo, progresscb, divergent, other, base, evolvestate) + haspubdiv = not (divergent.mutable() and other.mutable()) if not haspubdiv: return (res, newnode) else: + publicdiv = repo[evolvestate[b'public-divergent']] # we have content-divergence with a public cset: # after performing content divergence resolution steps, possbile cases: # 1) merging results in a new node: @@ -606,7 +634,6 @@ # resume resolution if progresscb: progresscb() - emtpycommitallowed = repo.ui.backupconfig(b'ui', b'allowemptycommit') tr = repo.currenttransaction() assert tr is not None # whether to store the obsmarker in the evolvestate @@ -634,68 +661,64 @@ obsolete.createmarkers(repo, [(otherdiv, (publicdiv,))], operation=b'evolve') return (True, publicnode) - try: - with repo.dirstate.parentchange(): - repo.dirstate.setparents(resparent, nodemod.nullid) - - dirstatedance(repo, divergent, resparent, None) - # merge the branches - mergebranches(repo, divergent, other, base) - # merge the commit messages - desc = mergecommitmessages(ui, base.description(), - divergent.description(), - other.description()) - user = utility.mergeusers(ui, base, divergent, other) + with repo.dirstate.parentchange(): + repo.dirstate.setparents(resparent, nodemod.nullid) + + dirstatedance(repo, divergent, resparent, None) - # new node if any formed as the replacement - newnode = None + # merge the branches + mergebranches(repo, divergent, other, base) + # merge the commit messages + desc = mergecommitmessages(ui, base.description(), + divergent.description(), + other.description()) + user = utility.mergeusers(ui, base, divergent, other) - mergehook(repo, base, divergent, other) + mergehook(repo, base, divergent, other) - date = divergent.date() - if other.date() != divergent.date(): - basedate = base.date() - if other.date() == basedate: - date = divergent.date() - elif divergent.date() == basedate: - date = other.date() - else: - date = max(divergent.date(), other.date()) + date = divergent.date() + if other.date() != divergent.date(): + basedate = base.date() + if other.date() == basedate: + date = divergent.date() + elif divergent.date() == basedate: + date = other.date() + else: + date = max(divergent.date(), other.date()) - newnode = repo.commit(text=desc, user=user, date=date) - if newnode == divergent.node() or newnode is None: - # no changes - new = divergent - storemarker = True - repo.ui.status(_(b"nothing changed\n")) - hg.updaterepo(repo, divergent.rev(), False) + # new node if any formed as the replacement + newnode = repo.commit(text=desc, user=user, date=date) + if newnode == divergent.node() or newnode is None: + # no changes + new = divergent + storemarker = True + repo.ui.status(_(b"nothing changed\n")) + hg.updaterepo(repo, divergent.rev(), False) + else: + new = repo[newnode] + newnode = new.node() + hg.updaterepo(repo, new.rev(), False) + if haspubdiv and publicdiv == divergent: + bypassphase(repo, (divergent, new), operation=b'evolve') else: - new = repo[newnode] - newnode = new.node() - hg.updaterepo(repo, new.rev(), False) - if haspubdiv and publicdiv == divergent: - bypassphase(repo, (divergent, new), operation=b'evolve') - else: - obsolete.createmarkers(repo, [(divergent, (new,))], - operation=b'evolve') + obsolete.createmarkers(repo, [(divergent, (new,))], + operation=b'evolve') - # creating markers and moving phases post-resolution - if haspubdiv and publicdiv == other: - bypassphase(repo, (other, new), operation=b'evolve') - else: - obsolete.createmarkers(repo, [(other, (new,))], operation=b'evolve') - if storemarker: - # storing the marker in the evolvestate - # we just store the precursors and successor pair for now, we might - # want to store more data and serialize obsmarker in a better way in - # future - evolvestate[b'obsmarkers'].append((other.node(), new.node())) + # creating markers and moving phases post-resolution + if haspubdiv and publicdiv == other: + bypassphase(repo, (other, new), operation=b'evolve') + else: + obsolete.createmarkers(repo, [(other, (new,))], operation=b'evolve') + if storemarker: + # storing the marker in the evolvestate + # we just store the precursors and successor pair for now, we might + # want to store more data and serialize obsmarker in a better way in + # future + evolvestate[b'obsmarkers'].append((other.node(), new.node())) - phases.retractboundary(repo, tr, other.phase(), [new.node()]) - return (True, newnode) - finally: - repo.ui.restoreconfig(emtpycommitallowed) + phases.retractboundary(repo, tr, other.phase(), [new.node()]) + return (True, newnode) def warnmetadataloss(repo, local, other): """warn the user for the metadata being lost while resolving @@ -953,8 +976,8 @@ ordering.extend(sorted(dependencies)) return ordering -def relocate(repo, orig, dest, evolvestate, pctx=None, keepbranch=False, - category=None): +def _relocate(repo, orig, dest, evolvestate, pctx=None, keepbranch=False, + category=None): """rewrites the orig rev on dest rev returns the node of new commit which is formed @@ -1008,10 +1031,6 @@ with repo.dirstate.parentchange(): repo.setparents(dest.node(), orig.node()) repo.dirstate.write(tr) - # fix up dirstate for copies and renames - copies.duplicatecopies(repo, repo[None], dest.rev(), - orig.p1().rev()) - dirstatedance(repo, dest, orig.node(), None) hint = _(b"see 'hg help evolve.interrupted'") raise error.InterventionRequired(_(b"unresolved merge conflicts"), hint=hint) @@ -1027,16 +1046,14 @@ del extra[b'branch'] extra[b'rebase_source'] = orig.hex() - backup = repo.ui.backupconfig(b'phases', b'new-commit') - try: - targetphase = max(orig.phase(), phases.draft) - repo.ui.setconfig(b'phases', b'new-commit', targetphase, b'evolve') + targetphase = max(orig.phase(), phases.draft) + configoverride = repo.ui.configoverride({ + (b'phases', b'new-commit'): targetphase + }, source=b'evolve') + with configoverride: # Commit might fail if unresolved files exist - nodenew = repo.commit(text=commitmsg, user=orig.user(), - date=orig.date(), extra=extra) - finally: - repo.ui.restoreconfig(backup) - return nodenew + return repo.commit(text=commitmsg, user=orig.user(), + date=orig.date(), extra=extra) def _finalizerelocate(repo, orig, dest, nodenew, tr, category, evolvestate): destbookmarks = repo.nodebookmarks(dest.node()) @@ -1045,7 +1062,7 @@ bmchanges = [] if nodenew is not None: - obsolete.createmarkers(repo, [(repo[nodesrc], (repo[nodenew],))], + obsolete.createmarkers(repo, [(orig, (repo[nodenew],))], operation=b'evolve') for book in oldbookmarks: bmchanges.append((book, nodenew)) @@ -1054,7 +1071,7 @@ if category == b'orphan': repo.ui.status(_(b"evolution of %d:%s created no changes " b"to commit\n") % (orig.rev(), orig)) - obsolete.createmarkers(repo, [(repo[nodesrc], ())], operation=b'evolve') + obsolete.createmarkers(repo, [(orig, ())], operation=b'evolve') # Behave like rebase, move bookmarks to dest for book in oldbookmarks: evolvestate[b'bookmarkchanges'].append((book, nodesrc)) @@ -1539,7 +1556,8 @@ b' in the repo')), ] + mergetoolopts, _(b'[OPTIONS]...'), - helpbasic=True + helpbasic=True, + **compat.helpcategorykwargs('CATEGORY_CHANGE_MANAGEMENT') ) def evolve(ui, repo, **opts): """solve troubled changesets in your repository @@ -1842,15 +1860,29 @@ """logic for handling of `hg evolve --stop`""" updated = False pctx = None + divrelocated = evolvestate.get(b'relocated-div') + otherrelocated = evolvestate.get(b'relocated-other') + strips = [] + if divrelocated: + strips.append(divrelocated) + if otherrelocated: + strips.append(otherrelocated) if (evolvestate[b'command'] == b'evolve' and evolvestate[b'category'] == b'contentdivergent' - and evolvestate[b'relocated']): + and strips): oldother = evolvestate[b'old-other'] - if oldother: + olddiv = evolvestate[b'old-divergent'] + if olddiv: + with repo.wlock(), repo.lock(): + repo = repo.unfiltered() + hg.updaterepo(repo, olddiv, True) + repair.strip(ui, repo, strips, False) + updated = True + pctx = repo[olddiv] + elif oldother: with repo.wlock(), repo.lock(): repo = repo.unfiltered() hg.updaterepo(repo, oldother, True) - strips = [evolvestate[b'relocated']] repair.strip(ui, repo, strips, False) updated = True pctx = repo[oldother] @@ -2024,13 +2056,47 @@ divergent = evolvestate[b'divergent'] base = evolvestate[b'base'] repo = repo.unfiltered() - if evolvestate[b'relocating']: + if evolvestate[b'relocating-div']: + newdiv = _completerelocation(ui, repo, evolvestate) + current = repo[evolvestate[b'current']] + obsolete.createmarkers(repo, [(current, (repo[newdiv],))], + operation=b'evolve') + evolvestate[b'old-divergent'] = repo[divergent].node() + evolvestate[b'relocating-div'] = False + evolvestate[b'relocated-div'] = newdiv + evolvestate[b'temprevs'].append(newdiv) + evolvestate[b'divergent'] = newdiv + + relocatereq = evolvestate[b'relocation-req'] + if relocatereq: + divergent = repo[evolvestate[b'divergent']] + other = repo[evolvestate[b'other-divergent']] + evolvestate[b'relocating-other'] = True + ui.status(_(b'rebasing "other" content-divergent changeset %s on' + b' %s\n' % (other, divergent.p1()))) + with state.saver(evolvestate, {b'current': other.node()}): + newother = _relocate(repo, other, divergent.p1(), + evolvestate, keepbranch=True) + evolvestate[b'old-other'] = other.node() + other = repo[newother] + evolvestate[b'relocating-other'] = False + evolvestate[b'relocated-other'] = other.node() + evolvestate[b'temprevs'].append(other.node()) + evolvestate[b'other-divergent'] = other.node() + # continue the resolution by merging the content-divergence + _mergecontentdivergents(repo, progresscb, + divergent, + repo[newother], + repo[base], + evolvestate) + + if evolvestate[b'relocating-other']: newother = _completerelocation(ui, repo, evolvestate) current = repo[evolvestate[b'current']] obsolete.createmarkers(repo, [(current, (repo[newother],))], operation=b'evolve') - evolvestate[b'relocating'] = False - evolvestate[b'relocated'] = newother + evolvestate[b'relocating-other'] = False + evolvestate[b'relocated-other'] = newother evolvestate[b'temprevs'].append(newother) evolvestate[b'other-divergent'] = newother # continue the resolution by merging the content-divergence @@ -2040,18 +2106,19 @@ repo[base], evolvestate) + divergent = evolvestate[b'divergent'] other = evolvestate[b'other-divergent'] - ret = _completecontentdivergent(ui, repo, progresscb, - repo[divergent], - repo[other], - repo[base], - evolvestate) + res, newnode = _completecontentdivergent(ui, repo, progresscb, + repo[divergent], + repo[other], + repo[base], + evolvestate) origdivergent = evolvestate[b'orig-divergent'] - evolvestate[b'replacements'][origdivergent] = ret[1] + evolvestate[b'replacements'][origdivergent] = newnode + ret = (res, newnode) # logic to continue the public content-divergent publicnode = evolvestate.get(b'public-divergent') if publicnode: - res, newnode = ret if not res: # no need to proceed for phase divergence resolution step pass @@ -2136,7 +2203,7 @@ ctxparents = orig.parents() if len(ctxparents) == 2: - currentp1 = repo.dirstate.parents()[0] + currentp1 = repo.dirstate.p1() p1obs = ctxparents[0].obsolete() p2obs = ctxparents[1].obsolete() # asumming that the parent of current wdir is successor of one @@ -2166,7 +2233,7 @@ pass else: with repo.dirstate.parentchange(): - repo.dirstate.setparents(repo.dirstate.parents()[0], nodemod.nullid) + repo.dirstate.setparents(repo.dirstate.p1(), nodemod.nullid) with repo.ui.configoverride(overrides, b'evolve-continue'): node = repo.commit(text=message, user=user, diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/evolve/exthelper.py --- a/hgext3rd/evolve/exthelper.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/evolve/exthelper.py Thu Dec 26 21:23:30 2019 +0100 @@ -50,7 +50,7 @@ @eh.command('mynewcommand', [('r', 'rev', [], _('operate on these revisions'))], _('-r REV...'), - helpcategory=command.CATEGORY_XXX) + **compat.helpcategorykwargs('CATEGORY_XXX')) def newcommand(ui, repo, *revs, **opts): # implementation goes here diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/evolve/genericcaches.py --- a/hgext3rd/evolve/genericcaches.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/evolve/genericcaches.py Thu Dec 26 21:23:30 2019 +0100 @@ -14,7 +14,7 @@ util, ) -class incrementalcachebase(object): +class incrementalcachebase(object): # pytype: disable=ignored-metaclass """base class for incremental cache from append only source There are multiple append only data source we might want to cache @@ -133,7 +133,7 @@ """read the cachekey from bytes""" return self._cachekeystruct.unpack(data) -class changelogsourcebase(incrementalcachebase): +class changelogsourcebase(incrementalcachebase): # pytype: disable=ignored-metaclass """an abstract class for cache sourcing data from the changelog For this purpose it use a cache key covering changelog content. diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/evolve/metadata.py --- a/hgext3rd/evolve/metadata.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/evolve/metadata.py Thu Dec 26 21:23:30 2019 +0100 @@ -5,7 +5,7 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -__version__ = b'9.2.2.dev' +__version__ = b'9.3.0.dev' testedwith = b'4.5.2 4.6.2 4.7 4.8 4.9 5.0 5.1' minimumhgversion = b'4.5' buglink = b'https://bz.mercurial-scm.org/' diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/evolve/obsexchange.py --- a/hgext3rd/evolve/obsexchange.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/evolve/obsexchange.py Thu Dec 26 21:23:30 2019 +0100 @@ -7,17 +7,11 @@ from __future__ import absolute_import -try: - from StringIO import StringIO -except ImportError: - from io import StringIO - from mercurial import ( bundle2, error, exchange, extensions, - lock as lockmod, node, obsolete, pushkey, @@ -35,7 +29,6 @@ eh = exthelper.exthelper() eh.merge(obsdiscovery.eh) obsexcmsg = utility.obsexcmsg -obsexcprg = utility.obsexcprg eh.configitem(b'experimental', b'verbose-obsolescence-exchange', False) @@ -156,82 +149,6 @@ return _obscommon_capabilities(oldcap, repo, proto) wireprotov1server.commands[b'capabilities'] = (newcap, args) -def _pushobsmarkers(repo, data): - tr = lock = None - try: - lock = repo.lock() - tr = repo.transaction(b'pushkey: obsolete markers') - new = repo.obsstore.mergemarkers(tr, data) - if new is not None: - obsexcmsg(repo.ui, b"%i obsolescence markers added\n" % new, True) - tr.close() - finally: - lockmod.release(tr, lock) - repo.hook(b'evolve_pushobsmarkers') - -def srv_pushobsmarkers(repo, proto): - """wireprotocol command""" - fp = StringIO() - proto.redirect() - proto.getfile(fp) - data = fp.getvalue() - fp.close() - _pushobsmarkers(repo, data) - try: - from mercurial import wireprototypes - wireprototypes.pushres # force demandimport - except (ImportError, AttributeError): - from mercurial import wireproto as wireprototypes - return wireprototypes.pushres(0) - -def _getobsmarkersstream(repo, heads=None, common=None): - """Get a binary stream for all markers relevant to `:: - ::` - """ - revset = b'' - args = [] - repo = repo.unfiltered() - if heads is None: - revset = b'all()' - elif heads: - revset += b"(::%ln)" - args.append(heads) - else: - assert False, b'pulling no heads?' - if common: - revset += b' - (::%ln)' - args.append(common) - nodes = [c.node() for c in repo.set(revset, *args)] - markers = repo.obsstore.relevantmarkers(nodes) - obsdata = StringIO() - for chunk in obsolete.encodemarkers(markers, True): - obsdata.write(chunk) - obsdata.seek(0) - return obsdata - -def srv_pullobsmarkers(repo, proto, others): - """serves a binary stream of markers. - - Serves relevant to changeset between heads and common. The stream is prefix - by a -string- representation of an integer. This integer is the size of the - stream.""" - try: - from mercurial import wireprototypes, wireprotov1server - wireprototypes.pushres # force demandimport - except (ImportError, AttributeError): - from mercurial import wireproto as wireprototypes - wireprotov1server = wireprototypes - opts = wireprotov1server.options(b'', [b'heads', b'common'], others) - for k, v in opts.items(): - if k in (b'heads', b'common'): - opts[k] = wireprototypes.decodelist(v) - obsdata = _getobsmarkersstream(repo, **opts) - finaldata = StringIO() - obsdata = obsdata.getvalue() - finaldata.write(b'%20i' % len(obsdata)) - finaldata.write(obsdata) - finaldata.seek(0) - return wireprototypes.streamres(reader=finaldata, v1compressible=True) - abortmsg = b"won't exchange obsmarkers through pushkey" hint = b"upgrade your client or server to use the bundle2 protocol" diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/evolve/obshistory.py --- a/hgext3rd/evolve/obshistory.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/evolve/obshistory.py Thu Dec 26 21:23:30 2019 +0100 @@ -50,7 +50,8 @@ (b'p', b'patch', False, _(b'show the patch between two obs versions')), (b'f', b'filternonlocal', False, _(b'filter out non local commits')), ] + commands.formatteropts, - _(b'hg olog [OPTION]... [[-r] REV]...')) + _(b'hg olog [OPTION]... [[-r] REV]...'), + **compat.helpcategorykwargs('CATEGORY_CHANGE_NAVIGATION')) def cmdobshistory(ui, repo, *revs, **opts): """show the obsolescence history of the specified revisions @@ -85,6 +86,13 @@ revs = [b'.'] revs = scmutil.revrange(repo, revs) + # Use the default template unless the user provided one, but not if + # -f was given, because that doesn't work with templates yet. Note + # that --no-graph doesn't support -f (it ignores it), so we also + # don't use templating with --no-graph. + if not opts['template'] and not (opts['filternonlocal'] and opts['graph']): + opts['template'] = DEFAULT_TEMPLATE + if opts['graph']: return _debugobshistorygraph(ui, repo, revs, opts) @@ -135,6 +143,35 @@ return values +TEMPLATE_MISSING_NODE = b"""{label("evolve.node evolve.missing_change_ctx", node|short)}""" +TEMPLATE_PRESENT_NODE = b"""{label("evolve.node", node|short)} {label("evolve.rev", "({rev})")} {label("evolve.short_description", desc|firstline)}""" +TEMPLATE_FIRST_LINE = b"""{if(rev, "%(presentnode)s", "%(missingnode)s")}""" % { + b"presentnode": TEMPLATE_PRESENT_NODE, + b"missingnode": TEMPLATE_MISSING_NODE +} +TEMPLATE_VERB = b"""{label("evolve.verb", verb)}""" +TEMPLATE_SUCCNODES = b"""{label("evolve.node", join(succnodes % "{succnode|short}", ", "))}""" +TEMPLATE_REWRITE = b"""{if(succnodes, "%(verb)s{if(effects, "({join(effects, ", ")})")} as %(succnodes)s", "pruned")}""" % { + b"verb": TEMPLATE_VERB, + b"succnodes": TEMPLATE_SUCCNODES +} +TEMPLATE_OPERATION = b"""{if(operation, "using {label("evolve.operation", operation)}")}""" +TEMPLATE_USER = b"""by {label("evolve.user", user)}""" +TEMPLATE_DATE = b"""{label("evolve.date", "({date(date, "%a %b %d %H:%M:%S %Y %1%2")})")}""" +TEMPLATE_NOTE = b"""{if(note, "\n note: {label("evolve.note", note)}")}""" +TEMPLATE_PATCH = b"""{if(patch, "{patch}")}{if(nopatchreason, "\n(No patch available, {nopatchreason})")}""" +DEFAULT_TEMPLATE = (b"""%(firstline)s +{markers %% " {separate(" ", "%(rewrite)s", "%(operation)s", "%(user)s", "%(date)s")}%(note)s{indent(descdiff, " ")}{indent("%(patch)s", " ")}\n"} +""") % { + b"firstline": TEMPLATE_FIRST_LINE, + b"rewrite": TEMPLATE_REWRITE, + b"operation": TEMPLATE_OPERATION, + b"user": TEMPLATE_USER, + b"date": TEMPLATE_DATE, + b"note": TEMPLATE_NOTE, + b"patch": TEMPLATE_PATCH, +} + class obsmarker_printer(compat.changesetprinter): """show (available) information about a node @@ -178,7 +215,7 @@ succs = sorted(succs) for successor in succs: - _debugobshistorydisplaymarker(markerfm, successor, + _debugobshistorydisplaymarker(self.ui, markerfm, successor, ctx.node(), self.repo, self._includediff) @@ -190,11 +227,11 @@ if not markers: continue successors = succset[b"successors"] - _debugobshistorydisplaysuccsandmarkers(markerfm, successors, markers, ctx.node(), self.repo, self._includediff) + _debugobshistorydisplaysuccsandmarkers(self.ui, markerfm, successors, markers, ctx.node(), self.repo, self._includediff) markerfm.end() - markerfm.plain(b'\n') + fm.plain(b'\n') fm.end() self.hunk[ctx.node()] = self.ui.popbuffer() @@ -454,8 +491,9 @@ markerfm = fm.nested(b"markers") for successor in sorted(succs): includediff = opts and opts.get("patch") - _debugobshistorydisplaymarker(markerfm, successor, ctxnode, unfi, includediff) + _debugobshistorydisplaymarker(ui, markerfm, successor, ctxnode, unfi, includediff) markerfm.end() + fm.plain(b'\n') precs = precursors.get(ctxnode, ()) for p in sorted(precs): @@ -477,12 +515,12 @@ shortdescription = shortdescription.splitlines()[0] fm.startitem() - fm.write(b'node', b'%s', bytes(ctx), - label=b"evolve.node") + fm.context(ctx=ctx) + fm.data(node=ctx.hex()) + fm.plain(b'%s' % bytes(ctx), label=b"evolve.node") fm.plain(b' ') - fm.write(b'rev', b'(%d)', ctx.rev(), - label=b"evolve.rev") + fm.plain(b'(%d)' % ctx.rev(), label=b"evolve.rev") fm.plain(b' ') fm.write(b'shortdescription', b'%s', shortdescription, @@ -490,19 +528,18 @@ fm.plain(b'\n') def _debugobshistorydisplaymissingctx(fm, nodewithoutctx): - hexnode = nodemod.short(nodewithoutctx) fm.startitem() - fm.write(b'node', b'%s', hexnode, + fm.data(node=nodemod.hex(nodewithoutctx)) + fm.plain(nodemod.short(nodewithoutctx), label=b"evolve.node evolve.missing_change_ctx") fm.plain(b'\n') -def _debugobshistorydisplaymarker(fm, marker, node, repo, includediff=False): +def _debugobshistorydisplaymarker(ui, fm, marker, node, repo, includediff=False): succnodes = marker[1] date = marker[4] metadata = dict(marker[3]) fm.startitem() - fm.plain(b' ') # Detect pruned revisions if len(succnodes) == 0: @@ -510,8 +547,7 @@ else: verb = b'rewritten' - fm.write(b'verb', b'%s', verb, - label=b"evolve.verb") + fm.data(verb=verb) effectflag = metadata.get(b'ef1') if effectflag is not None: @@ -520,54 +556,44 @@ except ValueError: effectflag = None if effectflag: - effect = [] + effects = [] # XXX should be a dict if effectflag & DESCCHANGED: - effect.append(b'description') + effects.append(b'description') if effectflag & METACHANGED: - effect.append(b'meta') + effects.append(b'meta') if effectflag & USERCHANGED: - effect.append(b'user') + effects.append(b'user') if effectflag & DATECHANGED: - effect.append(b'date') + effects.append(b'date') if effectflag & BRANCHCHANGED: - effect.append(b'branch') + effects.append(b'branch') if effectflag & PARENTCHANGED: - effect.append(b'parent') + effects.append(b'parent') if effectflag & DIFFCHANGED: - effect.append(b'content') + effects.append(b'content') - if effect: - fmteffect = fm.formatlist(effect, b'effect', sep=b', ') - fm.write(b'effect', b'(%s)', fmteffect) + if effects: + fmteffect = fm.formatlist(effects, b'effect') + fm.write(b'effects', b'(%s)', fmteffect) if len(succnodes) > 0: - fm.plain(b' as ') - - shortsnodes = (nodemod.short(succnode) for succnode in sorted(succnodes)) - nodes = fm.formatlist(shortsnodes, b'succnodes', sep=b', ') - fm.write(b'succnodes', b'%s', nodes, - label=b"evolve.node") + hexnodes = (nodemod.hex(succnode) for succnode in sorted(succnodes)) + nodes = fm.formatlist(hexnodes, b'succnode') + fm.write(b'succnodes', b'%s', nodes) operation = metadata.get(b'operation') if operation: - fm.plain(b' using ') - fm.write(b'operation', b'%s', operation, label=b"evolve.operation") - - fm.plain(b' by ') + fm.data(operation=operation) - fm.write(b'user', b'%s', metadata[b'user'], - label=b"evolve.user") - fm.plain(b' ') + fm.data(user=metadata[b'user']) - fm.write(b'date', b'(%s)', fm.formatdate(date), - label=b"evolve.date") + fm.data(date=date) # initial support for showing note if metadata.get(b'note'): - fm.plain(b'\n note: ') - fm.write(b'note', b"%s", metadata[b'note'], label=b"evolve.note") + fm.data(note=metadata[b'note']) # Patch display if includediff is True: @@ -592,15 +618,16 @@ def tolist(text): return [text] - fm.plain(b"\n") + ui.pushbuffer(labeled=True) + ui.write(b"\n") for chunk, label in patch.difflabel(tolist, descriptionpatch): chunk = chunk.strip(b'\t') - if chunk and chunk != b'\n': - fm.plain(b' ') - fm.write(b'desc-diff', b'%s', chunk, label=label) + ui.write(chunk, label=label) + fm.write(b'descdiff', b'%s', ui.popbuffer()) # Content patch + ui.pushbuffer(labeled=True) diffopts = patch.diffallopts(repo.ui, {}) matchfn = scmutil.matchall(repo) firstline = True @@ -608,23 +635,18 @@ for chunk, label in patch.diffui(repo, node, succ, matchfn, opts=diffopts): if firstline: - fm.plain(b'\n') + ui.write(b'\n') firstline = False if linestart: - fm.plain(b' ') linestart = False if chunk == b'\n': linestart = True - fm.write(b'patch', b'%s', chunk, label=label) + ui.write(chunk, label=label) + fm.data(patch=ui.popbuffer()) else: - nopatch = b" (No patch available, %s)" % _patchavailable[1] - fm.plain(b"\n") - # TODO: should be in json too - fm.plain(nopatch) + fm.data(nopatchreason=_patchavailable[1]) - fm.plain(b"\n") - -def _debugobshistorydisplaysuccsandmarkers(fm, succnodes, markers, node, repo, includediff=False): +def _debugobshistorydisplaysuccsandmarkers(ui, fm, succnodes, markers, node, repo, includediff=False): """ This function is a duplication of _debugobshistorydisplaymarker modified to accept multiple markers as input. @@ -648,33 +670,33 @@ effectflag |= int(ef) if effectflag: - effect = [] + effects = [] # XXX should be a dict if effectflag & DESCCHANGED: - effect.append(b'description') + effects.append(b'description') if effectflag & METACHANGED: - effect.append(b'meta') + effects.append(b'meta') if effectflag & USERCHANGED: - effect.append(b'user') + effects.append(b'user') if effectflag & DATECHANGED: - effect.append(b'date') + effects.append(b'date') if effectflag & BRANCHCHANGED: - effect.append(b'branch') + effects.append(b'branch') if effectflag & PARENTCHANGED: - effect.append(b'parent') + effects.append(b'parent') if effectflag & DIFFCHANGED: - effect.append(b'content') + effects.append(b'content') - if effect: - fmteffect = fm.formatlist(effect, b'effect', sep=b', ') - fm.write(b'effect', b'(%s)', fmteffect) + if effects: + fmteffect = fm.formatlist(effects, b'effect', sep=b', ') + fm.write(b'effects', b'(%s)', fmteffect) if len(succnodes) > 0: fm.plain(b' as ') shortsnodes = (nodemod.short(succnode) for succnode in sorted(succnodes)) - nodes = fm.formatlist(shortsnodes, b'succnodes', sep=b', ') + nodes = fm.formatlist(shortsnodes, b'succnode', sep=b', ') fm.write(b'succnodes', b'%s', nodes, label=b"evolve.node") @@ -732,15 +754,18 @@ def tolist(text): return [text] - fm.plain(b"\n") + ui.pushbuffer(labeled=True) + ui.write(b"\n") for chunk, label in patch.difflabel(tolist, descriptionpatch): chunk = chunk.strip(b'\t') if chunk and chunk != b'\n': - fm.plain(b' ') - fm.write(b'desc-diff', b'%s', chunk, label=label) + ui.write(b' ') + ui.write(chunk, label=label) + fm.write(b'descdiff', b'%s', ui.popbuffer()) # Content patch + ui.pushbuffer(labeled=True) diffopts = patch.diffallopts(repo.ui, {}) matchfn = scmutil.matchall(repo) firstline = True @@ -748,19 +773,18 @@ for chunk, label in patch.diffui(repo, node, succ, matchfn, opts=diffopts): if firstline: - fm.plain(b'\n') + ui.write(b'\n') firstline = False if linestart: - fm.plain(b' ') + ui.write(b' ') linestart = False if chunk == b'\n': linestart = True - fm.write(b'patch', b'%s', chunk, label=label) + ui.write(chunk, label=label) + fm.write(b'patch', b'%s', ui.popbuffer()) else: - nopatch = b" (No patch available, %s)" % _patchavailable[1] - fm.plain(b"\n") - # TODO: should be in json too - fm.plain(nopatch) + fm.write(b'nopatchreason', b"\n (No patch available, %s)", + _patchavailable[1]) fm.plain(b"\n") diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/evolve/rewind.py --- a/hgext3rd/evolve/rewind.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/evolve/rewind.py Thu Dec 26 21:23:30 2019 +0100 @@ -36,7 +36,8 @@ _(b"do not modify working directory during rewind")), ], _(b'[--as-divergence] [--exact] [--keep] [--to REV]... [--from REV]...'), - helpbasic=True) + helpbasic=True, + **compat.helpcategorykwargs('CATEGORY_CHANGE_MANAGEMENT')) def rewind(ui, repo, **opts): """rewind a stack of changesets to a previous state diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/evolve/utility.py --- a/hgext3rd/evolve/utility.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/evolve/utility.py Thu Dec 26 21:23:30 2019 +0100 @@ -13,10 +13,6 @@ from mercurial.node import nullrev -from . import ( - compat, -) - shorttemplate = b"[{label('evolve.rev', rev)}] {desc|firstline}\n" stacktemplate = b"""[{label('evolve.rev', if(topicidx, "s{topicidx}", rev))}] {desc|firstline}\n""" @@ -27,12 +23,6 @@ if important or verbose: ui.status(message) -def obsexcprg(ui, *args, **kwargs): - topic = b'obsmarkers exchange' - if ui.configbool(b'experimental', b'verbose-obsolescence-exchange'): - topic = b'OBSEXC' - compat.progress(ui, topic, *args, **kwargs) - def filterparents(parents): """filter nullrev parents @@ -126,7 +116,7 @@ ui.debug(b"stabilize target %s is plain dead," b" trying to stabilize on its parent\n" % obs) - obs = obs.parents()[0] + obs = obs.p1() newer = obsutil.successorssets(repo, obs.node()) if len(newer) > 1 or len(newer[0]) > 1: raise MultipleSuccessorsError(newer) diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/topic/__init__.py --- a/hgext3rd/topic/__init__.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/topic/__init__.py Thu Dec 26 21:23:30 2019 +0100 @@ -135,6 +135,7 @@ namespaces, node, obsolete, + obsutil, patch, phases, pycompat, @@ -187,7 +188,7 @@ b'topic.active': b'green', } -__version__ = b'0.17.2.dev' +__version__ = b'0.18.0.dev' testedwith = b'4.5.2 4.6.2 4.7 4.8 4.9 5.0 5.1' minimumhgversion = b'4.5' @@ -384,14 +385,14 @@ return caps def commit(self, *args, **kwargs): - backup = self.ui.backupconfig(b'ui', b'allowemptycommit') - try: - if self.currenttopic != self[b'.'].topic(): - # bypass the core "nothing changed" logic - self.ui.setconfig(b'ui', b'allowemptycommit', True) + configoverride = util.nullcontextmanager() + if self.currenttopic != self[b'.'].topic(): + # bypass the core "nothing changed" logic + configoverride = self.ui.configoverride({ + (b'ui', b'allowemptycommit'): True + }) + with configoverride: return super(topicrepo, self).commit(*args, **kwargs) - finally: - self.ui.restoreconfig(backup) def commitctx(self, ctx, *args, **kwargs): topicfilter = topicmap.topicfilter(self.filtername) @@ -634,7 +635,8 @@ (b'', b'age', False, b'show when you last touched the topics'), (b'', b'current', None, b'display the current topic only'), ] + commands.formatteropts, - _(b'hg topics [OPTION]... [-r REV]... [TOPIC]')) + _(b'hg topics [OPTION]... [-r REV]... [TOPIC]'), + **compat.helpcategorykwargs('CATEGORY_CHANGE_ORGANIZATION')) def topics(ui, repo, topic=None, **opts): """View current topic, set current topic, change topic for a set of revisions, or see all topics. @@ -777,7 +779,8 @@ (b'c', b'children', None, _(b'display data about children outside of the stack')) ] + commands.formatteropts, - _(b'hg stack [TOPIC]')) + _(b'hg stack [TOPIC]'), + **compat.helpcategorykwargs('CATEGORY_CHANGE_NAVIGATION')) def cmdstack(ui, repo, topic=b'', **opts): """list all changesets in a topic and other information @@ -1115,7 +1118,7 @@ user = repo[revs].user() # looking on the markers also to get more information and accurate # last touch time. - obsmarkers = compat.getmarkers(repo, [repo[revs].node()]) + obsmarkers = obsutil.getmarkers(repo, [repo[revs].node()]) for marker in obsmarkers: rt = marker.date() if rt[0] > maxtime[0]: @@ -1258,14 +1261,13 @@ def checkt0(orig, ui, repo, node=None, rev=None, *args, **kwargs): thezeros = set([b't0', b'b0', b's0']) - backup = repo.ui.backupconfig(b'_internal', b'keep-topic') - try: - if node in thezeros or rev in thezeros: - repo.ui.setconfig(b'_internal', b'keep-topic', b'yes', - source=b'topic-extension') + configoverride = util.nullcontextmanager() + if node in thezeros or rev in thezeros: + configoverride = repo.ui.configoverride({ + (b'_internal', b'keep-topic'): b'yes' + }, source=b'topic-extension') + with configoverride: return orig(ui, repo, node=node, rev=rev, *args, **kwargs) - finally: - repo.ui.restoreconfig(backup) def _fixrebase(loaded): if not loaded: diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/topic/compat.py --- a/hgext3rd/topic/compat.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/topic/compat.py Thu Dec 26 21:23:30 2019 +0100 @@ -8,25 +8,11 @@ from __future__ import absolute_import from mercurial import ( - obsolete, pycompat, + registrar, util, ) -getmarkers = None -successorssets = None -try: - from mercurial import obsutil - getmarkers = getattr(obsutil, 'getmarkers', None) - successorssets = getattr(obsutil, 'successorssets', None) -except ImportError: - pass - -if getmarkers is None: - getmarkers = obsolete.getmarkers -if successorssets is None: - successorssets = obsolete.successorssets - if pycompat.ispy3: def branchmapitems(branchmap): return branchmap.items() @@ -36,6 +22,15 @@ return branchmap.iteritems() # py3-transform: on +# help category compatibility +# hg <= 4.7 (c303d65d2e34) +def helpcategorykwargs(categoryname): + """Backwards-compatible specification of the helpategory argument.""" + category = getattr(registrar.command, categoryname, None) + if not category: + return {} + return {'helpcategory': category} + # nodemap.get and index.[has_node|rev|get_rev] # hg <= 5.3 (02802fa87b74) def getgetrev(cl): diff -r 1015a1dbaf7c -r c5efcbbd0dc4 hgext3rd/topic/evolvebits.py --- a/hgext3rd/topic/evolvebits.py Thu Dec 26 12:22:49 2019 +0700 +++ b/hgext3rd/topic/evolvebits.py Thu Dec 26 21:23:30 2019 +0100 @@ -81,7 +81,7 @@ ui.debug(b"stabilize target %s is plain dead," b" trying to stabilize on its parent\n" % obs) - obs = obs.parents()[0] + obs = obs.p1() newer = obsutil.successorssets(repo, obs.node()) if 1 < len(newer): # divergence case diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-content-divergent-meta.t --- a/tests/test-evolve-content-divergent-meta.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-content-divergent-meta.t Thu Dec 26 21:23:30 2019 +0100 @@ -14,6 +14,7 @@ > publish = False > [extensions] > rebase = + > strip = > EOF $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH @@ -157,3 +158,213 @@ user: baruser, foouser $ cd .. + +Test the content-divergence resolution involving date update +------------------------------------------------------------ + + $ hg init divergingdate + $ cd divergingdate + $ unset HGUSER + $ echo "[ui]" >> ./.hg/hgrc + $ echo "username = test" >> ./.hg/hgrc + + $ echo hi > r0 + $ hg ci -qAm 'add r0' + $ echo hi > foo.txt + $ hg ci -qAm 'add foo.txt' + $ hg metaedit -r . -d '0 2' + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + +date: updated on both side to the same value + + $ echo hi > bar.txt + $ hg add -q bar.txt + $ hg amend -q + $ hg metaedit -r 1 -d '0 1' --hidden + 2 new content-divergent changesets + $ hg log -G + * changeset: 4:c17bf400a278 + | tag: tip + | parent: 0:a24ed8ad918c + | user: test + | date: Wed Dec 31 23:59:59 1969 -0000 + | instability: content-divergent + | summary: add foo.txt + | + | @ changeset: 3:a25dd7af6cf6 + |/ parent: 0:a24ed8ad918c + | user: test + | date: Wed Dec 31 23:59:58 1969 -0000 + | instability: content-divergent + | summary: add foo.txt + | + o changeset: 0:a24ed8ad918c + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: add r0 + + $ hg evolve --list --rev . + a25dd7af6cf6: add foo.txt + content-divergent: c17bf400a278 (draft) (precursor cc71ffbc7c00) + + $ hg log --hidden -r cc71ffbc7c00 -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' + 1 cc71ffbc7c00 1970-01-01 00:00 +0000: date-changed using metaedit as 4:c17bf400a278; date-changed using metaedit as 2:0065551bd38f + $ hg log -r 'desc("add foo.txt")' -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' + 3 a25dd7af6cf6 1969-12-31 23:59 -0000: + 4 c17bf400a278 1969-12-31 23:59 -0000: + $ hg evolve --content-divergent + merge:[3] add foo.txt + with: [4] add foo.txt + base: [1] add foo.txt + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at 6c144bb30333 + $ hg log -r 'desc("add foo.txt")' -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' + 5 6c144bb30333 1969-12-31 23:59 -0000: + +date: updated one one side to an older value + + $ hg strip . + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + saved backup bundle to $TESTTMP/divergingdate/.hg/strip-backup/6c144bb30333-72e26b88-backup.hg + 2 new content-divergent changesets + $ hg up tip + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg amend --date "0 3" + $ hg log -G + @ changeset: 5:6189a9adfff0 + | tag: tip + | parent: 0:a24ed8ad918c + | user: test + | date: Wed Dec 31 23:59:57 1969 -0000 + | instability: content-divergent + | summary: add foo.txt + | + | * changeset: 3:a25dd7af6cf6 + |/ parent: 0:a24ed8ad918c + | user: test + | date: Wed Dec 31 23:59:58 1969 -0000 + | instability: content-divergent + | summary: add foo.txt + | + o changeset: 0:a24ed8ad918c + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: add r0 + + $ hg evolve --list -r . + 6189a9adfff0: add foo.txt + content-divergent: a25dd7af6cf6 (draft) (precursor cc71ffbc7c00) + + $ hg log -r cc71ffbc7c00+6189a9adfff0+a25dd7af6cf6 --hidden -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' + 1 cc71ffbc7c00 1970-01-01 00:00 +0000: date-changed using metaedit as 4:c17bf400a278; date-changed using metaedit as 2:0065551bd38f + 5 6189a9adfff0 1969-12-31 23:59 -0000: + 3 a25dd7af6cf6 1969-12-31 23:59 -0000: + $ hg evolve --content-divergent + merge:[3] add foo.txt + with: [5] add foo.txt + base: [1] add foo.txt + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at 806d0024c04d + $ hg log -r . --hidden -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' + 6 806d0024c04d 1969-12-31 23:59 -0000: + +date: updated one side to an newer value + + $ hg strip . + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + saved backup bundle to $TESTTMP/divergingdate/.hg/strip-backup/806d0024c04d-24cb28ad-backup.hg + 2 new content-divergent changesets + $ hg update a25dd7af6cf6 --hidden + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg amend --date "120 0" + $ hg log -G + @ changeset: 6:5199d0bc13d4 + | tag: tip + | parent: 0:a24ed8ad918c + | user: test + | date: Thu Jan 01 00:02:00 1970 +0000 + | instability: content-divergent + | summary: add foo.txt + | + | * changeset: 5:6189a9adfff0 + |/ parent: 0:a24ed8ad918c + | user: test + | date: Wed Dec 31 23:59:57 1969 -0000 + | instability: content-divergent + | summary: add foo.txt + | + o changeset: 0:a24ed8ad918c + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: add r0 + + $ hg evolve --list -r . + 5199d0bc13d4: add foo.txt + content-divergent: 6189a9adfff0 (draft) (precursor cc71ffbc7c00) + + $ hg up 6189a9adfff0 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg log -r cc71ffbc7c00+6189a9adfff0+5199d0bc13d4 --hidden -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' + 1 cc71ffbc7c00 1970-01-01 00:00 +0000: date-changed using metaedit as 4:c17bf400a278; date-changed using metaedit as 2:0065551bd38f + 5 6189a9adfff0 1969-12-31 23:59 -0000: + 6 5199d0bc13d4 1970-01-01 00:02 +0000: + $ hg evolve --content-divergent + merge:[5] add foo.txt + with: [6] add foo.txt + base: [1] add foo.txt + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at 51e08ac59670 + $ hg log -r . --hidden -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' + 7 51e08ac59670 1970-01-01 00:02 +0000: + +date: updated each side to a different value, newer should win + + $ hg strip . + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + saved backup bundle to $TESTTMP/divergingdate/.hg/strip-backup/51e08ac59670-d8a3c2ca-backup.hg + 2 new content-divergent changesets + $ hg up tip + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg amend --date "235 0" + $ hg update 6189a9adfff0 --hidden + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg amend --date "784 0" + $ hg log -G + @ changeset: 8:75254fb3164b + | tag: tip + | parent: 0:a24ed8ad918c + | user: test + | date: Thu Jan 01 00:13:04 1970 +0000 + | instability: content-divergent + | summary: add foo.txt + | + | * changeset: 7:5421a7efcc6e + |/ parent: 0:a24ed8ad918c + | user: test + | date: Thu Jan 01 00:03:55 1970 +0000 + | instability: content-divergent + | summary: add foo.txt + | + o changeset: 0:a24ed8ad918c + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: add r0 + + $ hg evolve --list -r . + 75254fb3164b: add foo.txt + content-divergent: 5421a7efcc6e (draft) (precursor cc71ffbc7c00) + + $ hg log -r 6189a9adfff0+5421a7efcc6e+75254fb3164b --hidden -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' + 5 6189a9adfff0 1969-12-31 23:59 -0000: date-changed using amend as 8:75254fb3164b + 7 5421a7efcc6e 1970-01-01 00:03 +0000: + 8 75254fb3164b 1970-01-01 00:13 +0000: + $ hg evolve --content-divergent + merge:[7] add foo.txt + with: [8] add foo.txt + base: [1] add foo.txt + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at ab7c0a425dc9 + $ hg log -r . --hidden -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' + 9 ab7c0a425dc9 1970-01-01 00:13 +0000: + + $ cd .. diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-content-divergent-stack.t --- a/tests/test-evolve-content-divergent-stack.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-content-divergent-stack.t Thu Dec 26 21:23:30 2019 +0100 @@ -10,6 +10,7 @@ > [phases] > publish = False > [extensions] + > strip = > rebase = > EOF $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH @@ -348,6 +349,386 @@ | () [default] draft o 0:8fa14d15e168 added hgignore () [default] draft + +when "divergent" and "other" both hit merge conflict in relocating +------------------------------------------------------------------ + + $ hg strip 14: --hidden + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + saved backup bundle to $TESTTMP/stackrepo1/.hg/strip-backup/74fbf3e6a0b6-f3612603-backup.hg + 8 new content-divergent changesets + +Prepare repo to have merge conflicts + $ hg up -r "max(desc('added a'))" + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg evolve -r . --content-divergent + merge:[10] added a + with: [5] watbar to a + base: [1] added a + rebasing "other" content-divergent changeset 8e222f257bbf on 2228e3b74514 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + 6 new orphan changesets + working directory is now at 74fbf3e6a0b6 + $ echo b_conflict > b + $ hg amend -A + adding b + +Let's try to evolve stack + $ hg evolve --content-divergent + merge:[11] added b + with: [6] added b + base: [2] added b + rebasing "divergent" content-divergent changeset 6eb54b5af3fb on 119989a4317e + merging b + warning: conflicts while merging b! (edit, then use 'hg resolve --mark') + unresolved merge conflicts + (see 'hg help evolve.interrupted') + [1] + + $ echo b > b + $ hg res -m + (no more unresolved files) + continue: hg evolve --continue + $ hg evolve --continue + evolving 11:6eb54b5af3fb "added b" + rebasing "other" content-divergent changeset d5f148423c16 on 119989a4317e + merging b + warning: conflicts while merging b! (edit, then use 'hg resolve --mark') + unresolved merge conflicts + (see 'hg help evolve.interrupted') + [1] + + $ echo b > b + $ hg res -m + (no more unresolved files) + continue: hg evolve --continue + $ hg evolve --continue + evolving 6:d5f148423c16 "added b" + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + merge:[12] added c + with: [7] added c + base: [3] added c + rebasing "divergent" content-divergent changeset 8ed612937375 on 646bd3372ee7 + rebasing "other" content-divergent changeset 3ce4be6d8e5e on 646bd3372ee7 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + merge:[13] added d + with: [8] added d + base: [4] added d + rebasing "divergent" content-divergent changeset d45f050514c2 on 67abc597e636 + rebasing "other" content-divergent changeset c72d2885eb51 on 67abc597e636 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at 119989a4317e + $ hg glog + o 25:5e2572194f59 added d + | () [default] draft + o 22:67abc597e636 added c + | () [default] draft + o 19:646bd3372ee7 added b + | () [default] draft + @ 16:119989a4317e watbar to a + | () [default] draft + o 9:2228e3b74514 add newfile + | () [default] draft + o 0:8fa14d15e168 added hgignore + () [default] draft + +when relocating "other" hit merge conflict but not "divergent" +-------------------------------------------------------------- + $ hg strip 14: --hidden + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + saved backup bundle to $TESTTMP/stackrepo1/.hg/strip-backup/74fbf3e6a0b6-15474722-backup.hg + 8 new content-divergent changesets + +Insert conflicting changes in between the stack of content-div csets + $ hg up -r "max(desc('added b'))" + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo b_diverging_local > b + $ hg amend + 2 new orphan changesets + $ hg evolve + move:[12] added c + atop:[14] added b + move:[13] added d + $ hg up -r d5f148423c16 + 2 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo b_diverging_other > b + $ hg amend + 2 new orphan changesets + $ hg evolve + move:[7] added c + atop:[17] added b + move:[8] added d + + $ hg log -r tip + changeset: 19:c351be27f199 + tag: tip + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + instability: content-divergent + summary: added d + +Now let's try to evolve stack + $ hg evolve --content-divergent + merge:[10] added a + with: [5] watbar to a + base: [1] added a + rebasing "other" content-divergent changeset 8e222f257bbf on 2228e3b74514 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + merge:[14] added b + with: [17] added b + base: [2] added b + rebasing "divergent" content-divergent changeset 2a955e808c53 on 74fbf3e6a0b6 + rebasing "other" content-divergent changeset 509103439e5e on 74fbf3e6a0b6 + merging b + warning: conflicts while merging b! (edit, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + 4 new orphan changesets + unresolved merge conflicts + (see 'hg help evolve.interrupted') + [1] + +As now we have interrupted evolution of stack of content-divergent cset (when +relocation of "divergent" also included) let's test --abort and --stop +test --abort: + $ hg evolve --abort + 2 new content-divergent changesets + evolve aborted + working directory is now at 509103439e5e + +confirm that tip is same as it was before we started --content-div resolution + $ hg log -r tip + changeset: 19:c351be27f199 + tag: tip + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + instability: content-divergent + summary: added d + +test --stop: + $ hg log -G + * changeset: 19:c351be27f199 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | instability: content-divergent + | summary: added d + | + * changeset: 18:eaf34afe4df3 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | instability: content-divergent + | summary: added c + | + @ changeset: 17:509103439e5e + | parent: 5:8e222f257bbf + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | instability: content-divergent + | summary: added b + | + | * changeset: 16:91c8ccb9c241 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | instability: content-divergent + | | summary: added d + | | + | * changeset: 15:48b0f803817a + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | instability: content-divergent + | | summary: added c + | | + | * changeset: 14:2a955e808c53 + | | parent: 10:c04ff147ef79 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | instability: content-divergent + | | summary: added b + | | + | * changeset: 10:c04ff147ef79 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | instability: content-divergent + | | summary: added a + | | + | o changeset: 9:2228e3b74514 + | | parent: 0:8fa14d15e168 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: add newfile + | | + * | changeset: 5:8e222f257bbf + |/ parent: 0:8fa14d15e168 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | instability: content-divergent + | summary: watbar to a + | + o changeset: 0:8fa14d15e168 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: added hgignore + + $ hg evolve --content-divergent + merge:[10] added a + with: [5] watbar to a + base: [1] added a + rebasing "other" content-divergent changeset 8e222f257bbf on 2228e3b74514 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + merge:[14] added b + with: [17] added b + base: [2] added b + rebasing "divergent" content-divergent changeset 2a955e808c53 on 74fbf3e6a0b6 + rebasing "other" content-divergent changeset 509103439e5e on 74fbf3e6a0b6 + merging b + warning: conflicts while merging b! (edit, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + 4 new orphan changesets + unresolved merge conflicts + (see 'hg help evolve.interrupted') + [1] + + $ hg evolve --stop + 2 new orphan changesets + stopped the interrupted evolve + working directory is now at 2a955e808c53 + $ hg log -G + o changeset: 21:74fbf3e6a0b6 + | tag: tip + | parent: 9:2228e3b74514 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: watbar to a + | + | * changeset: 19:c351be27f199 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | instability: orphan, content-divergent + | | summary: added d + | | + | * changeset: 18:eaf34afe4df3 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | instability: orphan, content-divergent + | | summary: added c + | | + | * changeset: 17:509103439e5e + | | parent: 5:8e222f257bbf + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | instability: orphan, content-divergent + | | summary: added b + | | + | | * changeset: 16:91c8ccb9c241 + | | | user: test + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | instability: orphan, content-divergent + | | | summary: added d + | | | + | | * changeset: 15:48b0f803817a + | | | user: test + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | instability: orphan, content-divergent + | | | summary: added c + | | | + | | @ changeset: 14:2a955e808c53 + | | | parent: 10:c04ff147ef79 + | | | user: test + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | instability: orphan, content-divergent + | | | summary: added b + | | | + +---x changeset: 10:c04ff147ef79 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | obsolete: rewritten using evolve as 21:74fbf3e6a0b6 + | | summary: added a + | | + o | changeset: 9:2228e3b74514 + | | parent: 0:8fa14d15e168 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: add newfile + | | + | x changeset: 5:8e222f257bbf + |/ parent: 0:8fa14d15e168 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | obsolete: rebased using evolve as 21:74fbf3e6a0b6 + | summary: watbar to a + | + o changeset: 0:8fa14d15e168 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: added hgignore + + $ hg obslog -r 'desc("watbar to a")' --all + o 74fbf3e6a0b6 (21) watbar to a + |\ + x | 186bdc2cdfa2 (20) watbar to a + | | rewritten as 74fbf3e6a0b6 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) + | | + | x c04ff147ef79 (10) added a + | | rewritten(description, content) as 74fbf3e6a0b6 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) + | | + x | 8e222f257bbf (5) watbar to a + |/ rewritten(parent) as 186bdc2cdfa2 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) + | + x c7586e2a9264 (1) added a + rewritten(description, content) as 8e222f257bbf using amend by test (Thu Jan 01 00:00:00 1970 +0000) + rewritten(parent) as c04ff147ef79 using rebase by test (Thu Jan 01 00:00:00 1970 +0000) + + $ hg obslog -r 'desc("added b")' --all + @ 2a955e808c53 (14) added b + | + | * 509103439e5e (17) added b + | | + x | 6eb54b5af3fb (11) added b + | | rewritten(content) as 2a955e808c53 using amend by test (Thu Jan 01 00:00:00 1970 +0000) + | | + | x d5f148423c16 (6) added b + |/ rewritten(content) as 509103439e5e using amend by test (Thu Jan 01 00:00:00 1970 +0000) + | + x b1661037fa25 (2) added b + rewritten(parent) as 6eb54b5af3fb using rebase by test (Thu Jan 01 00:00:00 1970 +0000) + rewritten(parent) as d5f148423c16 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) + + +Again, let's evolve the stack + $ hg evolve --content-divergent + merge:[14] added b + with: [17] added b + base: [2] added b + rebasing "divergent" content-divergent changeset 2a955e808c53 on 74fbf3e6a0b6 + rebasing "other" content-divergent changeset 509103439e5e on 74fbf3e6a0b6 + merging b + warning: conflicts while merging b! (edit, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + unresolved merge conflicts + (see 'hg help evolve.interrupted') + [1] + + $ echo foo > b + $ hg res -m + (no more unresolved files) + continue: hg evolve --continue + $ hg evolve --continue + merge:[15] added c + with: [18] added c + base: [3] added c + rebasing "divergent" content-divergent changeset 48b0f803817a on 4e29776e83a5 + rebasing "other" content-divergent changeset eaf34afe4df3 on 4e29776e83a5 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + merge:[16] added d + with: [19] added d + base: [4] added d + rebasing "divergent" content-divergent changeset 91c8ccb9c241 on 77126af93a25 + rebasing "other" content-divergent changeset c351be27f199 on 77126af93a25 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at 4e29776e83a5 + + $ hg evolve -l + $ cd .. Make sure that content-divergent resolution doesn't undo a change (issue6203) diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-continue.t --- a/tests/test-evolve-continue.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-continue.t Thu Dec 26 21:23:30 2019 +0100 @@ -434,3 +434,31 @@ M c A d ? c.orig + + $ cd .. + $ hg init transitive-renames + $ cd transitive-renames + $ echo 1 > a + $ echo 1 > b + $ hg ci -Aqm initial + $ echo 2 > a + $ hg mv b c + $ hg ci -m 'rename b to c' + $ echo 3 > a + $ hg mv c d + $ hg ci -m 'rename c to d' + $ hg prev -q + $ echo 2b > a + $ hg amend -q + 1 new orphan changesets + $ hg ev -q + warning: conflicts while merging a! (edit, then use 'hg resolve --mark') + unresolved merge conflicts + (see 'hg help evolve.interrupted') + [1] + $ hg st -C + M a + A d + c + R c + ? a.orig diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-cycles.t --- a/tests/test-evolve-cycles.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-cycles.t Thu Dec 26 21:23:30 2019 +0100 @@ -300,21 +300,20 @@ *, (glob) 0 ], - "effect": [ + "effects": [ "description", "parent", "content" ], "operation": "prune", "succnodes": [ - "0da815c333f6" + "0da815c333f6364b46c86b0a897c00eb617397b6" ], "user": "test", "verb": "rewritten" } ], - "node": "868d2e0eb19c", - "rev": 4, + "node": "868d2e0eb19c2b55a2894d37e1c435c221384d48", "shortdescription": "D" }, { @@ -324,21 +323,20 @@ *, (glob) 0 ], - "effect": [ + "effects": [ "description", "parent", "content" ], "operation": "prune", "succnodes": [ - "868d2e0eb19c" + "868d2e0eb19c2b55a2894d37e1c435c221384d48" ], "user": "test", "verb": "rewritten" } ], - "node": "d9f908fde1a1", - "rev": 6, + "node": "d9f908fde1a10ad198a462a3ec8b440bb397fc9c", "shortdescription": "F" }, { @@ -348,21 +346,20 @@ *, (glob) 0 ], - "effect": [ + "effects": [ "description", "parent", "content" ], "operation": "prune", "succnodes": [ - "d9f908fde1a1" + "d9f908fde1a10ad198a462a3ec8b440bb397fc9c" ], "user": "test", "verb": "rewritten" } ], - "node": "0da815c333f6", - "rev": 5, + "node": "0da815c333f6364b46c86b0a897c00eb617397b6", "shortdescription": "E" }, { @@ -372,22 +369,21 @@ *, (glob) 0 ], - "effect": [ + "effects": [ "description", "parent", "content" ], "operation": "prune", "succnodes": [ - "2a34000d3544", - "868d2e0eb19c" + "2a34000d35446022104f7a091c06fe21ff2b5912", + "868d2e0eb19c2b55a2894d37e1c435c221384d48" ], "user": "test", "verb": "rewritten" } ], - "node": "a8df460dbbfe", - "rev": 3, + "node": "a8df460dbbfe9ef0c1e5ab4fff02e9514672e379", "shortdescription": "C" }, { @@ -397,21 +393,20 @@ *, (glob) 0 ], - "effect": [ + "effects": [ "description", "parent", "content" ], "operation": "prune", "succnodes": [ - "a8df460dbbfe" + "a8df460dbbfe9ef0c1e5ab4fff02e9514672e379" ], "user": "test", "verb": "rewritten" } ], - "node": "c473644ee0e9", - "rev": 2, + "node": "c473644ee0e988d7f537e31423831bbc409f12f7", "shortdescription": "B" }, { @@ -421,21 +416,20 @@ *, (glob) 0 ], - "effect": [ + "effects": [ "description", "parent", "content" ], "operation": "prune", "succnodes": [ - "c473644ee0e9" + "c473644ee0e988d7f537e31423831bbc409f12f7" ], "user": "test", "verb": "rewritten" } ], - "node": "2a34000d3544", - "rev": 1, + "node": "2a34000d35446022104f7a091c06fe21ff2b5912", "shortdescription": "A" } ] diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-issue5958.t --- a/tests/test-evolve-issue5958.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-issue5958.t Thu Dec 26 21:23:30 2019 +0100 @@ -22,8 +22,6 @@ (Make changes in unrelated files so that we don't have any merge conflicts during the rebase, but the two touched revisions aren't identical) -date: updated on both side to the same value - $ echo hi > bar.txt $ hg add -q bar.txt $ hg amend -q @@ -81,15 +79,6 @@ rewritten(date) as 0065551bd38f using metaedit by test (Thu Jan 01 00:00:00 1970 +0000) rewritten(date) as c17bf400a278 using metaedit by test (Thu Jan 01 00:00:00 1970 +0000) - $ hg evolve --list --rev . - 08bc7ba82799: add foo.txt - content-divergent: c17bf400a278 (draft) (precursor cc71ffbc7c00) - - $ hg log --hidden -r cc71ffbc7c00 -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' - 1 cc71ffbc7c00 1970-01-01 00:00 +0000: date-changed using metaedit as 4:c17bf400a278; date-changed using metaedit as 2:0065551bd38f - $ hg log -r 'desc("add foo.txt")' -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' - 4 c17bf400a278 1969-12-31 23:59 -0000: - 6 08bc7ba82799 1969-12-31 23:59 -0000: $ hg evolve --content-divergent merge:[6] add foo.txt with: [4] add foo.txt @@ -97,160 +86,3 @@ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved 1 new orphan changesets working directory is now at 459c64f7eaad - $ hg log -r 'desc("add foo.txt")' -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' - 4 c17bf400a278 1969-12-31 23:59 -0000: rewritten using evolve as 7:459c64f7eaad - 7 459c64f7eaad 1969-12-31 23:59 -0000: - -date: updated one one side to an older value - - $ hg evolve -r . - move:[7] add foo.txt - atop:[0] add r0 - working directory is now at 545776b4e79f - $ hg update --hidden --rev 'predecessors(.)' - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - updated to hidden changeset 459c64f7eaad - (hidden revision '459c64f7eaad' was rewritten as: 545776b4e79f) - working directory parent is obsolete! (459c64f7eaad) - (use 'hg evolve' to update to its successor: 545776b4e79f) - $ hg amend --date "0 3" - 1 new orphan changesets - 2 new content-divergent changesets - $ hg rebase -r . -d 0 - rebasing 9:c117f15338e6 "add foo.txt" (tip) - $ hg log -G - @ changeset: 10:7a09c7a39546 - | tag: tip - | parent: 0:a24ed8ad918c - | user: test - | date: Wed Dec 31 23:59:57 1969 -0000 - | instability: content-divergent - | summary: add foo.txt - | - | * changeset: 8:545776b4e79f - |/ parent: 0:a24ed8ad918c - | user: test - | date: Wed Dec 31 23:59:58 1969 -0000 - | instability: content-divergent - | summary: add foo.txt - | - o changeset: 0:a24ed8ad918c - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add r0 - - $ hg evolve --list -r . - 7a09c7a39546: add foo.txt - content-divergent: 545776b4e79f (draft) (precursor 459c64f7eaad) - - $ hg log -r 459c64f7eaad+7a09c7a39546+545776b4e79f --hidden -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' - 7 459c64f7eaad 1969-12-31 23:59 -0000: date-changed using amend as 9:c117f15338e6; rebased using evolve as 8:545776b4e79f - 10 7a09c7a39546 1969-12-31 23:59 -0000: - 8 545776b4e79f 1969-12-31 23:59 -0000: - $ hg evolve --content-divergent - merge:[8] add foo.txt - with: [10] add foo.txt - base: [7] add foo.txt - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory is now at 39c4200c0d94 - $ hg log -r . --hidden -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' - 11 39c4200c0d94 1969-12-31 23:59 -0000: - -date: updated one side to an newer value - - $ hg update --hidden --rev 'predecessors(.)' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - updated to hidden changeset 7a09c7a39546 - (hidden revision '7a09c7a39546' was rewritten as: 39c4200c0d94) - working directory parent is obsolete! (7a09c7a39546) - (use 'hg evolve' to update to its successor: 39c4200c0d94) - $ hg amend --date "120 0" - 2 new content-divergent changesets - $ hg log -G - @ changeset: 12:da3be3d72fe2 - | tag: tip - | parent: 0:a24ed8ad918c - | user: test - | date: Thu Jan 01 00:02:00 1970 +0000 - | instability: content-divergent - | summary: add foo.txt - | - | * changeset: 11:39c4200c0d94 - |/ parent: 0:a24ed8ad918c - | user: test - | date: Wed Dec 31 23:59:57 1969 -0000 - | instability: content-divergent - | summary: add foo.txt - | - o changeset: 0:a24ed8ad918c - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add r0 - - $ hg evolve --list -r . - da3be3d72fe2: add foo.txt - content-divergent: 39c4200c0d94 (draft) (precursor 7a09c7a39546) - - $ hg up 39c4200c0d94 - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg log -r 7a09c7a39546+39c4200c0d94+da3be3d72fe2 --hidden -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' - 10 7a09c7a39546 1969-12-31 23:59 -0000: date-changed using amend as 12:da3be3d72fe2; rewritten using evolve as 11:39c4200c0d94 - 11 39c4200c0d94 1969-12-31 23:59 -0000: - 12 da3be3d72fe2 1970-01-01 00:02 +0000: - $ hg evolve --content-divergent - merge:[11] add foo.txt - with: [12] add foo.txt - base: [10] add foo.txt - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory is now at 06cde6010a51 - $ hg log -r . --hidden -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' - 13 06cde6010a51 1970-01-01 00:02 +0000: - -date: updated each side to a different value, newer should win - - $ hg amend --date "235 0" - $ hg update --hidden --rev 'predecessors(.)' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - updated to hidden changeset 06cde6010a51 - (hidden revision '06cde6010a51' was rewritten as: a7412ff9bfb3) - working directory parent is obsolete! (06cde6010a51) - (use 'hg evolve' to update to its successor: a7412ff9bfb3) - $ hg amend --date "784 0" - 2 new content-divergent changesets - $ hg log -G - @ changeset: 15:e3077936ec52 - | tag: tip - | parent: 0:a24ed8ad918c - | user: test - | date: Thu Jan 01 00:13:04 1970 +0000 - | instability: content-divergent - | summary: add foo.txt - | - | * changeset: 14:a7412ff9bfb3 - |/ parent: 0:a24ed8ad918c - | user: test - | date: Thu Jan 01 00:03:55 1970 +0000 - | instability: content-divergent - | summary: add foo.txt - | - o changeset: 0:a24ed8ad918c - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add r0 - - $ hg evolve --list -r . - e3077936ec52: add foo.txt - content-divergent: a7412ff9bfb3 (draft) (precursor 06cde6010a51) - - $ hg log -r 39c4200c0d94+a7412ff9bfb3+e3077936ec52 --hidden -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' - 11 39c4200c0d94 1969-12-31 23:59 -0000: date-changed using evolve as 13:06cde6010a51 - 14 a7412ff9bfb3 1970-01-01 00:03 +0000: - 15 e3077936ec52 1970-01-01 00:13 +0000: - $ hg evolve --content-divergent - merge:[14] add foo.txt - with: [15] add foo.txt - base: [13] add foo.txt - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory is now at 1a39f3901288 - $ hg log -r . --hidden -T '{rev} {node|short} {date|isodate}: {join(obsfate, "; ")}\n' - 16 1a39f3901288 1970-01-01 00:13 +0000: diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-obshistory-amend-then-fold.t --- a/tests/test-evolve-obshistory-amend-then-fold.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-obshistory-amend-then-fold.t Thu Dec 26 21:23:30 2019 +0100 @@ -152,8 +152,7 @@ [ { "markers": [], - "node": "eb5a0daa2192", - "rev": 4, + "node": "eb5a0daa21923bbf8caeb2c42085b9e463861fd0", "shortdescription": "C0" }, { @@ -163,21 +162,20 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ *, (glob) *, (glob) "content" ], "operation": "fold", "succnodes": [ - "eb5a0daa2192" + "eb5a0daa21923bbf8caeb2c42085b9e463861fd0" ], "user": "test", "verb": "rewritten" } ], - "node": "b7ea6d14e664", - "rev": 3, + "node": "b7ea6d14e664bdc8922221f7992631b50da3fb07", "shortdescription": "B1" }, { @@ -187,19 +185,18 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "description" ], "operation": "amend", "succnodes": [ - "b7ea6d14e664" + "b7ea6d14e664bdc8922221f7992631b50da3fb07" ], "user": "test", "verb": "rewritten" } ], - "node": "0dec01379d3b", - "rev": 2, + "node": "0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "shortdescription": "B0" }, { @@ -209,20 +206,19 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "description", "content" ], "operation": "fold", "succnodes": [ - "eb5a0daa2192" + "eb5a0daa21923bbf8caeb2c42085b9e463861fd0" ], "user": "test", "verb": "rewritten" } ], - "node": "471f378eab4c", - "rev": 1, + "node": "471f378eab4c5e25f6c77f785b27c936efb22874", "shortdescription": "A0" } ] diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-obshistory-amend.t --- a/tests/test-evolve-obshistory-amend.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-obshistory-amend.t Thu Dec 26 21:23:30 2019 +0100 @@ -92,6 +92,7 @@ $ hg obslog --no-graph --patch 4ae3a4151de9 4ae3a4151de9 (2) A1 + 471f378eab4c (1) A0 rewritten(description, content) as 4ae3a4151de9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r 4ae3a4151de9 changeset-description @@ -109,8 +110,32 @@ @@ -1,1 +1,2 @@ A0 +42 - + + +Test that content diff works with templating + $ hg obslog --color=debug --patch 4ae3a4151de9 \ + > -T '{node|short} {desc|firstline}\n{markers % "patch:\n```{patch}```\n"}' + @ 4ae3a4151de9 A1 + | + x 471f378eab4c A0 + patch: + ``` + [diff.diffline|diff -r 471f378eab4c -r 4ae3a4151de9 A0] + [diff.file_a|--- a/A0 Thu Jan 01 00:00:00 1970 +0000] + [diff.file_b|+++ b/A0 Thu Jan 01 00:00:00 1970 +0000] + [diff.hunk|@@ -1,1 +1,2 @@] + A0 + [diff.inserted|+42] + ``` + + $ hg obslog 4ae3a4151de9 --graph -T'{label("log.summary", desc|firstline)} {if(markers, join(markers % "at {date|hgdate} by {user|person} ", " also "))}' + @ A1 + | + x A0 at 0 0 by test + + +Check that the same thing works with the old {shortdescription} form $ hg obslog 4ae3a4151de9 --graph -T'{label("log.summary", shortdescription)} {if(markers, join(markers % "at {date|hgdate} by {user|person} ", " also "))}' @ A1 | @@ -120,8 +145,7 @@ [ { "markers": [], - "node": "4ae3a4151de9", - "rev": 2, + "node": "4ae3a4151de9aa872113f0b196e28323308981e8", "shortdescription": "A1" }, { @@ -131,20 +155,19 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "description", "content" ], "operation": "amend", "succnodes": [ - "4ae3a4151de9" + "4ae3a4151de9aa872113f0b196e28323308981e8" ], "user": "test", "verb": "rewritten" } ], - "node": "471f378eab4c", - "rev": 1, + "node": "471f378eab4c5e25f6c77f785b27c936efb22874", "shortdescription": "A0" } ] @@ -177,20 +200,19 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ *, (glob) "content" ], "operation": "amend", "succnodes": [ - "4ae3a4151de9" + "4ae3a4151de9aa872113f0b196e28323308981e8" ], "user": "test", "verb": "rewritten" } ], - "node": "471f378eab4c", - "rev": 1, + "node": "471f378eab4c5e25f6c77f785b27c936efb22874", "shortdescription": "A0" } ] @@ -220,15 +242,19 @@ $ hg obslog -R $TESTTMP/server --no-graph --patch 4ae3a4151de9 4ae3a4151de9 (1) A1 + 471f378eab4c rewritten(description, content) as 4ae3a4151de9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, context is not local) + $ hg obslog -R $TESTTMP/server --no-graph -f --patch 4ae3a4151de9 4ae3a4151de9 (1) A1 + 471f378eab4c rewritten(description, content) as 4ae3a4151de9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, context is not local) + Amend two more times ==================== @@ -347,6 +373,50 @@ +42 +Test that description diff works with templating + $ hg obslog --color=debug --patch 92210308515b \ + > -T '{node|short} {desc|firstline}\n{markers % "description diff:\n```{descdiff}```\n"}' + @ 92210308515b A3 + | + x 4f1685185907 A2 + | description diff: + | ``` + | [diff.diffline|diff -r 4f1685185907 -r 92210308515b changeset-description] + | [diff.file_a|--- a/changeset-description] + | [diff.file_b|+++ b/changeset-description] + | [diff.hunk|@@ -1,3 +1,3 @@] + | [diff.deleted|-A2] + | [diff.inserted|+A3] + | + | [diff.deleted|-Better better commit message] + | [diff.inserted|+Better better better commit message] + | ``` + x 4ae3a4151de9 A1 + | description diff: + | ``` + | [diff.diffline|diff -r 4ae3a4151de9 -r 4f1685185907 changeset-description] + | [diff.file_a|--- a/changeset-description] + | [diff.file_b|+++ b/changeset-description] + | [diff.hunk|@@ -1,3 +1,3 @@] + | [diff.deleted|-A1] + | [diff.inserted|+A2] + | + | [diff.deleted|-Better commit message] + | [diff.inserted|+Better better commit message] + | ``` + x 471f378eab4c A0 + description diff: + ``` + [diff.diffline|diff -r 471f378eab4c -r 4ae3a4151de9 changeset-description] + [diff.file_a|--- a/changeset-description] + [diff.file_b|+++ b/changeset-description] + [diff.hunk|@@ -1,1 +1,3 @@] + [diff.deleted|-A0] + [diff.inserted|+A1] + [diff.inserted|+] + [diff.inserted|+Better commit message] + ``` + Check the output on the server ------------------------------ @@ -383,24 +453,32 @@ $ hg obslog -R $TESTTMP/server --no-graph --patch 92210308515b 92210308515b (2) A3 + 4f1685185907 rewritten(description) as 92210308515b using amend by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, context is not local) + 4ae3a4151de9 (1) A1 rewritten(description) as 4f1685185907 using amend by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, successor is unknown locally) + 471f378eab4c rewritten(description, content) as 4ae3a4151de9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, context is not local) + $ hg obslog -R $TESTTMP/server --no-graph -f --patch 92210308515b 92210308515b (2) A3 + 4f1685185907 rewritten(description) as 92210308515b using amend by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, context is not local) + 4ae3a4151de9 (1) A1 rewritten(description) as 4f1685185907 using amend by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, successor is unknown locally) + 471f378eab4c rewritten(description, content) as 4ae3a4151de9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, context is not local) + diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-obshistory-content-divergent.t --- a/tests/test-evolve-obshistory-content-divergent.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-obshistory-content-divergent.t Thu Dec 26 21:23:30 2019 +0100 @@ -129,12 +129,12 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "description" ], "operation": "amend", "succnodes": [ - "65b757b745b9" + "65b757b745b935093c87a2bccd877521cccffcbd" ], "user": "test", "verb": "rewritten" @@ -144,19 +144,18 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "description" ], "operation": "amend", "succnodes": [ - "fdf9bde5129a" + "fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e" ], "user": "test", "verb": "rewritten" } ], - "node": "471f378eab4c", - "rev": 1, + "node": "471f378eab4c5e25f6c77f785b27c936efb22874", "shortdescription": "A0" } ] @@ -284,8 +283,7 @@ [ { "markers": [], - "node": "65b757b745b9", - "rev": 3, + "node": "65b757b745b935093c87a2bccd877521cccffcbd", "shortdescription": "A2" }, { @@ -295,12 +293,12 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "description" ], "operation": "amend", "succnodes": [ - "65b757b745b9" + "65b757b745b935093c87a2bccd877521cccffcbd" ], "user": "test", "verb": "rewritten" @@ -310,25 +308,23 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "description" ], "operation": "amend", "succnodes": [ - "fdf9bde5129a" + "fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e" ], "user": "test", "verb": "rewritten" } ], - "node": "471f378eab4c", - "rev": 1, + "node": "471f378eab4c5e25f6c77f785b27c936efb22874", "shortdescription": "A0" }, { "markers": [], - "node": "fdf9bde5129a", - "rev": 2, + "node": "fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e", "shortdescription": "A1" } ] diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-obshistory-fold.t --- a/tests/test-evolve-obshistory-fold.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-obshistory-fold.t Thu Dec 26 21:23:30 2019 +0100 @@ -172,8 +172,7 @@ [ { "markers": [], - "node": "eb5a0daa2192", - "rev": 3, + "node": "eb5a0daa21923bbf8caeb2c42085b9e463861fd0", "shortdescription": "C0" }, { @@ -183,20 +182,19 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "description", "content" ], "operation": "fold", "succnodes": [ - "eb5a0daa2192" + "eb5a0daa21923bbf8caeb2c42085b9e463861fd0" ], "user": "test", "verb": "rewritten" } ], - "node": "471f378eab4c", - "rev": 1, + "node": "471f378eab4c5e25f6c77f785b27c936efb22874", "shortdescription": "A0" }, { @@ -206,21 +204,20 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "description", "parent", "content" ], "operation": "fold", "succnodes": [ - "eb5a0daa2192" + "eb5a0daa21923bbf8caeb2c42085b9e463861fd0" ], "user": "test", "verb": "rewritten" } ], - "node": "0dec01379d3b", - "rev": 2, + "node": "0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "shortdescription": "B0" } ] diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-obshistory-lots-of-splits.t --- a/tests/test-evolve-obshistory-lots-of-splits.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-obshistory-lots-of-splits.t Thu Dec 26 21:23:30 2019 +0100 @@ -201,23 +201,22 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "parent", "content" ], "operation": "split", "succnodes": [ - "1ae8bc733a14", - "337fec4d2edc", - "c7f044602e9b", - "f257fde29c7a" + "1ae8bc733a14e374f11767d2ad128d4c891dc43f", + "337fec4d2edcf0e7a467e35f818234bc620068b5", + "c7f044602e9bd5dec6528b33114df3d0221e6359", + "f257fde29c7a847c9b607f6e958656d0df0fb15c" ], "user": "test", "verb": "rewritten" } ], - "node": "de7290d8b885", - "rev": 1, + "node": "de7290d8b885925115bb9e88887252dfc20ef2a8", "shortdescription": "A0" } ] @@ -232,8 +231,7 @@ [ { "markers": [], - "node": "c7f044602e9b", - "rev": 5, + "node": "c7f044602e9bd5dec6528b33114df3d0221e6359", "shortdescription": "A0" }, { @@ -243,23 +241,22 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "parent", "content" ], "operation": "split", "succnodes": [ - "1ae8bc733a14", - "337fec4d2edc", - "c7f044602e9b", - "f257fde29c7a" + "1ae8bc733a14e374f11767d2ad128d4c891dc43f", + "337fec4d2edcf0e7a467e35f818234bc620068b5", + "c7f044602e9bd5dec6528b33114df3d0221e6359", + "f257fde29c7a847c9b607f6e958656d0df0fb15c" ], "user": "test", "verb": "rewritten" } ], - "node": "de7290d8b885", - "rev": 1, + "node": "de7290d8b885925115bb9e88887252dfc20ef2a8", "shortdescription": "A0" } ] diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-obshistory-phase-divergent.t --- a/tests/test-evolve-obshistory-phase-divergent.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-obshistory-phase-divergent.t Thu Dec 26 21:23:30 2019 +0100 @@ -102,19 +102,18 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "description" ], "operation": "amend", "succnodes": [ - "fdf9bde5129a" + "fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e" ], "user": "test", "verb": "rewritten" } ], - "node": "471f378eab4c", - "rev": 1, + "node": "471f378eab4c5e25f6c77f785b27c936efb22874", "shortdescription": "A0" } ] @@ -196,30 +195,28 @@ [ { "markers": [], - "node": "fdf9bde5129a", - "rev": 2, + "node": "fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e", "shortdescription": "A1" }, { "markers": [ { "date": [ - 0, + 0.0, 0 ], - "effect": [ + "effects": [ "description" ], "operation": "amend", "succnodes": [ - "fdf9bde5129a" + "fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e" ], "user": "test", "verb": "rewritten" } ], - "node": "471f378eab4c", - "rev": 1, + "node": "471f378eab4c5e25f6c77f785b27c936efb22874", "shortdescription": "A0" } ] diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-obshistory-prune.t --- a/tests/test-evolve-obshistory-prune.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-obshistory-prune.t Thu Dec 26 21:23:30 2019 +0100 @@ -82,8 +82,7 @@ "verb": "pruned" } ], - "node": "0dec01379d3b", - "rev": 2, + "node": "0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "shortdescription": "B0" } ] @@ -94,8 +93,7 @@ [ { "markers": [], - "node": "471f378eab4c", - "rev": 1, + "node": "471f378eab4c5e25f6c77f785b27c936efb22874", "shortdescription": "A0" } ] diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-obshistory-split.t --- a/tests/test-evolve-obshistory-split.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-obshistory-split.t Thu Dec 26 21:23:30 2019 +0100 @@ -119,22 +119,21 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "parent", "content" ], "note": "testing split", "operation": "split", "succnodes": [ - "337fec4d2edc", - "f257fde29c7a" + "337fec4d2edcf0e7a467e35f818234bc620068b5", + "f257fde29c7a847c9b607f6e958656d0df0fb15c" ], "user": "test", "verb": "rewritten" } ], - "node": "471597cad322", - "rev": 1, + "node": "471597cad322d1f659bb169751be9133dad92ef3", "shortdescription": "A0" } ] @@ -245,14 +244,18 @@ $ hg obslog -R $TESTTMP/server --no-graph -f --all --patch tip f257fde29c7a (2) A0 + 471597cad322 rewritten(parent, content) as 337fec4d2edc, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) note: testing split (No patch available, context is not local) + $ hg obslog -R $TESTTMP/server --no-graph -f --all --patch tip f257fde29c7a (2) A0 + 471597cad322 rewritten(parent, content) as 337fec4d2edc, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) note: testing split (No patch available, context is not local) + diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-obshistory.t --- a/tests/test-evolve-obshistory.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-obshistory.t Thu Dec 26 21:23:30 2019 +0100 @@ -168,3 +168,12 @@ [evolve.verb|rewritten](description) as [evolve.node|fdf9bde5129a] using [evolve.operation|amend] by [evolve.user|test] [evolve.date|(Thu Jan 01 00:00:00 1970 +0000)] (No patch available, successor is unknown locally) + + $ hg obslog 7a230b46bf61 --graph \ + > -T '{node|short} {rev} {desc|firstline}\n{markers % "rewritten using {operation}"}\n' + o 7a230b46bf61 2 A2 + | + x fdf9bde5129a + | rewritten using amend + @ 471f378eab4c 1 A0 + rewritten using amend diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-evolve-orphan-merge.t --- a/tests/test-evolve-orphan-merge.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-evolve-orphan-merge.t Thu Dec 26 21:23:30 2019 +0100 @@ -134,11 +134,18 @@ date: Thu Jan 01 00:00:00 1970 +0000 summary: merging a and b + +Clean up to prepare for next test case + $ hg prune -r 64370c9805e7 -r 3d41537b44ca -r 968d205ba4d8 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + working directory is now at 8fa14d15e168 + 3 changesets pruned + 2) When merging both the parents resulted in conflicts ------------------------------------------------------ $ hg up 8fa14d15e168 - 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ echo foo > c $ hg ci -Aqm "foo to c" $ hg prev @@ -152,24 +159,6 @@ | () draft | o 8:1c165c673853 foo to c |/ () draft - | o 7:968d205ba4d8 merging a and b - | |\ () draft - +---o 6:3d41537b44ca added a - | | () draft - | o 4:64370c9805e7 added b - |/ () draft - o 0:8fa14d15e168 added hgignore - () draft - -Prune old test changesets to have clear graph view - $ hg prune -r 64370c9805e7 -r 3d41537b44ca -r 968d205ba4d8 - 3 changesets pruned - - $ hg glog - @ 9:d0f84b25d4e3 bar to c - | () draft - | o 8:1c165c673853 foo to c - |/ () draft o 0:8fa14d15e168 added hgignore () draft @@ -532,21 +521,16 @@ $ hg evolve -r . move:[28] merged l and x atop:[0] added hgignore - working directory is now at b61ba77b924a + evolution of 28:fb8fe870ae7d created no changes to commit + working directory is now at 8fa14d15e168 $ hg glog - @ 29:b61ba77b924a merged l and x - | () draft - o 0:8fa14d15e168 added hgignore + @ 0:8fa14d15e168 added hgignore () draft 7) When one parent is pruned without successor and has no parent ---------------------------------------------------------------- - $ hg prune -r . - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory is now at 8fa14d15e168 - 1 changesets pruned $ hg up null 0 files updated, 0 files merged, 1 files removed, 0 files unresolved @@ -560,9 +544,9 @@ (branch merge, don't forget to commit) $ hg ci -m "merge commit" $ hg glog - @ 31:32beb84b9dbc merge commit + @ 30:32beb84b9dbc merge commit |\ () draft - | o 30:f3ba8b99bb6f added foo + | o 29:f3ba8b99bb6f added foo | () draft o 0:8fa14d15e168 added hgignore () draft @@ -572,9 +556,9 @@ 1 new orphan changesets $ hg glog - @ 31:32beb84b9dbc merge commit + @ 30:32beb84b9dbc merge commit |\ () draft - | x 30:f3ba8b99bb6f added foo + | x 29:f3ba8b99bb6f added foo | () draft o 0:8fa14d15e168 added hgignore () draft @@ -592,12 +576,12 @@ just remove that chain. $ hg evolve -r . - move:[31] merge commit + move:[30] merge commit atop:[-1] working directory is now at d2a03dd8c951 $ hg glog - @ 32:d2a03dd8c951 merge commit + @ 31:d2a03dd8c951 merge commit | () draft o 0:8fa14d15e168 added hgignore () draft diff -r 1015a1dbaf7c -r c5efcbbd0dc4 tests/test-topic.t --- a/tests/test-topic.t Thu Dec 26 12:22:49 2019 +0700 +++ b/tests/test-topic.t Thu Dec 26 21:23:30 2019 +0100 @@ -122,10 +122,15 @@ list of commands: - stack list all changesets in a topic and other information + Change organization: + topics View current topic, set current topic, change topic for a set of revisions, or see all topics. + Change navigation: + + stack list all changesets in a topic and other information + (use 'hg help -v topic' to show built-in aliases and global options) $ hg help topics hg topics [OPTION]... [-r REV]... [TOPIC]