sparse: take lock before writing requirements
with `share-safe`, we will also write file in the store. So we take the `lock`
before altering the requirements.
Differential Revision: https://phab.mercurial-scm.org/D11993
--- a/mercurial/sparse.py Fri Jan 07 16:30:11 2022 +0100
+++ b/mercurial/sparse.py Tue Jan 11 06:40:44 2022 +0100
@@ -600,38 +600,41 @@
repo, includes, excludes, profiles, force=False, removing=False
):
"""Update the sparse config and working directory state."""
- raw = repo.vfs.tryread(b'sparse')
- oldincludes, oldexcludes, oldprofiles = parseconfig(repo.ui, raw, b'sparse')
-
- oldstatus = repo.status()
- oldmatch = matcher(repo)
- oldrequires = set(repo.requirements)
+ with repo.lock():
+ raw = repo.vfs.tryread(b'sparse')
+ oldincludes, oldexcludes, oldprofiles = parseconfig(
+ repo.ui, raw, b'sparse'
+ )
- # TODO remove this try..except once the matcher integrates better
- # with dirstate. We currently have to write the updated config
- # because that will invalidate the matcher cache and force a
- # re-read. We ideally want to update the cached matcher on the
- # repo instance then flush the new config to disk once wdir is
- # updated. But this requires massive rework to matcher() and its
- # consumers.
+ oldstatus = repo.status()
+ oldmatch = matcher(repo)
+ oldrequires = set(repo.requirements)
+
+ # TODO remove this try..except once the matcher integrates better
+ # with dirstate. We currently have to write the updated config
+ # because that will invalidate the matcher cache and force a
+ # re-read. We ideally want to update the cached matcher on the
+ # repo instance then flush the new config to disk once wdir is
+ # updated. But this requires massive rework to matcher() and its
+ # consumers.
- if requirements.SPARSE_REQUIREMENT in oldrequires and removing:
- repo.requirements.discard(requirements.SPARSE_REQUIREMENT)
- scmutil.writereporequirements(repo)
- elif requirements.SPARSE_REQUIREMENT not in oldrequires:
- repo.requirements.add(requirements.SPARSE_REQUIREMENT)
- scmutil.writereporequirements(repo)
+ if requirements.SPARSE_REQUIREMENT in oldrequires and removing:
+ repo.requirements.discard(requirements.SPARSE_REQUIREMENT)
+ scmutil.writereporequirements(repo)
+ elif requirements.SPARSE_REQUIREMENT not in oldrequires:
+ repo.requirements.add(requirements.SPARSE_REQUIREMENT)
+ scmutil.writereporequirements(repo)
- try:
- writeconfig(repo, includes, excludes, profiles)
- return refreshwdir(repo, oldstatus, oldmatch, force=force)
- except Exception:
- if repo.requirements != oldrequires:
- repo.requirements.clear()
- repo.requirements |= oldrequires
- scmutil.writereporequirements(repo)
- writeconfig(repo, oldincludes, oldexcludes, oldprofiles)
- raise
+ try:
+ writeconfig(repo, includes, excludes, profiles)
+ return refreshwdir(repo, oldstatus, oldmatch, force=force)
+ except Exception:
+ if repo.requirements != oldrequires:
+ repo.requirements.clear()
+ repo.requirements |= oldrequires
+ scmutil.writereporequirements(repo)
+ writeconfig(repo, oldincludes, oldexcludes, oldprofiles)
+ raise
def clearrules(repo, force=False):