dirstate: only reload the dirstate when it may have changed
authorPierre-Yves David <pierre-yves.david@octobus.net>
Wed, 22 Feb 2023 01:08:25 +0100
changeset 50177 2f60cd6442fd
parent 50176 ec769cbc1fa2
child 50178 3c6546b149ed
dirstate: only reload the dirstate when it may have changed This reinstall the equivalent of what the `filecache` was doing. However it does it at the dirstate level. There is a double motivation for this: - This avoid duplicating logic with the dirstate "identity" logic. - This increase the lifetime of the `dirstate` object, helping to implement change scoping.
mercurial/dirstate.py
mercurial/dirstatemap.py
mercurial/localrepo.py
mercurial/statichttprepo.py
--- a/mercurial/dirstate.py	Wed Feb 22 01:04:55 2023 +0100
+++ b/mercurial/dirstate.py	Wed Feb 22 01:08:25 2023 +0100
@@ -190,6 +190,12 @@
         # raises an exception).
         self._cwd
 
+    def refresh(self):
+        if '_branch' in vars(self):
+            del self._branch
+        if '_map' in vars(self) and self._map.may_need_refresh():
+            self.invalidate()
+
     def prefetch_parents(self):
         """make sure the parents are loaded
 
--- a/mercurial/dirstatemap.py	Wed Feb 22 01:04:55 2023 +0100
+++ b/mercurial/dirstatemap.py	Wed Feb 22 01:08:25 2023 +0100
@@ -67,6 +67,25 @@
         except FileNotFoundError:
             return None
 
+    def may_need_refresh(self):
+        if 'identity' not in vars(self):
+            # no existing identity, we need a refresh
+            return True
+        if self.identity is None:
+            return True
+        if not self.identity.cacheable():
+            # We cannot trust the entry
+            # XXX this is a problem on windows, NFS, or other inode less system
+            return True
+        current_identity = self._get_current_identity()
+        if current_identity is None:
+            return True
+        if not current_identity.cacheable():
+            # We cannot trust the entry
+            # XXX this is a problem on windows, NFS, or other inode less system
+            return True
+        return current_identity != self.identity
+
     def preload(self):
         """Loads the underlying data, if it's not already loaded"""
         self._map
--- a/mercurial/localrepo.py	Wed Feb 22 01:04:55 2023 +0100
+++ b/mercurial/localrepo.py	Wed Feb 22 01:08:25 2023 +0100
@@ -1465,6 +1465,7 @@
         # - bookmark changes
         self.filteredrevcache = {}
 
+        self._dirstate = None
         # post-dirstate-status hooks
         self._postdsstatus = []
 
@@ -1752,9 +1753,11 @@
 
     @unfilteredpropertycache
     def dirstate(self):
-        # XXX This is known to be missing smarter caching. Check the next
-        # changesets
-        return self._makedirstate()
+        if self._dirstate is None:
+            self._dirstate = self._makedirstate()
+        else:
+            self._dirstate.refresh()
+        return self._dirstate
 
     def _makedirstate(self):
         """Extension point for wrapping the dirstate per-repo."""
--- a/mercurial/statichttprepo.py	Wed Feb 22 01:04:55 2023 +0100
+++ b/mercurial/statichttprepo.py	Wed Feb 22 01:08:25 2023 +0100
@@ -225,6 +225,7 @@
         self.encodepats = None
         self.decodepats = None
         self._transref = None
+        self._dirstate = None
 
     def _restrictcapabilities(self, caps):
         caps = super(statichttprepository, self)._restrictcapabilities(caps)