diff -r 5c37a03ccfb3 -r 0f2268783c11 mercurial/localrepo.py --- a/mercurial/localrepo.py Fri Dec 20 16:11:19 2024 +0100 +++ b/mercurial/localrepo.py Thu Jan 30 09:23:16 2025 +0100 @@ -3071,6 +3071,7 @@ releasefn, acquirefn, desc, + steal_from=None, ): timeout = 0 warntimeout = 0 @@ -3083,18 +3084,31 @@ if not sync_file: sync_file = None - l = lockmod.trylock( - self.ui, - vfs, - lockname, - timeout, - warntimeout, - releasefn=releasefn, - acquirefn=acquirefn, - desc=desc, - signalsafe=signalsafe, - devel_wait_sync_file=sync_file, - ) + if steal_from is None: + l = lockmod.trylock( + self.ui, + vfs, + lockname, + timeout, + warntimeout, + releasefn=releasefn, + acquirefn=acquirefn, + desc=desc, + signalsafe=signalsafe, + devel_wait_sync_file=sync_file, + ) + else: + l = lockmod.steal_lock( + self.ui, + vfs, + lockname, + steal_from, + releasefn=releasefn, + acquirefn=acquirefn, + desc=desc, + signalsafe=signalsafe, + ) + return l def _afterlock(self, callback): @@ -3110,19 +3124,29 @@ else: # no lock have been found. callback(True) - def lock(self, wait=True): + def lock(self, wait=True, steal_from=None): """Lock the repository store (.hg/store) and return a weak reference to the lock. Use this before modifying the store (e.g. committing or stripping). If you are opening a transaction, get a lock as well.) If both 'lock' and 'wlock' must be acquired, ensure you always acquires - 'wlock' first to avoid a dead-lock hazard.""" + 'wlock' first to avoid a dead-lock hazard. + + + The steal_from argument is used during local clone when reloading a + repository. If we could remove the need for this during copy clone, we + could remove this function. + """ l = self._currentlock(self._lockref) if l is not None: + if steal_from is not None: + msg = "cannot steal lock if already locked" + raise error.ProgrammingError(msg) l.lock() return l - self.hook(b'prelock', throw=True) + if steal_from is None: + self.hook(b'prelock', throw=True) l = self._lock( vfs=self.svfs, lockname=b"lock", @@ -3130,24 +3154,34 @@ releasefn=None, acquirefn=self.invalidate, desc=_(b'repository %s') % self.origroot, + steal_from=steal_from, ) self._lockref = weakref.ref(l) return l - def wlock(self, wait=True): + def wlock(self, wait=True, steal_from=None): """Lock the non-store parts of the repository (everything under .hg except .hg/store) and return a weak reference to the lock. Use this before modifying files in .hg. If both 'lock' and 'wlock' must be acquired, ensure you always acquires - 'wlock' first to avoid a dead-lock hazard.""" - l = self._wlockref() if self._wlockref else None - if l is not None and l.held: + 'wlock' first to avoid a dead-lock hazard. + + The steal_from argument is used during local clone when reloading a + repository. If we could remove the need for this during copy clone, we + could remove this function. + """ + l = self._currentlock(self._wlockref) + if l is not None: + if steal_from is not None: + msg = "cannot steal wlock if already locked" + raise error.ProgrammingError(msg) l.lock() return l - self.hook(b'prewlock', throw=True) + if steal_from is None: + self.hook(b'prewlock', throw=True) # We do not need to check for non-waiting lock acquisition. Such # acquisition would not cause dead-lock as they would just fail. if wait and ( @@ -3179,6 +3213,7 @@ releasefn=unlock, acquirefn=self.invalidatedirstate, desc=_(b'working directory of %s') % self.origroot, + steal_from=steal_from, ) self._wlockref = weakref.ref(l) return l