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.
--- 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)