largefile: make sure we hold the lock when updating the second dirstate
authorPierre-Yves David <pierre-yves.david@octobus.net>
Fri, 27 Jan 2023 00:45:07 +0100
changeset 49964 0cf4c1b80fd9
parent 49963 f979d8af8648
child 49965 380ed77e9ad3
largefile: make sure we hold the lock when updating the second dirstate The largefile extension uses a second dirstate file (and object) to track some states. In some situations, it is lazily updated when needed. These operations might not have the lock taken. This means they might conflict and race with other ongoing operations. So we now take the lock to do these operations. This was caught by the next commit.
hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py	Thu Jan 26 15:19:39 2023 +0100
+++ b/hgext/largefiles/lfutil.py	Fri Jan 27 00:45:07 2023 +0100
@@ -223,20 +223,30 @@
     # it. This ensures that we create it on the first meaningful
     # largefiles operation in a new clone.
     if create and not vfs.exists(vfs.join(lfstoredir, b'dirstate')):
-        matcher = getstandinmatcher(repo)
-        standins = repo.dirstate.walk(
-            matcher, subrepos=[], unknown=False, ignored=False
-        )
+        try:
+            with repo.wlock(wait=False):
+                matcher = getstandinmatcher(repo)
+                standins = repo.dirstate.walk(
+                    matcher, subrepos=[], unknown=False, ignored=False
+                )
+
+                if len(standins) > 0:
+                    vfs.makedirs(lfstoredir)
 
-        if len(standins) > 0:
-            vfs.makedirs(lfstoredir)
-
-        with lfdirstate.changing_parents(repo):
-            for standin in standins:
-                lfile = splitstandin(standin)
-                lfdirstate.update_file(
-                    lfile, p1_tracked=True, wc_tracked=True, possibly_dirty=True
-                )
+                with lfdirstate.changing_parents(repo):
+                    for standin in standins:
+                        lfile = splitstandin(standin)
+                        lfdirstate.update_file(
+                            lfile,
+                            p1_tracked=True,
+                            wc_tracked=True,
+                            possibly_dirty=True,
+                        )
+        except error.LockError:
+            # Assume that whatever was holding the lock was important.
+            # If we were doing something important, we would already have
+            # either the lock or a largefile dirstate.
+            pass
     return lfdirstate