##// END OF EJS Templates
Returns lines changed for paths specified as arguments correctly....
madhu@madhu -
r7870:7bcce39e default
parent child Browse files
Show More
@@ -1,161 +1,162 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, 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 def changedlines(ui, repo, ctx1, ctx2):
24 def changedlines(ui, repo, ctx1, ctx2, fns):
25 25 lines = 0
26 diff = ''.join(patch.diff(repo, ctx1.node(), ctx2.node()))
26 fmatch = cmdutil.match(repo, pats=fns)
27 diff = ''.join(patch.diff(repo, ctx1.node(), ctx2.node(), fmatch))
27 28 for l in diff.split('\n'):
28 29 if (l.startswith("+") and not l.startswith("+++ ") or
29 30 l.startswith("-") and not l.startswith("--- ")):
30 31 lines += 1
31 32 return lines
32 33
33 34 def countrate(ui, repo, amap, *pats, **opts):
34 35 """Calculate stats"""
35 36 if opts.get('dateformat'):
36 37 def getkey(ctx):
37 38 t, tz = ctx.date()
38 39 date = datetime.datetime(*time.gmtime(float(t) - tz)[:6])
39 40 return date.strftime(opts['dateformat'])
40 41 else:
41 42 tmpl = opts.get('template', '{author|email}')
42 43 tmpl = maketemplater(ui, repo, tmpl)
43 44 def getkey(ctx):
44 45 ui.pushbuffer()
45 46 tmpl.show(ctx)
46 47 return ui.popbuffer()
47 48
48 49 count = pct = 0
49 50 rate = {}
50 51 df = False
51 52 if opts.get('date'):
52 53 df = util.matchdate(opts['date'])
53 54
54 55 get = util.cachefunc(lambda r: repo[r].changeset())
55 56 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
56 57 for st, rev, fns in changeiter:
57 58 if not st == 'add':
58 59 continue
59 60 if df and not df(get(rev)[2][0]): # doesn't match date format
60 61 continue
61 62
62 63 ctx = repo[rev]
63 64 key = getkey(ctx)
64 65 key = amap.get(key, key) # alias remap
65 66 if opts.get('changesets'):
66 67 rate[key] = rate.get(key, 0) + 1
67 68 else:
68 69 parents = ctx.parents()
69 70 if len(parents) > 1:
70 71 ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,))
71 72 continue
72 73
73 74 ctx1 = parents[0]
74 lines = changedlines(ui, repo, ctx1, ctx)
75 lines = changedlines(ui, repo, ctx1, ctx, fns)
75 76 rate[key] = rate.get(key, 0) + lines
76 77
77 78 if opts.get('progress'):
78 79 count += 1
79 80 newpct = int(100.0 * count / max(len(repo), 1))
80 81 if pct < newpct:
81 82 pct = newpct
82 83 ui.write(_("\rgenerating stats: %d%%") % pct)
83 84 sys.stdout.flush()
84 85
85 86 if opts.get('progress'):
86 87 ui.write("\r")
87 88 sys.stdout.flush()
88 89
89 90 return rate
90 91
91 92
92 93 def churn(ui, repo, *pats, **opts):
93 94 '''graph count of revisions grouped by template
94 95
95 96 Will graph count of changed lines or revisions grouped by template or
96 97 alternatively by date, if dateformat is used. In this case it will override
97 98 template.
98 99
99 100 By default statistics are counted for number of changed lines.
100 101
101 102 Examples:
102 103
103 104 # display count of changed lines for every committer
104 105 hg churn -t '{author|email}'
105 106
106 107 # display daily activity graph
107 108 hg churn -f '%H' -s -c
108 109
109 110 # display activity of developers by month
110 111 hg churn -f '%Y-%m' -s -c
111 112
112 113 # display count of lines changed in every year
113 114 hg churn -f '%Y' -s
114 115
115 116 The map file format used to specify aliases is fairly simple:
116 117
117 118 <alias email> <actual email>'''
118 119 def pad(s, l):
119 120 return (s + " " * l)[:l]
120 121
121 122 amap = {}
122 123 aliases = opts.get('aliases')
123 124 if aliases:
124 125 for l in open(aliases, "r"):
125 126 l = l.strip()
126 127 alias, actual = l.split()
127 128 amap[alias] = actual
128 129
129 130 rate = countrate(ui, repo, amap, *pats, **opts).items()
130 131 if not rate:
131 132 return
132 133
133 134 sortfn = ((not opts.get('sort')) and (lambda a, b: cmp(b[1], a[1])) or None)
134 135 rate.sort(sortfn)
135 136
136 137 maxcount = float(max([v for k, v in rate]))
137 138 maxname = max([len(k) for k, v in rate])
138 139
139 140 ttywidth = util.termwidth()
140 141 ui.debug(_("assuming %i character terminal\n") % ttywidth)
141 142 width = ttywidth - maxname - 2 - 6 - 2 - 2
142 143
143 144 for date, count in rate:
144 145 print "%s %6d %s" % (pad(date, maxname), count,
145 146 "*" * int(count * width / maxcount))
146 147
147 148
148 149 cmdtable = {
149 150 "churn":
150 151 (churn,
151 152 [('r', 'rev', [], _('count rate for the specified revision or range')),
152 153 ('d', 'date', '', _('count rate for revs matching date spec')),
153 154 ('t', 'template', '{author|email}', _('template to group changesets')),
154 155 ('f', 'dateformat', '',
155 156 _('strftime-compatible format for grouping by date')),
156 157 ('c', 'changesets', False, _('count rate by number of changesets')),
157 158 ('s', 'sort', False, _('sort by key (default: sort by count)')),
158 159 ('', 'aliases', '', _('file with email aliases')),
159 160 ('', 'progress', None, _('show progress'))],
160 161 _("hg churn [-d DATE] [-r REV] [--aliases FILE] [--progress] [FILE]")),
161 162 }
@@ -1,38 +1,46 b''
1 1 #!/bin/sh
2 2
3 3 echo "[extensions]" >> $HGRCPATH
4 4 echo "churn=" >> $HGRCPATH
5 5
6 6 COLUMNS=80; export COLUMNS
7 7
8 8 echo % create test repository
9 9 hg init repo
10 10 cd repo
11 11 echo a > a
12 12 hg ci -Am adda -u user1 -d 6:00
13 13 echo b >> a
14 14 echo b > b
15 15 hg ci -m changeba -u user2 -d 9:00 a
16 16 hg ci -Am addb -u user2 -d 9:30
17 17 echo c >> a
18 18 echo c >> b
19 19 echo c > c
20 20 hg ci -m changeca -u user3 -d 12:00 a
21 21 hg ci -m changecb -u user3 -d 12:15 b
22 22 hg ci -Am addc -u user3 -d 12:30
23 mkdir -p d/e
24 echo abc > d/e/f1.txt
25 hg ci -Am "add d/e/f1.txt" -u user1 -d 12:45 d/e/f1.txt
26 mkdir -p d/g
27 echo def > d/g/f2.txt
28 hg ci -Am "add d/g/f2.txt" -u user1 -d 13:00 d/g/f2.txt
23 29
30 echo % churn separate directories
31 hg churn d/e
24 32 echo % churn all
25 33 hg churn
26 34 echo % churn up to rev 2
27 35 hg churn -r :2
28 36 echo % churn with aliases
29 37 cat > ../aliases <<EOF
30 38 user1 alias1
31 39 user3 alias3
32 40 EOF
33 41 hg churn --aliases ../aliases
34 42 echo % churn with column specifier
35 43 COLUMNS=40 hg churn
36 44 echo % churn by hour
37 45 hg churn -f '%H' -s
38 46
@@ -1,23 +1,26 b''
1 1 % create test repository
2 2 adding a
3 3 adding b
4 4 adding c
5 % churn separate directories
6 user1 1 ***************************************************************
5 7 % churn all
6 8 user3 3 ***************************************************************
9 user1 3 ***************************************************************
7 10 user2 2 ******************************************
8 user1 1 *********************
9 11 % churn up to rev 2
10 12 user2 2 ***************************************************************
11 13 user1 1 *******************************
12 14 % churn with aliases
13 15 alias3 3 **************************************************************
16 alias1 3 **************************************************************
14 17 user2 2 *****************************************
15 alias1 1 ********************
16 18 % churn with column specifier
17 19 user3 3 ***********************
20 user1 3 ***********************
18 21 user2 2 ***************
19 user1 1 *******
20 22 % churn by hour
21 06 1 **********************
22 09 2 ********************************************
23 12 3 ******************************************************************
23 06 1 ****************
24 09 2 *********************************
25 12 4 ******************************************************************
26 13 1 ****************
General Comments 0
You need to be logged in to leave comments. Login now