D7492: localrepo: also fastpath access to working copy parents when possible

Alphare (Raphaël Gomès) phabricator at mercurial-scm.org
Thu Jan 16 09:26:50 EST 2020


Alphare updated this revision to Diff 19361.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D7492?vs=18382&id=19361

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7492/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7492

AFFECTED FILES
  mercurial/context.py
  mercurial/localrepo.py
  mercurial/scmutil.py
  tests/test-repo-filters-tiptoe.t

CHANGE DETAILS

diff --git a/tests/test-repo-filters-tiptoe.t b/tests/test-repo-filters-tiptoe.t
--- a/tests/test-repo-filters-tiptoe.t
+++ b/tests/test-repo-filters-tiptoe.t
@@ -62,7 +62,6 @@
 Getting status of working copy
 
   $ hg status
-  debug.filters: computing revision filter for "visible"
   M c
   A d
   R a
@@ -78,7 +77,6 @@
 Getting working copy diff
 
   $ hg diff
-  debug.filters: computing revision filter for "visible"
   diff -r c2932ca7786be30b67154d541a8764fae5532261 a
   --- a/a	Thu Jan 01 00:00:00 1970 +0000
   +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -1466,6 +1466,7 @@
         if src not in newctx or dst in newctx or ds[dst] != b'a':
             src = None
         ds.copy(src, dst)
+    repo._quick_access_changeid_invalidate()
 
 
 def writerequires(opener, requirements):
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1517,18 +1517,51 @@
         narrowspec.save(self, newincludes, newexcludes)
         self.invalidate(clearfilecache=True)
 
-    @util.propertycache
+    @unfilteredpropertycache
+    def _quick_access_changeid_null(self):
+        return {
+            b'null': (nullrev, nullid),
+            nullrev: (nullrev, nullid),
+            nullid: (nullrev, nullid),
+        }
+
+    @unfilteredpropertycache
+    def _quick_access_changeid_wc(self):
+        # also fast path access to the working copy parents
+        # however, only do it for filter that ensure wc is visible.
+        quick = {}
+        cl = self.unfiltered().changelog
+        for node in self.dirstate.parents():
+            if node == nullid:
+                continue
+            rev = cl.index.get_rev(node)
+            if rev is None:
+                # unknown working copy parent case:
+                #
+                #   skip the fast path and let higher code deal with it
+                continue
+            pair = (rev, node)
+            quick[rev] = pair
+            quick[node] = pair
+        return quick
+
+    @unfilteredmethod
+    def _quick_access_changeid_invalidate(self):
+        if '_quick_access_changeid_wc' in vars(self):
+            del self.__dict__['_quick_access_changeid_wc']
+
+    @property
     def _quick_access_changeid(self):
         """an helper dictionnary for __getitem__ calls
 
         This contains a list of symbol we can recognise right away without
         further processing.
         """
-        return {
-            b'null': (nullrev, nullid),
-            nullrev: (nullrev, nullid),
-            nullid: (nullrev, nullid),
-        }
+        mapping = self._quick_access_changeid_null
+        if self.filtername in repoview.filter_has_wc:
+            mapping = mapping.copy()
+            mapping.update(self._quick_access_changeid_wc)
+        return mapping
 
     def __getitem__(self, changeid):
         # dealing with special cases
@@ -1887,6 +1920,7 @@
 
     def setparents(self, p1, p2=nullid):
         self[None].setparents(p1, p2)
+        self._quick_access_changeid_invalidate()
 
     def filectx(self, path, changeid=None, fileid=None, changectx=None):
         """changeid must be a changeset revision, if specified.
@@ -2484,6 +2518,7 @@
     def invalidatevolatilesets(self):
         self.filteredrevcache.clear()
         obsolete.clearobscaches(self)
+        self._quick_access_changeid_invalidate()
 
     def invalidatedirstate(self):
         '''Invalidates the dirstate, causing the next call to dirstate
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -1989,6 +1989,7 @@
             for f in self.removed():
                 self._repo.dirstate.drop(f)
             self._repo.dirstate.setparents(node)
+            self._repo._quick_access_changeid_invalidate()
 
         # write changes out explicitly, because nesting wlock at
         # runtime may prevent 'wlock.release()' in 'repo.commit()'



To: marmoute, #hg-reviewers
Cc: pulkit, martinvonz, mercurial-devel


More information about the Mercurial-devel mailing list