diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -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: diff --git a/mercurial/sparse.py b/mercurial/sparse.py --- a/mercurial/sparse.py +++ b/mercurial/sparse.py @@ -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' diff --git a/tests/test-sparse-with-safe-share.t b/tests/test-sparse-with-safe-share.t --- a/tests/test-sparse-with-safe-share.t +++ b/tests/test-sparse-with-safe-share.t @@ -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^