##// END OF EJS Templates
hgweb: allow viewing diffs against p1 or p2 for merge commits (issue3904)...
hgweb: allow viewing diffs against p1 or p2 for merge commits (issue3904) This adds UI portion of the feature that has resided in mercurial since 2012. Back then the interface was added together with the code, but was shortly backed out because it was deemed "not ready". Code, however, stayed. For the original feature and its implementation, see issue2810 and d605a82cf189. In short, the backed-out interface had two outstanding issues: 1. it was introducing an entirely new term (baseline) and 2. it was present on every changeset's page, even for changesets with 1 parent (or no parents), which didn't make sense This patch implements a hopefully better interface because: 1. it uses the usual terms (diff) and 2. it only shows up when there actually are 2 parents.

File last commit:

r19230:6d6f148c stable
r23740:9e1f4c65 default
Show More
blackbox.py
158 lines | 5.1 KiB | text/x-python | PythonLexer
Bryan O'Sullivan
blackbox: fix copyright
r18676 # blackbox.py - log repository events to a file for post-mortem debugging
Durham Goode
blackbox: adds a blackbox extension...
r18669 #
Bryan O'Sullivan
blackbox: fix copyright
r18676 # Copyright 2010 Nicolas Dumazet
Durham Goode
blackbox: adds a blackbox extension...
r18669 # Copyright 2013 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
"""log repository events to a blackbox for debugging
Logs event information to .hg/blackbox.log to help debug and diagnose problems.
The events that get logged can be configured via the blackbox.track config key.
Takumi IINO
blackbox: fix literal block syntax
r19162 Examples::
Durham Goode
blackbox: adds a blackbox extension...
r18669
[blackbox]
track = *
[blackbox]
track = command, commandfinish, commandexception, exthook, pythonhook
[blackbox]
track = incoming
Bryan O'Sullivan
blackbox: automatically rotate log files...
r19066 [blackbox]
# limit the size of a log file
maxsize = 1.5 MB
# rotate up to N log files when the current one gets too big
maxfiles = 3
Durham Goode
blackbox: adds a blackbox extension...
r18669 """
from mercurial import util, cmdutil
from mercurial.i18n import _
Bryan O'Sullivan
blackbox: automatically rotate log files...
r19066 import errno, os, re
Durham Goode
blackbox: adds a blackbox extension...
r18669
cmdtable = {}
command = cmdutil.command(cmdtable)
testedwith = 'internal'
lastblackbox = None
def wrapui(ui):
class blackboxui(ui.__class__):
@util.propertycache
def track(self):
Bryan O'Sullivan
blackbox: fix a case of name capture
r19052 return self.configlist('blackbox', 'track', ['*'])
Durham Goode
blackbox: adds a blackbox extension...
r18669
Bryan O'Sullivan
blackbox: automatically rotate log files...
r19066 def _openlogfile(self):
def rotate(oldpath, newpath):
try:
os.unlink(newpath)
except OSError, err:
if err.errno != errno.ENOENT:
self.debug("warning: cannot remove '%s': %s\n" %
(newpath, err.strerror))
try:
if newpath:
os.rename(oldpath, newpath)
except OSError, err:
if err.errno != errno.ENOENT:
self.debug("warning: cannot rename '%s' to '%s': %s\n" %
(newpath, oldpath, err.strerror))
fp = self._bbopener('blackbox.log', 'a')
maxsize = self.configbytes('blackbox', 'maxsize', 1048576)
if maxsize > 0:
st = os.fstat(fp.fileno())
if st.st_size >= maxsize:
path = fp.name
fp.close()
maxfiles = self.configint('blackbox', 'maxfiles', 7)
for i in xrange(maxfiles - 1, 1, -1):
rotate(oldpath='%s.%d' % (path, i - 1),
newpath='%s.%d' % (path, i))
rotate(oldpath=path,
newpath=maxfiles > 0 and path + '.1')
fp = self._bbopener('blackbox.log', 'a')
return fp
Durham Goode
blackbox: adds a blackbox extension...
r18669 def log(self, event, *msg, **opts):
global lastblackbox
super(blackboxui, self).log(event, *msg, **opts)
if not '*' in self.track and not event in self.track:
return
if util.safehasattr(self, '_blackbox'):
blackbox = self._blackbox
Bryan O'Sullivan
blackbox: defer opening a log file until needed (issue3869)...
r18831 elif util.safehasattr(self, '_bbopener'):
try:
Bryan O'Sullivan
blackbox: automatically rotate log files...
r19066 self._blackbox = self._openlogfile()
Bryan O'Sullivan
blackbox: defer opening a log file until needed (issue3869)...
r18831 except (IOError, OSError), err:
self.debug('warning: cannot write to blackbox.log: %s\n' %
err.strerror)
del self._bbopener
self._blackbox = None
blackbox = self._blackbox
Durham Goode
blackbox: adds a blackbox extension...
r18669 else:
# certain ui instances exist outside the context of
# a repo, so just default to the last blackbox that
# was seen.
blackbox = lastblackbox
if blackbox:
date = util.datestr(None, '%Y/%m/%d %H:%M:%S')
Bryan O'Sullivan
blackbox: use util.getuser for portability...
r18787 user = util.getuser()
Durham Goode
blackbox: adds a blackbox extension...
r18669 formattedmsg = msg[0] % msg[1:]
Bryan O'Sullivan
blackbox: prevent failed I/O from causing hg to abort...
r18786 try:
blackbox.write('%s %s> %s' % (date, user, formattedmsg))
except IOError, err:
self.debug('warning: cannot write to blackbox.log: %s\n' %
err.strerror)
Durham Goode
blackbox: adds a blackbox extension...
r18669 lastblackbox = blackbox
def setrepo(self, repo):
Bryan O'Sullivan
blackbox: defer opening a log file until needed (issue3869)...
r18831 self._bbopener = repo.opener
Durham Goode
blackbox: adds a blackbox extension...
r18669
ui.__class__ = blackboxui
def uisetup(ui):
wrapui(ui)
def reposetup(ui, repo):
# During 'hg pull' a httppeer repo is created to represent the remote repo.
# It doesn't have a .hg directory to put a blackbox in, so we don't do
# the blackbox setup for it.
if not repo.local():
return
Durham Goode
blackbox: fix blackbox causing exceptions in tests...
r19230 if util.safehasattr(ui, 'setrepo'):
ui.setrepo(repo)
Durham Goode
blackbox: adds a 'blackbox' command for viewing recent logs...
r18673
@command('^blackbox',
[('l', 'limit', 10, _('the number of events to show')),
],
_('hg blackbox [OPTION]...'))
def blackbox(ui, repo, *revs, **opts):
'''view the recent repository events
'''
if not os.path.exists(repo.join('blackbox.log')):
return
limit = opts.get('limit')
blackbox = repo.opener('blackbox.log', 'r')
lines = blackbox.read().split('\n')
count = 0
output = []
for line in reversed(lines):
if count >= limit:
break
# count the commands by matching lines like: 2013/01/23 19:13:36 root>
if re.match('^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} .*> .*', line):
count += 1
output.append(line)
ui.status('\n'.join(reversed(output)))