##// END OF EJS Templates
churn: lowercase output...
Martin Geisler -
r7626:551afd4a default
parent child Browse files
Show More
@@ -1,161 +1,161 b''
1 1 # churn.py - create a graph of revisions count grouped by template
2 2 #
3 3 # Copyright 2006 Josef "Jeff" Sipek <jeffpc@josefsipek.net>
4 4 # Copyright 2008 Alexander Solovyov <piranha@piranha.org.ua>
5 5 #
6 6 # This software may be used and distributed according to the terms
7 7 # of the GNU General Public License, incorporated herein by reference.
8 8 '''command to show certain statistics about revision history'''
9 9
10 10 from mercurial.i18n import _
11 11 from mercurial import patch, cmdutil, util, templater
12 12 import os, sys
13 13 import time, datetime
14 14
15 15 def maketemplater(ui, repo, tmpl):
16 16 tmpl = templater.parsestring(tmpl, quoted=False)
17 17 try:
18 18 t = cmdutil.changeset_templater(ui, repo, False, None, False)
19 19 except SyntaxError, inst:
20 20 raise util.Abort(inst.args[0])
21 21 t.use_template(tmpl)
22 22 return t
23 23
24 24 def changedlines(ui, repo, ctx1, ctx2):
25 25 lines = 0
26 26 diff = ''.join(patch.diff(repo, ctx1.node(), ctx2.node()))
27 27 for l in diff.split('\n'):
28 28 if (l.startswith("+") and not l.startswith("+++ ") or
29 29 l.startswith("-") and not l.startswith("--- ")):
30 30 lines += 1
31 31 return lines
32 32
33 33 def countrate(ui, repo, amap, *pats, **opts):
34 34 """Calculate stats"""
35 35 if opts.get('dateformat'):
36 36 def getkey(ctx):
37 37 t, tz = ctx.date()
38 38 date = datetime.datetime(*time.gmtime(float(t) - tz)[:6])
39 39 return date.strftime(opts['dateformat'])
40 40 else:
41 41 tmpl = opts.get('template', '{author|email}')
42 42 tmpl = maketemplater(ui, repo, tmpl)
43 43 def getkey(ctx):
44 44 ui.pushbuffer()
45 45 tmpl.show(ctx)
46 46 return ui.popbuffer()
47 47
48 48 count = pct = 0
49 49 rate = {}
50 50 df = False
51 51 if opts.get('date'):
52 52 df = util.matchdate(opts['date'])
53 53
54 54 get = util.cachefunc(lambda r: repo[r].changeset())
55 55 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
56 56 for st, rev, fns in changeiter:
57 57 if not st == 'add':
58 58 continue
59 59 if df and not df(get(rev)[2][0]): # doesn't match date format
60 60 continue
61 61
62 62 ctx = repo[rev]
63 63 key = getkey(ctx)
64 64 key = amap.get(key, key) # alias remap
65 65 if opts.get('changesets'):
66 66 rate[key] = rate.get(key, 0) + 1
67 67 else:
68 68 parents = ctx.parents()
69 69 if len(parents) > 1:
70 70 ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,))
71 71 continue
72 72
73 73 ctx1 = parents[0]
74 74 lines = changedlines(ui, repo, ctx1, ctx)
75 75 rate[key] = rate.get(key, 0) + lines
76 76
77 77 if opts.get('progress'):
78 78 count += 1
79 79 newpct = int(100.0 * count / max(len(repo), 1))
80 80 if pct < newpct:
81 81 pct = newpct
82 ui.write(_("\rGenerating stats: %d%%") % pct)
82 ui.write(_("\rgenerating stats: %d%%") % pct)
83 83 sys.stdout.flush()
84 84
85 85 if opts.get('progress'):
86 86 ui.write("\r")
87 87 sys.stdout.flush()
88 88
89 89 return rate
90 90
91 91
92 92 def churn(ui, repo, *pats, **opts):
93 93 '''graph count of revisions grouped by template
94 94
95 95 Will graph count of changed lines or revisions grouped by template or
96 96 alternatively by date, if dateformat is used. In this case it will override
97 97 template.
98 98
99 99 By default statistics are counted for number of changed lines.
100 100
101 101 Examples:
102 102
103 103 # display count of changed lines for every committer
104 104 hg churn -t '{author|email}'
105 105
106 106 # display daily activity graph
107 107 hg churn -f '%H' -s -c
108 108
109 109 # display activity of developers by month
110 110 hg churn -f '%Y-%m' -s -c
111 111
112 112 # display count of lines changed in every year
113 113 hg churn -f '%Y' -s
114 114
115 115 The map file format used to specify aliases is fairly simple:
116 116
117 117 <alias email> <actual email>'''
118 118 def pad(s, l):
119 119 return (s + " " * l)[:l]
120 120
121 121 amap = {}
122 122 aliases = opts.get('aliases')
123 123 if aliases:
124 124 for l in open(aliases, "r"):
125 125 l = l.strip()
126 126 alias, actual = l.split()
127 127 amap[alias] = actual
128 128
129 129 rate = countrate(ui, repo, amap, *pats, **opts).items()
130 130 if not rate:
131 131 return
132 132
133 133 sortfn = ((not opts.get('sort')) and (lambda a, b: cmp(b[1], a[1])) or None)
134 134 rate.sort(sortfn)
135 135
136 136 maxcount = float(max([v for k, v in rate]))
137 137 maxname = max([len(k) for k, v in rate])
138 138
139 139 ttywidth = util.termwidth()
140 140 ui.debug(_("assuming %i character terminal\n") % ttywidth)
141 141 width = ttywidth - maxname - 2 - 6 - 2 - 2
142 142
143 143 for date, count in rate:
144 144 print "%s %6d %s" % (pad(date, maxname), count,
145 145 "*" * int(count * width / maxcount))
146 146
147 147
148 148 cmdtable = {
149 149 "churn":
150 150 (churn,
151 151 [('r', 'rev', [], _('count rate for the specified revision or range')),
152 152 ('d', 'date', '', _('count rate for revs matching date spec')),
153 153 ('t', 'template', '{author|email}', _('template to group changesets')),
154 154 ('f', 'dateformat', '',
155 155 _('strftime-compatible format for grouping by date')),
156 156 ('c', 'changesets', False, _('count rate by number of changesets')),
157 157 ('s', 'sort', False, _('sort by key (default: sort by count)')),
158 158 ('', 'aliases', '', _('file with email aliases')),
159 159 ('', 'progress', None, _('show progress'))],
160 160 _("hg churn [-d DATE] [-r REV] [--aliases FILE] [--progress] [FILE]")),
161 161 }
General Comments 0
You need to be logged in to leave comments. Login now