# HG changeset patch # User Pierre-Yves David # Date 1521644777 -3600 # Node ID d5adce52cef4e776db407baecd4d41a075680bcd # Parent e4ac2e2c2086f977afa35e23a62f849e9305a225# Parent 7dce44b4abb6629cd1341079ef2fdb76da932f5b test-compat: merge stable into mercurial-4.4 diff -r 7dce44b4abb6 -r d5adce52cef4 CHANGELOG --- a/CHANGELOG Wed Jan 24 15:08:09 2018 +0100 +++ b/CHANGELOG Wed Mar 21 16:06:17 2018 +0100 @@ -1,6 +1,21 @@ Changelog ========= +7.3.0 -- 2018-03-21 +--------------------- + + * grab: new command to grab a changeset, put in on wdir parent + and update to it + * resolve: shows how to continue evolve after resolving all conflicts + * evolve: `--continue` flag now continue evolving all the remaining revisions + * prev and next now prompts user to choose a changeset in case of ambiguity + * evolve: a new `--stop` flag which can be used to stop interrupted evolution + + * fold: fix issue related to bookmarks movement (issue5772) + * amend: take lock before parsing the commit description (issue5266) + * legacy: respect 'server.bundle1' config if any is set + * previous: fix behavior on obsolete rev when topic is involved (issue5708) + 7.2.1 --2018-01-20 ------------------- diff -r 7dce44b4abb6 -r d5adce52cef4 debian/changelog --- a/debian/changelog Wed Jan 24 15:08:09 2018 +0100 +++ b/debian/changelog Wed Mar 21 16:06:17 2018 +0100 @@ -1,3 +1,9 @@ +mercurial-evolve (7.3.0-1) unstable; urgency=medium + + * New upstream release + + -- Pierre-Yves David Wed, 21 Mar 2018 15:34:15 +0100 + mercurial-evolve (7.2.1-1) unstable; urgency=medium * new upstream release diff -r 7dce44b4abb6 -r d5adce52cef4 docs/index.rst --- a/docs/index.rst Wed Jan 24 15:08:09 2018 +0100 +++ b/docs/index.rst Wed Mar 21 16:06:17 2018 +0100 @@ -157,6 +157,8 @@ or care about the new features added by evolution won't be negatively impacted by the new default. +You can find the `evolution roadmap in the wiki`_. + .. # .. _`this query`: https://bz.mercurial-scm.org/buglist.cgi?component=evolution&bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=NEED_EXAMPLE Resources @@ -173,3 +175,4 @@ .. _`sharing mutable history`: sharing.html .. _`concepts`: concepts.html .. _`MQ migration guide`: from-mq.html +.. _`evolution roadmap in the wiki`: https://www.mercurial-scm.org/wiki/CEDRoadMap diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/__init__.py --- a/hgext3rd/evolve/__init__.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/__init__.py Wed Mar 21 16:06:17 2018 +0100 @@ -252,11 +252,7 @@ evolution=all """.strip() - -import os import sys -import re -import collections import struct try: @@ -287,23 +283,18 @@ cmdutil, commands, context, - copies, dirstate, error, extensions, help, hg, lock as lockmod, - merge, node, - obsolete, patch, - phases, revset, scmutil, ) -from mercurial.commands import mergetoolopts from mercurial.i18n import _ from mercurial.node import nullid @@ -312,7 +303,8 @@ compat, debugcmd, cmdrewrite, - evolvestate, + state, + evolvecmd, exthelper, metadata, obscache, @@ -330,8 +322,6 @@ minimumhgversion = metadata.minimumhgversion buglink = metadata.buglink -sha1re = re.compile(r'\b[0-9a-f]{6,40}\b') - # Flags for enabling optional parts of evolve commandopt = 'allnewcommands' @@ -345,6 +335,7 @@ 'evolve.date': 'cyan', 'evolve.current_rev': 'bold', 'evolve.verb': '', + 'evolve.operation': 'bold' } _pack = struct.pack @@ -353,7 +344,6 @@ aliases, entry = cmdutil.findcmd('commit', commands.table) commitopts3 = cmdrewrite.commitopts3 interactiveopt = cmdrewrite.interactiveopt -_bookmarksupdater = rewriteutil.bookmarksupdater rewrite = rewriteutil.rewrite # This extension contains the following code @@ -365,6 +355,7 @@ eh = exthelper.exthelper() eh.merge(debugcmd.eh) +eh.merge(evolvecmd.eh) eh.merge(obsexchange.eh) eh.merge(checkheads.eh) eh.merge(safeguard.eh) @@ -424,7 +415,9 @@ evolveopts = ['all'] repo.ui.setconfig('experimental', 'evolution', evolveopts, 'evolve') if obsolete.isenabled(repo, 'exchange'): - repo.ui.setconfig('server', 'bundle1', False) + # if no config explicitly set, disable bundle1 + if not isinstance(repo.ui.config('server', 'bundle1'), str): + repo.ui.setconfig('server', 'bundle1', False) class trdescrepo(repo.__class__): @@ -520,18 +513,6 @@ ui.setconfig('alias', 'odiff', "diff --hidden --rev 'limit(precursors(.),1)' --rev .", 'evolve') - if ui.config('alias', 'grab') is None: - if os.name == 'nt': - hgexe = ('"%s"' % util.hgexecutable()) - ui.setconfig('alias', 'grab', "! " + hgexe - + " rebase --dest . --rev $@ && " - + hgexe + " up tip", - 'evolve') - else: - ui.setconfig('alias', 'grab', - "! $HG rebase --dest . --rev $@ && $HG up tip", - 'evolve') - ### Troubled revset symbol @@ -710,7 +691,8 @@ ui.warn(msg % shortnode) # Check that evolve is activated for performance reasons - if ui.quiet or not obsolete.isenabled(repo, commandopt): + evolvecommandenabled = any('evolve' in e for e in cmdtable) + if ui.quiet or not evolvecommandenabled: return # Show a warning for helping the user to solve the issue @@ -853,8 +835,8 @@ raise def summaryhook(ui, repo): - state = evolvestate.evolvestate(repo) - if state: + evolvestate = state.cmdstate(repo) + if evolvestate: # i18n: column positioning for "hg summary" ui.status(_('evolve: (evolve --continue)\n')) @@ -888,79 +870,6 @@ ### Old Evolve extension content ### ##################################################################### -# XXX need clean up and proper sorting in other section - -### changeset rewriting logic -############################# - -class MergeFailure(error.Abort): - pass - -def relocate(repo, orig, dest, pctx=None, keepbranch=False): - """rewrite on dest""" - if orig.rev() == dest.rev(): - raise error.Abort(_('tried to relocate a node on top of itself'), - hint=_("This shouldn't happen. If you still " - "need to move changesets, please do so " - "manually with nothing to rebase - working " - "directory parent is also destination")) - - if pctx is None: - if len(orig.parents()) == 2: - raise error.Abort(_("tried to relocate a merge commit without " - "specifying which parent should be moved"), - hint=_("Specify the parent by passing in pctx")) - pctx = orig.p1() - - commitmsg = orig.description() - - cache = {} - sha1s = re.findall(sha1re, commitmsg) - unfi = repo.unfiltered() - for sha1 in sha1s: - ctx = None - try: - ctx = unfi[sha1] - except error.RepoLookupError: - continue - - if not ctx.obsolete(): - continue - - successors = compat.successorssets(repo, ctx.node(), cache) - - # We can't make any assumptions about how to update the hash if the - # cset in question was split or diverged. - if len(successors) == 1 and len(successors[0]) == 1: - newsha1 = node.hex(successors[0][0]) - commitmsg = commitmsg.replace(sha1, newsha1[:len(sha1)]) - else: - repo.ui.note(_('The stale commit message reference to %s could ' - 'not be updated\n') % sha1) - - tr = repo.currenttransaction() - assert tr is not None - try: - r = _evolvemerge(repo, orig, dest, pctx, keepbranch) - if r[-1]: # some conflict - raise error.Abort(_('unresolved merge conflicts ' - '(see hg help resolve)')) - nodenew = _relocatecommit(repo, orig, commitmsg) - except error.Abort as exc: - with repo.dirstate.parentchange(): - repo.setparents(repo['.'].node(), nullid) - repo.dirstate.write(tr) - # fix up dirstate for copies and renames - compat.duplicatecopies(repo, repo[None], dest.rev(), orig.p1().rev()) - - class LocalMergeFailure(MergeFailure, exc.__class__): - pass - exc.__class__ = LocalMergeFailure - tr.close() # to keep changes in this transaction (e.g. dirstate) - raise - _finalizerelocate(repo, orig, dest, nodenew, tr) - return nodenew - ### new command ############################# @@ -1038,1009 +947,6 @@ _deprecatealias('gup', 'next') _deprecatealias('gdown', 'previous') -def _solveone(ui, repo, ctx, dryrun, confirm, progresscb, category): - """Resolve the troubles affecting one revision""" - wlock = lock = tr = None - try: - wlock = repo.wlock() - lock = repo.lock() - tr = repo.transaction("evolve") - if 'orphan' == category: - result = _solveunstable(ui, repo, ctx, dryrun, confirm, progresscb) - elif 'phasedivergent' == category: - result = _solvebumped(ui, repo, ctx, dryrun, confirm, progresscb) - elif 'contentdivergent' == category: - result = _solvedivergent(ui, repo, ctx, dryrun, confirm, - progresscb) - else: - assert False, "unknown trouble category: %s" % (category) - tr.close() - return result - finally: - lockmod.release(tr, lock, wlock) - -def _handlenotrouble(ui, repo, allopt, revopt, anyopt, targetcat): - """Used by the evolve function to display an error message when - no troubles can be resolved""" - troublecategories = ['phasedivergent', 'contentdivergent', 'orphan'] - unselectedcategories = [c for c in troublecategories if c != targetcat] - msg = None - hint = None - - troubled = { - "orphan": repo.revs("orphan()"), - "contentdivergent": repo.revs("contentdivergent()"), - "phasedivergent": repo.revs("phasedivergent()"), - "all": repo.revs("troubled()"), - } - - hintmap = { - 'phasedivergent': _("do you want to use --phase-divergent"), - 'phasedivergent+contentdivergent': _("do you want to use " - "--phase-divergent or" - " --content-divergent"), - 'phasedivergent+orphan': _("do you want to use --phase-divergent" - " or --orphan"), - 'contentdivergent': _("do you want to use --content-divergent"), - 'contentdivergent+orphan': _("do you want to use --content-divergent" - " or --orphan"), - 'orphan': _("do you want to use --orphan"), - 'any+phasedivergent': _("do you want to use --any (or --rev) and" - " --phase-divergent"), - 'any+phasedivergent+contentdivergent': _("do you want to use --any" - " (or --rev) and" - " --phase-divergent or" - " --content-divergent"), - 'any+phasedivergent+orphan': _("do you want to use --any (or --rev)" - " and --phase-divergent or --orphan"), - 'any+contentdivergent': _("do you want to use --any (or --rev) and" - " --content-divergent"), - 'any+contentdivergent+orphan': _("do you want to use --any (or --rev)" - " and --content-divergent or " - "--orphan"), - 'any+orphan': _("do you want to use --any (or --rev)" - "and --orphan"), - } - - if revopt: - revs = scmutil.revrange(repo, revopt) - if not revs: - msg = _("set of specified revisions is empty") - else: - msg = _("no %s changesets in specified revisions") % targetcat - othertroubles = [] - for cat in unselectedcategories: - if revs & troubled[cat]: - othertroubles.append(cat) - if othertroubles: - hint = hintmap['+'.join(othertroubles)] - - elif anyopt: - msg = _("no %s changesets to evolve") % targetcat - othertroubles = [] - for cat in unselectedcategories: - if troubled[cat]: - othertroubles.append(cat) - if othertroubles: - hint = hintmap['+'.join(othertroubles)] - - else: - # evolve without any option = relative to the current wdir - if targetcat == 'orphan': - msg = _("nothing to evolve on current working copy parent") - else: - msg = _("current working copy parent is not %s") % targetcat - - p1 = repo['.'].rev() - othertroubles = [] - for cat in unselectedcategories: - if p1 in troubled[cat]: - othertroubles.append(cat) - if othertroubles: - hint = hintmap['+'.join(othertroubles)] - else: - length = len(troubled[targetcat]) - if length: - hint = _("%d other %s in the repository, do you want --any " - "or --rev") % (length, targetcat) - else: - othertroubles = [] - for cat in unselectedcategories: - if troubled[cat]: - othertroubles.append(cat) - if othertroubles: - hint = hintmap['any+' + ('+'.join(othertroubles))] - else: - msg = _("no troubled changesets") - - assert msg is not None - ui.write_err("%s\n" % msg) - if hint: - ui.write_err("(%s)\n" % hint) - return 2 - else: - return 1 - -def _cleanup(ui, repo, startnode, showprogress): - if showprogress: - ui.progress(_('evolve'), None) - if repo['.'] != startnode: - ui.status(_('working directory is now at %s\n') % repo['.']) - -class MultipleSuccessorsError(RuntimeError): - """Exception raised by _singlesuccessor when multiple successor sets exists - - The object contains the list of successorssets in its 'successorssets' - attribute to call to easily recover. - """ - - def __init__(self, successorssets): - self.successorssets = successorssets - -def _singlesuccessor(repo, p): - """returns p (as rev) if not obsolete or its unique latest successors - - fail if there are no such successor""" - - if not p.obsolete(): - return p.rev() - obs = repo[p] - ui = repo.ui - newer = compat.successorssets(repo, obs.node()) - # search of a parent which is not killed - while not newer: - ui.debug("stabilize target %s is plain dead," - " trying to stabilize on its parent\n" % - obs) - obs = obs.parents()[0] - newer = compat.successorssets(repo, obs.node()) - if len(newer) > 1 or len(newer[0]) > 1: - raise MultipleSuccessorsError(newer) - - return repo[newer[0][0]].rev() - -def builddependencies(repo, revs): - """returns dependency graphs giving an order to solve instability of revs - (see _orderrevs for more information on usage)""" - - # For each troubled revision we keep track of what instability if any should - # be resolved in order to resolve it. Example: - # dependencies = {3: [6], 6:[]} - # Means that: 6 has no dependency, 3 depends on 6 to be solved - dependencies = {} - # rdependencies is the inverted dict of dependencies - rdependencies = collections.defaultdict(set) - - for r in revs: - dependencies[r] = set() - for p in repo[r].parents(): - try: - succ = _singlesuccessor(repo, p) - except MultipleSuccessorsError as exc: - dependencies[r] = exc.successorssets - continue - if succ in revs: - dependencies[r].add(succ) - rdependencies[succ].add(r) - return dependencies, rdependencies - -def _dedupedivergents(repo, revs): - """Dedupe the divergents revs in revs to get one from each group with the - lowest revision numbers - """ - repo = repo.unfiltered() - res = set() - # To not reevaluate divergents of the same group once one is encountered - discarded = set() - for rev in revs: - if rev in discarded: - continue - divergent = repo[rev] - base, others = divergentdata(divergent) - othersrevs = [o.rev() for o in others] - res.add(min([divergent.rev()] + othersrevs)) - discarded.update(othersrevs) - return res - -instabilities_map = { - 'contentdivergent': "content-divergent", - 'phasedivergent': "phase-divergent" -} - -def _selectrevs(repo, allopt, revopt, anyopt, targetcat): - """select troubles in repo matching according to given options""" - revs = set() - if allopt or revopt: - revs = repo.revs("%s()" % targetcat) - if revopt: - revs = scmutil.revrange(repo, revopt) & revs - elif not anyopt: - topic = getattr(repo, 'currenttopic', '') - if topic: - revs = repo.revs('topic(%s)', topic) & revs - elif targetcat == 'orphan': - revs = _aspiringdescendant(repo, - repo.revs('(.::) - obsolete()::')) - revs = set(revs) - if targetcat == 'contentdivergent': - # Pick one divergent per group of divergents - revs = _dedupedivergents(repo, revs) - elif anyopt: - revs = repo.revs('first(%s())' % (targetcat)) - elif targetcat == 'orphan': - revs = set(_aspiringchildren(repo, repo.revs('(.::) - obsolete()::'))) - if 1 < len(revs): - msg = "multiple evolve candidates" - hint = (_("select one of %s with --rev") - % ', '.join([str(repo[r]) for r in sorted(revs)])) - raise error.Abort(msg, hint=hint) - elif instabilities_map.get(targetcat, targetcat) in repo['.'].instabilities(): - revs = set([repo['.'].rev()]) - return revs - - -def _orderrevs(repo, revs): - """Compute an ordering to solve instability for the given revs - - revs is a list of unstable revisions. - - Returns the same revisions ordered to solve their instability from the - bottom to the top of the stack that the stabilization process will produce - eventually. - - This ensures the minimal number of stabilizations, as we can stabilize each - revision on its final stabilized destination. - """ - # Step 1: Build the dependency graph - dependencies, rdependencies = builddependencies(repo, revs) - # Step 2: Build the ordering - # Remove the revisions with no dependency(A) and add them to the ordering. - # Removing these revisions leads to new revisions with no dependency (the - # one depending on A) that we can remove from the dependency graph and add - # to the ordering. We progress in a similar fashion until the ordering is - # built - solvablerevs = collections.deque([r for r in sorted(dependencies.keys()) - if not dependencies[r]]) - ordering = [] - while solvablerevs: - rev = solvablerevs.popleft() - for dependent in rdependencies[rev]: - dependencies[dependent].remove(rev) - if not dependencies[dependent]: - solvablerevs.append(dependent) - del dependencies[rev] - ordering.append(rev) - - ordering.extend(sorted(dependencies)) - return ordering - -def divergentsets(repo, ctx): - """Compute sets of commits divergent with a given one""" - cache = {} - base = {} - for n in compat.allprecursors(repo.obsstore, [ctx.node()]): - if n == ctx.node(): - # a node can't be a base for divergence with itself - continue - nsuccsets = compat.successorssets(repo, n, cache) - for nsuccset in nsuccsets: - if ctx.node() in nsuccset: - # we are only interested in *other* successor sets - continue - if tuple(nsuccset) in base: - # we already know the latest base for this divergency - continue - base[tuple(nsuccset)] = n - divergence = [] - for divset, b in base.iteritems(): - divergence.append({ - 'divergentnodes': divset, - 'commonprecursor': b - }) - - return divergence - -def _preparelistctxs(items, condition): - return [item.hex() for item in items if condition(item)] - -def _formatctx(fm, ctx): - fm.data(node=ctx.hex()) - fm.data(desc=ctx.description()) - fm.data(date=ctx.date()) - fm.data(user=ctx.user()) - -def listtroubles(ui, repo, troublecategories, **opts): - """Print all the troubles for the repo (or given revset)""" - troublecategories = troublecategories or ['contentdivergent', 'orphan', 'phasedivergent'] - showunstable = 'orphan' in troublecategories - showbumped = 'phasedivergent' in troublecategories - showdivergent = 'contentdivergent' in troublecategories - - revs = repo.revs('+'.join("%s()" % t for t in troublecategories)) - if opts.get('rev'): - revs = scmutil.revrange(repo, opts.get('rev')) - - fm = ui.formatter('evolvelist', opts) - for rev in revs: - ctx = repo[rev] - unpars = _preparelistctxs(ctx.parents(), lambda p: p.orphan()) - obspars = _preparelistctxs(ctx.parents(), lambda p: p.obsolete()) - imprecs = _preparelistctxs(repo.set("allprecursors(%n)", ctx.node()), - lambda p: not p.mutable()) - dsets = divergentsets(repo, ctx) - - fm.startitem() - # plain formatter section - hashlen, desclen = 12, 60 - desc = ctx.description() - if desc: - desc = desc.splitlines()[0] - desc = (desc[:desclen] + '...') if len(desc) > desclen else desc - fm.plain('%s: ' % ctx.hex()[:hashlen]) - fm.plain('%s\n' % desc) - fm.data(node=ctx.hex(), rev=ctx.rev(), desc=desc, phase=ctx.phasestr()) - - for unpar in unpars if showunstable else []: - fm.plain(' %s: %s (%s parent)\n' % (TROUBLES['ORPHAN'], - unpar[:hashlen], - TROUBLES['ORPHAN'])) - for obspar in obspars if showunstable else []: - fm.plain(' %s: %s (obsolete parent)\n' % (TROUBLES['ORPHAN'], - obspar[:hashlen])) - for imprec in imprecs if showbumped else []: - fm.plain(' %s: %s (immutable precursor)\n' % - (TROUBLES['PHASEDIVERGENT'], imprec[:hashlen])) - - if dsets and showdivergent: - for dset in dsets: - fm.plain(' %s: ' % TROUBLES['CONTENTDIVERGENT']) - first = True - for n in dset['divergentnodes']: - t = "%s (%s)" if first else " %s (%s)" - first = False - fm.plain(t % (node.hex(n)[:hashlen], repo[n].phasestr())) - comprec = node.hex(dset['commonprecursor'])[:hashlen] - fm.plain(" (precursor %s)\n" % comprec) - fm.plain("\n") - - # templater-friendly section - _formatctx(fm, ctx) - troubles = [] - for unpar in unpars: - troubles.append({'troubletype': TROUBLES['ORPHAN'], - 'sourcenode': unpar, 'sourcetype': 'orphanparent'}) - for obspar in obspars: - troubles.append({'troubletype': TROUBLES['ORPHAN'], - 'sourcenode': obspar, - 'sourcetype': 'obsoleteparent'}) - for imprec in imprecs: - troubles.append({'troubletype': TROUBLES['PHASEDIVERGENT'], - 'sourcenode': imprec, - 'sourcetype': 'immutableprecursor'}) - for dset in dsets: - divnodes = [{'node': node.hex(n), - 'phase': repo[n].phasestr(), - } for n in dset['divergentnodes']] - troubles.append({'troubletype': TROUBLES['CONTENTDIVERGENT'], - 'commonprecursor': node.hex(dset['commonprecursor']), - 'divergentnodes': divnodes}) - fm.data(troubles=troubles) - - fm.end() - -@eh.command( - '^evolve|stabilize|solve', - [('n', 'dry-run', False, - _('do not perform actions, just print what would be done')), - ('', 'confirm', False, - _('ask for confirmation before performing the action')), - ('A', 'any', False, - _('also consider troubled changesets unrelated to current working ' - 'directory')), - ('r', 'rev', [], _('solves troubles of these revisions')), - ('', 'bumped', False, _('solves only bumped changesets')), - ('', 'phase-divergent', False, _('solves only phase-divergent changesets')), - ('', 'divergent', False, _('solves only divergent changesets')), - ('', 'content-divergent', False, _('solves only content-divergent changesets')), - ('', 'unstable', False, _('solves only unstable changesets')), - ('', 'orphan', False, _('solves only orphan changesets (default)')), - ('a', 'all', False, _('evolve all troubled changesets related to the ' - 'current working directory and its descendants')), - ('c', 'continue', False, _('continue an interrupted evolution')), - ('l', 'list', False, 'provide details on troubled changesets in the repo'), - ] + mergetoolopts, - _('[OPTIONS]...') -) -def evolve(ui, repo, **opts): - """solve troubled changesets in your repository - - Modifying history can lead to various types of troubled changesets: - unstable, bumped, or divergent. The evolve command resolves your troubles - by executing one of the following actions: - - - update working copy to a successor - - rebase an unstable changeset - - extract the desired changes from a bumped changeset - - fuse divergent changesets back together - - If you pass no arguments, evolve works in automatic mode: it will execute a - single action to reduce instability related to your working copy. There are - two cases for this action. First, if the parent of your working copy is - obsolete, evolve updates to the parent's successor. Second, if the working - copy parent is not obsolete but has obsolete predecessors, then evolve - determines if there is an unstable changeset that can be rebased onto the - working copy parent in order to reduce instability. - If so, evolve rebases that changeset. If not, evolve refuses to guess your - intention, and gives a hint about what you might want to do next. - - Any time evolve creates a changeset, it updates the working copy to the new - changeset. (Currently, every successful evolve operation involves an update - as well; this may change in future.) - - Automatic mode only handles common use cases. For example, it avoids taking - action in the case of ambiguity, and it ignores unstable changesets that - are not related to your working copy. - It also refuses to solve bumped or divergent changesets unless you - explicitly request such behavior (see below). - - Eliminating all instability around your working copy may require multiple - invocations of :hg:`evolve`. Alternately, use ``--all`` to recursively - select and evolve all unstable changesets that can be rebased onto the - working copy parent. - This is more powerful than successive invocations, since ``--all`` handles - ambiguous cases (e.g. unstable changesets with multiple children) by - evolving all branches. - - When your repository cannot be handled by automatic mode, you might need to - use ``--rev`` to specify a changeset to evolve. For example, if you have - an unstable changeset that is not related to the working copy parent, - you could use ``--rev`` to evolve it. Or, if some changeset has multiple - unstable children, evolve in automatic mode refuses to guess which one to - evolve; you have to use ``--rev`` in that case. - - Alternately, ``--any`` makes evolve search for the next evolvable changeset - regardless of whether it is related to the working copy parent. - - You can supply multiple revisions to evolve multiple troubled changesets - in a single invocation. In revset terms, ``--any`` is equivalent to ``--rev - first(unstable())``. ``--rev`` and ``--all`` are mutually exclusive, as are - ``--rev`` and ``--any``. - - ``hg evolve --any --all`` is useful for cleaning up instability across all - branches, letting evolve figure out the appropriate order and destination. - - When you have troubled changesets that are not unstable, :hg:`evolve` - refuses to consider them unless you specify the category of trouble you - wish to resolve, with ``--bumped`` or ``--divergent``. These options are - currently mutually exclusive with each other and with ``--unstable`` - (the default). You can combine ``--bumped`` or ``--divergent`` with - ``--rev``, ``--all``, or ``--any``. - - You can also use the evolve command to list the troubles affecting your - repository by using the --list flag. You can choose to display only some - categories of troubles with the --unstable, --divergent or --bumped flags. - """ - - opts = _checkevolveopts(repo, opts) - # Options - contopt = opts['continue'] - anyopt = opts['any'] - allopt = opts['all'] - startnode = repo['.'] - dryrunopt = opts['dry_run'] - confirmopt = opts['confirm'] - revopt = opts['rev'] - - troublecategories = ['phase_divergent', 'content_divergent', 'orphan'] - specifiedcategories = [t.replace('_', '') - for t in troublecategories - if opts[t]] - if opts['list']: - compat.startpager(ui, 'evolve') - listtroubles(ui, repo, specifiedcategories, **opts) - return - - targetcat = 'orphan' - if 1 < len(specifiedcategories): - msg = _('cannot specify more than one trouble category to solve (yet)') - raise error.Abort(msg) - elif len(specifiedcategories) == 1: - targetcat = specifiedcategories[0] - elif repo['.'].obsolete(): - displayer = cmdutil.show_changeset(ui, repo, - {'template': shorttemplate}) - # no args and parent is obsolete, update to successors - try: - ctx = repo[_singlesuccessor(repo, repo['.'])] - except MultipleSuccessorsError as exc: - repo.ui.write_err('parent is obsolete with multiple successors:\n') - for ln in exc.successorssets: - for n in ln: - displayer.show(repo[n]) - return 2 - - ui.status(_('update:')) - if not ui.quiet: - displayer.show(ctx) - - if dryrunopt: - return 0 - res = hg.update(repo, ctx.rev()) - if ctx != startnode: - ui.status(_('working directory is now at %s\n') % ctx) - return res - - ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'evolve') - troubled = set(repo.revs('troubled()')) - - # Progress handling - seen = 1 - count = allopt and len(troubled) or 1 - showprogress = allopt - - def progresscb(): - if revopt or allopt: - ui.progress(_('evolve'), seen, unit=_('changesets'), total=count) - - # Continuation handling - if contopt: - state = evolvestate.evolvestate(repo) - if not state: - raise error.Abort('no evolve to continue') - state.load() - orig = repo[state['current']] - with repo.wlock(), repo.lock(): - ctx = orig - source = ctx.extra().get('source') - extra = {} - if source: - extra['source'] = source - extra['intermediate-source'] = ctx.hex() - else: - extra['source'] = ctx.hex() - user = ctx.user() - date = ctx.date() - message = ctx.description() - ui.status(_('evolving %d:%s "%s"\n') % (ctx.rev(), ctx, - message.split('\n', 1)[0])) - targetphase = max(ctx.phase(), phases.draft) - overrides = {('phases', 'new-commit'): targetphase} - - with repo.ui.configoverride(overrides, 'evolve-continue'): - node = repo.commit(text=message, user=user, - date=date, extra=extra) - - obsolete.createmarkers(repo, [(ctx, (repo[node],))]) - state.delete() - return - - cmdutil.bailifchanged(repo) - - revs = _selectrevs(repo, allopt, revopt, anyopt, targetcat) - - if not revs: - return _handlenotrouble(ui, repo, allopt, revopt, anyopt, targetcat) - - # For the progress bar to show - count = len(revs) - # Order the revisions - if targetcat == 'orphan': - revs = _orderrevs(repo, revs) - for rev in revs: - progresscb() - _solveone(ui, repo, repo[rev], dryrunopt, confirmopt, - progresscb, targetcat) - seen += 1 - progresscb() - _cleanup(ui, repo, startnode, showprogress) - -def _checkevolveopts(repo, opts): - """ check the options passed to `hg evolve` and warn for deprecation warning - if any """ - - if opts['continue']: - if opts['any']: - raise error.Abort('cannot specify both "--any" and "--continue"') - if opts['all']: - raise error.Abort('cannot specify both "--all" and "--continue"') - - if opts['rev']: - if opts['any']: - raise error.Abort('cannot specify both "--rev" and "--any"') - if opts['all']: - raise error.Abort('cannot specify both "--rev" and "--all"') - - # Backward compatibility - if opts['unstable']: - msg = ("'evolve --unstable' is deprecated, " - "use 'evolve --orphan'") - repo.ui.deprecwarn(msg, '4.4') - - opts['orphan'] = opts['divergent'] - - if opts['divergent']: - msg = ("'evolve --divergent' is deprecated, " - "use 'evolve --content-divergent'") - repo.ui.deprecwarn(msg, '4.4') - - opts['content_divergent'] = opts['divergent'] - - if opts['bumped']: - msg = ("'evolve --bumped' is deprecated, " - "use 'evolve --phase-divergent'") - repo.ui.deprecwarn(msg, '4.4') - - opts['phase_divergent'] = opts['bumped'] - - return opts - -def _possibledestination(repo, rev): - """return all changesets that may be a new parent for REV""" - tonode = repo.changelog.node - parents = repo.changelog.parentrevs - torev = repo.changelog.rev - dest = set() - tovisit = list(parents(rev)) - while tovisit: - r = tovisit.pop() - succsets = compat.successorssets(repo, tonode(r)) - if not succsets: - tovisit.extend(parents(r)) - else: - # We should probably pick only one destination from split - # (case where '1 < len(ss)'), This could be the currently tipmost - # but logic is less clear when result of the split are now on - # multiple branches. - for ss in succsets: - for n in ss: - dest.add(torev(n)) - return dest - -def _aspiringchildren(repo, revs): - """Return a list of changectx which can be stabilized on top of pctx or - one of its descendants. Empty list if none can be found.""" - target = set(revs) - result = [] - for r in repo.revs('orphan() - %ld', revs): - dest = _possibledestination(repo, r) - if target & dest: - result.append(r) - return result - -def _aspiringdescendant(repo, revs): - """Return a list of changectx which can be stabilized on top of pctx or - one of its descendants recursively. Empty list if none can be found.""" - target = set(revs) - result = set(target) - paths = collections.defaultdict(set) - for r in repo.revs('orphan() - %ld', revs): - for d in _possibledestination(repo, r): - paths[d].add(r) - - result = set(target) - tovisit = list(revs) - while tovisit: - base = tovisit.pop() - for unstable in paths[base]: - if unstable not in result: - tovisit.append(unstable) - result.add(unstable) - return sorted(result - target) - -def _solveunstable(ui, repo, orig, dryrun=False, confirm=False, - progresscb=None): - """Stabilize an unstable changeset""" - pctx = orig.p1() - keepbranch = orig.p1().branch() != orig.branch() - if len(orig.parents()) == 2: - if not pctx.obsolete(): - pctx = orig.p2() # second parent is obsolete ? - keepbranch = orig.p2().branch() != orig.branch() - elif orig.p2().obsolete(): - hint = _("Redo the merge (%s) and use `hg prune " - "--succ ` to obsolete the old one") % orig.hex()[:12] - ui.warn(_("warning: no support for evolving merge changesets " - "with two obsolete parents yet\n") + - _("(%s)\n") % hint) - return False - - if not pctx.obsolete(): - ui.warn(_("cannot solve instability of %s, skipping\n") % orig) - return False - obs = pctx - newer = compat.successorssets(repo, obs.node()) - # search of a parent which is not killed - while not newer or newer == [()]: - ui.debug("stabilize target %s is plain dead," - " trying to stabilize on its parent\n" % - obs) - obs = obs.parents()[0] - newer = compat.successorssets(repo, obs.node()) - if len(newer) > 1: - msg = _("skipping %s: divergent rewriting. can't choose " - "destination\n") % obs - ui.write_err(msg) - return 2 - 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('roots(%ld)', targetrevs) - heads = repo.revs('heads(%ld)', targetrevs) - if len(roots) > 1 or len(heads) > 1: - msg = "cannot solve split across two branches\n" - ui.write_err(msg) - return 2 - target = repo[heads.first()] - else: - target = targets[0] - displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) - target = repo[target] - if not ui.quiet or confirm: - repo.ui.write(_('move:')) - displayer.show(orig) - repo.ui.write(_('atop:')) - displayer.show(target) - if confirm and ui.prompt('perform evolve? [Ny]', 'n') != 'y': - raise error.Abort(_('evolve aborted by user')) - if progresscb: - progresscb() - todo = 'hg rebase -r %s -d %s\n' % (orig, target) - if dryrun: - repo.ui.write(todo) - else: - repo.ui.note(todo) - if progresscb: - progresscb() - try: - relocate(repo, orig, target, pctx, keepbranch) - except MergeFailure: - ops = {'current': orig.node()} - state = evolvestate.evolvestate(repo, opts=ops) - state.save() - repo.ui.write_err(_('evolve failed!\n')) - repo.ui.write_err( - _("fix conflict and run 'hg evolve --continue'" - " or use 'hg update -C .' to abort\n")) - raise - -def _solvebumped(ui, repo, bumped, dryrun=False, confirm=False, - progresscb=None): - """Stabilize a bumped changeset""" - repo = repo.unfiltered() - bumped = repo[bumped.rev()] - # For now we deny bumped merge - if len(bumped.parents()) > 1: - msg = _('skipping %s : we do not handle merge yet\n') % bumped - ui.write_err(msg) - return 2 - prec = repo.set('last(allprecursors(%d) and public())', bumped).next() - # For now we deny target merge - if len(prec.parents()) > 1: - msg = _('skipping: %s: public version is a merge, ' - 'this is not handled yet\n') % prec - ui.write_err(msg) - return 2 - - displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) - if not ui.quiet or confirm: - repo.ui.write(_('recreate:')) - displayer.show(bumped) - repo.ui.write(_('atop:')) - displayer.show(prec) - if confirm and ui.prompt('perform evolve? [Ny]', 'n') != 'y': - raise error.Abort(_('evolve aborted by user')) - if dryrun: - todo = 'hg rebase --rev %s --dest %s;\n' % (bumped, prec.p1()) - repo.ui.write(todo) - repo.ui.write(('hg update %s;\n' % prec)) - repo.ui.write(('hg revert --all --rev %s;\n' % bumped)) - repo.ui.write(('hg commit --msg "%s update to %s"\n' % - (TROUBLES['PHASEDIVERGENT'], bumped))) - return 0 - if progresscb: - progresscb() - newid = tmpctx = None - tmpctx = bumped - # Basic check for common parent. Far too complicated and fragile - tr = repo.currenttransaction() - assert tr is not None - bmupdate = _bookmarksupdater(repo, bumped.node(), tr) - if not list(repo.set('parents(%d) and parents(%d)', bumped, prec)): - # Need to rebase the changeset at the right place - repo.ui.status( - _('rebasing to destination parent: %s\n') % prec.p1()) - try: - tmpid = relocate(repo, bumped, prec.p1()) - if tmpid is not None: - tmpctx = repo[tmpid] - obsolete.createmarkers(repo, [(bumped, (tmpctx,))]) - except MergeFailure: - repo.vfs.write('graftstate', bumped.hex() + '\n') - repo.ui.write_err(_('evolution failed!\n')) - msg = _("fix conflict and run 'hg evolve --continue'\n") - repo.ui.write_err(msg) - raise - # Create the new commit context - repo.ui.status(_('computing new diff\n')) - files = set() - copied = copies.pathcopies(prec, bumped) - precmanifest = prec.manifest().copy() - # 3.3.2 needs a list. - # future 3.4 don't detect the size change during iteration - # this is fishy - for key, val in list(bumped.manifest().iteritems()): - precvalue = precmanifest.get(key, None) - if precvalue is not None: - del precmanifest[key] - if precvalue != val: - files.add(key) - files.update(precmanifest) # add missing files - # commit it - if files: # something to commit! - def filectxfn(repo, ctx, path): - if path in bumped: - fctx = bumped[path] - flags = fctx.flags() - mctx = compat.memfilectx(repo, ctx, fctx, flags, copied, path) - return mctx - return None - text = '%s update to %s:\n\n' % (TROUBLES['PHASEDIVERGENT'], prec) - text += bumped.description() - - new = context.memctx(repo, - parents=[prec.node(), node.nullid], - text=text, - files=files, - filectxfn=filectxfn, - user=bumped.user(), - date=bumped.date(), - extra=bumped.extra()) - - newid = repo.commitctx(new) - if newid is None: - obsolete.createmarkers(repo, [(tmpctx, ())]) - newid = prec.node() - else: - phases.retractboundary(repo, tr, bumped.phase(), [newid]) - obsolete.createmarkers(repo, [(tmpctx, (repo[newid],))], - flag=obsolete.bumpedfix) - bmupdate(newid) - repo.ui.status(_('committed as %s\n') % node.short(newid)) - # reroute the working copy parent to the new changeset - with repo.dirstate.parentchange(): - repo.dirstate.setparents(newid, node.nullid) - -def _solvedivergent(ui, repo, divergent, dryrun=False, confirm=False, - progresscb=None): - repo = repo.unfiltered() - divergent = repo[divergent.rev()] - base, others = divergentdata(divergent) - if len(others) > 1: - othersstr = "[%s]" % (','.join([str(i) for i in others])) - msg = _("skipping %d:%s with a changeset that got split" - " into multiple ones:\n" - "|[%s]\n" - "| This is not handled by automatic evolution yet\n" - "| You have to fallback to manual handling with commands " - "such as:\n" - "| - hg touch -D\n" - "| - hg prune\n" - "| \n" - "| You should contact your local evolution Guru for help.\n" - ) % (divergent, TROUBLES['CONTENTDIVERGENT'], othersstr) - ui.write_err(msg) - return 2 - other = others[0] - if len(other.parents()) > 1: - msg = _("skipping %s: %s changeset can't be " - "a merge (yet)\n") % (divergent, TROUBLES['CONTENTDIVERGENT']) - ui.write_err(msg) - hint = _("You have to fallback to solving this by hand...\n" - "| This probably means redoing the merge and using \n" - "| `hg prune` to kill older version.\n") - ui.write_err(hint) - return 2 - if other.p1() not in divergent.parents(): - msg = _("skipping %s: have a different parent than %s " - "(not handled yet)\n") % (divergent, other) - hint = _("| %(d)s, %(o)s are not based on the same changeset.\n" - "| With the current state of its implementation, \n" - "| evolve does not work in that case.\n" - "| rebase one of them next to the other and run \n" - "| this command again.\n" - "| - either: hg rebase --dest 'p1(%(d)s)' -r %(o)s\n" - "| - or: hg rebase --dest 'p1(%(o)s)' -r %(d)s\n" - ) % {'d': divergent, 'o': other} - ui.write_err(msg) - ui.write_err(hint) - return 2 - - displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) - if not ui.quiet or confirm: - ui.write(_('merge:')) - displayer.show(divergent) - ui.write(_('with: ')) - displayer.show(other) - ui.write(_('base: ')) - displayer.show(base) - if confirm and ui.prompt(_('perform evolve? [Ny]'), 'n') != 'y': - raise error.Abort(_('evolve aborted by user')) - if dryrun: - ui.write(('hg update -c %s &&\n' % divergent)) - ui.write(('hg merge %s &&\n' % other)) - ui.write(('hg commit -m "auto merge resolving conflict between ' - '%s and %s"&&\n' % (divergent, other))) - ui.write(('hg up -C %s &&\n' % base)) - ui.write(('hg revert --all --rev tip &&\n')) - ui.write(('hg commit -m "`hg log -r %s --template={desc}`";\n' - % divergent)) - return - if divergent not in repo[None].parents(): - repo.ui.status(_('updating to "local" conflict\n')) - hg.update(repo, divergent.rev()) - repo.ui.note(_('merging %s changeset\n') % TROUBLES['CONTENTDIVERGENT']) - if progresscb: - progresscb() - stats = merge.update(repo, - other.node(), - branchmerge=True, - force=False, - ancestor=base.node(), - mergeancestor=True) - hg._showstats(repo, stats) - if stats[3]: - repo.ui.status(_("use 'hg resolve' to retry unresolved file merges " - "or 'hg update -C .' to abort\n")) - if stats[3] > 0: - raise error.Abort('merge conflict between several amendments ' - '(this is not automated yet)', - hint="""/!\ You can try: -/!\ * manual merge + resolve => new cset X -/!\ * hg up to the parent of the amended changeset (which are named W and Z) -/!\ * hg revert --all -r X -/!\ * hg ci -m "same message as the amended changeset" => new cset Y -/!\ * hg prune -n Y W Z -""") - if progresscb: - progresscb() - emtpycommitallowed = repo.ui.backupconfig('ui', 'allowemptycommit') - tr = repo.currenttransaction() - assert tr is not None - try: - repo.ui.setconfig('ui', 'allowemptycommit', True, 'evolve') - with repo.dirstate.parentchange(): - repo.dirstate.setparents(divergent.node(), node.nullid) - oldlen = len(repo) - cmdrewrite.amend(ui, repo, message='', logfile='') - if oldlen == len(repo): - new = divergent - # no changes - else: - new = repo['.'] - obsolete.createmarkers(repo, [(other, (new,))]) - phases.retractboundary(repo, tr, other.phase(), [new.node()]) - finally: - repo.ui.restoreconfig(emtpycommitallowed) - -def divergentdata(ctx): - """return base, other part of a conflict - - This only return the first one. - - XXX this woobly function won't survive XXX - """ - repo = ctx._repo.unfiltered() - for base in repo.set('reverse(allprecursors(%d))', ctx): - newer = compat.successorssets(ctx._repo, base.node()) - # drop filter and solution including the original ctx - newer = [n for n in newer if n and ctx.node() not in n] - if newer: - return base, tuple(ctx._repo[o] for o in newer[0]) - raise error.Abort("base of divergent changeset %s not found" % ctx, - hint='this case is not yet handled') - def _gettopic(ctx): """handle topic fetching with or without the extension""" return getattr(ctx, 'topic', lambda: '')() @@ -2054,10 +960,10 @@ def _prevupdate(repo, displayer, target, bookmark, dryrun): if dryrun: - repo.ui.write(('hg update %s;\n' % target.rev())) + repo.ui.write(_('hg update %s;\n') % target) if bookmark is not None: - repo.ui.write(('hg bookmark %s -r %s;\n' - % (bookmark, target.rev()))) + repo.ui.write(_('hg bookmark %s -r %s;\n') + % (bookmark, target)) else: ret = hg.update(repo, target.rev()) if not ret: @@ -2086,7 +992,7 @@ # we do not filter in the 1 case to allow prev to t0 if currenttopic and topic and _gettopicidx(p1) != 1: - parents = [repo[_singlesuccessor(repo, ctx)] if ctx.mutable() else ctx + parents = [repo[utility._singlesuccessor(repo, ctx)] if ctx.mutable() else ctx for ctx in parents] parents = [ctx for ctx in parents if ctx.topic() == currenttopic] @@ -2102,16 +1008,22 @@ if movebookmark: bookmark = repo._activebookmark else: - for p in parents: - displayer.show(p) - repo.ui.warn(_('multiple parents, explicitly update to one\n')) + header = _("multiple parents, choose one to update:") + prevs = [p.rev() for p in parents] + choosedrev = utility.revselectionprompt(repo.ui, repo, prevs, header) + if choosedrev is None: + for p in parents: + displayer.show(p) + repo.ui.warn(_('multiple parents, explicitly update to one\n')) + else: + target = repo[choosedrev] return target, bookmark @eh.command( '^previous', [('B', 'move-bookmark', False, _('move active bookmark after update')), - ('', 'merge', False, _('bring uncommitted change along')), + ('m', 'merge', False, _('bring uncommitted change along')), ('', 'no-topic', False, _('ignore topic and move topologically')), ('n', 'dry-run', False, _('do not perform actions, just print what would be done'))], @@ -2128,7 +1040,7 @@ wkctx = repo[None] wparents = wkctx.parents() if len(wparents) != 1: - raise error.Abort('merge in progress') + raise error.Abort(_('merge in progress')) if not opts['merge']: try: cmdutil.bailifchanged(repo) @@ -2136,7 +1048,8 @@ exc.hint = _('do you want --merge?') raise - displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) + displayer = compat.changesetdisplayer(ui, repo, + {'template': shorttemplate}) topic = not opts.get("no_topic", False) target, bookmark = _findprevtarget(repo, displayer, @@ -2160,7 +1073,7 @@ '^next', [('B', 'move-bookmark', False, _('move active bookmark after update')), - ('', 'merge', False, _('bring uncommitted change along')), + ('m', 'merge', False, _('bring uncommitted change along')), ('', 'evolve', False, _('evolve the next changeset if necessary')), ('', 'no-topic', False, _('ignore topic and move topologically')), ('n', 'dry-run', False, @@ -2181,7 +1094,7 @@ wkctx = repo[None] wparents = wkctx.parents() if len(wparents) != 1: - raise error.Abort('merge in progress') + raise error.Abort(_('merge in progress')) if not opts['merge']: try: cmdutil.bailifchanged(repo) @@ -2196,41 +1109,25 @@ filtered = [ctx for ctx in children if ctx.topic() != topic] # XXX N-square membership on children children = [ctx for ctx in children if ctx not in filtered] - displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) + displayer = compat.changesetdisplayer(ui, repo, + {'template': shorttemplate}) if len(children) == 1: c = children[0] - bm = repo._activebookmark - shouldmove = opts.get('move_bookmark') and bm is not None - if dryrunopt: - ui.write(('hg update %s;\n' % c.rev())) - if shouldmove: - ui.write(('hg bookmark %s -r %s;\n' % (bm, c.rev()))) + return _updatetonext(ui, repo, c, displayer, opts) + elif children: + cheader = _("ambiguous next changeset, choose one to update:") + crevs = [c.rev() for c in children] + choosedrev = utility.revselectionprompt(ui, repo, crevs, cheader) + if choosedrev is None: + ui.warn(_("ambiguous next changeset:\n")) + for c in children: + displayer.show(c) + ui.warn(_("explicitly update to one of them\n")) + return 1 else: - ret = hg.update(repo, c.rev()) - if not ret: - lock = tr = None - try: - lock = repo.lock() - tr = repo.transaction('next') - if shouldmove: - bmchanges = [(bm, c.node())] - compat.bookmarkapplychanges(repo, tr, bmchanges) - else: - bookmarksmod.deactivate(repo) - tr.close() - finally: - lockmod.release(tr, lock) - if not ui.quiet: - displayer.show(c) - result = 0 - elif children: - ui.warn(_("ambiguous next changeset:\n")) - for c in children: - displayer.show(c) - ui.warn(_('explicitly update to one of them\n')) - result = 1 + return _updatetonext(ui, repo, repo[choosedrev], displayer, opts) else: - aspchildren = _aspiringchildren(repo, [repo['.'].rev()]) + aspchildren = evolvecmd._aspiringchildren(repo, [repo['.'].rev()]) if topic: filtered.extend(repo[c] for c in children if repo[c].topic() != topic) @@ -2246,26 +1143,67 @@ msg = _('(%i unstable changesets to be evolved here, ' 'do you want --evolve?)\n') ui.warn(msg % len(aspchildren)) - result = 1 + return 1 elif 1 < len(aspchildren): - ui.warn(_("ambiguous next (unstable) changeset:\n")) - for c in aspchildren: - displayer.show(repo[c]) - ui.warn(_("(run 'hg evolve --rev REV' on one of them)\n")) - return 1 + cheader = _("ambiguous next (unstable) changeset, choose one to" + " evolve and update:") + choosedrev = utility.revselectionprompt(ui, repo, + aspchildren, cheader) + if choosedrev is None: + ui.warn(_("ambiguous next (unstable) changeset:\n")) + for c in aspchildren: + displayer.show(repo[c]) + ui.warn(_("(run 'hg evolve --rev REV' on one of them)\n")) + return 1 + else: + return _nextevolve(ui, repo, repo[choosedrev], opts) else: - cmdutil.bailifchanged(repo) - result = _solveone(ui, repo, repo[aspchildren[0]], dryrunopt, - False, lambda: None, category='orphan') - if not result: - ui.status(_('working directory now at %s\n') - % ui.label(str(repo['.']), 'evolve.node')) - return result - return 1 - return result + return _nextevolve(ui, repo, aspchildren[0], opts) finally: lockmod.release(wlock) +def _nextevolve(ui, repo, aspchildren, opts): + """logic for hg next command to evolve and update to an aspiring children""" + + cmdutil.bailifchanged(repo) + evolvestate = state.cmdstate(repo, opts={'command': 'next'}) + result = evolvecmd._solveone(ui, repo, repo[aspchildren], + evolvestate, opts.get('dry_run'), False, + lambda: None, category='orphan') + # making sure a next commit is formed + if result[0] and result[1]: + ui.status(_('working directory now at %s\n') + % ui.label(str(repo['.']), 'evolve.node')) + return 0 + +def _updatetonext(ui, repo, children, displayer, opts): + """ logic for `hg next` command to update to children and move bookmarks if + required """ + bm = repo._activebookmark + shouldmove = opts.get('move_bookmark') and bm is not None + if opts.get('dry_run'): + ui.write(_('hg update %s;\n') % children) + if shouldmove: + ui.write(_('hg bookmark %s -r %s;\n') % (bm, children)) + else: + ret = hg.update(repo, children) + if not ret: + lock = tr = None + try: + lock = repo.lock() + tr = repo.transaction('next') + if shouldmove: + bmchanges = [(bm, children.node())] + compat.bookmarkapplychanges(repo, tr, bmchanges) + else: + bookmarksmod.deactivate(repo) + tr.close() + finally: + lockmod.release(tr, lock) + if not ui.quiet: + displayer.show(children) + return 0 + @eh.wrapcommand('commit') def commitwrapper(orig, ui, repo, *arg, **kwargs): tr = None @@ -2287,7 +1225,7 @@ oldbookmarks.extend(repo.nodebookmarks(old.node())) markers.append((old, (new,))) if markers: - obsolete.createmarkers(repo, markers) + compat.createmarkers(repo, markers, operation="amend") bmchanges = [] for book in oldbookmarks: bmchanges.append((book, new.node())) @@ -2432,47 +1370,6 @@ _helploader)) help.helptable.sort() -def _relocatecommit(repo, orig, commitmsg): - if commitmsg is None: - commitmsg = orig.description() - extra = dict(orig.extra()) - if 'branch' in extra: - del extra['branch'] - extra['rebase_source'] = orig.hex() - - backup = repo.ui.backupconfig('phases', 'new-commit') - try: - targetphase = max(orig.phase(), phases.draft) - repo.ui.setconfig('phases', 'new-commit', targetphase, 'evolve') - # 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 - -def _finalizerelocate(repo, orig, dest, nodenew, tr): - destbookmarks = repo.nodebookmarks(dest.node()) - nodesrc = orig.node() - destphase = repo[nodesrc].phase() - oldbookmarks = repo.nodebookmarks(nodesrc) - bmchanges = [] - - if nodenew is not None: - phases.retractboundary(repo, tr, destphase, [nodenew]) - obsolete.createmarkers(repo, [(repo[nodesrc], (repo[nodenew],))]) - for book in oldbookmarks: - bmchanges.append((book, nodenew)) - else: - obsolete.createmarkers(repo, [(repo[nodesrc], ())]) - # Behave like rebase, move bookmarks to dest - for book in oldbookmarks: - bmchanges.append((book, dest.node())) - for book in destbookmarks: # restore bookmark that rebase move - bmchanges.append((book, dest.node())) - if bmchanges: - compat.bookmarkapplychanges(repo, tr, bmchanges) - evolvestateversion = 0 @eh.uisetup @@ -2481,32 +1378,13 @@ _("use 'hg evolve --continue' or 'hg update -C .' to abort")) cmdutil.unfinishedstates.append(data) + afterresolved = ('evolvestate', _('hg evolve --continue')) + grabresolved = ('grabstate', _('hg grab --continue')) + cmdutil.afterresolvedstates.append(afterresolved) + cmdutil.afterresolvedstates.append(grabresolved) + @eh.wrapfunction(hg, 'clean') def clean(orig, repo, *args, **kwargs): ret = orig(repo, *args, **kwargs) util.unlinkpath(repo.vfs.join('evolvestate'), ignoremissing=True) return ret - -def _evolvemerge(repo, orig, dest, pctx, keepbranch): - """Used by the evolve function to merge dest on top of pctx. - return the same tuple as merge.graft""" - if repo['.'].rev() != dest.rev(): - merge.update(repo, - dest, - branchmerge=False, - force=True) - if repo._activebookmark: - repo.ui.status(_("(leaving bookmark %s)\n") % repo._activebookmark) - bookmarksmod.deactivate(repo) - if keepbranch: - repo.dirstate.setbranch(orig.branch()) - if util.safehasattr(repo, 'currenttopic'): - # uurrgs - # there no other topic setter yet - if not orig.topic() and repo.vfs.exists('topic'): - repo.vfs.unlink('topic') - else: - with repo.vfs.open('topic', 'w') as f: - f.write(orig.topic()) - - return merge.graft(repo, orig, pctx, ['destination', 'evolving'], True) diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/cmdrewrite.py --- a/hgext3rd/evolve/cmdrewrite.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/cmdrewrite.py Wed Mar 21 16:06:17 2018 +0100 @@ -22,6 +22,7 @@ error, hg, lock as lockmod, + merge, node, obsolete, patch, @@ -34,6 +35,7 @@ from . import ( compat, + state, exthelper, rewriteutil, utility, @@ -72,7 +74,7 @@ """ # N.B. this is extremely similar to setupheaderopts() in mq.py if not opts.get('date') and opts.get('current_date'): - opts['date'] = '%d %d' % util.makedate() + opts['date'] = '%d %d' % compat.makedate() if not opts.get('user') and opts.get('current_user'): opts['user'] = ui.username() @@ -126,13 +128,13 @@ edit = opts.pop('edit', False) log = opts.get('logfile') opts['amend'] = True - if not (edit or opts['message'] or log): - opts['message'] = repo['.'].description() _resolveoptions(ui, opts) _alias, commitcmd = cmdutil.findcmd('commit', commands.table) try: wlock = repo.wlock() lock = repo.lock() + if not (edit or opts['message'] or log): + opts['message'] = repo['.'].description() rewriteutil.precheck(repo, [repo['.'].rev()], action='amend') return commitcmd[0](ui, repo, *pats, **opts) finally: @@ -387,7 +389,8 @@ if opts.get('note'): metadata['note'] = opts['note'] - obsolete.createmarkers(repo, [(old, (repo[newid],))], metadata=metadata) + compat.createmarkers(repo, [(old, (repo[newid],))], metadata=metadata, + operation="uncommit") phases.retractboundary(repo, tr, oldphase, [newid]) if opts.get('revert'): hg.updaterepo(repo, newid, True) @@ -425,7 +428,7 @@ fp.seek(0) newnode = _patchtocommit(ui, repo, old, fp) # creating obs marker temp -> () - obsolete.createmarkers(repo, [(repo[tempnode], ())]) + compat.createmarkers(repo, [(repo[tempnode], ())], operation="uncommit") return newnode def _createtempcommit(ui, repo, old, match): @@ -609,8 +612,14 @@ root.p2().node()], commitopts=commitopts) phases.retractboundary(repo, tr, targetphase, [newid]) - obsolete.createmarkers(repo, [(ctx, (repo[newid],)) - for ctx in allctx], metadata=metadata) + compat.createmarkers(repo, [(ctx, (repo[newid],)) + for ctx in allctx], metadata=metadata, + operation="fold") + # move bookmarks from old nodes to the new one + # XXX: we should make rewriteutil.rewrite() handle such cases + for ctx in allctx: + bmupdater = rewriteutil.bookmarksupdater(repo, ctx.node(), tr) + bmupdater(newid) tr.close() finally: tr.release() @@ -736,9 +745,9 @@ metadata['note'] = opts['note'] phases.retractboundary(repo, tr, targetphase, [newid]) - obsolete.createmarkers(repo, [(ctx, (repo[newid],)) - for ctx in allctx], - metadata=metadata) + compat.createmarkers(repo, [(ctx, (repo[newid],)) + for ctx in allctx], + metadata=metadata, operation="metaedit") else: ui.status(_("nothing changed\n")) tr.close() @@ -764,7 +773,7 @@ date = opts.get('date') user = opts.get('user') if date: - metadata['date'] = '%i %i' % util.parsedate(date) + metadata['date'] = '%i %i' % compat.parsedate(date) if user: metadata['user'] = user return metadata @@ -930,12 +939,14 @@ metadata['note'] = opts['note'] # create markers - obsolete.createmarkers(repo, relations, metadata=metadata) + compat.createmarkers(repo, relations, metadata=metadata, + operation="prune") # informs that changeset have been pruned ui.status(_('%i changesets pruned\n') % len(precs)) - for ctx in repo.unfiltered().set('bookmark() and %ld', precs): + precrevs = (precursor.rev() for precursor in precs) + for ctx in repo.unfiltered().set('bookmark() and %ld', precrevs): # used to be: # # ldest = list(repo.set('max((::%d) - obsolete())', ctx)) @@ -986,11 +997,11 @@ try: wlock = repo.wlock() lock = repo.lock() - rev = scmutil.revsingle(repo, revarg[0]) + ctx = scmutil.revsingle(repo, revarg[0]) + rev = ctx.rev() cmdutil.bailifchanged(repo) rewriteutil.precheck(repo, [rev], action='split') tr = repo.transaction('split') - ctx = repo[rev] if len(ctx.parents()) > 1: raise error.Abort(_("cannot split merge commits")) @@ -1042,8 +1053,8 @@ metadata = {} if opts.get('note'): metadata['note'] = opts['note'] - obsolete.createmarkers(repo, [(repo[rev], newcommits)], - metadata=metadata) + compat.createmarkers(repo, [(repo[rev], newcommits)], + metadata=metadata, operation="split") tr.close() finally: # Restore the old branch @@ -1081,7 +1092,7 @@ if not duplicate: rewriteutil.precheck(repo, revs, touch) tmpl = utility.shorttemplate - displayer = cmdutil.show_changeset(ui, repo, {'template': tmpl}) + displayer = compat.changesetdisplayer(ui, repo, {'template': tmpl}) wlock = lock = tr = None try: wlock = repo.wlock() @@ -1134,8 +1145,8 @@ metadata = {} if opts.get('note'): metadata['note'] = opts['note'] - obsolete.createmarkers(repo, [(ctx, (repo[new],))], - metadata=metadata) + compat.createmarkers(repo, [(ctx, (repo[new],))], + metadata=metadata, operation="touch") phases.retractboundary(repo, tr, ctx.phase(), [new]) if ctx in repo[None].parents(): with repo.dirstate.parentchange(): @@ -1143,3 +1154,94 @@ tr.close() finally: lockmod.release(tr, lock, wlock) + +@eh.command( + 'grab', + [('r', 'rev', '', 'revision to grab'), + ('c', 'continue', False, 'continue interrupted grab'), + ('a', 'abort', False, 'abort interrupted grab'), + ], + _('[-r] rev')) +def grab(ui, repo, *revs, **opts): + """grabs a commit, move it on the top of working directory parent and + updates to it.""" + + cont = opts.get('continue') + abort = opts.get('abort') + + if cont and abort: + raise error.Abort(_("cannot specify both --continue and --abort")) + + revs = list(revs) + if opts.get('rev'): + revs.append(opts['rev']) + + with repo.wlock(), repo.lock(), repo.transaction('grab'): + grabstate = state.cmdstate(repo, path='grabstate') + pctx = repo['.'] + + if not cont and not abort: + cmdutil.bailifchanged(repo) + revs = scmutil.revrange(repo, revs) + if len(revs) > 1: + raise error.Abort(_("specify just one revision")) + elif not revs: + raise error.Abort(_("empty revision set")) + + origctx = repo[revs.first()] + + if origctx in pctx.ancestors() or origctx.node() == pctx.node(): + raise error.Abort(_("cannot grab an ancestor revision")) + + rewriteutil.precheck(repo, [origctx.rev()], 'grab') + + ui.status(_('grabbing %d:%s "%s"\n') % + (origctx.rev(), origctx, + origctx.description().split("\n", 1)[0])) + stats = merge.graft(repo, origctx, origctx.p1(), ['local', + 'destination']) + if stats[3]: + grabstate.addopts({'orignode': origctx.node(), + 'oldpctx': pctx.node()}) + grabstate.save() + raise error.InterventionRequired(_("unresolved merge conflicts" + " (see hg help resolve)")) + + elif abort: + if not grabstate: + raise error.Abort(_("no interrupted grab state exists")) + grabstate.load() + pctxnode = grabstate['oldpctx'] + ui.status(_("aborting grab, updating to %s\n") % + node.hex(pctxnode)[:12]) + hg.updaterepo(repo, pctxnode, True) + return 0 + + else: + if revs: + raise error.Abort(_("cannot specify both --continue and " + "revision")) + if not grabstate: + raise error.Abort(_("no interrupted grab state exists")) + + grabstate.load() + orignode = grabstate['orignode'] + origctx = repo[orignode] + + overrides = {('phases', 'new-commit'): origctx.phase()} + with repo.ui.configoverride(overrides, 'grab'): + newnode = repo.commit(text=origctx.description(), + user=origctx.user(), + date=origctx.date(), extra=origctx.extra()) + + if grabstate: + grabstate.delete() + newctx = repo[newnode] if newnode else pctx + compat.createmarkers(repo, [(origctx, (newctx,))], operation="grab") + + if newnode is None: + ui.warn(_("note: grab of %d:%s created no changes to commit\n") % + (origctx.rev(), origctx)) + return 0 + + return 0 diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/compat.py --- a/hgext3rd/evolve/compat.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/compat.py Wed Mar 21 16:06:17 2018 +0100 @@ -6,14 +6,21 @@ Compatibility module """ +import inspect + +import functools + from mercurial import ( copies, context, hg, + mdiff, obsolete, revset, util, + wireproto, ) +from mercurial.hgweb import hgweb_mod # hg < 4.2 compat try: @@ -28,12 +35,35 @@ except ImportError: obsutil = None +# hg < 4.6 compat (c8e2d6ed1f9e) +try: + from mercurial import logcmdutil + changesetdisplayer = logcmdutil.changesetdisplayer + changesetprinter = logcmdutil.changesetprinter + displaygraph = logcmdutil.displaygraph +except (AttributeError, ImportError): + from mercurial import cmdutil + changesetdisplayer = cmdutil.show_changeset + changesetprinter = cmdutil.changeset_printer + displaygraph = cmdutil.displaygraph + from . import ( exthelper, ) eh = exthelper.exthelper() +# Wrap obsolete.creatmarkers and make it accept but ignore "operation" argument +# for hg < 4.3 +createmarkers = obsolete.createmarkers +originalcreatemarkers = createmarkers +while isinstance(originalcreatemarkers, functools.partial): + originalcreatemarkers = originalcreatemarkers.func +if originalcreatemarkers.__code__.co_argcount < 6: + def createmarkers(repo, relations, flag=0, date=None, metadata=None, + operation=None): + return obsolete.createmarkers(repo, relations, flag, date, metadata) + if not util.safehasattr(hg, '_copycache'): # exact copy of relevantmarkers as in Mercurial-176d1a0ce385 # this fixes relevant markers computation for version < hg-4.3 @@ -226,3 +256,40 @@ cachevfs = vfsmod.vfs(repo.vfs.join('cache')) cachevfs.createmode = repo.store.createmode return cachevfs + +def strdiff(a, b, fn1, fn2): + """ A version of mdiff.unidiff for comparing two strings + """ + args = [a, '', b, '', fn1, fn2] + + # hg < 4.6 compat 8b6dd3922f70 + argspec = inspect.getargspec(mdiff.unidiff) + + if 'binary' in argspec.args: + args.append(False) + + return mdiff.unidiff(*args) + +# date related + +try: + import mercurial.utils.dateutil + makedate = mercurial.utils.dateutil.makedate + parsedate = mercurial.utils.dateutil.parsedate +except ImportError as e: + import mercurial.util + makedate = mercurial.util.makedate + parsedate = mercurial.util.parsedate + +def wireprotocommand(exthelper, name, args='', permission='pull'): + if 3 <= len(wireproto.wireprotocommand.func_defaults): + return wireproto.wireprotocommand(name, args, permission=permission) + + else: + # <= hg-4.5 permission must be registered in dictionnary + def decorator(func): + @eh.extsetup + def install(ui): + hgweb_mod.perms[name] = permission + wireproto.commands[name] = (func, args) + return decorator diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/depthcache.py --- a/hgext3rd/evolve/depthcache.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/depthcache.py Wed Mar 21 16:06:17 2018 +0100 @@ -87,11 +87,11 @@ if util.safehasattr(repo, 'updatecaches'): @localrepo.unfilteredmethod - def updatecaches(self, tr=None): + def updatecaches(self, tr=None, **kwargs): if utility.shouldwarmcache(self, tr): self.depthcache.update(self) self.depthcache.save(self) - super(depthcacherepo, self).updatecaches(tr) + super(depthcacherepo, self).updatecaches(tr, **kwargs) else: def transaction(self, *args, **kwargs): diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/evolvecmd.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgext3rd/evolve/evolvecmd.py Wed Mar 21 16:06:17 2018 +0100 @@ -0,0 +1,1297 @@ +# Copyright 2011 Peter Arrenbrecht +# Logilab SA +# Pierre-Yves David +# Patrick Mezard +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +"""logic related to hg evolve command""" + +import collections +import re + +from mercurial import ( + bookmarks as bookmarksmod, + cmdutil, + commands, + context, + copies, + error, + hg, + lock as lockmod, + merge, + node, + obsolete, + phases, + scmutil, + util, +) + +from mercurial.i18n import _ + +from . import ( + cmdrewrite, + compat, + exthelper, + rewriteutil, + state, + utility, +) + +TROUBLES = compat.TROUBLES +shorttemplate = utility.shorttemplate +_bookmarksupdater = rewriteutil.bookmarksupdater +sha1re = re.compile(r'\b[0-9a-f]{6,40}\b') + +eh = exthelper.exthelper() +_bookmarksupdater = rewriteutil.bookmarksupdater +mergetoolopts = commands.mergetoolopts + +def _solveone(ui, repo, ctx, evolvestate, dryrun, confirm, + progresscb, category): + """Resolve the troubles affecting one revision + + 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 ''. + """ + wlock = lock = tr = None + try: + wlock = repo.wlock() + lock = repo.lock() + tr = repo.transaction("evolve") + if 'orphan' == category: + result = _solveunstable(ui, repo, ctx, evolvestate, + dryrun, confirm, progresscb) + elif 'phasedivergent' == category: + result = _solvebumped(ui, repo, ctx, evolvestate, + dryrun, confirm, progresscb) + elif 'contentdivergent' == category: + result = _solvedivergent(ui, repo, ctx, evolvestate, + dryrun, confirm, progresscb) + else: + assert False, "unknown trouble category: %s" % (category) + tr.close() + return result + finally: + lockmod.release(tr, lock, wlock) + +def _solveunstable(ui, repo, orig, evolvestate, dryrun=False, confirm=False, + progresscb=None): + """ Tries to stabilize the changeset orig which is orphan. + + 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 ''. + """ + pctx = orig.p1() + keepbranch = orig.p1().branch() != orig.branch() + if len(orig.parents()) == 2: + p1obs = orig.p1().obsolete() + p2obs = orig.p2().obsolete() + if not p1obs and p2obs: + pctx = orig.p2() # second parent is obsolete ? + keepbranch = orig.p2().branch() != orig.branch() + elif not p2obs and p1obs: + pass + else: + # store that we are resolving an orphan merge with both parents + # obsolete and proceed with first parent + evolvestate['orphanmerge'] = True + # we should process the second parent first, so that in case of + # no-conflicts the first parent is processed later and preserved as + # first parent + pctx = orig.p2() + keepbranch = orig.p2().branch() != orig.branch() + + if not pctx.obsolete(): + ui.warn(_("cannot solve instability of %s, skipping\n") % orig) + return (False, '') + obs = pctx + newer = compat.successorssets(repo, obs.node()) + # search of a parent which is not killed + while not newer or newer == [()]: + ui.debug("stabilize target %s is plain dead," + " trying to stabilize on its parent\n" % + obs) + obs = obs.parents()[0] + newer = compat.successorssets(repo, obs.node()) + if len(newer) > 1: + msg = _("skipping %s: divergent rewriting. can't choose " + "destination\n") % obs + ui.write_err(msg) + return (False, '') + 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('roots(%ld)', targetrevs) + heads = repo.revs('heads(%ld)', targetrevs) + if len(roots) > 1 or len(heads) > 1: + cheader = _("ancestor '%s' split over multiple topological" + " branches.\nchoose an evolve destination:") % orig + selectedrev = utility.revselectionprompt(ui, repo, list(heads), + cheader) + if selectedrev is None: + msg = _("could not solve instability, " + "ambiguous destination: " + "parent split across two branches\n") + ui.write_err(msg) + return (False, '') + target = repo[selectedrev] + else: + target = repo[heads.first()] + else: + target = targets[0] + displayer = compat.changesetdisplayer(ui, repo, {'template': shorttemplate}) + target = repo[target] + if not ui.quiet or confirm: + repo.ui.write(_('move:'), label='evolve.operation') + displayer.show(orig) + repo.ui.write(_('atop:')) + displayer.show(target) + if confirm and ui.prompt('perform evolve? [Ny]', 'n') != 'y': + raise error.Abort(_('evolve aborted by user')) + if progresscb: + progresscb() + todo = 'hg rebase -r %s -d %s\n' % (orig, target) + if dryrun: + repo.ui.write(todo) + return (False, '') + else: + repo.ui.note(todo) + if progresscb: + progresscb() + try: + newid = relocate(repo, orig, target, pctx, keepbranch) + return (True, newid) + except MergeFailure: + ops = {'current': orig.node()} + evolvestate.addopts(ops) + evolvestate.save() + repo.ui.write_err(_('evolve failed!\n')) + repo.ui.write_err( + _("fix conflict and run 'hg evolve --continue'" + " or use 'hg update -C .' to abort\n")) + raise + +def _solvebumped(ui, repo, bumped, evolvestate, dryrun=False, confirm=False, + progresscb=None): + """Stabilize a bumped 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() + bumped = repo[bumped.rev()] + # For now we deny bumped merge + if len(bumped.parents()) > 1: + msg = _('skipping %s : we do not handle merge yet\n') % bumped + ui.write_err(msg) + return (False, '') + prec = repo.set('last(allprecursors(%d) and public())', bumped.rev()).next() + # For now we deny target merge + if len(prec.parents()) > 1: + msg = _('skipping: %s: public version is a merge, ' + 'this is not handled yet\n') % prec + ui.write_err(msg) + return (False, '') + + displayer = compat.changesetdisplayer(ui, repo, {'template': shorttemplate}) + if not ui.quiet or confirm: + repo.ui.write(_('recreate:'), label='evolve.operation') + displayer.show(bumped) + repo.ui.write(_('atop:')) + displayer.show(prec) + if confirm and ui.prompt('perform evolve? [Ny]', 'n') != 'y': + raise error.Abort(_('evolve aborted by user')) + if dryrun: + todo = 'hg rebase --rev %s --dest %s;\n' % (bumped, prec.p1()) + repo.ui.write(todo) + repo.ui.write(('hg update %s;\n' % prec)) + repo.ui.write(('hg revert --all --rev %s;\n' % bumped)) + repo.ui.write(('hg commit --msg "%s update to %s"\n' % + (TROUBLES['PHASEDIVERGENT'], bumped))) + return (False, '') + if progresscb: + progresscb() + newid = tmpctx = None + tmpctx = bumped + # Basic check for common parent. Far too complicated and fragile + tr = repo.currenttransaction() + assert tr is not None + bmupdate = _bookmarksupdater(repo, bumped.node(), tr) + if not list(repo.set('parents(%d) and parents(%d)', bumped.rev(), prec.rev())): + # Need to rebase the changeset at the right place + repo.ui.status( + _('rebasing to destination parent: %s\n') % prec.p1()) + try: + tmpid = relocate(repo, bumped, prec.p1()) + if tmpid is not None: + tmpctx = repo[tmpid] + compat.createmarkers(repo, [(bumped, (tmpctx,))], + operation='evolve') + except MergeFailure: + repo.vfs.write('graftstate', bumped.hex() + '\n') + repo.ui.write_err(_('evolution failed!\n')) + msg = _("fix conflict and run 'hg evolve --continue'\n") + repo.ui.write_err(msg) + raise + # Create the new commit context + repo.ui.status(_('computing new diff\n')) + files = set() + copied = copies.pathcopies(prec, bumped) + precmanifest = prec.manifest().copy() + # 3.3.2 needs a list. + # future 3.4 don't detect the size change during iteration + # this is fishy + for key, val in list(bumped.manifest().iteritems()): + precvalue = precmanifest.get(key, None) + if precvalue is not None: + del precmanifest[key] + if precvalue != val: + files.add(key) + files.update(precmanifest) # add missing files + # commit it + if files: # something to commit! + def filectxfn(repo, ctx, path): + if path in bumped: + fctx = bumped[path] + flags = fctx.flags() + mctx = compat.memfilectx(repo, ctx, fctx, flags, copied, path) + return mctx + return None + text = '%s update to %s:\n\n' % (TROUBLES['PHASEDIVERGENT'], prec) + text += bumped.description() + + new = context.memctx(repo, + parents=[prec.node(), node.nullid], + text=text, + files=files, + filectxfn=filectxfn, + user=bumped.user(), + date=bumped.date(), + extra=bumped.extra()) + + newid = repo.commitctx(new) + if newid is None: + compat.createmarkers(repo, [(tmpctx, ())], operation='evolve') + newid = prec.node() + else: + phases.retractboundary(repo, tr, bumped.phase(), [newid]) + compat.createmarkers(repo, [(tmpctx, (repo[newid],))], + flag=obsolete.bumpedfix, operation='evolve') + bmupdate(newid) + repo.ui.status(_('committed as %s\n') % node.short(newid)) + # reroute the working copy parent to the new changeset + with repo.dirstate.parentchange(): + repo.dirstate.setparents(newid, node.nullid) + return (True, newid) + +def _solvedivergent(ui, repo, divergent, evolvestate, 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() + divergent = repo[divergent.rev()] + base, others = divergentdata(divergent) + if len(others) > 1: + othersstr = "[%s]" % (','.join([str(i) for i in others])) + msg = _("skipping %d:%s with a changeset that got split" + " into multiple ones:\n" + "|[%s]\n" + "| This is not handled by automatic evolution yet\n" + "| You have to fallback to manual handling with commands " + "such as:\n" + "| - hg touch -D\n" + "| - hg prune\n" + "| \n" + "| You should contact your local evolution Guru for help.\n" + ) % (divergent, TROUBLES['CONTENTDIVERGENT'], othersstr) + ui.write_err(msg) + return (False, '') + other = others[0] + if len(other.parents()) > 1: + msg = _("skipping %s: %s changeset can't be " + "a merge (yet)\n") % (divergent, TROUBLES['CONTENTDIVERGENT']) + ui.write_err(msg) + hint = _("You have to fallback to solving this by hand...\n" + "| This probably means redoing the merge and using \n" + "| `hg prune` to kill older version.\n") + ui.write_err(hint) + return (False, '') + if other.p1() not in divergent.parents(): + msg = _("skipping %s: have a different parent than %s " + "(not handled yet)\n") % (divergent, other) + hint = _("| %(d)s, %(o)s are not based on the same changeset.\n" + "| With the current state of its implementation, \n" + "| evolve does not work in that case.\n" + "| rebase one of them next to the other and run \n" + "| this command again.\n" + "| - either: hg rebase --dest 'p1(%(d)s)' -r %(o)s\n" + "| - or: hg rebase --dest 'p1(%(o)s)' -r %(d)s\n" + ) % {'d': divergent, 'o': other} + ui.write_err(msg) + ui.write_err(hint) + return (False, '') + + displayer = compat.changesetdisplayer(ui, repo, {'template': shorttemplate}) + if not ui.quiet or confirm: + ui.write(_('merge:'), label='evolve.operation') + displayer.show(divergent) + ui.write(_('with: ')) + displayer.show(other) + ui.write(_('base: ')) + displayer.show(base) + if confirm and ui.prompt(_('perform evolve? [Ny]'), 'n') != 'y': + raise error.Abort(_('evolve aborted by user')) + if dryrun: + ui.write(('hg update -c %s &&\n' % divergent)) + ui.write(('hg merge %s &&\n' % other)) + ui.write(('hg commit -m "auto merge resolving conflict between ' + '%s and %s"&&\n' % (divergent, other))) + ui.write(('hg up -C %s &&\n' % base)) + ui.write(('hg revert --all --rev tip &&\n')) + ui.write(('hg commit -m "`hg log -r %s --template={desc}`";\n' + % divergent)) + return (False, '') + if divergent not in repo[None].parents(): + repo.ui.status(_('updating to "local" conflict\n')) + hg.update(repo, divergent.rev()) + repo.ui.note(_('merging %s changeset\n') % TROUBLES['CONTENTDIVERGENT']) + if progresscb: + progresscb() + stats = merge.update(repo, + other.node(), + branchmerge=True, + force=False, + ancestor=base.node(), + mergeancestor=True) + hg._showstats(repo, stats) + if stats[3]: + repo.ui.status(_("use 'hg resolve' to retry unresolved file merges " + "or 'hg update -C .' to abort\n")) + if stats[3] > 0: + raise error.Abort('merge conflict between several amendments ' + '(this is not automated yet)', + hint="""/!\ You can try: +/!\ * manual merge + resolve => new cset X +/!\ * hg up to the parent of the amended changeset (which are named W and Z) +/!\ * hg revert --all -r X +/!\ * hg ci -m "same message as the amended changeset" => new cset Y +/!\ * hg prune -n Y W Z +""") + if progresscb: + progresscb() + emtpycommitallowed = repo.ui.backupconfig('ui', 'allowemptycommit') + tr = repo.currenttransaction() + assert tr is not None + try: + repo.ui.setconfig('ui', 'allowemptycommit', True, 'evolve') + with repo.dirstate.parentchange(): + repo.dirstate.setparents(divergent.node(), node.nullid) + oldlen = len(repo) + cmdrewrite.amend(ui, repo, message='', logfile='') + if oldlen == len(repo): + new = divergent + # no changes + else: + new = repo['.'] + compat.createmarkers(repo, [(other, (new,))], operation='evolve') + phases.retractboundary(repo, tr, other.phase(), [new.node()]) + return (True, new.node()) + finally: + repo.ui.restoreconfig(emtpycommitallowed) + +class MergeFailure(error.Abort): + pass + +def _orderrevs(repo, revs): + """Compute an ordering to solve instability for the given revs + + revs is a list of unstable revisions. + + Returns the same revisions ordered to solve their instability from the + bottom to the top of the stack that the stabilization process will produce + eventually. + + This ensures the minimal number of stabilizations, as we can stabilize each + revision on its final stabilized destination. + """ + # Step 1: Build the dependency graph + dependencies, rdependencies = utility.builddependencies(repo, revs) + # Step 2: Build the ordering + # Remove the revisions with no dependency(A) and add them to the ordering. + # Removing these revisions leads to new revisions with no dependency (the + # one depending on A) that we can remove from the dependency graph and add + # to the ordering. We progress in a similar fashion until the ordering is + # built + solvablerevs = collections.deque([r for r in sorted(dependencies.keys()) + if not dependencies[r]]) + ordering = [] + while solvablerevs: + rev = solvablerevs.popleft() + for dependent in rdependencies[rev]: + dependencies[dependent].remove(rev) + if not dependencies[dependent]: + solvablerevs.append(dependent) + del dependencies[rev] + ordering.append(rev) + + ordering.extend(sorted(dependencies)) + return ordering + +def relocate(repo, orig, dest, pctx=None, keepbranch=False): + """rewrites the orig rev on dest rev + + returns the node of new commit which is formed + """ + if orig.rev() == dest.rev(): + raise error.Abort(_('tried to relocate a node on top of itself'), + hint=_("This shouldn't happen. If you still " + "need to move changesets, please do so " + "manually with nothing to rebase - working " + "directory parent is also destination")) + + if pctx is None: + if len(orig.parents()) == 2: + raise error.Abort(_("tried to relocate a merge commit without " + "specifying which parent should be moved"), + hint=_("Specify the parent by passing in pctx")) + pctx = orig.p1() + + commitmsg = orig.description() + + cache = {} + sha1s = re.findall(sha1re, commitmsg) + unfi = repo.unfiltered() + for sha1 in sha1s: + ctx = None + try: + ctx = unfi[sha1] + except error.RepoLookupError: + continue + + if not ctx.obsolete(): + continue + + successors = compat.successorssets(repo, ctx.node(), cache) + + # We can't make any assumptions about how to update the hash if the + # cset in question was split or diverged. + if len(successors) == 1 and len(successors[0]) == 1: + newsha1 = node.hex(successors[0][0]) + commitmsg = commitmsg.replace(sha1, newsha1[:len(sha1)]) + else: + repo.ui.note(_('The stale commit message reference to %s could ' + 'not be updated\n') % sha1) + + tr = repo.currenttransaction() + assert tr is not None + try: + r = _evolvemerge(repo, orig, dest, pctx, keepbranch) + if r[-1]: # some conflict + raise error.Abort(_('unresolved merge conflicts ' + '(see hg help resolve)')) + nodenew = _relocatecommit(repo, orig, commitmsg) + except error.Abort as exc: + with repo.dirstate.parentchange(): + repo.setparents(repo['.'].node(), node.nullid) + repo.dirstate.write(tr) + # fix up dirstate for copies and renames + compat.duplicatecopies(repo, repo[None], dest.rev(), orig.p1().rev()) + + class LocalMergeFailure(MergeFailure, exc.__class__): + pass + exc.__class__ = LocalMergeFailure + tr.close() # to keep changes in this transaction (e.g. dirstate) + raise + _finalizerelocate(repo, orig, dest, nodenew, tr) + return nodenew + +def _relocatecommit(repo, orig, commitmsg): + if commitmsg is None: + commitmsg = orig.description() + extra = dict(orig.extra()) + if 'branch' in extra: + del extra['branch'] + extra['rebase_source'] = orig.hex() + + backup = repo.ui.backupconfig('phases', 'new-commit') + try: + targetphase = max(orig.phase(), phases.draft) + repo.ui.setconfig('phases', 'new-commit', targetphase, 'evolve') + # 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 + +def _finalizerelocate(repo, orig, dest, nodenew, tr): + destbookmarks = repo.nodebookmarks(dest.node()) + nodesrc = orig.node() + oldbookmarks = repo.nodebookmarks(nodesrc) + bmchanges = [] + + if nodenew is not None: + compat.createmarkers(repo, [(repo[nodesrc], (repo[nodenew],))], + operation='evolve') + for book in oldbookmarks: + bmchanges.append((book, nodenew)) + else: + compat.createmarkers(repo, [(repo[nodesrc], ())], operation='evolve') + # Behave like rebase, move bookmarks to dest + for book in oldbookmarks: + bmchanges.append((book, dest.node())) + for book in destbookmarks: # restore bookmark that rebase move + bmchanges.append((book, dest.node())) + if bmchanges: + compat.bookmarkapplychanges(repo, tr, bmchanges) + +def _evolvemerge(repo, orig, dest, pctx, keepbranch): + """Used by the evolve function to merge dest on top of pctx. + return the same tuple as merge.graft""" + if repo['.'].rev() != dest.rev(): + merge.update(repo, + dest, + branchmerge=False, + force=True) + if repo._activebookmark: + repo.ui.status(_("(leaving bookmark %s)\n") % repo._activebookmark) + bookmarksmod.deactivate(repo) + if keepbranch: + repo.dirstate.setbranch(orig.branch()) + if util.safehasattr(repo, 'currenttopic'): + # uurrgs + # there no other topic setter yet + if not orig.topic() and repo.vfs.exists('topic'): + repo.vfs.unlink('topic') + else: + with repo.vfs.open('topic', 'w') as f: + f.write(orig.topic()) + + return merge.graft(repo, orig, pctx, ['destination', 'evolving'], True) + +instabilities_map = { + 'contentdivergent': "content-divergent", + 'phasedivergent': "phase-divergent" +} + +def _selectrevs(repo, allopt, revopt, anyopt, targetcat): + """select troubles in repo matching according to given options""" + revs = set() + if allopt or revopt: + revs = repo.revs("%s()" % targetcat) + if revopt: + revs = scmutil.revrange(repo, revopt) & revs + elif not anyopt: + topic = getattr(repo, 'currenttopic', '') + if topic: + revs = repo.revs('topic(%s)', topic) & revs + elif targetcat == 'orphan': + revs = _aspiringdescendant(repo, + repo.revs('(.::) - obsolete()::')) + revs = set(revs) + if targetcat == 'contentdivergent': + # Pick one divergent per group of divergents + revs = _dedupedivergents(repo, revs) + elif anyopt: + revs = repo.revs('first(%s())' % (targetcat)) + elif targetcat == 'orphan': + revs = set(_aspiringchildren(repo, repo.revs('(.::) - obsolete()::'))) + if 1 < len(revs): + msg = "multiple evolve candidates" + hint = (_("select one of %s with --rev") + % ', '.join([str(repo[r]) for r in sorted(revs)])) + raise error.Abort(msg, hint=hint) + elif instabilities_map.get(targetcat, targetcat) in repo['.'].instabilities(): + revs = set([repo['.'].rev()]) + return revs + +def _dedupedivergents(repo, revs): + """Dedupe the divergents revs in revs to get one from each group with the + lowest revision numbers + """ + repo = repo.unfiltered() + res = set() + # To not reevaluate divergents of the same group once one is encountered + discarded = set() + for rev in revs: + if rev in discarded: + continue + divergent = repo[rev] + base, others = divergentdata(divergent) + othersrevs = [o.rev() for o in others] + res.add(min([divergent.rev()] + othersrevs)) + discarded.update(othersrevs) + return res + +def divergentdata(ctx): + """return base, other part of a conflict + + This only return the first one. + + XXX this woobly function won't survive XXX + """ + repo = ctx._repo.unfiltered() + for base in repo.set('reverse(allprecursors(%d))', ctx.rev()): + newer = compat.successorssets(ctx._repo, base.node()) + # drop filter and solution including the original ctx + newer = [n for n in newer if n and ctx.node() not in n] + if newer: + return base, tuple(ctx._repo[o] for o in newer[0]) + raise error.Abort(_("base of divergent changeset %s not found") % ctx, + hint=_('this case is not yet handled')) + +def _aspiringdescendant(repo, revs): + """Return a list of changectx which can be stabilized on top of pctx or + one of its descendants recursively. Empty list if none can be found.""" + target = set(revs) + result = set(target) + paths = collections.defaultdict(set) + for r in repo.revs('orphan() - %ld', revs): + for d in _possibledestination(repo, r): + paths[d].add(r) + + result = set(target) + tovisit = list(revs) + while tovisit: + base = tovisit.pop() + for unstable in paths[base]: + if unstable not in result: + tovisit.append(unstable) + result.add(unstable) + return sorted(result - target) + +def _aspiringchildren(repo, revs): + """Return a list of changectx which can be stabilized on top of pctx or + one of its descendants. Empty list if none can be found.""" + target = set(revs) + result = [] + for r in repo.revs('orphan() - %ld', revs): + dest = _possibledestination(repo, r) + if target & dest: + result.append(r) + return result + +def _possibledestination(repo, rev): + """return all changesets that may be a new parent for REV""" + tonode = repo.changelog.node + parents = repo.changelog.parentrevs + torev = repo.changelog.rev + dest = set() + tovisit = list(parents(rev)) + while tovisit: + r = tovisit.pop() + succsets = compat.successorssets(repo, tonode(r)) + if not succsets: + tovisit.extend(parents(r)) + else: + # We should probably pick only one destination from split + # (case where '1 < len(ss)'), This could be the currently tipmost + # but logic is less clear when result of the split are now on + # multiple branches. + for ss in succsets: + for n in ss: + dest.add(torev(n)) + return dest + +def _handlenotrouble(ui, repo, allopt, revopt, anyopt, targetcat): + """Used by the evolve function to display an error message when + no troubles can be resolved""" + troublecategories = ['phasedivergent', 'contentdivergent', 'orphan'] + unselectedcategories = [c for c in troublecategories if c != targetcat] + msg = None + hint = None + + troubled = { + "orphan": repo.revs("orphan()"), + "contentdivergent": repo.revs("contentdivergent()"), + "phasedivergent": repo.revs("phasedivergent()"), + "all": repo.revs("troubled()"), + } + + hintmap = { + 'phasedivergent': _("do you want to use --phase-divergent"), + 'phasedivergent+contentdivergent': _("do you want to use " + "--phase-divergent or" + " --content-divergent"), + 'phasedivergent+orphan': _("do you want to use --phase-divergent" + " or --orphan"), + 'contentdivergent': _("do you want to use --content-divergent"), + 'contentdivergent+orphan': _("do you want to use --content-divergent" + " or --orphan"), + 'orphan': _("do you want to use --orphan"), + 'any+phasedivergent': _("do you want to use --any (or --rev) and" + " --phase-divergent"), + 'any+phasedivergent+contentdivergent': _("do you want to use --any" + " (or --rev) and" + " --phase-divergent or" + " --content-divergent"), + 'any+phasedivergent+orphan': _("do you want to use --any (or --rev)" + " and --phase-divergent or --orphan"), + 'any+contentdivergent': _("do you want to use --any (or --rev) and" + " --content-divergent"), + 'any+contentdivergent+orphan': _("do you want to use --any (or --rev)" + " and --content-divergent or " + "--orphan"), + 'any+orphan': _("do you want to use --any (or --rev)" + "and --orphan"), + } + + if revopt: + revs = scmutil.revrange(repo, revopt) + if not revs: + msg = _("set of specified revisions is empty") + else: + msg = _("no %s changesets in specified revisions") % targetcat + othertroubles = [] + for cat in unselectedcategories: + if revs & troubled[cat]: + othertroubles.append(cat) + if othertroubles: + hint = hintmap['+'.join(othertroubles)] + + elif anyopt: + msg = _("no %s changesets to evolve") % targetcat + othertroubles = [] + for cat in unselectedcategories: + if troubled[cat]: + othertroubles.append(cat) + if othertroubles: + hint = hintmap['+'.join(othertroubles)] + + else: + # evolve without any option = relative to the current wdir + if targetcat == 'orphan': + msg = _("nothing to evolve on current working copy parent") + else: + msg = _("current working copy parent is not %s") % targetcat + + p1 = repo['.'].rev() + othertroubles = [] + for cat in unselectedcategories: + if p1 in troubled[cat]: + othertroubles.append(cat) + if othertroubles: + hint = hintmap['+'.join(othertroubles)] + else: + length = len(troubled[targetcat]) + if length: + hint = _("%d other %s in the repository, do you want --any " + "or --rev") % (length, targetcat) + else: + othertroubles = [] + for cat in unselectedcategories: + if troubled[cat]: + othertroubles.append(cat) + if othertroubles: + hint = hintmap['any+' + ('+'.join(othertroubles))] + else: + msg = _("no troubled changesets") + + assert msg is not None + ui.write_err("%s\n" % msg) + if hint: + ui.write_err("(%s)\n" % hint) + return 2 + else: + return 1 + +def _preparelistctxs(items, condition): + return [item.hex() for item in items if condition(item)] + +def _formatctx(fm, ctx): + fm.data(node=ctx.hex()) + fm.data(desc=ctx.description()) + fm.data(date=ctx.date()) + fm.data(user=ctx.user()) + +def listtroubles(ui, repo, troublecategories, **opts): + """Print all the troubles for the repo (or given revset)""" + troublecategories = troublecategories or ['contentdivergent', 'orphan', 'phasedivergent'] + showunstable = 'orphan' in troublecategories + showbumped = 'phasedivergent' in troublecategories + showdivergent = 'contentdivergent' in troublecategories + + revs = repo.revs('+'.join("%s()" % t for t in troublecategories)) + if opts.get('rev'): + revs = scmutil.revrange(repo, opts.get('rev')) + + fm = ui.formatter('evolvelist', opts) + for rev in revs: + ctx = repo[rev] + unpars = _preparelistctxs(ctx.parents(), lambda p: p.orphan()) + obspars = _preparelistctxs(ctx.parents(), lambda p: p.obsolete()) + imprecs = _preparelistctxs(repo.set("allprecursors(%n)", ctx.node()), + lambda p: not p.mutable()) + dsets = divergentsets(repo, ctx) + + fm.startitem() + # plain formatter section + hashlen, desclen = 12, 60 + desc = ctx.description() + if desc: + desc = desc.splitlines()[0] + desc = (desc[:desclen] + '...') if len(desc) > desclen else desc + fm.plain('%s: ' % ctx.hex()[:hashlen]) + fm.plain('%s\n' % desc) + fm.data(node=ctx.hex(), rev=ctx.rev(), desc=desc, phase=ctx.phasestr()) + + for unpar in unpars if showunstable else []: + fm.plain(' %s: %s (%s parent)\n' % (TROUBLES['ORPHAN'], + unpar[:hashlen], + TROUBLES['ORPHAN'])) + for obspar in obspars if showunstable else []: + fm.plain(' %s: %s (obsolete parent)\n' % (TROUBLES['ORPHAN'], + obspar[:hashlen])) + for imprec in imprecs if showbumped else []: + fm.plain(' %s: %s (immutable precursor)\n' % + (TROUBLES['PHASEDIVERGENT'], imprec[:hashlen])) + + if dsets and showdivergent: + for dset in dsets: + fm.plain(' %s: ' % TROUBLES['CONTENTDIVERGENT']) + first = True + for n in dset['divergentnodes']: + t = "%s (%s)" if first else " %s (%s)" + first = False + fm.plain(t % (node.hex(n)[:hashlen], repo[n].phasestr())) + comprec = node.hex(dset['commonprecursor'])[:hashlen] + fm.plain(" (precursor %s)\n" % comprec) + fm.plain("\n") + + # templater-friendly section + _formatctx(fm, ctx) + troubles = [] + for unpar in unpars: + troubles.append({'troubletype': TROUBLES['ORPHAN'], + 'sourcenode': unpar, 'sourcetype': 'orphanparent'}) + for obspar in obspars: + troubles.append({'troubletype': TROUBLES['ORPHAN'], + 'sourcenode': obspar, + 'sourcetype': 'obsoleteparent'}) + for imprec in imprecs: + troubles.append({'troubletype': TROUBLES['PHASEDIVERGENT'], + 'sourcenode': imprec, + 'sourcetype': 'immutableprecursor'}) + for dset in dsets: + divnodes = [{'node': node.hex(n), + 'phase': repo[n].phasestr(), + } for n in dset['divergentnodes']] + troubles.append({'troubletype': TROUBLES['CONTENTDIVERGENT'], + 'commonprecursor': node.hex(dset['commonprecursor']), + 'divergentnodes': divnodes}) + fm.data(troubles=troubles) + + fm.end() + +def _checkevolveopts(repo, opts): + """ check the options passed to `hg evolve` and warn for deprecation warning + if any """ + + if opts['continue']: + if opts['any']: + raise error.Abort(_('cannot specify both "--any" and "--continue"')) + if opts['all']: + raise error.Abort(_('cannot specify both "--all" and "--continue"')) + if opts['rev']: + raise error.Abort(_('cannot specify both "--rev" and "--continue"')) + if opts['stop']: + raise error.Abort(_('cannot specify both "--stop" and' + ' "--continue"')) + + if opts['stop']: + if opts['any']: + raise error.Abort(_('cannot specify both "--any" and "--stop"')) + if opts['all']: + raise error.Abort(_('cannot specify both "--all" and "--stop"')) + if opts['rev']: + raise error.Abort(_('cannot specify both "--rev" and "--stop"')) + + if opts['rev']: + if opts['any']: + raise error.Abort(_('cannot specify both "--rev" and "--any"')) + if opts['all']: + raise error.Abort(_('cannot specify both "--rev" and "--all"')) + + # Backward compatibility + if opts['unstable']: + msg = ("'evolve --unstable' is deprecated, " + "use 'evolve --orphan'") + repo.ui.deprecwarn(msg, '4.4') + + opts['orphan'] = opts['divergent'] + + if opts['divergent']: + msg = ("'evolve --divergent' is deprecated, " + "use 'evolve --content-divergent'") + repo.ui.deprecwarn(msg, '4.4') + + opts['content_divergent'] = opts['divergent'] + + if opts['bumped']: + msg = ("'evolve --bumped' is deprecated, " + "use 'evolve --phase-divergent'") + repo.ui.deprecwarn(msg, '4.4') + + opts['phase_divergent'] = opts['bumped'] + + return opts + +def _cleanup(ui, repo, startnode, showprogress): + if showprogress: + ui.progress(_('evolve'), None) + if repo['.'] != startnode: + ui.status(_('working directory is now at %s\n') % repo['.']) + +def divergentsets(repo, ctx): + """Compute sets of commits divergent with a given one""" + cache = {} + base = {} + for n in compat.allprecursors(repo.obsstore, [ctx.node()]): + if n == ctx.node(): + # a node can't be a base for divergence with itself + continue + nsuccsets = compat.successorssets(repo, n, cache) + for nsuccset in nsuccsets: + if ctx.node() in nsuccset: + # we are only interested in *other* successor sets + continue + if tuple(nsuccset) in base: + # we already know the latest base for this divergency + continue + base[tuple(nsuccset)] = n + divergence = [] + for divset, b in base.iteritems(): + divergence.append({ + 'divergentnodes': divset, + 'commonprecursor': b + }) + + return divergence + +@eh.command( + '^evolve|stabilize|solve', + [('n', 'dry-run', False, + _('do not perform actions, just print what would be done')), + ('', 'confirm', False, + _('ask for confirmation before performing the action')), + ('A', 'any', False, + _('also consider troubled changesets unrelated to current working ' + 'directory')), + ('r', 'rev', [], _('solves troubles of these revisions')), + ('', 'bumped', False, _('solves only bumped changesets')), + ('', 'phase-divergent', False, _('solves only phase-divergent changesets')), + ('', 'divergent', False, _('solves only divergent changesets')), + ('', 'content-divergent', False, _('solves only content-divergent changesets')), + ('', 'unstable', False, _('solves only unstable changesets')), + ('', 'orphan', False, _('solves only orphan changesets (default)')), + ('a', 'all', False, _('evolve all troubled changesets related to the ' + 'current working directory and its descendants')), + ('c', 'continue', False, _('continue an interrupted evolution')), + ('', 'stop', False, _('stop the interrupted evolution')), + ('l', 'list', False, 'provide details on troubled changesets in the repo'), + ] + mergetoolopts, + _('[OPTIONS]...') +) +def evolve(ui, repo, **opts): + """solve troubled changesets in your repository + + Modifying history can lead to various types of troubled changesets: + unstable, bumped, or divergent. The evolve command resolves your troubles + by executing one of the following actions: + + - update working copy to a successor + - rebase an unstable changeset + - extract the desired changes from a bumped changeset + - fuse divergent changesets back together + + If you pass no arguments, evolve works in automatic mode: it will execute a + single action to reduce instability related to your working copy. There are + two cases for this action. First, if the parent of your working copy is + obsolete, evolve updates to the parent's successor. Second, if the working + copy parent is not obsolete but has obsolete predecessors, then evolve + determines if there is an unstable changeset that can be rebased onto the + working copy parent in order to reduce instability. + If so, evolve rebases that changeset. If not, evolve refuses to guess your + intention, and gives a hint about what you might want to do next. + + Any time evolve creates a changeset, it updates the working copy to the new + changeset. (Currently, every successful evolve operation involves an update + as well; this may change in future.) + + Automatic mode only handles common use cases. For example, it avoids taking + action in the case of ambiguity, and it ignores unstable changesets that + are not related to your working copy. + It also refuses to solve bumped or divergent changesets unless you + explicitly request such behavior (see below). + + Eliminating all instability around your working copy may require multiple + invocations of :hg:`evolve`. Alternately, use ``--all`` to recursively + select and evolve all unstable changesets that can be rebased onto the + working copy parent. + This is more powerful than successive invocations, since ``--all`` handles + ambiguous cases (e.g. unstable changesets with multiple children) by + evolving all branches. + + When your repository cannot be handled by automatic mode, you might need to + use ``--rev`` to specify a changeset to evolve. For example, if you have + an unstable changeset that is not related to the working copy parent, + you could use ``--rev`` to evolve it. Or, if some changeset has multiple + unstable children, evolve in automatic mode refuses to guess which one to + evolve; you have to use ``--rev`` in that case. + + Alternately, ``--any`` makes evolve search for the next evolvable changeset + regardless of whether it is related to the working copy parent. + + You can supply multiple revisions to evolve multiple troubled changesets + in a single invocation. In revset terms, ``--any`` is equivalent to ``--rev + first(unstable())``. ``--rev`` and ``--all`` are mutually exclusive, as are + ``--rev`` and ``--any``. + + ``hg evolve --any --all`` is useful for cleaning up instability across all + branches, letting evolve figure out the appropriate order and destination. + + When you have troubled changesets that are not unstable, :hg:`evolve` + refuses to consider them unless you specify the category of trouble you + wish to resolve, with ``--bumped`` or ``--divergent``. These options are + currently mutually exclusive with each other and with ``--unstable`` + (the default). You can combine ``--bumped`` or ``--divergent`` with + ``--rev``, ``--all``, or ``--any``. + + You can also use the evolve command to list the troubles affecting your + repository by using the --list flag. You can choose to display only some + categories of troubles with the --unstable, --divergent or --bumped flags. + """ + + opts = _checkevolveopts(repo, opts) + # Options + contopt = opts['continue'] + anyopt = opts['any'] + allopt = opts['all'] + startnode = repo['.'] + dryrunopt = opts['dry_run'] + confirmopt = opts['confirm'] + revopt = opts['rev'] + stopopt = opts['stop'] + + troublecategories = ['phase_divergent', 'content_divergent', 'orphan'] + specifiedcategories = [t.replace('_', '') + for t in troublecategories + if opts[t]] + if opts['list']: + compat.startpager(ui, 'evolve') + listtroubles(ui, repo, specifiedcategories, **opts) + return + + targetcat = 'orphan' + if 1 < len(specifiedcategories): + msg = _('cannot specify more than one trouble category to solve (yet)') + raise error.Abort(msg) + elif len(specifiedcategories) == 1: + targetcat = specifiedcategories[0] + elif repo['.'].obsolete(): + displayer = compat.changesetdisplayer(ui, repo, + {'template': shorttemplate}) + # no args and parent is obsolete, update to successors + try: + ctx = repo[utility._singlesuccessor(repo, repo['.'])] + except utility.MultipleSuccessorsError as exc: + repo.ui.write_err(_('parent is obsolete with multiple' + ' successors:\n')) + for ln in exc.successorssets: + for n in ln: + displayer.show(repo[n]) + return 2 + + ui.status(_('update:')) + if not ui.quiet: + displayer.show(ctx) + + if dryrunopt: + return 0 + res = hg.update(repo, ctx.rev()) + if ctx != startnode: + ui.status(_('working directory is now at %s\n') % ctx) + return res + + ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'evolve') + troubled = set(repo.revs('troubled()')) + + # Progress handling + seen = 1 + count = allopt and len(troubled) or 1 + showprogress = allopt + + def progresscb(): + if revopt or allopt: + ui.progress(_('evolve'), seen, unit=_('changesets'), total=count) + + evolvestate = state.cmdstate(repo) + # Continuation handling + if contopt: + if not evolvestate: + raise error.Abort(_('no interrupted evolve to continue')) + evolvestate.load() + continueevolve(ui, repo, evolvestate, progresscb) + if evolvestate['command'] != 'evolve': + evolvestate.delete() + return + startnode = repo.unfiltered()[evolvestate['startnode']] + evolvestate.delete() + elif stopopt: + if not evolvestate: + raise error.Abort(_('no interrupted evolve to stop')) + evolvestate.load() + pctx = repo['.'] + hg.updaterepo(repo, pctx.node(), True) + ui.status(_('stopped the interrupted evolve\n')) + ui.status(_('working directory is now at %s\n') % pctx) + evolvestate.delete() + return + else: + cmdutil.bailifchanged(repo) + + revs = _selectrevs(repo, allopt, revopt, anyopt, targetcat) + + if not revs: + return _handlenotrouble(ui, repo, allopt, revopt, anyopt, targetcat) + + # For the progress bar to show + count = len(revs) + # Order the revisions + if targetcat == 'orphan': + revs = _orderrevs(repo, revs) + + # cbor does not know how to serialize sets, using list for skippedrevs + stateopts = {'category': targetcat, 'replacements': {}, 'revs': revs, + 'confirm': confirmopt, 'startnode': startnode.node(), + 'skippedrevs': [], 'command': 'evolve', 'orphanmerge': False} + evolvestate.addopts(stateopts) + for rev in revs: + curctx = repo[rev] + progresscb() + ret = _solveone(ui, repo, curctx, evolvestate, dryrunopt, confirmopt, + progresscb, targetcat) + seen += 1 + if ret[0]: + evolvestate['replacements'][curctx.node()] = [ret[1]] + else: + evolvestate['skippedrevs'].append(curctx.node()) + + if evolvestate['orphanmerge']: + # we were processing an orphan merge with both parents obsolete, + # stabilized for second parent, re-stabilize for the first parent + ret = _solveone(ui, repo, repo[ret[1]], evolvestate, dryrunopt, + confirmopt, progresscb, targetcat) + if ret[0]: + evolvestate['replacements'][curctx.node()] = [ret[1]] + else: + evolvestate['skippedrevs'].append(curctx.node()) + + evolvestate['orphanmerge'] = False + + progresscb() + _cleanup(ui, repo, startnode, showprogress) + +def continueevolve(ui, repo, evolvestate, progresscb): + """logic for handling of `hg evolve --continue`""" + orig = repo[evolvestate['current']] + with repo.wlock(), repo.lock(): + ctx = orig + source = ctx.extra().get('source') + extra = {} + if source: + extra['source'] = source + extra['intermediate-source'] = ctx.hex() + else: + extra['source'] = ctx.hex() + user = ctx.user() + date = ctx.date() + message = ctx.description() + ui.status(_('evolving %d:%s "%s"\n') % (ctx.rev(), ctx, + message.split('\n', 1)[0])) + targetphase = max(ctx.phase(), phases.draft) + overrides = {('phases', 'new-commit'): targetphase} + + ctxparents = orig.parents() + if len(ctxparents) == 2: + currentp1 = repo.dirstate.parents()[0] + p1obs = ctxparents[0].obsolete() + p2obs = ctxparents[1].obsolete() + # asumming that the parent of current wdir is successor of one + # of p1 or p2 of the original changeset + if p1obs and not p2obs: + # p1 is obsolete and p2 is not obsolete, current working + # directory parent should be successor of p1, so we should + # set dirstate parents to (succ of p1, p2) + with repo.dirstate.parentchange(): + repo.dirstate.setparents(currentp1, + ctxparents[1].node()) + elif p2obs and not p1obs: + # p2 is obsolete and p1 is not obsolete, current working + # directory parent should be successor of p2, so we should + # set dirstate parents to (succ of p2, p1) + with repo.dirstate.parentchange(): + repo.dirstate.setparents(ctxparents[0].node(), + currentp1) + + else: + # both the parents were obsoleted, if orphanmerge is set, we + # are processing the second parent first (to keep parent order) + if evolvestate.get('orphanmerge'): + with repo.dirstate.parentchange(): + repo.dirstate.setparents(ctxparents[0].node(), + currentp1) + pass + + with repo.ui.configoverride(overrides, 'evolve-continue'): + node = repo.commit(text=message, user=user, + date=date, extra=extra) + + # resolving conflicts can lead to empty wdir and node can be None in + # those cases + newctx = repo[node] if node is not None else repo['.'] + compat.createmarkers(repo, [(ctx, (newctx,))], operation='evolve') + + # make sure we are continuing evolve and not `hg next --evolve` + if evolvestate['command'] == 'evolve': + evolvestate['replacements'][ctx.node()] = node + category = evolvestate['category'] + confirm = evolvestate['confirm'] + unfi = repo.unfiltered() + if evolvestate['orphanmerge']: + # processing a merge changeset with both parents obsoleted, + # stabilized on second parent, insert in front of list to + # re-process to stabilize on first parent + evolvestate['revs'].insert(0, repo[node].rev()) + evolvestate['orphanmerge'] = False + for rev in evolvestate['revs']: + # XXX: prevent this lookup by storing nodes instead of revnums + curctx = unfi[rev] + if (curctx.node() not in evolvestate['replacements'] and + curctx.node() not in evolvestate['skippedrevs']): + newnode = _solveone(ui, repo, curctx, evolvestate, False, + confirm, progresscb, category) + if newnode[0]: + evolvestate['replacements'][curctx.node()] = newnode[1] + else: + evolvestate['skippedrevs'].append(curctx.node()) + return diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/evolvestate.py --- a/hgext3rd/evolve/evolvestate.py Wed Jan 24 15:08:09 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -# This software may be used and distributed according to the terms of the -# GNU General Public License version 2 or any later version. - -""" -This file contains class to wrap the state for hg evolve command and other -related logic. - -All the data related to the command state is stored as dictionary in the object. -The class has methods using which the data can be stored to disk in -.hg/evolvestate file. - -We store the data on disk in cbor, for which we use cbor library to serialize -and deserialize data. -""" - -from __future__ import absolute_import - -from .thirdparty import cbor - -from mercurial import ( - util, -) - -class evolvestate(): - """a wrapper class to store the state of `hg evolve` command - - All the data for the state is stored in the form of key-value pairs in a - dictionary. - - The class object can write all the data to .hg/evolvestate file and also can - populate the object data reading that file - """ - - def __init__(self, repo, path='evolvestate', opts={}): - self._repo = repo - self.path = path - self.opts = opts - - def __nonzero__(self): - return self.exists() - - def __getitem__(self, key): - return self.opts[key] - - def load(self): - """load the existing evolvestate file into the class object""" - op = self._read() - self.opts.update(op) - - def addopts(self, opts): - """add more key-value pairs to the data stored by the object""" - self.opts.update(opts) - - def save(self): - """write all the evolvestate data stored in .hg/evolvestate file - - we use third-party library cbor to serialize data to write in the file. - """ - with self._repo.vfs(self.path, 'wb', atomictemp=True) as fp: - cbor.dump(self.opts, fp) - - def _read(self): - """reads the evolvestate file and returns a dictionary which contain - data in the same format as it was before storing""" - with self._repo.vfs(self.path, 'rb') as fp: - return cbor.load(fp) - - def delete(self): - """drop the evolvestate file if exists""" - util.unlinkpath(self._repo.vfs.join(self.path), ignoremissing=True) - - def exists(self): - """check whether the evolvestate file exists or not""" - return self._repo.vfs.exists(self.path) diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/exthelper.py --- a/hgext3rd/evolve/exthelper.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/exthelper.py Wed Mar 21 16:06:17 2018 +0100 @@ -128,8 +128,11 @@ revset.loadpredicate(ui, 'evolve', revsetpredicate) templatekeyword = registrar.templatekeyword() - for name, kw in self._templatekws: - templatekeyword(name)(kw) + for name, kw, requires in self._templatekws: + if requires is not None: + templatekeyword(name, requires=requires)(kw) + else: + templatekeyword(name)(kw) templatekw.loadkeyword(ui, 'evolve', templatekeyword) for ext, command, wrapper, opts in self._extcommandwrappers: @@ -215,7 +218,7 @@ return symbol return dec - def templatekw(self, keywordname): + def templatekw(self, keywordname, requires=None): """Decorated function is a template keyword The name of the keyword must be given as the decorator argument. @@ -228,7 +231,7 @@ return 'babar' """ def dec(keyword): - self._templatekws.append((keywordname, keyword)) + self._templatekws.append((keywordname, keyword, requires)) return keyword return dec diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/firstmergecache.py --- a/hgext3rd/evolve/firstmergecache.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/firstmergecache.py Wed Mar 21 16:06:17 2018 +0100 @@ -49,11 +49,11 @@ if util.safehasattr(repo, 'updatecaches'): @localrepo.unfilteredmethod - def updatecaches(self, tr=None): + def updatecaches(self, tr=None, **kwargs): if utility.shouldwarmcache(self, tr): self.firstmergecache.update(self) self.firstmergecache.save(self) - super(firstmergecacherepo, self).updatecaches(tr) + super(firstmergecacherepo, self).updatecaches(tr, **kwargs) else: def transaction(self, *args, **kwargs): diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/legacy.py --- a/hgext3rd/evolve/legacy.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/legacy.py Wed Mar 21 16:06:17 2018 +0100 @@ -30,6 +30,12 @@ from mercurial import registrar from mercurial import util +try: + from mercurial.utils.dateutil import makedate +except ImportError as e: + # compat with hg < 4.6 + from mercurial.util import makedate + if util.safehasattr(registrar, 'command'): commandfunc = registrar.command else: # compat with hg < 4.3 @@ -105,7 +111,7 @@ prec = bin(objhex) sucs = (suc == nullid) and [] or [suc] meta = { - 'date': '%i %i' % util.makedate(), + 'date': '%i %i' % makedate(), 'user': ui.username(), } try: diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/metadata.py --- a/hgext3rd/evolve/metadata.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/metadata.py Wed Mar 21 16:06:17 2018 +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__ = '7.2.1' -testedwith = '4.1.3 4.2.3 4.3.2 4.4.2' +__version__ = '7.3.0' +testedwith = '4.1.3 4.2.3 4.3.2 4.4.2 4.5.2' minimumhgversion = '4.1' buglink = 'https://bz.mercurial-scm.org/' diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/obscache.py --- a/hgext3rd/evolve/obscache.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/obscache.py Wed Mar 21 16:06:17 2018 +0100 @@ -225,6 +225,8 @@ self.clear(reset=True) starttime = timer() + revs = list(revs) + obsmarkers = list(obsmarkers) self._updatefrom(repo, revs, obsmarkers) duration = timer() - starttime repo.ui.log('evoext-cache', 'updated %s in %.4f seconds (%sr, %so)\n', @@ -523,8 +525,8 @@ if util.safehasattr(repo, 'updatecaches'): @localrepo.unfilteredmethod - def updatecaches(self, tr=None): - super(obscacherepo, self).updatecaches(tr) + def updatecaches(self, tr=None, **kwargs): + super(obscacherepo, self).updatecaches(tr, **kwargs) self.obsstore.obscache.update(repo) self.obsstore.obscache.save(repo) diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/obsdiscovery.py --- a/hgext3rd/evolve/obsdiscovery.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/obsdiscovery.py Wed Mar 21 16:06:17 2018 +0100 @@ -44,10 +44,10 @@ util, wireproto, ) -from mercurial.hgweb import hgweb_mod from mercurial.i18n import _ from . import ( + compat, exthelper, obscache, utility, @@ -95,7 +95,8 @@ common = set() undecided = set(probeset) totalnb = len(undecided) - ui.progress(_("comparing with other"), 0, total=totalnb) + ui.progress(_("comparing with other"), 0, total=totalnb, + unit=_("changesets")) _takefullsample = setdiscovery._takefullsample if remote.capable('_evoext_obshash_1'): getremotehash = remote.evoext_obshash1 @@ -114,7 +115,7 @@ roundtrips += 1 ui.progress(_("comparing with other"), totalnb - len(undecided), - total=totalnb) + total=totalnb, unit=_("changesets")) ui.debug("query %i; still undecided: %i, sample size is: %i\n" % (roundtrips, len(undecided), len(sample))) # indices between sample and externalized version must match @@ -175,7 +176,8 @@ local.obsstore.rangeobshashcache.update(local) querycount = 0 - ui.progress(_("comparing obsmarker with other"), querycount) + ui.progress(_("comparing obsmarker with other"), querycount, + unit=_("queries")) overflow = [] while sample or overflow: if overflow: @@ -230,7 +232,8 @@ addentry(new) assert nbsample == nbreplies querycount += 1 - ui.progress(_("comparing obsmarker with other"), querycount) + ui.progress(_("comparing obsmarker with other"), querycount, + unit=_("queries")) ui.progress(_("comparing obsmarker with other"), None) local.obsstore.rangeobshashcache.save(local) duration = timer() - starttime @@ -597,11 +600,11 @@ if util.safehasattr(repo, 'updatecaches'): @localrepo.unfilteredmethod - def updatecaches(self, tr=None): + def updatecaches(self, tr=None, **kwargs): if utility.shouldwarmcache(self, tr): self.obsstore.rangeobshashcache.update(self) self.obsstore.rangeobshashcache.save(self) - super(obshashrepo, self).updatecaches(tr) + super(obshashrepo, self).updatecaches(tr, **kwargs) else: def transaction(self, *args, **kwargs): @@ -675,6 +678,7 @@ except ValueError: self._abort(error.ResponseError(_("unexpected response:"), d)) +@compat.wireprotocommand(eh, 'evoext_obshashrange_v1', 'ranges') def srv_obshashrange_v1(repo, proto, ranges): ranges = wireproto.decodelist(ranges) ranges = [_decrange(r) for r in ranges] @@ -698,17 +702,26 @@ caps = orig(repo, proto) enabled = _useobshashrange(repo) if obsolete.isenabled(repo, obsolete.exchangeopt) and enabled: + + # Compat hg 4.6+ (2f7290555c96) + bytesresponse = False + if util.safehasattr(caps, 'data'): + bytesresponse = True + caps = caps.data + caps = caps.split() - caps.append('_evoext_obshashrange_v1') + caps.append(b'_evoext_obshashrange_v1') caps.sort() - caps = ' '.join(caps) + caps = b' '.join(caps) + + # Compat hg 4.6+ (2f7290555c96) + if bytesresponse: + from mercurial import wireprototypes + caps = wireprototypes.bytesresponse(caps) return caps @eh.extsetup def obshashrange_extsetup(ui): - hgweb_mod.perms['evoext_obshashrange_v1'] = 'pull' - - wireproto.commands['evoext_obshashrange_v1'] = (srv_obshashrange_v1, 'ranges') ### extensions.wrapfunction(wireproto, 'capabilities', _obshashrange_capabilities) # wrap command content @@ -759,7 +772,8 @@ cache = [] unfi = repo.unfiltered() markercache = {} - repo.ui.progress(_("preparing locally"), 0, total=len(unfi)) + repo.ui.progress(_("preparing locally"), 0, total=len(unfi), + unit=_("changesets")) for i in unfi: ctx = unfi[i] entry = 0 @@ -789,7 +803,8 @@ cache.append((ctx.node(), sha.digest())) else: cache.append((ctx.node(), node.nullid)) - repo.ui.progress(_("preparing locally"), i, total=len(unfi)) + repo.ui.progress(_("preparing locally"), i, total=len(unfi), + unit=_("changesets")) repo.ui.progress(_("preparing locally"), None) return cache @@ -828,9 +843,11 @@ except ValueError: self._abort(error.ResponseError(_("unexpected response:"), d)) +@compat.wireprotocommand(eh, 'evoext_obshash', 'nodes') def srv_obshash(repo, proto, nodes): return wireproto.encodelist(_obshash(repo, wireproto.decodelist(nodes))) +@compat.wireprotocommand(eh, 'evoext_obshash1', 'nodes') def srv_obshash1(repo, proto, nodes): return wireproto.encodelist(_obshash(repo, wireproto.decodelist(nodes), version=1)) @@ -840,20 +857,27 @@ caps = orig(repo, proto) if (obsolete.isenabled(repo, obsolete.exchangeopt) and repo.ui.configbool('experimental', 'evolution.obsdiscovery', True)): + + # Compat hg 4.6+ (2f7290555c96) + bytesresponse = False + if util.safehasattr(caps, 'data'): + bytesresponse = True + caps = caps.data + caps = caps.split() - caps.append('_evoext_obshash_0') - caps.append('_evoext_obshash_1') + caps.append(b'_evoext_obshash_0') + caps.append(b'_evoext_obshash_1') caps.sort() - caps = ' '.join(caps) + caps = b' '.join(caps) + + # Compat hg 4.6+ (2f7290555c96) + if bytesresponse: + from mercurial import wireprototypes + caps = wireprototypes.bytesresponse(caps) return caps @eh.extsetup def obshash_extsetup(ui): - hgweb_mod.perms['evoext_obshash'] = 'pull' - hgweb_mod.perms['evoext_obshash1'] = 'pull' - - wireproto.commands['evoext_obshash'] = (srv_obshash, 'nodes') - wireproto.commands['evoext_obshash1'] = (srv_obshash1, 'nodes') extensions.wrapfunction(wireproto, 'capabilities', _obshash_capabilities) # wrap command content oldcap, args = wireproto.commands['capabilities'] diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/obsexchange.py --- a/hgext3rd/evolve/obsexchange.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/obsexchange.py Wed Mar 21 16:06:17 2018 +0100 @@ -27,6 +27,12 @@ wireproto, ) +try: + from mercurial import wireprotoserver + wireprotoserver.handlewsgirequest +except (ImportError, AttributeError): + wireprotoserver = None + from mercurial.hgweb import common as hgwebcommon from . import ( @@ -106,10 +112,22 @@ """wrapper to advertise new capability""" caps = orig(repo, proto) if obsolete.isenabled(repo, obsolete.exchangeopt): + + # Compat hg 4.6+ (2f7290555c96) + bytesresponse = False + if util.safehasattr(caps, 'data'): + bytesresponse = True + caps = caps.data + caps = caps.split() - caps.append('_evoext_getbundle_obscommon') + caps.append(b'_evoext_getbundle_obscommon') caps.sort() - caps = ' '.join(caps) + caps = b' '.join(caps) + + # Compat hg 4.6+ (2f7290555c96) + if bytesresponse: + from mercurial import wireprototypes + caps = wireprototypes.bytesresponse(caps) return caps @eh.extsetup diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/obshistory.py --- a/hgext3rd/evolve/obshistory.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/obshistory.py Wed Mar 21 16:06:17 2018 +0100 @@ -10,11 +10,9 @@ import re from mercurial import ( - cmdutil, commands, error, graphmod, - mdiff, patch, obsolete, node as nodemod, @@ -58,7 +56,7 @@ ] + commands.formatteropts, _('hg olog [OPTION]... [REV]')) def cmdobshistory(ui, repo, *revs, **opts): - """show the obsolescence history of the specified revisions. + """show the obsolescence history of the specified revisions If no revision range is specified, we display the log for the current working copy parent. @@ -97,7 +95,7 @@ revs.reverse() _debugobshistoryrevs(ui, repo, revs, opts) -class obsmarker_printer(cmdutil.changeset_printer): +class obsmarker_printer(compat.changesetprinter): """show (available) information about a node We display the node, description (if available) and various information @@ -173,7 +171,7 @@ basename = "changeset-description" succname = "changeset-description" - d = mdiff.unidiff(basedesc, '', succdesc, '', basename, succname) + d = compat.strdiff(basedesc, succdesc, basename, succname) # mercurial 4.1 and before return the patch directly if not isinstance(d, tuple): patch = d @@ -356,7 +354,7 @@ displayer = obsmarker_printer(ui, repo.unfiltered(), matchfn, opts, buffered=True) edges = graphmod.asciiedges walker = _obshistorywalker(repo.unfiltered(), revs, opts.get('all', False)) - cmdutil.displaygraph(ui, repo, walker, displayer, edges) + compat.displaygraph(ui, repo, walker, displayer, edges) def _debugobshistoryrevs(ui, repo, revs, opts): """ Display the obsolescence history for revset @@ -404,7 +402,7 @@ label="evolve.node") fm.plain(' ') - fm.write('rev', '(%d)', int(ctx), + fm.write('rev', '(%d)', ctx.rev(), label="evolve.rev") fm.plain(' ') @@ -473,6 +471,11 @@ fm.write('succnodes', '%s', nodes, label="evolve.node") + operation = metadata.get('operation') + if operation: + fm.plain(' using ') + fm.write('operation', '%s', operation, label="evolve.operation") + fm.plain(' by ') fm.write('user', '%s', metadata['user'], diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/rewriteutil.py --- a/hgext3rd/evolve/rewriteutil.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/rewriteutil.py Wed Mar 21 16:06:17 2018 +0100 @@ -24,6 +24,7 @@ phases, repair, revset, + util, ) from mercurial.i18n import _ @@ -60,6 +61,10 @@ msg = _("cannot %s the null revision") % (action) hint = _("no changeset checked out") raise error.Abort(msg, hint=hint) + if any(util.safehasattr(r, 'rev') for r in revs): + msg = "rewriteutil.precheck called with ctx not revs" + repo.ui.develwarn(msg) + revs = (r.rev() for r in revs) publicrevs = repo.revs('%ld and public()', revs) if publicrevs: summary = _formatrevs(repo, publicrevs) diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/serveronly.py --- a/hgext3rd/evolve/serveronly.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/serveronly.py Wed Mar 21 16:06:17 2018 +0100 @@ -58,4 +58,6 @@ evolveopts = 'all' repo.ui.setconfig('experimental', 'evolution', evolveopts) if obsolete.isenabled(repo, 'exchange'): - repo.ui.setconfig('server', 'bundle1', False) + # if no config explicitly set, disable bundle1 + if not isinstance(repo.ui.config('server', 'bundle1'), str): + repo.ui.setconfig('server', 'bundle1', False) diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/stablerangecache.py --- a/hgext3rd/evolve/stablerangecache.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/stablerangecache.py Wed Mar 21 16:06:17 2018 +0100 @@ -366,11 +366,11 @@ if util.safehasattr(repo, 'updatecaches'): @localrepo.unfilteredmethod - def updatecaches(self, tr=None): + def updatecaches(self, tr=None, **kwargs): if utility.shouldwarmcache(self, tr): self.stablerange.update(self) self.stablerange.save(self) - super(stablerangerepo, self).updatecaches(tr) + super(stablerangerepo, self).updatecaches(tr, **kwargs) else: def transaction(self, *args, **kwargs): diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/stablesort.py --- a/hgext3rd/evolve/stablesort.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/stablesort.py Wed Mar 21 16:06:17 2018 +0100 @@ -14,7 +14,6 @@ from mercurial import ( commands, - cmdutil, localrepo, error, node as nodemod, @@ -76,7 +75,7 @@ raise error.Abort('unknown sorting method: "%s"' % method, hint='pick one of: %s' % valid_method) - displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True) + displayer = compat.changesetdisplayer(ui, repo, opts, buffered=True) kwargs = {} if opts['limit']: kwargs['limit'] = int(opts['limit']) @@ -673,11 +672,11 @@ if util.safehasattr(repo, 'updatecaches'): @localrepo.unfilteredmethod - def updatecaches(self, tr=None): + def updatecaches(self, tr=None, **kwargs): if utility.shouldwarmcache(self, tr): self.stablesort.update(self) self.stablesort.save(self) - super(stablesortrepo, self).updatecaches(tr) + super(stablesortrepo, self).updatecaches(tr, **kwargs) else: def transaction(self, *args, **kwargs): diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/state.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgext3rd/evolve/state.py Wed Mar 21 16:06:17 2018 +0100 @@ -0,0 +1,135 @@ +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +""" +This file contains class to wrap the state for commands and other +related logic. + +All the data related to the command state is stored as dictionary in the object. +The class has methods using which the data can be stored to disk in a file under +.hg/ directory. + +We store the data on disk in cbor, for which we use cbor library to serialize +and deserialize data. +""" + +from __future__ import absolute_import + +import errno +import struct + +from .thirdparty import cbor + +from mercurial import ( + error, + util, +) + +from mercurial.i18n import _ + +class cmdstate(): + """a wrapper class to store the state of commands like `evolve`, `grab` + + All the data for the state is stored in the form of key-value pairs in a + dictionary. + + The class object can write all the data to a file in .hg/ directory and also + can populate the object data reading that file + """ + + def __init__(self, repo, path='evolvestate', opts={}): + self._repo = repo + self.path = path + self.opts = opts + + def __nonzero__(self): + return self.exists() + + def __getitem__(self, key): + return self.opts[key] + + def __setitem__(self, key, value): + updates = {key: value} + self.opts.update(updates) + + def load(self): + """load the existing evolvestate file into the class object""" + op = self._read() + if isinstance(op, dict): + self.opts.update(op) + elif self.path == 'evolvestate': + # it is the old evolvestate file + oldop = _oldevolvestateread(self._repo) + self.opts.update(oldop) + + def addopts(self, opts): + """add more key-value pairs to the data stored by the object""" + self.opts.update(opts) + + def save(self): + """write all the evolvestate data stored in .hg/evolvestate file + + we use third-party library cbor to serialize data to write in the file. + """ + with self._repo.vfs(self.path, 'wb', atomictemp=True) as fp: + cbor.dump(self.opts, fp) + + def _read(self): + """reads the evolvestate file and returns a dictionary which contain + data in the same format as it was before storing""" + with self._repo.vfs(self.path, 'rb') as fp: + return cbor.load(fp) + + def delete(self): + """drop the evolvestate file if exists""" + util.unlinkpath(self._repo.vfs.join(self.path), ignoremissing=True) + + def exists(self): + """check whether the evolvestate file exists or not""" + return self._repo.vfs.exists(self.path) + +def _oldevolvestateread(repo): + """function to read the old evolvestate file + + This exists for BC reasons.""" + try: + f = repo.vfs('evolvestate') + except IOError as err: + if err.errno != errno.ENOENT: + raise + try: + versionblob = f.read(4) + if len(versionblob) < 4: + repo.ui.debug('ignoring corrupted evolvestate (file contains %i bits)' + % len(versionblob)) + return None + version = struct._unpack('>I', versionblob)[0] + if version != 0: + msg = _('unknown evolvestate version %i') % version + raise error.Abort(msg, hint=_('upgrade your evolve')) + records = [] + data = f.read() + off = 0 + end = len(data) + while off < end: + rtype = data[off] + off += 1 + length = struct._unpack('>I', data[off:(off + 4)])[0] + off += 4 + record = data[off:(off + length)] + off += length + if rtype == 't': + rtype, record = record[0], record[1:] + records.append((rtype, record)) + state = {} + for rtype, rdata in records: + if rtype == 'C': + state['current'] = rdata + elif rtype.lower(): + repo.ui.debug('ignore evolve state record type %s' % rtype) + else: + raise error.Abort(_('unknown evolvestate field type %r') + % rtype, hint=_('upgrade your evolve')) + return state + finally: + f.close() diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/templatekw.py --- a/hgext3rd/evolve/templatekw.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/templatekw.py Wed Mar 21 16:06:17 2018 +0100 @@ -9,13 +9,13 @@ """ from . import ( + compat, error, exthelper, obshistory ) from mercurial import ( - cmdutil, templatekw, node, util @@ -34,21 +34,29 @@ return 'obsolete' return '' -@eh.templatekw('troubles') -def showtroubles(**args): - """List of strings. Evolution troubles affecting the changeset - (zero or more of "unstable", "divergent" or "bumped").""" - ctx = args['ctx'] - try: - # specify plural= explicitly to trigger TypeError on hg < 4.2 - return templatekw.showlist('trouble', ctx.instabilities(), args, - plural='troubles') - except TypeError: - return templatekw.showlist('trouble', ctx.instabilities(), plural='troubles', - **args) +if util.safehasattr(templatekw, 'compatlist'): + @eh.templatekw('troubles', requires=set(['ctx', 'templ'])) + def showtroubles(context, mapping): + ctx = context.resource(mapping, 'ctx') + return templatekw.compatlist(context, mapping, 'trouble', + ctx.instabilities(), plural='troubles') +else: + # older template API in hg < 4.6 + @eh.templatekw('troubles') + def showtroubles(**args): + """List of strings. Evolution troubles affecting the changeset + (zero or more of "unstable", "divergent" or "bumped").""" + ctx = args['ctx'] + try: + # specify plural= explicitly to trigger TypeError on hg < 4.2 + return templatekw.showlist('trouble', ctx.instabilities(), args, + plural='troubles') + except TypeError: + return templatekw.showlist('trouble', ctx.instabilities(), plural='troubles', + **args) if util.safehasattr(templatekw, 'showpredecessors'): - eh.templatekw("precursors")(templatekw.showpredecessors) + templatekw.keywords["precursors"] = templatekw.showpredecessors else: # for version <= hg4.3 def closestprecursors(repo, nodeid): @@ -97,7 +105,7 @@ return directsuccessorssets(repo, nodeid) if util.safehasattr(templatekw, 'showsuccessorssets'): - eh.templatekw("successors")(templatekw.showsuccessorssets) + templatekw.keywords["successors"] = templatekw.showsuccessorssets else: # for version <= hg4.3 @@ -252,13 +260,33 @@ return "\n".join(lines) -@eh.templatekw("obsfatedata") -def showobsfatedata(repo, ctx, **args): - # Get the needed obsfate data - values = obsfatedata(repo, ctx) + +if util.safehasattr(templatekw, 'compatlist'): + @eh.templatekw('obsfatedata', requires=set(['ctx', 'templ'])) + def showobsfatedata(context, mapping): + ctx = context.resource(mapping, 'ctx') + repo = ctx.repo() + values = obsfatedata(repo, ctx) - if values is None: - return templatekw.showlist("obsfatedata", [], args) + if values is None: + return templatekw.compatlist(context, mapping, "obsfatedata", []) + args = mapping.copy() + args.pop('ctx') + args['templ'] = context.resource(mapping, 'templ') + return _showobsfatedata(repo, ctx, values, **args) +else: + # pre hg-4.6 + @eh.templatekw("obsfatedata") + def showobsfatedata(repo, ctx, **args): + # Get the needed obsfate data + values = obsfatedata(repo, ctx) + + if values is None: + return templatekw.showlist("obsfatedata", [], args) + + return _showobsfatedata(repo, ctx, values, **args) + +def _showobsfatedata(repo, ctx, values, **args): # Format each successorset successors list for raw in values: @@ -316,10 +344,10 @@ def showobsfate(*args, **kwargs): return showobsfatedata(*args, **kwargs) -if util.safehasattr(cmdutil.changeset_printer, '_showobsfate'): +if util.safehasattr(compat.changesetprinter, '_showobsfate'): pass # already included by default -elif util.safehasattr(cmdutil.changeset_printer, '_exthook'): - @eh.wrapfunction(cmdutil.changeset_printer, '_exthook') +elif util.safehasattr(compat.changesetprinter, '_exthook'): + @eh.wrapfunction(compat.changesetprinter, '_exthook') def exthook(original, self, ctx): # Call potential other extensions original(self, ctx) diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/evolve/utility.py --- a/hgext3rd/evolve/utility.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/evolve/utility.py Wed Mar 21 16:06:17 2018 +0100 @@ -5,8 +5,16 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. +import collections + +from mercurial.i18n import _ + from mercurial.node import nullrev +from . import ( + compat, +) + shorttemplate = "[{label('evolve.rev', rev)}] {desc|firstline}\n" def obsexcmsg(ui, message, important=False): @@ -66,3 +74,107 @@ if maxrevs is not None and maxrevs < len(repo.unfiltered()): return False return True + +class MultipleSuccessorsError(RuntimeError): + """Exception raised by _singlesuccessor when multiple successor sets exists + + The object contains the list of successorssets in its 'successorssets' + attribute to call to easily recover. + """ + + def __init__(self, successorssets): + self.successorssets = successorssets + +def builddependencies(repo, revs): + """returns dependency graphs giving an order to solve instability of revs + (see _orderrevs for more information on usage)""" + + # For each troubled revision we keep track of what instability if any should + # be resolved in order to resolve it. Example: + # dependencies = {3: [6], 6:[]} + # Means that: 6 has no dependency, 3 depends on 6 to be solved + dependencies = {} + # rdependencies is the inverted dict of dependencies + rdependencies = collections.defaultdict(set) + + for r in revs: + dependencies[r] = set() + for p in repo[r].parents(): + try: + succ = _singlesuccessor(repo, p) + except MultipleSuccessorsError as exc: + dependencies[r] = exc.successorssets + continue + if succ in revs: + dependencies[r].add(succ) + rdependencies[succ].add(r) + return dependencies, rdependencies + +def _singlesuccessor(repo, p): + """returns p (as rev) if not obsolete or its unique latest successors + + fail if there are no such successor""" + + if not p.obsolete(): + return p.rev() + obs = repo[p] + ui = repo.ui + newer = compat.successorssets(repo, obs.node()) + # search of a parent which is not killed + while not newer: + ui.debug("stabilize target %s is plain dead," + " trying to stabilize on its parent\n" % + obs) + obs = obs.parents()[0] + newer = compat.successorssets(repo, obs.node()) + if len(newer) > 1 or len(newer[0]) > 1: + raise MultipleSuccessorsError(newer) + + return repo[newer[0][0]].rev() + +def revselectionprompt(ui, repo, revs, customheader=""): + """function to prompt user to choose a revision from all the revs and return + that revision for further tasks + + revs is a list of rev number of revision from which one revision should be + choosed by the user + customheader is a text which the caller wants as the header of the prompt + which will list revisions to select + + returns value is: + rev number of revision choosed: if user choose a revision + None: if user entered a wrong input, user quit the prompt, + ui.interactive is not set + """ + + # ui.interactive is not set, fallback to default behavior and avoid showing + # the prompt + if not ui.configbool('ui', 'interactive'): + return None + + promptmsg = customheader + "\n" + for idx, rev in enumerate(revs): + curctx = repo[rev] + revmsg = _("%d: [%s] %s\n" % (idx, curctx, + curctx.description().split("\n")[0])) + promptmsg += revmsg + + promptmsg += _("q: quit the prompt\n") + promptmsg += _("enter the index of the revision you want to select:") + idxselected = ui.prompt(promptmsg) + + intidx = None + try: + intidx = int(idxselected) + except ValueError: + if idxselected == 'q': + return None + ui.write_err(_("invalid value '%s' entered for index\n") % idxselected) + return None + + if intidx >= len(revs) or intidx < 0: + # we can make this error message better + ui.write_err(_("invalid value '%d' entered for index\n") % intidx) + return None + + return revs[intidx] diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/serverminitopic.py --- a/hgext3rd/serverminitopic.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/serverminitopic.py Wed Mar 21 16:06:17 2018 +0100 @@ -68,7 +68,7 @@ def branchinfo(self, rev): """return branch name and close flag for rev, using and updating persistent cache.""" - phase = self._repo._phasecache.phase(self, rev) + phase = self._repo._phasecache.phase(self._repo, rev) if phase: ctx = self._repo[rev] return ctx.branch(), ctx.closesbranch() @@ -163,7 +163,7 @@ valid = super(_topiccache, self).validfor(repo) if not valid: return False - elif not mighttopic(repo) and self.phaseshash is None: + elif self.phaseshash is None: # phasehash at None means this is a branchmap # coming from a public only set return True diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/topic/__init__.py --- a/hgext3rd/topic/__init__.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/topic/__init__.py Wed Mar 21 16:06:17 2018 +0100 @@ -134,13 +134,14 @@ from . import ( compat, constants, + destination, + discovery, + evolvebits, flow, + randomname, revset as topicrevset, - destination, stack, topicmap, - discovery, - randomname ) if util.safehasattr(registrar, 'command'): @@ -175,9 +176,9 @@ 'topic.active': 'green', } -__version__ = '0.7.0' +__version__ = '0.8.0' -testedwith = '4.1.3 4.2.3 4.3.3 4.4.2' +testedwith = '4.1.3 4.2.3 4.3.3 4.4.2 4.5.2' minimumhgversion = '4.1' buglink = 'https://bz.mercurial-scm.org/' @@ -240,6 +241,12 @@ revlist = stack.stack(self._repo, topic=topic) try: return revlist.index(self.rev()) + except ValueError: + if self.obsolete(): + succ = evolvebits._singlesuccessor(self._repo, self) + if succ not in revlist: + return None + return revlist.index(succ) except IndexError: # Lets move to the last ctx of the current topic return None diff -r 7dce44b4abb6 -r d5adce52cef4 hgext3rd/topic/compat.py --- a/hgext3rd/topic/compat.py Wed Jan 24 15:08:09 2018 +0100 +++ b/hgext3rd/topic/compat.py Wed Mar 21 16:06:17 2018 +0100 @@ -7,6 +7,8 @@ """ from __future__ import absolute_import +import functools + from mercurial import ( obsolete, scmutil, @@ -27,6 +29,17 @@ if successorssets is None: successorssets = obsolete.successorssets +# Wrap obsolete.creatmarkers and make it accept but ignore "operation" argument +# for hg < 4.3 +createmarkers = obsolete.createmarkers +originalcreatemarkers = createmarkers +while isinstance(originalcreatemarkers, functools.partial): + originalcreatemarkers = originalcreatemarkers.func +if originalcreatemarkers.__code__.co_argcount < 6: + def createmarkers(repo, relations, flag=0, date=None, metadata=None, + operation=None): + return obsolete.createmarkers(repo, relations, flag, date, metadata) + def startpager(ui, cmd): """function to start a pager in case ui.pager() exists""" try: @@ -44,4 +57,4 @@ else: relations = [(repo[o], tuple(repo[n] for n in new)) for (o, new) in replacements.iteritems()] - obsolete.createmarkers(repo, relations) + createmarkers(repo, relations, operation=operation) diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-amend.t --- a/tests/test-amend.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-amend.t Wed Mar 21 16:06:17 2018 +0100 @@ -25,7 +25,7 @@ @ 6a022cbb61d5 (1) adda | x 07f494440405 (0) adda - rewritten(branch) as 6a022cbb61d5 by test (Thu Jan 01 00:00:00 1970 +0000) + rewritten(branch) as 6a022cbb61d5 using amend by test (Thu Jan 01 00:00:00 1970 +0000) note: this a note on the obsmarker and supported for hg>=4.4 $ hg branch diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-discovery-obshashrange.t --- a/tests/test-discovery-obshashrange.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-discovery-obshashrange.t Wed Mar 21 16:06:17 2018 +0100 @@ -34,11 +34,13 @@ * @0000000000000000000000000000000000000000 (*)> init server exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> -R server serve --stdio (glob) * @0000000000000000000000000000000000000000 (*)> -R server serve --stdio exited 0 after *.?? seconds (glob) - * @0000000000000000000000000000000000000000 (*)> debugbuilddag .+7 (glob) + * @0000000000000000000000000000000000000000 (*)> debugbuilddag .+7 (glob) (no-windows !) + * @0000000000000000000000000000000000000000 (*)> debugbuilddag ".+7" (glob) (windows !) * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 1 nodes (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (8r, 0o) (glob) - * @0000000000000000000000000000000000000000 (*)> debugbuilddag .+7 exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugbuilddag .+7 exited 0 after *.?? seconds (glob) (no-windows !) + * @0000000000000000000000000000000000000000 (*)> debugbuilddag ".+7" exited 0 after *.?? seconds (glob) (windows !) * @0000000000000000000000000000000000000000 (*)> blackbox (glob) $ rm .hg/blackbox.log $ hg log -G @@ -79,18 +81,18 @@ * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 66f7d451a68b85ed82ff5fcc254daf50c74144bd exited 0 after *.?? seconds (glob) - * @0000000000000000000000000000000000000000 (*)> debugobsolete bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 01241442b3c2bf3211e593b549c655ea65b295e3 --config 'experimental.obshashrange.max-revs=1' (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 01241442b3c2bf3211e593b549c655ea65b295e3 --config *experimental.obshashrange.max-revs=1* (glob) * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) - * @0000000000000000000000000000000000000000 (*)> debugobsolete bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 01241442b3c2bf3211e593b549c655ea65b295e3 --config 'experimental.obshashrange.max-revs=1' exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 01241442b3c2bf3211e593b549c655ea65b295e3 --config *experimental.obshashrange.max-revs=1* exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d (glob) * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d exited 0 after *.?? seconds (glob) - * @0000000000000000000000000000000000000000 (*)> debugobsolete dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 --config 'experimental.obshashrange.warm-cache=0' (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 --config *experimental.obshashrange.warm-cache=0* (glob) * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) - * @0000000000000000000000000000000000000000 (*)> debugobsolete dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 --config 'experimental.obshashrange.warm-cache=0' exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 --config *experimental.obshashrange.warm-cache=0* exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 4de32a90b66cd083ebf3c00b41277aa7abca51dd (glob) * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) @@ -150,7 +152,7 @@ cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} $ rm ../server/.hg/blackbox.log $ hg blackbox - * @0000000000000000000000000000000000000000 (*)> clone 'ssh://user@dummy/server' client exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> clone *ssh://user@dummy/server* client exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> pull --rev 4 (glob) * @0000000000000000000000000000000000000000 (*)> updated base branch cache in *.???? seconds (glob) * @0000000000000000000000000000000000000000 (*)> wrote base branch cache with 1 labels and 1 nodes (glob) @@ -175,10 +177,10 @@ $ hg debugobsolete ffffffffffffffffffffffffffffffffffffffff `getid '.'` $ hg push -f --debug pushing to ssh://user@dummy/server - running python "*/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) + running python "*/dummyssh" *user@dummy* *hg -R server serve --stdio* (glob) sending hello command sending between command - remote: 483 + remote: * (glob) remote: capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_obshashrange_v1 batch * (glob) remote: 1 preparing listkeys for "phases" @@ -213,7 +215,7 @@ 45f8b879de922f6a6e620ba04205730335b6fc7e sending unbundle command bundle2-output-bundle: "HG20", 4 parts total - bundle2-output-part: "replycaps" 185 bytes payload + bundle2-output-part: "replycaps" * bytes payload (glob) bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload bundle2-output-part: "phase-heads" 24 bytes payload bundle2-output-part: "obsmarkers" streamed payload @@ -382,10 +384,12 @@ (run 'hg heads' to see heads, 'hg merge' to merge) $ hg -R ../server blackbox - * @0000000000000000000000000000000000000000 (*)> -R ../server/ debugobsolete --rev '::tip' (glob) + * @0000000000000000000000000000000000000000 (*)> -R ../server/ debugobsolete --rev '::tip' (glob) (no-windows !) + * @0000000000000000000000000000000000000000 (*)> -R ../server/ debugobsolete --rev ::tip (glob) (windows !) * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) * @0000000000000000000000000000000000000000 (*)> writing .hg/cache/tags2-visible with 0 tags (glob) - * @0000000000000000000000000000000000000000 (*)> -R ../server/ debugobsolete --rev '::tip' exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> -R ../server/ debugobsolete --rev '::tip' exited 0 after *.?? seconds (glob) (no-windows !) + * @0000000000000000000000000000000000000000 (*)> -R ../server/ debugobsolete --rev ::tip exited 0 after *.?? seconds (glob) (windows !) * @0000000000000000000000000000000000000000 (*)> -R ../server debugobsolete aaaaaaa11111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd (glob) * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) @@ -489,18 +493,22 @@ 3 2dc09a01254d 3 1 4 26f996446ecb 1 66f7d451a68b 1 1 2 327c7dd73d29 $ hg blackbox - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete --rev '::6' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete --rev '::6' (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete --rev ::6 (glob) (windows !) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> writing .hg/cache/tags2-visible with 0 tags (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete --rev '::6' exited 0 after *.?? seconds (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete --rev '::6' exited 0 after *.?? seconds (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete --rev ::6 exited 0 after *.?? seconds (glob) (windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev "heads(all())" (glob) (windows !) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-stablerange-mergepoint cache reset (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-depthcache cache reset (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (8r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (8r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache clean - new markers affect 2 changeset and cached ranges (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (2r, 3o) (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' exited 0 after *.?? seconds (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev "heads(all())" exited 0 after *.?? seconds (glob) (windows !) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r f69452c5b1af6cbaaa56ef50cf94fff5bcc6ca23 (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-stablerange-mergepoint cache reset (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-depthcache cache reset (glob) @@ -509,14 +517,16 @@ * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 2/7 mismatch - 1 obshashrange queries in *.???? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 2o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r f69452c5b1af6cbaaa56ef50cf94fff5bcc6ca23 exited 0 after *.?? seconds (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'desc("r3")' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'desc("r3")' (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev "desc(\"r3\")" (glob) (windows !) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-stablerange-mergepoint cache reset (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-depthcache cache reset (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (8r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (8r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache clean - new markers affect 2 changeset and cached ranges (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 2o) (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'desc("r3")' exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'desc("r3")' exited 0 after *.?? seconds (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev "desc(\"r3\")" exited 0 after *.?? seconds (glob) (windows !) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> blackbox (glob) $ rm .hg/blackbox.log @@ -576,14 +586,16 @@ $ hg rollback repository tip rolled back to revision 7 (undo pull) $ hg blackbox - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev "heads(all())" (glob) (windows !) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-stablerange-mergepoint cache reset (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-depthcache cache reset (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (8r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (8r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache clean - new markers affect 1 changeset and cached ranges (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' exited 0 after *.?? seconds (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev "heads(all())" exited 0 after *.?? seconds (glob) (windows !) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-stablerange-mergepoint cache reset (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-depthcache cache reset (glob) @@ -641,8 +653,10 @@ new changesets 4de32a90b66c (run 'hg update' to get a working copy) $ hg blackbox - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev "heads(all())" (glob) (windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' exited 0 after *.?? seconds (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev "heads(all())" exited 0 after *.?? seconds (glob) (windows !) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 0/8 mismatch - 1 obshashrange queries in *.???? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (1r, 1o) (glob) @@ -747,15 +761,18 @@ o 0 1ea73414a91b r0 $ hg blackbox - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev "heads(all())" (glob) (windows !) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> writing .hg/cache/tags2-visible with 0 tags (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (1r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (1r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 1o) (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' exited 0 after *.?? seconds (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev "heads(all())" exited 0 after *.?? seconds (glob) (windows !) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G exited 0 after *.?? seconds (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> --config 'extensions.strip=' strip -r 'desc("foo")' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> --config 'extensions.strip=' strip -r 'desc("foo")' (glob) (no-windows !) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> --config "extensions.strip=" strip -r "desc(\"foo\")" (glob) (windows !) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> saved backup bundle to $TESTTMP/client/.hg/strip-backup/45f8b879de92-94c82517-backup.hg (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-obscache cache reset (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (5r, 11o) (glob) @@ -773,7 +790,8 @@ * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated base branch cache in *.???? seconds (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> wrote base branch cache with 1 labels and 1 nodes (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> 3 incoming changes - new heads: 4de32a90b66c (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> --config 'extensions.strip=' strip -r 'desc("foo")' exited 0 after *.?? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> --config 'extensions.strip=' strip -r 'desc("foo")' exited 0 after *.?? seconds (glob) (no-windows !) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> --config "extensions.strip=" strip -r "desc(\"foo\")" exited 0 after *.?? seconds (glob) (windows !) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> log -G (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> writing .hg/cache/tags2-visible with 0 tags (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> log -G exited 0 after *.?? seconds (glob) diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-divergent.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-drop.t --- a/tests/test-drop.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-drop.t Wed Mar 21 16:06:17 2018 +0100 @@ -220,7 +220,7 @@ summary: add base ============ obsmark ============ - 34b6c051bf1f78db6aef400776de5cb964470207 a2c06c884bfe53d3840026248bd8a7eafa152df8 0 (*) {'ef1': '*', 'user': 'test'} (glob) + 34b6c051bf1f78db6aef400776de5cb964470207 a2c06c884bfe53d3840026248bd8a7eafa152df8 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} $ hg drop . 0 files updated, 0 files merged, 1 files removed, 0 files unresolved working directory now at 19509a42b0d0 diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-continue.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-continue.t Wed Mar 21 16:06:17 2018 +0100 @@ -0,0 +1,375 @@ +Testing the continue functionality of `hg evolve` + + $ cat >> $HGRCPATH < [ui] + > interactive = True + > [alias] + > glog = log -GT "{rev}:{node|short} {desc}\n ({bookmarks}) {phase}" + > [extensions] + > rebase = + > EOF + $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH + +Setting up the repo + + $ hg init repo + $ cd repo + $ echo ".*\.orig" > .hgignore + $ hg add .hgignore + $ hg ci -m "added hgignore" + $ for ch in a b c d; do echo foo>$ch; hg add $ch; hg ci -qm "added "$ch; done + + $ hg glog + @ 4:c41c793e0ef1 added d + | () draft + o 3:ca1b80f7960a added c + | () draft + o 2:b1661037fa25 added b + | () draft + o 1:c7586e2a9264 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + +Simple case of evolve --continue + + $ hg up ca1b80f7960a + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo bar > d + $ hg add d + $ hg amend + 1 new orphan changesets + $ hg glog + @ 5:cb6a2ab625bb added c + | () draft + | o 4:c41c793e0ef1 added d + | | () draft + | x 3:ca1b80f7960a added c + |/ () draft + o 2:b1661037fa25 added b + | () draft + o 1:c7586e2a9264 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --all + move:[4] added d + atop:[5] added c + merging d + warning: conflicts while merging d! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ echo foo > d + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + + $ hg evolve --continue + evolving 4:c41c793e0ef1 "added d" + working directory is now at 2a4e03d422e2 + + $ hg glog + @ 6:2a4e03d422e2 added d + | () draft + o 5:cb6a2ab625bb added c + | () draft + o 2:b1661037fa25 added b + | () draft + o 1:c7586e2a9264 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + +Case when conflicts resolution lead to empty wdir in evolve --continue + + $ echo foo > e + $ hg ci -Aqm "added e" + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [6] added d + $ echo bar > e + $ hg add e + $ hg amend + 1 new orphan changesets + + $ hg glog + @ 8:00a5c774cc37 added d + | () draft + | o 7:ad0a59d83efe added e + | | () draft + | x 6:2a4e03d422e2 added d + |/ () draft + o 5:cb6a2ab625bb added c + | () draft + o 2:b1661037fa25 added b + | () draft + o 1:c7586e2a9264 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve + move:[7] added e + atop:[8] added d + merging e + warning: conflicts while merging e! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ echo bar > e + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + $ hg diff + +XXX: maybe we should add a message here about evolve resulting in no commit + $ hg evolve --continue + evolving 7:ad0a59d83efe "added e" + + $ hg glog + @ 8:00a5c774cc37 added d + | () draft + o 5:cb6a2ab625bb added c + | () draft + o 2:b1661037fa25 added b + | () draft + o 1:c7586e2a9264 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + +Case when there are a lot of revision to continue + + $ hg up c7586e2a9264 + 0 files updated, 0 files merged, 4 files removed, 0 files unresolved + $ echo bar > b + $ hg add b + $ hg amend + 3 new orphan changesets + + $ hg evolve --all + move:[2] added b + atop:[9] added a + merging b + warning: conflicts while merging b! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ echo foo > b + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + $ hg evolve --continue + evolving 2:b1661037fa25 "added b" + move:[5] added c + atop:[10] added b + move:[8] added d + atop:[11] added c + working directory is now at 6642d2c9176e + + $ hg glog + @ 12:6642d2c9176e added d + | () draft + o 11:95665a2de664 added c + | () draft + o 10:87f748868183 added b + | () draft + o 9:53b632d203d8 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + +Conlicts -> resolve -> continue -> conflicts -> resolve -> continue +Test multiple conflicts in one evolve + + $ for ch in f g h; do echo foo > $ch; hg add $ch; hg ci -m "added "$ch; done; + + $ hg glog + @ 15:09becba8f97d added h + | () draft + o 14:5aa7b2bbd944 added g + | () draft + o 13:be88f889b6dc added f + | () draft + o 12:6642d2c9176e added d + | () draft + o 11:95665a2de664 added c + | () draft + o 10:87f748868183 added b + | () draft + o 9:53b632d203d8 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg up 95665a2de664 + 1 files updated, 0 files merged, 4 files removed, 0 files unresolved + + $ echo bar > f + $ echo bar > h + $ hg add f h + $ hg amend + 4 new orphan changesets + + $ hg glog + @ 16:645135c5caa4 added c + | () draft + | o 15:09becba8f97d added h + | | () draft + | o 14:5aa7b2bbd944 added g + | | () draft + | o 13:be88f889b6dc added f + | | () draft + | o 12:6642d2c9176e added d + | | () draft + | x 11:95665a2de664 added c + |/ () draft + o 10:87f748868183 added b + | () draft + o 9:53b632d203d8 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --all + move:[12] added d + atop:[16] added c + move:[13] added f + atop:[17] added d + merging f + warning: conflicts while merging f! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ echo foo > f + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + $ hg evolve --continue + evolving 13:be88f889b6dc "added f" + move:[14] added g + atop:[18] added f + move:[15] added h + atop:[19] added g + merging h + warning: conflicts while merging h! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ echo foo > h + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + $ hg evolve --continue + evolving 15:09becba8f97d "added h" + working directory is now at 3ba9d3d1b089 + +Make sure, confirmopt is respected while continue + + $ hg glog + @ 20:3ba9d3d1b089 added h + | () draft + o 19:981e615b14ca added g + | () draft + o 18:5794f1a3cbb2 added f + | () draft + o 17:e47537da02b3 added d + | () draft + o 16:645135c5caa4 added c + | () draft + o 10:87f748868183 added b + | () draft + o 9:53b632d203d8 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg up 5794f1a3cbb2 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo bar > g + $ hg add g + $ hg amend + 2 new orphan changesets + + $ hg evolve --all --confirm< y + > EOF + move:[19] added g + atop:[21] added f + perform evolve? [Ny] y + merging g + warning: conflicts while merging g! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ echo foo > g + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + +XXX: this should have asked for confirmation + + $ hg evolve --continue< y + > EOF + evolving 19:981e615b14ca "added g" + move:[20] added h + atop:[22] added g + perform evolve? [Ny] y + working directory is now at af6bd002a48d + + $ hg glog + @ 23:af6bd002a48d added h + | () draft + o 22:d2c94a8f44bd added g + | () draft + o 21:9849fa96c885 added f + | () draft + o 17:e47537da02b3 added d + | () draft + o 16:645135c5caa4 added c + | () draft + o 10:87f748868183 added b + | () draft + o 9:53b632d203d8 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + +Testing `evolve --continue` after `hg next --evolve` + + $ hg up .^^ + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo foobar > g + $ hg amend + 2 new orphan changesets + + $ hg next --evolve + move:[22] added g + atop:[24] added f + merging g + warning: conflicts while merging g! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + $ echo foo > g + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + $ hg evolve --continue + evolving 22:d2c94a8f44bd "added g" diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-cycles.t --- a/tests/test-evolve-cycles.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-evolve-cycles.t Wed Mar 21 16:06:17 2018 +0100 @@ -62,19 +62,19 @@ | tag: tip | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 1:2a34000d3544 + | obsolete: rewritten using prune as 1:2a34000d3544 | summary: C | x changeset: 2:c473644ee0e9 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 3:a8df460dbbfe + | obsolete: rewritten using prune as 3:a8df460dbbfe | summary: B | @ changeset: 1:2a34000d3544 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 2:c473644ee0e9 + | obsolete: rewritten using prune as 2:c473644ee0e9 | summary: A | o changeset: 0:ea207398892e @@ -89,48 +89,48 @@ $ hg obslog "desc(A)" --hidden @ 2a34000d3544 (1) A - | rewritten(description, parent, content) as c473644ee0e9 by test (*) (glob) + | rewritten(description, parent, content) as c473644ee0e9 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | x a8df460dbbfe (3) C - | rewritten(description, parent, content) as 2a34000d3544 by test (*) (glob) + | rewritten(description, parent, content) as 2a34000d3544 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | x c473644ee0e9 (2) B - | rewritten(description, parent, content) as a8df460dbbfe by test (*) (glob) + | rewritten(description, parent, content) as a8df460dbbfe using prune by test (Thu Jan 01 00:00:00 1970 +0000) | $ hg obslog "desc(B)" --hidden @ 2a34000d3544 (1) A - | rewritten(description, parent, content) as c473644ee0e9 by test (*) (glob) + | rewritten(description, parent, content) as c473644ee0e9 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | x a8df460dbbfe (3) C - | rewritten(description, parent, content) as 2a34000d3544 by test (*) (glob) + | rewritten(description, parent, content) as 2a34000d3544 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | x c473644ee0e9 (2) B - | rewritten(description, parent, content) as a8df460dbbfe by test (*) (glob) + | rewritten(description, parent, content) as a8df460dbbfe using prune by test (Thu Jan 01 00:00:00 1970 +0000) | $ hg obslog "desc(C)" --hidden @ 2a34000d3544 (1) A - | rewritten(description, parent, content) as c473644ee0e9 by test (*) (glob) + | rewritten(description, parent, content) as c473644ee0e9 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | x a8df460dbbfe (3) C - | rewritten(description, parent, content) as 2a34000d3544 by test (*) (glob) + | rewritten(description, parent, content) as 2a34000d3544 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | x c473644ee0e9 (2) B - | rewritten(description, parent, content) as a8df460dbbfe by test (*) (glob) + | rewritten(description, parent, content) as a8df460dbbfe using prune by test (Thu Jan 01 00:00:00 1970 +0000) | Check that all option don't crash on a cycle either $ hg obslog "desc(C)" --hidden --all @ 2a34000d3544 (1) A - | rewritten(description, parent, content) as c473644ee0e9 by test (*) (glob) + | rewritten(description, parent, content) as c473644ee0e9 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | x a8df460dbbfe (3) C - | rewritten(description, parent, content) as 2a34000d3544 by test (*) (glob) + | rewritten(description, parent, content) as 2a34000d3544 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | x c473644ee0e9 (2) B - | rewritten(description, parent, content) as a8df460dbbfe by test (*) (glob) + | rewritten(description, parent, content) as a8df460dbbfe using prune by test (Thu Jan 01 00:00:00 1970 +0000) | Test with multiple cyles @@ -207,37 +207,37 @@ | tag: tip | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 4:868d2e0eb19c + | obsolete: rewritten using prune as 4:868d2e0eb19c | summary: F | x changeset: 5:0da815c333f6 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 6:d9f908fde1a1 + | obsolete: rewritten using prune as 6:d9f908fde1a1 | summary: E | @ changeset: 4:868d2e0eb19c | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 5:0da815c333f6 + | obsolete: rewritten using prune as 5:0da815c333f6 | summary: D | x changeset: 3:a8df460dbbfe | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: split as 1:2a34000d3544, 4:868d2e0eb19c + | obsolete: split using prune as 1:2a34000d3544, 4:868d2e0eb19c | summary: C | x changeset: 2:c473644ee0e9 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 3:a8df460dbbfe + | obsolete: rewritten using prune as 3:a8df460dbbfe | summary: B | x changeset: 1:2a34000d3544 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 2:c473644ee0e9 + | obsolete: rewritten using prune as 2:c473644ee0e9 | summary: A | o changeset: 0:ea207398892e @@ -252,42 +252,42 @@ $ hg obslog "desc(D)" --hidden x 0da815c333f6 (5) E - | rewritten(description, parent, content) as d9f908fde1a1 by test (*) (glob) + | rewritten(description, parent, content) as d9f908fde1a1 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | @ 868d2e0eb19c (4) D - |\ rewritten(description, parent, content) as 0da815c333f6 by test (*) (glob) + |\ rewritten(description, parent, content) as 0da815c333f6 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | | x d9f908fde1a1 (6) F - | | rewritten(description, parent, content) as 868d2e0eb19c by test (*) (glob) + | | rewritten(description, parent, content) as 868d2e0eb19c using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | +---x 2a34000d3544 (1) A - | | rewritten(description, parent, content) as c473644ee0e9 by test (*) (glob) + | | rewritten(description, parent, content) as c473644ee0e9 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | x | a8df460dbbfe (3) C - | | rewritten(description, parent, content) as 2a34000d3544, 868d2e0eb19c by test (*) (glob) + | | rewritten(description, parent, content) as 2a34000d3544, 868d2e0eb19c using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | x | c473644ee0e9 (2) B - | | rewritten(description, parent, content) as a8df460dbbfe by test (*) (glob) + | | rewritten(description, parent, content) as a8df460dbbfe using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | Check that all option don't crash either on a cycle $ hg obslog --all --hidden "desc(F)" x 0da815c333f6 (5) E - | rewritten(description, parent, content) as d9f908fde1a1 by test (*) (glob) + | rewritten(description, parent, content) as d9f908fde1a1 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | @ 868d2e0eb19c (4) D - |\ rewritten(description, parent, content) as 0da815c333f6 by test (*) (glob) + |\ rewritten(description, parent, content) as 0da815c333f6 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | | x d9f908fde1a1 (6) F - | | rewritten(description, parent, content) as 868d2e0eb19c by test (*) (glob) + | | rewritten(description, parent, content) as 868d2e0eb19c using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | +---x 2a34000d3544 (1) A - | | rewritten(description, parent, content) as c473644ee0e9 by test (*) (glob) + | | rewritten(description, parent, content) as c473644ee0e9 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | x | a8df460dbbfe (3) C - | | rewritten(description, parent, content) as 2a34000d3544, 868d2e0eb19c by test (*) (glob) + | | rewritten(description, parent, content) as 2a34000d3544, 868d2e0eb19c using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | x | c473644ee0e9 (2) B - | | rewritten(description, parent, content) as a8df460dbbfe by test (*) (glob) + | | rewritten(description, parent, content) as a8df460dbbfe using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | Check the json output is valid in this case @@ -305,6 +305,7 @@ "parent", "content" ], + "operation": "prune", "succnodes": [ "0da815c333f6" ], @@ -328,6 +329,7 @@ "parent", "content" ], + "operation": "prune", "succnodes": [ "868d2e0eb19c" ], @@ -351,6 +353,7 @@ "parent", "content" ], + "operation": "prune", "succnodes": [ "d9f908fde1a1" ], @@ -374,6 +377,7 @@ "parent", "content" ], + "operation": "prune", "succnodes": [ "2a34000d3544", "868d2e0eb19c" @@ -398,6 +402,7 @@ "parent", "content" ], + "operation": "prune", "succnodes": [ "a8df460dbbfe" ], @@ -421,6 +426,7 @@ "parent", "content" ], + "operation": "prune", "succnodes": [ "c473644ee0e9" ], diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-effectflags.t --- a/tests/test-evolve-effectflags.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-evolve-effectflags.t Wed Mar 21 16:06:17 2018 +0100 @@ -34,7 +34,7 @@ @ fdf9bde5129a (2) A1 | x 471f378eab4c (1) A0 - rewritten(description) as fdf9bde5129a by test (*) (glob) + rewritten(description) as fdf9bde5129a using amend by test (Thu Jan 01 00:00:00 1970 +0000) $ hg log --hidden -r "desc(A0)" changeset: 1:471f378eab4c @@ -58,7 +58,7 @@ @ 5485c92d3433 (4) B0 | x ef4a313b1e0a (3) B0 - rewritten(user) as 5485c92d3433 by test (*) (glob) + rewritten(user) as 5485c92d3433 using amend by test (Thu Jan 01 00:00:00 1970 +0000) $ hg log --hidden -r "ef4a313b1e0a" changeset: 3:ef4a313b1e0a @@ -82,7 +82,7 @@ @ 4dd84345082e (6) B1 | x 2ef0680ff450 (5) B1 - rewritten(date) as 4dd84345082e by test (*) (glob) + rewritten(date) as 4dd84345082e using amend by test (Thu Jan 01 00:00:00 1970 +0000) $ hg log --hidden -r "2ef0680ff450" changeset: 5:2ef0680ff450 @@ -109,7 +109,7 @@ @ 14a01456e057 (8) B2 | x bd3db8264cee (7) B2 - rewritten(branch) as 14a01456e057 by test (*) (glob) + rewritten(branch) as 14a01456e057 using amend by test (Thu Jan 01 00:00:00 1970 +0000) $ hg log --hidden -r "bd3db8264cee" changeset: 7:bd3db8264cee @@ -138,7 +138,7 @@ @ da86aa2f19a3 (11) D0 | x c85eff83a034 (10) D0 - rewritten(parent) as da86aa2f19a3 by test (*) (glob) + rewritten(parent) as da86aa2f19a3 using rebase by test (Thu Jan 01 00:00:00 1970 +0000) $ hg log --hidden -r "c85eff83a034" changeset: 10:c85eff83a034 @@ -163,7 +163,7 @@ @ 75781fdbdbf5 (13) E0 | x ebfe0333e0d9 (12) E0 - rewritten(content) as 75781fdbdbf5 by test (*) (glob) + rewritten(content) as 75781fdbdbf5 using amend by test (Thu Jan 01 00:00:00 1970 +0000) $ hg log --hidden -r "ebfe0333e0d9" changeset: 12:ebfe0333e0d9 @@ -189,7 +189,7 @@ @ a94e0fd5f1c8 (15) F1 | x fad47e5bd78e (14) F0 - rewritten(description, user, date, branch) as a94e0fd5f1c8 by test (*) (glob) + rewritten(description, user, date, branch) as a94e0fd5f1c8 using amend by test (Thu Jan 01 00:00:00 1970 +0000) $ hg log --hidden -r "fad47e5bd78e" changeset: 14:fad47e5bd78e @@ -244,7 +244,7 @@ o e509e2eb3df5 (19) H1 | x b57fed8d8322 (17) H1 - rewritten(parent) as e509e2eb3df5 by test (*) (glob) + rewritten(parent) as e509e2eb3df5 using rebase by test (Thu Jan 01 00:00:00 1970 +0000) $ hg log --hidden -r "b57fed8d8322" changeset: 17:b57fed8d8322 @@ -269,7 +269,7 @@ @ 12c6238b5e37 (22) I0 | x 2f599e54c1c6 (21) I0 - rewritten(meta) as 12c6238b5e37 by test (*) (glob) + rewritten(meta) as 12c6238b5e37 using amend by test (Thu Jan 01 00:00:00 1970 +0000) $ hg log --hidden -r "2f599e54c1c6" changeset: 21:2f599e54c1c6 diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-obshistory-complex.t --- a/tests/test-evolve-obshistory-complex.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-evolve-obshistory-complex.t Wed Mar 21 16:06:17 2018 +0100 @@ -78,11 +78,11 @@ @ 100cc25b765f (9) fold2 |\ x | 0da815c333f6 (5) E - / rewritten(description, content) as 100cc25b765f by test (Thu Jan 01 00:00:00 1970 +0000) + / rewritten(description, content) as 100cc25b765f using fold by test (Thu Jan 01 00:00:00 1970 +0000) | note: folding changesets to test | x d9f908fde1a1 (6) F - rewritten(description, parent, content) as 100cc25b765f by test (Thu Jan 01 00:00:00 1970 +0000) + rewritten(description, parent, content) as 100cc25b765f using fold by test (Thu Jan 01 00:00:00 1970 +0000) note: folding changesets to test $ hg log -G @@ -110,25 +110,25 @@ x | | changeset: 4:868d2e0eb19c | | | user: test | | | date: Thu Jan 01 00:00:00 1970 +0000 - | | | obsolete: rewritten as 8:d15d0ffc75f6 + | | | obsolete: rewritten using fold as 8:d15d0ffc75f6 | | | summary: D | | | x | | changeset: 3:a8df460dbbfe |/ / user: test | | date: Thu Jan 01 00:00:00 1970 +0000 - | | obsolete: rewritten as 8:d15d0ffc75f6 + | | obsolete: rewritten using fold as 8:d15d0ffc75f6 | | summary: C | | x | changeset: 2:c473644ee0e9 | | user: test | | date: Thu Jan 01 00:00:00 1970 +0000 - | | obsolete: rewritten as 7:b868bc49b0a4 + | | obsolete: rewritten using fold as 7:b868bc49b0a4 | | summary: B | | x | changeset: 1:2a34000d3544 |/ user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 7:b868bc49b0a4 + | obsolete: rewritten using fold as 7:b868bc49b0a4 | summary: A | o changeset: 0:ea207398892e @@ -284,25 +284,25 @@ x | | changeset: 4:868d2e0eb19c | | | user: test | | | date: Thu Jan 01 00:00:00 1970 +0000 - | | | obsolete: split as 12:7b3290f6e0a0, 13:d0f33db50670 + | | | obsolete: split using fold, split as 12:7b3290f6e0a0, 13:d0f33db50670 | | | summary: D | | | x | | changeset: 3:a8df460dbbfe |/ / user: test | | date: Thu Jan 01 00:00:00 1970 +0000 - | | obsolete: split as 12:7b3290f6e0a0, 13:d0f33db50670 + | | obsolete: split using fold, split as 12:7b3290f6e0a0, 13:d0f33db50670 | | summary: C | | x | changeset: 2:c473644ee0e9 | | user: test | | date: Thu Jan 01 00:00:00 1970 +0000 - | | obsolete: split as 10:19e14c8397fc, 11:e036916b63ea + | | obsolete: split using fold, split as 10:19e14c8397fc, 11:e036916b63ea | | summary: B | | x | changeset: 1:2a34000d3544 |/ user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: split as 10:19e14c8397fc, 11:e036916b63ea + | obsolete: split using fold, split as 10:19e14c8397fc, 11:e036916b63ea | summary: A | o changeset: 0:ea207398892e @@ -349,25 +349,25 @@ x | | changeset: 4:868d2e0eb19c | | | user: test | | | date: Thu Jan 01 00:00:00 1970 +0000 - | | | obsolete: split as 12:7b3290f6e0a0, 14:ec31316faa9d + | | | obsolete: split using fold, prune, split as 12:7b3290f6e0a0, 14:ec31316faa9d | | | summary: D | | | x | | changeset: 3:a8df460dbbfe |/ / user: test | | date: Thu Jan 01 00:00:00 1970 +0000 - | | obsolete: split as 12:7b3290f6e0a0, 14:ec31316faa9d + | | obsolete: split using fold, prune, split as 12:7b3290f6e0a0, 14:ec31316faa9d | | summary: C | | x | changeset: 2:c473644ee0e9 | | user: test | | date: Thu Jan 01 00:00:00 1970 +0000 - | | obsolete: split as 10:19e14c8397fc, 12:7b3290f6e0a0 + | | obsolete: split using fold, prune, split as 10:19e14c8397fc, 12:7b3290f6e0a0 | | summary: B | | x | changeset: 1:2a34000d3544 |/ user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: split as 10:19e14c8397fc, 12:7b3290f6e0a0 + | obsolete: split using fold, prune, split as 10:19e14c8397fc, 12:7b3290f6e0a0 | summary: A | o changeset: 0:ea207398892e @@ -385,25 +385,25 @@ o 7b3290f6e0a0 (12) fold1 |\ x | d15d0ffc75f6 (8) fold1 - |\ \ rewritten(parent, content) as 7b3290f6e0a0, d0f33db50670 by test (*) (glob) + |\ \ rewritten(parent, content) as 7b3290f6e0a0, d0f33db50670 using split by test (Thu Jan 01 00:00:00 1970 +0000) | | | | | x e036916b63ea (11) fold0 - | | | rewritten(description, parent, content) as 7b3290f6e0a0 by test (*) (glob) + | | | rewritten(description, parent, content) as 7b3290f6e0a0 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | | x | | 868d2e0eb19c (4) D - / / rewritten(description, parent, content) as d15d0ffc75f6 by test (*) (glob) + / / rewritten(description, parent, content) as d15d0ffc75f6 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | | x | a8df460dbbfe (3) C - / rewritten(description, content) as d15d0ffc75f6 by test (*) (glob) + / rewritten(description, content) as d15d0ffc75f6 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | x b868bc49b0a4 (7) fold0 - |\ rewritten(parent, content) as 19e14c8397fc, e036916b63ea by test (*) (glob) + |\ rewritten(parent, content) as 19e14c8397fc, e036916b63ea using split by test (Thu Jan 01 00:00:00 1970 +0000) | | x | 2a34000d3544 (1) A - / rewritten(description, content) as b868bc49b0a4 by test (*) (glob) + / rewritten(description, content) as b868bc49b0a4 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | x c473644ee0e9 (2) B - rewritten(description, parent, content) as b868bc49b0a4 by test (*) (glob) + rewritten(description, parent, content) as b868bc49b0a4 using fold by test (Thu Jan 01 00:00:00 1970 +0000) While with all option, we should see 15 changesets @@ -417,38 +417,38 @@ | | | | o ec31316faa9d (14) fold2 | | | |/| | | | x | 100cc25b765f (9) fold2 - | | | |\ \ rewritten(parent, content) as d4a000f63ee9, ec31316faa9d by test (*) (glob) + | | | |\ \ rewritten(parent, content) as d4a000f63ee9, ec31316faa9d using split by test (Thu Jan 01 00:00:00 1970 +0000) | | | | | | | +-------x d0f33db50670 (13) fold1 - | | | | | rewritten(description, parent, content) as ec31316faa9d by test (*) (glob) + | | | | | rewritten(description, parent, content) as ec31316faa9d using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | | | | note: this is a note stored in obsmarker in prune | | | | | +---x | | e036916b63ea (11) fold0 - | | / / rewritten(description, parent, content) as 7b3290f6e0a0 by test (*) (glob) + | | / / rewritten(description, parent, content) as 7b3290f6e0a0 using prune by test (Thu Jan 01 00:00:00 1970 +0000) | | | | | | x | 0da815c333f6 (5) E - | | / rewritten(description, content) as 100cc25b765f by test (*) (glob) + | | / rewritten(description, content) as 100cc25b765f using fold by test (Thu Jan 01 00:00:00 1970 +0000) | | | note: folding changesets to test | | | x | | b868bc49b0a4 (7) fold0 - |\ \ \ rewritten(parent, content) as 19e14c8397fc, e036916b63ea by test (*) (glob) + |\ \ \ rewritten(parent, content) as 19e14c8397fc, e036916b63ea using split by test (Thu Jan 01 00:00:00 1970 +0000) | | | | | | x | d15d0ffc75f6 (8) fold1 - | | |\ \ rewritten(parent, content) as 7b3290f6e0a0, d0f33db50670 by test (*) (glob) + | | |\ \ rewritten(parent, content) as 7b3290f6e0a0, d0f33db50670 using split by test (Thu Jan 01 00:00:00 1970 +0000) | | | | | | | | | x d9f908fde1a1 (6) F - | | | | rewritten(description, parent, content) as 100cc25b765f by test (*) (glob) + | | | | rewritten(description, parent, content) as 100cc25b765f using fold by test (Thu Jan 01 00:00:00 1970 +0000) | | | | note: folding changesets to test | | | | x | | | 2a34000d3544 (1) A - / / / rewritten(description, content) as b868bc49b0a4 by test (*) (glob) + / / / rewritten(description, content) as b868bc49b0a4 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | | | | x | 868d2e0eb19c (4) D - | / rewritten(description, parent, content) as d15d0ffc75f6 by test (*) (glob) + | / rewritten(description, parent, content) as d15d0ffc75f6 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | | | x a8df460dbbfe (3) C - | rewritten(description, content) as d15d0ffc75f6 by test (*) (glob) + | rewritten(description, content) as d15d0ffc75f6 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | x c473644ee0e9 (2) B - rewritten(description, parent, content) as b868bc49b0a4 by test (*) (glob) + rewritten(description, parent, content) as b868bc49b0a4 using fold by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-obshistory.t --- a/tests/test-evolve-obshistory.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-evolve-obshistory.t Wed Mar 21 16:06:17 2018 +0100 @@ -55,7 +55,7 @@ @ 4ae3a4151de9 (2) A1 | x 471f378eab4c (1) A0 - rewritten(description, content) as 4ae3a4151de9 by test (*) (glob) + rewritten(description, content) as 4ae3a4151de9 using amend by test (*) (glob) diff -r 471f378eab4c -r 4ae3a4151de9 changeset-description --- a/changeset-description +++ b/changeset-description @@ -77,7 +77,7 @@ @ [evolve.node|4ae3a4151de9] [evolve.rev|(2)] [evolve.short_description|A1] | x [evolve.node|471f378eab4c] [evolve.rev|(1)] [evolve.short_description|A0] - [evolve.verb|rewritten](description, content) as [evolve.node|4ae3a4151de9] by [evolve.user|test] [evolve.date|(Thu Jan 01 00:00:00 1970 +0000)] + [evolve.verb|rewritten](description, content) as [evolve.node|4ae3a4151de9] using [evolve.operation|amend] by [evolve.user|test] [evolve.date|(Thu Jan 01 00:00:00 1970 +0000)] [diff.diffline|diff -r 471f378eab4c -r 4ae3a4151de9 changeset-description] [diff.file_a|--- a/changeset-description] [diff.file_b|+++ b/changeset-description] @@ -99,7 +99,7 @@ $ hg obslog --no-graph --patch 4ae3a4151de9 4ae3a4151de9 (2) A1 471f378eab4c (1) A0 - rewritten(description, content) as 4ae3a4151de9 by test (Thu Jan 01 00:00:00 1970 +0000) + rewritten(description, content) as 4ae3a4151de9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r 4ae3a4151de9 changeset-description --- a/changeset-description +++ b/changeset-description @@ -141,6 +141,7 @@ "description", "content" ], + "operation": "amend", "succnodes": [ "4ae3a4151de9" ], @@ -155,7 +156,7 @@ ] $ hg obslog --hidden --patch 471f378eab4c x 471f378eab4c (1) A0 - rewritten(description, content) as 4ae3a4151de9 by test (*) (glob) + rewritten(description, content) as 4ae3a4151de9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r 4ae3a4151de9 changeset-description --- a/changeset-description +++ b/changeset-description @@ -186,6 +187,7 @@ *, (glob) "content" ], + "operation": "amend", "succnodes": [ "4ae3a4151de9" ], @@ -244,7 +246,7 @@ | tag: tip | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: pruned + | obsolete: pruned using prune | summary: B0 | @ changeset: 1:471f378eab4c @@ -263,7 +265,7 @@ $ hg obslog 'desc(B0)' --hidden --patch x 0dec01379d3b (2) B0 - pruned by test (*) (glob) + pruned using prune by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, no successors) $ hg obslog 'desc(B0)' --hidden --no-graph -Tjson | python -m json.tool @@ -275,6 +277,7 @@ *, (glob) 0 (glob) ], + "operation": "prune", "user": "test", "verb": "pruned" } @@ -384,7 +387,7 @@ | x changeset: 1:471597cad322 |/ user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: split as 2:337fec4d2edc, 3:f257fde29c7a + | obsolete: split using split as 2:337fec4d2edc, 3:f257fde29c7a | summary: A0 | o changeset: 0:ea207398892e @@ -398,7 +401,7 @@ Check that debugobshistory on splitted commit show both targets $ hg obslog 471597cad322 --hidden --patch x 471597cad322 (1) A0 - rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob) + rewritten(parent, content) as 337fec4d2edc, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) note: testing split (No patch available, too many successors (2)) @@ -416,6 +419,7 @@ "content" ], "note": "testing split", + "operation": "split", "succnodes": [ "337fec4d2edc", "f257fde29c7a" @@ -435,7 +439,7 @@ o 337fec4d2edc (2) A0 | x 471597cad322 (1) A0 - rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob) + rewritten(parent, content) as 337fec4d2edc, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) note: testing split (No patch available, too many successors (2)) @@ -446,7 +450,7 @@ | @ f257fde29c7a (3) A0 |/ x 471597cad322 (1) A0 - rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob) + rewritten(parent, content) as 337fec4d2edc, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) note: testing split (No patch available, too many successors (2)) @@ -456,7 +460,7 @@ @ f257fde29c7a (3) A0 | x 471597cad322 (1) A0 - rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob) + rewritten(parent, content) as 337fec4d2edc, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) note: testing split (No patch available, too many successors (2)) @@ -467,7 +471,7 @@ | @ f257fde29c7a (3) A0 |/ x 471597cad322 (1) A0 - rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob) + rewritten(parent, content) as 337fec4d2edc, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) note: testing split (No patch available, too many successors (2)) @@ -478,7 +482,7 @@ | @ f257fde29c7a (3) A0 |/ x 471597cad322 (1) A0 - rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob) + rewritten(parent, content) as 337fec4d2edc, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) note: testing split (No patch available, too many successors (2)) @@ -490,7 +494,7 @@ | @ f257fde29c7a (3) A0 |/ x 471597cad322 (1) A0 - rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob) + rewritten(parent, content) as 337fec4d2edc, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) note: testing split (No patch available, too many successors (2)) @@ -646,7 +650,7 @@ | x changeset: 1:de7290d8b885 |/ user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: split as 2:337fec4d2edc, 3:f257fde29c7a, 4:1ae8bc733a14, 5:c7f044602e9b + | obsolete: split using split as 2:337fec4d2edc, 3:f257fde29c7a, 4:1ae8bc733a14, 5:c7f044602e9b | summary: A0 | o changeset: 0:ea207398892e @@ -659,7 +663,7 @@ $ hg obslog de7290d8b885 --hidden --patch x de7290d8b885 (1) A0 - rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a by test (*) (glob) + rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, too many successors (4)) $ hg obslog de7290d8b885 --hidden --all --patch @@ -672,7 +676,7 @@ | o f257fde29c7a (3) A0 |/ x de7290d8b885 (1) A0 - rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a by test (*) (glob) + rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, too many successors (4)) $ hg obslog de7290d8b885 --hidden --no-graph -Tjson | python -m json.tool @@ -688,6 +692,7 @@ "parent", "content" ], + "operation": "split", "succnodes": [ "1ae8bc733a14", "337fec4d2edc", @@ -707,7 +712,7 @@ @ c7f044602e9b (5) A0 | x de7290d8b885 (1) A0 - rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a by test (*) (glob) + rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, too many successors (4)) $ hg obslog c7f044602e9b --no-graph -Tjson | python -m json.tool @@ -729,6 +734,7 @@ "parent", "content" ], + "operation": "split", "succnodes": [ "1ae8bc733a14", "337fec4d2edc", @@ -755,7 +761,7 @@ | o f257fde29c7a (3) A0 |/ x de7290d8b885 (1) A0 - rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a by test (*) (glob) + rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, too many successors (4)) $ hg obslog 5 --all --patch @@ -768,7 +774,7 @@ | o f257fde29c7a (3) A0 |/ x de7290d8b885 (1) A0 - rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a by test (*) (glob) + rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a using split by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, too many successors (4)) $ hg update de7290d8b885 @@ -822,13 +828,13 @@ | x changeset: 2:0dec01379d3b | | user: test | | date: Thu Jan 01 00:00:00 1970 +0000 - | | obsolete: rewritten as 3:eb5a0daa2192 + | | obsolete: rewritten using fold as 3:eb5a0daa2192 | | summary: B0 | | | x changeset: 1:471f378eab4c |/ user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 3:eb5a0daa2192 + | obsolete: rewritten using fold as 3:eb5a0daa2192 | summary: A0 | o changeset: 0:ea207398892e @@ -843,7 +849,7 @@ the revision with the target $ hg obslog --hidden 471f378eab4c --patch x 471f378eab4c (1) A0 - rewritten(description, content) as eb5a0daa2192 by test (*) (glob) + rewritten(description, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r eb5a0daa2192 changeset-description --- a/changeset-description +++ b/changeset-description @@ -863,11 +869,11 @@ @ eb5a0daa2192 (3) C0 |\ x | 0dec01379d3b (2) B0 - / rewritten(description, parent, content) as eb5a0daa2192 by test (*) (glob) + / rewritten(description, parent, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | (No patch available, changesets rebased) | x 471f378eab4c (1) A0 - rewritten(description, content) as eb5a0daa2192 by test (*) (glob) + rewritten(description, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r eb5a0daa2192 changeset-description --- a/changeset-description +++ b/changeset-description @@ -886,7 +892,7 @@ the revision with the target $ hg obslog --hidden 0dec01379d3b --patch x 0dec01379d3b (2) B0 - rewritten(description, parent, content) as eb5a0daa2192 by test (*) (glob) + rewritten(description, parent, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, changesets rebased) Check that with all option, all changesets are shown @@ -894,11 +900,11 @@ @ eb5a0daa2192 (3) C0 |\ x | 0dec01379d3b (2) B0 - / rewritten(description, parent, content) as eb5a0daa2192 by test (*) (glob) + / rewritten(description, parent, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | (No patch available, changesets rebased) | x 471f378eab4c (1) A0 - rewritten(description, content) as eb5a0daa2192 by test (*) (glob) + rewritten(description, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r eb5a0daa2192 changeset-description --- a/changeset-description +++ b/changeset-description @@ -919,11 +925,11 @@ @ eb5a0daa2192 (3) C0 |\ x | 0dec01379d3b (2) B0 - / rewritten(description, parent, content) as eb5a0daa2192 by test (*) (glob) + / rewritten(description, parent, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | (No patch available, changesets rebased) | x 471f378eab4c (1) A0 - rewritten(description, content) as eb5a0daa2192 by test (*) (glob) + rewritten(description, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r eb5a0daa2192 changeset-description --- a/changeset-description +++ b/changeset-description @@ -957,6 +963,7 @@ "description", "content" ], + "operation": "fold", "succnodes": [ "eb5a0daa2192" ], @@ -980,6 +987,7 @@ "parent", "content" ], + "operation": "fold", "succnodes": [ "eb5a0daa2192" ], @@ -1079,7 +1087,7 @@ Check that debugobshistory on the divergent revision show both destinations $ hg obslog --hidden 471f378eab4c --patch x 471f378eab4c (1) A0 - rewritten(description) as 65b757b745b9 by test (*) (glob) + rewritten(description) as 65b757b745b9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r 65b757b745b9 changeset-description --- a/changeset-description +++ b/changeset-description @@ -1087,7 +1095,7 @@ -A0 +A2 - rewritten(description) as fdf9bde5129a by test (*) (glob) + rewritten(description) as fdf9bde5129a using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r fdf9bde5129a changeset-description --- a/changeset-description +++ b/changeset-description @@ -1104,7 +1112,7 @@ | o fdf9bde5129a (2) A1 |/ x 471f378eab4c (1) A0 - rewritten(description) as 65b757b745b9 by test (*) (glob) + rewritten(description) as 65b757b745b9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r 65b757b745b9 changeset-description --- a/changeset-description +++ b/changeset-description @@ -1112,7 +1120,7 @@ -A0 +A2 - rewritten(description) as fdf9bde5129a by test (*) (glob) + rewritten(description) as fdf9bde5129a using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r fdf9bde5129a changeset-description --- a/changeset-description +++ b/changeset-description @@ -1133,6 +1141,7 @@ "effect": [ "description" ], + "operation": "amend", "succnodes": [ "65b757b745b9" ], @@ -1147,6 +1156,7 @@ "effect": [ "description" ], + "operation": "amend", "succnodes": [ "fdf9bde5129a" ], @@ -1165,7 +1175,7 @@ o fdf9bde5129a (2) A1 | x 471f378eab4c (1) A0 - rewritten(description) as 65b757b745b9 by test (*) (glob) + rewritten(description) as 65b757b745b9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r 65b757b745b9 changeset-description --- a/changeset-description +++ b/changeset-description @@ -1173,7 +1183,7 @@ -A0 +A2 - rewritten(description) as fdf9bde5129a by test (*) (glob) + rewritten(description) as fdf9bde5129a using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r fdf9bde5129a changeset-description --- a/changeset-description +++ b/changeset-description @@ -1190,7 +1200,7 @@ | o fdf9bde5129a (2) A1 |/ x 471f378eab4c (1) A0 - rewritten(description) as 65b757b745b9 by test (*) (glob) + rewritten(description) as 65b757b745b9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r 65b757b745b9 changeset-description --- a/changeset-description +++ b/changeset-description @@ -1198,7 +1208,7 @@ -A0 +A2 - rewritten(description) as fdf9bde5129a by test (*) (glob) + rewritten(description) as fdf9bde5129a using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r fdf9bde5129a changeset-description --- a/changeset-description +++ b/changeset-description @@ -1213,7 +1223,7 @@ @ 65b757b745b9 (3) A2 | x 471f378eab4c (1) A0 - rewritten(description) as 65b757b745b9 by test (*) (glob) + rewritten(description) as 65b757b745b9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r 65b757b745b9 changeset-description --- a/changeset-description +++ b/changeset-description @@ -1221,7 +1231,7 @@ -A0 +A2 - rewritten(description) as fdf9bde5129a by test (*) (glob) + rewritten(description) as fdf9bde5129a using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r fdf9bde5129a changeset-description --- a/changeset-description +++ b/changeset-description @@ -1237,7 +1247,7 @@ | o fdf9bde5129a (2) A1 |/ x 471f378eab4c (1) A0 - rewritten(description) as 65b757b745b9 by test (*) (glob) + rewritten(description) as 65b757b745b9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r 65b757b745b9 changeset-description --- a/changeset-description +++ b/changeset-description @@ -1245,7 +1255,7 @@ -A0 +A2 - rewritten(description) as fdf9bde5129a by test (*) (glob) + rewritten(description) as fdf9bde5129a using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r fdf9bde5129a changeset-description --- a/changeset-description +++ b/changeset-description @@ -1262,7 +1272,7 @@ | o fdf9bde5129a (2) A1 |/ x 471f378eab4c (1) A0 - rewritten(description) as 65b757b745b9 by test (*) (glob) + rewritten(description) as 65b757b745b9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r 65b757b745b9 changeset-description --- a/changeset-description +++ b/changeset-description @@ -1270,7 +1280,7 @@ -A0 +A2 - rewritten(description) as fdf9bde5129a by test (*) (glob) + rewritten(description) as fdf9bde5129a using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r fdf9bde5129a changeset-description --- a/changeset-description +++ b/changeset-description @@ -1297,6 +1307,7 @@ "effect": [ "description" ], + "operation": "amend", "succnodes": [ "65b757b745b9" ], @@ -1311,6 +1322,7 @@ "effect": [ "description" ], + "operation": "amend", "succnodes": [ "fdf9bde5129a" ], @@ -1389,7 +1401,7 @@ | | parent: 1:471f378eab4c | | user: test | | date: Thu Jan 01 00:00:00 1970 +0000 - | | obsolete: rewritten as 4:eb5a0daa2192 + | | obsolete: rewritten using fold as 4:eb5a0daa2192 | | summary: B1 | | | | x changeset: 2:0dec01379d3b @@ -1401,7 +1413,7 @@ | x changeset: 1:471f378eab4c |/ user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 4:eb5a0daa2192 + | obsolete: rewritten using fold as 4:eb5a0daa2192 | summary: A0 | o changeset: 0:ea207398892e @@ -1417,7 +1429,7 @@ @ eb5a0daa2192 (4) C0 |\ x | 471f378eab4c (1) A0 - / rewritten(description, content) as eb5a0daa2192 by test (*) (glob) + / rewritten(description, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | diff -r 471f378eab4c -r eb5a0daa2192 changeset-description | --- a/changeset-description | +++ b/changeset-description @@ -1433,11 +1445,11 @@ | | x b7ea6d14e664 (3) B1 - | rewritten(description, parent, content) as eb5a0daa2192 by test (*) (glob) + | rewritten(description, parent, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | (No patch available, changesets rebased) | x 0dec01379d3b (2) B0 - rewritten(description) as b7ea6d14e664 by test (*) (glob) + rewritten(description) as b7ea6d14e664 using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 0dec01379d3b -r b7ea6d14e664 changeset-description --- a/changeset-description +++ b/changeset-description @@ -1451,7 +1463,7 @@ @ eb5a0daa2192 (4) C0 |\ x | 471f378eab4c (1) A0 - / rewritten(description, content) as eb5a0daa2192 by test (*) (glob) + / rewritten(description, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | diff -r 471f378eab4c -r eb5a0daa2192 changeset-description | --- a/changeset-description | +++ b/changeset-description @@ -1467,11 +1479,11 @@ | | x b7ea6d14e664 (3) B1 - | rewritten(description, parent, content) as eb5a0daa2192 by test (*) (glob) + | rewritten(description, parent, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000) | (No patch available, changesets rebased) | x 0dec01379d3b (2) B0 - rewritten(description) as b7ea6d14e664 by test (*) (glob) + rewritten(description) as b7ea6d14e664 using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 0dec01379d3b -r b7ea6d14e664 changeset-description --- a/changeset-description +++ b/changeset-description @@ -1500,6 +1512,7 @@ *, (glob) "content" ], + "operation": "fold", "succnodes": [ "eb5a0daa2192" ], @@ -1521,6 +1534,7 @@ "effect": [ "description" ], + "operation": "amend", "succnodes": [ "b7ea6d14e664" ], @@ -1543,6 +1557,7 @@ "description", "content" ], + "operation": "fold", "succnodes": [ "eb5a0daa2192" ], @@ -1646,7 +1661,7 @@ @ 7a230b46bf61 (3) A2 | x fdf9bde5129a (2) A1 - | rewritten(description) as 7a230b46bf61 by test (*) (glob) + | rewritten(description) as 7a230b46bf61 using amend by test (Thu Jan 01 00:00:00 1970 +0000) | diff -r fdf9bde5129a -r 7a230b46bf61 changeset-description | --- a/changeset-description | +++ b/changeset-description @@ -1656,7 +1671,7 @@ | | x 471f378eab4c (1) A0 - rewritten(description) as fdf9bde5129a by test (*) (glob) + rewritten(description) as fdf9bde5129a using amend by test (Thu Jan 01 00:00:00 1970 +0000) diff -r 471f378eab4c -r fdf9bde5129a changeset-description --- a/changeset-description +++ b/changeset-description @@ -1685,21 +1700,21 @@ o 7a230b46bf61 (2) A2 | x fdf9bde5129a - | rewritten(description) as 7a230b46bf61 by test (*) (glob) + | rewritten(description) as 7a230b46bf61 using amend by test (Thu Jan 01 00:00:00 1970 +0000) | (No patch available, context is not local) | @ 471f378eab4c (1) A0 - rewritten(description) as fdf9bde5129a by test (*) (glob) + rewritten(description) as fdf9bde5129a using amend by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, successor is unknown locally) $ hg obslog 7a230b46bf61 --color=debug --patch o [evolve.node|7a230b46bf61] [evolve.rev|(2)] [evolve.short_description|A2] | x [evolve.node evolve.missing_change_ctx|fdf9bde5129a] - | [evolve.verb|rewritten](description) as [evolve.node|7a230b46bf61] by [evolve.user|test] [evolve.date|(*)] (glob) + | [evolve.verb|rewritten](description) as [evolve.node|7a230b46bf61] using [evolve.operation|amend] by [evolve.user|test] [evolve.date|(Thu Jan 01 00:00:00 1970 +0000)] | (No patch available, context is not local) | @ [evolve.node|471f378eab4c] [evolve.rev|(1)] [evolve.short_description|A0] - [evolve.verb|rewritten](description) as [evolve.node|fdf9bde5129a] by [evolve.user|test] [evolve.date|(*)] (glob) + [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) diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-order.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-orphan-merge.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-orphan-merge.t Wed Mar 21 16:06:17 2018 +0100 @@ -0,0 +1,606 @@ +** Testing resolution of orphans by `hg evolve` when merges are involved ** + + $ cat >> $HGRCPATH < [ui] + > interactive = True + > [alias] + > glog = log -GT "{rev}:{node|short} {desc}\n ({bookmarks}) {phase}" + > [extensions] + > rebase = + > EOF + $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH + +Repo Setup + + $ hg init repo + $ cd repo + $ echo ".*\.orig" > .hgignore + $ hg add .hgignore + $ hg ci -m "added hgignore" + +An orphan merge changeset with one of the parent obsoleted +========================================================== + +1) When merging both the parents does not result in conflicts +------------------------------------------------------------- + + $ echo foo > a + $ hg ci -Aqm "added a" + $ hg up .^ + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo foo > b + $ hg ci -Aqm "added b" + $ hg merge + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg ci -m "merging a and b" + + $ hg glog + @ 3:3b2b6f4652ee merging a and b + |\ () draft + | o 2:d76850646258 added b + | | () draft + o | 1:c7586e2a9264 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + +Testing with obsoleting the second parent + + $ hg up d76850646258 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo bar > b + $ hg amend + 1 new orphan changesets + + $ hg glog + @ 4:64370c9805e7 added b + | () draft + | o 3:3b2b6f4652ee merging a and b + | |\ () draft + +---x 2:d76850646258 added b + | | () draft + | o 1:c7586e2a9264 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --all + move:[3] merging a and b + atop:[4] added b + working directory is now at 91fd62122a4b + + $ hg glog + @ 5:91fd62122a4b merging a and b + |\ () draft + | o 4:64370c9805e7 added b + | | () draft + o | 1:c7586e2a9264 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg parents + changeset: 5:91fd62122a4b + tag: tip + parent: 4:64370c9805e7 + parent: 1:c7586e2a9264 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: merging a and b + + +Testing with obsoleting the first parent + + $ hg up c7586e2a9264 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo bar > a + $ hg amend + 1 new orphan changesets + + $ hg glog + @ 6:3d41537b44ca added a + | () draft + | o 5:91fd62122a4b merging a and b + | |\ () draft + +---o 4:64370c9805e7 added b + | | () draft + | x 1:c7586e2a9264 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --all + move:[5] merging a and b + atop:[6] added a + working directory is now at 968d205ba4d8 + + $ hg glog + @ 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 + + $ hg parents + changeset: 7:968d205ba4d8 + tag: tip + parent: 6:3d41537b44ca + parent: 4:64370c9805e7 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: merging a and b + +2) When merging both the parents resulted in conflicts +------------------------------------------------------ + + $ hg up 8fa14d15e168 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ echo foo > c + $ hg ci -Aqm "foo to c" + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [0] added hgignore + $ echo bar > c + $ hg ci -Aqm "bar to c" + + $ hg glog + @ 9:d0f84b25d4e3 bar to c + | () 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 + + $ hg merge + merging c + warning: conflicts while merging c! (edit, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon + [1] + $ echo foobar > c + $ hg resolve -m + (no more unresolved files) + $ hg ci -m "foobar to c" + + $ hg glog + @ 10:fd41d25a3e90 foobar to c + |\ () draft + | o 9:d0f84b25d4e3 bar to c + | | () draft + o | 8:1c165c673853 foo to c + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + +Testing with first parent obsoleted + + $ hg up 1c165c673853 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo FOO > c + $ hg amend + 1 new orphan changesets + + $ hg glog + @ 11:31c317b7bdb1 foo to c + | () draft + | o 10:fd41d25a3e90 foobar to c + | |\ () draft + +---o 9:d0f84b25d4e3 bar to c + | | () draft + | x 8:1c165c673853 foo to c + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --all + move:[10] foobar to c + atop:[11] foo to c + merging c + warning: conflicts while merging c! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ echo FOObar > c + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + $ hg evolve --continue + evolving 10:fd41d25a3e90 "foobar to c" + working directory is now at c5405d2da7a1 + + $ hg glog + @ 12:c5405d2da7a1 foobar to c + |\ () draft + | o 11:31c317b7bdb1 foo to c + | | () draft + o | 9:d0f84b25d4e3 bar to c + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg parents + changeset: 12:c5405d2da7a1 + tag: tip + parent: 9:d0f84b25d4e3 + parent: 11:31c317b7bdb1 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: foobar to c + +Testing a conlficting merge with second parent obsoleted + + $ hg up 31c317b7bdb1 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo foo > c + $ hg amend + 1 new orphan changesets + + $ hg glog + @ 13:928097d0b5b5 foo to c + | () draft + | o 12:c5405d2da7a1 foobar to c + | |\ () draft + +---x 11:31c317b7bdb1 foo to c + | | () draft + | o 9:d0f84b25d4e3 bar to c + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --all + move:[12] foobar to c + atop:[13] foo to c + merging c + warning: conflicts while merging c! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ echo foobar > c + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + + $ hg evolve --continue + evolving 12:c5405d2da7a1 "foobar to c" + working directory is now at dc1948a6eeab + + $ hg glog + @ 14:dc1948a6eeab foobar to c + |\ () draft + | o 13:928097d0b5b5 foo to c + | | () draft + o | 9:d0f84b25d4e3 bar to c + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + +3) When stabilizing other changesets resulted in orphan merge changeset +----------------------------------------------------------------------- + + $ hg prune -r d0f84b25d4e3 -r 928097d0b5b5 -r dc1948a6eeab + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + working directory now at 8fa14d15e168 + 3 changesets pruned + + $ for ch in l m; do echo foo > $ch; hg ci -Aqm "added "$ch; done; + $ hg up 8fa14d15e168 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ for ch in x y; do echo foo > $ch; hg ci -Aqm "added "$ch; done; + $ hg glog + @ 18:863d11043c67 added y + | () draft + o 17:3f2247835c1d added x + | () draft + | o 16:e44dc179e7f5 added m + | | () draft + | o 15:8634bee7bf1e added l + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg merge + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg ci -m "merge commit" + + $ hg up 8634bee7bf1e + 0 files updated, 0 files merged, 3 files removed, 0 files unresolved + $ echo bar > l + $ hg amend + 2 new orphan changesets + + $ hg glog + @ 20:fccc9de66799 added l + | () draft + | o 19:190763373d8b merge commit + | |\ () draft + | | o 18:863d11043c67 added y + | | | () draft + +---o 17:3f2247835c1d added x + | | () draft + | o 16:e44dc179e7f5 added m + | | () draft + | x 15:8634bee7bf1e added l + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + $ hg evolve --all + move:[16] added m + atop:[20] added l + move:[19] merge commit + atop:[21] added m + working directory is now at a446ad3e6700 + + $ hg glog + @ 22:a446ad3e6700 merge commit + |\ () draft + | o 21:495d2039f8f1 added m + | | () draft + | o 20:fccc9de66799 added l + | | () draft + o | 18:863d11043c67 added y + | | () draft + o | 17:3f2247835c1d added x + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + +4) When both the parents of the merge changeset are obsolete with a succ +------------------------------------------------------------------------ + + $ hg prune -r a446ad3e6700 -r 495d2039f8f1 -r 863d11043c67 + 0 files updated, 0 files merged, 3 files removed, 0 files unresolved + working directory now at fccc9de66799 + 3 changesets pruned + + $ hg glog + @ 20:fccc9de66799 added l + | () draft + | o 17:3f2247835c1d added x + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg merge + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg ci -m "merged l and x" + + $ hg up fccc9de66799 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo foobar > l + $ hg amend + 1 new orphan changesets + $ hg up 3f2247835c1d + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo bar > x + $ hg amend + $ hg glog + @ 25:cdf6547da25f added x + | () draft + | o 24:3f371171d767 added l + |/ () draft + | o 23:7b78a9784f3e merged l and x + | |\ () draft + +---x 20:fccc9de66799 added l + | | () draft + | x 17:3f2247835c1d added x + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + +XXX: We should handle this case too + $ hg evolve --all + move:[23] merged l and x + atop:[25] added x + move:[26] merged l and x + atop:[24] added l + working directory is now at adb665a78e08 + + $ hg glog + @ 27:adb665a78e08 merged l and x + |\ () draft + | o 25:cdf6547da25f added x + | | () draft + o | 24:3f371171d767 added l + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID adb665a78e08b962cff415301058d782086c0f33 + # Parent 3f371171d767ef79cf85d156cf46d4035960fcf0 + # Parent cdf6547da25f1ca5d01102302ad713f444547b48 + merged l and x + + diff -r 3f371171d767 -r adb665a78e08 x + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 + +++ b/x Thu Jan 01 00:00:00 1970 +0000 + @@ -0,0 +1,1 @@ + +bar + + $ hg parents + changeset: 27:adb665a78e08 + tag: tip + parent: 24:3f371171d767 + parent: 25:cdf6547da25f + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: merged l and x + + +5) When one of the merge parent is pruned without a successor +------------------------------------------------------------- + + $ hg prune -r cdf6547da25f + 1 changesets pruned + 1 new orphan changesets + $ hg glog + @ 27:adb665a78e08 merged l and x + |\ () draft + | x 25:cdf6547da25f added x + | | () draft + o | 24:3f371171d767 added l + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --rev . + move:[27] merged l and x + atop:[0] added hgignore + working directory is now at fb8fe870ae7d + + $ hg glog + @ 28:fb8fe870ae7d merged l and x + |\ () draft + | o 24:3f371171d767 added l + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + +6) When one parent is pruned without successor and the other parent of merge is +the parent of the pruned commit +-------------------------------------------------------------------------------- + + $ hg glog + @ 28:fb8fe870ae7d merged l and x + |\ () draft + | o 24:3f371171d767 added l + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg prune -r 3f371171d767 + 1 changesets pruned + 1 new orphan changesets + + $ hg glog + @ 28:fb8fe870ae7d merged l and x + |\ () draft + | x 24:3f371171d767 added l + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + +This is the right thing to do here. When you have a merge changeset, and one +parent is pruned and parent of that pruned parent is same as another parent of +the merge changeset, that should lead to merge changeset being a non-merge +changeset and non-pruned changeset as its only parent + +If you look at the above graph, the side part: + +\ + x +/ + +is redundant now as the changeset is pruned and we should remove this chain +while evolving. + +This case can occur a lot of times in workflows where people make branches and +merge them again. After getting their work done, they may want to get rid of +that branch and they prune all their changeset, which will result in this +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. + + $ hg evolve -r . + move:[28] merged l and x + atop:[0] added hgignore + working directory is now at b61ba77b924a + + $ hg glog + @ 29:b61ba77b924a merged l and x + | () draft + o 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 now at 8fa14d15e168 + 1 changesets pruned + $ hg up null + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ echo foo > foo + $ hg add foo + $ hg ci -m "added foo" + created new head + + $ hg merge + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg ci -m "merge commit" + $ hg glog + @ 31:32beb84b9dbc merge commit + |\ () draft + | o 30:f3ba8b99bb6f added foo + | () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg prune -r f3ba8b99bb6f + 1 changesets pruned + 1 new orphan changesets + + $ hg glog + @ 31:32beb84b9dbc merge commit + |\ () draft + | x 30:f3ba8b99bb6f added foo + | () draft + o 0:8fa14d15e168 added hgignore + () draft + +The current behavior seems to be the correct behavior in the above case. This is +also another case which can arise flow merge workflow where people start a +branch from null changeset and merge it and then prune it or get rid of it. + +Also if you look at the above graph, the side part: + +\ + x + +becomes redundant as the changeset is pruned without successor and we should +just remove that chain. + + $ hg evolve -r . + move:[31] merge commit + atop:[-1] + working directory is now at d2a03dd8c951 + + $ hg glog + @ 32:d2a03dd8c951 merge commit + | () draft + o 0:8fa14d15e168 added hgignore + () draft diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-orphan-split.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-orphan-split.t Wed Mar 21 16:06:17 2018 +0100 @@ -0,0 +1,271 @@ +** Testing resolution of orphans by `hg evolve` where an obsolete changeset has +multiple successors ** + + $ cat >> $HGRCPATH < [ui] + > interactive = True + > [alias] + > glog = log -GT "{rev}:{node|short} {desc}\n ({bookmarks}) {phase}" + > [extensions] + > rebase = + > EOF + $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH + +Repo Setup + + $ hg init repo + $ cd repo + $ echo ".*\.orig" > .hgignore + $ hg add .hgignore + $ hg ci -m "added hgignore" + +An orphan changeset with parent got splitted +-------------------------------------------- + + $ for ch in a b c; do echo foo > $ch; done; + + $ hg add a b + $ hg ci -m "added a and b" + $ hg add c + $ hg ci -m "added c" + + $ hg glog + @ 2:86e1ebf1ca61 added c + | () draft + o 1:d0ddb614efbd added a and b + | () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg split -r 1 < y + > y + > n + > y + > EOF + 0 files updated, 0 files merged, 3 files removed, 0 files unresolved + adding a + adding b + diff --git a/a b/a + new file mode 100644 + examine changes to 'a'? [Ynesfdaq?] y + + @@ -0,0 +1,1 @@ + +foo + record change 1/2 to 'a'? [Ynesfdaq?] y + + diff --git a/b b/b + new file mode 100644 + examine changes to 'b'? [Ynesfdaq?] n + + created new head + Done splitting? [yN] y + + $ hg glog + @ 4:8b179cffc81c added a and b + | () draft + o 3:bd3735d4dab0 added a and b + | () draft + | o 2:86e1ebf1ca61 added c + | | () draft + | x 1:d0ddb614efbd added a and b + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve + move:[2] added c + atop:[4] added a and b + working directory is now at af13f0560b31 + + $ hg glog + @ 5:af13f0560b31 added c + | () draft + o 4:8b179cffc81c added a and b + | () draft + o 3:bd3735d4dab0 added a and b + | () draft + o 0:8fa14d15e168 added hgignore + () draft + +When the successors does not form a linear chain and are multiple heads +----------------------------------------------------------------------- + + $ hg fold -r .^^::. --exact -m "added a b c" + 3 changesets folded + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg glog + @ 6:f89e4764f2ed added a b c + | () draft + o 0:8fa14d15e168 added hgignore + () draft + $ echo foo > d + $ hg ci -Aqm "added d" + + $ hg glog + @ 7:d48a30875f01 added d + | () draft + o 6:f89e4764f2ed added a b c + | () draft + o 0:8fa14d15e168 added hgignore + () draft + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [6] added a b c + $ hg split -r . < y + > n + > y + > y + > y + > y + > y + > EOF + 0 files updated, 0 files merged, 3 files removed, 0 files unresolved + adding a + adding b + adding c + diff --git a/a b/a + new file mode 100644 + examine changes to 'a'? [Ynesfdaq?] y + + @@ -0,0 +1,1 @@ + +foo + record change 1/3 to 'a'? [Ynesfdaq?] n + + diff --git a/b b/b + new file mode 100644 + examine changes to 'b'? [Ynesfdaq?] y + + @@ -0,0 +1,1 @@ + +foo + record change 2/3 to 'b'? [Ynesfdaq?] y + + diff --git a/c b/c + new file mode 100644 + examine changes to 'c'? [Ynesfdaq?] y + + @@ -0,0 +1,1 @@ + +foo + record change 3/3 to 'c'? [Ynesfdaq?] y + + created new head + Done splitting? [yN] y + + $ hg glog + @ 9:c0fbf8aaf6c4 added a b c + | () draft + o 8:f2632392aefe added a b c + | () draft + | o 7:d48a30875f01 added d + | | () draft + | x 6:f89e4764f2ed added a b c + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg rebase -r . -d 8fa14d15e168 + rebasing 9:c0fbf8aaf6c4 "added a b c" (tip) + $ hg glog + @ 10:7f87764e5b64 added a b c + | () draft + | o 8:f2632392aefe added a b c + |/ () draft + | o 7:d48a30875f01 added d + | | () draft + | x 6:f89e4764f2ed added a b c + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --dry-run < 0 + > EOF + ancestor 'd48a30875f01' split over multiple topological branches. + choose an evolve destination: + 0: [f2632392aefe] added a b c + 1: [7f87764e5b64] added a b c + q: quit the prompt + enter the index of the revision you want to select: 0 + move:[7] added d + atop:[8] added a b c + hg rebase -r d48a30875f01 -d f2632392aefe + + $ hg evolve --dry-run < 1 + > EOF + ancestor 'd48a30875f01' split over multiple topological branches. + choose an evolve destination: + 0: [f2632392aefe] added a b c + 1: [7f87764e5b64] added a b c + q: quit the prompt + enter the index of the revision you want to select: 1 + move:[7] added d + atop:[10] added a b c + hg rebase -r d48a30875f01 -d 7f87764e5b64 + +Testing the interactive prompt with invalid values first +(this should move its own test file when we use it at multiple places) + + $ hg evolve --all < foo + > EOF + ancestor 'd48a30875f01' split over multiple topological branches. + choose an evolve destination: + 0: [f2632392aefe] added a b c + 1: [7f87764e5b64] added a b c + q: quit the prompt + enter the index of the revision you want to select: foo + invalid value 'foo' entered for index + could not solve instability, ambiguous destination: parent split across two branches + + $ hg evolve --all < 4 + > EOF + ancestor 'd48a30875f01' split over multiple topological branches. + choose an evolve destination: + 0: [f2632392aefe] added a b c + 1: [7f87764e5b64] added a b c + q: quit the prompt + enter the index of the revision you want to select: 4 + invalid value '4' entered for index + could not solve instability, ambiguous destination: parent split across two branches + + $ hg evolve --all < -1 + > EOF + ancestor 'd48a30875f01' split over multiple topological branches. + choose an evolve destination: + 0: [f2632392aefe] added a b c + 1: [7f87764e5b64] added a b c + q: quit the prompt + enter the index of the revision you want to select: -1 + invalid value '-1' entered for index + could not solve instability, ambiguous destination: parent split across two branches + + $ hg evolve --all < q + > EOF + ancestor 'd48a30875f01' split over multiple topological branches. + choose an evolve destination: + 0: [f2632392aefe] added a b c + 1: [7f87764e5b64] added a b c + q: quit the prompt + enter the index of the revision you want to select: q + could not solve instability, ambiguous destination: parent split across two branches + +Doing the evolve with the interactive prompt + + $ hg evolve --all < 1 + > EOF + ancestor 'd48a30875f01' split over multiple topological branches. + choose an evolve destination: + 0: [f2632392aefe] added a b c + 1: [7f87764e5b64] added a b c + q: quit the prompt + enter the index of the revision you want to select: 1 + move:[7] added d + atop:[10] added a b c + working directory is now at 1c6caa7c902a diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-phase.t --- a/tests/test-evolve-phase.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-evolve-phase.t Wed Mar 21 16:06:17 2018 +0100 @@ -115,8 +115,10 @@ $ echo c2 > a $ hg resolve -m (no more unresolved files) + continue: hg evolve --continue $ hg evolve -c evolving 2:13833940840c "c" + working directory is now at 3d2080c198e5 $ hg glog @ 4 - 3d2080c198e5 c (secret) diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-split.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-stop.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-stop.t Wed Mar 21 16:06:17 2018 +0100 @@ -0,0 +1,382 @@ +Tests for the --stop flag for `hg evolve` command +================================================= + +The `--stop` flag stops the interrupted evolution and delete the state file so +user can do other things and comeback and do evolution later on + +Setup +===== + + $ cat >> $HGRCPATH < [alias] + > glog = log -GT "{rev}:{node|short} {desc}\n ({bookmarks}) {phase}" + > [extensions] + > EOF + $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH + + $ hg init stoprepo + $ cd stoprepo + $ echo ".*\.orig" > .hgignore + $ hg add .hgignore + $ hg ci -m "added hgignore" + $ for ch in a b c d; do echo foo > $ch; hg add $ch; hg ci -qm "added "$ch; done; + + $ hg glog + @ 4:c41c793e0ef1 added d + | () draft + o 3:ca1b80f7960a added c + | () draft + o 2:b1661037fa25 added b + | () draft + o 1:c7586e2a9264 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + +Testing `--stop` when no evolve is interrupted +============================================== + + $ hg evolve --stop + abort: no interrupted evolve to stop + [255] + +Testing with wrong combinations of flags +======================================== + + $ hg evolve --stop --rev 1 + abort: cannot specify both "--rev" and "--stop" + [255] + + $ hg evolve --stop --continue + abort: cannot specify both "--stop" and "--continue" + [255] + + $ hg evolve --stop --all + abort: cannot specify both "--all" and "--stop" + [255] + + $ hg evolve --stop --any + abort: cannot specify both "--any" and "--stop" + [255] + +Testing when only one revision is to evolve +=========================================== + + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [3] added c + $ echo bar > d + $ hg add d + $ hg amend + 1 new orphan changesets + $ hg glog + @ 5:cb6a2ab625bb added c + | () draft + | o 4:c41c793e0ef1 added d + | | () draft + | x 3:ca1b80f7960a added c + |/ () draft + o 2:b1661037fa25 added b + | () draft + o 1:c7586e2a9264 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve + move:[4] added d + atop:[5] added c + merging d + warning: conflicts while merging d! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ hg evolve --stop + stopped the interrupted evolve + working directory is now at cb6a2ab625bb + +Checking whether evolvestate file exists or not + $ cat .hg/evolvestate + cat: .hg/evolvestate: No such file or directory + [1] + +Checking where we are + $ hg id + cb6a2ab625bb tip + +Checking working dir + $ hg status +Checking for incomplete mergestate + $ ls .hg/merge + ls: cannot access .?\.hg/merge.?: No such file or directory (re) + [2] + +Checking graph + $ hg glog + @ 5:cb6a2ab625bb added c + | () draft + | o 4:c41c793e0ef1 added d + | | () draft + | x 3:ca1b80f7960a added c + |/ () draft + o 2:b1661037fa25 added b + | () draft + o 1:c7586e2a9264 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + +Testing the stop flag in case conflicts are caused by `hg next --evolve` +======================================================================== + + $ hg next --evolve + move:[4] added d + atop:[5] added c + merging d + warning: conflicts while merging d! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ hg diff + diff -r cb6a2ab625bb d + --- a/d Thu Jan 01 00:00:00 1970 +0000 + +++ b/d Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +1,5 @@ + +<<<<<<< destination: cb6a2ab625bb - test: added c + bar + +======= + +foo + +>>>>>>> evolving: c41c793e0ef1 - test: added d + + $ hg evolve --stop + stopped the interrupted evolve + working directory is now at cb6a2ab625bb + + $ hg glog + @ 5:cb6a2ab625bb added c + | () draft + | o 4:c41c793e0ef1 added d + | | () draft + | x 3:ca1b80f7960a added c + |/ () draft + o 2:b1661037fa25 added b + | () draft + o 1:c7586e2a9264 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg status + +Checking when multiple revs need to be evolved, some revs evolve without +conflicts +========================================================================= + +Making sure obsmarkers should be on evolved changeset and not rest of them once +we do `evolve --stop` +-------------------------------------------------------------------------------- + + $ hg evolve + move:[4] added d + atop:[5] added c + merging d + warning: conflicts while merging d! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + $ echo foo > d + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + $ hg evolve --continue + evolving 4:c41c793e0ef1 "added d" + working directory is now at 2a4e03d422e2 + $ hg glog + @ 6:2a4e03d422e2 added d + | () draft + o 5:cb6a2ab625bb added c + | () draft + o 2:b1661037fa25 added b + | () draft + o 1:c7586e2a9264 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg up .^^^^ + 0 files updated, 0 files merged, 4 files removed, 0 files unresolved + $ echo bar > c + $ hg add c + $ hg amend + 4 new orphan changesets + + $ hg glog + @ 7:21817cd42526 added hgignore + () draft + o 6:2a4e03d422e2 added d + | () draft + o 5:cb6a2ab625bb added c + | () draft + o 2:b1661037fa25 added b + | () draft + o 1:c7586e2a9264 added a + | () draft + x 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --all + move:[1] added a + atop:[7] added hgignore + move:[2] added b + atop:[8] added a + move:[5] added c + atop:[9] added b + merging c + warning: conflicts while merging c! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ hg status + M c + A d + + $ hg evolve --stop + stopped the interrupted evolve + working directory is now at aec285328e90 + +Only changeset which has a successor now are obsoleted + $ hg glog + @ 9:aec285328e90 added b + | () draft + o 8:fd00db71edca added a + | () draft + o 7:21817cd42526 added hgignore + () draft + o 6:2a4e03d422e2 added d + | () draft + o 5:cb6a2ab625bb added c + | () draft + x 2:b1661037fa25 added b + | () draft + x 1:c7586e2a9264 added a + | () draft + x 0:8fa14d15e168 added hgignore + () draft + +Making sure doing evolve again resumes from right place and does the right thing + + $ hg evolve --all + move:[5] added c + atop:[9] added b + merging c + warning: conflicts while merging c! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ echo foobar > c + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + $ hg evolve --continue + evolving 5:cb6a2ab625bb "added c" + move:[6] added d + atop:[10] added c + working directory is now at cd0909a30222 + $ hg glog + @ 11:cd0909a30222 added d + | () draft + o 10:cb1dd1086ef6 added c + | () draft + o 9:aec285328e90 added b + | () draft + o 8:fd00db71edca added a + | () draft + o 7:21817cd42526 added hgignore + () draft + +Bookmarks should only be moved of the changesets which have been evolved, +bookmarks of rest of them should stay where they are are +------------------------------------------------------------------------- + + $ hg up .^ + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg bookmark b1 + $ hg up .^ + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + (leaving bookmark b1) + $ hg bookmark b2 + + $ hg glog + o 11:cd0909a30222 added d + | () draft + o 10:cb1dd1086ef6 added c + | (b1) draft + @ 9:aec285328e90 added b + | (b2) draft + o 8:fd00db71edca added a + | () draft + o 7:21817cd42526 added hgignore + () draft + + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [8] added a + $ echo tom > c + $ hg amend + 3 new orphan changesets + + $ hg glog + @ 12:a3cc2042492f added a + | () draft + | o 11:cd0909a30222 added d + | | () draft + | o 10:cb1dd1086ef6 added c + | | (b1) draft + | o 9:aec285328e90 added b + | | (b2) draft + | x 8:fd00db71edca added a + |/ () draft + o 7:21817cd42526 added hgignore + () draft + + $ hg evolve --all + move:[9] added b + atop:[12] added a + move:[10] added c + atop:[13] added b + merging c + warning: conflicts while merging c! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ hg evolve --stop + stopped the interrupted evolve + working directory is now at a3f4b95da934 + +Bookmarks of only the changeset which are evolved is moved + $ hg glog + @ 13:a3f4b95da934 added b + | (b2) draft + o 12:a3cc2042492f added a + | () draft + | o 11:cd0909a30222 added d + | | () draft + | o 10:cb1dd1086ef6 added c + | | (b1) draft + | x 9:aec285328e90 added b + | | () draft + | x 8:fd00db71edca added a + |/ () draft + o 7:21817cd42526 added hgignore + () draft diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-templates.t --- a/tests/test-evolve-templates.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-evolve-templates.t Wed Mar 21 16:06:17 2018 +0100 @@ -73,10 +73,10 @@ o d004c8f274b9 (3) A2 | x a468dc9b3633 (2) A1 - | rewritten(description) as d004c8f274b9 by test2 (Thu Apr 19 04:25:21 2001 +0000) + | rewritten(description) as d004c8f274b9 using amend by test2 (Thu Apr 19 04:25:21 2001 +0000) | @ 471f378eab4c (1) A0 - rewritten(description, content) as a468dc9b3633 by test (Fri Feb 13 23:31:30 2009 +0000) + rewritten(description, content) as a468dc9b3633 using amend by test (Fri Feb 13 23:31:30 2009 +0000) $ hg tlog o d004c8f274b9 @@ -326,7 +326,7 @@ | x changeset: 1:471597cad322 |/ user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: split as 2:337fec4d2edc, 3:f257fde29c7a + | obsolete: split using split as 2:337fec4d2edc, 3:f257fde29c7a | summary: A0 | o changeset: 0:ea207398892e @@ -354,7 +354,7 @@ | @ 471597cad322 |/ Successors: 2:337fec4d2edc 3:f257fde29c7a | semi-colon: 2:337fec4d2edc 3:f257fde29c7a - | Fate: split as 2:337fec4d2edc, 3:f257fde29c7a + | Fate: split using split as 2:337fec4d2edc, 3:f257fde29c7a | o ea207398892e @@ -364,7 +364,7 @@ o 337fec4d2edc | | @ 471597cad322 - |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a + |/ Obsfate: split using split as 2:337fec4d2edc, 3:f257fde29c7a | o ea207398892e @@ -393,7 +393,7 @@ | x 471597cad322 |/ Successors: 2:337fec4d2edc 3:f257fde29c7a | semi-colon: 2:337fec4d2edc 3:f257fde29c7a - | Fate: split as 2:337fec4d2edc, 3:f257fde29c7a + | Fate: split using split as 2:337fec4d2edc, 3:f257fde29c7a | o ea207398892e @@ -403,7 +403,7 @@ o 337fec4d2edc | | x 471597cad322 - |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a + |/ Obsfate: split using split as 2:337fec4d2edc, 3:f257fde29c7a | o ea207398892e @@ -413,7 +413,7 @@ | o 337fec4d2edc [] | - | x 471597cad322 [{"markers": [["471597cad322d1f659bb169751be9133dad92ef3", ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"], 0, [["ef1", "12"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"], "users": ["test"], "verb": "split"}] + | x 471597cad322 [{"markers": [["471597cad322d1f659bb169751be9133dad92ef3", ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"], 0, [["ef1", "12"], ["operation", "split"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"], "users": ["test"], "verb": "split"}] |/ o ea207398892e [] @@ -460,13 +460,13 @@ | x changeset: 2:0dec01379d3b | | user: test | | date: Thu Jan 01 00:00:00 1970 +0000 - | | obsolete: rewritten as 3:eb5a0daa2192 + | | obsolete: rewritten using fold as 3:eb5a0daa2192 | | summary: B0 | | | x changeset: 1:471f378eab4c |/ user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 3:eb5a0daa2192 + | obsolete: rewritten using fold as 3:eb5a0daa2192 | summary: A0 | o changeset: 0:ea207398892e @@ -490,7 +490,7 @@ | @ 471f378eab4c |/ Successors: 3:eb5a0daa2192 | semi-colon: 3:eb5a0daa2192 - | Fate: rewritten as 3:eb5a0daa2192 + | Fate: rewritten using fold as 3:eb5a0daa2192 | o ea207398892e @@ -498,7 +498,7 @@ o eb5a0daa2192 | | @ 471f378eab4c - |/ Obsfate: rewritten as 3:eb5a0daa2192 + |/ Obsfate: rewritten using fold as 3:eb5a0daa2192 | o ea207398892e @@ -516,12 +516,12 @@ | @ 0dec01379d3b | | Successors: 3:eb5a0daa2192 | | semi-colon: 3:eb5a0daa2192 - | | Fate: rewritten as 3:eb5a0daa2192 + | | Fate: rewritten using fold as 3:eb5a0daa2192 | | | x 471f378eab4c |/ Successors: 3:eb5a0daa2192 | semi-colon: 3:eb5a0daa2192 - | Fate: rewritten as 3:eb5a0daa2192 + | Fate: rewritten using fold as 3:eb5a0daa2192 | o ea207398892e @@ -529,10 +529,10 @@ o eb5a0daa2192 | | @ 0dec01379d3b - | | Obsfate: rewritten as 3:eb5a0daa2192 + | | Obsfate: rewritten using fold as 3:eb5a0daa2192 | | | x 471f378eab4c - |/ Obsfate: rewritten as 3:eb5a0daa2192 + |/ Obsfate: rewritten using fold as 3:eb5a0daa2192 | o ea207398892e @@ -556,12 +556,12 @@ | x 0dec01379d3b | | Successors: 3:eb5a0daa2192 | | semi-colon: 3:eb5a0daa2192 - | | Fate: rewritten as 3:eb5a0daa2192 + | | Fate: rewritten using fold as 3:eb5a0daa2192 | | | x 471f378eab4c |/ Successors: 3:eb5a0daa2192 | semi-colon: 3:eb5a0daa2192 - | Fate: rewritten as 3:eb5a0daa2192 + | Fate: rewritten using fold as 3:eb5a0daa2192 | o ea207398892e @@ -569,10 +569,10 @@ @ eb5a0daa2192 | | x 0dec01379d3b - | | Obsfate: rewritten as 3:eb5a0daa2192 + | | Obsfate: rewritten using fold as 3:eb5a0daa2192 | | | x 471f378eab4c - |/ Obsfate: rewritten as 3:eb5a0daa2192 + |/ Obsfate: rewritten using fold as 3:eb5a0daa2192 | o ea207398892e @@ -580,9 +580,9 @@ $ hg fatelogjson --hidden @ eb5a0daa2192 [] | - | x 0dec01379d3b [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["ef1", "13"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}] + | x 0dec01379d3b [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["ef1", "13"], ["operation", "fold"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}] | | - | x 471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["ef1", "9"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}] + | x 471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["ef1", "9"], ["operation", "fold"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}] |/ o ea207398892e [] @@ -807,7 +807,7 @@ | | parent: 1:471f378eab4c | | user: test | | date: Thu Jan 01 00:00:00 1970 +0000 - | | obsolete: rewritten as 4:eb5a0daa2192 + | | obsolete: rewritten using fold as 4:eb5a0daa2192 | | summary: B1 | | | | x changeset: 2:0dec01379d3b @@ -819,7 +819,7 @@ | x changeset: 1:471f378eab4c |/ user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rewritten as 4:eb5a0daa2192 + | obsolete: rewritten using fold as 4:eb5a0daa2192 | summary: A0 | o changeset: 0:ea207398892e @@ -841,7 +841,7 @@ | @ 471f378eab4c |/ Successors: 4:eb5a0daa2192 | semi-colon: 4:eb5a0daa2192 - | Fate: rewritten as 4:eb5a0daa2192 + | Fate: rewritten using fold as 4:eb5a0daa2192 | o ea207398892e @@ -849,7 +849,7 @@ o eb5a0daa2192 | | @ 471f378eab4c - |/ Obsfate: rewritten as 4:eb5a0daa2192 + |/ Obsfate: rewritten using fold as 4:eb5a0daa2192 | o ea207398892e @@ -864,12 +864,12 @@ | @ 0dec01379d3b | | Successors: 4:eb5a0daa2192 | | semi-colon: 4:eb5a0daa2192 - | | Fate: rewritten using amend as 4:eb5a0daa2192 + | | Fate: rewritten using amend, fold as 4:eb5a0daa2192 | | | x 471f378eab4c |/ Successors: 4:eb5a0daa2192 | semi-colon: 4:eb5a0daa2192 - | Fate: rewritten as 4:eb5a0daa2192 + | Fate: rewritten using fold as 4:eb5a0daa2192 | o ea207398892e @@ -877,10 +877,10 @@ o eb5a0daa2192 | | @ 0dec01379d3b - | | Obsfate: rewritten using amend as 4:eb5a0daa2192 + | | Obsfate: rewritten using amend, fold as 4:eb5a0daa2192 | | | x 471f378eab4c - |/ Obsfate: rewritten as 4:eb5a0daa2192 + |/ Obsfate: rewritten using fold as 4:eb5a0daa2192 | o ea207398892e @@ -896,12 +896,12 @@ | @ b7ea6d14e664 | | Successors: 4:eb5a0daa2192 | | semi-colon: 4:eb5a0daa2192 - | | Fate: rewritten as 4:eb5a0daa2192 + | | Fate: rewritten using fold as 4:eb5a0daa2192 | | | x 471f378eab4c |/ Successors: 4:eb5a0daa2192 | semi-colon: 4:eb5a0daa2192 - | Fate: rewritten as 4:eb5a0daa2192 + | Fate: rewritten using fold as 4:eb5a0daa2192 | o ea207398892e @@ -909,10 +909,10 @@ o eb5a0daa2192 | | @ b7ea6d14e664 - | | Obsfate: rewritten as 4:eb5a0daa2192 + | | Obsfate: rewritten using fold as 4:eb5a0daa2192 | | | x 471f378eab4c - |/ Obsfate: rewritten as 4:eb5a0daa2192 + |/ Obsfate: rewritten using fold as 4:eb5a0daa2192 | o ea207398892e @@ -933,7 +933,7 @@ | | semi-colon: 2:0dec01379d3b | | Successors: 4:eb5a0daa2192 | | semi-colon: 4:eb5a0daa2192 - | | Fate: rewritten as 4:eb5a0daa2192 + | | Fate: rewritten using fold as 4:eb5a0daa2192 | | | | x 0dec01379d3b | |/ Successors: 3:b7ea6d14e664 @@ -943,7 +943,7 @@ | x 471f378eab4c |/ Successors: 4:eb5a0daa2192 | semi-colon: 4:eb5a0daa2192 - | Fate: rewritten as 4:eb5a0daa2192 + | Fate: rewritten using fold as 4:eb5a0daa2192 | o ea207398892e @@ -951,24 +951,24 @@ @ eb5a0daa2192 | | x b7ea6d14e664 - | | Obsfate: rewritten as 4:eb5a0daa2192 + | | Obsfate: rewritten using fold as 4:eb5a0daa2192 | | | | x 0dec01379d3b | |/ Obsfate: reworded using amend as 3:b7ea6d14e664 | | | x 471f378eab4c - |/ Obsfate: rewritten as 4:eb5a0daa2192 + |/ Obsfate: rewritten using fold as 4:eb5a0daa2192 | o ea207398892e $ hg fatelogjson --hidden @ eb5a0daa2192 [] | - | x b7ea6d14e664 [{"markers": [["b7ea6d14e664bdc8922221f7992631b50da3fb07", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["ef1", "13"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}] + | x b7ea6d14e664 [{"markers": [["b7ea6d14e664bdc8922221f7992631b50da3fb07", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["ef1", "13"], ["operation", "fold"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}] | | | | x 0dec01379d3b [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["b7ea6d14e664bdc8922221f7992631b50da3fb07"], 0, [["ef1", "1"], ["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["b7ea6d14e664bdc8922221f7992631b50da3fb07"], "users": ["test"], "verb": "reworded"}] | |/ - | x 471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["ef1", "9"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}] + | x 471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["ef1", "9"], ["operation", "fold"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}] |/ o ea207398892e [] @@ -1593,13 +1593,13 @@ (use 'hg evolve' to update to its parent successor) $ hg tlog @ 471f378eab4c - | Fate: pruned + | Fate: pruned using prune | o ea207398892e $ hg fatelog -v @ 471f378eab4c - | Obsfate: pruned by test (at 1970-01-01 00:00 +0000) + | Obsfate: pruned using prune by test (at 1970-01-01 00:00 +0000) | o ea207398892e diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve-topic.t --- a/tests/test-evolve-topic.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-evolve-topic.t Wed Mar 21 16:06:17 2018 +0100 @@ -267,3 +267,107 @@ $ hg prev 0 files updated, 0 files merged, 1 files removed, 0 files unresolved [18] add fff + +Testing issue 5708 when we are on obsolete changeset and there is active topic +------------------------------------------------------------------------------ + + $ hg log --graph + @ 18 - {bar} 793eb6370b2d add fff (draft) + | + | o 17 - {bar} 9bf430c106b7 add jjj (draft) + | | + | o 16 - {bar} d2dc89c57700 add iii (draft) + | | + | o 15 - {bar} 20bc4d02aa62 add hhh (draft) + | | + | o 14 - {bar} 16d6f664b17c add ggg (draft) + | | + | x 13 - {foo} 070c5573d8f9 add fff (draft) + |/ + o 12 - {foo} 42b49017ff90 add eee (draft) + | + o 10 - {foo} d9cacd156ffc add ddd (draft) + | + o 2 - {foo} cced9bac76e3 add ccc (draft) + | + o 1 - {} a4dbed0837ea add bbb (draft) + | + o 0 - {} 199cc73e9a0b add aaa (draft) + + + $ hg topic + * bar (5 changesets, 4 troubled) + foo (3 changesets) + +When the current topic, obsoleted changesets topic and successor topic are same + + $ hg up 20bc4d02aa62 + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo foobar >> hhh + $ hg amend + $ hg up 20bc4d02aa62 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory parent is obsolete! (20bc4d02aa62) + (use 'hg evolve' to update to its successor: d834582d9ee3) + $ hg log -Gr 14:: + o 19 - {bar} d834582d9ee3 add hhh (draft) + | + | o 17 - {bar} 9bf430c106b7 add jjj (draft) + | | + | o 16 - {bar} d2dc89c57700 add iii (draft) + | | + | @ 15 - {bar} 20bc4d02aa62 add hhh (draft) + |/ + o 14 - {bar} 16d6f664b17c add ggg (draft) + | + ~ + + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [14] add ggg + +When the current topic and successors topic are same, but obsolete cset has +different topic + + $ hg rebase -s d2dc89c57700 -d d834582d9ee3 --config extensions.rebase= + rebasing 16:d2dc89c57700 "add iii" (bar) + rebasing 17:9bf430c106b7 "add jjj" (bar) + $ hg log -Gr 42b49017ff90:: + o 21 - {bar} 7542e76aba2c add jjj (draft) + | + o 20 - {bar} 7858bd7e9906 add iii (draft) + | + o 19 - {bar} d834582d9ee3 add hhh (draft) + | + | o 18 - {bar} 793eb6370b2d add fff (draft) + | | + @ | 14 - {bar} 16d6f664b17c add ggg (draft) + | | + x | 13 - {foo} 070c5573d8f9 add fff (draft) + |/ + o 12 - {foo} 42b49017ff90 add eee (draft) + | + ~ + + $ hg up 070c5573d8f9 + switching to topic foo + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + working directory parent is obsolete! (070c5573d8f9) + (use 'hg evolve' to update to its successor: 793eb6370b2d) + + $ hg topic bar + + $ hg prev + no parent in topic "bar" + (do you want --no-topic) + [1] + +When current topic and obsolete cset topic are same but successor has different +one + + $ hg up 070c5573d8f9 + switching to topic foo + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [12] add eee diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-evolve.t --- a/tests/test-evolve.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-evolve.t Wed Mar 21 16:06:17 2018 +0100 @@ -616,8 +616,8 @@ o 0:8685c6d34325@default(draft) add 0 $ hg debugobsolete - 0e84df4912da4c7cad22a3b4fcfd58ddfb7c8ae9 0b9e50c35132ff548ec0065caea6a87e1ebcef32 0 (*) {'ef1': '4', 'user': 'test'} (glob) - db038628b9e56f51a454c0da0c508df247b41748 acb28cd497b7f8767e01ef70f68697a959573c2d 0 (*) {'ef1': '13', 'user': 'test'} (glob) + 0e84df4912da4c7cad22a3b4fcfd58ddfb7c8ae9 0b9e50c35132ff548ec0065caea6a87e1ebcef32 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'amend', 'user': 'test'} + db038628b9e56f51a454c0da0c508df247b41748 acb28cd497b7f8767e01ef70f68697a959573c2d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'amend', 'user': 'test'} Test graft --continue @@ -661,9 +661,9 @@ o 0:8685c6d34325@default(draft) add 0 $ hg debugobsolete - 0e84df4912da4c7cad22a3b4fcfd58ddfb7c8ae9 0b9e50c35132ff548ec0065caea6a87e1ebcef32 0 (*) {'ef1': '4', 'user': 'test'} (glob) - db038628b9e56f51a454c0da0c508df247b41748 acb28cd497b7f8767e01ef70f68697a959573c2d 0 (*) {'ef1': '13', 'user': 'test'} (glob) - a5bfd90a2f29c7ccb8f917ff4e5013a9053d0a04 920e58bb443b73eea9d6d65570b4241051ea3229 0 (*) {'ef1': '12', 'user': 'test'} (glob) + 0e84df4912da4c7cad22a3b4fcfd58ddfb7c8ae9 0b9e50c35132ff548ec0065caea6a87e1ebcef32 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'amend', 'user': 'test'} + db038628b9e56f51a454c0da0c508df247b41748 acb28cd497b7f8767e01ef70f68697a959573c2d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'amend', 'user': 'test'} + a5bfd90a2f29c7ccb8f917ff4e5013a9053d0a04 920e58bb443b73eea9d6d65570b4241051ea3229 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '12', 'operation': 'amend', 'user': 'test'} Test touch @@ -766,12 +766,12 @@ @ d26d339c513f (12) add 4 |\ x | af636757ce3b (11) add 3 - |\ \ rewritten(description, user, parent, content) as d26d339c513f by test (*) (glob) + |\ \ rewritten(description, user, parent, content) as d26d339c513f using fold by test (Thu Jan 01 00:00:00 1970 +0000) | | | | \ \ | |\ \ | | | x ce341209337f (4) add 4 - | | | rewritten(description, user, content) as d26d339c513f by test (*) (glob) + | | | rewritten(description, user, content) as d26d339c513f using fold by test (Thu Jan 01 00:00:00 1970 +0000) | | | Test obsstore stat @@ -786,13 +786,14 @@ more than 2 successors: 0 available keys: ef1: 10 + operation: 10 user: 10 marker size: format v1: - smallest length: 75 - longer length: 76 - median length: 76 - mean length: 75 + smallest length: 90 + longer length: 92 + median length: 91 + mean length: 91 format v0: smallest length: * (glob) longer length: * (glob) @@ -1250,6 +1251,20 @@ (use 'hg help' for the full list of commands or 'hg -v' for details) [255] +Shows "use 'hg evolve' to..." hints iff the evolve command is enabled + + $ hg --hidden up 14 + 2 files updated, 0 files merged, 1 files removed, 0 files unresolved + working directory parent is obsolete! (484fb3cfa7f2) + $ cat >> $HGRCPATH < [experimental] + > evolutioncommands=evolve + > EOF + $ hg --hidden up 15 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + working directory parent is obsolete! (daa1ff1c7fbd) + (use 'hg evolve' to update to its successor: 0c049e4e5422) + Restore all of the evolution features $ cat >> $HGRCPATH < [extensions] > evolve= > [ui] - > logtemplate = '{rev} - {node|short} {desc|firstline} [{author}] ({phase})\n' + > logtemplate = '{rev} - {node|short} {desc|firstline} [{author}] ({phase}) {bookmarks}\n' > EOF $ hg init fold-tests @@ -16,6 +16,7 @@ $ hg debugbuilddag .+3:branchpoint+4*branchpoint+2 $ hg up 'desc("r7")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg bookmark bm1 $ hg log -G o 10 - a8407f9a3dc1 r10 [debugbuilddag] (draft) | @@ -23,7 +24,7 @@ | o 8 - abf57d94268b r8 [debugbuilddag] (draft) | - | @ 7 - 4de32a90b66c r7 [debugbuilddag] (draft) + | @ 7 - 4de32a90b66c r7 [debugbuilddag] (draft) bm1 | | | o 6 - f69452c5b1af r6 [debugbuilddag] (draft) | | @@ -87,6 +88,27 @@ 3 changesets folded 0 files updated, 0 files merged, 0 files removed, 0 files unresolved +Checking whether the bookmarks are moved or not + + $ hg log -G + @ 11 - 198b5c405d01 r5 [debugbuilddag] (draft) bm1 + | + | o 10 - a8407f9a3dc1 r10 [debugbuilddag] (draft) + | | + | o 9 - 529dfc5bb875 r9 [debugbuilddag] (draft) + | | + | o 8 - abf57d94268b r8 [debugbuilddag] (draft) + | | + o | 4 - bebd167eb94d r4 [debugbuilddag] (draft) + |/ + o 3 - 2dc09a01254d r3 [debugbuilddag] (draft) + | + o 2 - 01241442b3c2 r2 [debugbuilddag] (draft) + | + o 1 - 66f7d451a68b r1 [debugbuilddag] (draft) + | + o 0 - 1ea73414a91b r0 [debugbuilddag] (public) + (test inherited from test-evolve.t) $ hg fold --from 6 # want to run hg fold 6 @@ -95,7 +117,7 @@ [255] $ hg log -G - @ 11 - 198b5c405d01 r5 [debugbuilddag] (draft) + @ 11 - 198b5c405d01 r5 [debugbuilddag] (draft) bm1 | | o 10 - a8407f9a3dc1 r10 [debugbuilddag] (draft) | | @@ -124,7 +146,7 @@ $ hg log -G o 12 - b568edbee6e0 r8 [debugbuilddag] (draft) | - | @ 11 - 198b5c405d01 r5 [debugbuilddag] (draft) + | @ 11 - 198b5c405d01 r5 [debugbuilddag] (draft) bm1 | | | o 4 - bebd167eb94d r4 [debugbuilddag] (draft) |/ @@ -144,8 +166,9 @@ $ hg commit '-m r11' $ hg up '.^' 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + (leaving bookmark bm1) $ hg log -G - o 13 - 14d0e0da8e91 r11 [test] (draft) + o 13 - 14d0e0da8e91 r11 [test] (draft) bm1 | | o 12 - b568edbee6e0 r8 [debugbuilddag] (draft) | | @@ -190,7 +213,7 @@ 2 changesets folded 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg log -G - @ 14 - 29b470a33594 r5 [Victor Rataxes ] (draft) + @ 14 - 29b470a33594 r5 [Victor Rataxes ] (draft) bm1 | | o 12 - b568edbee6e0 r8 [debugbuilddag] (draft) | | @@ -209,7 +232,7 @@ 2 changesets folded 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg log -G - @ 15 - 91880abed0f2 r4 [test] (draft) + @ 15 - 91880abed0f2 r4 [test] (draft) bm1 | | o 12 - b568edbee6e0 r8 [debugbuilddag] (draft) |/ diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-grab.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-grab.t Wed Mar 21 16:06:17 2018 +0100 @@ -0,0 +1,331 @@ +Test for the grab command + + $ cat >> $HGRCPATH < [alias] + > glog = log -G -T "{rev}:{node|short} {desc}\n" + > [extensions] + > EOF + $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH + + $ mkcommit() { + > echo "$1" > "$1" + > hg add "$1" + > hg ci -m "add $1" + > } + + $ hg init repo + $ cd repo + $ hg help grab + hg grab [-r] rev + + grabs a commit, move it on the top of working directory parent and + updates to it. + + options: + + -r --rev VALUE revision to grab + -c --continue continue interrupted grab + -a --abort abort interrupted grab + + (some details hidden, use --verbose to show complete help) + + $ mkcommit a + $ mkcommit b + $ mkcommit c + + $ hg glog + @ 2:4538525df7e2 add c + | + o 1:7c3bad9141dc add b + | + o 0:1f0dee641bb7 add a + + +Grabbing an ancestor + + $ hg grab -r 7c3bad9141dc + abort: cannot grab an ancestor revision + [255] + +Grabbing the working directory parent + + $ hg grab -r . + abort: cannot grab an ancestor revision + [255] + +Specifying multiple revisions to grab + + $ hg grab 1f0dee641bb7 -r 7c3bad9141dc + abort: specify just one revision + [255] + +Specifying no revisions to grab + + $ hg grab + abort: empty revision set + [255] + +Continuing without interrupted grab + + $ hg grab --continue + abort: no interrupted grab state exists + [255] + +Aborting without interrupted grab + + $ hg grab --abort + abort: no interrupted grab state exists + [255] + +Specifying both continue and revs + + $ hg up 1f0dee641bb7 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ hg grab -r 4538525df7e2 --continue + abort: cannot specify both --continue and revision + [255] + +Making new branch heads + + $ mkcommit x + created new head + $ mkcommit y + + $ hg glog + @ 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + | o 2:4538525df7e2 add c + | | + | o 1:7c3bad9141dc add b + |/ + o 0:1f0dee641bb7 add a + +Grabbing a revision + + $ hg grab 7c3bad9141dc + grabbing 1:7c3bad9141dc "add b" + $ hg glog + @ 5:7c15c05db6fa add b + | + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + | o 2:4538525df7e2 add c + | | + | x 1:7c3bad9141dc add b + |/ + o 0:1f0dee641bb7 add a + + +When grab does not create any changes + + $ hg graft -r 4538525df7e2 + grafting 2:4538525df7e2 "add c" + + $ hg glog + @ 6:c4636a81ebeb add c + | + o 5:7c15c05db6fa add b + | + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + | o 2:4538525df7e2 add c + | | + | x 1:7c3bad9141dc add b + |/ + o 0:1f0dee641bb7 add a + + $ hg grab -r 4538525df7e2 + grabbing 2:4538525df7e2 "add c" + note: grab of 2:4538525df7e2 created no changes to commit + + $ hg glog + @ 6:c4636a81ebeb add c + | + o 5:7c15c05db6fa add b + | + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + o 0:1f0dee641bb7 add a + +interrupted grab + + $ hg up d46dc301d92f + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ echo foo > c + $ hg ci -Aqm "foo to c" + $ hg grab -r c4636a81ebeb + grabbing 6:c4636a81ebeb "add c" + merging c + warning: conflicts while merging c! (edit, then use 'hg resolve --mark') + unresolved merge conflicts (see hg help resolve) + [1] + + $ echo foobar > c + $ hg resolve --all --mark + (no more unresolved files) + continue: hg grab --continue + $ hg grab --continue + $ hg glog + @ 8:44e155eb95c7 add c + | + o 7:2ccc03d1d096 foo to c + | + | o 5:7c15c05db6fa add b + |/ + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + o 0:1f0dee641bb7 add a + + +When interrupted grab results in no changes to commit + + $ hg up d46dc301d92f + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo bar > c + $ hg add c + $ hg ci -m "foo to c" + created new head + + $ hg up 44e155eb95c7 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg grab 4e04628911f6 + grabbing 9:4e04628911f6 "foo to c" + merging c + warning: conflicts while merging c! (edit, then use 'hg resolve --mark') + unresolved merge conflicts (see hg help resolve) + [1] + $ echo foobar > c + $ hg resolve -m + (no more unresolved files) + continue: hg grab --continue + + $ hg grab --continue + note: grab of 9:4e04628911f6 created no changes to commit + +Testing the abort functionality of hg grab + + $ echo foo > b + $ hg ci -Aqm "foo to b" + $ hg glog -r .^:: + hg: parse error at 4: not a prefix: end + [255] + + $ hg grab -r 7c15c05db6fa + grabbing 5:7c15c05db6fa "add b" + merging b + warning: conflicts while merging b! (edit, then use 'hg resolve --mark') + unresolved merge conflicts (see hg help resolve) + [1] + + $ hg grab --abort + aborting grab, updating to c437988de89f + + $ hg glog + @ 10:c437988de89f foo to b + | + o 8:44e155eb95c7 add c + | + o 7:2ccc03d1d096 foo to c + | + | o 5:7c15c05db6fa add b + |/ + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + o 0:1f0dee641bb7 add a + + +Trying to grab a public changeset + + $ hg phase -r 7c15c05db6fa -p + + $ hg grab -r 7c15c05db6fa + abort: cannot grab public changesets: 7c15c05db6fa + (see 'hg help phases' for details) + [255] + + $ hg glog + @ 10:c437988de89f foo to b + | + o 8:44e155eb95c7 add c + | + o 7:2ccc03d1d096 foo to c + | + | o 5:7c15c05db6fa add b + |/ + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + o 0:1f0dee641bb7 add a + +Checking phase preservation while grabbing secret changeset + +In case of merge conflicts + + $ hg phase -r 7c15c05db6fa -s -f + + $ hg grab -r 7c15c05db6fa + grabbing 5:7c15c05db6fa "add b" + merging b + warning: conflicts while merging b! (edit, then use 'hg resolve --mark') + unresolved merge conflicts (see hg help resolve) + [1] + + $ echo bar > b + $ hg resolve -m + (no more unresolved files) + continue: hg grab --continue + + $ hg grab --continue + $ hg phase -r . + 11: secret + +No merge conflicts + + $ hg up d46dc301d92f + 0 files updated, 0 files merged, 3 files removed, 0 files unresolved + $ echo foo > l + $ hg add l + $ hg ci -qm "added l" --secret + + $ hg phase -r . + 12: secret + + $ hg glog + @ 12:508d572e7053 added l + | + | o 11:10427de9e26e add b + | | + | o 10:c437988de89f foo to b + | | + | o 8:44e155eb95c7 add c + | | + | o 7:2ccc03d1d096 foo to c + |/ + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + o 0:1f0dee641bb7 add a + + $ hg up 10427de9e26e + 3 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ hg grab -r 508d572e7053 + grabbing 12:508d572e7053 "added l" + + $ hg phase -r . + 13: secret diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-issue-5720.t --- a/tests/test-issue-5720.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-issue-5720.t Wed Mar 21 16:06:17 2018 +0100 @@ -70,10 +70,12 @@ $ echo c2 > a $ hg resolve -m (no more unresolved files) + continue: hg evolve --continue Continue the evolution $ hg evolve --continue evolving 2:13833940840c "c" + working directory is now at 3d2080c198e5 Tip should stay in secret phase $ hg log -G -T "{rev}: {phase}" diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-metaedit.t --- a/tests/test-metaedit.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-metaedit.t Wed Mar 21 16:06:17 2018 +0100 @@ -169,15 +169,15 @@ @ a08d35fd7d9d (9) E |\ x | 212b2a2b87cd (8) F - | | rewritten(description, user, parent, content) as a08d35fd7d9d by test (Thu Jan 01 00:00:00 1970 +0000) + | | rewritten(description, user, parent, content) as a08d35fd7d9d using metaedit by test (Thu Jan 01 00:00:00 1970 +0000) | | note: folding changesets using metaedit | | | x c2bd843aa246 (6) E - | rewritten(description, content) as a08d35fd7d9d by test (Thu Jan 01 00:00:00 1970 +0000) + | rewritten(description, content) as a08d35fd7d9d using metaedit by test (Thu Jan 01 00:00:00 1970 +0000) | note: folding changesets using metaedit | x 587528abfffe (7) F - rewritten(user) as 212b2a2b87cd by test (Thu Jan 01 00:00:00 1970 +0000) + rewritten(user) as 212b2a2b87cd using metaedit by test (Thu Jan 01 00:00:00 1970 +0000) no new commit is created here because the date is the same diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-obsolete.t --- a/tests/test-obsolete.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-obsolete.t Wed Mar 21 16:06:17 2018 +0100 @@ -35,7 +35,7 @@ $ hg debugobsolete 4538525df7e2b9f09423636c61ef63a4cb872a2d 0d3f46688ccc6e756c7e96cf64c391c411309597 obsoleted 1 changesets $ hg debugobsolete - 4538525df7e2b9f09423636c61ef63a4cb872a2d 0d3f46688ccc6e756c7e96cf64c391c411309597 0 (*) {'user': 'test'} (glob) + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0d3f46688ccc6e756c7e96cf64c391c411309597 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} Test hidden() revset @@ -655,17 +655,17 @@ summary: add a $ hg debugobsolete | grep -v 33d458d86621f3186c40bfccd77652f4a122743e - 4538525df7e2b9f09423636c61ef63a4cb872a2d 0d3f46688ccc6e756c7e96cf64c391c411309597 0 (*) {'user': 'test'} (glob) - 0d3f46688ccc6e756c7e96cf64c391c411309597 725c380fe99b5e76613493f0903e8d11ddc70d54 0 (*) {'user': 'test'} (glob) - a7a6f2b5d8a54b81bc7aa2fba2934ad6d700a79e 95de7fc6918dea4c9c8d5382f50649794b474c4a 0 (*) {'user': 'test'} (glob) - 95de7fc6918dea4c9c8d5382f50649794b474c4a 909a0fb57e5d909f353d89e394ffd7e0890fec88 0 (*) {'user': 'test'} (glob) - 909a0fb57e5d909f353d89e394ffd7e0890fec88 159dfc9fa5d334d7e03a0aecfc7f7ab4c3431fea 0 (*) {'user': 'test'} (glob) - 1f0dee641bb7258c56bd60e93edfa2405381c41e 83b5778897adafb967ef2f75be3aaa4fce49a4cc 0 (*) {'user': 'test'} (glob) - 83b5778897adafb967ef2f75be3aaa4fce49a4cc 0 (*) {'user': 'test'} (glob) - 0d3f46688ccc6e756c7e96cf64c391c411309597 2033b4e494742365851fac84d276640cbf52833e 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 159dfc9fa5d334d7e03a0aecfc7f7ab4c3431fea 9468a5f5d8b2c5d91e17474e95ae4791e9718fdf 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 9468a5f5d8b2c5d91e17474e95ae4791e9718fdf 6db5e282cb91df5c43ff1f1287c119ff83230d42 0 (*) {'user': 'test'} (glob) - 0b1b6dd009c037985363e2290a0b579819f659db 705ab2a6b72e2cd86edb799ebe15f2695f86143e 0 (*) {'ef1': '*', 'user': 'test'} (glob) + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0d3f46688ccc6e756c7e96cf64c391c411309597 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + 0d3f46688ccc6e756c7e96cf64c391c411309597 725c380fe99b5e76613493f0903e8d11ddc70d54 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + a7a6f2b5d8a54b81bc7aa2fba2934ad6d700a79e 95de7fc6918dea4c9c8d5382f50649794b474c4a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + 95de7fc6918dea4c9c8d5382f50649794b474c4a 909a0fb57e5d909f353d89e394ffd7e0890fec88 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + 909a0fb57e5d909f353d89e394ffd7e0890fec88 159dfc9fa5d334d7e03a0aecfc7f7ab4c3431fea 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + 1f0dee641bb7258c56bd60e93edfa2405381c41e 83b5778897adafb967ef2f75be3aaa4fce49a4cc 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + 83b5778897adafb967ef2f75be3aaa4fce49a4cc 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + 0d3f46688ccc6e756c7e96cf64c391c411309597 2033b4e494742365851fac84d276640cbf52833e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'} + 159dfc9fa5d334d7e03a0aecfc7f7ab4c3431fea 9468a5f5d8b2c5d91e17474e95ae4791e9718fdf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'} + 9468a5f5d8b2c5d91e17474e95ae4791e9718fdf 6db5e282cb91df5c43ff1f1287c119ff83230d42 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + 0b1b6dd009c037985363e2290a0b579819f659db 705ab2a6b72e2cd86edb799ebe15f2695f86143e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} #no produced by 2.3 33d458d86621f3186c40bfccd77652f4a122743e 3734a65252e69ddcced85901647a4f335d40de1e 0 {'date': '* *', 'user': 'test'} (glob) @@ -709,11 +709,11 @@ [2] $ hg olog @ 0d3f46688ccc (3) add obsol_c - | rewritten(parent) as 2033b4e49474 by test (*) (glob) - | rewritten as 725c380fe99b by test (*) (glob) + | rewritten(parent) as 2033b4e49474 using rebase by test (Thu Jan 01 00:00:00 1970 +0000) + | rewritten as 725c380fe99b by test (Thu Jan 01 00:00:00 1970 +0000) | x 4538525df7e2 (2) add c - rewritten as 0d3f46688ccc by test (*) (glob) + rewritten as 0d3f46688ccc by test (Thu Jan 01 00:00:00 1970 +0000) Check import reports new unstable changeset: @@ -847,7 +847,7 @@ Simple rewrite $ hg --hidden debugobsolete --rev 3 - 4538525df7e2b9f09423636c61ef63a4cb872a2d 0d3f46688ccc6e756c7e96cf64c391c411309597 0 (*) {'user': 'test'} (glob) + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0d3f46688ccc6e756c7e96cf64c391c411309597 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} simple rewrite with a prune attached to it @@ -857,7 +857,7 @@ Transitive rewrite $ hg --hidden debugobsolete --rev 8 - 909a0fb57e5d909f353d89e394ffd7e0890fec88 159dfc9fa5d334d7e03a0aecfc7f7ab4c3431fea 0 (*) {'user': 'test'} (glob) - 95de7fc6918dea4c9c8d5382f50649794b474c4a 909a0fb57e5d909f353d89e394ffd7e0890fec88 0 (*) {'user': 'test'} (glob) - a7a6f2b5d8a54b81bc7aa2fba2934ad6d700a79e 95de7fc6918dea4c9c8d5382f50649794b474c4a 0 (*) {'user': 'test'} (glob) + 909a0fb57e5d909f353d89e394ffd7e0890fec88 159dfc9fa5d334d7e03a0aecfc7f7ab4c3431fea 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + 95de7fc6918dea4c9c8d5382f50649794b474c4a 909a0fb57e5d909f353d89e394ffd7e0890fec88 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + a7a6f2b5d8a54b81bc7aa2fba2934ad6d700a79e 95de7fc6918dea4c9c8d5382f50649794b474c4a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-prev-next.t --- a/tests/test-prev-next.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-prev-next.t Wed Mar 21 16:06:17 2018 +0100 @@ -1,4 +1,6 @@ $ cat >> $HGRCPATH < [ui] + > interactive = True > [extensions] > EOF $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH @@ -35,8 +37,8 @@ hg next -B should move active bookmark $ hg next -B --dry-run - hg update 1; - hg bookmark mark -r 1; + hg update 6e742c9127b3; + hg bookmark mark -r 6e742c9127b3; [1] added b $ hg next -B 1 files updated, 0 files merged, 0 files removed, 0 files unresolved @@ -46,7 +48,7 @@ hg prev should unset active bookmark $ hg prev --dry-run - hg update 0; + hg update a154386e50d1; [0] added a $ hg prev 0 files updated, 0 files merged, 1 files removed, 0 files unresolved @@ -60,7 +62,7 @@ mark 1:6e742c9127b3 * mark2 0:a154386e50d1 $ hg next --dry-run --color=debug - hg update 1; + hg update 6e742c9127b3; [[evolve.rev|1]] added b $ hg next 1 files updated, 0 files merged, 0 files removed, 0 files unresolved @@ -172,7 +174,7 @@ no children [1] $ hg prev --dry-run --color=debug - hg update 1; + hg update 6e742c9127b3; [[evolve.rev|1]] added b $ hg prev 0 files updated, 0 files merged, 1 files removed, 0 files unresolved @@ -190,12 +192,11 @@ move:[2] added c atop:[3] added b (2) hg rebase -r 4e26ef31f919 -d 9ad178109a19 - working directory now at 9ad178109a19 (add color output for smoke testing) $ hg next --evolve --color debug - move:[[evolve.rev|2]] added c + [evolve.operation|move:][[evolve.rev|2]] added c atop:[[evolve.rev|3]] added b (2) [ ui.status|working directory now at [evolve.node|e3b6d5df389b]] @@ -211,12 +212,20 @@ $ hg prev 0 files updated, 0 files merged, 1 files removed, 0 files unresolved [3] added b (2) - $ hg next - ambiguous next changeset: - [4] added c + $ hg next < 1 + > EOF + ambiguous next changeset, choose one to update: + 0: [e3b6d5df389b] added c + 1: [9df671ccd2c7] added d + q: quit the prompt + enter the index of the revision you want to select: 1 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved [5] added d - explicitly update to one of them - [1] + + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [3] added b (2) next with ambiguity in aspiring children @@ -226,24 +235,100 @@ no children (2 unstable changesets to be evolved here, do you want --evolve?) [1] - $ hg next --evolve - ambiguous next (unstable) changeset: - [4] added c - [5] added d - (run 'hg evolve --rev REV' on one of them) - [1] + $ hg next --evolve < 0 + > EOF + ambiguous next (unstable) changeset, choose one to evolve and update: + 0: [e3b6d5df389b] added c + 1: [9df671ccd2c7] added d + q: quit the prompt + enter the index of the revision you want to select: 0 + move:[4] added c + atop:[6] added b (3) + working directory now at 5ce67c2407b0 + + $ hg log -GT "{rev}:{node|short} {desc}\n" + @ 7:5ce67c2407b0 added c + | + o 6:d7f119adc759 added b (3) + | + | o 5:9df671ccd2c7 added d + | | + | x 3:9ad178109a19 added b (2) + |/ + o 0:a154386e50d1 added a + + $ hg evolve -r 5 move:[5] added d atop:[6] added b (3) working directory is now at 47ea25be8aea +prev with multiple parents + + $ hg log -GT "{rev}:{node|short} {desc}\n" + @ 8:47ea25be8aea added d + | + | o 7:5ce67c2407b0 added c + |/ + o 6:d7f119adc759 added b (3) + | + o 0:a154386e50d1 added a + + $ hg merge -r 5ce67c2407b0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg ci -m "merge commit" + + $ hg prev < q + > EOF + multiple parents, choose one to update: + 0: [47ea25be8aea] added d + 1: [5ce67c2407b0] added c + q: quit the prompt + enter the index of the revision you want to select: q + [8] added d + [7] added c + multiple parents, explicitly update to one + [1] + + $ hg prev --config ui.interactive=False + [8] added d + [7] added c + multiple parents, explicitly update to one + [1] + + $ hg prev < 1 + > EOF + multiple parents, choose one to update: + 0: [47ea25be8aea] added d + 1: [5ce67c2407b0] added c + q: quit the prompt + enter the index of the revision you want to select: 1 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [7] added c + + $ hg log -GT "{rev}:{node|short} {desc}\n" + o 9:a4b8c25a87d3 merge commit + |\ + | o 8:47ea25be8aea added d + | | + @ | 7:5ce67c2407b0 added c + |/ + o 6:d7f119adc759 added b (3) + | + o 0:a154386e50d1 added a + + $ cd .. prev and next should lock properly against other commands $ hg init repo $ cd repo - $ HGEDITOR=${TESTDIR}/fake-editor.sh + $ HGEDITOR="sh ${TESTDIR}/fake-editor.sh" $ echo hi > foo $ hg ci -Am 'one' adding foo diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-prune.t --- a/tests/test-prune.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-prune.t Wed Mar 21 16:06:17 2018 +0100 @@ -57,7 +57,7 @@ $ hg bookmark * BABAR 3:47d2a3944de8 $ hg debugobsolete - 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '*', 'user': 'blah'} (glob) + 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'blah'} prune leaving instability behind @@ -66,8 +66,8 @@ 2 new orphan changesets $ hg book -i BABAR $ hg debugobsolete - 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '*', 'user': 'blah'} (glob) - 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (*) {'ef1': '*', 'user': 'test'} (glob) + 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'blah'} + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} pruning multiple changeset at once @@ -78,10 +78,10 @@ [ ui.status|working directory now at [evolve.node|1f0dee641bb7]] [ ui.status|2 changesets pruned] $ hg debugobsolete - 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '*', 'user': 'blah'} (glob) - 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (*) {'ef1': '*', 'user': 'test'} (glob) - 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (*) {'ef1': '*', 'user': 'test'} (glob) - 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (*) {'ef1': '*', 'user': 'test'} (glob) + 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'blah'} + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} cannot prune public changesets @@ -90,10 +90,10 @@ (see 'hg help phases' for details) [255] $ hg debugobsolete - 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '*', 'user': 'blah'} (glob) - 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (*) {'ef1': '*', 'user': 'test'} (glob) - 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (*) {'ef1': '*', 'user': 'test'} (glob) - 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (*) {'ef1': '*', 'user': 'test'} (glob) + 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'blah'} + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} Check successors addition ---------------------------- @@ -139,11 +139,11 @@ working directory now at 6e8148413dd5 1 changesets pruned $ hg debugobsolete - 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '*', 'user': 'blah'} (glob) - 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (*) {'ef1': '*', 'user': 'test'} (glob) - 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (*) {'ef1': '*', 'user': 'test'} (glob) - 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (*) {'ef1': '*', 'user': 'test'} (glob) - bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 (*) {'ef1': '*', 'user': 'test'} (glob) + 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'blah'} + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} $ hg log -G @ 12:6e8148413dd5[] (draft) add nE | @@ -170,12 +170,12 @@ $ hg prune 'desc("add dd")' -s 'desc("add nD")' -s 'desc("add nC")' --split 1 changesets pruned $ hg debugobsolete - 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '*', 'user': 'blah'} (glob) - 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (*) {'ef1': '*', 'user': 'test'} (glob) - 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (*) {'ef1': '*', 'user': 'test'} (glob) - 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (*) {'ef1': '*', 'user': 'test'} (glob) - bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 (*) {'ef1': '*', 'user': 'test'} (glob) + 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'blah'} + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} + 00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} $ hg log -G @ 12:6e8148413dd5[] (draft) add nE | @@ -199,12 +199,12 @@ (use --biject to mark a series as a replacement for another) [255] $ hg debugobsolete - 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '*', 'user': 'blah'} (glob) - 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (*) {'ef1': '*', 'user': 'test'} (glob) - 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (*) {'ef1': '*', 'user': 'test'} (glob) - 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (*) {'ef1': '*', 'user': 'test'} (glob) - bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 (*) {'ef1': '*', 'user': 'test'} (glob) + 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'blah'} + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} + 00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} two old, one new: @@ -214,14 +214,14 @@ $ hg prune 'desc("add cc")' 'desc("add bb")' -s 'desc("add nB")' --fold 2 changesets pruned $ hg debugobsolete - 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '*', 'user': 'blah'} (glob) - 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (*) {'ef1': '*', 'user': 'test'} (glob) - 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (*) {'ef1': '*', 'user': 'test'} (glob) - 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (*) {'ef1': '*', 'user': 'test'} (glob) - bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 814c38b95e72dfe2cbf675b1649ea9d780c89a80 6f6f25e4f748d8f7571777e6e168aedf50350ce8 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 354011cd103f58bbbd9091a3cee6d6a6bd0dddf7 6f6f25e4f748d8f7571777e6e168aedf50350ce8 0 (*) {'ef1': '*', 'user': 'test'} (glob) + 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'blah'} + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} + 00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} + 814c38b95e72dfe2cbf675b1649ea9d780c89a80 6f6f25e4f748d8f7571777e6e168aedf50350ce8 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '9', 'operation': 'prune', 'user': 'test'} + 354011cd103f58bbbd9091a3cee6d6a6bd0dddf7 6f6f25e4f748d8f7571777e6e168aedf50350ce8 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} two old, two new with --biject @@ -236,16 +236,16 @@ working directory now at 1f0dee641bb7 2 changesets pruned $ hg debugobsolete - 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '*', 'user': 'blah'} (glob) - 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (*) {'ef1': '*', 'user': 'test'} (glob) - 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (*) {'ef1': '*', 'user': 'test'} (glob) - 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (*) {'ef1': '*', 'user': 'test'} (glob) - bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 814c38b95e72dfe2cbf675b1649ea9d780c89a80 6f6f25e4f748d8f7571777e6e168aedf50350ce8 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 354011cd103f58bbbd9091a3cee6d6a6bd0dddf7 6f6f25e4f748d8f7571777e6e168aedf50350ce8 0 (*) {'ef1': '*', 'user': 'test'} (glob) - cb7f8f706a6532967b98cf8583a81baab79a0fa7 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 21b6f2f1cece8c10326e575dd38239189d467190 6e8148413dd541855b72a920a90c06fca127c7e7 0 (*) {'ef1': '*', 'user': 'test'} (glob) + 9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'blah'} + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {7c3bad9141dcb46ff89abf5f61856facd56e476c} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} + bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} + 00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} + 814c38b95e72dfe2cbf675b1649ea9d780c89a80 6f6f25e4f748d8f7571777e6e168aedf50350ce8 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '9', 'operation': 'prune', 'user': 'test'} + 354011cd103f58bbbd9091a3cee6d6a6bd0dddf7 6f6f25e4f748d8f7571777e6e168aedf50350ce8 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} + cb7f8f706a6532967b98cf8583a81baab79a0fa7 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} + 21b6f2f1cece8c10326e575dd38239189d467190 6e8148413dd541855b72a920a90c06fca127c7e7 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'prune', 'user': 'test'} test hg strip replacement @@ -354,13 +354,14 @@ more than 2 successors: 0 available keys: ef1: 7 + operation: 7 user: 7 marker size: format v1: - smallest length: 75 - longer length: 75 - median length: 75 - mean length: 75 + smallest length: 91 + longer length: 91 + median length: 91 + mean length: 91 format v0: smallest length: * (glob) longer length: * (glob) diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-partial-C2.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-partial-C4.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-pruned-B2.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-pruned-B3.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-pruned-B4.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-pruned-B5.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-pruned-B8.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-superceed-A2.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-superceed-A3.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-superceed-A6.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-superceed-A7.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-unpushed-D2.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-unpushed-D3.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-unpushed-D4.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-push-checkheads-unpushed-D5.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-sharing.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-split.t --- a/tests/test-split.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-split.t Wed Mar 21 16:06:17 2018 +0100 @@ -92,7 +92,7 @@ $ hg debugobsolete 1334a80b33c3f9873edab728fbbcf500eab61d2e d2fe56e71366c2c5376c89960c281395062c0619 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} - d2fe56e71366c2c5376c89960c281395062c0619 2d8abdb827cdf71ca477ef6985d7ceb257c53c1b 033b3f5ae73db67c10de938fb6f26b949aaef172 0 (*) {'ef1': '13', 'user': 'test'} (glob) + d2fe56e71366c2c5376c89960c281395062c0619 2d8abdb827cdf71ca477ef6985d7ceb257c53c1b 033b3f5ae73db67c10de938fb6f26b949aaef172 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'split', 'user': 'test'} $ hg log -G @ changeset: 6:033b3f5ae73d | tag: tip @@ -209,11 +209,11 @@ $ hg debugobsolete 1334a80b33c3f9873edab728fbbcf500eab61d2e d2fe56e71366c2c5376c89960c281395062c0619 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} - d2fe56e71366c2c5376c89960c281395062c0619 2d8abdb827cdf71ca477ef6985d7ceb257c53c1b 033b3f5ae73db67c10de938fb6f26b949aaef172 0 (*) {'ef1': '13', 'user': 'test'} (glob) + d2fe56e71366c2c5376c89960c281395062c0619 2d8abdb827cdf71ca477ef6985d7ceb257c53c1b 033b3f5ae73db67c10de938fb6f26b949aaef172 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'split', 'user': 'test'} 52149352b372d39b19127d5bd2d488b1b63f9f85 b434287e665ce757ee5463a965cb3d119ca9e893 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '9', 'operation': 'amend', 'user': 'test'} - 2d8abdb827cdf71ca477ef6985d7ceb257c53c1b e2b4afde39803bd42bb1374b230fca1b1e8cc868 0 (*) {'ef1': '4', 'user': 'test'} (glob) - 033b3f5ae73db67c10de938fb6f26b949aaef172 bb5e4f6020c74e7961a51fda635ea9df9b04dda8 0 (*) {'ef1': '4', 'user': 'test'} (glob) - b434287e665ce757ee5463a965cb3d119ca9e893 ead2066d1dbf14833fe1069df1b735e4e9468c40 1188c4216eba37f18a1de6558564601d00ff2143 0 (*) {'ef1': '13', 'user': 'test'} (glob) + 2d8abdb827cdf71ca477ef6985d7ceb257c53c1b e2b4afde39803bd42bb1374b230fca1b1e8cc868 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'evolve', 'user': 'test'} + 033b3f5ae73db67c10de938fb6f26b949aaef172 bb5e4f6020c74e7961a51fda635ea9df9b04dda8 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'evolve', 'user': 'test'} + b434287e665ce757ee5463a965cb3d119ca9e893 ead2066d1dbf14833fe1069df1b735e4e9468c40 1188c4216eba37f18a1de6558564601d00ff2143 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'split', 'user': 'test'} $ hg evolve --all move:[8] split1 atop:[11] split4 diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-stabilize-conflict.t --- a/tests/test-stabilize-conflict.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-stabilize-conflict.t Wed Mar 21 16:06:17 2018 +0100 @@ -65,8 +65,8 @@ $ safesed 's/huit/eight/' babar $ hg diff diff -r 9d5daf8bd956 babar - --- a/babar * (glob) - +++ b/babar * (glob) + --- a/babar Thu Jan 01 00:00:00 1970 +0000 + +++ b/babar Thu Jan 01 00:00:00 1970 +0000 @@ -5,6 +5,6 @@ cinq six @@ -167,8 +167,10 @@ $ safesed 's/dix/ten/' babar $ hg resolve --all -m (no more unresolved files) + continue: hg evolve --continue $ hg evolve --continue evolving 4:71c18f70c34f "babar count up to fifteen" + working directory is now at 1836b91c6c1d $ hg resolve -l $ hg log -G @ changeset: 6:1836b91c6c1d diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-stabilize-order.t --- a/tests/test-stabilize-order.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-stabilize-order.t Wed Mar 21 16:06:17 2018 +0100 @@ -112,8 +112,8 @@ @@ -1,3 +1,4 @@ ef23d6ef94d68dea65d20587dfecc8b33d165617 22619daeed78036f80fbd326b6852519c4f0c25e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} 93418d2c0979643ad446f621195e78720edb05b4 005fe5914f78e8bc64c7eba28117b0b1fa210d0d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} - 22619daeed78036f80fbd326b6852519c4f0c25e 81b8bbcd5892841efed41433d7a5e9df922396cb 0 (*) {'ef1': '4', 'user': 'test'} (glob) - +7a7552255fb5f8bd745e46fba6f0ca633a4dd716 0f691739f91762462bf8ba21f35fdf71fe64310e 0 (*) {'ef1': '4', 'user': 'test'} (glob) + 22619daeed78036f80fbd326b6852519c4f0c25e 81b8bbcd5892841efed41433d7a5e9df922396cb 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'evolve', 'user': 'test'} + +7a7552255fb5f8bd745e46fba6f0ca633a4dd716 0f691739f91762462bf8ba21f35fdf71fe64310e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'evolve', 'user': 'test'} [1] diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-stabilize-result.t --- a/tests/test-stabilize-result.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-stabilize-result.t Wed Mar 21 16:06:17 2018 +0100 @@ -50,8 +50,8 @@ o 0:07f494440405@default(draft) bk:[] adda $ hg debugobsolete - 102a90ea7b4a3361e4082ed620918c261189a36a fb9d051ec0a450a4aa2ffc8c324979832ef88065 0 (*) {'ef1': '*', 'user': 'test'} (glob) - cce2c55b896511e0b6e04173c9450ba822ebc740 0 {102a90ea7b4a3361e4082ed620918c261189a36a} (*) {'ef1': '*', 'user': 'test'} (glob) + 102a90ea7b4a3361e4082ed620918c261189a36a fb9d051ec0a450a4aa2ffc8c324979832ef88065 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '9', 'operation': 'amend', 'user': 'test'} + cce2c55b896511e0b6e04173c9450ba822ebc740 0 {102a90ea7b4a3361e4082ed620918c261189a36a} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'evolve', 'user': 'test'} Test evolve with conflict @@ -60,8 +60,8 @@ b $ hg pdiff a diff -r 07f494440405 a - --- a/a * (glob) - +++ b/a * (glob) + --- a/a Thu Jan 01 00:00:00 1970 +0000 + +++ b/a Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +1,2 @@ a +a @@ -86,8 +86,8 @@ $ hg revert -r "orphan()" a $ hg diff diff -r 66719795a494 a - --- a/a * (glob) - +++ b/a * (glob) + --- a/a Thu Jan 01 00:00:00 1970 +0000 + +++ b/a Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +1,3 @@ a +a @@ -98,8 +98,10 @@ [255] $ hg resolve -m a (no more unresolved files) + continue: hg evolve --continue $ hg evolve --continue evolving 4:3655f0f50885 "newer a" + working directory is now at 1cf0aacfd363 Stabilize latecomer with different parent ========================================= @@ -127,8 +129,7 @@ Get a successors of 8 on it $ hg grab 1cf0aacfd363 - rebasing 6:1cf0aacfd363 "newer a" - ? files updated, 0 files merged, 0 files removed, 0 files unresolved (glob) + grabbing 6:1cf0aacfd363 "newer a" Add real change to the successors @@ -140,7 +141,7 @@ $ hg phase --hidden --public 1cf0aacfd363 1 new phase-divergent changesets $ glog - @ 9:(73b15c7566e9|d5c7ef82d003)@default\(draft\) bk:\[\] newer a (re) + @ 9:99c21c89bcef@default(draft) bk:[] newer a | o 7:7bc2f5967f5e@default(draft) bk:[] add c | @@ -156,10 +157,10 @@ $ hg evolve --any --dry-run --phase-divergent recreate:[9] newer a atop:[6] newer a - hg rebase --rev d5c7ef82d003 --dest 66719795a494; + hg rebase --rev 99c21c89bcef --dest 66719795a494; hg update 1cf0aacfd363; - hg revert --all --rev d5c7ef82d003; - hg commit --msg "phase-divergent update to d5c7ef82d003" + hg revert --all --rev 99c21c89bcef; + hg commit --msg "phase-divergent update to 99c21c89bcef" $ hg evolve --any --confirm --phase-divergent recreate:[9] newer a atop:[6] newer a @@ -172,10 +173,10 @@ perform evolve? [Ny] y rebasing to destination parent: 66719795a494 computing new diff - committed as 8c986e77913c - working directory is now at 8c986e77913c + committed as 3d968e0b3097 + working directory is now at 3d968e0b3097 $ glog - @ 11:8c986e77913c@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: + @ 11:3d968e0b3097@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: | | o 7:7bc2f5967f5e@default(draft) bk:[] add c | | @@ -204,7 +205,7 @@ $ glog @ 12:3932c176bbaa@default(draft) bk:[] More addition | - | o 11:8c986e77913c@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: + | o 11:3d968e0b3097@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: | | o | 7:7bc2f5967f5e@default(draft) bk:[] add c | | @@ -231,7 +232,7 @@ | | o 13:d2f173e25686@default(draft) bk:[] More addition |/ - | o 11:8c986e77913c@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: + | o 11:3d968e0b3097@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: | | o | 7:7bc2f5967f5e@default(draft) bk:[] add c | | @@ -281,7 +282,7 @@ $ glog @ 15:f344982e63c4@default(draft) bk:[] More addition | - | o 11:8c986e77913c@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: + | o 11:3d968e0b3097@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: | | o | 7:7bc2f5967f5e@default(draft) bk:[] add c | | diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-stack-branch.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-topic-change.t --- a/tests/test-topic-change.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-topic-change.t Wed Mar 21 16:06:17 2018 +0100 @@ -98,7 +98,7 @@ foo (8 changesets) Changing topics on some revisions (also testing issue 5441) - $ hg topic -r 12:: bar + $ hg topic -r abcedffeae90:: bar switching to topic bar changed topic on 4 changes $ hg glog diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-topic-debugcb.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-topic-stack-complex.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-topic-stack-data.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-topic-stack.t --- a/tests/test-topic-stack.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-topic-stack.t Wed Mar 21 16:06:17 2018 +0100 @@ -861,16 +861,16 @@ | @ e7ea874afbd5 (22) c_G |/ x b24bab30ac12 (20) c_G - | rewritten(parent, content) as dde94df880e9, e7ea874afbd5 by test (Thu Jan 01 00:00:00 1970 +0000) + | rewritten(parent, content) as dde94df880e9, e7ea874afbd5 using split by test (Thu Jan 01 00:00:00 1970 +0000) | x 907f7d3c2333 (18) c_G - | rewritten as b24bab30ac12 by test (Thu Jan 01 00:00:00 1970 +0000) + | rewritten as b24bab30ac12 using amend by test (Thu Jan 01 00:00:00 1970 +0000) | x 3ab2eedae500 (13) c_G - | rewritten as 907f7d3c2333 by test (Thu Jan 01 00:00:00 1970 +0000) + | rewritten as 907f7d3c2333 using rebase by test (Thu Jan 01 00:00:00 1970 +0000) | x c7d60a180d05 (6) c_G - rewritten as 3ab2eedae500 by test (Thu Jan 01 00:00:00 1970 +0000) + rewritten as 3ab2eedae500 using amend by test (Thu Jan 01 00:00:00 1970 +0000) $ hg export . # HG changeset patch diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-topic-tutorial.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-topic.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-touch.t --- a/tests/test-touch.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-touch.t Wed Mar 21 16:06:17 2018 +0100 @@ -155,7 +155,7 @@ 1 new orphan changesets $ hg obslog -r 13 --hidden x [0-9a-f]{12} (.*) move (re) - pruned by test (Thu Jan 01 00:00:00 1970 +0000) - rewritten(.*) as [0-9a-f]{12} by test (.*) (re) + pruned using prune by test (Thu Jan 01 00:00:00 1970 +0000) + rewritten(.*) as [0-9a-f]{12} using touch by test (.*) (re) note: testing with no successor diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-tutorial.t --- a/tests/test-tutorial.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-tutorial.t Wed Mar 21 16:06:17 2018 +0100 @@ -665,11 +665,10 @@ $ hg up 'p1(10b8aeaa8cc8)' # going on "bathroom stuff" parent 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg grab fac207dec9f5 # moving "SPAM SPAM" to the working directory parent - rebasing 9:fac207dec9f5 "SPAM SPAM" (tip) + grabbing 9:fac207dec9f5 "SPAM SPAM" merging shopping - ? files updated, 0 files merged, 0 files removed, 0 files unresolved (glob) $ hg log -G - @ a224f2a4fb9f (draft): SPAM SPAM + @ 57e9caedbcb8 (draft): SPAM SPAM | | o 10b8aeaa8cc8 (draft): bathroom stuff |/ @@ -775,7 +774,7 @@ # User test # Date 0 0 # Thu Jan 01 00:00:00 1970 +0000 - # Node ID a224f2a4fb9f9f828f608959912229d7b38b26de + # Node ID 57e9caedbcb8575a01c128db9d1bcbd624ef2115 # Parent 41aff6a42b7578ec7ec3cb2041633f1ca43cca96 SPAM SPAM @@ -808,14 +807,13 @@ for simplicity sake we get the bathroom change in line again $ hg grab 10b8aeaa8cc8 - rebasing 8:10b8aeaa8cc8 "bathroom stuff" + grabbing 8:10b8aeaa8cc8 "bathroom stuff" merging shopping - ? files updated, 0 files merged, 0 files removed, 0 files unresolved (glob) $ hg phase --draft . $ hg log -G - @ 75954b8cd933 (draft): bathroom stuff + @ 4710c0968793 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1016,12 +1014,12 @@ adding file changes added 1 changesets with 1 changes to 1 files 1 new obsolescence markers - new changesets 75954b8cd933 + new changesets 4710c0968793 (run 'hg update' to get a working copy) $ hg log -G - o 75954b8cd933 (public): bathroom stuff + o 4710c0968793 (public): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1039,7 +1037,7 @@ $ hg rollback repository tip rolled back to revision 4 (undo pull) $ hg log -G - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1072,12 +1070,12 @@ adding file changes added 1 changesets with 1 changes to 1 files 1 new obsolescence markers - new changesets 75954b8cd933 + new changesets 4710c0968793 (run 'hg update' to get a working copy) $ hg log -G - o 75954b8cd933 (draft): bathroom stuff + o 4710c0968793 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1093,7 +1091,7 @@ Remotely someone add a new changeset on top of the mutable "bathroom" on. - $ hg up 75954b8cd933 -q + $ hg up 4710c0968793 -q $ cat >> shopping << EOF > Giraffe > Rhino @@ -1105,13 +1103,13 @@ But at the same time, locally, this same "bathroom changeset" was updated. $ cd ../local - $ hg up 75954b8cd933 -q + $ hg up 4710c0968793 -q $ sed -i'' -e 's/... More bathroom stuff to come/Bath Robe/' shopping $ hg commit --amend $ hg log -G - @ a44c85f957d3 (draft): bathroom stuff + @ 682004e81e71 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1213,22 +1211,21 @@ adding manifests adding file changes added 1 changesets with 1 changes to 1 files - new changesets bf1b0d202029 + new changesets e4e4fa805d92 (run 'hg update' to get a working copy) 1 new orphan changesets - The new changeset "animal" is based on an old changeset of "bathroom". You can see both version showing up in the log. $ hg log -G - o bf1b0d202029 (draft): animals + o e4e4fa805d92 (draft): animals | - | @ a44c85f957d3 (draft): bathroom stuff + | @ 682004e81e71 (draft): bathroom stuff | | - x | 75954b8cd933 (draft): bathroom stuff + x | 4710c0968793 (draft): bathroom stuff |/ - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1361,7 +1358,7 @@ $ hg push other pushing to $TESTTMP/other (glob) searching for changes - abort: push includes orphan changeset: bf1b0d202029! + abort: push includes orphan changeset: e4e4fa805d92! (use 'hg evolve' to get a stable history or --force to ignore warnings) [255] @@ -1374,7 +1371,7 @@ $ hg evolve --dry-run move:[13] animals atop:[12] bathroom stuff - hg rebase -r bf1b0d202029 -d a44c85f957d3 + hg rebase -r e4e4fa805d92 -d 682004e81e71 Let's do it @@ -1382,16 +1379,16 @@ move:[13] animals atop:[12] bathroom stuff merging shopping - working directory is now at ee942144f952 + working directory is now at 2a2b36e14660 The old version of bathroom is hidden again. $ hg log -G - @ ee942144f952 (draft): animals + @ 2a2b36e14660 (draft): animals | - o a44c85f957d3 (draft): bathroom stuff + o 682004e81e71 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1520,13 +1517,13 @@ Now let's see where we are, and update to the successor. $ hg parents - bf1b0d202029 (draft): animals - working directory parent is obsolete! (bf1b0d202029) - (use 'hg evolve' to update to its successor: ee942144f952) + e4e4fa805d92 (draft): animals + working directory parent is obsolete! (e4e4fa805d92) + (use 'hg evolve' to update to its successor: 2a2b36e14660) $ hg evolve update:[8] animals 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory is now at ee942144f952 + working directory is now at 2a2b36e14660 Relocating unstable change after prune ---------------------------------------------- @@ -1546,16 +1543,16 @@ adding manifests adding file changes added 1 changesets with 1 changes to 1 files - new changesets 99f039c5ec9e + new changesets fc41faf45288 (run 'hg update' to get a working copy) $ hg log -G - o 99f039c5ec9e (draft): SPAM SPAM SPAM + o fc41faf45288 (draft): SPAM SPAM SPAM | - @ ee942144f952 (draft): animals + @ 2a2b36e14660 (draft): animals | - o a44c85f957d3 (draft): bathroom stuff + o 682004e81e71 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1674,9 +1671,9 @@ In the mean time I noticed you can't buy animals in a super market and I prune the animal changeset: - $ hg prune ee942144f952 + $ hg prune 2a2b36e14660 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory now at a44c85f957d3 + working directory now at 682004e81e71 1 changesets pruned 1 new orphan changesets @@ -1685,13 +1682,13 @@ is neither dead or obsolete. My repository is in an unstable state again. $ hg log -G - o 99f039c5ec9e (draft): SPAM SPAM SPAM + o fc41faf45288 (draft): SPAM SPAM SPAM | - x ee942144f952 (draft): animals + x 2a2b36e14660 (draft): animals | - @ a44c85f957d3 (draft): bathroom stuff + @ 682004e81e71 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1809,7 +1806,7 @@ #endif $ hg log -r "orphan()" - 99f039c5ec9e (draft): SPAM SPAM SPAM + fc41faf45288 (draft): SPAM SPAM SPAM #if docgraph-ext $ hg docgraph -r "orphan()" --sphinx-directive --rankdir LR #rest-ignore @@ -1837,14 +1834,14 @@ move:[15] SPAM SPAM SPAM atop:[12] bathroom stuff merging shopping - working directory is now at 40aa40daeefb + working directory is now at e6cfcb672150 $ hg log -G - @ 40aa40daeefb (draft): SPAM SPAM SPAM + @ e6cfcb672150 (draft): SPAM SPAM SPAM | - o a44c85f957d3 (draft): bathroom stuff + o 682004e81e71 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-uncommit-interactive.t --- a/tests/test-uncommit-interactive.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-uncommit-interactive.t Wed Mar 21 16:06:17 2018 +0100 @@ -168,7 +168,7 @@ @ 678a59e5ff90 (3) another one | x f70fb463d5bf (1) another one - rewritten(content) as 678a59e5ff90 by test (Thu Jan 01 00:00:00 1970 +0000) + rewritten(content) as 678a59e5ff90 using uncommit by test (Thu Jan 01 00:00:00 1970 +0000) note: note on amend --extract The unselected part should be in the diff @@ -300,11 +300,11 @@ @ 46e35360be47 (5) another one | x 678a59e5ff90 (3) another one - | rewritten(content) as 46e35360be47 by test (Thu Jan 01 00:00:00 1970 +0000) + | rewritten(content) as 46e35360be47 using uncommit by test (Thu Jan 01 00:00:00 1970 +0000) | note: testing uncommit on dirty wdir | x f70fb463d5bf (1) another one - rewritten(content) as 678a59e5ff90 by test (Thu Jan 01 00:00:00 1970 +0000) + rewritten(content) as 678a59e5ff90 using uncommit by test (Thu Jan 01 00:00:00 1970 +0000) note: note on amend --extract diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-uncommit.t --- a/tests/test-uncommit.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-uncommit.t Wed Mar 21 16:06:17 2018 +0100 @@ -233,7 +233,7 @@ touncommit-bm-inactive 4:e8db4aa611f6 unrelated 2:f63b90038565 $ hg debugobsolete - 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 e8db4aa611f6d5706374288e6898e498f5c44098 0 (*) {'ef1': '*', 'user': 'test'} (glob) + 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 e8db4aa611f6d5706374288e6898e498f5c44098 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'uncommit', 'user': 'test'} Test phase is preserved, no local changes @@ -279,8 +279,8 @@ o 0:07f494440405@default(draft) adda $ hg debugobsolete - 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 e8db4aa611f6d5706374288e6898e498f5c44098 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 a1d4c1ad76cc7eb5e8a36ef52396da334b6d59c5 0 (*) {'ef1': '*', 'user': 'test'} (glob) + 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 e8db4aa611f6d5706374288e6898e498f5c44098 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'uncommit', 'user': 'test'} + 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 a1d4c1ad76cc7eb5e8a36ef52396da334b6d59c5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'uncommit', 'user': 'test'} Test --all @@ -313,9 +313,9 @@ A e $ hg debugobsolete - 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 e8db4aa611f6d5706374288e6898e498f5c44098 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 a1d4c1ad76cc7eb5e8a36ef52396da334b6d59c5 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 c4cbebac3751269bdf12d1466deabcc78521d272 0 (*) {'ef1': '*', 'user': 'test'} (glob) + 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 e8db4aa611f6d5706374288e6898e498f5c44098 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'uncommit', 'user': 'test'} + 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 a1d4c1ad76cc7eb5e8a36ef52396da334b6d59c5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'uncommit', 'user': 'test'} + 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 c4cbebac3751269bdf12d1466deabcc78521d272 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'uncommit', 'user': 'test'} Display a warning if nothing left @@ -323,10 +323,10 @@ new changeset is empty (use 'hg prune .' to remove it) $ hg debugobsolete - 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 e8db4aa611f6d5706374288e6898e498f5c44098 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 a1d4c1ad76cc7eb5e8a36ef52396da334b6d59c5 0 (*) {'ef1': '*', 'user': 'test'} (glob) - 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 c4cbebac3751269bdf12d1466deabcc78521d272 0 (*) {'ef1': '*', 'user': 'test'} (glob) - c4cbebac3751269bdf12d1466deabcc78521d272 4f1c269eab68720f54e88ce3c1dc02b2858b6b89 0 (*) {'ef1': '*', 'user': 'test'} (glob) + 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 e8db4aa611f6d5706374288e6898e498f5c44098 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'uncommit', 'user': 'test'} + 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 a1d4c1ad76cc7eb5e8a36ef52396da334b6d59c5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'uncommit', 'user': 'test'} + 5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 c4cbebac3751269bdf12d1466deabcc78521d272 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'uncommit', 'user': 'test'} + c4cbebac3751269bdf12d1466deabcc78521d272 4f1c269eab68720f54e88ce3c1dc02b2858b6b89 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'uncommit', 'user': 'test'} Test instability warning diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-unstable.t --- a/tests/test-unstable.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-unstable.t Wed Mar 21 16:06:17 2018 +0100 @@ -68,154 +68,6 @@ $ cd .. =============================================================================== -Test instability resolution for a merge changeset unstable because one -of its parent is obsolete -Not supported yet -============================================================================== - - $ hg init test2 - $ cd test2 - $ mkcommit base - $ mkcommits _a - $ hg up "desc(base)" - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ mkcommit _c - created new head - $ hg merge "desc(_a)" >/dev/null - $ hg commit -m "merge" - $ hg up "desc(_a)" - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg amend -m "aprime" - 1 new orphan changesets - $ hg log -G - @ 4:47127ea62e5f@default(draft) aprime - | - | o 3:6b4280e33286@default(draft) merge - | |\ - +---o 2:474da87dd33b@default(draft) add _c - | | - | x 1:b3264cec9506@default(draft) add _a - |/ - o 0:b4952fcf48cf@default(draft) add base - - - $ hg evo --all --any --orphan - move:[3] merge - atop:[4] aprime - working directory is now at 0bf3f3a59c8c - $ hg log -G - @ 5:0bf3f3a59c8c@default(draft) merge - |\ - | o 4:47127ea62e5f@default(draft) aprime - | | - o | 2:474da87dd33b@default(draft) add _c - |/ - o 0:b4952fcf48cf@default(draft) add base - - - $ cd .. - -=============================================================================== -Test instability resolution for a merge changeset unstable because both -of its parent are obsolete -Not supported yet -============================================================================== - - $ hg init test3 - $ cd test3 - $ mkcommit base - $ mkcommits _a - $ hg up "desc(base)" - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ mkcommit _c - created new head - $ hg merge "desc(_a)" >/dev/null - $ hg commit -m "merge" - $ hg up "desc(_a)" - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg amend -m "aprime" - 1 new orphan changesets - $ hg up "desc(_c)" - 1 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg amend -m "cprime" - $ hg log -G - @ 5:2db39fda7e2f@default(draft) cprime - | - | o 4:47127ea62e5f@default(draft) aprime - |/ - | o 3:6b4280e33286@default(draft) merge - | |\ - +---x 2:474da87dd33b@default(draft) add _c - | | - | x 1:b3264cec9506@default(draft) add _a - |/ - o 0:b4952fcf48cf@default(draft) add base - - - $ hg evo --all --any --orphan - warning: no support for evolving merge changesets with two obsolete parents yet - (Redo the merge (6b4280e33286) and use `hg prune --succ ` to obsolete the old one) - $ hg log -G - @ 5:2db39fda7e2f@default(draft) cprime - | - | o 4:47127ea62e5f@default(draft) aprime - |/ - | o 3:6b4280e33286@default(draft) merge - | |\ - +---x 2:474da87dd33b@default(draft) add _c - | | - | x 1:b3264cec9506@default(draft) add _a - |/ - o 0:b4952fcf48cf@default(draft) add base - - - $ cd .. - -=============================================================================== -Test instability resolution for a changeset unstable because its parent -is obsolete with multiple successors all in one chain (simple split) -============================================================================== - - $ hg init test4 - $ cd test4 - $ mkcommits _a _b _c - $ hg up "desc(_a)" - 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ mkcommits bprimesplit1 bprimesplit2 - created new head - $ hg prune "desc(_b)" -s "desc(bprimesplit1) + desc(bprimesplit2)" --split - 1 changesets pruned - 1 new orphan changesets - $ hg log -G - @ 4:2a4ccc0bb20c@default(draft) add bprimesplit2 - | - o 3:8b87864bd0f4@default(draft) add bprimesplit1 - | - | o 2:102002290587@default(draft) add _c - | | - | x 1:37445b16603b@default(draft) add _b - |/ - o 0:135f39f4bd78@default(draft) add _a - - - $ hg evo --all --any --orphan - move:[2] add _c - atop:[4] add bprimesplit2 - working directory is now at 387cc1e837d7 - $ hg log -G - @ 5:387cc1e837d7@default(draft) add _c - | - o 4:2a4ccc0bb20c@default(draft) add bprimesplit2 - | - o 3:8b87864bd0f4@default(draft) add bprimesplit1 - | - o 0:135f39f4bd78@default(draft) add _a - - - - $ cd .. - -=============================================================================== Test instability resolution for a changeset unstable because its parent is obsolete with multiple successors on one branches but in reverse order (cross-split). @@ -266,55 +118,4 @@ o 0:135f39f4bd78@default(draft) add _a - $ cd .. - -=============================================================================== -Test instability resolution for a changeset unstable because its parent -is obsolete with multiple successors on two branches. -Not supported yet -============================================================================== - - $ hg init test6 - $ cd test6 - $ mkcommits _a _b _c - $ hg up "desc(_a)" - 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ mkcommit bprimesplit1 - created new head - $ hg up "desc(_a)" - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ mkcommit bprimesplit2 - created new head - $ hg prune "desc(_b)" -s "desc(bprimesplit1) + desc(bprimesplit2)" --split - 1 changesets pruned - 1 new orphan changesets - $ hg log -G - @ 4:3c69ea6aa93e@default(draft) add bprimesplit2 - | - | o 3:8b87864bd0f4@default(draft) add bprimesplit1 - |/ - | o 2:102002290587@default(draft) add _c - | | - | x 1:37445b16603b@default(draft) add _b - |/ - o 0:135f39f4bd78@default(draft) add _a - - - $ hg evo --all --any --orphan - cannot solve split across two branches - $ hg log -G - @ 4:3c69ea6aa93e@default(draft) add bprimesplit2 - | - | o 3:8b87864bd0f4@default(draft) add bprimesplit1 - |/ - | o 2:102002290587@default(draft) add _c - | | - | x 1:37445b16603b@default(draft) add _b - |/ - o 0:135f39f4bd78@default(draft) add _a - - - - $ cd .. - diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-userguide.t diff -r 7dce44b4abb6 -r d5adce52cef4 tests/test-wireproto.t --- a/tests/test-wireproto.t Wed Jan 24 15:08:09 2018 +0100 +++ b/tests/test-wireproto.t Wed Mar 21 16:06:17 2018 +0100 @@ -141,7 +141,7 @@ remote: adding manifests remote: adding file changes remote: added 1 changesets with 0 changes to 1 files (+1 heads) - remote: obsmarker-exchange: 167 bytes received + remote: obsmarker-exchange: 183 bytes received remote: 1 new obsolescence markers remote: obsoleted 1 changesets $ hg -R ../other pull @@ -151,7 +151,7 @@ adding manifests adding file changes added 1 changesets with 0 changes to 1 files (+1 heads) - obsmarker-exchange: 167 bytes received + obsmarker-exchange: 183 bytes received 1 new obsolescence markers obsoleted 1 changesets new changesets * (glob) @@ -177,7 +177,7 @@ (skipping discovery of obsolescence markers, will exchange everything) (controled by 'experimental.evolution.obsdiscovery' configuration) no changes found - remote: obsmarker-exchange: 258 bytes received + remote: obsmarker-exchange: 274 bytes received [1] $ hg -R ../other pull --config experimental.evolution.obsdiscovery=no pulling from ssh://user@dummy/server @@ -185,7 +185,7 @@ no changes found (skipping discovery of obsolescence markers, will exchange everything) (controled by 'experimental.evolution.obsdiscovery' configuration) - obsmarker-exchange: 258 bytes received + obsmarker-exchange: 274 bytes received $ cd .. @@ -202,6 +202,7 @@ $ hg debugpushkey http://localhost:$HGPORT/ obsolete abort: HTTP Error 410: won't exchange obsmarkers through pushkey [255] + $ cat errors.log $ hg debugpushkey ssh://user@dummy/server obsolete remote: abort: won't exchange obsmarkers through pushkey remote: (upgrade your client or server to use the bundle2 protocol) @@ -214,7 +215,7 @@ pulling from http://localhost:$HGPORT/ searching for changes no changes found - obsmarker-exchange: 258 bytes received + obsmarker-exchange: 274 bytes received $ hg -R client pull http://localhost:$HGPORT/ --config experimental.evolution=createmarkers pulling from http://localhost:$HGPORT/