changeset 17669:405b5f8fdad7

lock-checker: new contrib extension based on work done by Mads This makes it possible to do lock validation as part of a normal test run. I didn't attempt any wlock validation because that's a bit more subtle to detect properly. Thanks to the initial patch from Mads for the idea.
author Augie Fackler <raf@durin42.com>
date Wed, 01 Aug 2012 22:13:27 -0500
parents 28c43957f8b4
children 9dbd5fa6d301
files contrib/lock-checker.py
diffstat 1 files changed, 48 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/lock-checker.py	Wed Aug 01 22:13:27 2012 -0500
@@ -0,0 +1,48 @@
+"""Extension to verify locks are obtained in the required places.
+
+This works by wrapping functions that should be surrounded by a lock
+and asserting the lock is held. Missing locks are called out with a
+traceback printed to stderr.
+
+This currently only checks store locks, not working copy locks.
+"""
+import os
+import traceback
+
+def _warnstack(ui, msg, skip=1):
+    '''issue warning with the message and the current stack, skipping the
+    skip last entries'''
+    ui.warn('%s at:\n' % msg)
+    entries = traceback.extract_stack()[:-skip]
+    fnmax = max(len(entry[0]) for entry in entries)
+    for fn, ln, func, _text in entries:
+        ui.warn(' %*s:%-4s in %s\n' % (fnmax, fn, ln, func))
+
+def _checklock(repo):
+    l = repo._lockref and repo._lockref()
+    if l is None or not l.held:
+        _warnstack(repo.ui, 'missing lock', skip=2)
+
+def reposetup(ui, repo):
+    orig = repo.__class__
+    class lockcheckrepo(repo.__class__):
+        def _writejournal(self, *args, **kwargs):
+            _checklock(self)
+            return orig._writejournal(self, *args, **kwargs)
+
+        def transaction(self, *args, **kwargs):
+            _checklock(self)
+            return orig.transaction(self, *args, **kwargs)
+
+        # TODO(durin42): kiilerix had a commented-out lock check in
+        # writebranchcache and _writerequirements
+
+        def _tag(self, *args, **kwargs):
+            _checklock(self)
+            return orig._tag(self, *args, **kwargs)
+
+        def write(self, *args, **kwargs):
+            assert os.path.lexists(self._join('.hg/wlock'))
+            return orig.write(self, *args, **kwargs)
+
+    repo.__class__ = lockcheckrepo