[PATCH 2 of 3] backout: avoid update on simple case

pierre-yves.david at ens-lyon.org pierre-yves.david at ens-lyon.org
Wed Jan 8 19:40:16 CST 2014


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at fb.com>
# Date 1389221626 28800
#      Wed Jan 08 14:53:46 2014 -0800
# Node ID 693ba13bf57b3654617cc77e485df7f68235227b
# Parent  c1b82a66191b13a66df0d1708f0b4f4a4d2c2cfd
backout: avoid update on simple case.

Before the changeset the backout process was:
1) go to <target>
2) revert to <target> parent
3) update back to changeset we came from

The two update steps can takes a very long time to move back and forth unrelated
file change between <target> and current working directory.

The new process is just merging current working directory with the parent of
<target> using <target> as ancestor. This give the very same result but skip
the two updates. On big repo with a lot of files and changes that save a lots of
time (x20 for one week window).

The "merge" version (hg backout --merge) is still done with upgrades. We could
imagine using in memory commit to speed it up but this is another fish.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -459,20 +459,27 @@ def backout(ui, repo, node=None, rev=Non
     # the backout should appear on the same branch
     wlock = repo.wlock()
     try:
         branch = repo.dirstate.branch()
         bheads = repo.branchheads(branch)
-        hg.clean(repo, node, show_stats=False)
-        repo.dirstate.setbranch(branch)
         rctx = scmutil.revsingle(repo, hex(parent))
-        cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
         if not opts.get('merge') and op1 != node:
             try:
                 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
-                return hg.update(repo, op1)
+                stats = mergemod.update(repo, parent, True, True, False, node, False)
+                repo.setparents(op1, op2)
+                hg._showstats(repo, stats)
+                if stats[3]:
+                    repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
+                return stats[3] > 0
             finally:
                 ui.setconfig('ui', 'forcemerge', '')
+        else:
+            hg.clean(repo, node, show_stats=False)
+            repo.dirstate.setbranch(branch)
+            cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
+
 
         e = cmdutil.commiteditor
         if not opts['message'] and not opts['logfile']:
             # we don't translate commit messages
             opts['message'] = "Backed out changeset %s" % short(node)
diff --git a/tests/test-backout.t b/tests/test-backout.t
--- a/tests/test-backout.t
+++ b/tests/test-backout.t
@@ -186,11 +186,10 @@ backout should not back out subsequent c
   commit: (clean)
   update: (current)
 
 without --merge
   $ hg backout -d '3 0' 1 --tool=true
-  reverting a
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg locate b
   b
   $ hg update -C tip
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -322,12 +321,11 @@ named branches
   $ hg ci -d '2 0' -Am file2
   adding file2
 
 without --merge
   $ hg backout -r 1 --tool=true
-  removing file1
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg branch
   branch2
   $ hg status -A
   R file1
   C default
diff --git a/tests/test-subrepo.t b/tests/test-subrepo.t
--- a/tests/test-subrepo.t
+++ b/tests/test-subrepo.t
@@ -466,15 +466,10 @@ update
 
 backout calls revert internally with minimal opts, which should not raise
 KeyError
 
   $ hg backout ".^"
-  reverting .hgsubstate
-  reverting subrepo s
-  reverting s/a (glob)
-  reverting subrepo ss
-  reverting subrepo t
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ hg up -C # discard changes
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 


More information about the Mercurial-devel mailing list