[PATCH 1 of 1 DRAFT] blackblox extension to help with debugging
Nicolas Dumazet
nicdumz at gmail.com
Tue Oct 19 04:36:32 CDT 2010
# HG changeset patch
# User Nicolas Dumazet <nicdumz.commits at gmail.com>
# Date 1287388636 -32400
# Node ID 9e9d0137348c7841e416c29ff71af6ddafbfb8d0
# Parent d10369fefd01f165f76263d9b92423ae018b84bc
blackblox extension to help with debugging
diff --git a/hgext/blackbox.py b/hgext/blackbox.py
new file mode 100644
--- /dev/null
+++ b/hgext/blackbox.py
@@ -0,0 +1,74 @@
+"""log repository events to help debugging
+
+Appends to .hg/blackbox events happening in the repository to help
+debugging and diagnosis. So far, this blackbox will track:
+ - hg commands and their return codes
+ - tracebacks
+ - hooks
+ - incoming changesets
+"""
+
+from mercurial import dispatch, extensions, hook, util
+import os, traceback
+
+def wrapui(ui, repo):
+ class blackboxui(ui.__class__):
+ @util.propertycache
+ def _blackbox(self):
+ introduction = not os.path.exists(repo.join('blackbox'))
+ blackbox = repo.opener('blackbox', 'a')
+ if introduction:
+ blackbox.write(
+"""
+blackbox extension logs here hg events to help diagnosing errors.
+You can truncate or delete this file, or include parts of the log
+in bug reports on http://mercurial.selenic.com/bts/
+
+""")
+ blackbox.write(util.datestr() + '\n')
+ return blackbox
+
+ def blackbox(self, msg):
+ self._blackbox.write(' %s\n' % msg)
+
+ ui.__class__ = blackboxui
+
+def runcommand(orig, lui, repo, cmd, fullargs, *args, **kwargs):
+ if repo is None:
+ # not much we can log
+ return orig(lui, repo, cmd, fullargs, *args, **kwargs)
+
+ wrapui(lui, repo)
+
+ lui.blackbox(' '.join(fullargs))
+ try:
+ ret = orig(lui, repo, cmd, fullargs, *args, **kwargs)
+ if ret:
+ lui._blackbox.write(' [%d]\n' % ret)
+ return ret
+ except:
+ traceback.print_exc(None, lui._blackbox)
+ raise
+
+def exthook(orig, ui, repo, name, cmd, *args, **kw):
+ if repo:
+ ui.blackbox('exthook: %s: %s' % (name, cmd))
+ return orig(ui, repo, name, cmd, *args, **kw)
+def pythonhook(orig, ui, repo, name, hname, funcname, *args, **kw):
+ if repo and not hname.endswith('.blackbox'):
+ ui.blackbox('pythonhook: %s: %s' % (hname, funcname))
+ return orig(ui, repo, name, hname, funcname, *args, **kw)
+
+def uisetup(ui):
+ extensions.wrapfunction(dispatch, 'runcommand', runcommand)
+ extensions.wrapfunction(hook, '_exthook', exthook)
+ extensions.wrapfunction(hook, '_pythonhook', pythonhook)
+
+def reposetup(ui, repo):
+ if not repo.local():
+ return
+
+ wrapui(ui, repo)
+ def incoming(ui, repo, hooktype, node, source, url):
+ ui.blackbox('incoming: %s: %s from %s' % (source, node[:12], url))
+ ui.setconfig('hooks', 'incoming.blackbox', incoming)
diff --git a/tests/test-blackbox.t b/tests/test-blackbox.t
new file mode 100644
--- /dev/null
+++ b/tests/test-blackbox.t
@@ -0,0 +1,97 @@
+ $ echo '[extensions]' >> $HGRCPATH
+ $ echo 'blackbox =' >> $HGRCPATH
+
+ $ blackbox() {
+ > # trash the header
+ > tail --lines=+6 .hg/blackbox
+ > }
+
+== Non-zero exit codes / header ==
+
+ $ hg init empty; cd empty
+ $ hg log
+ $ hg add empty
+ empty: No such file or directory
+ [1]
+ $ cat .hg/blackbox
+
+ blackbox extension logs here hg events to help diagnosing errors.
+ You can truncate or delete this file, or include parts of the log
+ in bug reports on http://mercurial.selenic.com/bts/
+
+ * (glob)
+ log
+ * (glob)
+ add empty
+ [1]
+
+== Logging hooks ==
+
+ $ rm .hg/blackbox
+ $ hg --config "hooks.pre-log.foo=echo 'hook'" log
+ hook
+ $ blackbox
+ * (glob)
+ log
+ exthook: pre-log.foo: echo 'hook'
+ $ cd ..
+
+== Incoming changesets ==
+
+Create a repo with a dummy changeset
+
+ $ hg init foo; cd foo
+ $ touch a
+ $ hg ci -Am'a'
+ adding a
+ $ hg clone . ../remote
+ updating to branch default
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+And pretend we push to remote a new changeset
+
+ $ echo foo > a
+ $ hg ci -Am'modify a'
+ $ hg push ../remote
+ pushing to ../remote
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 1 changes to 1 files
+
+And check that the incoming operation was recorded
+
+ $ cd ../remote
+ $ blackbox
+ * (glob)
+ incoming: push: c3cdbe7bbdc4 from file:$TESTTMP/foo
+
+== Tracebacks ==
+
+ $ rm .hg/blackbox
+ $ hg diff -c notexisting
+ abort: unknown revision 'notexisting'!
+ [255]
+ $ blackbox
+ * (glob)
+ diff -c notexisting
+ Traceback (most recent call last):
+ File "*/hgext/blackbox.py", line *, in runcommand (glob)
+ ret = orig(lui, repo, cmd, fullargs, *args, **kwargs)
+ File "*/mercurial/dispatch.py", line *, in runcommand (glob)
+ ret = _runcommand(ui, options, cmd, d)
+ File "*/mercurial/dispatch.py", line *, in _runcommand (glob)
+ return checkargs()
+ File "*/mercurial/dispatch.py", line *, in checkargs (glob)
+ return cmdfunc()
+ File "*/mercurial/dispatch.py", line *, in <lambda> (glob)
+ d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
+ File "*/mercurial/util.py", line *, in check (glob)
+ return func(*args, **kwargs)
+ File "*/mercurial/commands.py", line *, in diff (glob)
+ node2 = repo.lookup(change)
+ File "*/mercurial/localrepo.py", line *, in lookup (glob)
+ raise error.RepoLookupError(_("unknown revision '%s'") % key)
+ RepoLookupError: unknown revision 'notexisting'
+
More information about the Mercurial-devel
mailing list