##// END OF EJS Templates
Merge with stable
Merge with stable

File last commit:

r9672:5bbf4f13 default
r10023:15fbbc93 merge default
Show More
churn.py
192 lines | 6.4 KiB | text/x-python | PythonLexer
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 # churn.py - create a graph of revisions count grouped by template
Patrick Mezard
Make churn an official extension
r6348 #
# Copyright 2006 Josef "Jeff" Sipek <jeffpc@josefsipek.net>
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 # Copyright 2008 Alexander Solovyov <piranha@piranha.org.ua>
Patrick Mezard
Make churn an official extension
r6348 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
# GNU General Public License version 2, incorporated herein by reference.
Martin Geisler
add blank line after copyright notices and after header
r8228
Dirkjan Ochtman
extensions: change descriptions for extensions providing a few commands
r8934 '''command to display statistics about repository history'''
Patrick Mezard
Make churn an official extension
r6348
Martin Geisler
i18n, churn: mark string for translation
r7051 from mercurial.i18n import _
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 from mercurial import patch, cmdutil, util, templater
Martin Geisler
churn: use .hgchurn in repo root as default map file
r8254 import sys, os
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 import time, datetime
Patrick Mezard
Make churn an official extension
r6348
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 def maketemplater(ui, repo, tmpl):
tmpl = templater.parsestring(tmpl, quoted=False)
try:
Jim Correia
add --git option to commands supporting --patch (log, incoming, history, tip)...
r7762 t = cmdutil.changeset_templater(ui, repo, False, None, None, False)
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 except SyntaxError, inst:
raise util.Abort(inst.args[0])
t.use_template(tmpl)
return t
madhu@madhu
Returns lines changed for paths specified as arguments correctly....
r7870 def changedlines(ui, repo, ctx1, ctx2, fns):
Alexander Solovyov
churn: ability to display added/removed lines separately
r9669 added, removed = 0, 0
Brendan Cully
churn: correct output when run in subdirectories
r9321 fmatch = cmdutil.matchfiles(repo, fns)
madhu@madhu
Returns lines changed for paths specified as arguments correctly....
r7870 diff = ''.join(patch.diff(repo, ctx1.node(), ctx2.node(), fmatch))
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 for l in diff.split('\n'):
Alexander Solovyov
churn: ability to display added/removed lines separately
r9669 if l.startswith("+") and not l.startswith("+++ "):
added += 1
elif l.startswith("-") and not l.startswith("--- "):
removed += 1
return (added, removed)
Patrick Mezard
Make churn an official extension
r6348
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 def countrate(ui, repo, amap, *pats, **opts):
"""Calculate stats"""
if opts.get('dateformat'):
def getkey(ctx):
t, tz = ctx.date()
date = datetime.datetime(*time.gmtime(float(t) - tz)[:6])
return date.strftime(opts['dateformat'])
else:
tmpl = opts.get('template', '{author|email}')
tmpl = maketemplater(ui, repo, tmpl)
def getkey(ctx):
ui.pushbuffer()
Dirkjan Ochtman
cmdutil: use change contexts for cset-printer and cset-templater
r7369 tmpl.show(ctx)
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 return ui.popbuffer()
Alexander Solovyov
churn: fix --progress (broken by f3d60543924f)
r9672 state = {'count': 0, 'pct': 0}
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 rate = {}
df = False
if opts.get('date'):
df = util.matchdate(opts['date'])
Matt Mackall
walkchangerevs: pull out matchfn...
r9652 m = cmdutil.match(repo, pats, opts)
Matt Mackall
walkchangerevs: move 'add' to callback...
r9662 def prep(ctx, fns):
Matt Mackall
walkchangerevs: yield contexts
r9654 rev = ctx.rev()
Dirkjan Ochtman
cmdutil: use context objects for walkchangerevs()
r9367 if df and not df(ctx.date()[0]): # doesn't match date format
Matt Mackall
walkchangerevs: move 'add' to callback...
r9662 return
Patrick Mezard
Make churn an official extension
r6348
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 key = getkey(ctx)
key = amap.get(key, key) # alias remap
Alexander Solovyov
churn and stats commands merged
r7070 if opts.get('changesets'):
Alexander Solovyov
churn: fix changeset count (broken by 9b127e888640)
r9670 rate[key] = (rate.get(key, (0,))[0] + 1, 0)
Alexander Solovyov
churn and stats commands merged
r7070 else:
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 parents = ctx.parents()
if len(parents) > 1:
ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,))
Matt Mackall
walkchangerevs: move 'add' to callback...
r9662 return
Patrick Mezard
Make churn an official extension
r6348
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 ctx1 = parents[0]
madhu@madhu
Returns lines changed for paths specified as arguments correctly....
r7870 lines = changedlines(ui, repo, ctx1, ctx, fns)
Alexander Solovyov
churn: ability to display added/removed lines separately
r9669 rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)]
Patrick Mezard
Make churn an official extension
r6348
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 if opts.get('progress'):
Alexander Solovyov
churn: fix --progress (broken by f3d60543924f)
r9672 state['count'] += 1
newpct = int(100.0 * state['count'] / max(len(repo), 1))
if state['pct'] < newpct:
state['pct'] = newpct
ui.write("\r" + _("generating stats: %d%%") % state['pct'])
Patrick Mezard
Make churn an official extension
r6348 sys.stdout.flush()
Matt Mackall
walkchangerevs: drop ui arg
r9665 for ctx in cmdutil.walkchangerevs(repo, m, opts, prep):
Matt Mackall
walkchangerevs: move 'add' to callback...
r9662 continue
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 if opts.get('progress'):
Patrick Mezard
Make churn an official extension
r6348 ui.write("\r")
sys.stdout.flush()
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 return rate
Alexander Solovyov
churn and stats commands merged
r7070 def churn(ui, repo, *pats, **opts):
Cédric Duval
churn: improve description...
r8823 '''histogram of changes to the repository
Patrick Mezard
Make churn an official extension
r6348
Cédric Duval
churn: improve description...
r8823 This command will display a histogram representing the number
of changed lines or revisions, grouped according to the given
template. The default template will group changes by author.
The --dateformat option may be used to group the results by
date instead.
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065
Cédric Duval
churn: improve description...
r8823 Statistics are based on the number of changed lines, or
alternatively the number of matching revisions if the
--changesets option is specified.
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065
Martin Geisler
churn: use reST syntax for literal blocks
r9205 Examples::
Dirkjan Ochtman
convert comments to docstrings in a bunch of extensions
r6666
Alexander Solovyov
churn and stats commands merged
r7070 # display count of changed lines for every committer
hg churn -t '{author|email}'
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065
# display daily activity graph
Alexander Solovyov
churn and stats commands merged
r7070 hg churn -f '%H' -s -c
Dirkjan Ochtman
convert comments to docstrings in a bunch of extensions
r6666
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 # display activity of developers by month
Alexander Solovyov
churn and stats commands merged
r7070 hg churn -f '%Y-%m' -s -c
Patrick Mezard
Make churn an official extension
r6348
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 # display count of lines changed in every year
Alexander Solovyov
churn and stats commands merged
r7070 hg churn -f '%Y' -s
Cédric Duval
churn: improve description...
r8823 It is possible to map alternate email addresses to a main address
Martin Geisler
churn: wrap docstrings at 70 characters
r9254 by providing a file using the following format::
Dirkjan Ochtman
kill trailing whitespace
r8843
Martin Geisler
churn: use reST syntax for literal blocks
r9205 <alias email> <actual email>
Martin Geisler
churn: use .hgchurn in repo root as default map file
r8254
Martin Geisler
churn: wrap docstrings at 70 characters
r9254 Such a file may be specified with the --aliases option, otherwise
a .hgchurn file will be looked for in the working directory root.
Martin Geisler
churn: use .hgchurn in repo root as default map file
r8254 '''
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')
Martin Geisler
churn: use .hgchurn in repo root as default map file
r8254 if not aliases and os.path.exists(repo.wjoin('.hgchurn')):
aliases = repo.wjoin('.hgchurn')
Patrick Mezard
Make churn an official extension
r6348 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
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 rate = countrate(ui, repo, amap, *pats, **opts).items()
if not rate:
Patrick Mezard
Make churn an official extension
r6348 return
Alexander Solovyov
churn: ability to display added/removed lines separately
r9669 sortkey = ((not opts.get('sort')) and (lambda x: -sum(x[1])) or None)
Alejandro Santos
compat: use 'key' argument instead of 'cmp' when sorting a list
r9032 rate.sort(key=sortkey)
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065
Nicolas Dumazet
churn: issue833 was reintroduced in 9bc46d069a76, correct it and add a test
r9388 # Be careful not to have a zero maxcount (issue833)
Alexander Solovyov
churn: ability to display added/removed lines separately
r9669 maxcount = float(max(sum(v) for k, v in rate)) or 1.0
Nicolas Dumazet
churn: use genexps now that we dropped 2.3 compatibility
r9390 maxname = max(len(k) for k, v in rate)
Patrick Mezard
Make churn an official extension
r6348
Alexander Solovyov
python implementation of diffstat...
r7547 ttywidth = util.termwidth()
Martin Geisler
do not attempt to translate ui.debug output
r9467 ui.debug("assuming %i character terminal\n" % ttywidth)
Alexander Solovyov
churn: ability to display added/removed lines separately
r9669 width = ttywidth - maxname - 2 - 2 - 2
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065
Alexander Solovyov
churn: ability to display added/removed lines separately
r9669 if opts.get('diffstat'):
width -= 15
def format(name, (added, removed)):
return "%s %15s %s%s\n" % (pad(name, maxname),
'+%d/-%d' % (added, removed),
'+' * charnum(added),
'-' * charnum(removed))
else:
width -= 6
def format(name, count):
return "%s %6d %s\n" % (pad(name, maxname), sum(count),
'*' * charnum(sum(count)))
def charnum(count):
return int(round(count*width/maxcount))
for name, count in rate:
ui.write(format(name, count))
Patrick Mezard
Make churn an official extension
r6348
cmdtable = {
Alexander Solovyov
churn and stats commands merged
r7070 "churn":
(churn,
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 [('r', 'rev', [], _('count rate for the specified revision or range')),
Martin Geisler
expand "rev" to "revision" in help texts
r8028 ('d', 'date', '', _('count rate for revisions matching date spec')),
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 ('t', 'template', '{author|email}', _('template to group changesets')),
('f', 'dateformat', '',
_('strftime-compatible format for grouping by date')),
Alexander Solovyov
churn and stats commands merged
r7070 ('c', 'changesets', False, _('count rate by number of changesets')),
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 ('s', 'sort', False, _('sort by key (default: sort by count)')),
Alexander Solovyov
churn: ability to display added/removed lines separately
r9669 ('', 'diffstat', False, _('display added/removed lines separately')),
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 ('', 'aliases', '', _('file with email aliases')),
('', 'progress', None, _('show progress'))],
Martin Geisler
churn: corrected help output
r7129 _("hg churn [-d DATE] [-r REV] [--aliases FILE] [--progress] [FILE]")),
Patrick Mezard
Make churn an official extension
r6348 }