annotate hgext/churn.py @ 6858:8f256bf98219

Add support for multiple possible bisect results (issue1228, issue1182) The real reason for both issue is that bisect can not handle cases where there are multiple possibilities for the result. Example (from issue1228): rev 0 -> good rev 1 -> skipped rev 2 -> skipped rev 3 -> skipped rev 4 -> bad Note that this patch does not only fix the reported Assertion Error but also the problem of a non converging bisect: hg init for i in `seq 3`; do echo $i > $i; hg add $i; hg ci -m$i; done hg bisect -b 2 hg bisect -g 0 hg bisect -s From this state on, you can: a) mark as bad forever (non converging!) b) mark as good to get an inconsistent state c) skip for the Assertion Error Minor description and code edits by pmezard.
author Bernhard Leiner <bleiner@gmail.com>
date Sat, 02 Aug 2008 22:10:10 +0200
parents 05a62e8ddf3d
children b114a8c7998f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
1 # churn.py - create a graph showing who changed the most lines
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
2 #
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
3 # Copyright 2006 Josef "Jeff" Sipek <jeffpc@josefsipek.net>
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
4 #
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
5 # This software may be used and distributed according to the terms
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
6 # of the GNU General Public License, incorporated herein by reference.
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
7 #
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
8 #
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
9 # Aliases map file format is simple one alias per line in the following
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
10 # format:
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
11 #
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
12 # <alias email> <actual email>
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
13
3045
c0be8990e819 Add revision range support
Brendan Cully <brendan@kublai.com>
parents: 3043
diff changeset
14 from mercurial.i18n import gettext as _
6212
e75aab656f46 Remove unused imports
Joel Rosdahl <joel@rosdahl.net>
parents: 5990
diff changeset
15 from mercurial import mdiff, cmdutil, util, node
4955
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
16 import os, sys
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
17
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
18 def get_tty_width():
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
19 if 'COLUMNS' in os.environ:
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
20 try:
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
21 return int(os.environ['COLUMNS'])
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
22 except ValueError:
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
23 pass
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
24 try:
5419
041bd297f01e churn: simplify code to get terminal width
Christian Ebert <blacktrash@gmx.net>
parents: 4955
diff changeset
25 import termios, array, fcntl
4955
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
26 for dev in (sys.stdout, sys.stdin):
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
27 try:
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
28 fd = dev.fileno()
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
29 if not os.isatty(fd):
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
30 continue
5419
041bd297f01e churn: simplify code to get terminal width
Christian Ebert <blacktrash@gmx.net>
parents: 4955
diff changeset
31 arri = fcntl.ioctl(fd, termios.TIOCGWINSZ, '\0' * 8)
041bd297f01e churn: simplify code to get terminal width
Christian Ebert <blacktrash@gmx.net>
parents: 4955
diff changeset
32 return array.array('h', arri)[1]
4955
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
33 except ValueError:
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
34 pass
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
35 except ImportError:
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
36 pass
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
37 return 80
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
38
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
39 def __gather(ui, repo, node1, node2):
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
40 def dirtywork(f, mmap1, mmap2):
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
41 lines = 0
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
42
3042
2d35d7c6f251 [churn] Trivial cleanup suggested by Thomas
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3041
diff changeset
43 to = mmap1 and repo.file(f).read(mmap1[f]) or None
2d35d7c6f251 [churn] Trivial cleanup suggested by Thomas
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3041
diff changeset
44 tn = mmap2 and repo.file(f).read(mmap2[f]) or None
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
45
5482
e5eedd74e70f Use both the from and to name in mdiff.unidiff.
Dustin Sallings <dustin@spy.net>
parents: 5419
diff changeset
46 diff = mdiff.unidiff(to, "", tn, "", f, f).split("\n")
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
47
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
48 for line in diff:
3043
fe0e3508ec6e [churn] Trivial cleanup
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3042
diff changeset
49 if not line:
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
50 continue # skip EOF
3042
2d35d7c6f251 [churn] Trivial cleanup suggested by Thomas
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3041
diff changeset
51 if line.startswith(" "):
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
52 continue # context line
3042
2d35d7c6f251 [churn] Trivial cleanup suggested by Thomas
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3041
diff changeset
53 if line.startswith("--- ") or line.startswith("+++ "):
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
54 continue # begining of diff
3042
2d35d7c6f251 [churn] Trivial cleanup suggested by Thomas
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3041
diff changeset
55 if line.startswith("@@ "):
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
56 continue # info line
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
57
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
58 # changed lines
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
59 lines += 1
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
60
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
61 return lines
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
62
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
63 ##
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
64
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
65 lines = 0
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
66
3048
8d344bc72e68 [churn] repo.changes was renamed to repo.status
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3046
diff changeset
67 changes = repo.status(node1, node2, None, util.always)[:5]
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
68
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
69 modified, added, removed, deleted, unknown = changes
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
70
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
71 who = repo.changelog.read(node2)[1]
5975
75d9fe70c654 templater: move email function to util
Matt Mackall <mpm@selenic.com>
parents: 5915
diff changeset
72 who = util.email(who) # get the email of the person
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
73
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
74 mmap1 = repo.manifest.read(repo.changelog.read(node1)[0])
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
75 mmap2 = repo.manifest.read(repo.changelog.read(node2)[0])
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
76 for f in modified:
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
77 lines += dirtywork(f, mmap1, mmap2)
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
78
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
79 for f in added:
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
80 lines += dirtywork(f, None, mmap2)
3223
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3090
diff changeset
81
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
82 for f in removed:
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
83 lines += dirtywork(f, mmap1, None)
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
84
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
85 for f in deleted:
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
86 lines += dirtywork(f, mmap1, mmap2)
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
87
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
88 for f in unknown:
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
89 lines += dirtywork(f, mmap1, mmap2)
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
90
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
91 return (who, lines)
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
92
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
93 def gather_stats(ui, repo, amap, revs=None, progress=False):
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
94 stats = {}
3223
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3090
diff changeset
95
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
96 cl = repo.changelog
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
97
3045
c0be8990e819 Add revision range support
Brendan Cully <brendan@kublai.com>
parents: 3043
diff changeset
98 if not revs:
3046
2a4d4aecb2b4 Merge with Brendan Cully
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents: 3045 3044
diff changeset
99 revs = range(0, cl.count())
3045
c0be8990e819 Add revision range support
Brendan Cully <brendan@kublai.com>
parents: 3043
diff changeset
100
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
101 nr_revs = len(revs)
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
102 cur_rev = 0
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
103
3045
c0be8990e819 Add revision range support
Brendan Cully <brendan@kublai.com>
parents: 3043
diff changeset
104 for rev in revs:
3051
7ffaf5aba4d8 [churn] Fix progress bar not incrementing when merge cset is encountered
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3050
diff changeset
105 cur_rev += 1 # next revision
7ffaf5aba4d8 [churn] Fix progress bar not incrementing when merge cset is encountered
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3050
diff changeset
106
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
107 node2 = cl.node(rev)
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
108 node1 = cl.parents(node2)[0]
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
109
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
110 if cl.parents(node2)[1] != node.nullid:
3049
461573aa02ef [churn] Ignore merge csets
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3048
diff changeset
111 ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,))
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
112 continue
3049
461573aa02ef [churn] Ignore merge csets
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3048
diff changeset
113
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
114 who, lines = __gather(ui, repo, node1, node2)
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
115
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
116 # remap the owner if possible
5915
d0576d065993 Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents: 5588
diff changeset
117 if who in amap:
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
118 ui.note("using '%s' alias for '%s'\n" % (amap[who], who))
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
119 who = amap[who]
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
120
5915
d0576d065993 Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents: 5588
diff changeset
121 if not who in stats:
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
122 stats[who] = 0
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
123 stats[who] += lines
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
124
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
125 ui.note("rev %d: %d lines by %s\n" % (rev, lines, who))
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
126
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
127 if progress:
5588
083b6e3142a2 churn: avoid division by zero
Matt Mackall <mpm@selenic.com>
parents: 5482
diff changeset
128 nr_revs = max(nr_revs, 1)
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
129 if int(100.0*(cur_rev - 1)/nr_revs) < int(100.0*cur_rev/nr_revs):
5990
71d675f4b1f8 Fixed typo: Gnerating -> Generating
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5989
diff changeset
130 ui.write("\rGenerating stats: %d%%" % (int(100.0*cur_rev/nr_revs),))
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
131 sys.stdout.flush()
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
132
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
133 if progress:
5989
a7817ad608ea added \r for progress counting in churn extension
Armin Ronacher <armin.ronacher@active-4.com>
parents: 5976
diff changeset
134 ui.write("\r")
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
135 sys.stdout.flush()
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
136
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
137 return stats
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
138
3045
c0be8990e819 Add revision range support
Brendan Cully <brendan@kublai.com>
parents: 3043
diff changeset
139 def churn(ui, repo, **opts):
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
140 "Graphs the number of lines changed"
3223
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3090
diff changeset
141
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
142 def pad(s, l):
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
143 if len(s) < l:
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
144 return s + " " * (l-len(s))
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
145 return s[0:l]
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
146
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
147 def graph(n, maximum, width, char):
5588
083b6e3142a2 churn: avoid division by zero
Matt Mackall <mpm@selenic.com>
parents: 5482
diff changeset
148 maximum = max(1, maximum)
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
149 n = int(n * width / float(maximum))
3223
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3090
diff changeset
150
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
151 return char * (n)
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
152
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
153 def get_aliases(f):
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
154 aliases = {}
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
155
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
156 for l in f.readlines():
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
157 l = l.strip()
6421
ecde0baee570 churn: allow whitespaces as delimiter in aliases
Kirill Smelkov <kirr@mns.spb.ru>
parents: 6348
diff changeset
158 alias, actual = l.split()
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
159 aliases[alias] = actual
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
160
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
161 return aliases
3223
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3090
diff changeset
162
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
163 amap = {}
3045
c0be8990e819 Add revision range support
Brendan Cully <brendan@kublai.com>
parents: 3043
diff changeset
164 aliases = opts.get('aliases')
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
165 if aliases:
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
166 try:
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
167 f = open(aliases,"r")
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
168 except OSError, e:
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
169 print "Error: " + e
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
170 return
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
171
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
172 amap = get_aliases(f)
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
173 f.close()
3045
c0be8990e819 Add revision range support
Brendan Cully <brendan@kublai.com>
parents: 3043
diff changeset
174
3792
4670470b97bd Fix revrange() call in the churn contrib
Edouard Gomez <ed.gomez@free.fr>
parents: 3223
diff changeset
175 revs = [int(r) for r in cmdutil.revrange(repo, opts['rev'])]
3045
c0be8990e819 Add revision range support
Brendan Cully <brendan@kublai.com>
parents: 3043
diff changeset
176 revs.sort()
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
177 stats = gather_stats(ui, repo, amap, revs, opts.get('progress'))
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
178
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
179 # make a list of tuples (name, lines) and sort it in descending order
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
180 ordered = stats.items()
5588
083b6e3142a2 churn: avoid division by zero
Matt Mackall <mpm@selenic.com>
parents: 5482
diff changeset
181 if not ordered:
083b6e3142a2 churn: avoid division by zero
Matt Mackall <mpm@selenic.com>
parents: 5482
diff changeset
182 return
6223
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
183 ordered.sort(lambda x, y: cmp(y[1], x[1]))
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
184 max_churn = ordered[0][1]
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
185
6223
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
186 tty_width = get_tty_width()
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
187 ui.note(_("assuming %i character terminal\n") % tty_width)
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
188 tty_width -= 1
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
189
6223
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
190 max_user_width = max([len(user) for user, churn in ordered])
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
191
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
192 graph_width = tty_width - max_user_width - 1 - 6 - 2 - 2
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
193
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
194 for user, churn in ordered:
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
195 print "%s %6d %s" % (pad(user, max_user_width),
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
196 churn,
bab6c8f2bb1a churn: show comitter email addresses unclipped (bug 1023)
Stephen Deasey <sdeasey@gmail.com>
parents: 6212
diff changeset
197 graph(churn, max_churn, graph_width, '*'))
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
198
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
199 cmdtable = {
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
200 "churn":
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
201 (churn,
3045
c0be8990e819 Add revision range support
Brendan Cully <brendan@kublai.com>
parents: 3043
diff changeset
202 [('r', 'rev', [], _('limit statistics to the specified revisions')),
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
203 ('', 'aliases', '', _('file with email aliases')),
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
204 ('', 'progress', None, _('show progress'))],
6841
05a62e8ddf3d churn: fix documentation for churn options
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6421
diff changeset
205 'hg churn [-r REVISIONS] [--aliases FILE] [--progress]'),
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
206 }