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