[PATCH 2 of 2] revert: special case 'hg revert --all'

Durham Goode durham at fb.com
Fri Sep 19 20:55:33 CDT 2014


On 9/19/14, 6:53 PM, Durham Goode wrote:
> # HG changeset patch
> # User Durham Goode <durham at fb.com>
> # Date 1411177433 25200
> #      Fri Sep 19 18:43:53 2014 -0700
> # Node ID 4ba21a38b9dc7d351e88cc575516443046f6d913
> # Parent  b74b7d5f46d5d8ad13ca74e6b740970129090529
> revert: special case 'hg revert --all'
>
> On large repos, hg revert --all can take over 13 seconds. This is mainly due to
> it walking the tree three times: once to find the list of files in the
> dirstate, once to find the list of files in the target, and once to compute the
> status from the dirstate to the target.
>
> This optimizes the hg revert --all case to only require the final status. This
> speeds it up to 1.3 seconds or so (with hgwatchman enabled).
>
> Further optimizations could be done for the -r NODE and pattern cases, but they
> are significantly more complex.
>
This last patch looks big, but 'hg diff -w' shows you it's pretty tiny.

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -2480,6 +2480,7 @@
          # walk dirstate to fill `names`

          m = scmutil.match(repo[None], pats, opts)
+        if not m.always() or node != parent:
          m.bad = lambda x, y: False
          for abs in repo.walk(m):
              names[abs] = m.rel(abs), m.exact(abs)
@@ -2508,6 +2509,14 @@

          changes = repo.status(node1=node, match=m,
                                unknown=True, ignored=True, clean=True)
+        else:
+            changes = repo.status(match=m)
+            for kind in changes:
+                for abs in kind:
+                    names[abs] = m.rel(abs), m.exact(abs)
+
+            m = scmutil.matchfiles(repo, names)
+
          modified = set(changes[0])
          added    = set(changes[1])
          removed  = set(changes[2])


More information about the Mercurial-devel mailing list