Mercurial > evolve
changeset 5111:1fe3f7ffb462
branching
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Sat, 01 Feb 2020 12:50:10 +0100 |
parents | e50f4fc6cc6d (diff) 48abf37e552b (current diff) |
children | 51e38bf936cf |
files | CHANGELOG hgext3rd/evolve/cmdrewrite.py hgext3rd/evolve/compat.py hgext3rd/evolve/evolvecmd.py hgext3rd/evolve/metadata.py hgext3rd/evolve/rewind.py hgext3rd/topic/__init__.py tests/test-evolve-content-divergent-first-changeset.t |
diffstat | 56 files changed, 1694 insertions(+), 1473 deletions(-) [+] |
line wrap: on
line diff
--- a/.gitlab-ci.yml Fri Jan 31 14:50:37 2020 +0100 +++ b/.gitlab-ci.yml Sat Feb 01 12:50:10 2020 +0100 @@ -3,6 +3,16 @@ script: - hg files -0 'set:(**.py or grep("^#!.*python")) - removed()' -X hgext3rd/evolve/thirdparty | xargs -0 flake8 +pytype: + image: octobus/ci-py3-hgext3rd + script: + - hg pull -R /ci/repos/mercurial/ + - hg_rev=$(tests/testlib/map-hg-rev.sh "$(hg log -r . -T '{branch}')") + - hg -R /ci/repos/mercurial/ update "$hg_rev" + - jobs=$(python -c 'import multiprocessing; print multiprocessing.cpu_count()') + - pytype -P /ci/repos/mercurial/:hgext3rd -k hgext3rd -x hgext3rd/evolve/thirdparty -j $jobs || true + when: manual + tests-py2-cext: image: octobus/ci-py2-hgext3rd script: @@ -34,3 +44,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/*
--- a/CHANGELOG Fri Jan 31 14:50:37 2020 +0100 +++ b/CHANGELOG Sat Feb 01 12:50:10 2020 +0100 @@ -1,6 +1,19 @@ Changelog ========= +9.3.0 - in progress +------------------- + + * evolve: extensive cleanup of functions, template keywords and compatibility + code related to obsfate and successorssets + * 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 + * evolve: add content divergence checking to the standard pre-rewrite check, + * evolve: improve the message associated with content divergence. + 9.2.2 -- 2020-01-31 -------------------
--- a/hgext3rd/evolve/__init__.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/__init__.py Sat Feb 01 12:50:10 2020 +0100 @@ -251,7 +251,6 @@ """.strip() import sys -import struct try: from mercurial import registrar @@ -326,9 +325,6 @@ b'evolve.operation': b'bold' } -_pack = struct.pack -_unpack = struct.unpack - aliases, entry = cmdutil.findcmd(b'commit', commands.table) # This extension contains the following code @@ -465,7 +461,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 +477,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 @@ -705,10 +703,10 @@ debugcommand = b"hg evolve --list --content-divergent" basemsg = _(b"%s has diverged, use '%s' to resolve the issue") solvemsg = basemsg % (shortnode, debugcommand) - elif reason == b'superseed': + elif reason == b'superseded': msg = _(b"use 'hg evolve' to update to its successor: %s") solvemsg = msg % successors[0] - elif reason == b'superseed_split': + elif reason == b'superseded_split': msg = _(b"use 'hg evolve' to update to its tipmost successor: %s") if len(successors) <= 2: @@ -736,10 +734,10 @@ rev = repo[scmutil.revsingle(unfilteredrepo, changeid)] reason, successors = obshistory._getobsfateandsuccs(unfilteredrepo, rev.node()) - # Be more precise in case the revision is superseed - if reason == b'superseed': + # Be more precise in case the revision is superseded + if reason == b'superseded': reason = _(b"successor: %s") % successors[0] - elif reason == b'superseed_split': + elif reason == b'superseded_split': if len(successors) <= 2: reason = _(b"successors: %s") % b", ".join(successors) else: @@ -947,7 +945,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 +987,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 +1022,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 +1046,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 +1338,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
--- a/hgext3rd/evolve/cmdrewrite.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/cmdrewrite.py Sat Feb 01 12:50:10 2020 +0100 @@ -26,7 +26,6 @@ merge, node, obsolete, - obsutil, patch, phases, pycompat, @@ -36,11 +35,6 @@ from mercurial.i18n import _ -try: - from mercurial.utils.dateutil import datestr -except ImportError: # hg <= 4.5 - from mercurial.util import datestr - from . import ( compat, state, @@ -56,6 +50,7 @@ commitopts2 = commands.commitopts2 mergetoolopts = commands.mergetoolopts stringio = util.stringio +precheck_contentdiv = rewriteutil.precheck_contentdiv # option added by evolve @@ -66,9 +61,6 @@ if not note: return - if not compat.isobsnotesupported(): - ui.warn(_(b"current hg version does not support storing" - b" note in obsmarker\n")) if len(note) > 255: raise error.Abort(_(b"cannot store a note of more than 255 bytes")) if b'\n' in note: @@ -109,7 +101,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 @@ -274,7 +267,7 @@ fp.write(b"# HG changeset patch\n") fp.write(b"# User %s\n" % ctx.user()) fp.write(b"# Date %d %d\n" % ctx.date()) - fp.write(b"# %s\n" % datestr(ctx.date())) + fp.write(b"# %s\n" % compat.datestr(ctx.date())) if branch and branch != b'default': fp.write(b"# Branch %s\n" % branch) fp.write(b"# Node ID %s\n" % node.hex(nodeval)) @@ -458,7 +451,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 @@ -694,7 +688,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 @@ -824,7 +819,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 @@ -982,7 +978,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 @@ -1092,7 +1089,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 @@ -1176,7 +1173,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 @@ -1353,7 +1351,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 @@ -1393,27 +1392,7 @@ p2 = newmapping.get(p2, p2) if not (duplicate or allowdivergence): - # If reviving this cset creates divergence, let's ask user - # what to do: create divergence or duplicate - - # We need to check two cases that can cause divergence: - # case 1: the rev being revived has a non-obsolete successor (easily - # detected by successorssets) - sset = obsutil.successorssets(repo, ctx.node()) - nodivergencerisk = (len(sset) == 0 - or (len(sset) == 1 - and len(sset[0]) == 1 - and repo[sset[0][0]].rev() == ctx.rev() - )) - if nodivergencerisk: - # case 2: one of the precursors of the rev being revived has a - # non-obsolete successor (we need divergentsets for this) - from . import evolvecmd - if evolvecmd.divergentsets(repo, ctx): - nodivergencerisk = False - if nodivergencerisk: - duplicate = False - else: + if precheck_contentdiv(repo, ctx): displayer.show(ctx) index = ui.promptchoice( _(b"reviving this changeset will create divergence" @@ -1421,9 +1400,7 @@ b" (d)uplicate the changeset? $$ &Allowdivergence $$ " b"&Duplicate"), 0) choice = [b'allowdivergence', b'duplicate'][index] - if choice == b'allowdivergence': - duplicate = False - else: + if choice == b'duplicate': duplicate = True updates = [] @@ -1454,7 +1431,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."""
--- a/hgext3rd/evolve/compat.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/compat.py Sat Feb 01 12:50:10 2020 +0100 @@ -13,11 +13,10 @@ from mercurial import ( context, copies, - encoding, mdiff, obsolete, - obsutil, pycompat, + registrar, repair, scmutil, util, @@ -41,9 +40,9 @@ changesetdiffer = logcmdutil.changesetdiffer except (AttributeError, ImportError): from mercurial import cmdutil - changesetdisplayer = cmdutil.show_changeset - changesetprinter = cmdutil.changeset_printer - displaygraph = cmdutil.displaygraph + changesetdisplayer = cmdutil.show_changeset # pytype: disable=module-attr + changesetprinter = cmdutil.changeset_printer # pytype: disable=module-attr + displaygraph = cmdutil.displaygraph # pytype: disable=module-attr changesetdiffer = None # hg <= 5.3 (c21aca51b392) @@ -51,7 +50,7 @@ from mercurial import pathutil dirs = pathutil.dirs except (AttributeError, ImportError): - dirs = util.dirs + dirs = util.dirs # pytype: disable=module-attr from . import ( exthelper, @@ -59,14 +58,6 @@ eh = exthelper.exthelper() -def isobsnotesupported(): - # hack to know obsnote is supported. The patches for obsnote support was - # pushed before the obsfateprinter patches, so this will serve as a good - # check - if not obsutil: - return False - return util.safehasattr(obsutil, 'obsfateprinter') - # Evolution renaming compat TROUBLES = { @@ -75,6 +66,7 @@ r'PHASEDIVERGENT': b'phase-divergent', } +# hg <= 4.6 (bec1212eceaa) if util.safehasattr(uimod.ui, 'makeprogress'): def progress(ui, topic, pos, item=b"", unit=b"", total=None): progress = ui.makeprogress(topic, unit, total) @@ -96,7 +88,7 @@ def memfilectx(repo, ctx, fctx, flags, copied, path): # XXX Would it be better at the module level? - varnames = context.memfilectx.__init__.__code__.co_varnames + varnames = context.memfilectx.__init__.__code__.co_varnames # pytype: disable=attribute-error if r"copysource" in varnames: mctx = context.memfilectx(repo, ctx, fctx.path(), fctx.data(), @@ -108,12 +100,12 @@ mctx = context.memfilectx(repo, ctx, fctx.path(), fctx.data(), islink=b'l' in flags, isexec=b'x' in flags, - copied=copied.get(path)) + copied=copied.get(path)) # pytype: disable=wrong-keyword-args else: mctx = context.memfilectx(repo, fctx.path(), fctx.data(), islink=b'l' in flags, isexec=b'x' in flags, - copied=copied.get(path)) + copied=copied.get(path)) # pytype: disable=wrong-keyword-args return mctx def strdiff(a, b, fn1, fn2): @@ -136,14 +128,17 @@ # date related +# hg <= 4.5 (c6061cadb400) try: import mercurial.utils.dateutil + datestr = mercurial.utils.dateutil.datestr makedate = mercurial.utils.dateutil.makedate parsedate = mercurial.utils.dateutil.parsedate except ImportError: import mercurial.util - makedate = mercurial.util.makedate - parsedate = mercurial.util.parsedate + datestr = mercurial.util.datestr # pytype: disable=module-attr + makedate = mercurial.util.makedate # pytype: disable=module-attr + parsedate = mercurial.util.parsedate # pytype: disable=module-attr def wireprotocommand(exthelper, name, args=b'', permission=b'pull'): try: @@ -174,7 +169,7 @@ # scmutil.bookmarkrevs # This change is a part of 4.7 cycle, so drop this when we drop support for 4.6 try: - bmrevset = repair.stripbmrevset + bmrevset = repair.stripbmrevset # pytype: disable=module-attr except AttributeError: bmrevset = scmutil.bookmarkrevs @@ -220,9 +215,9 @@ # hg < 4.8 compat (dc50121126ae) try: - limit = copies._findlimit(repo, c1, c2) + limit = copies._findlimit(repo, c1, c2) # pytype: disable=module-attr except (AttributeError, TypeError): - limit = copies._findlimit(repo, c1.rev(), c2.rev()) + limit = copies._findlimit(repo, c1.rev(), c2.rev()) # pytype: disable=module-attr if limit is None: # no common ancestor, no copies return {}, {}, {}, {}, {} @@ -263,11 +258,11 @@ bothnew = sorted(addedinm1 & addedinm2) if tca == base: # unmatched file from base - u1r, u2r = copies._computenonoverlap(repo, c1, c2, addedinm1, addedinm2) + u1r, u2r = copies._computenonoverlap(repo, c1, c2, addedinm1, addedinm2) # pytype: disable=module-attr u1u, u2u = u1r, u2r else: # unmatched file from base (DAG rotation in the graft case) - u1r, u2r = copies._computenonoverlap(repo, c1, c2, addedinm1, addedinm2, + u1r, u2r = copies._computenonoverlap(repo, c1, c2, addedinm1, addedinm2, # pytype: disable=module-attr baselabel=b'base') # unmatched file from topological common ancestors (no DAG rotation) # need to recompute this for directory move handling when grafting @@ -276,18 +271,18 @@ m1f = m1.filesnotin(mta, repo.narrowmatch()) m2f = m2.filesnotin(mta, repo.narrowmatch()) baselabel = b'topological common ancestor' - u1u, u2u = copies._computenonoverlap(repo, c1, c2, m1f, m2f, + u1u, u2u = copies._computenonoverlap(repo, c1, c2, m1f, m2f, # pytype: disable=module-attr baselabel=baselabel) else: - u1u, u2u = copies._computenonoverlap(repo, c1, c2, m1.filesnotin(mta), + u1u, u2u = copies._computenonoverlap(repo, c1, c2, m1.filesnotin(mta), # pytype: disable=module-attr m2.filesnotin(mta), baselabel=b'topological common ancestor') for f in u1u: - copies._checkcopies(c1, c2, f, base, tca, dirtyc1, limit, data1) + copies._checkcopies(c1, c2, f, base, tca, dirtyc1, limit, data1) # pytype: disable=module-attr for f in u2u: - copies._checkcopies(c2, c1, f, base, tca, dirtyc2, limit, data2) + copies._checkcopies(c2, c1, f, base, tca, dirtyc2, limit, data2) # pytype: disable=module-attr copy = dict(data1[b'copy']) copy.update(data2[b'copy']) @@ -295,10 +290,10 @@ fullcopy.update(data2[b'fullcopy']) if dirtyc1: - copies._combinecopies(data2[b'incomplete'], data1[b'incomplete'], copy, diverge, + copies._combinecopies(data2[b'incomplete'], data1[b'incomplete'], copy, diverge, # pytype: disable=module-attr incompletediverge) else: - copies._combinecopies(data1[b'incomplete'], data2[b'incomplete'], copy, diverge, + copies._combinecopies(data1[b'incomplete'], data2[b'incomplete'], copy, diverge, # pytype: disable=module-attr incompletediverge) renamedelete = {} @@ -334,19 +329,19 @@ b'incompletediverge': bothincompletediverge } for f in bothnew: - copies._checkcopies(c1, c2, f, base, tca, dirtyc1, limit, both1) - copies._checkcopies(c2, c1, f, base, tca, dirtyc2, limit, both2) + copies._checkcopies(c1, c2, f, base, tca, dirtyc1, limit, both1) # pytype: disable=module-attr + copies._checkcopies(c2, c1, f, base, tca, dirtyc2, limit, both2) # pytype: disable=module-attr if dirtyc1 and dirtyc2: pass elif dirtyc1: # incomplete copies may only be found on the "dirty" side for bothnew assert not both2[b'incomplete'] - remainder = copies._combinecopies({}, both1[b'incomplete'], copy, bothdiverge, + remainder = copies._combinecopies({}, both1[b'incomplete'], copy, bothdiverge, # pytype: disable=module-attr bothincompletediverge) elif dirtyc2: assert not both1[b'incomplete'] - remainder = copies._combinecopies({}, both2[b'incomplete'], copy, bothdiverge, + remainder = copies._combinecopies({}, both2[b'incomplete'], copy, bothdiverge, # pytype: disable=module-attr bothincompletediverge) else: # incomplete copies and divergences can't happen outside grafts @@ -444,85 +439,14 @@ if not fixupstreamed: copies._fullcopytracing = fixedcopytracing -if not util.safehasattr(obsutil, "_succs"): - class _succs(list): - """small class to represent a successors with some metadata about it""" - - def __init__(self, *args, **kwargs): - super(_succs, self).__init__(*args, **kwargs) - self.markers = set() - - def copy(self): - new = _succs(self) - new.markers = self.markers.copy() - return new - - @util.propertycache - def _set(self): - # immutable - return set(self) - - def canmerge(self, other): - return self._set.issubset(other._set) -else: - from mercurial.obsutil import _succs - -def wrap_succs(succs): - """ Wrap old data format of successorsets (tuple) only if if's not yet a - _succs instance - """ - - if not util.safehasattr(succs, "markers"): - return _succs(succs) - else: - return succs - -if not util.safehasattr(obsutil, "markersdates"): - MARKERS_DATE_COMPAT = True -else: - MARKERS_DATE_COMPAT = False - -def markersdates(markers): - """returns the list of dates for a list of markers - """ - if MARKERS_DATE_COMPAT is False: - return obsutil.markersdates(markers) - - return [m[4] for m in markers] - -if not util.safehasattr(obsutil, "markersusers"): - MARKERS_USERS_COMPAT = True -else: - MARKERS_USERS_COMPAT = False - -def markersusers(markers): - """ Returns a sorted list of markers users without duplicates - """ - if MARKERS_USERS_COMPAT is False: - return obsutil.markersusers(markers) - - markersmeta = [dict(m[3]) for m in markers] - users = set(encoding.tolocal(meta[b'user']) for meta in markersmeta - if meta.get(b'user')) - - return sorted(users) - -if not util.safehasattr(obsutil, "markersoperations"): - MARKERS_OPERATIONS_COMPAT = True -else: - MARKERS_OPERATIONS_COMPAT = False - -def markersoperations(markers): - """ Returns a sorted list of markers operations without duplicates - """ - if MARKERS_OPERATIONS_COMPAT is False: - return obsutil.markersoperations(markers) - - markersmeta = [dict(m[3]) for m in markers] - operations = set(meta.get(b'operation') for meta in markersmeta - if meta.get(b'operation')) - - 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)
--- a/hgext3rd/evolve/evolvecmd.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/evolvecmd.py Sat Feb 01 12:50:10 2020 +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() @@ -123,43 +122,28 @@ ui.warn(_(b"cannot solve instability of %s, skipping\n") % orig) return (False, b".") 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(): - ui.debug(b"stabilize target %s is plain dead," - b" trying to stabilize on its parent\n" % - obs) - obs = obs.parents()[0] - newer = obsutil.successorssets(repo, obs.node()) - if len(newer) > 1: - msg = _(b"skipping %s: divergent rewriting. can't choose " - b"destination\n") % obs - ui.write_err(msg) - return (False, b".") - targets = newer[0] - assert targets - if len(targets) > 1: - # split target, figure out which one to pick, are they all in line? - targetrevs = [repo[r].rev() for r in targets] - roots = repo.revs(b'roots(%ld)', targetrevs) - heads = repo.revs(b'heads(%ld)', targetrevs) - if len(roots) > 1 or len(heads) > 1: - cheader = _(b"ancestor '%s' split over multiple topological" - b" branches.\nchoose an evolve destination:") % orig - selectedrev = utility.revselectionprompt(ui, repo, list(heads), - cheader) - if selectedrev is None: + try: + newer = utility._singlesuccessor(repo, obs) + # search of a parent which isn't the orig + while repo[newer].node() == orig.node(): + obs = obs.parents()[0] + newer = utility._singlesuccessor(repo, obs) + except utility.MultipleSuccessorsError as exc: + if exc.divergenceflag: + msg = _(b"skipping %s: divergent rewriting. can't choose " + b"destination\n") % obs + ui.write_err(msg) + return (False, b".") + if exc.splitflag: + splitsucc = utility.picksplitsuccessor(ui, repo, obs, orig) + if not splitsucc[0]: msg = _(b"could not solve instability, " b"ambiguous destination: " b"parent split across two branches\n") ui.write_err(msg) return (False, b".") - target = repo[selectedrev] - else: - target = repo[heads.first()] - else: - target = targets[0] - target = repo[target] + newer = splitsucc[1] + target = repo[newer] if not ui.quiet or confirm: repo.ui.write(_(b'move:'), label=b'evolve.operation') displayer.show(orig) @@ -179,8 +163,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 +222,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,))], @@ -300,17 +284,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() @@ -320,32 +296,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 @@ -364,6 +323,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 " @@ -375,32 +335,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(), @@ -428,32 +388,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 @@ -482,6 +441,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) @@ -502,19 +507,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() @@ -522,22 +534,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() @@ -545,9 +556,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: @@ -607,7 +620,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 @@ -635,68 +647,64 @@ obsolete.createmarkers(repo, [(otherdiv, (publicdiv,))], operation=b'evolve') return (True, publicnode) - try: - with repo.dirstate.parentchange(), compat.parentchange(repo): - 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(), compat.parentchange(repo): + 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 @@ -954,8 +962,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 @@ -1009,14 +1017,6 @@ with repo.dirstate.parentchange(), compat.parentchange(repo): repo.setparents(dest.node(), orig.node()) repo.dirstate.write(tr) - # fix up dirstate for copies and renames - if util.safehasattr(copies, 'graftcopies'): - copies.graftcopies(repo[None], dest, orig.p1()) - else: - # hg <= 5.2 (2f0a44c69e07) - 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) @@ -1032,16 +1032,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()) @@ -1050,7 +1048,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)) @@ -1059,7 +1057,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)) @@ -1544,7 +1542,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 @@ -1847,15 +1846,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] @@ -2029,13 +2042,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 @@ -2045,18 +2092,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 @@ -2141,7 +2189,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 @@ -2171,7 +2219,7 @@ pass else: with repo.dirstate.parentchange(), compat.parentchange(repo): - 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,
--- a/hgext3rd/evolve/exthelper.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/exthelper.py Sat Feb 01 12:50:10 2020 +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
--- a/hgext3rd/evolve/genericcaches.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/genericcaches.py Sat Feb 01 12:50:10 2020 +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.
--- a/hgext3rd/evolve/metadata.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/metadata.py Sat Feb 01 12:50:10 2020 +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.3.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 5.2 5.3' minimumhgversion = b'4.5' buglink = b'https://bz.mercurial-scm.org/'
--- a/hgext3rd/evolve/obsexchange.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/obsexchange.py Sat Feb 01 12:50:10 2020 +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 `::<heads> - ::<common>` - """ - 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"
--- a/hgext3rd/evolve/obshistory.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/obshistory.py Sat Feb 01 12:50:10 2020 +0100 @@ -42,6 +42,10 @@ item.default = True efd.clear() +@eh.extsetup +def addtouchnoise(ui): + obsutil.METABLACKLIST.append(re.compile(br'^__touch-noise__$')) + @eh.command( b'obslog|olog', [(b'G', b'graph', True, _(b"show the revision DAG")), @@ -50,7 +54,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,55 +90,47 @@ 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) revs.reverse() _debugobshistoryrevs(ui, repo, revs, opts) -def _successorsandmarkers(repo, ctx): - """compute the raw data needed for computing obsfate - Returns a list of dict, one dict per successors set - """ - ssets = obsutil.successorssets(repo, ctx.node(), closest=True) - - # closestsuccessors returns an empty list for pruned revisions, remap it - # into a list containing an empty list for future processing - if ssets == []: - ssets = [[]] - - # Try to recover pruned markers - succsmap = repo.obsstore.successors - fullsuccessorsets = [] # successor set + markers - for sset in ssets: - if sset: - fullsuccessorsets.append(compat.wrap_succs(sset)) - else: - # successorsset return an empty set() when ctx or one of its - # successors is pruned. - # In this case, walk the obs-markers tree again starting with ctx - # and find the relevant pruning obs-makers, the ones without - # successors. - # Having these markers allow us to compute some information about - # its fate, like who pruned this changeset and when. - - # XXX we do not catch all prune markers (eg rewritten then pruned) - # (fix me later) - foundany = False - for mark in succsmap.get(ctx.node(), ()): - if not mark[1]: - foundany = True - sset = compat._succs() - sset.markers.add(mark) - fullsuccessorsets.append(sset) - if not foundany: - fullsuccessorsets.append(compat._succs()) - - values = [] - for sset in fullsuccessorsets: - values.append({b'successors': sset, b'markers': sset.markers}) - - 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,23 +175,25 @@ succs = sorted(succs) for successor in succs: - _debugobshistorydisplaymarker(markerfm, successor, + _debugobshistorydisplaymarker(self.ui, markerfm, successor, ctx.node(), self.repo, self._includediff) else: - r = _successorsandmarkers(self.repo, ctx) + r = obsutil.successorsandmarkers(self.repo, ctx) + if r is None: + r = [] for succset in sorted(r): markers = succset[b"markers"] 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 +453,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 +477,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 +490,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,64 +509,29 @@ else: verb = b'rewritten' - fm.write(b'verb', b'%s', verb, - label=b"evolve.verb") - - effectflag = metadata.get(b'ef1') - if effectflag is not None: - try: - effectflag = int(effectflag) - except ValueError: - effectflag = None - if effectflag: - effect = [] + fm.data(verb=verb) - # XXX should be a dict - if effectflag & DESCCHANGED: - effect.append(b'description') - if effectflag & METACHANGED: - effect.append(b'meta') - if effectflag & USERCHANGED: - effect.append(b'user') - if effectflag & DATECHANGED: - effect.append(b'date') - if effectflag & BRANCHCHANGED: - effect.append(b'branch') - if effectflag & PARENTCHANGED: - effect.append(b'parent') - if effectflag & DIFFCHANGED: - effect.append(b'content') - - if effect: - fmteffect = fm.formatlist(effect, b'effect', sep=b', ') - fm.write(b'effect', b'(%s)', fmteffect) + effects = _markerseffects([marker]) + 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', ') - 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 +556,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 +573,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. @@ -638,48 +598,21 @@ fm.write(b'verb', b'%s', verb, label=b"evolve.verb") - # Effect flag - metadata = [dict(marker[3]) for marker in markers] - ef1 = [data.get(b'ef1') for data in metadata] - - effectflag = 0 - for ef in ef1: - if ef: - effectflag |= int(ef) - - if effectflag: - effect = [] - - # XXX should be a dict - if effectflag & DESCCHANGED: - effect.append(b'description') - if effectflag & METACHANGED: - effect.append(b'meta') - if effectflag & USERCHANGED: - effect.append(b'user') - if effectflag & DATECHANGED: - effect.append(b'date') - if effectflag & BRANCHCHANGED: - effect.append(b'branch') - if effectflag & PARENTCHANGED: - effect.append(b'parent') - if effectflag & DIFFCHANGED: - effect.append(b'content') - - if effect: - fmteffect = fm.formatlist(effect, b'effect', sep=b', ') - fm.write(b'effect', b'(%s)', fmteffect) + effects = _markerseffects(markers) + 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") # Operations - operations = compat.markersoperations(markers) + operations = obsutil.markersoperations(markers) if operations: fm.plain(b' using ') fm.write(b'operation', b'%s', b", ".join(operations), label=b"evolve.operation") @@ -687,13 +620,13 @@ fm.plain(b' by ') # Users - users = compat.markersusers(markers) + users = obsutil.markersusers(markers) fm.write(b'user', b'%s', b", ".join(users), label=b"evolve.user") fm.plain(b' ') # Dates - dates = compat.markersdates(markers) + dates = obsutil.markersdates(markers) if dates: min_date = min(dates) max_date = max(dates) @@ -732,15 +665,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,50 +684,21 @@ 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") -# logic around storing and using effect flags -DESCCHANGED = 1 << 0 # action changed the description -METACHANGED = 1 << 1 # action change the meta -PARENTCHANGED = 1 << 2 # action change the parent -DIFFCHANGED = 1 << 3 # action change diff introduced by the changeset -USERCHANGED = 1 << 4 # the user changed -DATECHANGED = 1 << 5 # the date changed -BRANCHCHANGED = 1 << 6 # the branch changed - -METABLACKLIST = [ - re.compile(br'^__touch-noise__$'), - re.compile(br'^branch$'), - re.compile(br'^.*-source$'), - re.compile(br'^.*_source$'), - re.compile(br'^source$'), -] - -def ismetablacklisted(metaitem): - """ Check that the key of a meta item (extrakey, extravalue) does not - match at least one of the blacklist pattern - """ - metakey = metaitem[0] - for pattern in METABLACKLIST: - if pattern.match(metakey): - return False - - return True - def _prepare_hunk(hunk): """Drop all information but the username and patch""" cleanunk = [] @@ -810,40 +717,14 @@ return None return _prepare_hunk(lines) -def _getobsfate(successorssets): - """ Compute a changeset obsolescence fate based on his successorssets. - Successors can be the tipmost ones or the immediate ones. - Returns one fate in the following list: - - pruned - - diverged - - superseed - - superseed_split - """ - - if len(successorssets) == 0: - # The commit has been pruned - return b'pruned' - elif len(successorssets) > 1: - return b'diverged' - else: - # No divergence, only one set of successors - successors = successorssets[0] - - if len(successors) == 1: - return b'superseed' - else: - return b'superseed_split' - -def _getobsfateandsuccs(repo, revnode, successorssets=None): +def _getobsfateandsuccs(repo, revnode): """ Return a tuple containing: - - the reason a revision is obsolete (diverged, pruned or superseed) + - the reason a revision is obsolete (diverged, pruned or superseded) - the list of successors short node if the revision is neither pruned or has diverged """ - if successorssets is None: - successorssets = obsutil.successorssets(repo, revnode) - - fate = _getobsfate(successorssets) + successorssets = obsutil.successorssets(repo, revnode) + fate = obsutil._getobsfate(successorssets) # Apply node.short if we have no divergence if len(successorssets) == 1: @@ -855,42 +736,66 @@ return (fate, successors) -def _successorsetdates(successorset, markers): - """returns the max date and the min date of the markers list - """ +EFFECTMAPPING = util.sortdict([ + (obsutil.DESCCHANGED, b'description'), + (obsutil.METACHANGED, b'meta'), + (obsutil.USERCHANGED, b'user'), + (obsutil.DATECHANGED, b'date'), + (obsutil.BRANCHCHANGED, b'branch'), + (obsutil.PARENTCHANGED, b'parent'), + (obsutil.DIFFCHANGED, b'content'), +]) - if not markers: - return {} - - dates = [m[4] for m in markers] +def _markerseffects(markers): + """ Return a list of effects as strings based on effect flags in markers - return { - b'min_date': min(dates), - b'max_date': max(dates) - } - -def _successorsetusers(successorset, markers): - """ Returns a sorted list of markers users without duplicates + Return None if verb cannot be more precise than just "rewritten", i.e. when + markers collectively have more than one effect in the flags. """ - if not markers: - return {} + metadata = [dict(marker[3]) for marker in markers] + ef1 = [data.get(b'ef1') for data in metadata] + effects = [] - # Check that user is present in meta - markersmeta = [dict(m[3]) for m in markers] - users = set(meta.get(b'user') for meta in markersmeta if meta.get(b'user')) + combined = 0 + for ef in ef1: + if ef: + combined |= int(ef) - return {b'users': sorted(users)} + if combined: + for key, value in EFFECTMAPPING.items(): + if combined & key: + effects.append(value) + + return effects VERBMAPPING = { - DESCCHANGED: b"reworded", - METACHANGED: b"meta-changed", - USERCHANGED: b"reauthored", - DATECHANGED: b"date-changed", - BRANCHCHANGED: b"branch-changed", - PARENTCHANGED: b"rebased", - DIFFCHANGED: b"amended" + obsutil.DESCCHANGED: b"reworded", + obsutil.METACHANGED: b"meta-changed", + obsutil.USERCHANGED: b"reauthored", + obsutil.DATECHANGED: b"date-changed", + obsutil.BRANCHCHANGED: b"branch-changed", + obsutil.PARENTCHANGED: b"rebased", + obsutil.DIFFCHANGED: b"amended" } +def _markerspreciseverb(markers): + """ Return a more precise verb based on effect flags in markers + + Return None if verb cannot be more precise than just "rewritten", i.e. when + markers collectively have more than one effect in the flags. + """ + metadata = [dict(marker[3]) for marker in markers] + ef1 = [data.get(b'ef1') for data in metadata] + + if all(ef1): + combined = 0 + for ef in ef1: + combined |= int(ef) + + # Combined will be in VERBMAPPING only if one bit is set + if combined in VERBMAPPING: + return VERBMAPPING[combined] + def _successorsetverb(successorset, markers): """ Return the verb summarizing the successorset """ @@ -898,19 +803,7 @@ if not successorset: verb = b'pruned' elif len(successorset) == 1: - # Check for effect flag - - metadata = [dict(marker[3]) for marker in markers] - ef1 = [data.get(b'ef1') for data in metadata] - - if all(ef1): - combined = 0 - for ef in ef1: - combined |= int(ef) - - # Combined will be in VERBMAPPING only of one bit is set - if combined in VERBMAPPING: - verb = VERBMAPPING[combined] + verb = _markerspreciseverb(markers) if verb is None: verb = b'rewritten' @@ -919,101 +812,6 @@ return {b'verb': verb} # Use a more advanced version of obsfateverb that uses effect-flag -if util.safehasattr(obsutil, 'obsfateverb'): - - @eh.wrapfunction(obsutil, 'obsfateverb') - def obsfateverb(orig, *args, **kwargs): - return _successorsetverb(*args, **kwargs)[b'verb'] - -# Hijack callers of successorsetverb -elif util.safehasattr(obsutil, 'obsfateprinter'): - - @eh.wrapfunction(obsutil, 'obsfateprinter') - def obsfateprinter(orig, successors, markers, ui): - - def closure(successors): - return _successorsetverb(successors, markers)[b'verb'] - - if not util.safehasattr(obsutil, 'successorsetverb'): - return orig(successors, markers, ui) - - # Save the old value - old = obsutil.successorsetverb - - try: - # Replace by own - obsutil.successorsetverb = closure - - # Call the orig - result = orig(successors, markers, ui) - - # And return result - return result - finally: - # Replace the old one - obsutil.successorsetverb = old - -FORMATSSETSFUNCTIONS = [ - _successorsetdates, - _successorsetusers, - _successorsetverb -] - -def successorsetallmarkers(successorset, pathscache): - """compute all successors of a successorset. - - pathscache must contains all successors starting from selected nodes - or revision. This way, iterating on each successor, we can take all - precursors and have the subgraph of all obsmarkers between roots to - successors. - """ - - markers = set() - seen = set() - - for successor in successorset: - stack = [successor] - - while stack: - element = stack.pop() - seen.add(element) - for prec, mark in pathscache.get(element, []): - if prec not in seen: - # Process element precursors - stack.append(prec) - - if mark not in markers: - markers.add(mark) - - return markers - -def preparesuccessorset(successorset, rawmarkers): - """ For a successor set, get all related markers, compute the set of user, - the min date and the max date - """ - hex = nodemod.hex - - successorset = [hex(n) for n in successorset] - - # hex the binary nodes in the markers - markers = [] - for m in rawmarkers: - hexprec = hex(m[0]) - hexsucs = tuple(hex(n) for n in m[1]) - hexparents = None - if m[5] is not None: - hexparents = tuple(hex(n) for n in m[5]) - newmarker = (hexprec, hexsucs) + m[2:5] + (hexparents,) + m[6:] - markers.append(newmarker) - - # Format basic data - data = { - b"successors": sorted(successorset), - b"markers": sorted(markers) - } - - # Call an extensible list of functions to override or add new data - for function in FORMATSSETSFUNCTIONS: - data.update(function(successorset, markers)) - - return data +@eh.wrapfunction(obsutil, 'obsfateverb') +def obsfateverb(orig, *args, **kwargs): + return _successorsetverb(*args, **kwargs)[b'verb']
--- a/hgext3rd/evolve/rewind.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/rewind.py Sat Feb 01 12:50:10 2020 +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
--- a/hgext3rd/evolve/rewriteutil.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/rewriteutil.py Sat Feb 01 12:50:10 2020 +0100 @@ -21,7 +21,7 @@ lock as lockmod, node, obsolete, - phases, + obsutil, revset, util, ) @@ -76,6 +76,31 @@ msg %= (action, len(newunstable)) hint = _(b"see 'hg help evolution.instability'") raise error.Abort(msg, hint=hint) + divrisk = revs_hascontentdivrisk(repo, revs) + allowdivergence = repo.ui.configbool(b'experimental', + b'evolution.allowdivergence') + if divrisk and not allowdivergence: + localdiv = repo[divrisk[0]] + otherdiv, base = repo[divrisk[1][0]], repo[divrisk[1][1]] + msg = _(b"%s of %s creates content-divergence " + b"with %s") % (action, localdiv, otherdiv) + if localdiv.rev() != base.rev(): + msg += _(b', from %s') % base + hint = _(b"add --verbose for details or see " + b"'hg help evolution.instability'") + if repo.ui.verbose: + if localdiv.rev() != base.rev(): + msg += _(b'\n changeset %s is an evolution of ' + b'changeset %s') % (localdiv, base) + msg += _(b'\n changeset %s already have a successors as ' + b'changeset %s\n' + b' rewriting changeset %s would create ' + b'"content-divergence"\n' + b' set experimental.evolution.allowdivergence=True to ' + b'overwrite this check') % (base, otherdiv, localdiv) + hint = _(b"see 'hg help evolution.instability' for details " + b"on content-divergence") + raise error.Abort(msg, hint=hint) def bookmarksupdater(repo, oldid, tr): """Return a callable update(newid) updating the current bookmark @@ -88,6 +113,14 @@ repo._bookmarks.applychanges(repo, tr, bmchanges) return updatebookmarks +def revs_hascontentdivrisk(repo, revs): + obsrevs = repo.revs(b'%ld and obsolete()', revs) + for r in obsrevs: + div = precheck_contentdiv(repo, repo[r]) + if div: + return [r, div] + return [] + def disallowednewunstable(repo, revs): """Check that editing <revs> will not create disallowed unstable @@ -105,9 +138,6 @@ if len(roots) > 1: raise error.Abort(_(b"cannot fold non-linear revisions " b"(multiple roots given)")) - root = repo[roots.first()] - if root.phase() <= phases.public: - raise error.Abort(_(b"cannot fold public revisions")) heads = repo.revs(b'heads(%ld)', revs) if len(heads) > 1: raise error.Abort(_(b"cannot fold non-linear revisions " @@ -124,6 +154,7 @@ hint = _(b'set experimental.evolution.allowdivergence=yes' b' to allow folding them') raise error.Abort(msg, hint=hint) + root = repo[roots.first()] # root's p1 is already used as the target ctx p1 baseparents -= {root.p1().rev()} p2 = repo[baseparents.first()] @@ -254,3 +285,31 @@ return newid, created finally: lockmod.release(tr, lock, wlock) + +def precheck_contentdiv(repo, ctx): + """return divergent revision if rewriting an obsolete cset (ctx) will + create divergence""" + # We need to check two cases that can cause divergence: + # case 1: the rev being rewritten has a non-obsolete successor (easily + # detected by successorssets) + divergent = [] # contains [divergent_cset, common_precursor] + sset = obsutil.successorssets(repo, ctx.node()) + nodivergencerisk = (len(sset) == 0 + or (len(sset) == 1 + and len(sset[0]) == 1 + and repo[sset[0][0]].rev() == ctx.rev() + )) + if nodivergencerisk: + # case 2: one of the precursors of the rev being revived has a + # non-obsolete successor (we need divergentsets for this) + from . import evolvecmd + divsets = evolvecmd.divergentsets(repo, ctx) + if divsets: + nsuccset = divsets[0][b'divergentnodes'] + divergent.append(nsuccset[0]) + prec = divsets[0][b'commonprecursor'] + divergent.append(prec) + else: + divergent.append(sset[0][0]) + divergent.append(ctx.node()) + return divergent
--- a/hgext3rd/evolve/templatekw.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/templatekw.py Sat Feb 01 12:50:10 2020 +0100 @@ -11,7 +11,6 @@ from . import ( error, exthelper, - obshistory ) from mercurial import ( @@ -24,7 +23,7 @@ ### template keywords if util.safehasattr(templatekw, 'compatlist'): - @eh.templatekeyword(b'instabilities', requires=set([b'ctx', b'templ'])) + @eh.templatekeyword(b'instabilities', requires={b'ctx', b'templ'}) def showinstabilities(context, mapping): """List of strings. Evolution instabilities affecting the changeset (zero or more of "orphan", "content-divergent" or "phase-divergent").""" @@ -33,7 +32,7 @@ ctx.instabilities(), plural=b'instabilities') - @eh.templatekeyword(b'troubles', requires=set([b'ctx', b'templ'])) + @eh.templatekeyword(b'troubles', requires={b'ctx', b'templ'}) def showtroubles(context, mapping): # legacy name for instabilities ctx = context.resource(mapping, b'ctx') return templatekw.compatlist(context, mapping, b'trouble', @@ -87,192 +86,6 @@ except error.Abort: # no easy way to avoid ui raising Abort here :-/ return None -def obsfatedefaulttempl(ui): - """ Returns a dict with the default templates for obs fate - """ - # Prepare templates - verbtempl = b'{verb}' - usertempl = b'{if(users, " by {join(users, ", ")}")}' - succtempl = b'{if(successors, " as ")}{successors}' # Bypass if limitation - datetempleq = b' (at {min_date|isodate})' - datetemplnoteq = b' (between {min_date|isodate} and {max_date|isodate})' - datetempl = b'{if(max_date, "{ifeq(min_date, max_date, "%s", "%s")}")}' % (datetempleq, datetemplnoteq) - - optionalusertempl = usertempl - username = _getusername(ui) - if username is not None: - optionalusertempl = (b'{ifeq(join(users, "\0"), "%s", "", "%s")}' - % (username, usertempl)) - - # Assemble them - return { - b'obsfate_quiet': verbtempl + succtempl, - b'obsfate': verbtempl + succtempl + optionalusertempl, - b'obsfate_verbose': verbtempl + succtempl + usertempl + datetempl, - } - -def obsfatedata(repo, ctx): - """compute the raw data needed for computing obsfate - Returns a list of dict - """ - if not ctx.obsolete(): - return None - - successorssets, pathcache = closestsuccessors(repo, ctx.node()) - - # closestsuccessors returns an empty list for pruned revisions, remap it - # into a list containing en empty list for future processing - if successorssets == []: - successorssets = [[]] - - succsmap = repo.obsstore.successors - fullsuccessorsets = [] # successor set + markers - for sset in successorssets: - if sset: - markers = obshistory.successorsetallmarkers(sset, pathcache) - fullsuccessorsets.append((sset, markers)) - else: - # XXX we do not catch all prune markers (eg rewritten then pruned) - # (fix me later) - foundany = False - for mark in succsmap.get(ctx.node(), ()): - if not mark[1]: - foundany = True - fullsuccessorsets.append((sset, [mark])) - if not foundany: - fullsuccessorsets.append(([], [])) - - values = [] - for sset, rawmarkers in fullsuccessorsets: - raw = obshistory.preparesuccessorset(sset, rawmarkers) - values.append(raw) - - return values - -def obsfatelineprinter(obsfateline, ui): - quiet = ui.quiet - verbose = ui.verbose - normal = not verbose and not quiet - - # Build the line step by step - line = [] - - # Verb - line.append(obsfateline[b'verb']) - - # Successors - successors = obsfateline[b"successors"] - - if successors: - fmtsuccessors = map(lambda s: s[:12], successors) - line.append(b" as %s" % b", ".join(fmtsuccessors)) - - # Users - if (verbose or normal) and b'users' in obsfateline: - users = obsfateline[b'users'] - - if not verbose: - # If current user is the only user, do not show anything if not in - # verbose mode - username = _getusername(ui) - if len(users) == 1 and users[0] == username: - users = None - - if users: - line.append(b" by %s" % b", ".join(users)) - - # Date - if verbose: - min_date = obsfateline[b'min_date'] - max_date = obsfateline[b'max_date'] - - if min_date == max_date: - fmtmin_date = util.datestr(min_date, b'%Y-%m-%d %H:%M %1%2') - line.append(b" (at %s)" % fmtmin_date) - else: - fmtmin_date = util.datestr(min_date, b'%Y-%m-%d %H:%M %1%2') - fmtmax_date = util.datestr(max_date, b'%Y-%m-%d %H:%M %1%2') - line.append(b" (between %s and %s)" % (fmtmin_date, fmtmax_date)) - - return b"".join(line) - -def obsfateprinter(obsfate, ui, prefix=b""): - lines = [] - for raw in obsfate: - lines.append(obsfatelineprinter(raw, ui)) - - if prefix: - lines = [prefix + line for line in lines] - - return b"\n".join(lines) - -if not util.safehasattr(templatekw, 'obsfateverb'): # <= hg-4.5 - @eh.templatekeyword(b"obsfatedata") - def showobsfatedata(repo, ctx, **args): - # Get the needed obsfate data - values = obsfatedata(repo, ctx) - - if values is None: - return templatekw.showlist(b"obsfatedata", [], args) - - return _showobsfatedata(repo, ctx, values, **args) - -def _showobsfatedata(repo, ctx, values, **args): - - # Format each successorset successors list - for raw in values: - # As we can't do something like - # "{join(map(nodeshort, successors), ', '}" in template, manually - # create a correct textual representation - gen = b', '.join(n[:12] for n in raw[b'successors']) - - makemap = lambda x: {b'successor': x} - joinfmt = lambda d: b"%s" % d[b'successor'] - raw[b'successors'] = templatekw._hybrid(gen, raw[b'successors'], makemap, - joinfmt) - - # And then format them - # Insert default obsfate templates - args[b'templ'].cache.update(obsfatedefaulttempl(repo.ui)) - - if repo.ui.quiet: - name = b"obsfate_quiet" - elif repo.ui.verbose: - name = b"obsfate_verbose" - elif repo.ui.debugflag: - name = b"obsfate_debug" - else: - name = b"obsfate" - - # Format a single value - def fmt(d): - nargs = args.copy() - nargs.update(d[name]) - templ = args[b'templ'] - # HG 4.6 - if hasattr(templ, "generate"): - return templ.generate(name, nargs) - else: - return args[b'templ'](name, **nargs) - - # Generate a good enough string representation using templater - gen = [] - for d in values: - chunk = fmt({name: d}) - chunkstr = [] - - # Empty the generator - try: - while True: - chunkstr.append(next(chunk)) - except StopIteration: - pass - - gen.append(b"".join(chunkstr)) - gen = b"; ".join(gen) - - return templatekw._hybrid(gen, values, lambda x: {name: x}, fmt) - # copy from mercurial.obsolete with a small change to stop at first known changeset. def directsuccessorssets(repo, initialnode, cache=None):
--- a/hgext3rd/evolve/utility.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/evolve/utility.py Sat Feb 01 12:50:10 2020 +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 @@ -85,6 +75,8 @@ def __init__(self, successorssets): self.successorssets = successorssets + self.divergenceflag = len(successorssets) > 1 + self.splitflag = len(successorssets[0]) > 1 def builddependencies(repo, revs): """returns dependency graphs giving an order to solve instability of revs @@ -126,13 +118,41 @@ 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) return repo[newer[0][0]].rev() +def picksplitsuccessor(ui, repo, ctx, evolvecand): + """choose a successor of ctx from split targets + + Choose highest one if all successors are in a topological branch. And if + they are split over multiple topological branches, we ask user to choose + an evolve destination. + + Return (True, succ) unless split targets are split over multiple + topological branches and user didn't choose any evolve destination, + in which case return (False, '.') + """ + targets = obsutil.successorssets(repo, ctx.node())[0] + assert targets + targetrevs = [repo[r].rev() for r in targets] + roots = repo.revs(b'roots(%ld)', targetrevs) + heads = repo.revs(b'heads(%ld)', targetrevs) + if len(roots) > 1 or len(heads) > 1: + cheader = (_(b"ancestor '%s' split over multiple topological" + b" branches.\nchoose an evolve destination:") % + evolvecand) + selectedrev = revselectionprompt(ui, repo, list(heads), cheader) + if selectedrev is None: + return (False, '.') + succ = repo[selectedrev] + else: + succ = repo[heads.first()] + return (True, repo[succ].rev()) + def _successorrevs(repo, ctx): try: return {_singlesuccessor(repo, ctx)}
--- a/hgext3rd/pullbundle.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/pullbundle.py Sat Feb 01 12:50:10 2020 +0100 @@ -87,6 +87,7 @@ node as nodemod, registrar, scmutil, + ui as uimod, util, ) @@ -508,7 +509,7 @@ if 1 < min_cache: repo.ui.write(b" not caching ranges smaller than %d changesets\n" % min_cache) for i in range(count): - repo.ui.progress(b'gathering data', i, total=count) + progress(repo.ui, b'gathering data', i, total=count) outgoing = takeonesample(repo, actionrevs) ranges = sliceoutgoing(repo, outgoing) hitranges = 0 @@ -532,7 +533,7 @@ hitranges, ) pullstats.append(stats) - repo.ui.progress(b'gathering data', None) + progress(repo.ui, b'gathering data', None) sizes = [] changesmissing = [] @@ -591,6 +592,7 @@ def takeonesample(repo, revs): node = repo.changelog.node + revs = list(revs) pulled = random.sample(revs, max(4, len(revs) // 1000)) pulled = repo.revs(b'%ld::%ld', pulled, pulled) nodes = [node(r) for r in pulled] @@ -610,19 +612,32 @@ b'max': data[-1], } -STATSFORMAT = b"""{name}: - min: {min} - 10%: {10%} - 25%: {25%} - 50%: {50%} - 75%: {75%} - 90%: {90%} - 95%: {95%} - max: {max} +STATSFORMAT = b"""%(name)s: + min: %(min)r + 10%%: %(10%)r + 25%%: %(25%)r + 50%%: %(50%)r + 75%%: %(75%)r + 90%%: %(90%)r + 95%%: %(95%)r + max: %(max)r """ def fmtdist(name, data): - return STATSFORMAT.format(name=name, **data) + data[b'name'] = name + return STATSFORMAT % data + +# hg <= 4.6 (bec1212eceaa) +if util.safehasattr(uimod.ui, 'makeprogress'): + def progress(ui, topic, pos, item=b"", unit=b"", total=None): + progress = ui.makeprogress(topic, unit, total) + if pos is not None: + progress.update(pos, item=item) + else: + progress.complete() +else: + def progress(ui, topic, pos, item=b"", unit=b"", total=None): + ui.progress(topic, pos, item, unit, total) # nodemap.get and index.[has_node|rev|get_rev] # hg <= 5.3 (02802fa87b74)
--- a/hgext3rd/serverminitopic.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/serverminitopic.py Sat Feb 01 12:50:10 2020 +0100 @@ -23,10 +23,11 @@ util, ) +# hg <= 4.5 (b4d85bc122bd) try: - from mercurial import wireproto + from mercurial import wireproto # pytype: disable=import-error wireproto.branchmap -except ImportError: # <= hg-4.5 +except ImportError: from mercurial import wireprotov1server as wireproto if util.safehasattr(registrar, 'configitem'):
--- a/hgext3rd/topic/__init__.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/topic/__init__.py Sat Feb 01 12:50:10 2020 +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.3.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 5.2 5.3' 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:
--- a/hgext3rd/topic/compat.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/topic/compat.py Sat Feb 01 12:50:10 2020 +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):
--- a/hgext3rd/topic/discovery.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/topic/discovery.py Sat Feb 01 12:50:10 2020 +0100 @@ -17,10 +17,11 @@ compat, ) +# hg <= 4.5 (b4d85bc122bd) try: - from mercurial import wireproto + from mercurial import wireproto # pytype: disable=import-error wireproto.branchmap -except (AttributeError, ImportError): # <= hg-4.5 +except (AttributeError, ImportError): from mercurial import wireprotov1server as wireproto def _headssummary(orig, pushop, *args, **kwargs):
--- a/hgext3rd/topic/evolvebits.py Fri Jan 31 14:50:37 2020 +0100 +++ b/hgext3rd/topic/evolvebits.py Sat Feb 01 12:50:10 2020 +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
--- a/tests/test-amend.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-amend.t Sat Feb 01 12:50:10 2020 +0100 @@ -121,6 +121,9 @@ update: (current) phases: 3 draft +setting the user after we have performed the test with no username + $ HGUSER=test + Check the help $ hg amend -h hg amend [OPTION]... [FILE]... @@ -170,3 +173,63 @@ $ hg amend --patch --extract abort: cannot use both --patch and --extract [255] + + $ cd .. + +Check the pre-check logic for content-divergence + $ hg init precheckrepo + $ cd precheckrepo + $ echo a > a + $ hg ci -Am "added a" + adding a + $ echo newchanges > a + $ hg amend + $ hg up 0 --hidden -q + updated to hidden changeset 9092f1db7931 + (hidden revision '9092f1db7931' was rewritten as: aafaf407b00d) + working directory parent is obsolete! (9092f1db7931) + +when rewritting an already rewritten changeset (i.e cset being rewritten will +be the base of divergence) + $ hg amend -m "i am gonna create divergence" + abort: amend of 9092f1db7931 creates content-divergence with aafaf407b00d + (add --verbose for details or see 'hg help evolution.instability') + [255] + $ hg amend -m "i am gonna create divergence" --verbose + abort: amend of 9092f1db7931 creates content-divergence with aafaf407b00d + changeset 9092f1db7931 already have a successors as changeset aafaf407b00d + rewriting changeset 9092f1db7931 would create "content-divergence" + set experimental.evolution.allowdivergence=True to overwrite this check + (see 'hg help evolution.instability' for details on content-divergence) + [255] + +when rewritting a cset which has a predecessor with non-obsolete successor + +to prepare the repo +1) create content-divergence +2) remove divergence by pruning one of the divergent cset + $ echo edited_a > a + $ hg ci -m "edited a" + 1 new orphan changesets + $ hg debugobsolete $(hg id -ir 0 --debug) $(hg id -ir 2 --debug) + 1 new obsolescence markers + 2 new content-divergent changesets + +remove divergence by pruning one side of divergenence + $ hg debugobsolete $(hg id -ir 2 --debug) + 1 new obsolescence markers + obsoleted 1 changesets + + $ hg evolve -l + $ hg amend -m "i am gonna create divergence" + abort: amend of f8c05838af90 creates content-divergence with aafaf407b00d, from 9092f1db7931 + (add --verbose for details or see 'hg help evolution.instability') + [255] + $ hg amend -m "i am gonna create divergence" --verbose + abort: amend of f8c05838af90 creates content-divergence with aafaf407b00d, from 9092f1db7931 + changeset f8c05838af90 is an evolution of changeset 9092f1db7931 + changeset 9092f1db7931 already have a successors as changeset aafaf407b00d + rewriting changeset f8c05838af90 would create "content-divergence" + set experimental.evolution.allowdivergence=True to overwrite this check + (see 'hg help evolution.instability' for details on content-divergence) + [255]
--- a/tests/test-evolve-content-divergent-basic.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-content-divergent-basic.t Sat Feb 01 12:50:10 2020 +0100 @@ -21,6 +21,8 @@ > unified = 0 > [ui] > logtemplate = {rev}:{node|short}@{branch}({phase}) {desc|firstline} [{instabilities}]\n + > [experimental] + > evolution.allowdivergence = True > [extensions] > EOF $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
--- a/tests/test-evolve-content-divergent-corner-cases.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-content-divergent-corner-cases.t Sat Feb 01 12:50:10 2020 +0100 @@ -21,6 +21,8 @@ > unified = 0 > [ui] > logtemplate = {rev}:{node|short}@{branch}({phase}) {desc|firstline} [{instabilities}]\n + > [experimental] + > evolution.allowdivergence = True > [extensions] > EOF $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
--- a/tests/test-evolve-content-divergent-first-changeset.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-content-divergent-first-changeset.t Sat Feb 01 12:50:10 2020 +0100 @@ -1,6 +1,11 @@ $ . $TESTDIR/testlib/pythonpath.sh - $ echo "[extensions]" >> $HGRCPATH - $ echo "evolve=" >> $HGRCPATH + $ cat >> $HGRCPATH << EOF + > [extensions] + > evolve= + > [experimental] + > evolution.allowdivergence = True + > EOF + This test file tests the case of content-divergence resolution of changesets that have the null revision as the parent.
--- a/tests/test-evolve-content-divergent-interrupted.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-content-divergent-interrupted.t Sat Feb 01 12:50:10 2020 +0100 @@ -24,6 +24,8 @@ > publish = False > [alias] > glog = log -GT "{rev}:{node|short} {desc}\n ({bookmarks}) {phase}" + > [experimental] + > evolution.allowdivergence = True > [extensions] > EOF $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
--- a/tests/test-evolve-content-divergent-meta.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-content-divergent-meta.t Sat Feb 01 12:50:10 2020 +0100 @@ -12,8 +12,11 @@ > glog = log -GT "{rev}:{node|short} {desc|firstline}\n {phase} {instabilities}\n\n" > [phases] > publish = False + > [experimental] + > evolution.allowdivergence = True > [extensions] > rebase = + > strip = > EOF $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH @@ -157,3 +160,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 ..
--- a/tests/test-evolve-content-divergent-stack.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-content-divergent-stack.t Sat Feb 01 12:50:10 2020 +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)
--- a/tests/test-evolve-continue.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-continue.t Sat Feb 01 12:50:10 2020 +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
--- a/tests/test-evolve-cycles.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-cycles.t Sat Feb 01 12:50:10 2020 +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" } ]
--- a/tests/test-evolve-issue5958.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-issue5958.t Sat Feb 01 12:50:10 2020 +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:
--- a/tests/test-evolve-obshistory-amend-then-fold.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-obshistory-amend-then-fold.t Sat Feb 01 12:50:10 2020 +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" } ]
--- a/tests/test-evolve-obshistory-amend.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-obshistory-amend.t Sat Feb 01 12:50:10 2020 +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) +
--- a/tests/test-evolve-obshistory-content-divergent.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-obshistory-content-divergent.t Sat Feb 01 12:50:10 2020 +0100 @@ -5,6 +5,10 @@ ============ $ . $TESTDIR/testlib/obshistory_setup.sh + $ cat >> $HGRCPATH << EOF + > [experimental] + > evolution.allowdivergence = True + > EOF Test output with content-divergence =================================== @@ -129,12 +133,12 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "description" ], "operation": "amend", "succnodes": [ - "65b757b745b9" + "65b757b745b935093c87a2bccd877521cccffcbd" ], "user": "test", "verb": "rewritten" @@ -144,19 +148,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 +287,7 @@ [ { "markers": [], - "node": "65b757b745b9", - "rev": 3, + "node": "65b757b745b935093c87a2bccd877521cccffcbd", "shortdescription": "A2" }, { @@ -295,12 +297,12 @@ *, (glob) 0 (glob) ], - "effect": [ + "effects": [ "description" ], "operation": "amend", "succnodes": [ - "65b757b745b9" + "65b757b745b935093c87a2bccd877521cccffcbd" ], "user": "test", "verb": "rewritten" @@ -310,25 +312,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" } ]
--- a/tests/test-evolve-obshistory-fold.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-obshistory-fold.t Sat Feb 01 12:50:10 2020 +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" } ]
--- a/tests/test-evolve-obshistory-lots-of-splits.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-obshistory-lots-of-splits.t Sat Feb 01 12:50:10 2020 +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" } ]
--- a/tests/test-evolve-obshistory-phase-divergent.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-obshistory-phase-divergent.t Sat Feb 01 12:50:10 2020 +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" } ]
--- a/tests/test-evolve-obshistory-prune.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-obshistory-prune.t Sat Feb 01 12:50:10 2020 +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" } ]
--- a/tests/test-evolve-obshistory-split.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-obshistory-split.t Sat Feb 01 12:50:10 2020 +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) +
--- a/tests/test-evolve-obshistory.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-obshistory.t Sat Feb 01 12:50:10 2020 +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
--- a/tests/test-evolve-order.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-order.t Sat Feb 01 12:50:10 2020 +0100 @@ -15,6 +15,8 @@ > unified = 0 > [ui] > logtemplate = {rev}:{node|short}@{branch}({phase}) {desc|firstline}\n + > [experimental] + > evolution.allowdivergence = True > [extensions] > EOF $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
--- a/tests/test-evolve-orphan-merge.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-orphan-merge.t Sat Feb 01 12:50:10 2020 +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 @@ -529,28 +518,19 @@ case where merge commit becomes orphan with its ancestors pruned up until a point where the other parent of merge is the first non-pruned ancestor. -Note: allowing an empty commit here to have the same output on all hg versions. -In newer versions or Mercurial this command would not create a new commit. -hg <= 5.2 (32d11a23c9cf) - - $ hg evolve -r . --config ui.allowemptycommit=true + $ hg evolve -r . move:[28] merged l and x atop:[0] added hgignore - working directory is now at * (glob) + evolution of 28:fb8fe870ae7d created no changes to commit + working directory is now at 8fa14d15e168 $ hg glog - @ 29:* merged l and x (glob) - | () 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 @@ -564,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 @@ -576,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 @@ -596,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
--- a/tests/test-evolve-public-content-divergent-corner-cases.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-public-content-divergent-corner-cases.t Sat Feb 01 12:50:10 2020 +0100 @@ -12,6 +12,8 @@ > glog = log -GT "{rev}:{node|short} {desc|firstline}\n {phase} {instabilities}\n\n" > [phases] > publish = False + > [experimental] + > evolution.allowdivergence = True > [extensions] > rebase = > EOF
--- a/tests/test-evolve-public-content-divergent-discard.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-public-content-divergent-discard.t Sat Feb 01 12:50:10 2020 +0100 @@ -17,6 +17,8 @@ > glog = log -GT "{rev}:{node|short} {desc|firstline}\n {phase} {instabilities}\n\n" > [phases] > publish = False + > [experimental] + > evolution.allowdivergence = True > [extensions] > rebase = > EOF
--- a/tests/test-evolve-public-content-divergent-main.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-public-content-divergent-main.t Sat Feb 01 12:50:10 2020 +0100 @@ -15,6 +15,8 @@ > glog = log -GT "{rev}:{node|short} {desc|firstline}\n {phase} {instabilities}\n\n" > [phases] > publish = False + > [experimental] + > evolution.allowdivergence = True > [extensions] > rebase = > EOF
--- a/tests/test-evolve-templates.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-evolve-templates.t Sat Feb 01 12:50:10 2020 +0100 @@ -1,4 +1,4 @@ -This test file test the various templates for precursors and successors. +This test file test the various templates for predecessors and successors. Global setup ============ @@ -9,12 +9,14 @@ > interactive = true > [phases] > publish=False + > [experimental] + > evolution.allowdivergence = True > [extensions] > evolve = > [alias] > tlog = log -G -T '{node|short}\ - > {if(precursors, "\n Precursors: {precursors}")}\ - > {if(precursors, "\n semi-colon: {join(precursors, "; ")}")}\ + > {if(predecessors, "\n Predecessors: {predecessors}")}\ + > {if(predecessors, "\n semi-colon: {join(predecessors, "; ")}")}\ > {if(successors, "\n Successors: {successors}")}\ > {if(successors, "\n semi-colon: {join(successors, "; ")}")}\ > {if(obsfate, "\n Fate: {join(obsfate, "\n Fate: ")}\n")}\n' @@ -69,7 +71,7 @@ working directory parent is obsolete! (471f378eab4c) (use 'hg evolve' to update to its successor: d004c8f274b9) -Precursors template should show current revision as it is the working copy +Predecessors template should show current revision as it is the working copy $ hg olog tip o d004c8f274b9 (3) A2 | @@ -81,7 +83,7 @@ $ hg tlog o d004c8f274b9 - | Precursors: 1:471f378eab4c + | Predecessors: 1:471f378eab4c | semi-colon: 1:471f378eab4c | @ 471f378eab4c |/ Successors: 3:d004c8f274b9 @@ -139,7 +141,7 @@ (check json) - $ hg log -GT '{precursors|json}\n' + $ hg log -GT '{predecessors|json}\n' o ["471f378eab4c5e25f6c77f785b27c936efb22874"] | | @ [] @@ -162,10 +164,10 @@ working directory parent is obsolete! (a468dc9b3633) (use 'hg evolve' to update to its successor: d004c8f274b9) -Precursors template should show current revision as it is the working copy +Predecessors template should show current revision as it is the working copy $ hg tlog o d004c8f274b9 - | Precursors: 2:a468dc9b3633 + | Predecessors: 2:a468dc9b3633 | semi-colon: 2:a468dc9b3633 | @ a468dc9b3633 |/ Successors: 3:d004c8f274b9 @@ -174,14 +176,14 @@ | o ea207398892e -Precursors template should show the precursor as we force its display with +Predecessors template should show the precursor as we force its display with --hidden $ hg tlog --hidden o d004c8f274b9 - | Precursors: 2:a468dc9b3633 + | Predecessors: 2:a468dc9b3633 | semi-colon: 2:a468dc9b3633 | @ a468dc9b3633 - |/ Precursors: 1:471f378eab4c + |/ Predecessors: 1:471f378eab4c | semi-colon: 1:471f378eab4c | Successors: 3:d004c8f274b9 | semi-colon: 3:d004c8f274b9 @@ -211,10 +213,10 @@ $ hg tlog --hidden @ d004c8f274b9 - | Precursors: 2:a468dc9b3633 + | Predecessors: 2:a468dc9b3633 | semi-colon: 2:a468dc9b3633 | x a468dc9b3633 - |/ Precursors: 1:471f378eab4c + |/ Predecessors: 1:471f378eab4c | semi-colon: 1:471f378eab4c | Successors: 3:d004c8f274b9 | semi-colon: 3:d004c8f274b9 @@ -343,13 +345,13 @@ working directory parent is obsolete! (471597cad322) (use 'hg evolve' to update to its tipmost successor: 337fec4d2edc, f257fde29c7a) -Precursors template should show current revision as it is the working copy +Predecessors template should show current revision as it is the working copy $ hg tlog o f257fde29c7a - | Precursors: 1:471597cad322 + | Predecessors: 1:471597cad322 | semi-colon: 1:471597cad322 o 337fec4d2edc - | Precursors: 1:471597cad322 + | Predecessors: 1:471597cad322 | semi-colon: 1:471597cad322 | @ 471597cad322 |/ Successors: 2:337fec4d2edc 3:f257fde29c7a @@ -372,7 +374,7 @@ $ hg up f257fde29c7a 0 files updated, 0 files merged, 0 files removed, 0 files unresolved -Precursors template should not show a precursor as it's not displayed in the +Predecessors template should not show a precursor as it's not displayed in the log $ hg tlog @ f257fde29c7a @@ -381,14 +383,14 @@ | o ea207398892e -Precursors template should show the precursor as we force its display with +Predecessors template should show the precursor as we force its display with --hidden $ hg tlog --hidden @ f257fde29c7a - | Precursors: 1:471597cad322 + | Predecessors: 1:471597cad322 | semi-colon: 1:471597cad322 o 337fec4d2edc - | Precursors: 1:471597cad322 + | Predecessors: 1:471597cad322 | semi-colon: 1:471597cad322 | x 471597cad322 |/ Successors: 2:337fec4d2edc 3:f257fde29c7a @@ -474,10 +476,10 @@ working directory parent is obsolete! (471f378eab4c) (use 'hg evolve' to update to its successor: eb5a0daa2192) -Precursors template should show current revision as it is the working copy +Predecessors template should show current revision as it is the working copy $ hg tlog o eb5a0daa2192 - | Precursors: 1:471f378eab4c + | Predecessors: 1:471f378eab4c | semi-colon: 1:471f378eab4c | @ 471f378eab4c |/ Successors: 3:eb5a0daa2192 @@ -501,11 +503,11 @@ working directory parent is obsolete! (0dec01379d3b) (use 'hg evolve' to update to its successor: eb5a0daa2192) -Precursors template should show both precursors as they should be both +Predecessors template should show both predecessors as they should be both displayed $ hg tlog o eb5a0daa2192 - | Precursors: 2:0dec01379d3b 1:471f378eab4c + | Predecessors: 2:0dec01379d3b 1:471f378eab4c | semi-colon: 2:0dec01379d3b; 1:471f378eab4c | @ 0dec01379d3b | | Successors: 3:eb5a0daa2192 @@ -534,18 +536,18 @@ $ hg up 'desc(C0)' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved -Precursors template should not show precursors as it's not displayed in the +Predecessors template should not show predecessors as it's not displayed in the log $ hg tlog @ eb5a0daa2192 | o ea207398892e -Precursors template should show both precursors as we force its display with +Predecessors template should show both predecessors as we force its display with --hidden $ hg tlog --hidden @ eb5a0daa2192 - | Precursors: 2:0dec01379d3b 1:471f378eab4c + | Predecessors: 2:0dec01379d3b 1:471f378eab4c | semi-colon: 2:0dec01379d3b; 1:471f378eab4c | x 0dec01379d3b | | Successors: 3:eb5a0daa2192 @@ -649,13 +651,13 @@ working directory parent is obsolete! (471f378eab4c) (471f378eab4c has diverged, use 'hg evolve --list --content-divergent' to resolve the issue) -Precursors template should show current revision as it is the working copy +Predecessors template should show current revision as it is the working copy $ hg tlog * 019fadeab383 - | Precursors: 1:471f378eab4c + | Predecessors: 1:471f378eab4c | semi-colon: 1:471f378eab4c | * fdf9bde5129a - |/ Precursors: 1:471f378eab4c + |/ Predecessors: 1:471f378eab4c | semi-colon: 1:471f378eab4c | @ 471f378eab4c |/ Successors: 2:fdf9bde5129a; 4:019fadeab383 @@ -678,7 +680,7 @@ $ hg up 'desc(A1)' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved -Precursors template should not show precursors as it's not displayed in the +Predecessors template should not show predecessors as it's not displayed in the log $ hg tlog * 019fadeab383 @@ -695,20 +697,20 @@ |/ o ea207398892e -Precursors template should a precursor as we force its display with --hidden +Predecessors template should a precursor as we force its display with --hidden $ hg tlog --hidden * 019fadeab383 - | Precursors: 3:65b757b745b9 + | Predecessors: 3:65b757b745b9 | semi-colon: 3:65b757b745b9 | x 65b757b745b9 - |/ Precursors: 1:471f378eab4c + |/ Predecessors: 1:471f378eab4c | semi-colon: 1:471f378eab4c | Successors: 4:019fadeab383 | semi-colon: 4:019fadeab383 | Fate: reworded using amend as 4:019fadeab383 | | @ fdf9bde5129a - |/ Precursors: 1:471f378eab4c + |/ Predecessors: 1:471f378eab4c | semi-colon: 1:471f378eab4c | x 471f378eab4c |/ Successors: 2:fdf9bde5129a; 3:65b757b745b9 @@ -814,7 +816,7 @@ (use 'hg evolve' to update to its successor: eb5a0daa2192) $ hg tlog o eb5a0daa2192 - | Precursors: 1:471f378eab4c + | Predecessors: 1:471f378eab4c | semi-colon: 1:471f378eab4c | @ 471f378eab4c |/ Successors: 4:eb5a0daa2192 @@ -839,7 +841,7 @@ (use 'hg evolve' to update to its successor: eb5a0daa2192) $ hg tlog o eb5a0daa2192 - | Precursors: 2:0dec01379d3b 1:471f378eab4c + | Predecessors: 2:0dec01379d3b 1:471f378eab4c | semi-colon: 2:0dec01379d3b; 1:471f378eab4c | @ 0dec01379d3b | | Successors: 4:eb5a0daa2192 @@ -873,7 +875,7 @@ (use 'hg evolve' to update to its successor: eb5a0daa2192) $ hg tlog o eb5a0daa2192 - | Precursors: 1:471f378eab4c 3:b7ea6d14e664 + | Predecessors: 1:471f378eab4c 3:b7ea6d14e664 | semi-colon: 1:471f378eab4c; 3:b7ea6d14e664 | @ b7ea6d14e664 | | Successors: 4:eb5a0daa2192 @@ -908,10 +910,10 @@ $ hg tlog --hidden @ eb5a0daa2192 - | Precursors: 1:471f378eab4c 3:b7ea6d14e664 + | Predecessors: 1:471f378eab4c 3:b7ea6d14e664 | semi-colon: 1:471f378eab4c; 3:b7ea6d14e664 | x b7ea6d14e664 - | | Precursors: 2:0dec01379d3b + | | Predecessors: 2:0dec01379d3b | | semi-colon: 2:0dec01379d3b | | Successors: 4:eb5a0daa2192 | | semi-colon: 4:eb5a0daa2192 @@ -1037,7 +1039,7 @@ $ hg tlog o 7a230b46bf61 - | Precursors: 1:471f378eab4c + | Predecessors: 1:471f378eab4c | semi-colon: 1:471f378eab4c | @ 471f378eab4c |/ Successors: 2:7a230b46bf61 @@ -1068,7 +1070,7 @@ $ hg tlog --hidden @ 7a230b46bf61 - | Precursors: 1:471f378eab4c + | Predecessors: 1:471f378eab4c | semi-colon: 1:471f378eab4c | x 471f378eab4c |/ Successors: 2:7a230b46bf61 @@ -1135,10 +1137,10 @@ (use 'hg evolve' to update to its parent successor) $ hg tlog o f897c6137566 - | Precursors: 2:0dec01379d3b + | Predecessors: 2:0dec01379d3b | semi-colon: 2:0dec01379d3b | @ 0dec01379d3b - | | Precursors: 1:471f378eab4c + | | Predecessors: 1:471f378eab4c | | semi-colon: 1:471f378eab4c | | Successors: 3:f897c6137566; 1:471f378eab4c | | semi-colon: 3:f897c6137566; 1:471f378eab4c @@ -1146,7 +1148,7 @@ | | Fate: rewritten as 1:471f378eab4c | | | x 471f378eab4c - |/ Precursors: 2:0dec01379d3b + |/ Predecessors: 2:0dec01379d3b | semi-colon: 2:0dec01379d3b | Successors: 2:0dec01379d3b | semi-colon: 2:0dec01379d3b @@ -1171,7 +1173,7 @@ (use 'hg evolve' to update to its parent successor) $ hg tlog o f897c6137566 - | Precursors: 1:471f378eab4c + | Predecessors: 1:471f378eab4c | semi-colon: 1:471f378eab4c | @ 471f378eab4c |/ Fate: pruned @@ -1201,10 +1203,10 @@ $ hg tlog --hidden o f897c6137566 - | Precursors: 2:0dec01379d3b + | Predecessors: 2:0dec01379d3b | semi-colon: 2:0dec01379d3b | x 0dec01379d3b - | | Precursors: 1:471f378eab4c + | | Predecessors: 1:471f378eab4c | | semi-colon: 1:471f378eab4c | | Successors: 3:f897c6137566; 1:471f378eab4c | | semi-colon: 3:f897c6137566; 1:471f378eab4c @@ -1212,7 +1214,7 @@ | | Fate: rewritten as 1:471f378eab4c | | | x 471f378eab4c - |/ Precursors: 2:0dec01379d3b + |/ Predecessors: 2:0dec01379d3b | semi-colon: 2:0dec01379d3b | Successors: 2:0dec01379d3b | semi-colon: 2:0dec01379d3b @@ -1388,10 +1390,10 @@ $ hg tlog @ 0b997eb7ceee - | Precursors: 6:4a004186e638 + | Predecessors: 6:4a004186e638 | semi-colon: 6:4a004186e638 | * b18bc8331526 - |/ Precursors: 6:4a004186e638 + |/ Predecessors: 6:4a004186e638 | semi-colon: 6:4a004186e638 | * ba2ed02b0c9a | | @@ -1425,16 +1427,16 @@ $ hg tlog --hidden @ 0b997eb7ceee - | Precursors: 6:4a004186e638 + | Predecessors: 6:4a004186e638 | semi-colon: 6:4a004186e638 | * b18bc8331526 - |/ Precursors: 6:4a004186e638 + |/ Predecessors: 6:4a004186e638 | semi-colon: 6:4a004186e638 | * ba2ed02b0c9a - | | Precursors: 4:9bd10a0775e4 + | | Predecessors: 4:9bd10a0775e4 | | semi-colon: 4:9bd10a0775e4 | x 4a004186e638 - |/ Precursors: 4:9bd10a0775e4 + |/ Predecessors: 4:9bd10a0775e4 | semi-colon: 4:9bd10a0775e4 | Successors: 8:b18bc8331526; 9:0b997eb7ceee | semi-colon: 8:b18bc8331526; 9:0b997eb7ceee @@ -1442,7 +1444,7 @@ | Fate: reworded using amend as 9:0b997eb7ceee | * dd800401bd8c - | Precursors: 4:9bd10a0775e4 + | Predecessors: 4:9bd10a0775e4 | semi-colon: 4:9bd10a0775e4 | x 9bd10a0775e4 |/ Successors: 5:dd800401bd8c 6:4a004186e638 7:ba2ed02b0c9a @@ -1450,10 +1452,10 @@ | Fate: split as 5:dd800401bd8c, 6:4a004186e638, 7:ba2ed02b0c9a | o f897c6137566 - | Precursors: 2:0dec01379d3b + | Predecessors: 2:0dec01379d3b | semi-colon: 2:0dec01379d3b | x 0dec01379d3b - | | Precursors: 1:471f378eab4c + | | Predecessors: 1:471f378eab4c | | semi-colon: 1:471f378eab4c | | Successors: 3:f897c6137566; 1:471f378eab4c | | semi-colon: 3:f897c6137566; 1:471f378eab4c @@ -1461,7 +1463,7 @@ | | Fate: rewritten as 1:471f378eab4c | | | x 471f378eab4c - |/ Precursors: 2:0dec01379d3b + |/ Predecessors: 2:0dec01379d3b | semi-colon: 2:0dec01379d3b | Successors: 2:0dec01379d3b | semi-colon: 2:0dec01379d3b @@ -1504,16 +1506,16 @@ rebasing 7:ba2ed02b0c9a "Add A,B,C" $ hg tlog * eceed8f98ffc - | Precursors: 4:9bd10a0775e4 + | Predecessors: 4:9bd10a0775e4 | semi-colon: 4:9bd10a0775e4 | * 0b997eb7ceee - | | Precursors: 4:9bd10a0775e4 + | | Predecessors: 4:9bd10a0775e4 | | semi-colon: 4:9bd10a0775e4 * | b18bc8331526 - |/ Precursors: 4:9bd10a0775e4 + |/ Predecessors: 4:9bd10a0775e4 | semi-colon: 4:9bd10a0775e4 * dd800401bd8c - | Precursors: 4:9bd10a0775e4 + | Predecessors: 4:9bd10a0775e4 | semi-colon: 4:9bd10a0775e4 | @ 9bd10a0775e4 |/ Successors: 5:dd800401bd8c 9:0b997eb7ceee 10:eceed8f98ffc; 5:dd800401bd8c 8:b18bc8331526 10:eceed8f98ffc
--- a/tests/test-fold.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-fold.t Sat Feb 01 12:50:10 2020 +0100 @@ -405,8 +405,8 @@ $ hg fold --exact -r 'desc("A")::desc("B")' -m 'second fold' \ > --config experimental.evolution.allowdivergence=no - abort: folding obsolete revisions may cause divergence - (set experimental.evolution.allowdivergence=yes to allow folding them) + abort: fold of 4b34ecfb0d56 creates content-divergence with fcfd42a7fa46 + (add --verbose for details or see 'hg help evolution.instability') [255] but if we allow divergence, this should work and should create new content-divergent changesets
--- a/tests/test-pullbundle.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-pullbundle.t Sat Feb 01 12:50:10 2020 +0100 @@ -1158,3 +1158,14 @@ 02-e469a7aa5cce57653b6b02ff46c80b2d94d62629-0000000912skip-0000000016size.hg 02-e74670ea99533967c5d90da3ddbc0318cc1fd502-0000001280skip-0000000256size.hg 02-fb6c210a224903e81e5a8d2ee099cb0c9526ba8c-0000001512skip-0000000004size.hg + + $ hg debugpullbundlecacheoverlap -R server 'all()' | grep -v '^ ' + gathering 100 sample pulls within 2131 revisions + pull size: + non-cached changesets: + ratio of cached changesets: + bundle count: + ratio of cached bundles: + changesets served: + size of cached bundles: + hit on cached bundles:
--- a/tests/test-push-checkheads-pruned-B6.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-push-checkheads-pruned-B6.t Sat Feb 01 12:50:10 2020 +0100 @@ -9,7 +9,7 @@ This case is part of a series of tests checking this behavior. Category B: simple case involving pruned changesets -TestCase 6: single changesets, pruned then superseeded (on a new changeset) +TestCase 6: single changesets, pruned then superseded (on a new changeset) .. old-state: ..
--- a/tests/test-push-checkheads-pruned-B7.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-push-checkheads-pruned-B7.t Sat Feb 01 12:50:10 2020 +0100 @@ -9,7 +9,7 @@ This case is part of a series of tests checking this behavior. Category B: simple case involving pruned changesets -TestCase 7: single changesets, pruned then superseeded (on an existing changeset) +TestCase 7: single changesets, pruned then superseded (on an existing changeset) .. old-state: ..
--- a/tests/test-push-checkheads-unpushed-D6.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-push-checkheads-unpushed-D6.t Sat Feb 01 12:50:10 2020 +0100 @@ -9,7 +9,7 @@ This case is part of a series of tests checking this behavior. Category D: remote head is "obs-affected" locally, but result is not part of the push -TestCase 6: single changeset, superseeded then pruned (on a new changeset unpushed) changeset +TestCase 6: single changeset, superseded then pruned (on a new changeset unpushed) changeset This is a partial push variation of case B-6
--- a/tests/test-push-checkheads-unpushed-D7.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-push-checkheads-unpushed-D7.t Sat Feb 01 12:50:10 2020 +0100 @@ -9,7 +9,7 @@ This case is part of a series of tests checking this behavior. Category D: remote head is "obs-affected" locally, but result is not part of the push -TestCase 7: single changesets, superseeded multiple time then pruned (on a new changeset unpushed) changeset +TestCase 7: single changesets, superseded multiple time then pruned (on a new changeset unpushed) changeset This is a partial push variation of B6
--- a/tests/test-topic-stack-complex.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-topic-stack-complex.t Sat Feb 01 12:50:10 2020 +0100 @@ -7,6 +7,7 @@ $ cat << EOF >> $HGRCPATH > [experimental] > evolution = all + > evolution.allowdivergence = True > [ui] > interactive = True > [extensions]
--- a/tests/test-topic.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-topic.t Sat Feb 01 12:50:10 2020 +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]
--- a/tests/test-touch.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-touch.t Sat Feb 01 12:50:10 2020 +0100 @@ -6,6 +6,8 @@ > amend=-d "0 0" > [alias] > glog = log -GT "{rev}: {desc}" + > [experimental] + > evolution.allowdivergence = True > [extensions] > hgext.rebase= > EOF
--- a/tests/test-uncommit.t Fri Jan 31 14:50:37 2020 +0100 +++ b/tests/test-uncommit.t Sat Feb 01 12:50:10 2020 +0100 @@ -1,4 +1,6 @@ $ cat >> $HGRCPATH <<EOF + > [experimental] + > evolution.allowdivergence = True > [extensions] > EOF $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH