##// END OF EJS Templates
churn: wrap docstrings at 70 characters
Martin Geisler -
r9254:db132556 default
parent child Browse files
Show More
@@ -1,172 +1,174
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 display statistics about repository 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 95 '''histogram of changes to the repository
96 96
97 This command will display a histogram representing the number of changed
98 lines or revisions, grouped according to the given template. The default
99 template will group changes by author. The --dateformat option may be used
100 to group the results by date instead.
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.
101 102
102 Statistics are based on the number of changed lines, or alternatively the
103 number of matching revisions if the --changesets option is specified.
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.
104 106
105 107 Examples::
106 108
107 109 # display count of changed lines for every committer
108 110 hg churn -t '{author|email}'
109 111
110 112 # display daily activity graph
111 113 hg churn -f '%H' -s -c
112 114
113 115 # display activity of developers by month
114 116 hg churn -f '%Y-%m' -s -c
115 117
116 118 # display count of lines changed in every year
117 119 hg churn -f '%Y' -s
118 120
119 It is possible to map alternate email addresses to a main address by
120 providing a file using the following format::
121 It is possible to map alternate email addresses to a main address
122 by providing a file using the following format::
121 123
122 124 <alias email> <actual email>
123 125
124 Such a file may be specified with the --aliases option, otherwise a
125 .hgchurn file will be looked for in the working directory root.
126 Such a file may be specified with the --aliases option, otherwise
127 a .hgchurn file will be looked for in the working directory root.
126 128 '''
127 129 def pad(s, l):
128 130 return (s + " " * l)[:l]
129 131
130 132 amap = {}
131 133 aliases = opts.get('aliases')
132 134 if not aliases and os.path.exists(repo.wjoin('.hgchurn')):
133 135 aliases = repo.wjoin('.hgchurn')
134 136 if aliases:
135 137 for l in open(aliases, "r"):
136 138 l = l.strip()
137 139 alias, actual = l.split()
138 140 amap[alias] = actual
139 141
140 142 rate = countrate(ui, repo, amap, *pats, **opts).items()
141 143 if not rate:
142 144 return
143 145
144 146 sortkey = ((not opts.get('sort')) and (lambda x: -x[1]) or None)
145 147 rate.sort(key=sortkey)
146 148
147 149 maxcount = float(max([v for k, v in rate]))
148 150 maxname = max([len(k) for k, v in rate])
149 151
150 152 ttywidth = util.termwidth()
151 153 ui.debug(_("assuming %i character terminal\n") % ttywidth)
152 154 width = ttywidth - maxname - 2 - 6 - 2 - 2
153 155
154 156 for date, count in rate:
155 157 print "%s %6d %s" % (pad(date, maxname), count,
156 158 "*" * int(count * width / maxcount))
157 159
158 160
159 161 cmdtable = {
160 162 "churn":
161 163 (churn,
162 164 [('r', 'rev', [], _('count rate for the specified revision or range')),
163 165 ('d', 'date', '', _('count rate for revisions matching date spec')),
164 166 ('t', 'template', '{author|email}', _('template to group changesets')),
165 167 ('f', 'dateformat', '',
166 168 _('strftime-compatible format for grouping by date')),
167 169 ('c', 'changesets', False, _('count rate by number of changesets')),
168 170 ('s', 'sort', False, _('sort by key (default: sort by count)')),
169 171 ('', 'aliases', '', _('file with email aliases')),
170 172 ('', 'progress', None, _('show progress'))],
171 173 _("hg churn [-d DATE] [-r REV] [--aliases FILE] [--progress] [FILE]")),
172 174 }
General Comments 0
You need to be logged in to leave comments. Login now