diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -6154,6 +6154,7 @@ [('C', 'clean', None, _('discard uncommitted changes (no backup)')), ('c', 'check', None, _('require clean working directory')), ('m', 'merge', None, _('merge uncommitted changes')), + ('', 'abort', False, _('abort interrupted update')), ('d', 'date', '', _('tipmost revision matching date'), _('DATE')), ('r', 'rev', '', _('revision'), _('REV')) ] + mergetoolopts, @@ -6220,6 +6221,7 @@ clean = opts.get(r'clean') check = opts.get(r'check') merge = opts.get(r'merge') + abort = opts.get(r'abort') if rev and node: raise error.Abort(_("please specify just one revision")) @@ -6245,6 +6247,8 @@ updatecheck = 'none' with repo.wlock(): + if abort: + return hg.abortupdate(ui, repo) cmdutil.clearunfinished(repo) if date: rev = cmdutil.finddate(ui, repo, date) diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -984,6 +984,34 @@ _showstats(repo, stats) return stats.unresolvedcount > 0 +def _unmarkandresolvelocal(ui, repo , ms): + """Helper for abortupdate(). This unmarks partially resolved files and then + resolves the update generated conflicts.""" + wctx = repo[None] + for f in ms: + ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH) + ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED) + try: + overrides = {('ui', 'forcemerge'): ':local'} + with ui.configoverride(overrides, 'resolve'): + ms.preresolve(f, wctx) + ms.resolve(f, wctx) + finally: + ms.commit() + +def abortupdate(ui, repo): + """logic to abort an conflicted update""" + ms = mergemod.mergestate.read(repo) + node = ms.localctx.hex() + _unmarkandresolvelocal(ui, repo, ms) + repo.ui.status(_("aborting the update, updating back to" + " %s\n") % node[:12]) + mergemod.update(repo, node, branchmerge=False, force=False) + ms2 = mergemod.mergestate.read(repo) + _unmarkandresolvelocal(ui, repo, ms2) + ui.status(_("update aborted\n")) + ui.status(_("working directory is now at %s\n") % node[:12]) + def _incoming(displaychlist, subreporecurse, ui, repo, source, opts, buffered=False): """ diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t --- a/tests/test-merge-tools.t +++ b/tests/test-merge-tools.t @@ -4,6 +4,8 @@ $ cat >> $HGRCPATH << EOF > [ui] > merge= + > [extensions] + > graphlog= > EOF $ hg init repo $ cd repo @@ -2086,3 +2088,63 @@ f = false $ cd .. + +Test for 'hg update --abort' + + $ hg init test + $ cd test + $ echo before > file + $ hg add file + $ hg commit -mbefore + $ echo after > file + $ hg commit -mafter + $ echo edited > file + +Pre-update log and file content + $ hg glog + @ changeset: 1:47d1da7c1f80 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: after + | + o changeset: 0:dd67ebc4de84 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: before + + + $ cat file + edited + $ hg update 0 + merging file + warning: conflicts while merging file! (edit, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges + [1] + + $ hg update --abort + aborting the update, updating back to 47d1da7c1f80 + merging file + warning: conflicts while merging file! (edit, then use 'hg resolve --mark') + update aborted + working directory is now at 47d1da7c1f80 + +Post-update log and file content + $ hg glog + @ changeset: 1:47d1da7c1f80 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: after + | + o changeset: 0:dd67ebc4de84 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: before + + + $ cat file + edited + + $ cd ..