##// END OF EJS Templates
fix conflicting variables when no native osutil is available...
fix conflicting variables when no native osutil is available thanks weijun for the bug report and patch, fix issue1309

File last commit:

r7051:5f201f71 default
r7057:094af6ee default
Show More
churn.py
119 lines | 3.5 KiB | text/x-python | PythonLexer
# 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.
'''allow graphing the number of lines changed per contributor'''
from mercurial.i18n import _
from mercurial import patch, cmdutil, util, node
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
def countrevs(ui, repo, amap, revs, progress=False):
stats = {}
count = pct = 0
if not revs:
revs = range(len(repo))
for rev in revs:
ctx2 = repo[rev]
parents = ctx2.parents()
if len(parents) > 1:
ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,))
continue
ctx1 = parents[0]
lines = 0
ui.pushbuffer()
patch.diff(repo, ctx1.node(), ctx2.node())
diff = ui.popbuffer()
for l in diff.split('\n'):
if (l.startswith("+") and not l.startswith("+++ ") or
l.startswith("-") and not l.startswith("--- ")):
lines += 1
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))
if progress:
count += 1
newpct = int(100.0 * count / max(len(revs), 1))
if pct < newpct:
pct = newpct
ui.write(_("\rGenerating stats: %d%%") % pct)
sys.stdout.flush()
if progress:
ui.write("\r")
sys.stdout.flush()
return stats
def churn(ui, repo, **opts):
'''graphs the number of lines changed
The map file format used to specify aliases is fairly simple:
<alias email> <actual email>'''
def pad(s, l):
return (s + " " * l)[:l]
amap = {}
aliases = opts.get('aliases')
if aliases:
for l in open(aliases, "r"):
l = l.strip()
alias, actual = l.split()
amap[alias] = actual
revs = util.sort([int(r) for r in cmdutil.revrange(repo, opts['rev'])])
stats = countrevs(ui, repo, amap, revs, opts.get('progress'))
if not stats:
return
stats = util.sort([(-l, u, l) for u,l in stats.items()])
maxchurn = float(max(1, stats[0][2]))
maxuser = max([len(u) for k, u, l in stats])
ttywidth = get_tty_width()
ui.debug(_("assuming %i character terminal\n") % ttywidth)
width = ttywidth - maxuser - 2 - 6 - 2 - 2
for k, user, churn in stats:
print "%s %6d %s" % (pad(user, maxuser), churn,
"*" * int(churn * width / maxchurn))
cmdtable = {
"churn":
(churn,
[('r', 'rev', [], _('limit statistics to the specified revisions')),
('', 'aliases', '', _('file with email aliases')),
('', 'progress', None, _('show progress'))],
_('hg churn [-r REVISIONS] [--aliases FILE] [--progress]')),
}