##// END OF EJS Templates
util: add sort helper
util: add sort helper

File last commit:

r6762:f67d1468 default
r6762:f67d1468 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'))],
'hg churn [-r revision range] [-a file] [--progress]'),
}