diff mercurial/localrepo.py @ 33437:0720e6265c8a

reposvfs: add a ward to check if locks are properly taken we wrap 'repo.svfs.audit' to check for the store lock when accessing file in '.hg/store' for writing. This caught a couple of instance where the transaction was released after the lock, we should probably have a dedicated checker for that case.
author Boris Feld <boris.feld@octobus.net>
date Mon, 08 Aug 2016 18:14:42 +0200
parents 9bb4decd43b0
children ec306bc6915b
line wrap: on
line diff
--- a/mercurial/localrepo.py	Tue Jul 11 12:38:17 2017 +0200
+++ b/mercurial/localrepo.py	Mon Aug 08 18:14:42 2016 +0200
@@ -423,6 +423,12 @@
         self.svfs = self.store.vfs
         self.sjoin = self.store.join
         self.vfs.createmode = self.store.createmode
+        if (self.ui.configbool('devel', 'all-warnings') or
+            self.ui.configbool('devel', 'check-locks')):
+            if util.safehasattr(self.svfs, 'vfs'): # this is filtervfs
+                self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit)
+            else: # standard vfs
+                self.svfs.audit = self._getsvfsward(self.svfs.audit)
         self._applyopenerreqs()
         if create:
             self._writerequirements()
@@ -496,6 +502,25 @@
             return ret
         return checkvfs
 
+    def _getsvfsward(self, origfunc):
+        """build a ward for self.svfs"""
+        rref = weakref.ref(self)
+        def checksvfs(path, mode=None):
+            ret = origfunc(path, mode=mode)
+            repo = rref()
+            if repo is None or not util.safehasattr(repo, '_lockref'):
+                return
+            if mode in (None, 'r', 'rb'):
+                return
+            if path.startswith(repo.sharedpath):
+                # truncate name relative to the repository (.hg)
+                path = path[len(repo.sharedpath) + 1:]
+            if repo._currentlock(repo._lockref) is None:
+                repo.ui.develwarn('write with no lock: "%s"' % path,
+                                  stacklevel=3)
+            return ret
+        return checksvfs
+
     def close(self):
         self._writecaches()