changeset 49965:0cf4c1b80fd9

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.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Fri, 27 Jan 2023 00:45:07 +0100
parents f979d8af8648
children 380ed77e9ad3
files hgext/largefiles/lfutil.py
diffstat 1 files changed, 23 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- 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