sparse: lock the store when updating requirements config
Differential Revision: https://phab.mercurial-scm.org/D11817
--- a/mercurial/hg.py Tue Nov 16 17:35:57 2021 +0000
+++ b/mercurial/hg.py Mon Nov 29 12:27:33 2021 +0000
@@ -12,6 +12,7 @@
import os
import shutil
import stat
+import weakref
from .i18n import _
from .node import (
@@ -677,7 +678,7 @@
srcpeer = source.peer() # in case we were called with a localrepo
branches = (None, branch or [])
origsource = source = srcpeer.url()
- srclock = destlock = cleandir = None
+ srclock = destlock = destwlock = cleandir = None
destpeer = None
try:
revs, checkout = addbranchrevs(srcpeer, srcpeer, branches, revs)
@@ -865,6 +866,8 @@
requirements=dest_reqs,
)
destrepo = localrepo.makelocalrepository(ui, destrootpath)
+
+ destwlock = destrepo.wlock()
destlock = destrepo.lock()
from . import streamclone # avoid cycle
@@ -873,6 +876,18 @@
# we need to re-init the repo after manually copying the data
# into it
destpeer = peer(srcrepo, peeropts, dest)
+
+ # make the peer aware that is it already locked
+ #
+ # important:
+ #
+ # We still need to release that lock at the end of the function
+ destpeer.local()._lockref = weakref.ref(destlock)
+ destpeer.local()._wlockref = weakref.ref(destwlock)
+ # dirstate also needs to be copied because `_wlockref` has a reference
+ # to it: this dirstate is saved to disk when the wlock is released
+ destpeer.local().dirstate = destrepo.dirstate
+
srcrepo.hook(
b'outgoing', source=b'clone', node=srcrepo.nodeconstants.nullhex
)
@@ -1040,6 +1055,8 @@
bookmarks.activate(destrepo, update)
if destlock is not None:
release(destlock)
+ if destwlock is not None:
+ release(destlock)
# here is a tiny windows were someone could end up writing the
# repository before the cache are sure to be warm. This is "fine"
# as the only "bad" outcome would be some slowness. That potential
@@ -1047,7 +1064,7 @@
with destrepo.lock():
destrepo.updatecaches(caches=repositorymod.CACHES_POST_CLONE)
finally:
- release(srclock, destlock)
+ release(srclock, destlock, destwlock)
if cleandir is not None:
shutil.rmtree(cleandir, True)
if srcpeer is not None:
--- a/mercurial/sparse.py Tue Nov 16 17:35:57 2021 +0000
+++ b/mercurial/sparse.py Mon Nov 29 12:27:33 2021 +0000
@@ -718,7 +718,7 @@
The new config is written out and a working directory refresh is performed.
"""
- with repo.wlock(), repo.dirstate.parentchange():
+ with repo.wlock(), repo.lock(), repo.dirstate.parentchange():
raw = repo.vfs.tryread(b'sparse')
oldinclude, oldexclude, oldprofiles = parseconfig(
repo.ui, raw, b'sparse'
--- a/tests/test-sparse-with-safe-share.t Tue Nov 16 17:35:57 2021 +0000
+++ b/tests/test-sparse-with-safe-share.t Mon Nov 29 12:27:33 2021 +0000
@@ -16,10 +16,8 @@
$ echo x > hide
$ hg ci -Aqm 'initial'
-Verify basic --include
+Regression test: checks that this command correctly locks the store
+before updating the store [requirements] config.
$ hg up -q 0
$ hg debugsparse --include 'hide'
- devel-warn: write with no lock: "requires" at: *mercurial/scmutil.py:1558 (writerequires) (glob)
-
-TODO: bug in sparse when used together with safe-share^