##// END OF EJS Templates
registrar: move cmdutil.command to registrar module (API)...
registrar: move cmdutil.command to registrar module (API) cmdutil.command wasn't a member of the registrar framework only for a historical reason. Let's make that happen. This patch keeps cmdutil.command as an alias for extension compatibility.

File last commit:

r32337:46ba2cdd default
r32337:46ba2cdd default
Show More
churn.py
212 lines | 7.0 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
Gregory Szorc
churn: use absolute_import
r28094 from __future__ import absolute_import
import datetime
import os
import time
Martin Geisler
i18n, churn: mark string for translation
r7051 from mercurial.i18n import _
Gregory Szorc
churn: use absolute_import
r28094 from mercurial import (
cmdutil,
commands,
encoding,
patch,
Yuya Nishihara
registrar: move cmdutil.command to registrar module (API)...
r32337 registrar,
Gregory Szorc
churn: use absolute_import
r28094 scmutil,
util,
)
Patrick Mezard
Make churn an official extension
r6348
Gregory Szorc
churn: declare command using decorator
r21245 cmdtable = {}
Yuya Nishihara
registrar: move cmdutil.command to registrar module (API)...
r32337 command = registrar.command(cmdtable)
Augie Fackler
extensions: change magic "shipped with hg" string...
r29841 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
Augie Fackler
extensions: document that `testedwith = 'internal'` is special...
r25186 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
# be specifying the version(s) of Mercurial they are tested with, or
# leave the attribute unspecified.
Augie Fackler
extensions: change magic "shipped with hg" string...
r29841 testedwith = 'ships-with-hg-core'
Augie Fackler
hgext: mark all first-party extensions as such
r16743
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 def maketemplater(ui, repo, tmpl):
Yuya Nishihara
templater: do not abuse SyntaxError to report errors in template map file...
r28628 return cmdutil.changeset_templater(ui, repo, False, None, tmpl, None, False)
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065
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:
Jordi Gutiérrez Hermoso
churn: deprecate -t option in favour of -T...
r24139 tmpl = opts.get('oldtemplate') or opts.get('template')
Alexander Solovyov
churn: generalisation, now it is possible to see statistics grouped by custom template
r7065 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
av6
churn: specify unit for ui.progress when analyzing revisions
r28472 ui.progress(_('analyzing'), state['count'], total=len(repo),
unit=_('revisions'))
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
Gregory Szorc
churn: declare command using decorator
r21245 @command('churn',
[('r', 'rev', [],
Jordi Gutiérrez Hermoso
doc: change 'revision or range' to 'revision or revset'...
r23091 _('count rate for the specified revision or revset'), _('REV')),
Gregory Szorc
churn: declare command using decorator
r21245 ('d', 'date', '',
_('count rate for revisions matching date spec'), _('DATE')),
Jordi Gutiérrez Hermoso
churn: deprecate -t option in favour of -T...
r24139 ('t', 'oldtemplate', '',
_('template to group changesets (DEPRECATED)'), _('TEMPLATE')),
('T', 'template', '{author|email}',
Gregory Szorc
churn: declare command using decorator
r21245 _('template to group changesets'), _('TEMPLATE')),
('f', 'dateformat', '',
_('strftime-compatible format for grouping by date'), _('FORMAT')),
('c', 'changesets', False, _('count rate by number of changesets')),
('s', 'sort', False, _('sort by key (default: sort by count)')),
('', 'diffstat', False, _('display added/removed lines separately')),
('', 'aliases', '', _('file with email aliases'), _('FILE')),
] + commands.walkopts,
Gregory Szorc
churn: define inferrepo in command decorator
r21779 _("hg churn [-d DATE] [-r REV] [--aliases FILE] [FILE]"),
inferrepo=True)
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
Matt Harbison
churn: use the non-deprecated template option in the examples
r32229 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
FUJIWARA Katsunori
doc: use double quotation mark to quote arguments in examples for Windows users...
r19959 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
FUJIWARA Katsunori
doc: use double quotation mark to quote arguments in examples for Windows users...
r19959 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
FUJIWARA Katsunori
doc: use double quotation mark to quote arguments in examples for Windows users...
r19959 hg churn -f "%Y" -s
Alexander Solovyov
churn and stats commands merged
r7070
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.
Matthew Turk
churn: split email aliases from the right...
r19464 Aliases will be split from the rightmost "=".
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):
Isaac Jurado
churn: compute padding with unicode strings...
r21163 return s + " " * (l - encoding.colwidth(s))
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:
Matthew Turk
churn: split email aliases from the right...
r19464 alias, actual = l.rsplit('=' in l and '=' or None, 1)
Martin Geisler
churn: do not crash on malformed lines in alias file
r12069 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
Mads Kiilerich
churn: sort users with same churn by name...
r18369 if opts.get('sort'):
rate.sort()
else:
rate.sort(key=lambda x: (-sum(x[1]), x))
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))