##// END OF EJS Templates
hgweb: removed unnecessary del before function return...
hgweb: removed unnecessary del before function return Deleting tmpl just before the return statement should have no effect since tmpl goes out of scope anyway. But it confuses pyflakes who thinks tmpl is undefined when it is used in the except blocks below.

File last commit:

r6843:b114a8c7 merge default
r6914:95f35b55 default
Show More
churn.py
119 lines | 3.5 KiB | text/x-python | PythonLexer
Patrick Mezard
Make churn an official extension
r6348 # churn.py - create a graph showing who changed the most lines
#
# Copyright 2006 Josef "Jeff" Sipek <jeffpc@josefsipek.net>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
Dirkjan Ochtman
convert comments to docstrings in a bunch of extensions
r6666 '''allow graphing the number of lines changed per contributor'''
Patrick Mezard
Make churn an official extension
r6348
from mercurial.i18n import gettext as _
Matt Mackall
churn: major refactor...
r6759 from mercurial import patch, cmdutil, util, node
Patrick Mezard
Make churn an official extension
r6348 import os, sys
def get_tty_width():
if 'COLUMNS' in os.environ:
try:
return int(os.environ['COLUMNS'])
except ValueError:
pass
try:
import termios, array, fcntl
for dev in (sys.stdout, sys.stdin):
try:
fd = dev.fileno()
if not os.isatty(fd):
continue
arri = fcntl.ioctl(fd, termios.TIOCGWINSZ, '\0' * 8)
return array.array('h', arri)[1]
except ValueError:
pass
except ImportError:
pass
return 80
Matt Mackall
churn: major refactor...
r6759 def countrevs(ui, repo, amap, revs, progress=False):
Patrick Mezard
Make churn an official extension
r6348 stats = {}
Matt Mackall
churn: major refactor...
r6759 count = pct = 0
Patrick Mezard
Make churn an official extension
r6348 if not revs:
Matt Mackall
churn: major refactor...
r6759 revs = range(len(repo))
Patrick Mezard
Make churn an official extension
r6348
for rev in revs:
Matt Mackall
churn: major refactor...
r6759 ctx2 = repo[rev]
parents = ctx2.parents()
if len(parents) > 1:
Patrick Mezard
Make churn an official extension
r6348 ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,))
continue
Matt Mackall
churn: major refactor...
r6759 ctx1 = parents[0]
lines = 0
ui.pushbuffer()
patch.diff(repo, ctx1.node(), ctx2.node())
diff = ui.popbuffer()
Patrick Mezard
Make churn an official extension
r6348
Matt Mackall
churn: major refactor...
r6759 for l in diff.split('\n'):
if (l.startswith("+") and not l.startswith("+++ ") or
l.startswith("-") and not l.startswith("--- ")):
lines += 1
Patrick Mezard
Make churn an official extension
r6348
Matt Mackall
churn: major refactor...
r6759 user = util.email(ctx2.user())
user = amap.get(user, user) # remap
stats[user] = stats.get(user, 0) + lines
ui.debug("rev %d: %d lines by %s\n" % (rev, lines, user))
Patrick Mezard
Make churn an official extension
r6348
if progress:
Matt Mackall
churn: major refactor...
r6759 count += 1
newpct = int(100.0 * count / max(len(revs), 1))
if pct < newpct:
pct = newpct
ui.write("\rGenerating stats: %d%%" % pct)
Patrick Mezard
Make churn an official extension
r6348 sys.stdout.flush()
if progress:
ui.write("\r")
sys.stdout.flush()
return stats
def churn(ui, repo, **opts):
Dirkjan Ochtman
convert comments to docstrings in a bunch of extensions
r6666 '''graphs the number of lines changed
The map file format used to specify aliases is fairly simple:
<alias email> <actual email>'''
Patrick Mezard
Make churn an official extension
r6348
def pad(s, l):
Matt Mackall
churn: major refactor...
r6759 return (s + " " * l)[:l]
Patrick Mezard
Make churn an official extension
r6348
amap = {}
aliases = opts.get('aliases')
if aliases:
Matt Mackall
churn: major refactor...
r6759 for l in open(aliases, "r"):
l = l.strip()
alias, actual = l.split()
amap[alias] = actual
Patrick Mezard
Make churn an official extension
r6348
Matt Mackall
util: add sort helper
r6762 revs = util.sort([int(r) for r in cmdutil.revrange(repo, opts['rev'])])
Matt Mackall
churn: major refactor...
r6759 stats = countrevs(ui, repo, amap, revs, opts.get('progress'))
if not stats:
Patrick Mezard
Make churn an official extension
r6348 return
Matt Mackall
util: add sort helper
r6762 stats = util.sort([(-l, u, l) for u,l in stats.items()])
Matt Mackall
churn: major refactor...
r6759 maxchurn = float(max(1, stats[0][2]))
maxuser = max([len(u) for k, u, l in stats])
Patrick Mezard
Make churn an official extension
r6348
Matt Mackall
churn: major refactor...
r6759 ttywidth = get_tty_width()
ui.debug(_("assuming %i character terminal\n") % ttywidth)
width = ttywidth - maxuser - 2 - 6 - 2 - 2
Patrick Mezard
Make churn an official extension
r6348
Matt Mackall
churn: major refactor...
r6759 for k, user, churn in stats:
print "%s %6d %s" % (pad(user, maxuser), churn,
"*" * int(churn * width / maxchurn))
Patrick Mezard
Make churn an official extension
r6348
cmdtable = {
"churn":
(churn,
[('r', 'rev', [], _('limit statistics to the specified revisions')),
('', 'aliases', '', _('file with email aliases')),
('', 'progress', None, _('show progress'))],
Dirkjan Ochtman
churn: fix documentation for churn options
r6841 'hg churn [-r REVISIONS] [--aliases FILE] [--progress]'),
Patrick Mezard
Make churn an official extension
r6348 }