changeset 50027:0b4a6912292e

largefiles: link the core dirstate._changing context to the lfdirstate one This will be much cleaner and safer to make sure the two dirstates are in sync. This way, the large-files dirstate will simply inherit the state of the main dirstate, so if the core code does the right thing, the large-files code should be right too.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 15 Feb 2023 10:46:46 +0100
parents 3550e4a88ccd
children a46dfc2b58a3
files hgext/largefiles/lfutil.py hgext/largefiles/overrides.py
diffstat 2 files changed, 31 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/largefiles/lfutil.py	Thu Jan 26 17:44:27 2023 +0100
+++ b/hgext/largefiles/lfutil.py	Wed Feb 15 10:46:46 2023 +0100
@@ -159,6 +159,8 @@
 
 
 class largefilesdirstate(dirstate.dirstate):
+    _large_file_dirstate = True
+
     def __getitem__(self, key):
         return super(largefilesdirstate, self).__getitem__(unixpath(key))
 
@@ -204,7 +206,13 @@
     """
     Return a dirstate object that tracks largefiles: i.e. its root is
     the repo root, but it is saved in .hg/largefiles/dirstate.
+
+    If a dirstate object already exists and is being used for a 'changing_*'
+    context, it will be returned.
     """
+    sub_dirstate = getattr(repo.dirstate, '_sub_dirstate', None)
+    if sub_dirstate is not None:
+        return sub_dirstate
     vfs = repo.vfs
     lfstoredir = longname
     opener = vfsmod.vfs(vfs.join(lfstoredir))
--- a/hgext/largefiles/overrides.py	Thu Jan 26 17:44:27 2023 +0100
+++ b/hgext/largefiles/overrides.py	Wed Feb 15 10:46:46 2023 +0100
@@ -8,6 +8,7 @@
 
 '''Overridden Mercurial commands and functions for the largefiles extension'''
 
+import contextlib
 import copy
 import os
 
@@ -21,6 +22,7 @@
     archival,
     cmdutil,
     copies as copiesmod,
+    dirstate,
     error,
     exchange,
     extensions,
@@ -311,6 +313,27 @@
     )
 
 
+@eh.wrapfunction(dirstate.dirstate, b'_changing')
+@contextlib.contextmanager
+def _changing(orig, self, repo, change_type):
+    pre = sub_dirstate = getattr(self, '_sub_dirstate', None)
+    try:
+        lfd = getattr(self, '_large_file_dirstate', False)
+        if sub_dirstate is None and not lfd:
+            sub_dirstate = lfutil.openlfdirstate(repo.ui, repo)
+            self._sub_dirstate = sub_dirstate
+        if not lfd:
+            assert self._sub_dirstate is not None
+        with orig(self, repo, change_type):
+            if sub_dirstate is None:
+                yield
+            else:
+                with sub_dirstate._changing(repo, change_type):
+                    yield
+    finally:
+        self._sub_dirstate = pre
+
+
 @eh.wrapfunction(subrepo.hgsubrepo, b'status')
 def overridestatusfn(orig, repo, rev2, **opts):
     with lfstatus(repo._repo):