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