rendered paste body# HG changeset patch# User Nicolas Dumazet <nicdumz.commits@gmail.com># Date 1287388636 -32400# Node ID 2a2697be51688d3c5f3284bd6c55074e0d26ec40# Parent d10369fefd01f165f76263d9b92423ae018b84bcblackblox extension to help with debuggingdiff --git a/hgext/blackbox.py b/hgext/blackbox.pynew file mode 100644--- /dev/null+++ b/hgext/blackbox.py@@ -0,0 +1,70 @@+"""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 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)++ repo.blackbox(' '.join(fullargs))+ try:+ ret = orig(lui, repo, cmd, fullargs, *args, **kwargs)+ if ret:+ repo._blackbox.write(' [%d]\n' % ret)+ return ret+ except:+ traceback.print_exc(None, repo._blackbox)+ raise++def exthook(orig, ui, repo, name, cmd, *args, **kw):+ if repo:+ repo.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'):+ repo.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 incoming(ui, repo, hooktype, node, source, url):+ repo.blackbox('incoming: %s: %s from %s' % (source, node[:12], url))+def reposetup(ui, repo):+ if not repo.local():+ return++ class blackboxrepo(repo.__class__):+ @util.propertycache+ def _blackbox(self):+ introduction = not os.path.exists(self.join('blackbox'))+ blackbox = self.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)++ repo.__class__ = blackboxrepo+ ui.setconfig('hooks', 'incoming.blackbox', incoming)+diff --git a/tests/test-blackbox.t b/tests/test-blackbox.tnew 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'+