# HG changeset patch # User Pierre-Yves David # Date 1524478980 -7200 # Node ID a77fb9669e990d6f549b45b70642a96a781411b7 # Parent 19ec729f3ca2575517bb28938d1caa8449ca93d6# Parent 98941c28f3e2a686a4a5ef3900cc68c7a4c06687 test-compat: merge mercurial-4.4 into mercurial-4.3 diff -r 98941c28f3e2 -r a77fb9669e99 .hgtags --- a/.hgtags Wed Mar 21 16:18:31 2018 +0100 +++ b/.hgtags Mon Apr 23 12:23:00 2018 +0200 @@ -64,3 +64,4 @@ 06a3cb59495636df8b567e49a0fd7fd8fd823074 7.1.0 bf6b859807bac23752a26e58876fe3a4a9a2fef8 7.2.0 6c772398eb4e209914e1074cdac4f3ebf714e437 7.2.1 +e4ac2e2c2086f977afa35e23a62f849e9305a225 7.3.0 diff -r 98941c28f3e2 -r a77fb9669e99 CHANGELOG --- a/CHANGELOG Wed Mar 21 16:18:31 2018 +0100 +++ b/CHANGELOG Mon Apr 23 12:23:00 2018 +0200 @@ -1,6 +1,25 @@ Changelog ========= +8.0.0 - in progress +------------------- + + * drop support for Mercurial 4.1 and 4.2 + * `--obsolete` and `--old-obsolete` flags for `hg graft` are dropped + * evolve: a new `--abort` flag which aborts an interrupted evolve + resolving orphans + * `hg evolve` now return 0 if there is nothing to evolve + * amend: a new `--patch` flag to make changes to wdir parent by editing patch + + * fixed some memory leak issue + + * templatekw: remove `obsfatedata` templatekw. Individuals fields are + available in core as single template functions. + + * fixed issue 5833 and 5832 + + * topic: restring name to letter, '-', '_' and '.' + 7.3.0 -- 2018-03-21 --------------------- diff -r 98941c28f3e2 -r a77fb9669e99 docs/from-mq.rst --- a/docs/from-mq.rst Wed Mar 21 16:18:31 2018 +0100 +++ b/docs/from-mq.rst Mon Apr 23 12:23:00 2018 +0200 @@ -125,7 +125,7 @@ You can also decide to do it manually using:: - $ hg graft -O + $ hg grab or:: diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/__init__.py --- a/hgext3rd/evolve/__init__.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/__init__.py Mon Apr 23 12:23:00 2018 +0200 @@ -32,7 +32,7 @@ backported to older version of Mercurial by this extension. Some older experimental protocol are also supported for a longer time in the extensions to help people transitioning. (The extensions is currently compatible down to -Mercurial version 4.1). +Mercurial version 4.3). New Config:: @@ -78,11 +78,11 @@ # auto: warm cache at the end of server side transaction (default). obshashrange.warm-cache = 'auto' -The initial cache warming might be a bit slow. To make sure it is build you -can run one of the following commands in your repository:: + $ hg debugupdatecache - $ hg debugupdatecache # mercurial 4.3 and above - $ hg debugobshashrange --rev 'head() # mercurial 4.2 and below +It is recommended to enable the blackbox extension. It gathers useful data about +the experiment. It is shipped with Mercurial so no extra install is needed:: + $ hg debugupdatecache It is recommended to enable the blackbox extension. It gathers useful data about the experiment. It is shipped with Mercurial so no extra install is needed:: @@ -299,7 +299,6 @@ from mercurial.node import nullid from . import ( - checkheads, compat, debugcmd, cmdrewrite, @@ -357,7 +356,6 @@ eh.merge(debugcmd.eh) eh.merge(evolvecmd.eh) eh.merge(obsexchange.eh) -eh.merge(checkheads.eh) eh.merge(safeguard.eh) eh.merge(obscache.eh) eh.merge(obshistory.eh) @@ -509,7 +507,7 @@ @eh.uisetup def _installalias(ui): - if ui.config('alias', 'odiff') is None: + if ui.config('alias', 'odiff', None) is None: ui.setconfig('alias', 'odiff', "diff --hidden --rev 'limit(precursors(.),1)' --rev .", 'evolve') @@ -722,8 +720,7 @@ ui.warn("(%s)\n" % solvemsg) -if util.safehasattr(context, '_filterederror'): - # if < hg-4.2 we do not update the message +if util.safehasattr(context, '_filterederror'): # <= hg-4.5 @eh.wrapfunction(context, '_filterederror') def evolve_filtererror(original, repo, changeid): """build an exception to be raised about a filtered changeid @@ -733,10 +730,10 @@ if repo.filtername.startswith('visible'): unfilteredrepo = repo.unfiltered() - rev = unfilteredrepo[changeid] + rev = repo[scmutil.revsingle(unfilteredrepo, changeid)] reason, successors = obshistory._getobsfateandsuccs(unfilteredrepo, rev.node()) - # Be more precise in cqse the revision is superseed + # Be more precise in case the revision is superseed if reason == 'superseed': reason = _("successor: %s") % successors[0] elif reason == 'superseed_split': @@ -880,25 +877,36 @@ _('mark the old node as obsoleted by ' 'the created commit'))) +def _getnodefrompatch(patch, dest): + patchnode = patch.get('nodeid') + if patchnode is not None: + dest['node'] = node.bin(patchnode) + @eh.wrapfunction(mercurial.cmdutil, 'tryimportone') def tryimportone(orig, ui, repo, hunk, parents, opts, *args, **kwargs): - extracted = patch.extract(ui, hunk) - expected = extracted.get('nodeid') - if expected is not None: - expected = node.bin(expected) - oldextract = patch.extract - try: - patch.extract = lambda ui, hunk: extracted + expected = {'node': None} + if not util.safehasattr(hunk, 'get'): # hg < 4.6 + oldextract = patch.extract + + def extract(*args, **kwargs): + ret = oldextract(*args, **kwargs) + _getnodefrompatch(ret, expected) + return ret + try: + patch.extract = extract + ret = orig(ui, repo, hunk, parents, opts, *args, **kwargs) + finally: + patch.extract = oldextract + else: + _getnodefrompatch(hunk, expected) ret = orig(ui, repo, hunk, parents, opts, *args, **kwargs) - finally: - patch.extract = oldextract created = ret[1] - if (opts['obsolete'] and None not in (created, expected) - and created != expected): + if (opts['obsolete'] and None not in (created, expected['node']) + and created != expected['node']): tr = repo.transaction('import-obs') try: metadata = {'user': ui.username()} - repo.obsstore.create(tr, expected, (created,), + repo.obsstore.create(tr, expected['node'], (created,), metadata=metadata) tr.close() finally: @@ -973,7 +981,7 @@ tr = repo.transaction('previous') if bookmark is not None: bmchanges = [(bookmark, target.node())] - compat.bookmarkapplychanges(repo, tr, bmchanges) + repo._bookmarks.applychanges(repo, tr, bmchanges) else: bookmarksmod.deactivate(repo) tr.close() @@ -1166,7 +1174,8 @@ """logic for hg next command to evolve and update to an aspiring children""" cmdutil.bailifchanged(repo) - evolvestate = state.cmdstate(repo, opts={'command': 'next'}) + evolvestate = state.cmdstate(repo, opts={'command': 'next', + 'bookmarkchanges': []}) result = evolvecmd._solveone(ui, repo, repo[aspchildren], evolvestate, opts.get('dry_run'), False, lambda: None, category='orphan') @@ -1194,7 +1203,7 @@ tr = repo.transaction('next') if shouldmove: bmchanges = [(bm, children.node())] - compat.bookmarkapplychanges(repo, tr, bmchanges) + repo._bookmarks.applychanges(repo, tr, bmchanges) else: bookmarksmod.deactivate(repo) tr.close() @@ -1218,14 +1227,14 @@ obsoleted = repo.set('%lr', obsoleted) result = orig(ui, repo, *arg, **kwargs) if not result: # commit succeeded - new = repo['-1'] + new = repo['tip'] oldbookmarks = [] markers = [] for old in obsoleted: oldbookmarks.extend(repo.nodebookmarks(old.node())) markers.append((old, (new,))) if markers: - compat.createmarkers(repo, markers, operation="amend") + obsolete.createmarkers(repo, markers, operation="amend") bmchanges = [] for book in oldbookmarks: bmchanges.append((book, new.node())) @@ -1235,7 +1244,7 @@ if not lock: lock = repo.lock() tr = repo.transaction('commit') - compat.bookmarkapplychanges(repo, tr, bmchanges) + repo._bookmarks.applychanges(repo, tr, bmchanges) tr.close() return result finally: @@ -1266,33 +1275,6 @@ kwargs['biject'] = False return cmdrewrite.cmdprune(ui, repo, *revs, **kwargs) -@eh.wrapcommand('graft') -def graftwrapper(orig, ui, repo, *revs, **kwargs): - kwargs = dict(kwargs) - revs = list(revs) + kwargs.get('rev', []) - kwargs['rev'] = [] - obsoleted = kwargs.setdefault('obsolete', []) - - wlock = lock = None - try: - wlock = repo.wlock() - lock = repo.lock() - if kwargs.get('old_obsolete'): - if kwargs.get('continue'): - obsoleted.extend(repo.vfs.read('graftstate').splitlines()) - else: - obsoleted.extend(revs) - # convert obsolete target into revs to avoid alias joke - obsoleted[:] = [str(i) for i in repo.revs('%lr', obsoleted)] - if obsoleted and len(revs) > 1: - - raise error.Abort(_('cannot graft multiple revisions while ' - 'obsoleting (for now).')) - - return commitwrapper(orig, ui, repo, *revs, **kwargs) - finally: - lockmod.release(lock, wlock) - @eh.extsetup def oldevolveextsetup(ui): for cmd in ['prune', 'uncommit', 'touch', 'fold']: @@ -1306,11 +1288,6 @@ entry = cmdutil.findcmd('commit', commands.table)[1] entry[1].append(('o', 'obsolete', [], _("make commit obsolete this revision (DEPRECATED)"))) - entry = cmdutil.findcmd('graft', commands.table)[1] - entry[1].append(('o', 'obsolete', [], - _("make graft obsoletes this revision (DEPRECATED)"))) - entry[1].append(('O', 'old-obsolete', False, - _("make graft obsoletes its source (DEPRECATED)"))) @eh.wrapfunction(obsolete, '_checkinvalidmarkers') def _checkinvalidmarkers(orig, markers): @@ -1374,7 +1351,7 @@ @eh.uisetup def setupevolveunfinished(ui): - data = ('evolvestate', True, False, _('evolve in progress'), + data = ('evolvestate', False, False, _('evolve in progress'), _("use 'hg evolve --continue' or 'hg update -C .' to abort")) cmdutil.unfinishedstates.append(data) diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/checkheads.py --- a/hgext3rd/evolve/checkheads.py Wed Mar 21 16:18:31 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,276 +0,0 @@ -# Code dedicated to the postprocessing new heads check with obsolescence -# -# Copyright 2017 Pierre-Yves David -# -# This software may be used and distributed according to the terms of the -# GNU General Public License version 2 or any later version. - -import functools - -from mercurial import ( - discovery, - error, - extensions, - node as nodemod, - phases, - util, -) - -from mercurial.i18n import _ - -from . import exthelper - -nullid = nodemod.nullid -short = nodemod.short -_headssummary = discovery._headssummary -_oldheadssummary = discovery._oldheadssummary -_nowarnheads = discovery._nowarnheads - -eh = exthelper.exthelper() - -@eh.uisetup -def setupcheckheadswrapper(ui): - if not util.safehasattr(discovery, '_postprocessobsolete'): - # hg-4.2+ has all the code natively - extensions.wrapfunction(discovery, 'checkheads', - checkheadsfulloverlay) - -# have dedicated wrapper to keep the rest as close as core as possible -def checkheadsfulloverlay(orig, pushop): - if pushop.repo.obsstore: - return corecheckheads(pushop) - else: - return orig(pushop) - -# copied from mercurial.discovery.checkheads as in a5bad127128d (4.1) -# -# The only differences are: -# * the _postprocessobsolete section have been extracted, -# * minor test adjustment to please flake8 -def corecheckheads(pushop): - """Check that a push won't add any outgoing head - - raise Abort error and display ui message as needed. - """ - - repo = pushop.repo.unfiltered() - remote = pushop.remote - outgoing = pushop.outgoing - remoteheads = pushop.remoteheads - newbranch = pushop.newbranch - inc = bool(pushop.incoming) - - # Check for each named branch if we're creating new remote heads. - # To be a remote head after push, node must be either: - # - unknown locally - # - a local outgoing head descended from update - # - a remote head that's known locally and not - # ancestral to an outgoing head - if remoteheads == [nullid]: - # remote is empty, nothing to check. - return - - if remote.capable('branchmap'): - headssum = _headssummary(repo, remote, outgoing) - else: - headssum = _oldheadssummary(repo, remoteheads, outgoing, inc) - newbranches = [branch for branch, heads in headssum.iteritems() - if heads[0] is None] - # 1. Check for new branches on the remote. - if newbranches and not newbranch: # new branch requires --new-branch - branchnames = ', '.join(sorted(newbranches)) - raise error.Abort(_("push creates new remote branches: %s!") - % branchnames, - hint=_("use 'hg push --new-branch' to create" - " new remote branches")) - - # 2. Find heads that we need not warn about - nowarnheads = _nowarnheads(pushop) - - # 3. Check for new heads. - # If there are more heads after the push than before, a suitable - # error message, depending on unsynced status, is displayed. - errormsg = None - # If there is no obsstore, allfuturecommon won't be used, so no - # need to compute it. - if repo.obsstore: - allmissing = set(outgoing.missing) - cctx = repo.set('%ld', outgoing.common) - allfuturecommon = set(c.node() for c in cctx) - allfuturecommon.update(allmissing) - for branch, heads in sorted(headssum.iteritems()): - remoteheads, newheads, unsyncedheads = heads - candidate_newhs = set(newheads) - # add unsynced data - if remoteheads is None: - oldhs = set() - else: - oldhs = set(remoteheads) - oldhs.update(unsyncedheads) - candidate_newhs.update(unsyncedheads) - dhs = None # delta heads, the new heads on branch - if not repo.obsstore: - discardedheads = set() - newhs = candidate_newhs - else: - newhs, discardedheads = _postprocessobsolete(pushop, - allfuturecommon, - candidate_newhs) - unsynced = sorted(h for h in unsyncedheads if h not in discardedheads) - if unsynced: - if None in unsynced: - # old remote, no heads data - heads = None - elif len(unsynced) <= 4 or repo.ui.verbose: - heads = ' '.join(short(h) for h in unsynced) - else: - heads = (' '.join(short(h) for h in unsynced[:4]) + - ' ' + _("and %s others") % (len(unsynced) - 4)) - if heads is None: - repo.ui.status(_("remote has heads that are " - "not known locally\n")) - elif branch is None: - repo.ui.status(_("remote has heads that are " - "not known locally: %s\n") % heads) - else: - repo.ui.status(_("remote has heads on branch '%s' that are " - "not known locally: %s\n") % (branch, heads)) - if remoteheads is None: - if len(newhs) > 1: - dhs = list(newhs) - if errormsg is None: - errormsg = (_("push creates new branch '%s' " - "with multiple heads") % (branch)) - hint = _("merge or" - " see 'hg help push' for details about" - " pushing new heads") - elif len(newhs) > len(oldhs): - # remove bookmarked or existing remote heads from the new heads list - dhs = sorted(newhs - nowarnheads - oldhs) - if dhs: - if errormsg is None: - if branch not in ('default', None): - errormsg = _("push creates new remote head %s " - "on branch '%s'!") % (short(dhs[0]), branch) - elif repo[dhs[0]].bookmarks(): - errormsg = (_("push creates new remote head %s " - "with bookmark '%s'!") - % (short(dhs[0]), repo[dhs[0]].bookmarks()[0])) - else: - errormsg = _("push creates new remote head %s!" - ) % short(dhs[0]) - if unsyncedheads: - hint = _("pull and merge or" - " see 'hg help push' for details about" - " pushing new heads") - else: - hint = _("merge or" - " see 'hg help push' for details about" - " pushing new heads") - if branch is None: - repo.ui.note(_("new remote heads:\n")) - else: - repo.ui.note(_("new remote heads on branch '%s':\n") % branch) - for h in dhs: - repo.ui.note((" %s\n") % short(h)) - if errormsg: - raise error.Abort(errormsg, hint=hint) - -def _postprocessobsolete(pushop, futurecommon, candidate): - """post process the list of new heads with obsolescence information - - Exist as a subfunction to contains the complexity and allow extensions to - experiment with smarter logic. - Returns (newheads, discarded_heads) tuple - """ - # remove future heads which are actually obsoleted by another - # pushed element: - # - # known issue - # - # * We "silently" skip processing on all changeset unknown locally - # - # * if is public on the remote, it won't be affected by obsolete - # marker and a new is created - repo = pushop.repo - unfi = repo.unfiltered() - tonode = unfi.changelog.node - public = phases.public - getphase = unfi._phasecache.phase - ispublic = (lambda r: getphase(unfi, r) == public) - hasoutmarker = functools.partial(pushingmarkerfor, unfi.obsstore, futurecommon) - successorsmarkers = unfi.obsstore.successors - newhs = set() - discarded = set() - # I leave the print in the code because they are so handy at debugging - # and I keep getting back to this piece of code. - # - localcandidate = set() - unknownheads = set() - for h in candidate: - if h in unfi: - localcandidate.add(h) - else: - if successorsmarkers.get(h) is not None: - msg = ('checkheads: remote head unknown locally has' - ' local marker: %s\n') - repo.ui.debug(msg % nodemod.hex(h)) - unknownheads.add(h) - if len(localcandidate) == 1: - return unknownheads | set(candidate), set() - while localcandidate: - nh = localcandidate.pop() - # run this check early to skip the revset on the whole branch - if (nh in futurecommon - or unfi[nh].phase() <= public): - newhs.add(nh) - continue - # XXX there is a corner case if there is a merge in the branch. we - # might end up with -more- heads. However, these heads are not "added" - # by the push, but more by the "removal" on the remote so I think is a - # okay to ignore them, - branchrevs = unfi.revs('only(%n, (%ln+%ln))', - nh, localcandidate, newhs) - branchnodes = [tonode(r) for r in branchrevs] - - # The branch will still exist on the remote if - # * any part of it is public, - # * any part of it is considered part of the result by previous logic, - # * if we have no markers to push to obsolete it. - if (any(ispublic(r) for r in branchrevs) - or any(n in futurecommon for n in branchnodes) - or any(not hasoutmarker(n) for n in branchnodes)): - newhs.add(nh) - else: - discarded.add(nh) - newhs |= unknownheads - return newhs, discarded - -def pushingmarkerfor(obsstore, pushset, node): - """True if some markers are to be pushed for node - - We cannot just look in to the pushed obsmarkers from the pushop because - discover might have filtered relevant markers. In addition listing all - markers relevant to all changeset in the pushed set would be too expensive. - - The is probably some cache opportunity in this function. but it would - requires a two dimentions stack. - """ - successorsmarkers = obsstore.successors - stack = [node] - seen = set(stack) - while stack: - current = stack.pop() - if current in pushset: - return True - markers = successorsmarkers.get(current, ()) - # markers fields = ('prec', 'succs', 'flag', 'meta', 'date', 'parents') - for m in markers: - nexts = m[1] # successors - if not nexts: # this is a prune marker - nexts = m[5] # parents - for n in nexts: - if n not in seen: - seen.add(n) - stack.append(n) - return False diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/cmdrewrite.py --- a/hgext3rd/evolve/cmdrewrite.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/cmdrewrite.py Mon Apr 23 12:23:00 2018 +0200 @@ -11,6 +11,7 @@ from __future__ import absolute_import +import contextlib import random from mercurial import ( @@ -25,6 +26,7 @@ merge, node, obsolete, + obsutil, patch, phases, scmutil, @@ -33,6 +35,11 @@ from mercurial.i18n import _ +try: + from mercurial.utils.dateutil import datestr +except ImportError: # hg <= 4.5 + from mercurial.util import datestr + from . import ( compat, state, @@ -94,6 +101,7 @@ ('a', 'all', False, _("match all files")), ('e', 'edit', False, _('invoke editor on commit messages')), ('', 'extract', False, _('extract changes from the commit to the working copy')), + ('', 'patch', False, _('make changes to wdir parent by editing patch')), ('', 'close-branch', None, _('mark a branch as closed, hiding it from the branch list')), ('s', 'secret', None, _('use the secret phase for committing')), @@ -118,6 +126,8 @@ """ _checknotesize(ui, opts) opts = opts.copy() + if opts.get('patch'): + return amendpatch(ui, repo, *pats, **opts) if opts.get('extract'): return uncommit(ui, repo, *pats, **opts) else: @@ -140,6 +150,155 @@ finally: lockmod.release(lock, wlock) +def amendpatch(ui, repo, *pats, **opts): + """logic for --patch flag of `hg amend` command.""" + lock = wlock = tr = None + try: + wlock = repo.wlock() + lock = repo.lock() + tr = repo.transaction('amend') + cmdutil.bailifchanged(repo) + # first get the patch + old = repo['.'] + p1 = old.p1() + rewriteutil.precheck(repo, [old.rev()], 'amend') + bookmarkupdater = rewriteutil.bookmarksupdater(repo, old.node(), tr) + diffopts = patch.difffeatureopts(repo.ui, whitespace=True) + diffopts.nodates = True + diffopts.git = True + fp = stringio() + _writectxmetadata(repo, old, fp) + matcher = scmutil.match(old, pats, opts) + for chunk, label in patch.diffui(repo, p1.node(), old.node(), + match=matcher, + opts=diffopts): + fp.write(chunk) + newnode = _editandapply(ui, repo, pats, old, p1, fp, diffopts) + if newnode == old.node(): + raise error.Abort(_("nothing changed")) + metadata = {} + if opts.get('note'): + metadata['note'] = opts['note'] + obsolete.createmarkers(repo, [(old, (repo[newnode],))], + metadata=metadata, operation='amend') + phases.retractboundary(repo, tr, old.phase(), [newnode]) + hg.updaterepo(repo, newnode, True) + bookmarkupdater(newnode) + tr.close() + finally: + tr.release() + lockmod.release(lock, wlock) + +def _editandapply(ui, repo, pats, old, p1, fp, diffopts): + RETRYCHOICE = _('try to fix the patch (yn)?$$ &Yes $$ &No') + newnode = None + while newnode is None: + fp.seek(0) + previous_patch = fp.getvalue() + if 5 <= len(ui.edit.im_func.func_defaults): + newpatch = ui.edit(fp.getvalue(), old.user(), action="diff") + else: + newpatch = ui.edit(fp.getvalue(), old.user()) + + afp = stringio() + afp.write(newpatch) + if pats: + # write rest of the files in the patch + restmatcher = scmutil.match(old, [], opts={'exclude': pats}) + for chunk, label in patch.diffui(repo, p1.node(), old.node(), + match=restmatcher, + opts=diffopts): + afp.write(chunk) + + user_patch = afp.getvalue() + if user_patch == previous_patch: + raise error.Abort(_("patch unchanged")) + afp.seek(0) + # write the patch to repo and get the newnode + try: + newnode = _writepatch(ui, repo, old, afp) + except patch.PatchError as err: + ui.write_err(_("failed to apply edited patch: %s\n") % err) + defaultchoice = 0 # yes + if not ui.interactive: + defaultchoice = 1 # no + if ui.promptchoice(RETRYCHOICE, default=defaultchoice): + raise error.Abort(_("Could not apply amended path")) + else: + # consider a third choice where we restore the original patch + fp = stringio() + fp.write(user_patch) + return newnode + +def _writepatch(ui, repo, old, fp): + """utility function to use filestore and patchrepo to apply a patch to the + repository with metadata being extracted from the patch""" + metadata = patch.extract(ui, fp) + if util.safehasattr(metadata, 'get'): # < hg-4.6 + @contextlib.contextmanager + def patchcontext(): + yield metadata + patchcontext = patchcontext() + else: + patchcontext = metadata + pold = old.p1() + + with patchcontext as metadata: + # store the metadata from the patch to variables + parents = (metadata.get('p1'), metadata.get('p2')) + date = metadata.get('date') or old.date() + branch = metadata.get('branch') or old.branch() + user = metadata.get('user') or old.user() + # XXX: we must extract extras from the patchfile too + extra = old.extra() + message = metadata.get('message') or old.description() + store = patch.filestore() + fp.seek(0) + try: + files = set() + # beware: next line may raise a PatchError to be handled by the caller + # of this function + patch.patchrepo(ui, repo, pold, store, fp, 1, '', + files=files, eolmode=None) + + memctx = context.memctx(repo, parents, message, files=files, + filectxfn=store, + user=user, + date=date, + branch=branch, + extra=extra) + newcm = memctx.commit() + finally: + store.close() + return newcm + +def _writectxmetadata(repo, ctx, fp): + nodeval = scmutil.binnode(ctx) + parents = [p.node() for p in ctx.parents() if p] + branch = ctx.branch() + if parents: + prev = parents[0] + else: + prev = node.nullid + + fp.write("# HG changeset patch\n") + fp.write("# User %s\n" % ctx.user()) + fp.write("# Date %d %d\n" % ctx.date()) + fp.write("# %s\n" % datestr(ctx.date())) + if branch and branch != 'default': + fp.write("# Branch %s\n" % branch) + fp.write("# Node ID %s\n" % node.hex(nodeval)) + fp.write("# Parent %s\n" % node.hex(prev)) + if len(parents) > 1: + fp.write("# Parent %s\n" % node.hex(parents[1])) + + for headerid in cmdutil.extraexport: + header = cmdutil.extraexportmap[headerid](1, ctx) + if header is not None: + fp.write('# %s\n' % header) + fp.write(ctx.description().rstrip()) + fp.write("\n\n") + def _touchedbetween(repo, source, dest, match=None): touched = set() for files in repo.status(source, dest, match=match)[:3]: @@ -389,8 +548,8 @@ if opts.get('note'): metadata['note'] = opts['note'] - compat.createmarkers(repo, [(old, (repo[newid],))], metadata=metadata, - operation="uncommit") + obsolete.createmarkers(repo, [(old, (repo[newid],))], metadata=metadata, + operation="uncommit") phases.retractboundary(repo, tr, oldphase, [newid]) if opts.get('revert'): hg.updaterepo(repo, newid, True) @@ -428,7 +587,7 @@ fp.seek(0) newnode = _patchtocommit(ui, repo, old, fp) # creating obs marker temp -> () - compat.createmarkers(repo, [(repo[tempnode], ())], operation="uncommit") + obsolete.createmarkers(repo, [(repo[tempnode], ())], operation="uncommit") return newnode def _createtempcommit(ui, repo, old, match): @@ -612,9 +771,9 @@ root.p2().node()], commitopts=commitopts) phases.retractboundary(repo, tr, targetphase, [newid]) - compat.createmarkers(repo, [(ctx, (repo[newid],)) - for ctx in allctx], metadata=metadata, - operation="fold") + obsolete.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: @@ -745,9 +904,9 @@ metadata['note'] = opts['note'] phases.retractboundary(repo, tr, targetphase, [newid]) - compat.createmarkers(repo, [(ctx, (repo[newid],)) - for ctx in allctx], - metadata=metadata, operation="metaedit") + obsolete.createmarkers(repo, [(ctx, (repo[newid],)) + for ctx in allctx], + metadata=metadata, operation="metaedit") else: ui.status(_("nothing changed\n")) tr.close() @@ -923,7 +1082,7 @@ if movebookmark: bookmarksmod.deactivate(repo) bmchanges = [(bookactive, newnode.node())] - compat.bookmarkapplychanges(repo, tr, bmchanges) + repo._bookmarks.applychanges(repo, tr, bmchanges) commands.update(ui, repo, newnode.rev()) ui.status(_('working directory now at %s\n') % ui.label(str(newnode), 'evolve.node')) @@ -939,8 +1098,8 @@ metadata['note'] = opts['note'] # create markers - compat.createmarkers(repo, relations, metadata=metadata, - operation="prune") + obsolete.createmarkers(repo, relations, metadata=metadata, + operation="prune") # informs that changeset have been pruned ui.status(_('%i changesets pruned\n') % len(precs)) @@ -1053,8 +1212,8 @@ metadata = {} if opts.get('note'): metadata['note'] = opts['note'] - compat.createmarkers(repo, [(repo[rev], newcommits)], - metadata=metadata, operation="split") + obsolete.createmarkers(repo, [(repo[rev], newcommits)], + metadata=metadata, operation="split") tr.close() finally: # Restore the old branch @@ -1113,7 +1272,7 @@ if not (duplicate or allowdivergence): # The user hasn't yet decided what to do with the revived # cset, let's ask - sset = compat.successorssets(repo, ctx.node()) + sset = obsutil.successorssets(repo, ctx.node()) nodivergencerisk = (len(sset) == 0 or (len(sset) == 1 and len(sset[0]) == 1 and @@ -1145,8 +1304,8 @@ metadata = {} if opts.get('note'): metadata['note'] = opts['note'] - compat.createmarkers(repo, [(ctx, (repo[new],))], - metadata=metadata, operation="touch") + obsolete.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(): @@ -1200,7 +1359,7 @@ origctx.description().split("\n", 1)[0])) stats = merge.graft(repo, origctx, origctx.p1(), ['local', 'destination']) - if stats[3]: + if compat.hasconflict(stats): grabstate.addopts({'orignode': origctx.node(), 'oldpctx': pctx.node()}) grabstate.save() @@ -1237,7 +1396,7 @@ if grabstate: grabstate.delete() newctx = repo[newnode] if newnode else pctx - compat.createmarkers(repo, [(origctx, (newctx,))], operation="grab") + obsolete.createmarkers(repo, [(origctx, (newctx,))], operation="grab") if newnode is None: ui.warn(_("note: grab of %d:%s created no changes to commit\n") % diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/compat.py --- a/hgext3rd/evolve/compat.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/compat.py Mon Apr 23 12:23:00 2018 +0200 @@ -8,33 +8,17 @@ import inspect -import functools - from mercurial import ( - copies, context, - hg, mdiff, obsolete, + obsutil, revset, util, - wireproto, + vfs as vfsmod, ) from mercurial.hgweb import hgweb_mod -# hg < 4.2 compat -try: - from mercurial import vfs as vfsmod - vfsmod.vfs -except ImportError: - from mercurial import scmutil as vfsmod - -try: - from mercurial import obsutil - obsutil.closestpredecessors -except ImportError: - obsutil = None - # hg < 4.6 compat (c8e2d6ed1f9e) try: from mercurial import logcmdutil @@ -53,87 +37,6 @@ 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 - @eh.wrapfunction(obsolete.obsstore, 'relevantmarkers') - def relevantmarkers(orig, self, nodes): - """return a set of all obsolescence markers relevant to a set of nodes. - - "relevant" to a set of nodes mean: - - - marker that use this changeset as successor - - prune marker of direct children on this changeset - - recursive application of the two rules on precursors of these markers - - It is a set so you cannot rely on order. - - Backport of mercurial changeset 176d1a0ce385 for version < 4.3 - """ - - pendingnodes = set(nodes) - seenmarkers = set() - seennodes = set(pendingnodes) - precursorsmarkers = self.predecessors - succsmarkers = self.successors - children = self.children - while pendingnodes: - direct = set() - for current in pendingnodes: - direct.update(precursorsmarkers.get(current, ())) - pruned = [m for m in children.get(current, ()) if not m[1]] - direct.update(pruned) - pruned = [m for m in succsmarkers.get(current, ()) if not m[1]] - direct.update(pruned) - direct -= seenmarkers - pendingnodes = set([m[0] for m in direct]) - seenmarkers |= direct - pendingnodes -= seennodes - seennodes |= pendingnodes - return seenmarkers - -# successors set move from mercurial.obsolete to mercurial.obsutil in 4.3 -def successorssets(*args, **kwargs): - func = getattr(obsutil, 'successorssets', None) - if func is None: - func = obsolete.successorssets - return func(*args, **kwargs) - -# allprecursors set move from mercurial.obsolete to mercurial.obsutil in 4.3 -# allprecursors was renamed into allpredecessors in 4.4 -def allprecursors(*args, **kwargs): - func = getattr(obsutil, 'allpredecessors', None) - if func is None: - func = getattr(obsutil, 'allprecursors', None) - if func is None: - func = obsolete.allprecursors - return func(*args, **kwargs) - -# compatibility layer for mercurial < 4.3 -def bookmarkapplychanges(repo, tr, changes): - """Apply a list of changes to bookmarks - """ - bookmarks = repo._bookmarks - if util.safehasattr(bookmarks, 'applychanges'): - return bookmarks.applychanges(repo, tr, changes) - for name, node in changes: - if node is None: - del bookmarks[name] - else: - bookmarks[name] = node - bookmarks.recordchange(tr) - def isobsnotesupported(): # hack to know obsnote is supported. The patches for obsnote support was # pushed before the obsfateprinter patches, so this will serve as a good @@ -219,20 +122,6 @@ if not util.safehasattr(obsolete, '_computephasedivergentset'): obsolete._computephasedivergentset = obsolete.cachefor('phasedivergent')(obsolete._computebumpedset) -def startpager(ui, cmd): - """function to start a pager in case ui.pager() exists""" - if util.safehasattr(ui, 'pager'): - ui.pager(cmd) - -def duplicatecopies(repo, wctx, rev, fromrev, skiprev=None): - # cannot use anything else until 4.3 support is dropped. - assert wctx.rev() is None - if copies.duplicatecopies.__code__.co_argcount < 5: - # pre 4.4 duplicatecopies compat - copies.duplicatecopies(repo, rev, fromrev, skiprev=skiprev) - else: - copies.duplicatecopies(repo, wctx, rev, fromrev, skiprev=skiprev) - def memfilectx(repo, ctx, fctx, flags, copied, path): # XXX Would it be better at the module level? varnames = context.memfilectx.__init__.__code__.co_varnames @@ -282,14 +171,31 @@ parsedate = mercurial.util.parsedate def wireprotocommand(exthelper, name, args='', permission='pull'): + try: + # Since b4d85bc1 + from mercurial.wireprotov1server import wireprotocommand + return wireprotocommand(name, args, permission=permission) + except (ImportError, AttributeError): + from mercurial import wireproto + 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 + # <= 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 + +# mercurial <= 4.5 do not have the updateresult object +try: + from mercurial.merge import updateresult +except (ImportError, AttributeError): + updateresult = None + +def hasconflict(upres): + if updateresult is None: + return bool(upres[-1]) + return bool(upres.unresolvedcount) diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/evolvecmd.py --- a/hgext3rd/evolve/evolvecmd.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/evolvecmd.py Mon Apr 23 12:23:00 2018 +0200 @@ -23,7 +23,9 @@ merge, node, obsolete, + obsutil, phases, + repair, scmutil, util, ) @@ -45,7 +47,6 @@ 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, @@ -67,8 +68,8 @@ result = _solveunstable(ui, repo, ctx, evolvestate, dryrun, confirm, progresscb) elif 'phasedivergent' == category: - result = _solvebumped(ui, repo, ctx, evolvestate, - dryrun, confirm, progresscb) + result = _solvephasedivergence(ui, repo, ctx, evolvestate, + dryrun, confirm, progresscb) elif 'contentdivergent' == category: result = _solvedivergent(ui, repo, ctx, evolvestate, dryrun, confirm, progresscb) @@ -113,14 +114,14 @@ ui.warn(_("cannot solve instability of %s, skipping\n") % orig) return (False, '') obs = pctx - newer = compat.successorssets(repo, obs.node()) + newer = obsutil.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()) + newer = obsutil.successorssets(repo, obs.node()) if len(newer) > 1: msg = _("skipping %s: divergent rewriting. can't choose " "destination\n") % obs @@ -169,7 +170,8 @@ if progresscb: progresscb() try: - newid = relocate(repo, orig, target, pctx, keepbranch) + newid = relocate(repo, orig, target, evolvestate, pctx, + keepbranch, 'orphan') return (True, newid) except MergeFailure: ops = {'current': orig.node()} @@ -178,12 +180,12 @@ 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")) + " or use 'hg evolve --abort' to abort\n")) raise -def _solvebumped(ui, repo, bumped, evolvestate, dryrun=False, confirm=False, - progresscb=None): - """Stabilize a bumped changeset +def _solvephasedivergence(ui, repo, bumped, evolvestate, dryrun=False, + confirm=False, progresscb=None): + """Stabilize a phase divergent changeset returns a tuple (bool, newnode) where, bool: a boolean value indicating whether the instability was solved @@ -224,28 +226,51 @@ 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) + + # Checking for whether the phase-divergent changeset has common parents as + # it's precursors. Phase-divergent changeset and precursor having different + # parents is a result of when the changeset is rebased, grabbed, histedit or + # evolved or any other operation which can change parent. In such cases, + # when parents are not same, we first rebase the divergent changeset onto + # parent or precursor and then perform later steps 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()) + tmpid = relocate(repo, bumped, prec.p1(), evolvestate, + category='phasedivergent') if tmpid is not None: tmpctx = repo[tmpid] - compat.createmarkers(repo, [(bumped, (tmpctx,))], - operation='evolve') + obsolete.createmarkers(repo, [(bumped, (tmpctx,))], + operation='evolve') except MergeFailure: - repo.vfs.write('graftstate', bumped.hex() + '\n') + evolvestate['current'] = bumped.hex() + evolvestate['precursor'] = prec.hex() + evolvestate.save() repo.ui.write_err(_('evolution failed!\n')) - msg = _("fix conflict and run 'hg evolve --continue'\n") + msg = _("fix conflict then run 'hg evolve --continue' or " + "use `hg evolve --abort`\n") repo.ui.write_err(msg) raise + + return _resolvephasedivergent(ui, repo, prec, bumped, tmpctx) + +def _resolvephasedivergent(ui, repo, prec, bumped, tmpctx=None): + + tr = repo.currenttransaction() + assert tr is not None + bmupdate = _bookmarksupdater(repo, bumped.node(), tr) + newid = None + + # function to update the bookmark from the rebased changeset to new resolved + # changeset + rebasedbmupdate = None + if tmpctx and tmpctx.node() != bumped.node(): + rebasedbmupdate = _bookmarksupdater(repo, tmpctx.node(), tr) + bumped = tmpctx + # Create the new commit context repo.ui.status(_('computing new diff\n')) files = set() @@ -261,6 +286,7 @@ if precvalue != val: files.add(key) files.update(precmanifest) # add missing files + # commit it if files: # something to commit! def filectxfn(repo, ctx, path): @@ -284,13 +310,16 @@ newid = repo.commitctx(new) if newid is None: - compat.createmarkers(repo, [(tmpctx, ())], operation='evolve') + obsolete.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') + obsolete.createmarkers(repo, [(tmpctx, (repo[newid],))], + flag=obsolete.bumpedfix, operation='evolve') bmupdate(newid) + # if rebased happened, update bookmarks from there too + if rebasedbmupdate: + rebasedbmupdate(newid) repo.ui.status(_('committed as %s\n') % node.short(newid)) # reroute the working copy parent to the new changeset with repo.dirstate.parentchange(): @@ -383,10 +412,9 @@ ancestor=base.node(), mergeancestor=True) hg._showstats(repo, stats) - if stats[3]: + if compat.hasconflict(stats): 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: @@ -412,7 +440,7 @@ # no changes else: new = repo['.'] - compat.createmarkers(repo, [(other, (new,))], operation='evolve') + obsolete.createmarkers(repo, [(other, (new,))], operation='evolve') phases.retractboundary(repo, tr, other.phase(), [new.node()]) return (True, new.node()) finally: @@ -456,7 +484,8 @@ ordering.extend(sorted(dependencies)) return ordering -def relocate(repo, orig, dest, pctx=None, keepbranch=False): +def relocate(repo, orig, dest, evolvestate, pctx=None, keepbranch=False, + category=None): """rewrites the orig rev on dest rev returns the node of new commit which is formed @@ -481,16 +510,17 @@ sha1s = re.findall(sha1re, commitmsg) unfi = repo.unfiltered() for sha1 in sha1s: - ctx = None - try: - ctx = unfi[sha1] - except error.RepoLookupError: + if util.safehasattr(scmutil, 'resolvehexnodeidprefix'): # > hg-4.6 + fullnode = scmutil.resolvehexnodeidprefix(unfi, sha1) + else: + fullnode = unfi.changelog.index.partialmatch(sha1) + if fullnode is None: continue - + ctx = unfi[fullnode] if not ctx.obsolete(): continue - successors = compat.successorssets(repo, ctx.node(), cache) + successors = obsutil.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. @@ -505,7 +535,7 @@ assert tr is not None try: r = _evolvemerge(repo, orig, dest, pctx, keepbranch) - if r[-1]: # some conflict + if compat.hasconflict(r): # some conflict raise error.Abort(_('unresolved merge conflicts ' '(see hg help resolve)')) nodenew = _relocatecommit(repo, orig, commitmsg) @@ -514,14 +544,14 @@ 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()) + copies.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) + _finalizerelocate(repo, orig, dest, nodenew, tr, category, evolvestate) return nodenew def _relocatecommit(repo, orig, commitmsg): @@ -543,26 +573,31 @@ repo.ui.restoreconfig(backup) return nodenew -def _finalizerelocate(repo, orig, dest, nodenew, tr): +def _finalizerelocate(repo, orig, dest, nodenew, tr, category, evolvestate): 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') + obsolete.createmarkers(repo, [(repo[nodesrc], (repo[nodenew],))], + operation='evolve') for book in oldbookmarks: bmchanges.append((book, nodenew)) + evolvestate['bookmarkchanges'].append((book, nodesrc)) else: - compat.createmarkers(repo, [(repo[nodesrc], ())], operation='evolve') + if category == 'orphan': + repo.ui.status(_("evolution of %d:%s created no changes " + "to commit\n") % (orig.rev(), orig)) + obsolete.createmarkers(repo, [(repo[nodesrc], ())], operation='evolve') # Behave like rebase, move bookmarks to dest for book in oldbookmarks: + evolvestate['bookmarkchanges'].append((book, nodesrc)) 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) + repo._bookmarks.applychanges(repo, tr, bmchanges) def _evolvemerge(repo, orig, dest, pctx, keepbranch): """Used by the evolve function to merge dest on top of pctx. @@ -651,7 +686,7 @@ """ repo = ctx._repo.unfiltered() for base in repo.set('reverse(allprecursors(%d))', ctx.rev()): - newer = compat.successorssets(ctx._repo, base.node()) + newer = obsutil.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: @@ -699,7 +734,7 @@ tovisit = list(parents(rev)) while tovisit: r = tovisit.pop() - succsets = compat.successorssets(repo, tonode(r)) + succsets = obsutil.successorssets(repo, tonode(r)) if not succsets: tovisit.extend(parents(r)) else: @@ -719,6 +754,7 @@ unselectedcategories = [c for c in troublecategories if c != targetcat] msg = None hint = None + retoverride = None troubled = { "orphan": repo.revs("orphan()"), @@ -805,14 +841,20 @@ hint = hintmap['any+' + ('+'.join(othertroubles))] else: msg = _("no troubled changesets") + # Exit with a 0 (success) status in this case. + retoverride = 0 assert msg is not None ui.write_err("%s\n" % msg) if hint: ui.write_err("(%s)\n" % hint) - return 2 + ret = 2 else: - return 1 + ret = 1 + + if retoverride is not None: + return retoverride + return ret def _preparelistctxs(items, condition): return [item.hex() for item in items if condition(item)] @@ -916,6 +958,9 @@ if opts['stop']: raise error.Abort(_('cannot specify both "--stop" and' ' "--continue"')) + if opts['abort']: + raise error.Abort(_('cannot specify both "--abort" and' + ' "--continue"')) if opts['stop']: if opts['any']: @@ -924,6 +969,16 @@ raise error.Abort(_('cannot specify both "--all" and "--stop"')) if opts['rev']: raise error.Abort(_('cannot specify both "--rev" and "--stop"')) + if opts['abort']: + raise error.Abort(_('cannot specify both "--abort" and "--stop"')) + + if opts['abort']: + if opts['any']: + raise error.Abort(_('cannot specify both "--any" and "--abort"')) + if opts['all']: + raise error.Abort(_('cannot specify both "--all" and "--abort"')) + if opts['rev']: + raise error.Abort(_('cannot specify both "--rev" and "--abort"')) if opts['rev']: if opts['any']: @@ -965,11 +1020,14 @@ """Compute sets of commits divergent with a given one""" cache = {} base = {} - for n in compat.allprecursors(repo.obsstore, [ctx.node()]): + allpredecessors = getattr(obsutil, 'allpredecessors', None) + if allpredecessors is None: # <= Mercurial 4.3 + allpredecessors = obsutil.allprecursors + for n in allpredecessors(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) + nsuccsets = obsutil.successorssets(repo, n, cache) for nsuccset in nsuccsets: if ctx.node() in nsuccset: # we are only interested in *other* successor sets @@ -1007,7 +1065,9 @@ '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'), + ('', 'abort', False, _('abort the interrupted evolution')), + ('l', 'list', False, _('provide details on troubled changesets' + ' in the repo')), ] + mergetoolopts, _('[OPTIONS]...') ) @@ -1091,13 +1151,14 @@ confirmopt = opts['confirm'] revopt = opts['rev'] stopopt = opts['stop'] + abortopt = opts['abort'] troublecategories = ['phase_divergent', 'content_divergent', 'orphan'] specifiedcategories = [t.replace('_', '') for t in troublecategories if opts[t]] if opts['list']: - compat.startpager(ui, 'evolve') + ui.pager('evolve') listtroubles(ui, repo, specifiedcategories, **opts) return @@ -1166,6 +1227,11 @@ ui.status(_('working directory is now at %s\n') % pctx) evolvestate.delete() return + elif abortopt: + if not evolvestate: + raise error.Abort(_('no interrupted evolve to stop')) + evolvestate.load() + return abortevolve(ui, repo, evolvestate) else: cmdutil.bailifchanged(repo) @@ -1181,9 +1247,11 @@ 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} + stateopts = {'category': targetcat, 'replacements': {}, + 'revs': list(revs), 'confirm': confirmopt, + 'startnode': startnode.node(), 'skippedrevs': [], + 'command': 'evolve', 'orphanmerge': False, + 'bookmarkchanges': []} evolvestate.addopts(stateopts) for rev in revs: curctx = repo[rev] @@ -1211,78 +1279,86 @@ progresscb() _cleanup(ui, repo, startnode, showprogress) +def abortevolve(ui, repo, evolvestate): + """ logic for handling of `hg evolve --abort`""" + + with repo.wlock(), repo.lock(): + evolvedctx = [] + # boolean value to say whether we should strip or not + cleanup = True + startnode = evolvestate['startnode'] + for old, new in evolvestate['replacements'].iteritems(): + evolvedctx.append(repo[new[0]]) + evolvedrevs = [c.rev() for c in evolvedctx] + + # checking if phase changed of any of the evolved rev + immutable = [c for c in evolvedctx if not c.mutable()] + if immutable: + repo.ui.warn(_("cannot clean up public changesets: %s\n") + % ', '.join(str(c) for c in immutable), + hint=_("see 'hg help phases' for details")) + cleanup = False + + # checking no new changesets are created on evolved revs + descendants = set() + if evolvedrevs: + descendants = set(repo.changelog.descendants(evolvedrevs)) + if descendants - set(evolvedrevs): + repo.ui.warn(_("warning: new changesets detected on destination " + "branch\n")) + cleanup = False + + if cleanup: + if evolvedrevs: + strippoints = [c.node() + for c in repo.set('roots(%ld)', evolvedrevs)] + + # updating the working directory + hg.updaterepo(repo, startnode, True) + + # Strip from the first evolved revision + if evolvedrevs: + # no backup of evolved cset versions needed + repair.strip(repo.ui, repo, strippoints, False) + + tr = None + try: + tr = repo.transaction('evolve') + # restoring bookmarks at there original place + bmchanges = evolvestate['bookmarkchanges'] + if bmchanges: + repo._bookmarks.applychanges(repo, tr, bmchanges) + tr.close() + finally: + tr.release() + + evolvestate.delete() + ui.status(_('evolve aborted\n')) + ui.status(_('working directory is now at %s\n') + % node.hex(startnode)[:12]) + else: + raise error.Abort(_("unable to abort interrupted evolve, use 'hg " + "evolve --stop' to stop evolve")) + 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() + if (evolvestate['command'] == 'next' or + evolvestate['category'] == 'orphan'): + _completeorphan(ui, repo, evolvestate) + elif evolvestate['category'] == 'phasedivergent': + _completephasedivergent(ui, repo, evolvestate) 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') + repo.ui.status(_("continuing interrupted '%s' resolution is not yet" + " supported\n") % evolvestate['category']) + return # 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] @@ -1295,3 +1371,109 @@ else: evolvestate['skippedrevs'].append(curctx.node()) return + +def _completephasedivergent(ui, repo, evolvestate): + """function to complete the interrupted phase-divergence resolution. + + First completes the relocation of the commit and then process resolving + phase-divergence""" + + tr = None + try: + # need to start transaction for bookmark changes + tr = repo.transaction('evolve') + node = _completerelocation(ui, repo, evolvestate) + # resolving conflicts can lead to empty wdir and node can be None in + # those cases + ctx = repo[evolvestate['current']] + newctx = repo[node] if node is not None else repo['.'] + obsolete.createmarkers(repo, [(ctx, (newctx,))], operation='evolve') + + # now continuing the phase-divergence resolution part + prec = repo[evolvestate['precursor']] + _resolvephasedivergent(ui, repo, prec, ctx, newctx) + evolvestate['replacements'][ctx.node()] = node + tr.close() + finally: + tr.release() + +def _completeorphan(ui, repo, evolvestate): + """function to complete the interrupted orphan resolution""" + + node = _completerelocation(ui, repo, evolvestate) + # resolving conflicts can lead to empty wdir and node can be None in + # those cases + ctx = repo[evolvestate['current']] + if node is None: + repo.ui.status(_("evolution of %d:%s created no changes" + " to commit\n") % (ctx.rev(), ctx)) + newctx = repo[node] if node is not None else repo['.'] + obsolete.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 + 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 + +def _completerelocation(ui, repo, evolvestate): + """function to complete the interrupted relocation of a commit + return the new node formed + """ + + orig = repo[evolvestate['current']] + 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) + return node diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/genericcaches.py --- a/hgext3rd/evolve/genericcaches.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/genericcaches.py Mon Apr 23 12:23:00 2018 +0200 @@ -8,25 +8,12 @@ import abc import struct -import time -import os from mercurial import ( node, - pycompat, util, ) -# prior to hg-4.2 there are not util.timer -if util.safehasattr(util, 'timer'): - timer = util.timer -elif util.safehasattr(time, "perf_counter"): - timer = time.perf_counter -elif getattr(pycompat, 'osname', os.name) == 'nt': - timer = time.clock -else: - timer = time.time - class incrementalcachebase(object): """base class for incremental cache from append only source @@ -129,9 +116,9 @@ % self._cachename) self.clear(reset=True) - starttime = timer() + starttime = util.timer() self._updatefrom(repo, data) - duration = timer() - starttime + duration = util.timer() - starttime summary = self._updatesummary(data) repo.ui.log('cache', 'updated %s in %.4f seconds (%s)\n', self._cachename, duration, summary) diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/metadata.py --- a/hgext3rd/evolve/metadata.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/metadata.py Mon Apr 23 12:23:00 2018 +0200 @@ -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.3.0' -testedwith = '4.1.3 4.2.3 4.3.2 4.4.2 4.5.2' -minimumhgversion = '4.1' +__version__ = '8.0.0.dev' +testedwith = '4.3.2 4.4.2 4.5.2' +minimumhgversion = '4.3' buglink = 'https://bz.mercurial-scm.org/' diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/obscache.py --- a/hgext3rd/evolve/obscache.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/obscache.py Mon Apr 23 12:23:00 2018 +0200 @@ -9,23 +9,17 @@ import errno import hashlib -import os import struct -import time import weakref from mercurial import ( - error, localrepo, obsolete, phases, - pycompat, node, util, ) -from mercurial.i18n import _ - from . import ( compat, exthelper, @@ -33,17 +27,6 @@ eh = exthelper.exthelper() -# prior to hg-4.2 there are not util.timer -if util.safehasattr(util, 'timer'): - timer = util.timer -elif util.safehasattr(time, "perf_counter"): - timer = time.perf_counter -elif getattr(pycompat, 'osname', os.name) == 'nt': - timer = time.clock -else: - timer = time.time - - obsstorefilecache = localrepo.localrepository.obsstore # obsstore is a filecache so we have do to some spacial dancing @@ -98,30 +81,6 @@ return obsstore -if obsolete._fm0readmarkers.__code__.co_argcount > 2: - # hg-4.3+ has the "offset" parameter, and _fm?readmarkers also have an - # extra "stop" parameter - # Note that _readmarkers is wrapped by @util.nogc, so its co_argcount is - # misleadingly 0. So we check _fm0readmarkers instead, which increased its - # argument count in the same changeset (5d3ba439). - _readmarkers = obsolete._readmarkers -else: - # XXX copied as is from Mercurial 4.2 and added the "offset" parameters - @util.nogc - def _readmarkers(data, offset=None): - """Read and enumerate markers from raw data""" - off = 0 - diskversion = struct.unpack('>B', data[off:off + 1])[0] - if offset is None: - off += 1 - else: - assert 1 <= offset - off = offset - if diskversion not in obsolete.formats: - raise error.Abort(_('parsing obsolete marker: unknown version %r') - % diskversion) - return diskversion, obsolete.formats[diskversion][0](data, off) - def markersfrom(obsstore, byteoffset, firstmarker): if not firstmarker: return list(obsstore) @@ -130,7 +89,7 @@ return obsstore._all[firstmarker:] else: obsdata = obsstore.svfs.tryread('obsstore') - return _readmarkers(obsdata, byteoffset)[1] + return obsolete._readmarkers(obsdata, byteoffset)[1] class dualsourcecache(object): @@ -224,11 +183,11 @@ repo.ui.log('evoext-cache', 'strip detected, %s cache reset\n' % self._cachename) self.clear(reset=True) - starttime = timer() + starttime = util.timer() revs = list(revs) obsmarkers = list(obsmarkers) self._updatefrom(repo, revs, obsmarkers) - duration = timer() - starttime + duration = util.timer() - starttime repo.ui.log('evoext-cache', 'updated %s in %.4f seconds (%sr, %so)\n', self._cachename, duration, len(revs), len(obsmarkers)) @@ -470,11 +429,7 @@ """the set of obsolete revisions""" obs = set() repo = repo.unfiltered() - if util.safehasattr(repo._phasecache, 'getrevset'): - notpublic = repo._phasecache.getrevset(repo, (phases.draft, phases.secret)) - else: - # < hg-4.2 compat - notpublic = repo.revs("not public()") + notpublic = repo._phasecache.getrevset(repo, (phases.draft, phases.secret)) if notpublic: obscache = repo.obsstore.obscache # Since we warm the cache at the end of every transaction, the cache @@ -527,8 +482,8 @@ @localrepo.unfilteredmethod def updatecaches(self, tr=None, **kwargs): super(obscacherepo, self).updatecaches(tr, **kwargs) - self.obsstore.obscache.update(repo) - self.obsstore.obscache.save(repo) + self.obsstore.obscache.update(self) + self.obsstore.obscache.save(self) else: def transaction(self, *args, **kwargs): diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/obsdiscovery.py --- a/hgext3rd/evolve/obsdiscovery.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/obsdiscovery.py Mon Apr 23 12:23:00 2018 +0200 @@ -24,10 +24,8 @@ import hashlib import heapq -import os import sqlite3 import struct -import time import weakref from mercurial import ( @@ -38,11 +36,9 @@ localrepo, node, obsolete, - pycompat, scmutil, setdiscovery, util, - wireproto, ) from mercurial.i18n import _ @@ -55,15 +51,14 @@ stablerangecache, ) -# prior to hg-4.2 there are not util.timer -if util.safehasattr(util, 'timer'): - timer = util.timer -elif util.safehasattr(time, "perf_counter"): - timer = time.perf_counter -elif getattr(pycompat, 'osname', os.name) == 'nt': - timer = time.clock -else: - timer = time.time +try: + from mercurial import wireprototypes, wireprotov1server + from mercurial.wireprotov1peer import wirepeer + from mercurial.wireprototypes import encodelist, decodelist +except (ImportError, AttributeError): # <= hg-4.5 + from mercurial import wireproto as wireprototypes + wireprotov1server = wireprototypes + from mercurial.wireproto import wirepeer, encodelist, decodelist _pack = struct.pack _unpack = struct.unpack @@ -146,7 +141,7 @@ initialsamplesize=100, fullsamplesize=200): missing = set() - starttime = timer() + starttime = util.timer() heads = local.revs('heads(%ld)', probeset) local.stablerange.warmup(local) @@ -236,7 +231,7 @@ unit=_("queries")) ui.progress(_("comparing obsmarker with other"), None) local.obsstore.rangeobshashcache.save(local) - duration = timer() - starttime + duration = util.timer() - starttime logmsg = ('obsdiscovery, %d/%d mismatch' ' - %d obshashrange queries in %.4f seconds\n') logmsg %= (len(missing), len(probeset), querycount, duration) @@ -668,22 +663,22 @@ index = _unpack(_indexformat, data[-_indexsize:])[0] return (headnode, index) -@eh.addattr(wireproto.wirepeer, 'evoext_obshashrange_v1') +@eh.addattr(wirepeer, 'evoext_obshashrange_v1') def peer_obshashrange_v0(self, ranges): binranges = [_encrange(r) for r in ranges] - encranges = wireproto.encodelist(binranges) + encranges = encodelist(binranges) d = self._call("evoext_obshashrange_v1", ranges=encranges) try: - return wireproto.decodelist(d) + return decodelist(d) 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 = decodelist(ranges) ranges = [_decrange(r) for r in ranges] hashes = _obshashrange_v0(repo, ranges) - return wireproto.encodelist(hashes) + return encodelist(hashes) def _useobshashrange(repo): base = repo.ui.configbool('experimental', 'obshashrange', False) @@ -716,20 +711,20 @@ # Compat hg 4.6+ (2f7290555c96) if bytesresponse: - from mercurial import wireprototypes caps = wireprototypes.bytesresponse(caps) return caps @eh.extsetup def obshashrange_extsetup(ui): ### - extensions.wrapfunction(wireproto, 'capabilities', _obshashrange_capabilities) + extensions.wrapfunction(wireprotov1server, 'capabilities', + _obshashrange_capabilities) # wrap command content - oldcap, args = wireproto.commands['capabilities'] + oldcap, args = wireprotov1server.commands['capabilities'] def newcap(repo, proto): return _obshashrange_capabilities(oldcap, repo, proto) - wireproto.commands['capabilities'] = (newcap, args) + wireprotov1server.commands['capabilities'] = (newcap, args) ############################# ### Tree Hash computation ### @@ -827,30 +822,30 @@ def local_obshash1(peer, nodes): return _obshash(peer._repo, nodes, version=1) -@eh.addattr(wireproto.wirepeer, 'evoext_obshash') +@eh.addattr(wirepeer, 'evoext_obshash') def peer_obshash(self, nodes): - d = self._call("evoext_obshash", nodes=wireproto.encodelist(nodes)) + d = self._call("evoext_obshash", nodes=encodelist(nodes)) try: - return wireproto.decodelist(d) + return decodelist(d) except ValueError: self._abort(error.ResponseError(_("unexpected response:"), d)) -@eh.addattr(wireproto.wirepeer, 'evoext_obshash1') +@eh.addattr(wirepeer, 'evoext_obshash1') def peer_obshash1(self, nodes): - d = self._call("evoext_obshash1", nodes=wireproto.encodelist(nodes)) + d = self._call("evoext_obshash1", nodes=encodelist(nodes)) try: - return wireproto.decodelist(d) + return decodelist(d) 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))) + return encodelist(_obshash(repo, decodelist(nodes))) @compat.wireprotocommand(eh, 'evoext_obshash1', 'nodes') def srv_obshash1(repo, proto, nodes): - return wireproto.encodelist(_obshash(repo, wireproto.decodelist(nodes), - version=1)) + return encodelist(_obshash(repo, decodelist(nodes), + version=1)) def _obshash_capabilities(orig, repo, proto): """wrapper to advertise new capability""" @@ -872,19 +867,19 @@ # Compat hg 4.6+ (2f7290555c96) if bytesresponse: - from mercurial import wireprototypes caps = wireprototypes.bytesresponse(caps) return caps @eh.extsetup def obshash_extsetup(ui): - extensions.wrapfunction(wireproto, 'capabilities', _obshash_capabilities) + extensions.wrapfunction(wireprotov1server, 'capabilities', + _obshash_capabilities) # wrap command content - oldcap, args = wireproto.commands['capabilities'] + oldcap, args = wireprotov1server.commands['capabilities'] def newcap(repo, proto): return _obshash_capabilities(oldcap, repo, proto) - wireproto.commands['capabilities'] = (newcap, args) + wireprotov1server.commands['capabilities'] = (newcap, args) ########################################## ### trigger discovery during exchange ### diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/obsexchange.py --- a/hgext3rd/evolve/obsexchange.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/obsexchange.py Mon Apr 23 12:23:00 2018 +0200 @@ -24,15 +24,8 @@ obsolete, pushkey, util, - wireproto, ) -try: - from mercurial import wireprotoserver - wireprotoserver.handlewsgirequest -except (ImportError, AttributeError): - wireprotoserver = None - from mercurial.hgweb import common as hgwebcommon from . import ( @@ -60,8 +53,15 @@ @eh.uisetup def addgetbundleargs(self): - wireproto.gboptsmap['evo_obscommon'] = 'nodes' - wireproto.gboptsmap['evo_missing_nodes'] = 'nodes' + try: + from mercurial import wireprototypes + gboptsmap = wireprototypes.GETBUNDLE_ARGUMENTS + except (ImportError, AttributeError): + # <= hg 4.5 + from mercurial import wireproto + gboptsmap = wireproto.gboptsmap + gboptsmap['evo_obscommon'] = 'nodes' + gboptsmap['evo_missing_nodes'] = 'nodes' @eh.wrapfunction(exchange, '_pullbundle2extraprepare') def _addobscommontob2pull(orig, pullop, kwargs): @@ -132,7 +132,15 @@ @eh.extsetup def extsetup_obscommon(ui): - wireproto.gboptsmap['evo_obscommon'] = 'nodes' + try: + from mercurial import wireprototypes, wireprotov1server + gboptsmap = wireprototypes.GETBUNDLE_ARGUMENTS + except (ImportError, AttributeError): + # <= hg 4.5 + from mercurial import wireproto + gboptsmap = wireproto.gboptsmap + wireprotov1server = wireproto + gboptsmap['evo_obscommon'] = 'nodes' # wrap module content origfunc = exchange.getbundle2partsmapping['obsmarkers'] @@ -141,13 +149,14 @@ return _getbundleobsmarkerpart(origfunc, *args, **kwargs) exchange.getbundle2partsmapping['obsmarkers'] = newfunc - extensions.wrapfunction(wireproto, 'capabilities', _obscommon_capabilities) + extensions.wrapfunction(wireprotov1server, 'capabilities', + _obscommon_capabilities) # wrap command content - oldcap, args = wireproto.commands['capabilities'] + oldcap, args = wireprotov1server.commands['capabilities'] def newcap(repo, proto): return _obscommon_capabilities(oldcap, repo, proto) - wireproto.commands['capabilities'] = (newcap, args) + wireprotov1server.commands['capabilities'] = (newcap, args) def _pushobsmarkers(repo, data): tr = lock = None @@ -170,7 +179,12 @@ data = fp.getvalue() fp.close() _pushobsmarkers(repo, data) - return wireproto.pushres(0) + try: + from mercurial import wireprototypes + wireprototypes.pushres # force demandimport + except (ImportError, AttributeError): + from mercurial import wireproto as wireprototypes + return wireprototypes.pushres(0) def _getobsmarkersstream(repo, heads=None, common=None): """Get a binary stream for all markers relevant to `:: - ::` @@ -202,17 +216,23 @@ Serves relevant to changeset between heads and common. The stream is prefix by a -string- representation of an integer. This integer is the size of the stream.""" - opts = wireproto.options('', ['heads', 'common'], others) + try: + from mercurial import wireprototypes, wireprotov1server + wireprototypes.pushres # force demandimport + except (ImportError, AttributeError): + from mercurial import wireproto as wireprototypes + wireprotov1server = wireprototypes + opts = wireprotov1server.options('', ['heads', 'common'], others) for k, v in opts.iteritems(): if k in ('heads', 'common'): - opts[k] = wireproto.decodelist(v) + opts[k] = wireprototypes.decodelist(v) obsdata = _getobsmarkersstream(repo, **opts) finaldata = StringIO() obsdata = obsdata.getvalue() finaldata.write('%20i' % len(obsdata)) finaldata.write(obsdata) finaldata.seek(0) - return wireproto.streamres(reader=finaldata, v1compressible=True) + return wireprototypes.streamres(reader=finaldata, v1compressible=True) abortmsg = "won't exchange obsmarkers through pushkey" hint = "upgrade your client or server to use the bundle2 protocol" diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/obshistory.py --- a/hgext3rd/evolve/obshistory.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/obshistory.py Mon Apr 23 12:23:00 2018 +0200 @@ -83,7 +83,7 @@ Returns 0 on success. """ - compat.startpager(ui, 'obslog') + ui.pager('obslog') revs = list(revs) + opts['rev'] if not revs: revs = ['.'] @@ -172,15 +172,11 @@ succname = "changeset-description" d = compat.strdiff(basedesc, succdesc, basename, succname) - # mercurial 4.1 and before return the patch directly - if not isinstance(d, tuple): - patch = d - else: - uheaders, hunks = d + uheaders, hunks = d - # Copied from patch.diff - text = ''.join(sum((list(hlines) for hrange, hlines in hunks), [])) - patch = "\n".join(uheaders + [text]) + # Copied from patch.diff + text = ''.join(sum((list(hlines) for hrange, hlines in hunks), [])) + patch = "\n".join(uheaders + [text]) return patch @@ -623,9 +619,6 @@ def _getdifflines(iterdiff): """return a cleaned up lines""" try: - # XXX-COMPAT Mercurial 4.1 compat - if isinstance(iterdiff, list) and len(iterdiff) == 0: - return None lines = iterdiff.next() except StopIteration: return None @@ -727,7 +720,7 @@ or has diverged """ if successorssets is None: - successorssets = compat.successorssets(repo, revnode) + successorssets = obsutil.successorssets(repo, revnode) fate = _getobsfate(successorssets) diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/rewriteutil.py --- a/hgext3rd/evolve/rewriteutil.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/rewriteutil.py Mon Apr 23 12:23:00 2018 +0200 @@ -86,7 +86,7 @@ oldbookmarks = repo.nodebookmarks(oldid) bmchanges = [(b, newid) for b in oldbookmarks] if bmchanges: - compat.bookmarkapplychanges(repo, tr, bmchanges) + repo._bookmarks.applychanges(repo, tr, bmchanges) return updatebookmarks def disallowednewunstable(repo, revs): @@ -125,7 +125,7 @@ bmchanges = [] for bookmark in bookmarks: bmchanges.append((bookmark, None)) - compat.bookmarkapplychanges(repo, tr, bmchanges) + repo._bookmarks.applychanges(repo, tr, bmchanges) tr.close() for bookmark in sorted(bookmarks): repo.ui.write(_("bookmark '%s' deleted\n") % bookmark) diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/safeguard.py --- a/hgext3rd/evolve/safeguard.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/safeguard.py Mon Apr 23 12:23:00 2018 +0200 @@ -25,17 +25,17 @@ def checkpush(self, pushop): super(noautopublishrepo, self).checkpush(pushop) - behavior = repo.ui.config('experimental', 'auto-publish', 'default') + behavior = self.ui.config('experimental', 'auto-publish', 'default') remotephases = pushop.remote.listkeys('phases') publishing = remotephases.get('publishing', False) if behavior in ('warn', 'abort') and publishing: if pushop.revs is None: - published = repo.filtered('served').revs("not public()") + published = self.filtered('served').revs("not public()") else: - published = repo.revs("::%ln - public()", pushop.revs) + published = self.revs("::%ln - public()", pushop.revs) if published: if behavior == 'warn': - repo.ui.warn(_('%i changesets about to be published\n') % len(published)) + self.ui.warn(_('%i changesets about to be published\n') % len(published)) elif behavior == 'abort': msg = _('push would publish 1 changesets') hint = _("behavior controlled by 'experimental.auto-publish' config") diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/stablerange.py --- a/hgext3rd/evolve/stablerange.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/stablerange.py Mon Apr 23 12:23:00 2018 +0200 @@ -11,13 +11,11 @@ import functools import heapq import math -import os import time from mercurial import ( error, node as nodemod, - pycompat, scmutil, util, ) @@ -37,16 +35,6 @@ eh.merge(stablesort.eh) eh.merge(firstmergecache.eh) -# prior to hg-4.2 there are not util.timer -if util.safehasattr(util, 'timer'): - timer = util.timer -elif util.safehasattr(time, "perf_counter"): - timer = time.perf_counter -elif getattr(pycompat, 'osname', os.name) == 'nt': - timer = time.clock -else: - timer = time.time - ################################# ### Stable Range computation ### @@ -592,7 +580,7 @@ # # we use the revnumber as an approximation for depth ui = repo.ui - starttime = timer() + starttime = util.timer() if upto is None: upto = len(cl) - 1 @@ -608,7 +596,8 @@ rangeheap = [] for idx, r in enumerate(revs): if not idx % 1000: - ui.progress(_("filling depth cache"), idx, total=nbrevs) + ui.progress(_("filling depth cache"), idx, total=nbrevs, + unit=_("changesets")) # warm up depth self.depthrev(repo, r) rangeheap.append((-r, (r, 0))) @@ -633,7 +622,8 @@ progress_new = time.time() if (1 < progress_each) and (0.1 < progress_new - progress_last): progress_each /= 10 - ui.progress(_("filling stablerange cache"), seen, total=nbrevs) + ui.progress(_("filling stablerange cache"), seen, + total=nbrevs, unit=_("changesets")) progress_last = progress_new seen += 1 original.remove(value) # might have been added from other source @@ -647,7 +637,7 @@ self._tiprev = upto self._tipnode = cl.node(upto) - duration = timer() - starttime + duration = util.timer() - starttime repo.ui.log('evoext-cache', 'updated stablerange cache in %.4f seconds\n', duration) diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/stablerangecache.py --- a/hgext3rd/evolve/stablerangecache.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/stablerangecache.py Mon Apr 23 12:23:00 2018 +0200 @@ -66,7 +66,8 @@ progress_new = time.time() if (1 < progress_each) and (0.1 < progress_new - progress_last): progress_each /= 10 - ui.progress(_("filling stablerange cache"), seen, total=total) + ui.progress(_("filling stablerange cache"), seen, + total=total, unit=_("changesets")) progress_last = progress_new seen += 1 original.remove(rangeid) # might have been added from other source @@ -353,8 +354,8 @@ @localrepo.unfilteredpropertycache def stablerange(self): - cache = mergepointsql(repo) - cache.update(repo) + cache = mergepointsql(self) + cache.update(self) return cache @localrepo.unfilteredmethod diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/templatekw.py --- a/hgext3rd/evolve/templatekw.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/templatekw.py Mon Apr 23 12:23:00 2018 +0200 @@ -47,13 +47,8 @@ """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) + return templatekw.showlist('trouble', ctx.instabilities(), args, + plural='troubles') if util.safehasattr(templatekw, 'showpredecessors'): templatekw.keywords["precursors"] = templatekw.showpredecessors @@ -91,12 +86,7 @@ precursors = sorted(closestprecursors(repo, ctx.node())) precursors = [node.hex(p) for p in precursors] - # <= hg-4.1 requires an explicite gen. - # we can use None once the support is dropped - # - # They also requires an iterator instead of an iterable. - gen = iter(" ".join(p[:12] for p in precursors)) - return templatekw._hybrid(gen.__iter__(), precursors, lambda x: {'precursor': x}, + return templatekw._hybrid(None, precursors, lambda x: {'precursor': x}, lambda d: d['precursor'][:12]) def closestsuccessors(repo, nodeid): @@ -260,8 +250,10 @@ return "\n".join(lines) - -if util.safehasattr(templatekw, 'compatlist'): +if util.safehasattr(templatekw, 'obsfateverb'): + # Individuals fragments are available in core + pass +elif util.safehasattr(templatekw, 'compatlist'): @eh.templatekw('obsfatedata', requires=set(['ctx', 'templ'])) def showobsfatedata(context, mapping): ctx = context.resource(mapping, 'ctx') @@ -272,7 +264,7 @@ return templatekw.compatlist(context, mapping, "obsfatedata", []) args = mapping.copy() args.pop('ctx') - args['templ'] = context.resource(mapping, 'templ') + args['templ'] = context return _showobsfatedata(repo, ctx, values, **args) else: # pre hg-4.6 @@ -317,7 +309,12 @@ def fmt(d): nargs = args.copy() nargs.update(d[name]) - return args['templ'](name, **nargs) + templ = args['templ'] + # HG 4.6 + if hasattr(templ, "generate"): + return templ.generate(name, nargs) + else: + return args['templ'](name, **nargs) # Generate a good enough string representation using templater gen = [] diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/evolve/utility.py --- a/hgext3rd/evolve/utility.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/evolve/utility.py Mon Apr 23 12:23:00 2018 +0200 @@ -7,14 +7,14 @@ import collections +from mercurial import ( + obsutil, +) + 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): @@ -103,7 +103,10 @@ try: succ = _singlesuccessor(repo, p) except MultipleSuccessorsError as exc: - dependencies[r] = exc.successorssets + tset = set() + for node in exc.successorssets[0]: + tset.add(repo[node].rev()) + dependencies[r] = tset continue if succ in revs: dependencies[r].add(succ) @@ -119,14 +122,14 @@ return p.rev() obs = repo[p] ui = repo.ui - newer = compat.successorssets(repo, obs.node()) + newer = obsutil.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()) + newer = obsutil.successorssets(repo, obs.node()) if len(newer) > 1 or len(newer[0]) > 1: raise MultipleSuccessorsError(newer) diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/serverminitopic.py --- a/hgext3rd/serverminitopic.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/serverminitopic.py Mon Apr 23 12:23:00 2018 +0200 @@ -18,9 +18,14 @@ node, registrar, util, - wireproto, ) +try: + from mercurial import wireproto + wireproto.branchmap +except ImportError: # <= hg-4.5 + from mercurial import wireprotov1server as wireproto + if util.safehasattr(registrar, 'configitem'): configtable = {} @@ -43,17 +48,14 @@ ### make topic visible though "ctx.branch()" -class topicchangectx(context.changectx): - """a sunclass of changectx that add topic to the branch name""" - - def branch(self): - branch = super(topicchangectx, self).branch() - if hasminitopic(self._repo) and self.phase(): - topic = self._changeset.extra.get('topic') - if topic is not None: - topic = encoding.tolocal(topic) - branch = '%s:%s' % (branch, topic) - return branch +def topicbranch(orig, self): + branch = orig(self) + if hasminitopic(self._repo) and self.phase(): + topic = self._changeset.extra.get('topic') + if topic is not None: + topic = encoding.tolocal(topic) + branch = '%s:%s' % (branch, topic) + return branch ### avoid caching topic data in rev-branch-cache @@ -220,7 +222,7 @@ assert issubclass(current, new), (current, new, targetclass) def uisetup(ui): - wrapclass(context, 'changectx', topicchangectx) wrapclass(branchmap, 'branchcache', _topiccache) extensions.wrapfunction(branchmap, 'read', wrapread) extensions.wrapfunction(wireproto, '_capabilities', wireprotocaps) + extensions.wrapfunction(context.changectx, 'branch', topicbranch) diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/topic/__init__.py --- a/hgext3rd/topic/__init__.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/topic/__init__.py Mon Apr 23 12:23:00 2018 +0200 @@ -176,10 +176,10 @@ 'topic.active': 'green', } -__version__ = '0.8.0' +__version__ = '0.9.0.dev' -testedwith = '4.1.3 4.2.3 4.3.3 4.4.2 4.5.2' -minimumhgversion = '4.1' +testedwith = '4.3.3 4.4.2 4.5.2' +minimumhgversion = '4.3' buglink = 'https://bz.mercurial-scm.org/' if util.safehasattr(registrar, 'configitem'): @@ -594,7 +594,13 @@ # Have some restrictions on the topic name just like bookmark name scmutil.checknewlabel(repo, topic, 'topic') - compat.startpager(ui, 'topics') + rmatch = re.match(br'[-_.\w]+', topic) + if not rmatch or rmatch.group(0) != topic: + helptxt = _("topic names can only consist of alphanumeric, '-'" + " '_' and '.' characters") + raise error.Abort(_("invalid topic name: '%s'") % topic, hint=helptxt) + + ui.pager('topics') if list: if clear or rev: @@ -675,7 +681,7 @@ topic = repo.currenttopic if topic is None: branch = repo[None].branch() - compat.startpager(ui, 'stack') + ui.pager('stack') return stack.showstack(ui, repo, branch=branch, topic=topic, opts=opts) @command('debugcb|debugconvertbookmark', [ @@ -879,7 +885,7 @@ # create obsmarkers and move bookmarks # XXX we should be creating marker as we go instead of only at the end, # this makes the operations more modulars - compat.cleanupnodes(repo, successors, 'changetopics') + scmutil.cleanupnodes(repo, successors, 'changetopics') # move the working copy too wctx = repo[None] @@ -1166,7 +1172,7 @@ if node in thezeros or rev in thezeros: repo.ui.setconfig('_internal', 'keep-topic', 'yes', source='topic-extension') - return orig(ui, repo, node, rev, *args, **kwargs) + return orig(ui, repo, node=node, rev=rev, *args, **kwargs) finally: repo.ui.restoreconfig(backup) @@ -1178,17 +1184,22 @@ if ctx.topic(): extra[constants.extrakey] = ctx.topic() - def newmakeextrafn(orig, copiers): - return orig(copiers + [savetopic]) - def setrebaseconfig(orig, ui, repo, **opts): repo.ui.setconfig('experimental', 'topicrebase', 'yes', source='topic-extension') return orig(ui, repo, **opts) + def new_init(orig, *args, **kwargs): + runtime = orig(*args, **kwargs) + + if util.safehasattr(runtime, 'extrafns'): + runtime.extrafns.append(savetopic) + + return runtime + try: rebase = extensions.find("rebase") - extensions.wrapfunction(rebase, '_makeextrafn', newmakeextrafn) + extensions.wrapfunction(rebase.rebaseruntime, '__init__', new_init) # This exists to store in the config that rebase is running so that we can # update the topic according to rebase. This is a hack and should be removed # when we have better options. diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/topic/compat.py --- a/hgext3rd/topic/compat.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/topic/compat.py Mon Apr 23 12:23:00 2018 +0200 @@ -7,12 +7,8 @@ """ from __future__ import absolute_import -import functools - from mercurial import ( obsolete, - scmutil, - util, ) getmarkers = None @@ -28,33 +24,3 @@ getmarkers = obsolete.getmarkers 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: - ui.pager(cmd) - except AttributeError: - pass - -def cleanupnodes(repo, replacements, operation, moves=None): - # create obsmarkers and move bookmarks - # XXX we should be creating marker as we go instead of only at the end, - # this makes the operations more modulars - if util.safehasattr(scmutil, 'cleanupnodes'): - scmutil.cleanupnodes(repo, replacements, 'changetopics', - moves=moves) - else: - relations = [(repo[o], tuple(repo[n] for n in new)) - for (o, new) in replacements.iteritems()] - createmarkers(repo, relations, operation=operation) diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/topic/discovery.py --- a/hgext3rd/topic/discovery.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/topic/discovery.py Mon Apr 23 12:23:00 2018 +0200 @@ -11,37 +11,30 @@ exchange, extensions, util, - wireproto, ) -def _headssummary(orig, *args): - # In mercurial < 4.2, we receive repo, remote and outgoing as arguments - pushop = None - if len(args) == 3: - pushoparg = False - repo, remote, outgoing = args +try: + from mercurial import wireproto + wireproto.branchmap +except ImportError: # <= hg-4.5 + from mercurial import wireprotov1server as wireproto +def _headssummary(orig, pushop, *args, **kwargs): # In mercurial > 4.3, we receive the pushop as arguments - elif len(args) == 1: - pushoparg = True - pushop = args[0] - repo = pushop.repo.unfiltered() - remote = pushop.remote - else: - msg = 'topic-ext _headssummary() takes 1 or 3 arguments (%d given)' - raise TypeError(msg % len(args)) + repo = pushop.repo.unfiltered() + remote = pushop.remote publishing = ('phases' not in remote.listkeys('namespaces') or bool(remote.listkeys('phases').get('publishing', False))) if ((publishing or not remote.capable('topics')) and not getattr(pushop, 'publish', False)): - return orig(*args) + return orig(pushop, *args, **kwargs) publishedset = () remotebranchmap = None origremotebranchmap = remote.branchmap # < hg-4.4 do not have a --publish flag anyway - if pushoparg and util.safehasattr(pushop, 'remotephases'): + if util.safehasattr(pushop, 'remotephases'): publishednode = [c.node() for c in pushop.outdatedphases] publishedset = repo.revs('ancestors(%ln + %ln)', publishednode, @@ -109,11 +102,8 @@ remote.branchmap = remotebranchmap unxx = repo.filtered('unfiltered-topic') repo.unfiltered = lambda: unxx - if pushoparg: - pushop.repo = repo - summary = orig(pushop) - else: - summary = orig(repo, remote, outgoing) + pushop.repo = repo + summary = orig(pushop) for key, value in summary.iteritems(): if ':' in key: # This is a topic if value[0] is None and value[1]: diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/topic/evolvebits.py --- a/hgext3rd/topic/evolvebits.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/topic/evolvebits.py Mon Apr 23 12:23:00 2018 +0200 @@ -1,6 +1,8 @@ import collections -from . import compat +from mercurial import ( + obsutil, +) # Copied from evolve 081605c2e9b6 @@ -73,14 +75,14 @@ return p.rev() obs = repo[p] ui = repo.ui - newer = compat.successorssets(repo, obs.node()) + newer = obsutil.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()) + newer = obsutil.successorssets(repo, obs.node()) if 1 < len(newer): # divergence case # we should pick as arbitrary one diff -r 98941c28f3e2 -r a77fb9669e99 hgext3rd/topic/revset.py --- a/hgext3rd/topic/revset.py Wed Mar 21 16:18:31 2018 +0100 +++ b/hgext3rd/topic/revset.py Mon Apr 23 12:23:00 2018 +0200 @@ -15,7 +15,11 @@ try: mkmatcher = revset._stringmatcher except AttributeError: - mkmatcher = util.stringmatcher + try: + from mercurial.utils import stringutil + mkmatcher = stringutil.stringmatcher + except (ImportError, AttributeError): + mkmatcher = util.stringmatcher revsetpredicate = registrar.revsetpredicate() diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-amend-patch.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-amend-patch.t Mon Apr 23 12:23:00 2018 +0200 @@ -0,0 +1,1158 @@ +** Test for the `--patch` flag for `hg amend` command ** + +Setup + + $ cat >> $HGRCPATH << EOF + > [alias] + > glog = log -GT "{rev}:{node|short} {desc}\n ({bookmarks}) {phase}" + > [diff] + > git = 1 + > [extensions] + > EOF + $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH + +Reposetup + + $ hg init repo + $ cd repo + $ echo foo > a + $ hg ci -Aqm "added a" + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID f7ad4196431346de3c33c52e75374fba45e04313 + # Parent 0000000000000000000000000000000000000000 + added a + + diff --git a/a b/a + new file mode 100644 + --- /dev/null + +++ b/a + @@ -0,0 +1,1 @@ + +foo + +Testing of just changing the diff, not the patch metadata +========================================================== + +Testing the normal case +----------------------- + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID f7ad4196431346de3c33c52e75374fba45e04313 + > # Parent 0000000000000000000000000000000000000000 + > added a + > diff --git a/a b/a + > new file mode 100644 + > --- /dev/null + > +++ b/a + > @@ -0,0 +1,1 @@ + > +Gello + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + +Making sure the amended commit is correct + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID af624b221c0c0bec5d74e2650180dd3eddcb7c42 + # Parent 0000000000000000000000000000000000000000 + added a + + diff --git a/a b/a + new file mode 100644 + --- /dev/null + +++ b/a + @@ -0,0 +1,1 @@ + +Gello + + $ hg glog + @ 1:af624b221c0c added a + () draft + +Obsolsence history is fine + + $ hg obslog -p -r . + @ af624b221c0c (1) added a + | + x f7ad41964313 (0) added a + rewritten(content) as af624b221c0c using amend by test (Thu Jan 01 00:00:00 1970 +0000) + diff --git a/a b/a + --- a/a + +++ b/a + @@ -1,1 +1,1 @@ + -foo + +Gello + + +Diff and status are good too + $ hg diff + $ hg status + ? editor.sh + $ cat a + Gello + +Dirstate parents should be correctly set + $ hg parents + changeset: 1:af624b221c0c + tag: tip + parent: -1:000000000000 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: added a + +Trying to amend with a wrong patch +---------------------------------- + +Having context which was is not present + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID c6ba250efbf73e671f2ca24b79db2c178ccbfff9 + > # Parent 0000000000000000000000000000000000000000 + > added a + > diff --git a/a b/a + > new file mode 100644 + > --- /dev/null + > +++ b/a + > @@ -0,0 +1,1 @@ + > I was not there before! + > +Gello + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + failed to apply edited patch: bad hunk #1 @@ -0,0 +1,1 @@ + (1 0 1 1) + try to fix the patch (yn)? y + abort: patch unchanged + [255] + +Having deletions which dont exists + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID af624b221c0c0bec5d74e2650180dd3eddcb7c42 + > # Parent 0000000000000000000000000000000000000000 + > added a + > diff --git a/a b/a + > new file mode 100644 + > --- /dev/null + > +++ b/a + > @@ -0,0 +1,1 @@ + > -I was not deleted before! + > +Gello + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + failed to apply edited patch: bad hunk #1 @@ -0,0 +1,1 @@ + (1 0 1 1) + try to fix the patch (yn)? y + abort: patch unchanged + [255] + +Changing the file mode using amend --patch +------------------------------------------ + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID af624b221c0c0bec5d74e2650180dd3eddcb7c42 + > # Parent 0000000000000000000000000000000000000000 + > added a + > diff --git a/a b/a + > new file mode 100755 + > --- /dev/null + > +++ b/a + > @@ -0,0 +1,1 @@ + > +Gello + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp --git + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 3a99e4b7ac73da799e20ae56914e3dd5b1a22d4d + # Parent 0000000000000000000000000000000000000000 + added a + + diff --git a/a b/a + new file mode 100755 + --- /dev/null + +++ b/a + @@ -0,0 +1,1 @@ + +Gello + +Changing the file using amend --patch +------------------------------------- + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID 3a99e4b7ac73da799e20ae56914e3dd5b1a22d4d + > # Parent 0000000000000000000000000000000000000000 + > added a + > diff --git a/changedfile b/changedfile + > new file mode 100755 + > --- /dev/null + > +++ b/changedfile + > @@ -0,0 +1,1 @@ + > +Gello + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID fc57c20be380f2878f4db139dad66d6cfb42ec62 + # Parent 0000000000000000000000000000000000000000 + added a + + diff --git a/changedfile b/changedfile + new file mode 100755 + --- /dev/null + +++ b/changedfile + @@ -0,0 +1,1 @@ + +Gello + + $ hg status + ? editor.sh + + $ ls + changedfile + editor.sh + +Handling both deletions and additions +------------------------------------- + + $ echo foobar > changedfile + $ hg ci -m "foobar to changedfile" + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 7969f70ffb81c3a6eee2d4f2f7032b694ce05349 + # Parent fc57c20be380f2878f4db139dad66d6cfb42ec62 + foobar to changedfile + + diff --git a/changedfile b/changedfile + --- a/changedfile + +++ b/changedfile + @@ -1,1 +1,1 @@ + -Gello + +foobar + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID 7969f70ffb81c3a6eee2d4f2f7032b694ce05349 + > # Parent fc57c20be380f2878f4db139dad66d6cfb42ec62 + > foobar to changedfile + > diff --git a/changedfile b/changedfile + > --- a/changedfile + > +++ b/changedfile + > @@ -1,1 +1,1 @@ + > -Gello + > +foobar + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + abort: nothing changed + [255] + +Cannot change lines which are deleted + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID 7969f70ffb81c3a6eee2d4f2f7032b694ce05349 + > # Parent fc57c20be380f2878f4db139dad66d6cfb42ec62 + > foobar to changedfile + > diff --git a/changedfile b/changedfile + > --- a/changedfile + > +++ b/changedfile + > @@ -1,1 +1,1 @@ + > -Hello + > +foobar + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + patching file changedfile + Hunk #1 FAILED at 0 + failed to apply edited patch: patch failed to apply + try to fix the patch (yn)? y + abort: patch unchanged + [255] + +Add more addition to the patch + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID 7969f70ffb81c3a6eee2d4f2f7032b694ce05349 + > # Parent fc57c20be380f2878f4db139dad66d6cfb42ec62 + > foobar to changedfile + > diff --git a/changedfile b/changedfile + > --- a/changedfile + > +++ b/changedfile + > @@ -1,1 +1,2 @@ + > -Gello + > +foobar + > +babar + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 5d54400acb70b88f07128a1df497ed794b0b177b + # Parent fc57c20be380f2878f4db139dad66d6cfb42ec62 + foobar to changedfile + + diff --git a/changedfile b/changedfile + --- a/changedfile + +++ b/changedfile + @@ -1,1 +1,2 @@ + -Gello + +foobar + +babar + + $ cat changedfile + foobar + babar + +Introduce files which were not there +------------------------------------ + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID 5d54400acb70b88f07128a1df497ed794b0b177b + > # Parent fc57c20be380f2878f4db139dad66d6cfb42ec62 + > foobar to changedfile + > diff --git a/changedfile b/changedfile + > --- a/changedfile + > +++ b/changedfile + > @@ -1,1 +1,2 @@ + > -Gello + > +foobar + > +babar + > diff --git a/a b/a + > new file mode 100755 + > --- /dev/null + > +++ b/a + > @@ -0,0 +1,1 @@ + > +Gello + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID c3e29c061982c94418ce141d521434d6da76cd46 + # Parent fc57c20be380f2878f4db139dad66d6cfb42ec62 + foobar to changedfile + + diff --git a/a b/a + new file mode 100755 + --- /dev/null + +++ b/a + @@ -0,0 +1,1 @@ + +Gello + diff --git a/changedfile b/changedfile + --- a/changedfile + +++ b/changedfile + @@ -1,1 +1,2 @@ + -Gello + +foobar + +babar + +Delete files which were not deleted in the first place +------------------------------------------------------ + + $ echo Hello >> a + $ hg ci -m "hello to a" + $ hg glog + @ 7:3d62c45a1699 hello to a + | () draft + o 6:c3e29c061982 foobar to changedfile + | () draft + o 3:fc57c20be380 added a + () draft + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID 3d62c45a1699b11c7ecae573f013601712f2cc5f + > # Parent c3e29c061982c94418ce141d521434d6da76cd46 + > hello to a + > diff --git a/a b/a + > --- a/a + > +++ b/a + > @@ -1,1 +1,2 @@ + > Gello + > +Hello + > diff --git a/changedfile b/changedfile + > deleted file mode 100755 + > --- a/changedfile + > +++ /dev/null + > @@ -1,2 +0,0 @@ + > -foobar + > -babar + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID c9875799c53fb862c0dbaf01500459c9397373a4 + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + diff --git a/a b/a + --- a/a + +++ b/a + @@ -1,1 +1,2 @@ + Gello + +Hello + diff --git a/changedfile b/changedfile + deleted file mode 100755 + --- a/changedfile + +++ /dev/null + @@ -1,2 +0,0 @@ + -foobar + -babar + + $ hg status + ? editor.sh + + $ cat changedfile + cat: changedfile: No such file or directory + [1] + +Testing sercret phase preservation during `hg amend --patch` +------------------------------------------------------------ + + $ hg phase -r . --secret --force + + $ hg phase -r . + 8: secret + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID c9875799c53fb862c0dbaf01500459c9397373a4 + > # Parent c3e29c061982c94418ce141d521434d6da76cd46 + > hello to a + > diff --git a/a b/a + > --- a/a + > +++ b/a + > @@ -1,1 +1,3 @@ + > Gello + > +Hello + > +mello + > diff --git a/changedfile b/changedfile + > deleted file mode 100755 + > --- a/changedfile + > +++ /dev/null + > @@ -1,2 +0,0 @@ + > -foobar + > -babar + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 4414485658e719a1f3d5e58bc8b2412385aa1592 + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + diff --git a/a b/a + --- a/a + +++ b/a + @@ -1,1 +1,3 @@ + Gello + +Hello + +mello + diff --git a/changedfile b/changedfile + deleted file mode 100755 + --- a/changedfile + +++ /dev/null + @@ -1,2 +0,0 @@ + -foobar + -babar + + $ hg phase -r . + 9: secret + +Testing bookmark movement on amend --patch +------------------------------------------ + + $ hg bookmark foo + $ hg glog + @ 9:4414485658e7 hello to a + | (foo) secret + o 6:c3e29c061982 foobar to changedfile + | () draft + o 3:fc57c20be380 added a + () draft + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID 4414485658e719a1f3d5e58bc8b2412385aa1592 + > # Parent c3e29c061982c94418ce141d521434d6da76cd46 + > hello to a + > diff --git a/a b/a + > --- a/a + > +++ b/a + > @@ -1,1 +1,3 @@ + > Gello + > +Hello + > +bello + > diff --git a/changedfile b/changedfile + > deleted file mode 100755 + > --- a/changedfile + > +++ /dev/null + > @@ -1,2 +0,0 @@ + > -foobar + > -babar + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 36454bda1fdb8e2e4fe07bb084eef378e29cba74 + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + diff --git a/a b/a + --- a/a + +++ b/a + @@ -1,1 +1,3 @@ + Gello + +Hello + +bello + diff --git a/changedfile b/changedfile + deleted file mode 100755 + --- a/changedfile + +++ /dev/null + @@ -1,2 +0,0 @@ + -foobar + -babar + + $ hg glog + @ 10:36454bda1fdb hello to a + | (foo) secret + o 6:c3e29c061982 foobar to changedfile + | () draft + o 3:fc57c20be380 added a + () draft + +Trying to amend --patch a public changeset +------------------------------------------ + + $ hg phase -r . --public + $ hg glog + @ 10:36454bda1fdb hello to a + | (foo) public + o 6:c3e29c061982 foobar to changedfile + | () public + o 3:fc57c20be380 added a + () public + + $ HGEDITOR=cat hg amend --patch + abort: cannot amend public changesets: 36454bda1fdb + (see 'hg help phases' for details) + [255] + + $ hg phase -r . --draft --force + +Trying on a dirty working directory +------------------------------------- + + $ echo bar > bar + $ hg add bar + $ HGEDITOR=cat hg amend --patch + abort: uncommitted changes + [255] + + $ hg revert --all + forgetting bar + +Trying to pass filenames, only mentioned file names should be popped up in +editor and rest should stay in the commit as they were +-------------------------------------------------------------------------- + +Checking the we pop-up with the files which were mentioned + + $ HGEDITOR=cat hg amend --patch changedfile + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 36454bda1fdb8e2e4fe07bb084eef378e29cba74 + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + diff --git a/changedfile b/changedfile + deleted file mode 100755 + --- a/changedfile + +++ /dev/null + @@ -1,2 +0,0 @@ + -foobar + -babar + abort: nothing changed + [255] + + $ HGEDITOR=cat hg amend --patch a + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 36454bda1fdb8e2e4fe07bb084eef378e29cba74 + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + diff --git a/a b/a + --- a/a + +++ b/a + @@ -1,1 +1,3 @@ + Gello + +Hello + +bello + abort: nothing changed + [255] + + $ HGEDITOR=cat hg amend --patch changedfile a + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 36454bda1fdb8e2e4fe07bb084eef378e29cba74 + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + diff --git a/a b/a + --- a/a + +++ b/a + @@ -1,1 +1,3 @@ + Gello + +Hello + +bello + diff --git a/changedfile b/changedfile + deleted file mode 100755 + --- a/changedfile + +++ /dev/null + @@ -1,2 +0,0 @@ + -foobar + -babar + abort: patch unchanged + [255] + + $ HGEDITOR=cat hg amend --patch doesnotexists + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 36454bda1fdb8e2e4fe07bb084eef378e29cba74 + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + abort: nothing changed + [255] + +Changing only one file + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID 36454bda1fdb8e2e4fe07bb084eef378e29cba74 + > # Parent c3e29c061982c94418ce141d521434d6da76cd46 + > hello to a + > diff --git a/a b/a + > --- a/a + > +++ b/a + > @@ -1,1 +1,3 @@ + > Gello + > +Hello + > +betto + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch a + +file 'a' should be amended, rest of them should remain unchanged + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID ea175dcc4ee38c106db157975e006b4092444c65 + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + diff --git a/a b/a + --- a/a + +++ b/a + @@ -1,1 +1,3 @@ + Gello + +Hello + +betto + diff --git a/changedfile b/changedfile + deleted file mode 100755 + --- a/changedfile + +++ /dev/null + @@ -1,2 +0,0 @@ + -foobar + -babar + + $ hg status + ? bar + ? editor.sh + + $ hg diff + +Testing again with file 'changedfile' + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID ea175dcc4ee38c106db157975e006b4092444c65 + > # Parent c3e29c061982c94418ce141d521434d6da76cd46 + > hello to a + > diff --git a/changedfile b/changedfile + > --- a/changedfile + > +++ b/changedfile + > @@ -1,2 +1,1 @@ + > foobar + > -babar + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch changedfile + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 0e64d76c3519308c398a28192cb095d48b29aede + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + diff --git a/a b/a + --- a/a + +++ b/a + @@ -1,1 +1,3 @@ + Gello + +Hello + +betto + diff --git a/changedfile b/changedfile + --- a/changedfile + +++ b/changedfile + @@ -1,2 +1,1 @@ + foobar + -babar + + $ hg diff + $ hg status + ? bar + ? editor.sh + +Dropping a file from commit by removing related hunks +------------------------------------------------------ + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User test + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID 0e64d76c3519308c398a28192cb095d48b29aede + > # Parent c3e29c061982c94418ce141d521434d6da76cd46 + > hello to a + > diff --git a/a b/a + > --- a/a + > +++ b/a + > @@ -1,1 +1,3 @@ + > Gello + > +Kello + > +betto + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 944e9f65fa55fdb2de98577c9d8ab30de0927d8e + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + diff --git a/a b/a + --- a/a + +++ b/a + @@ -1,1 +1,3 @@ + Gello + +Kello + +betto + +The part which was dropped from the patch will not be there in working directory +too + $ hg diff + + $ hg status + ? bar + ? editor.sh + +Changing metadata of a patch by editing patch content +====================================================== + +Changing user +------------- + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User RandomUser + > # Date 0 0 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID 944e9f65fa55fdb2de98577c9d8ab30de0927d8e + > # Parent c3e29c061982c94418ce141d521434d6da76cd46 + > hello to a + > diff --git a/a b/a + > --- a/a + > +++ b/a + > @@ -1,1 +1,3 @@ + > Gello + > +Kello + > +betto + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp + # HG changeset patch + # User RandomUser + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 5ded18a8c333a55da4b0e051162457cfe5d85558 + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + diff --git a/a b/a + --- a/a + +++ b/a + @@ -1,1 +1,3 @@ + Gello + +Kello + +betto + +Changing Date +------------- + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User RandomUser + > # Date 123456 1200 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Node ID 944e9f65fa55fdb2de98577c9d8ab30de0927d8e + > # Parent c3e29c061982c94418ce141d521434d6da76cd46 + > hello to a + > diff --git a/a b/a + > --- a/a + > +++ b/a + > @@ -1,1 +1,3 @@ + > Gello + > +Kello + > +betto + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp + # HG changeset patch + # User RandomUser + # Date 123456 1200 + # Fri Jan 02 09:57:36 1970 -0020 + # Node ID e2312ddcd8756665075a60bd05431ddca3c45050 + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + diff --git a/a b/a + --- a/a + +++ b/a + @@ -1,1 +1,3 @@ + Gello + +Kello + +betto + +Changing branch +--------------- + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User RandomUser + > # Date 123456 1200 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Branch stable + > # Node ID 944e9f65fa55fdb2de98577c9d8ab30de0927d8e + > # Parent c3e29c061982c94418ce141d521434d6da76cd46 + > hello to a + > diff --git a/a b/a + > --- a/a + > +++ b/a + > @@ -1,1 +1,3 @@ + > Gello + > +Kello + > +betto + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp + # HG changeset patch + # User RandomUser + # Date 123456 1200 + # Fri Jan 02 09:57:36 1970 -0020 + # Branch stable + # Node ID ddc61a4058687b2dd4a316f4b5fe7d52a35b702a + # Parent c3e29c061982c94418ce141d521434d6da76cd46 + hello to a + + diff --git a/a b/a + --- a/a + +++ b/a + @@ -1,1 +1,3 @@ + Gello + +Kello + +betto + +Changing parent (this should be fun) +------------------------------------ + + $ hg glog + @ 16:ddc61a405868 hello to a + | (foo) draft + o 6:c3e29c061982 foobar to changedfile + | () public + o 3:fc57c20be380 added a + () public + + $ hg log -r .^^ -T '{node}' + fc57c20be380f2878f4db139dad66d6cfb42ec62 (no-eol) + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User RandomUser + > # Date 123456 1200 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Branch stable + > # Node ID 944e9f65fa55fdb2de98577c9d8ab30de0927d8e + > # Parent fc57c20be380f2878f4db139dad66d6cfb42ec62 + > hello to a + > diff --git a/a b/a + > --- a/a + > +++ b/a + > @@ -1,1 +1,3 @@ + > Gello + > +Kello + > +betto + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp + # HG changeset patch + # User RandomUser + # Date 123456 1200 + # Fri Jan 02 09:57:36 1970 -0020 + # Branch stable + # Node ID b763f7cb2302f2efa1275e2a9202655872c9567f + # Parent fc57c20be380f2878f4db139dad66d6cfb42ec62 + hello to a + + diff --git a/a b/a + new file mode 100755 + --- /dev/null + +++ b/a + @@ -0,0 +1,3 @@ + +Gello + +Kello + +betto + + $ hg glog + @ 17:b763f7cb2302 hello to a + | (foo) draft + | o 6:c3e29c061982 foobar to changedfile + |/ () public + o 3:fc57c20be380 added a + () public + +Changing the commit desciption +------------------------------- + + $ cat > editor.sh < #!/bin/sh + > cat > \$1 < # HG changeset patch + > # User RandomUser + > # Date 123456 1200 + > # Thu Jan 01 00:00:00 1970 +0000 + > # Branch stable + > # Node ID 944e9f65fa55fdb2de98577c9d8ab30de0927d8e + > # Parent fc57c20be380f2878f4db139dad66d6cfb42ec62 + > I am a message which is testing change of message + > diff --git a/a b/a + > new file mode 100755 + > --- /dev/null + > +++ b/a + > @@ -0,0 +1,3 @@ + > +Gello + > +Kello + > +betto + > ENDOF + > EOF + + $ HGEDITOR="sh ./editor.sh" hg amend --patch + + $ hg exp + # HG changeset patch + # User RandomUser + # Date 123456 1200 + # Fri Jan 02 09:57:36 1970 -0020 + # Branch stable + # Node ID f14ecd7121e63915ac93edbad7f60f605e62dd52 + # Parent fc57c20be380f2878f4db139dad66d6cfb42ec62 + I am a message which is testing change of message + + diff --git a/a b/a + new file mode 100755 + --- /dev/null + +++ b/a + @@ -0,0 +1,3 @@ + +Gello + +Kello + +betto + +Changing the Node ID of the patch +--------------------------------- + +Nothing happens in that case we dont care about the node ID. Look the above 3-4 +tests to realize I was testing that too. diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-amend.t --- a/tests/test-amend.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-amend.t Mon Apr 23 12:23:00 2018 +0200 @@ -152,6 +152,7 @@ -a --all match all files -e --edit invoke editor on commit messages --extract extract changes from the commit to the working copy + --patch make changes to wdir parent by editing patch --close-branch mark a branch as closed, hiding it from the branch list -s --secret use the secret phase for committing diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-discovery-obshashrange.t diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-evolve-abort.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-abort.t Mon Apr 23 12:23:00 2018 +0200 @@ -0,0 +1,494 @@ +Tests for the --abort flag for `hg evolve` command +================================================== + +Setup +===== + + $ cat >> $HGRCPATH < [phases] + > publish = False + > [alias] + > glog = log -GT "{rev}:{node|short} {desc}\n ({bookmarks}) {phase}" + > [extensions] + > EOF + $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH + + $ hg init abortrepo + $ cd abortrepo + $ 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 --abort when no evolve is interrupted +============================================= + + $ hg evolve --abort + abort: no interrupted evolve to stop + [255] + +Testing with wrong combination of flags +======================================= + + $ hg evolve --abort --continue + abort: cannot specify both "--abort" and "--continue" + [255] + + $ hg evolve --abort --stop + abort: cannot specify both "--abort" and "--stop" + [255] + + $ hg evolve --abort --rev 3 + abort: cannot specify both "--rev" and "--abort" + [255] + + $ hg evolve --abort --any + abort: cannot specify both "--any" and "--abort" + [255] + + $ hg evolve --abort --all + abort: cannot specify both "--all" and "--abort" + [255] + +Normal testingw when no rev was evolved +======================================== + + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [3] added c + + $ echo babar > d + $ hg add d + $ hg amend + 1 new orphan changesets + + $ 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 evolve --abort' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ hg evolve --abort + evolve aborted + working directory is now at e93a9161a274 + + $ hg glog + @ 5:e93a9161a274 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 diff + + $ hg status + +cleaning up things for next testing + + $ 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 evolve --abort' 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 e83de241f751 + + $ hg up .^^^ + 0 files updated, 0 files merged, 3 files removed, 0 files unresolved + +When there are evolved revisions but on a single branch +======================================================= + + $ echo bar > c + $ hg add c + $ hg amend + 3 new orphan changesets + + $ hg evolve --all + move:[2] added b + atop:[7] added a + move:[5] added c + atop:[8] 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 evolve --abort' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ hg glog + @ 8:0c41ec482070 added b + | () draft + o 7:125af0ed8cae added a + | () draft + | o 6:e83de241f751 added d + | | () draft + | o 5:e93a9161a274 added c + | | () draft + | x 2:b1661037fa25 added b + | | () draft + | x 1:c7586e2a9264 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --abort + evolve aborted + working directory is now at 125af0ed8cae + + $ hg glog + @ 7:125af0ed8cae added a + | () draft + | o 6:e83de241f751 added d + | | () draft + | o 5:e93a9161a274 added c + | | () draft + | o 2:b1661037fa25 added b + | | () draft + | x 1:c7586e2a9264 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ cd .. + +Testing when evolved revs are on multiple branches +================================================== + + $ hg init repotwo + $ cd repotwo + $ echo ".*\.orig" > .hgignore + $ hg add .hgignore + $ hg ci -m "added hgignore" + $ echo a > a + $ hg ci -Aqm "added a" + $ for ch in b c; do echo $ch > $ch; hg add $ch; hg ci -m "added "$ch; done; + $ hg up .^^ + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ for ch in c d; do echo $ ch > $ch; hg add $ch; hg ci -m "added "$ch; done; + created new head + $ hg up .^^ + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ echo foo > a + $ hg ci -m "foo to a" + created new head + + $ hg glog + @ 6:8f20d4390c21 foo to a + | () draft + | o 5:bcb1c47f8520 added d + | | () draft + | o 4:86d2603075a3 added c + |/ () draft + | o 3:17509928e5bf added c + | | () draft + | o 2:9f0c80a55ddc added b + |/ () draft + o 1:2f913b0c9220 added a + | () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg prev + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + [1] added a + $ echo aa > a + $ hg amend + 5 new orphan changesets + + $ hg evolve --all + move:[2] added b + atop:[7] added a + move:[4] added c + atop:[7] added a + move:[6] foo to a + atop:[7] added a + merging a + warning: conflicts while merging a! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ hg glog + o 9:7f8e8bd9f0b6 added c + | () draft + | o 8:db3b42ef4da7 added b + |/ () draft + @ 7:807e8e2ca559 added a + | () draft + | o 6:8f20d4390c21 foo to a + | | () draft + | | o 5:bcb1c47f8520 added d + | | | () draft + | | x 4:86d2603075a3 added c + | |/ () draft + | | o 3:17509928e5bf added c + | | | () draft + | | x 2:9f0c80a55ddc added b + | |/ () draft + | x 1:2f913b0c9220 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --abort + evolve aborted + working directory is now at 807e8e2ca559 + + $ hg glog + @ 7:807e8e2ca559 added a + | () draft + | o 6:8f20d4390c21 foo to a + | | () draft + | | o 5:bcb1c47f8520 added d + | | | () draft + | | o 4:86d2603075a3 added c + | |/ () draft + | | o 3:17509928e5bf added c + | | | () draft + | | o 2:9f0c80a55ddc added b + | |/ () draft + | x 1:2f913b0c9220 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg status + + $ hg diff + +Testing when user created a new changesets on top of evolved revisions +====================================================================== + + $ hg evolve --all + move:[2] added b + atop:[7] added a + move:[4] added c + atop:[7] added a + move:[6] foo to a + atop:[7] added a + merging a + warning: conflicts while merging a! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + $ hg glog + o 9:7f8e8bd9f0b6 added c + | () draft + | o 8:db3b42ef4da7 added b + |/ () draft + @ 7:807e8e2ca559 added a + | () draft + | o 6:8f20d4390c21 foo to a + | | () draft + | | o 5:bcb1c47f8520 added d + | | | () draft + | | x 4:86d2603075a3 added c + | |/ () draft + | | o 3:17509928e5bf added c + | | | () draft + | | x 2:9f0c80a55ddc added b + | |/ () draft + | x 1:2f913b0c9220 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ echo foo > a + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + + $ cd .. + $ hg init clonerepo + $ cd repotwo + $ hg push ../clonerepo --force + pushing to ../clonerepo + searching for changes + adding changesets + adding manifests + adding file changes + added 10 changesets with 8 changes to 5 files (+4 heads) + 3 new obsolescence markers + $ cd ../clonerepo + $ hg up 7f8e8bd9f0b6 + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo bar > bar + $ hg add bar + $ hg ci -m "made an new commit on evolved rev" + + $ hg push ../repotwo --force + pushing to ../repotwo + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + $ cd ../repotwo + $ hg evolve --abort + warning: new changesets detected on destination branch + abort: unable to abort interrupted evolve, use 'hg evolve --stop' to stop evolve + [255] + + $ hg evolve --stop + stopped the interrupted evolve + working directory is now at 807e8e2ca559 + +Testing when the evolved revision turned public due to some other user actions +============================================================================== + + $ hg evolve --all + move:[3] added c + atop:[8] added b + move:[5] added d + atop:[9] added c + move:[6] foo to a + atop:[7] added a + merging a + warning: conflicts while merging a! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ hg glog + o 12:1c476940790a added d + | () draft + | o 11:c10a55eb0cc6 added c + | | () draft + +---o 10:48eca1ed5478 made an new commit on evolved rev + | | () draft + o | 9:7f8e8bd9f0b6 added c + | | () draft + | o 8:db3b42ef4da7 added b + |/ () draft + @ 7:807e8e2ca559 added a + | () draft + | o 6:8f20d4390c21 foo to a + | | () draft + | x 1:2f913b0c9220 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg phase -r 1c476940790a --public + + $ hg evolve --abort + cannot clean up public changesets: 1c476940790a + abort: unable to abort interrupted evolve, use 'hg evolve --stop' to stop evolve + [255] + + $ hg evolve --stop + stopped the interrupted evolve + working directory is now at 807e8e2ca559 + + $ cd .. + +Testing that bookmark should be moved back when doing `hg evolve --abort` +========================================================================= + + $ hg init repothree + $ cd repothree + $ echo ".*\.orig" > .hgignore + $ hg add .hgignore + $ hg ci -m "added hgignore" + $ for ch in a b c; do echo $ch > $ch; hg add $ch; hg ci -m "added "$ch; done; + + $ hg up .^ + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg bookmark bm1 + $ hg up .^ + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + (leaving bookmark bm1) + $ echo foo > c + $ hg add c + $ hg amend + 2 new orphan changesets + + $ hg glog + @ 4:a0086c17bfc7 added a + | () draft + | o 3:17509928e5bf added c + | | () draft + | o 2:9f0c80a55ddc added b + | | (bm1) draft + | x 1:2f913b0c9220 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --all + move:[2] added b + atop:[4] added a + move:[3] added c + atop:[5] 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 evolve --abort' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ hg glog + @ 5:c1f4718020e3 added b + | (bm1) draft + o 4:a0086c17bfc7 added a + | () draft + | o 3:17509928e5bf added c + | | () draft + | x 2:9f0c80a55ddc added b + | | () draft + | x 1:2f913b0c9220 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft + + $ hg evolve --abort + evolve aborted + working directory is now at a0086c17bfc7 + + $ hg glog + @ 4:a0086c17bfc7 added a + | () draft + | o 3:17509928e5bf added c + | | () draft + | o 2:9f0c80a55ddc added b + | | (bm1) draft + | x 1:2f913b0c9220 added a + |/ () draft + o 0:8fa14d15e168 added hgignore + () draft diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-evolve-bumped.t --- a/tests/test-evolve-bumped.t Wed Mar 21 16:18:31 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ - $ hg init public - $ cd public - $ echo a > a - $ mkcommit() { - > echo "$1" > "$1" - > hg add "$1" - > hg ci -m "add $1" - > } - $ hg commit -A -m init - adding a - $ cd .. - - $ evolvepath=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/ - $ hg clone -U public private - $ cd private - $ cat >> .hg/hgrc < [extensions] - > evolve = $evolvepath - > [ui] - > logtemplate = {rev}:{node|short}@{branch}({phase}) {desc|firstline}\n - > [phases] - > publish = false - > EOF - $ cd .. - - $ cp -a private alice - $ cp -a private bob - - $ cd alice - $ hg update - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ echo a >> a - $ hg commit -u alice -m 'modify a' - $ hg push ../private - pushing to ../private - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files - $ hg log -r 'draft()' - 1:4d1169d82e47@default(draft) modify a - - $ cd ../bob - $ hg pull ../private - pulling from ../private - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files - (run 'hg update' to get a working copy) - $ hg log -r 'draft()' - 1:4d1169d82e47@default(draft) modify a - $ hg push ../public - pushing to ../public - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files - $ hg log -r 'draft()' - - $ cd ../alice - $ hg amend -m 'tweak a' - $ hg pull ../public - pulling from ../public - searching for changes - no changes found - 1 new bumped changesets - - $ hg evolve -a -A --phase-divergent - recreate:[2] tweak a - atop:[1] modify a - computing new diff - committed as 4d1169d82e47 - working directory is now at 4d1169d82e47 - -Bumped Merge changeset: ------------------------ - -We currently cannot automatically solve bumped changeset that is the -product of a merge, we add a test for it. - - $ mkcommit _a - $ hg up .^ - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ mkcommit _b - created new head - $ mkcommit _c - $ hg log -G - @ 5:eeaf70969381@default(draft) add _c - | - o 4:6612fc0ddeb6@default(draft) add _b - | - | o 3:154ad198ff4a@default(draft) add _a - |/ - o 1:4d1169d82e47@default(public) modify a - | - o 0:d3873e73d99e@default(public) init - - $ hg merge 3 - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - (branch merge, don't forget to commit) - $ hg commit -m "merge" - $ hg commit --amend -m "New message" - $ hg phase --public 551127da2a8a --hidden - 1 new bumped changesets - $ hg log -G - @ 7:b28e84916d8c@default(draft) New message - |\ - +---o 6:551127da2a8a@default(public) merge - | |/ - | o 5:eeaf70969381@default(public) add _c - | | - | o 4:6612fc0ddeb6@default(public) add _b - | | - o | 3:154ad198ff4a@default(public) add _a - |/ - o 1:4d1169d82e47@default(public) modify a - | - o 0:d3873e73d99e@default(public) init - - $ hg evolve --all --phase-divergent - skipping b28e84916d8c : we do not handle merge yet diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-evolve-continue.t --- a/tests/test-evolve-continue.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-evolve-continue.t Mon Apr 23 12:23:00 2018 +0200 @@ -59,7 +59,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] @@ -118,7 +118,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] @@ -128,9 +128,9 @@ continue: hg evolve --continue $ hg diff -XXX: maybe we should add a message here about evolve resulting in no commit $ hg evolve --continue evolving 8:ad0a59d83efe "added e" + evolution of 8:ad0a59d83efe created no changes to commit $ hg glog @ 10:00a5c774cc37 added d @@ -159,7 +159,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] @@ -247,7 +247,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] @@ -264,7 +264,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] @@ -312,7 +312,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] @@ -364,7 +364,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] $ echo foo > g diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-evolve-issue5832.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-issue5832.t Mon Apr 23 12:23:00 2018 +0200 @@ -0,0 +1,280 @@ +Test for issue 5832 present at https://bz.mercurial-scm.org/show_bug.cgi?id=5832 +================================================================================ + +Setup +===== + + $ cat >> $HGRCPATH < [phases] + > publish = False + > [alias] + > glog = log -GT "{rev}:{node|short} {desc}\n ({bookmarks}) {phase}" + > [extensions] + > EOF + $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH + + $ hg init issue5832 + $ cd issue5832 + + $ echo base > base + $ hg ci -Aqm "added base" + + $ echo a > a + $ hg ci -Aqm "added a" + + $ echo b > b + $ hg ci -Aqm "added b" + + $ hg up .^^ + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ echo c > c + $ echo d > d + $ hg ci -Aqm "added c and d" + + $ 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 glog + @ 4:b9b387427a53 merge commit + |\ () draft + | o 3:9402371b436e added c and d + | | () draft + o | 2:a1da0651488c added b + | | () draft + o | 1:1b24879c5c3c added a + |/ () draft + o 0:bde1d2b6b5e5 added base + () draft + + $ hg up 1b24879c5c3c + 0 files updated, 0 files merged, 3 files removed, 0 files unresolved + $ echo foo > a + $ hg amend + 2 new orphan changesets + + $ hg up bde1d2b6b5e5 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo c > c + $ hg ci -Aqm "added c" + $ hg up .^ + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo d > d + $ hg ci -Aqm "added d" + $ hg glog + @ 7:5841d7cf9893 added d + | () draft + | o 6:62fb70414f99 added c + |/ () draft + | o 5:7014ec2829cd added a + |/ () draft + | o 4:b9b387427a53 merge commit + | |\ () draft + +---o 3:9402371b436e added c and d + | | () draft + | o 2:a1da0651488c added b + | | () draft + | x 1:1b24879c5c3c added a + |/ () draft + o 0:bde1d2b6b5e5 added base + () draft + + $ hg prune -r 9402371b436e --succ 62fb70414f99 --succ 5841d7cf9893 --split + 1 changesets pruned + + $ hg glog + @ 7:5841d7cf9893 added d + | () draft + | o 6:62fb70414f99 added c + |/ () draft + | o 5:7014ec2829cd added a + |/ () draft + | o 4:b9b387427a53 merge commit + | |\ () draft + +---x 3:9402371b436e added c and d + | | () draft + | o 2:a1da0651488c added b + | | () draft + | x 1:1b24879c5c3c added a + |/ () draft + o 0:bde1d2b6b5e5 added base + () draft + +Checking what evolve is trying to do + + $ hg evolve --dry-run --any --all + move:[2] added b + atop:[5] added a + hg rebase -r a1da0651488c -d 7014ec2829cd + could not solve instability, ambiguous destination: parent split across two branches + +Resolving instability using `hg evolve` + + $ hg evolve --any --all --config ui.interactive=True < 0 + > EOF + move:[2] added b + atop:[5] added a + move:[4] merge commit + atop:[8] added b + ancestor '7235ef625ea3' split over multiple topological branches. + choose an evolve destination: + 0: [62fb70414f99] added c + 1: [5841d7cf9893] added d + q: quit the prompt + enter the index of the revision you want to select: 0 + move:[9] merge commit + atop:[6] added c + working directory is now at 28a0775ac832 + + $ hg glog + @ 10:28a0775ac832 merge commit + |\ () draft + | o 8:2baf8bae7ea4 added b + | | () draft + | | o 7:5841d7cf9893 added d + | | | () draft + o---+ 6:62fb70414f99 added c + / / () draft + o / 5:7014ec2829cd added a + |/ () draft + o 0:bde1d2b6b5e5 added base + () draft + + $ cd .. + +Test for issue5833 present at https://bz.mercurial-scm.org/show_bug.cgi?id=5833 +=============================================================================== + + $ hg init issue5833 + $ cd issue5833 + $ echo base > base + $ hg ci -Aqm "added base" + + $ echo a > a + $ hg ci -Aqm "added a" + + $ echo b > b + $ hg ci -Aqm "added b" + + $ hg up .^^ + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ echo c > c + $ echo d > d + $ hg ci -Aqm "added c and d" + + $ 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 glog + @ 4:b9b387427a53 merge commit + |\ () draft + | o 3:9402371b436e added c and d + | | () draft + o | 2:a1da0651488c added b + | | () draft + o | 1:1b24879c5c3c added a + |/ () draft + o 0:bde1d2b6b5e5 added base + () draft + + $ hg up bde1d2b6b5e5 + 0 files updated, 0 files merged, 4 files removed, 0 files unresolved + $ echo l > l + $ hg ci -Aqm "added l" + $ hg grab -r 1b24879c5c3c + grabbing 1:1b24879c5c3c "added a" + + $ hg up bde1d2b6b5e5 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ echo c > c + $ hg ci -Aqm "added c" + $ hg up .^ + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo d > d + $ hg ci -Aqm "added d" + + $ hg glog + @ 8:5841d7cf9893 added d + | () draft + | o 7:62fb70414f99 added c + |/ () draft + | o 6:5568b87b1491 added a + | | () draft + | o 5:0a6281e212fe added l + |/ () draft + | o 4:b9b387427a53 merge commit + | |\ () draft + +---o 3:9402371b436e added c and d + | | () draft + | o 2:a1da0651488c added b + | | () draft + | x 1:1b24879c5c3c added a + |/ () draft + o 0:bde1d2b6b5e5 added base + () draft + + $ hg prune -r 9402371b436e --succ 5841d7cf9893 --succ 62fb70414f99 --split + 1 changesets pruned + + $ hg glog + @ 8:5841d7cf9893 added d + | () draft + | o 7:62fb70414f99 added c + |/ () draft + | o 6:5568b87b1491 added a + | | () draft + | o 5:0a6281e212fe added l + |/ () draft + | o 4:b9b387427a53 merge commit + | |\ () draft + +---x 3:9402371b436e added c and d + | | () draft + | o 2:a1da0651488c added b + | | () draft + | x 1:1b24879c5c3c added a + |/ () draft + o 0:bde1d2b6b5e5 added base + () draft + + $ hg evolve --any --all --dry-run + move:[2] added b + atop:[6] added a + hg rebase -r a1da0651488c -d 5568b87b1491 + could not solve instability, ambiguous destination: parent split across two branches + + $ hg evolve --any --all --config ui.interactive=True < 1 + > EOF + move:[2] added b + atop:[6] added a + move:[4] merge commit + atop:[9] added b + ancestor 'cdf2ea1b9312' split over multiple topological branches. + choose an evolve destination: + 0: [62fb70414f99] added c + 1: [5841d7cf9893] added d + q: quit the prompt + enter the index of the revision you want to select: 1 + move:[10] merge commit + atop:[8] added d + working directory is now at 460e6e72b7f9 + + $ hg glog + @ 11:460e6e72b7f9 merge commit + |\ () draft + | o 9:da76bb7cd904 added b + | | () draft + o | 8:5841d7cf9893 added d + | | () draft + +---o 7:62fb70414f99 added c + | | () draft + | o 6:5568b87b1491 added a + | | () draft + | o 5:0a6281e212fe added l + |/ () draft + o 0:bde1d2b6b5e5 added base + () draft diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-evolve-obshistory.t diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-evolve-orphan-merge.t --- a/tests/test-evolve-orphan-merge.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-evolve-orphan-merge.t Mon Apr 23 12:23:00 2018 +0200 @@ -220,7 +220,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] @@ -277,7 +277,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-evolve-phase-divergence.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-phase-divergence.t Mon Apr 23 12:23:00 2018 +0200 @@ -0,0 +1,1221 @@ +** Test for handling of phase divergent changesets by `hg evolve` ** +==================================================================== + + $ cat >> $HGRCPATH < [alias] + > glog = log -GT "{rev}:{node|short} {desc|firstline}\n ({bookmarks}) {phase}" + > [extensions] + > rebase = + > EOF + +Setting up a public repo +------------------------ + + $ hg init public + $ cd public + $ echo a > a + $ mkcommit() { + > echo "$1" > "$1" + > hg add "$1" + > hg ci -m "add $1" + > } + $ hg commit -A -m init + adding a + $ cd .. + + $ evolvepath=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/ + +Setting up a private non-publishing repo +---------------------------------------- + + $ hg clone -U public private + $ cd private + $ cat >> .hg/hgrc < [extensions] + > evolve = $evolvepath + > [ui] + > logtemplate = {rev}:{node|short}@{branch}({phase}) {desc|firstline}\n + > [phases] + > publish = false + > EOF + $ cd .. + +Setting up couple of more instances of private repo +--------------------------------------------------- + + $ cp -a private alice + $ cp -a private bob + +Creating a phase-divergence changeset +------------------------------------- + +Alice creating a draft changeset and pushing to main private repo + + $ cd alice + $ hg update + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo a >> a + $ hg commit -u alice -m 'modify a' + $ hg push ../private + pushing to ../private + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + $ hg glog + @ 1:4d1169d82e47 modify a + | () draft + o 0:d3873e73d99e init + () public + +Bob pulling from private repo and pushing to the main public repo making the +changeset public + + $ cd ../bob + $ hg pull ../private + pulling from ../private + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + (run 'hg update' to get a working copy) + + $ hg glog + o 1:4d1169d82e47 modify a + | () draft + o 0:d3873e73d99e init + () public + + $ hg push ../public + pushing to ../public + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + + $ hg glog + o 1:4d1169d82e47 modify a + | () public + o 0:d3873e73d99e init + () public + +*But* Alice decided to amend the changeset she had and then pulling from public +repo creating phase-divergent changeset locally + + $ cd ../alice + $ hg amend -m 'tweak a' + +XXX: pull should tell us how to see what is the new phase-divergent changeset + $ hg pull ../public + pulling from ../public + searching for changes + no changes found + 1 new phase-divergent changesets + + $ hg glog + @ 2:98bb3a6cfe1a tweak a + | () draft + | o 1:4d1169d82e47 modify a + |/ () public + o 0:d3873e73d99e init + () public + +Using evolve --list to list phase-divergent changesets +------------------------------------------------------ + + $ hg evolve --list + 98bb3a6cfe1a: tweak a + phase-divergent: 4d1169d82e47 (immutable precursor) + + + +XXX-Pulkit: Trying to see instability on public changeset + +XXX-Pulkit: this is not helpful + +XXX-Marmoute: public changeset "instable themself" +XXX-Marmoute: I'm not sure if we store this information and it is useful to show it. +XXX-Marmoute: We should maybe point the user toward `hg obslog` instead` + $ hg evolve -r 4d1169d8 --list + 4d1169d82e47: modify a + + +Understanding phasedivergence using obslog +------------------------------------------ + +XXX: There must be mention of phase-divergence here + $ hg obslog -r . --all + @ 98bb3a6cfe1a (2) tweak a + | + o 4d1169d82e47 (1) modify a + rewritten(description) as 98bb3a6cfe1a using amend by test (Thu Jan 01 00:00:00 1970 +0000) + +Solving the phase divergence using evolve command +-------------------------------------------------- + +(We do not solve evolution other than orphan by default because it turned out +it was too confusing for users. We used to behave this way, but having multiple +possible outcome to evolve end up scaring people) + + $ hg evolve + nothing to evolve on current working copy parent + (do you want to use --phase-divergent) + [2] + +testing the --confirm option + $ hg evolve --phase-divergent --confirm < n + > EOF + recreate:[2] tweak a + atop:[1] modify a + perform evolve? [Ny] n + abort: evolve aborted by user + [255] + +testing the --dry-run option + + $ hg evolve --phase-divergent --dry-run + recreate:[2] tweak a + atop:[1] modify a + hg rebase --rev 98bb3a6cfe1a --dest d3873e73d99e; + hg update 4d1169d82e47; + hg revert --all --rev 98bb3a6cfe1a; + hg commit --msg "phase-divergent update to 98bb3a6cfe1a" + +XXX: evolve should have mentioned that draft commit is just obsoleted in favour +of public one. From the message it looks like a new commit is created. + + $ hg evolve --phase-divergent + recreate:[2] tweak a + atop:[1] modify a + computing new diff + committed as 4d1169d82e47 + working directory is now at 4d1169d82e47 + + $ hg glog + @ 1:4d1169d82e47 modify a + | () public + o 0:d3873e73d99e init + () public + +Syncying every repo with the new state +-------------------------------------- + + $ hg push ../public + pushing to ../public + searching for changes + no changes found + 2 new obsolescence markers + [1] + $ hg push ../private + pushing to ../private + searching for changes + no changes found + 2 new obsolescence markers + [1] + $ hg push ../bob + pushing to ../bob + searching for changes + no changes found + 2 new obsolescence markers + [1] + +Creating more phase-divergence where a new resolution commit will be formed and +also testing bookmark movement +-------------------------------------------------------------------------------- + +Alice created a commit and push to private non-publishing repo + + $ echo foo > foo + $ hg add foo + $ hg ci -m "added foo to foo" + $ hg glog + @ 3:aa071e5554e3 added foo to foo + | () draft + o 1:4d1169d82e47 modify a + | () public + o 0:d3873e73d99e init + () public + + $ hg push ../private + pushing to ../private + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + +Bob pulled from the private repo and pushed that to publishing repo + + $ cd ../bob + $ hg pull ../private + pulling from ../private + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + new changesets aa071e5554e3 + (run 'hg update' to get a working copy) + + $ hg push ../public + pushing to ../public + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + +Alice amended that changeset and then pulled from publishing repo creating +phase-divergence + + $ cd ../alice + $ echo bar >> foo + $ hg amend -m "added bar to foo" + $ hg bookmark bm + + $ hg pull ../public + pulling from ../public + searching for changes + no changes found + 1 new phase-divergent changesets + + $ hg glog + @ 4:d47f2b37ed82 added bar to foo + | (bm) draft + | o 3:aa071e5554e3 added foo to foo + |/ () public + o 1:4d1169d82e47 modify a + | () public + o 0:d3873e73d99e init + () public + +Resolving the new phase-divergence changeset using `hg evolve` +-------------------------------------------------------------- + +XXX: this should have popped up for a new commit message of the changeset or an +option should be there + +XXX: we should document what should user expect where running this, writing this +test I have to go through code base to understand what will be the behavior + + $ hg evolve --phase-divergent + recreate:[4] added bar to foo + atop:[3] added foo to foo + computing new diff + committed as 3d62500c673d + working directory is now at 3d62500c673d + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 3d62500c673dd1c88bb09a73e86d0210aed6fcb6 + # Parent aa071e5554e36080a36cfd24accd5a71e3320f1e + phase-divergent update to aa071e5554e3: + + added bar to foo + + diff -r aa071e5554e3 -r 3d62500c673d foo + --- a/foo Thu Jan 01 00:00:00 1970 +0000 + +++ b/foo Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +1,2 @@ + foo + +bar + +XXX: the commit message is not best one, we should give option to user to modify +the commit message + + $ hg glog + @ 5:3d62500c673d phase-divergent update to aa071e5554e3: + | (bm) draft + o 3:aa071e5554e3 added foo to foo + | () public + o 1:4d1169d82e47 modify a + | () public + o 0:d3873e73d99e init + () public + + $ hg obslog -r . --all + @ 3d62500c673d (5) phase-divergent update to aa071e5554e3: + | + x d47f2b37ed82 (4) added bar to foo + | rewritten(description, parent, content) as 3d62500c673d using evolve by test (Thu Jan 01 00:00:00 1970 +0000) + | + o aa071e5554e3 (3) added foo to foo + rewritten(description, content) as d47f2b37ed82 using amend by test (Thu Jan 01 00:00:00 1970 +0000) + + +Syncing all other repositories +------------------------------ + +These pushed should not be turned to quiet mode as the output is very helpful to +make sure everything is working fine + + $ hg push ../bob + pushing to ../bob + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + 2 new obsolescence markers + + $ hg push ../private + pushing to ../private + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + 2 new obsolescence markers + + $ hg push ../public + pushing to ../public + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + 2 new obsolescence markers + +Creating a phasedivergence changeset where the divergent changeset changed in a +way that we rebase that on old public changeset, there will be conflicts, but +the `hg evolve` command handles it very well and uses `hg revert` logic to +prevent any conflicts +------------------------------------------------------------------------------- + +Alice creates one more changeset and pushes to private repo + + $ echo bar > bar + $ hg ci -Aqm "added bar to bar" + $ hg push ../private + pushing to ../private + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + +Bob pulls from private and pushes to public repo + $ cd ../bob + + $ hg pull ../private + pulling from ../private + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + new changesets b756eb10ea73 + (run 'hg update' to get a working copy) + + $ hg push ../public + pushing to ../public + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + +Alice amends the changeset and then pull from public creating phase-divergence + + $ cd ../alice + $ echo foo > bar + $ hg amend -m "foo to bar" + + $ hg pull ../public + pulling from ../public + searching for changes + no changes found + 1 new phase-divergent changesets + + $ hg glog + @ 7:2c3560aedead foo to bar + | (bm) draft + | o 6:b756eb10ea73 added bar to bar + |/ () public + o 5:3d62500c673d phase-divergent update to aa071e5554e3: + | () public + o 3:aa071e5554e3 added foo to foo + | () public + o 1:4d1169d82e47 modify a + | () public + o 0:d3873e73d99e init + () public + +Resolving the new phase-divergence changeset using `hg evolve` +--------------------------------------------------------------- + + $ hg evolve --phase-divergent + recreate:[7] foo to bar + atop:[6] added bar to bar + computing new diff + committed as 502e73736632 + working directory is now at 502e73736632 + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 502e737366322886cf628276aa0a2796904453b4 + # Parent b756eb10ea73ee4ba69c998e64a5c6e1005d74b5 + phase-divergent update to b756eb10ea73: + + foo to bar + + diff -r b756eb10ea73 -r 502e73736632 bar + --- a/bar Thu Jan 01 00:00:00 1970 +0000 + +++ b/bar Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +1,1 @@ + -bar + +foo + + $ hg glog + @ 8:502e73736632 phase-divergent update to b756eb10ea73: + | (bm) draft + o 6:b756eb10ea73 added bar to bar + | () public + o 5:3d62500c673d phase-divergent update to aa071e5554e3: + | () public + o 3:aa071e5554e3 added foo to foo + | () public + o 1:4d1169d82e47 modify a + | () public + o 0:d3873e73d99e init + () public + +Syncing all the repositories +---------------------------- + + $ hg push ../private + pushing to ../private + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + 2 new obsolescence markers + $ hg push ../public + pushing to ../public + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + 2 new obsolescence markers + +Creating phase-divergence with divergent changeset and precursor having +different parents +----------------------------------------------------------------------- + +Alice creates a changeset and pushes to private repo + + $ echo x > x + $ hg ci -Am "added x to x" + adding x + + $ hg push ../private + pushing to ../private + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + +Bob does what he always does, pull from private and push to public, he is acting +as a CI service + + $ cd ../bob + $ hg pull ../private + pulling from ../private + searching for changes + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files + 2 new obsolescence markers + new changesets 502e73736632:2352021b3785 + (run 'hg update' to get a working copy) + $ hg push ../public + pushing to ../public + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + +Alice like always dont care about Bob existence and rebases her changeset and +then pull from public repo creating phase divergence + + $ cd ../alice + $ hg rebase -r . -d .^^^ + rebasing 9:2352021b3785 "added x to x" (bm tip) + + $ hg pull ../public + pulling from ../public + searching for changes + no changes found + 1 new bumped changesets + + $ hg obslog -r . + @ 334e300d6db5 (10) added x to x + | + o 2352021b3785 (9) added x to x + rewritten(parent) as 334e300d6db5 using rebase by test (Thu Jan 01 00:00:00 1970 +0000) + + $ hg glog -r .^:: + hg: parse error at 4: not a prefix: end + [255] + +Using `hg evolve` to resolve phase-divergence +--------------------------------------------- + + $ hg evolve --phase-divergent + recreate:[10] added x to x + atop:[9] added x to x + rebasing to destination parent: 502e73736632 + (leaving bookmark bm) + computing new diff + committed as 2352021b3785 + working directory is now at 2352021b3785 + +XXX: we should move bookmark here + $ hg glog + @ 9:2352021b3785 added x to x + | (bm) public + o 8:502e73736632 phase-divergent update to b756eb10ea73: + | () public + o 6:b756eb10ea73 added bar to bar + | () public + o 5:3d62500c673d phase-divergent update to aa071e5554e3: + | () public + o 3:aa071e5554e3 added foo to foo + | () public + o 1:4d1169d82e47 modify a + | () public + o 0:d3873e73d99e init + () public + + $ hg obslog -r . b1a0e143e32b --all --hidden + x b1a0e143e32b (11) added x to x + | pruned using evolve by test (Thu Jan 01 00:00:00 1970 +0000) + | + x 334e300d6db5 (10) added x to x + | rewritten(parent) as b1a0e143e32b using evolve by test (Thu Jan 01 00:00:00 1970 +0000) + | + @ 2352021b3785 (9) added x to x + rewritten(parent) as 334e300d6db5 using rebase by test (Thu Jan 01 00:00:00 1970 +0000) + + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 2352021b37851be226ebed109b0eb6eada918566 + # Parent 502e737366322886cf628276aa0a2796904453b4 + added x to x + + diff -r 502e73736632 -r 2352021b3785 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 @@ + +x + +Creating divergence with parent and content change both but not resulting in +conflicts +----------------------------------------------------------------------------- + +Alice is tired of pushing and pulling and will create phase-divergence locally + + $ hg glog + @ 9:2352021b3785 added x to x + | (bm) public + o 8:502e73736632 phase-divergent update to b756eb10ea73: + | () public + o 6:b756eb10ea73 added bar to bar + | () public + o 5:3d62500c673d phase-divergent update to aa071e5554e3: + | () public + o 3:aa071e5554e3 added foo to foo + | () public + o 1:4d1169d82e47 modify a + | () public + o 0:d3873e73d99e init + () public + + $ echo y > y + $ echo foobar >> foo + $ hg add y + $ hg ci -m "y to y and foobar to foo" + $ hg rebase -r . -d .^^^ + rebasing 12:dc88f5aa9bc9 "y to y and foobar to foo" (tip) + + $ echo foo > y + $ hg amend + +Alice making the old changeset public to have content-divergence + + $ hg phase -r dc88f5aa9bc9 --public --hidden + 1 new phase-divergent changesets + $ hg glog + @ 14:13015a180eee y to y and foobar to foo + | () draft + | o 12:dc88f5aa9bc9 y to y and foobar to foo + | | () public + | o 9:2352021b3785 added x to x + | | (bm) public + | o 8:502e73736632 phase-divergent update to b756eb10ea73: + |/ () public + o 6:b756eb10ea73 added bar to bar + | () public + o 5:3d62500c673d phase-divergent update to aa071e5554e3: + | () public + o 3:aa071e5554e3 added foo to foo + | () public + o 1:4d1169d82e47 modify a + | () public + o 0:d3873e73d99e init + () public + + $ hg obslog -r . + @ 13015a180eee (14) y to y and foobar to foo + | + x 211ab84d1689 (13) y to y and foobar to foo + | rewritten(content) as 13015a180eee using amend by test (Thu Jan 01 00:00:00 1970 +0000) + | + o dc88f5aa9bc9 (12) y to y and foobar to foo + rewritten(parent) as 211ab84d1689 using rebase by test (Thu Jan 01 00:00:00 1970 +0000) + +Resolving divergence using `hg evolve` +------------------------------------- + + $ hg evolve --phase-divergent + recreate:[14] y to y and foobar to foo + atop:[12] y to y and foobar to foo + rebasing to destination parent: 2352021b3785 + computing new diff + committed as 8c2bb6fb44e9 + working directory is now at 8c2bb6fb44e9 + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 8c2bb6fb44e9443c64b3a2a3d061272c8e25e6ce + # Parent dc88f5aa9bc90a6418899d267d9524205dfb429b + phase-divergent update to dc88f5aa9bc9: + + y to y and foobar to foo + + diff -r dc88f5aa9bc9 -r 8c2bb6fb44e9 y + --- a/y Thu Jan 01 00:00:00 1970 +0000 + +++ b/y Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +1,1 @@ + -y + +foo + + $ hg glog + @ 16:8c2bb6fb44e9 phase-divergent update to dc88f5aa9bc9: + | () draft + o 12:dc88f5aa9bc9 y to y and foobar to foo + | () public + o 9:2352021b3785 added x to x + | (bm) public + o 8:502e73736632 phase-divergent update to b756eb10ea73: + | () public + o 6:b756eb10ea73 added bar to bar + | () public + o 5:3d62500c673d phase-divergent update to aa071e5554e3: + | () public + o 3:aa071e5554e3 added foo to foo + | () public + o 1:4d1169d82e47 modify a + | () public + o 0:d3873e73d99e init + () public + +Creating divergence with parent and content change both which results in +conflicts while rebasing on parent +----------------------------------------------------------------------------- + + $ echo l > l + $ hg ci -Aqm "added l to l" + $ hg rebase -r . -d .^^^^ + rebasing 17:f3794e5a91dc "added l to l" (tip) + $ echo kl > l + $ echo foo > x + $ hg add x + $ hg amend + + $ hg obslog -r . + @ 5fd38c0de46e (19) added l to l + | + x 2bfd56949cf0 (18) added l to l + | rewritten(content) as 5fd38c0de46e using amend by test (Thu Jan 01 00:00:00 1970 +0000) + | + x f3794e5a91dc (17) added l to l + rewritten(parent) as 2bfd56949cf0 using rebase by test (Thu Jan 01 00:00:00 1970 +0000) + + + $ hg phase -r f3794e5a91dc --public --hidden + 1 new phase-divergent changesets + +Resolution using `hg evolve --phase-divergent` +---------------------------------------------- + + $ hg evolve --phase-divergent + recreate:[19] added l to l + atop:[17] added l to l + rebasing to destination parent: 8c2bb6fb44e9 + merging x + warning: conflicts while merging x! (edit, then use 'hg resolve --mark') + evolution failed! + fix conflict then run 'hg evolve --continue' or use `hg evolve --abort` + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ hg diff + diff -r 8c2bb6fb44e9 l + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 + +++ b/l Thu Jan 01 00:00:00 1970 +0000 + @@ -0,0 +1,1 @@ + +kl + diff -r 8c2bb6fb44e9 x + --- a/x Thu Jan 01 00:00:00 1970 +0000 + +++ b/x Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +1,5 @@ + +<<<<<<< destination: 8c2bb6fb44e9 - test: phase-divergent update to dc88f5aa9... + x + +======= + +foo + +>>>>>>> evolving: 5fd38c0de46e - test: added l to l + + $ echo foo > x + + $ hg resolve -m + (no more unresolved files) + continue: hg evolve --continue + + $ hg evolve --continue + evolving 19:5fd38c0de46e "added l to l" + computing new diff + committed as e3090241a10c + working directory is now at e3090241a10c + + $ hg glog + @ 21:e3090241a10c phase-divergent update to f3794e5a91dc: + | () draft + o 17:f3794e5a91dc added l to l + | () public + o 16:8c2bb6fb44e9 phase-divergent update to dc88f5aa9bc9: + | () public + o 12:dc88f5aa9bc9 y to y and foobar to foo + | () public + o 9:2352021b3785 added x to x + | (bm) public + o 8:502e73736632 phase-divergent update to b756eb10ea73: + | () public + o 6:b756eb10ea73 added bar to bar + | () public + o 5:3d62500c673d phase-divergent update to aa071e5554e3: + | () public + o 3:aa071e5554e3 added foo to foo + | () public + o 1:4d1169d82e47 modify a + | () public + o 0:d3873e73d99e init + () public + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID e3090241a10c320b6132e4673915fd6b19c0de39 + # Parent f3794e5a91dc1d4d36fee5c423386b19433a1f48 + phase-divergent update to f3794e5a91dc: + + added l to l + + diff -r f3794e5a91dc -r e3090241a10c l + --- a/l Thu Jan 01 00:00:00 1970 +0000 + +++ b/l Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +1,1 @@ + -l + +kl + diff -r f3794e5a91dc -r e3090241a10c x + --- a/x Thu Jan 01 00:00:00 1970 +0000 + +++ b/x Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +1,1 @@ + -x + +foo + +Creating phase divergence when couple of changesets are folded into one +------------------------------------------------------------------------ + + $ hg glog -r . + @ 21:e3090241a10c phase-divergent update to f3794e5a91dc: + | () draft + ~ + $ echo f > f + $ hg ci -Aqm "added f" + $ echo g > g + $ hg ci -Aqm "added g" + + $ hg fold -r . -r .^ --exact + 2 changesets folded + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg evolve --list + + $ hg phase -r 428f7900a969 --public --hidden + 1 new phase-divergent changesets + + $ hg glog -r f3794e5a91dc:: + @ 24:e450d05b7d27 added g + | () draft + | o 23:428f7900a969 added g + | | () public + | o 22:21ae52e414e6 added f + |/ () public + o 21:e3090241a10c phase-divergent update to f3794e5a91dc: + | () public + o 17:f3794e5a91dc added l to l + | () public + ~ + + $ hg evolve --list + e450d05b7d27: added g + phase-divergent: 21ae52e414e6 (immutable precursor) + phase-divergent: 428f7900a969 (immutable precursor) + +Resolving phase divergence using `hg evolve` + + $ hg evolve --phase-divergent --all + recreate:[24] added g + atop:[23] added g + rebasing to destination parent: 21ae52e414e6 + computing new diff + committed as 428f7900a969 + working directory is now at 428f7900a969 + + $ hg glog -r f3794e5a91dc:: + @ 23:428f7900a969 added g + | () public + o 22:21ae52e414e6 added f + | () public + o 21:e3090241a10c phase-divergent update to f3794e5a91dc: + | () public + o 17:f3794e5a91dc added l to l + | () public + ~ + +When the public changesets is splitted causing phase-divergence +--------------------------------------------------------------- + + $ echo m > m + $ echo n > n + $ hg ci -Aqm "added m and n" + + $ hg glog -r 21ae52e414e6:: + @ 26:849cee0a874b added m and n + | () draft + o 23:428f7900a969 added g + | () public + o 22:21ae52e414e6 added f + | () public + ~ + + $ hg prev + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + [23] added g + $ echo m > m + $ hg ci -Aqm "added m" + $ echo n > n + $ hg ci -Aqm "added n" + + $ hg glog -r 428f7900a969:: + @ 28:63ccb8ea7cae added n + | () draft + o 27:f313e2b90e70 added m + | () draft + | o 26:849cee0a874b added m and n + |/ () draft + o 23:428f7900a969 added g + | () public + ~ + + $ hg prune -r 849cee0a874b --succ f313e2b90e70 --succ 63ccb8ea7cae --split + 1 changesets pruned + + $ hg phase -r 849cee0a874b --hidden --public + 2 new phase-divergent changesets + + $ hg glog -r 428f7900a969:: + @ 28:63ccb8ea7cae added n + | () draft + o 27:f313e2b90e70 added m + | () draft + | o 26:849cee0a874b added m and n + |/ () public + o 23:428f7900a969 added g + | () public + ~ + + $ hg evolve --all --phase-divergent + recreate:[27] added m + atop:[26] added m and n + computing new diff + committed as 870e1c3eddc3 + recreate:[28] added n + atop:[26] added m and n + rebasing to destination parent: 428f7900a969 + computing new diff + committed as 154b0179fb9b + working directory is now at 154b0179fb9b + +XXX: this is messy, we should solve things in better way + $ hg glog -r 428f7900a969:: --hidden + @ 31:154b0179fb9b phase-divergent update to 849cee0a874b: + | () draft + | x 30:1ebf33547a82 added n + | | () draft + +---o 29:870e1c3eddc3 phase-divergent update to 849cee0a874b: + | | () draft + | | x 28:63ccb8ea7cae added n + | | | () draft + | | x 27:f313e2b90e70 added m + | |/ () draft + o | 26:849cee0a874b added m and n + |/ () public + o 23:428f7900a969 added g + | () public + ~ + +XXX: not sure this is the correct + $ hg exp 154b0179fb9b + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 154b0179fb9b53d2f853d6ba04740bb3d7a5cabe + # Parent 849cee0a874be7c4e75dfacb5ad72aa5696951ba + phase-divergent update to 849cee0a874b: + + added n + + diff -r 849cee0a874b -r 154b0179fb9b m + --- a/m Thu Jan 01 00:00:00 1970 +0000 + +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +0,0 @@ + -m + +XXX: not sure this is correct + $ hg exp 870e1c3eddc3 + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 870e1c3eddc34cc475e8e13d2fe1934210c1937e + # Parent 849cee0a874be7c4e75dfacb5ad72aa5696951ba + phase-divergent update to 849cee0a874b: + + added m + + diff -r 849cee0a874b -r 870e1c3eddc3 n + --- a/n Thu Jan 01 00:00:00 1970 +0000 + +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +0,0 @@ + -n + +When the public changeset is splitted across various branches +-------------------------------------------------------------- + + $ echo p > p + $ echo q > q + $ hg ci -Aqm "added p and q" + + $ hg prev + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + [31] phase-divergent update to 849cee0a874b: + $ echo p > p + $ hg ci -Aqm "added p" + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [31] phase-divergent update to 849cee0a874b: + $ echo q > q + $ hg ci -Aqm "added q" + + $ hg glog -r 154b0179fb9b:: + @ 34:e046341aa97c added q + | () draft + | o 33:6f8c250eecff added p + |/ () draft + | o 32:8a70f55b2af3 added p and q + |/ () draft + o 31:154b0179fb9b phase-divergent update to 849cee0a874b: + | () draft + ~ + + $ hg prune -r 8a70f55b2af3 --succ 6f8c250eecff --succ e046341aa97c --split + 1 changesets pruned + + $ hg phase -r 8a70f55b2af3 --public --hidden + 2 new phase-divergent changesets + + $ hg glog -r 154b0179fb9b:: + @ 34:e046341aa97c added q + | () draft + | o 33:6f8c250eecff added p + |/ () draft + | o 32:8a70f55b2af3 added p and q + |/ () public + o 31:154b0179fb9b phase-divergent update to 849cee0a874b: + | () public + ~ + + $ hg evolve --list + 6f8c250eecff: added p + phase-divergent: 8a70f55b2af3 (immutable precursor) + + e046341aa97c: added q + phase-divergent: 8a70f55b2af3 (immutable precursor) + + $ hg evolve --all --phase-divergent + recreate:[33] added p + atop:[32] added p and q + computing new diff + committed as f3e41d89b3c5 + recreate:[34] added q + atop:[32] added p and q + computing new diff + committed as 605c306d4f87 + working directory is now at 605c306d4f87 + + $ hg glog -r 154b0179fb9b:: --hidden + @ 36:605c306d4f87 phase-divergent update to 8a70f55b2af3: + | () draft + | o 35:f3e41d89b3c5 phase-divergent update to 8a70f55b2af3: + |/ () draft + | x 34:e046341aa97c added q + | | () draft + | | x 33:6f8c250eecff added p + | |/ () draft + o | 32:8a70f55b2af3 added p and q + |/ () public + o 31:154b0179fb9b phase-divergent update to 849cee0a874b: + | () public + ~ + +XXX: not sure this is correct + $ hg exp 605c306d4f87 + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 605c306d4f87fccfdb5e7dd1c750b6d4f813defb + # Parent 8a70f55b2af35452916dc89401a5ecf6553646a5 + phase-divergent update to 8a70f55b2af3: + + added q + + diff -r 8a70f55b2af3 -r 605c306d4f87 p + --- a/p Thu Jan 01 00:00:00 1970 +0000 + +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +0,0 @@ + -p + +XXX: not sure this is correct + $ hg exp f3e41d89b3c5 + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID f3e41d89b3c5f6ee49ccc734045856d7b025f048 + # Parent 8a70f55b2af35452916dc89401a5ecf6553646a5 + phase-divergent update to 8a70f55b2af3: + + added p + + diff -r 8a70f55b2af3 -r f3e41d89b3c5 q + --- a/q Thu Jan 01 00:00:00 1970 +0000 + +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +0,0 @@ + -q + +Testing the evolution of a phase-divergent merge with no conflicts +------------------------------------------------------------------ + + $ hg glog -r 154b0179fb9b:: + @ 36:605c306d4f87 phase-divergent update to 8a70f55b2af3: + | () draft + | o 35:f3e41d89b3c5 phase-divergent update to 8a70f55b2af3: + |/ () draft + o 32:8a70f55b2af3 added p and q + | () public + o 31:154b0179fb9b phase-divergent update to 849cee0a874b: + | () public + ~ + + $ echo h > h + $ hg ci -Aqm "added h" + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [36] phase-divergent update to 8a70f55b2af3: + $ echo i > i + $ hg ci -Aqm "added i" + $ hg merge -r ef8c23f37b55 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg ci -m "merge h and i" + + $ hg glog -r 605c306d4f87:: + @ 39:12ebe0d625d7 merge h and i + |\ () draft + | o 38:9bb561db4230 added i + | | () draft + o | 37:ef8c23f37b55 added h + |/ () draft + o 36:605c306d4f87 phase-divergent update to 8a70f55b2af3: + | () draft + ~ + + $ hg up ef8c23f37b55 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg merge -r 9bb561db4230 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg ci -m "merge h and i successor" + created new head + $ hg glog -r 605c306d4f87:: + @ 40:d2aeda868461 merge h and i successor + |\ () draft + +---o 39:12ebe0d625d7 merge h and i + | |/ () draft + | o 38:9bb561db4230 added i + | | () draft + o | 37:ef8c23f37b55 added h + |/ () draft + o 36:605c306d4f87 phase-divergent update to 8a70f55b2af3: + | () draft + ~ + + $ hg prune -r 12ebe0d625d7 --succ . + 1 changesets pruned + + $ hg phase 12ebe0d625d7 --hidden --public + 1 new bumped changesets + +Resolution of phase-divergent merge commit using `hg evolve` + +XXX: we should handle phase-divergent merges + $ hg evolve --phase-divergent + skipping d2aeda868461 : we do not handle merge yet diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-evolve-phase.t --- a/tests/test-evolve-phase.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-evolve-phase.t Mon Apr 23 12:23:00 2018 +0200 @@ -87,7 +87,7 @@ merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') evolve failed! - fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-evolve-stop.t --- a/tests/test-evolve-stop.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-evolve-stop.t Mon Apr 23 12:23:00 2018 +0200 @@ -89,7 +89,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] @@ -137,7 +137,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] @@ -186,7 +186,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] $ echo foo > d @@ -239,7 +239,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] @@ -278,7 +278,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] @@ -356,7 +356,7 @@ 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 + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-evolve-templates.t --- a/tests/test-evolve-templates.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-evolve-templates.t Mon Apr 23 12:23:00 2018 +0200 @@ -19,7 +19,6 @@ > {if(successors, "\n semi-colon: {join(successors, "; ")}")}\ > {if(obsfate, "\n Fate: {join(obsfate, "\n Fate: ")}\n")}\n' > fatelog = log -G -T '{node|short}\n{if(obsfate, " Obsfate: {join(obsfate, "; ")}\n\n")}' - > fatelogjson = log -G -T '{node|short} {obsfate|json}\n' > EOF Test templates on amended commit @@ -249,18 +248,6 @@ o ea207398892e - $ hg fatelogjson --hidden - @ d004c8f274b9 [] - | - | x a468dc9b3633 [{"markers": [["a468dc9b36338b14fdb7825f55ce3df4e71517ad", ["d004c8f274b9ec480a47a93c10dac5eee63adb78"], 0, [["ef1", "1"], ["user", "test2"]], [987654321.0, 0], null]], "max_date": [987654321.0, 0], "min_date": [987654321.0, 0], "successors": ["d004c8f274b9ec480a47a93c10dac5eee63adb78"], "users": ["test2"], "verb": "reworded"}] - |/ - | x f137d23bb3e1 [{"markers": [["f137d23bb3e11dc1daeb6264fac9cb2433782e15", [], 0, [["ef1", "0"], ["user", "test"]], [1234567890.0, 0], ["471f378eab4c5e25f6c77f785b27c936efb22874"]]], "max_date": [1234567890.0, 0], "min_date": [1234567890.0, 0], "successors": [], "users": ["test"], "verb": "pruned"}] - | | - | x 471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"], 0, [["ef1", "9"], ["user", "test"]], [1234567890.0, 0], null]], "max_date": [1234567890.0, 0], "min_date": [1234567890.0, 0], "successors": ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"], "users": ["test"], "verb": "rewritten"}] - |/ - o ea207398892e [] - - Test templates with splitted commit =================================== @@ -417,16 +404,6 @@ o ea207398892e - $ hg fatelogjson --hidden - @ f257fde29c7a [] - | - o 337fec4d2edc [] - | - | x 471597cad322 [{"markers": [["471597cad322d1f659bb169751be9133dad92ef3", ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"], 0, [["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 [] - - Test templates with folded commit ============================== @@ -586,16 +563,6 @@ o ea207398892e - $ hg fatelogjson --hidden - @ eb5a0daa2192 [] - | - | x 0dec01379d3b [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["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, [["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}] - |/ - o ea207398892e [] - - Test templates with divergence ============================== @@ -753,18 +720,6 @@ o ea207398892e - $ hg fatelogjson --hidden - o 019fadeab383 [] - | - | x 65b757b745b9 [{"markers": [["65b757b745b935093c87a2bccd877521cccffcbd", ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"], 0, [["ef1", "1"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"], "users": ["test"], "verb": "reworded"}] - |/ - | @ fdf9bde5129a [] - |/ - | x 471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], 0, [["ef1", "1"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], "users": ["test"], "verb": "reworded"}, {"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["65b757b745b935093c87a2bccd877521cccffcbd"], 0, [["ef1", "1"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["65b757b745b935093c87a2bccd877521cccffcbd"], "users": ["test"], "verb": "reworded"}] - |/ - o ea207398892e [] - - Test templates with amended + folded commit =========================================== @@ -970,17 +925,6 @@ | o ea207398892e - $ hg fatelogjson --hidden - @ eb5a0daa2192 [] - | - | x b7ea6d14e664 [{"markers": [["b7ea6d14e664bdc8922221f7992631b50da3fb07", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["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"], ["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, [["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}] - |/ - o ea207398892e [] - Test template with pushed and pulled obs markers ============================================== @@ -1122,14 +1066,6 @@ | o ea207398892e - - $ hg fatelogjson --hidden - @ 7a230b46bf61 [] - | - | x 471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], 0, [["ef1", "1"], ["user", "test"]], [0.0, 0], null], ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e", ["7a230b46bf61e50b30308c6cfd7bd1269ef54702"], 0, [["ef1", "1"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["7a230b46bf61e50b30308c6cfd7bd1269ef54702"], "users": ["test"], "verb": "reworded"}] - |/ - o ea207398892e [] - Test template with obsmarkers cycle =================================== diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-evolve.t --- a/tests/test-evolve.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-evolve.t Mon Apr 23 12:23:00 2018 +0200 @@ -578,7 +578,7 @@ $ cd .. -Test graft --obsolete/--old-obsolete +Normal testing $ hg init test-graft $ cd test-graft @@ -600,14 +600,16 @@ |/ o 0:8685c6d34325@default(draft) add 0 - $ hg graft -r3 -O - grafting 3:0e84df4912da "add 3" - $ hg graft -r1 -o 2 + $ hg grab -r3 + grabbing 3:0e84df4912da "add 3" + $ hg graft -r1 grafting 1:73d38bb17fd7 "add 1" + $ hg prune -r2 --succ . + 1 changesets pruned $ glog --hidden - @ 6:acb28cd497b7@default(draft) add 1 + @ 6:417185465d2c@default(draft) add 1 | - o 5:0b9e50c35132@default(draft) add 3 + o 5:fa455b5098e0@default(draft) add 3 | o 4:ce341209337f@default(draft) add 4 | @@ -623,36 +625,34 @@ 0e84df4912da4c7cad22a3b4fcfd58ddfb7c8ae9 0b9e50c35132ff548ec0065caea6a87e1ebcef32 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} db038628b9e56f51a454c0da0c508df247b41748 acb28cd497b7f8767e01ef70f68697a959573c2d 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} -Test graft --continue +Test grab --continue $ hg up -qC 0 $ echo 2 > 1 $ hg ci -Am conflict 1 created new head $ hg up -qC 6 - $ hg graft -O 7 - grafting 7:a5bfd90a2f29 "conflict" (tip) + $ hg grab -r 7 + grabbing 7:a5bfd90a2f29 "conflict" merging 1 warning: conflicts while merging 1! (edit, then use 'hg resolve --mark') - abort: unresolved conflicts, can't continue - (use 'hg resolve' and 'hg graft --continue') - [255] + unresolved merge conflicts (see hg help resolve) + [1] $ hg log -r7 --template '{rev}:{node|short} {obsolete}\n' 7:a5bfd90a2f29 $ echo 3 > 1 $ hg resolve -m 1 (no more unresolved files) - continue: hg graft --continue - $ hg graft --continue -O - grafting 7:a5bfd90a2f29 "conflict" (tip) + continue: hg grab --continue + $ hg grab --continue $ glog --hidden - @ 8:920e58bb443b@default(draft) conflict + @ 8:fb2c0f0a0c54@default(draft) conflict | | x 7:a5bfd90a2f29@default(draft) conflict | | - o | 6:acb28cd497b7@default(draft) add 1 + o | 6:417185465d2c@default(draft) add 1 | | - o | 5:0b9e50c35132@default(draft) add 3 + o | 5:fa455b5098e0@default(draft) add 3 | | o | 4:ce341209337f@default(draft) add 4 |/ @@ -672,11 +672,11 @@ Test touch $ glog - @ 8:920e58bb443b@default(draft) conflict + @ 8:fb2c0f0a0c54@default(draft) conflict | - o 6:acb28cd497b7@default(draft) add 1 + o 6:417185465d2c@default(draft) add 1 | - o 5:0b9e50c35132@default(draft) add 3 + o 5:fa455b5098e0@default(draft) add 3 | o 4:ce341209337f@default(draft) add 4 | @@ -688,9 +688,9 @@ $ glog @ 9:*@default(draft) conflict (glob) | - o 6:acb28cd497b7@default(draft) add 1 + o 6:417185465d2c@default(draft) add 1 | - o 5:0b9e50c35132@default(draft) add 3 + o 5:fa455b5098e0@default(draft) add 3 | o 4:ce341209337f@default(draft) add 4 | @@ -702,9 +702,9 @@ $ glog @ 10:*@default(draft) conflict (glob) | - o 6:acb28cd497b7@default(draft) add 1 + o 6:417185465d2c@default(draft) add 1 | - o 5:0b9e50c35132@default(draft) add 3 + o 5:fa455b5098e0@default(draft) add 3 | o 4:ce341209337f@default(draft) add 4 | @@ -1499,7 +1499,7 @@ merging newfile warning: conflicts while merging newfile! (edit, then use 'hg resolve --mark') evolve failed! - fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-fold.t diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-issue-5720.t --- a/tests/test-issue-5720.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-issue-5720.t Mon Apr 23 12:23:00 2018 +0200 @@ -62,7 +62,7 @@ merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') evolve failed! - fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-prune.t diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-stabilize-conflict.t --- a/tests/test-stabilize-conflict.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-stabilize-conflict.t Mon Apr 23 12:23:00 2018 +0200 @@ -129,7 +129,7 @@ merging babar warning: conflicts while merging babar! (edit, then use 'hg resolve --mark') evolve failed! - fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] $ hg resolve -l @@ -223,7 +223,7 @@ was merge successful (yn)? n merging babar failed! evolve failed! - fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] $ hg resolve -l diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-stabilize-order.t --- a/tests/test-stabilize-order.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-stabilize-order.t Mon Apr 23 12:23:00 2018 +0200 @@ -129,7 +129,6 @@ $ hg evolve -v no troubled changesets - [1] Test behavior with --any diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-stabilize-result.t --- a/tests/test-stabilize-result.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-stabilize-result.t Mon Apr 23 12:23:00 2018 +0200 @@ -40,6 +40,8 @@ perform evolve? [Ny] y hg rebase -r cce2c55b8965 -d fb9d051ec0a4 resolving manifests + evolution of 2:cce2c55b8965 created no changes to commit + $ glog --hidden @ 4:fb9d051ec0a4@default(draft) bk:[changea] changea | @@ -83,7 +85,7 @@ merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') evolve failed! - fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + fix conflict and run 'hg evolve --continue' or use 'hg evolve --abort' to abort abort: unresolved merge conflicts (see hg help resolve) [255] $ hg revert -r "orphan()" a @@ -189,13 +191,32 @@ | o 0:07f494440405@default(public) bk:[] adda + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 +0000 + # Node ID 8fc63fe1f297f356d1156bbbbe865b9911efad74 + # Parent 1cf0aacfd36310b18e403e1594871187e0364a82 + phase-divergent update to 1cf0aacfd363: + + newer a + + diff -r 1cf0aacfd363 -r 8fc63fe1f297 a + --- a/a Thu Jan 01 00:00:00 1970 +0000 + +++ b/a Thu Jan 01 00:00:00 1970 +0000 + @@ -1,3 +1,4 @@ + a + a + newer a + +babar Stabilize divergent changesets with same parent =============================================== $ rm a.orig $ hg up 7bc2f5967f5e - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cat << EOF >> a > flore > arthur diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-topic.t --- a/tests/test-topic.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-topic.t Mon Apr 23 12:23:00 2018 +0200 @@ -115,6 +115,24 @@ abort: topic name cannot consist entirely of whitespaces [255] + $ hg topic 'a12#45' + abort: invalid topic name: 'a12#45' + (topic names can only consist of alphanumeric, '-' '_' and '.' characters) + [255] + + $ hg topic 'foo bar' + abort: invalid topic name: 'foo bar' + (topic names can only consist of alphanumeric, '-' '_' and '.' characters) + [255] + +this is trying to list topic names + $ hg topic '' + + $ hg topic '*12 B23' + abort: invalid topic name: '*12 B23' + (topic names can only consist of alphanumeric, '-' '_' and '.' characters) + [255] + Test commit flag and help text $ echo stuff >> alpha diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-userguide.t diff -r 98941c28f3e2 -r a77fb9669e99 tests/test-wireproto.t --- a/tests/test-wireproto.t Wed Mar 21 16:18:31 2018 +0100 +++ b/tests/test-wireproto.t Mon Apr 23 12:23:00 2018 +0200 @@ -191,7 +191,7 @@ $ cat hg.pid >> $DAEMON_PIDS $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon batch branchmap bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Aobsmarkers%3DV0%2CV1%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps changegroupsubset compression=zstd,zlib getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-eol) + _evoext_getbundle_obscommon batch branchmap bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Aobsmarkers%3DV0%2CV1%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps changegroupsubset compression=*zlib getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-eol) (glob) Check we cannot use pushkey for marker exchange anymore