##// END OF EJS Templates
churn: support spaces in aliases (issue2222)
Alexander Solovyov -
r11264:30c620e4 default
parent child Browse files
Show More
@@ -1,188 +1,187
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 or any later version.
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 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 added, removed = 0, 0
27 27 fmatch = cmdutil.matchfiles(repo, 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("+++ "):
31 31 added += 1
32 32 elif l.startswith("-") and not l.startswith("--- "):
33 33 removed += 1
34 34 return (added, removed)
35 35
36 36 def countrate(ui, repo, amap, *pats, **opts):
37 37 """Calculate stats"""
38 38 if opts.get('dateformat'):
39 39 def getkey(ctx):
40 40 t, tz = ctx.date()
41 41 date = datetime.datetime(*time.gmtime(float(t) - tz)[:6])
42 42 return date.strftime(opts['dateformat'])
43 43 else:
44 44 tmpl = opts.get('template', '{author|email}')
45 45 tmpl = maketemplater(ui, repo, tmpl)
46 46 def getkey(ctx):
47 47 ui.pushbuffer()
48 48 tmpl.show(ctx)
49 49 return ui.popbuffer()
50 50
51 51 state = {'count': 0}
52 52 rate = {}
53 53 df = False
54 54 if opts.get('date'):
55 55 df = util.matchdate(opts['date'])
56 56
57 57 m = cmdutil.match(repo, pats, opts)
58 58 def prep(ctx, fns):
59 59 rev = ctx.rev()
60 60 if df and not df(ctx.date()[0]): # doesn't match date format
61 61 return
62 62
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,))[0] + 1, 0)
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 return
72 72
73 73 ctx1 = parents[0]
74 74 lines = changedlines(ui, repo, ctx1, ctx, fns)
75 75 rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)]
76 76
77 77 state['count'] += 1
78 78 ui.progress(_('analyzing'), state['count'], total=len(repo))
79 79
80 80 for ctx in cmdutil.walkchangerevs(repo, m, opts, prep):
81 81 continue
82 82
83 83 ui.progress(_('analyzing'), None)
84 84
85 85 return rate
86 86
87 87
88 88 def churn(ui, repo, *pats, **opts):
89 89 '''histogram of changes to the repository
90 90
91 91 This command will display a histogram representing the number
92 92 of changed lines or revisions, grouped according to the given
93 93 template. The default template will group changes by author.
94 94 The --dateformat option may be used to group the results by
95 95 date instead.
96 96
97 97 Statistics are based on the number of changed lines, or
98 98 alternatively the number of matching revisions if the
99 99 --changesets option is specified.
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 It is possible to map alternate email addresses to a main address
116 116 by providing a file using the following format::
117 117
118 <alias email> <actual email>
118 <alias email> = <actual email>
119 119
120 120 Such a file may be specified with the --aliases option, otherwise
121 121 a .hgchurn file will be looked for in the working directory root.
122 122 '''
123 123 def pad(s, l):
124 124 return (s + " " * l)[:l]
125 125
126 126 amap = {}
127 127 aliases = opts.get('aliases')
128 128 if not aliases and os.path.exists(repo.wjoin('.hgchurn')):
129 129 aliases = repo.wjoin('.hgchurn')
130 130 if aliases:
131 131 for l in open(aliases, "r"):
132 l = l.strip()
133 alias, actual = l.split()
134 amap[alias] = actual
132 alias, actual = l.split('=' in l and '=' or None, 1)
133 amap[alias.strip()] = actual.strip()
135 134
136 135 rate = countrate(ui, repo, amap, *pats, **opts).items()
137 136 if not rate:
138 137 return
139 138
140 139 sortkey = ((not opts.get('sort')) and (lambda x: -sum(x[1])) or None)
141 140 rate.sort(key=sortkey)
142 141
143 142 # Be careful not to have a zero maxcount (issue833)
144 143 maxcount = float(max(sum(v) for k, v in rate)) or 1.0
145 144 maxname = max(len(k) for k, v in rate)
146 145
147 146 ttywidth = util.termwidth()
148 147 ui.debug("assuming %i character terminal\n" % ttywidth)
149 148 width = ttywidth - maxname - 2 - 2 - 2
150 149
151 150 if opts.get('diffstat'):
152 151 width -= 15
153 152 def format(name, (added, removed)):
154 153 return "%s %15s %s%s\n" % (pad(name, maxname),
155 154 '+%d/-%d' % (added, removed),
156 155 ui.label('+' * charnum(added),
157 156 'diffstat.inserted'),
158 157 ui.label('-' * charnum(removed),
159 158 'diffstat.deleted'))
160 159 else:
161 160 width -= 6
162 161 def format(name, count):
163 162 return "%s %6d %s\n" % (pad(name, maxname), sum(count),
164 163 '*' * charnum(sum(count)))
165 164
166 165 def charnum(count):
167 166 return int(round(count * width / maxcount))
168 167
169 168 for name, count in rate:
170 169 ui.write(format(name, count))
171 170
172 171
173 172 cmdtable = {
174 173 "churn":
175 174 (churn,
176 175 [('r', 'rev', [], _('count rate for the specified revision or range')),
177 176 ('d', 'date', '', _('count rate for revisions matching date spec')),
178 177 ('t', 'template', '{author|email}',
179 178 _('template to group changesets')),
180 179 ('f', 'dateformat', '',
181 180 _('strftime-compatible format for grouping by date')),
182 181 ('c', 'changesets', False, _('count rate by number of changesets')),
183 182 ('s', 'sort', False, _('sort by key (default: sort by count)')),
184 183 ('', 'diffstat', False, _('display added/removed lines separately')),
185 184 ('', 'aliases', '', _('file with email aliases')),
186 185 ],
187 186 _("hg churn [-d DATE] [-r REV] [--aliases FILE] [FILE]")),
188 187 }
@@ -1,71 +1,77
1 1 #!/bin/sh
2 2
3 3 echo "[extensions]" >> $HGRCPATH
4 4 echo "churn=" >> $HGRCPATH
5 5
6 6 echo % create test repository
7 7 hg init repo
8 8 cd repo
9 9 echo a > a
10 10 hg ci -Am adda -u user1 -d 6:00
11 11 echo b >> a
12 12 echo b > b
13 13 hg ci -m changeba -u user2 -d 9:00 a
14 14 hg ci -Am addb -u user2 -d 9:30
15 15 echo c >> a
16 16 echo c >> b
17 17 echo c > c
18 18 hg ci -m changeca -u user3 -d 12:00 a
19 19 hg ci -m changecb -u user3 -d 12:15 b
20 20 hg ci -Am addc -u user3 -d 12:30
21 21 mkdir -p d/e
22 22 echo abc > d/e/f1.txt
23 23 hg ci -Am "add d/e/f1.txt" -u user1 -d 12:45 d/e/f1.txt
24 24 mkdir -p d/g
25 25 echo def > d/g/f2.txt
26 26 hg ci -Am "add d/g/f2.txt" -u user1 -d 13:00 d/g/f2.txt
27 27
28 28 echo % churn separate directories
29 29 cd d
30 30 hg churn e
31 31 echo % churn all
32 32 hg churn
33 33 echo % churn up to rev 2
34 34 hg churn -r :2
35 35 cd ..
36 36 echo % churn with aliases
37 37 cat > ../aliases <<EOF
38 38 user1 alias1
39 39 user3 alias3
40 40 EOF
41 41 hg churn --aliases ../aliases
42 42 echo % churn with .hgchurn
43 43 mv ../aliases .hgchurn
44 44 hg churn
45 45 rm .hgchurn
46 46 echo % churn with column specifier
47 47 COLUMNS=40 hg churn
48 48 echo % churn by hour
49 49 hg churn -f '%H' -s
50 50
51 51 echo % churn with separated added/removed lines
52 52 hg rm d/g/f2.txt
53 53 hg ci -Am "removed d/g/f2.txt" -u user1 -d 14:00 d/g/f2.txt
54 54 hg churn --diffstat
55 55 echo % churn --diffstat with color
56 56 hg --config extensions.color= churn --config color.mode=ansi \
57 57 --diffstat --color=always
58 58
59 59 echo % changeset number churn
60 60 hg churn -c
61 61
62 echo 'with space = no-space' >> ../aliases
63 echo a >> a
64 hg commit -m a -u 'with space' -d 15:00
65 echo % churn with space in alias
66 hg churn --aliases ../aliases -r tip
67
62 68 cd ..
63 69
64 70 # issue 833: ZeroDivisionError
65 71 hg init issue-833
66 72 cd issue-833
67 73 touch foo
68 74 hg ci -Am foo
69 75 # this was failing with a ZeroDivisionError
70 76 hg churn
71 77 cd ..
@@ -1,44 +1,46
1 1 % create test repository
2 2 adding a
3 3 adding b
4 4 adding c
5 5 % churn separate directories
6 6 user1 1 ***************************************************************
7 7 % churn all
8 8 user3 3 ***************************************************************
9 9 user1 3 ***************************************************************
10 10 user2 2 ******************************************
11 11 % churn up to rev 2
12 12 user2 2 ***************************************************************
13 13 user1 1 ********************************
14 14 % churn with aliases
15 15 alias3 3 **************************************************************
16 16 alias1 3 **************************************************************
17 17 user2 2 *****************************************
18 18 % churn with .hgchurn
19 19 alias3 3 **************************************************************
20 20 alias1 3 **************************************************************
21 21 user2 2 *****************************************
22 22 % churn with column specifier
23 23 user3 3 ***********************
24 24 user1 3 ***********************
25 25 user2 2 ***************
26 26 % churn by hour
27 27 06 1 *****************
28 28 09 2 *********************************
29 29 12 4 ******************************************************************
30 30 13 1 *****************
31 31 % churn with separated added/removed lines
32 32 user1 +3/-1 +++++++++++++++++++++++++++++++++++++++++--------------
33 33 user3 +3/-0 +++++++++++++++++++++++++++++++++++++++++
34 34 user2 +2/-0 +++++++++++++++++++++++++++
35 35 % churn --diffstat with color
36 36 user1 +3/-1 +++++++++++++++++++++++++++++++++++++++++--------------
37 37 user3 +3/-0 +++++++++++++++++++++++++++++++++++++++++
38 38 user2 +2/-0 +++++++++++++++++++++++++++
39 39 % changeset number churn
40 40 user1 4 ***************************************************************
41 41 user3 3 ***********************************************
42 42 user2 2 ********************************
43 % churn with space in alias
44 no-space 1 ************************************************************
43 45 adding foo
44 46 test 0
General Comments 0
You need to be logged in to leave comments. Login now