mercurial/localrepo.py
changeset 52725 0f2268783c11
parent 52724 5c37a03ccfb3
child 52838 e52dc683bf6b
--- 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