##// END OF EJS Templates
cvsps: use commitids (when present) to detect changesets...
cvsps: use commitids (when present) to detect changesets Simplify core logic by no longer attempting to work around missing class attributes. Instead always generate the attributes and ignore the cache if the attributes are missing

File last commit:

r17773:434e5bd6 default
r18261:1b7b5975 default
Show More
churn.py
201 lines | 6.7 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
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
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 _
Matt Mackall
scmutil: drop aliases in cmdutil for match functions
r14322 from mercurial import patch, cmdutil, scmutil, util, templater, commands
Nicolas Dumazet
pylint, pyflakes: remove unused or duplicate imports
r10905 import 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
Augie Fackler
hgext: mark all first-party extensions as such
r16743 testedwith = 'internal'
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
Matt Mackall
scmutil: drop aliases in cmdutil for match functions
r14322 fmatch = scmutil.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()
Eric Eisner
churn: use ui.progress instead of --progress
r10647 state = {'count': 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
scmutil: switch match users to supplying contexts...
r14671 m = scmutil.match(repo[None], 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: strip key earlier to avoid false negative seach in aliases
r14040 key = getkey(ctx).strip()
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 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:
Martin Geisler
churn: lowercase message
r16924 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
Eric Eisner
churn: use ui.progress instead of --progress
r10647 state['count'] += 1
Martin Geisler
progress: use a verb in present participle
r10700 ui.progress(_('analyzing'), state['count'], total=len(repo))
Patrick Mezard
Make churn an official extension
r6348
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
Martin Geisler
progress: use a verb in present participle
r10700 ui.progress(_('analyzing'), None)
Patrick Mezard
Make churn an official extension
r6348
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
Alexander Solovyov
churn: support spaces in aliases (issue2222)
r11264 <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"):
Martin Geisler
churn: do not crash on malformed lines in alias file
r12069 try:
alias, actual = l.split('=' in l and '=' or None, 1)
amap[alias.strip()] = actual.strip()
except ValueError:
l = l.strip()
if l:
Matt Mackall
i18n: fix all remaining uses of % inside _()
r16231 ui.warn(_("skipping malformed alias: %s\n") % l)
Ronny Pfannschmidt
churn: do not crash on empty lines in alias file
r12068 continue
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
Augie Fackler
termwidth: move to ui.ui from util
r12689 ttywidth = ui.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
Renato Cunha
churn: remove tuple parameter unpacking (deprecated in py3k)
r11501 def format(name, diffstat):
added, removed = diffstat
Steve Borho
Backed out changeset: e1dde7363601
r11310 return "%s %15s %s%s\n" % (pad(name, maxname),
'+%d/-%d' % (added, removed),
Brodie Rao
churn: make use of output labeling
r10821 ui.label('+' * charnum(added),
'diffstat.inserted'),
ui.label('-' * charnum(removed),
'diffstat.deleted'))
Alexander Solovyov
churn: ability to display added/removed lines separately
r9669 else:
width -= 6
def format(name, count):
Steve Borho
Backed out changeset: e1dde7363601
r11310 return "%s %6d %s\n" % (pad(name, maxname), sum(count),
'*' * charnum(sum(count)))
Alexander Solovyov
churn: ability to display added/removed lines separately
r9669
def charnum(count):
Matt Mackall
many, many trivial check-code fixups
r10282 return int(round(count * width / maxcount))
Alexander Solovyov
churn: ability to display added/removed lines separately
r9669
for name, count in rate:
Steve Borho
Backed out changeset: e1dde7363601
r11310 ui.write(format(name, count))
Patrick Mezard
Make churn an official extension
r6348
cmdtable = {
Alexander Solovyov
churn and stats commands merged
r7070 "churn":
(churn,
FUJIWARA Katsunori
help: show value requirement and multiple occurrence of options...
r11321 [('r', 'rev', [],
_('count rate for the specified revision or range'), _('REV')),
('d', 'date', '',
_('count rate for revisions matching date spec'), _('DATE')),
Matt Mackall
many, many trivial check-code fixups
r10282 ('t', 'template', '{author|email}',
FUJIWARA Katsunori
help: show value requirement and multiple occurrence of options...
r11321 _('template to group changesets'), _('TEMPLATE')),
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 ('f', 'dateformat', '',
FUJIWARA Katsunori
help: show value requirement and multiple occurrence of options...
r11321 _('strftime-compatible format for grouping by date'), _('FORMAT')),
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')),
FUJIWARA Katsunori
help: show value requirement and multiple occurrence of options...
r11321 ('', 'aliases', '',
_('file with email aliases'), _('FILE')),
Alexander Solovyov
churn: add possibility to include/exclude paths
r11265 ] + commands.walkopts,
Eric Eisner
churn: use ui.progress instead of --progress
r10647 _("hg churn [-d DATE] [-r REV] [--aliases FILE] [FILE]")),
Patrick Mezard
Make churn an official extension
r6348 }
Siddharth Agarwal
commands: don't infer repo for commands like update (issue2748)...
r17773
commands.inferrepo += " churn"