# HG changeset patch # User Pierre-Yves David # Date 2023-01-26 23:45:07 # Node ID 0cf4c1b80fd9d924cb8145b1565923f652771aab # Parent f979d8af86489c39939752bb9211b43efa67882c 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. diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py --- a/hgext/largefiles/lfutil.py +++ b/hgext/largefiles/lfutil.py @@ -223,20 +223,30 @@ def openlfdirstate(ui, repo, create=True # 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