comparison hgext/churn.py @ 9669:9b127e888640

churn: ability to display added/removed lines separately
author Alexander Solovyov <piranha@piranha.org.ua>
date Thu, 29 Oct 2009 20:50:24 +0200
parents 1de5ebfa5585
children 7d56b6ffef72
comparison
equal deleted inserted replaced
9668:2c24471d478c 9669:9b127e888640
21 raise util.Abort(inst.args[0]) 21 raise util.Abort(inst.args[0])
22 t.use_template(tmpl) 22 t.use_template(tmpl)
23 return t 23 return t
24 24
25 def changedlines(ui, repo, ctx1, ctx2, fns): 25 def changedlines(ui, repo, ctx1, ctx2, fns):
26 lines = 0 26 added, removed = 0, 0
27 fmatch = cmdutil.matchfiles(repo, fns) 27 fmatch = cmdutil.matchfiles(repo, fns)
28 diff = ''.join(patch.diff(repo, ctx1.node(), ctx2.node(), fmatch)) 28 diff = ''.join(patch.diff(repo, ctx1.node(), ctx2.node(), fmatch))
29 for l in diff.split('\n'): 29 for l in diff.split('\n'):
30 if (l.startswith("+") and not l.startswith("+++ ") or 30 if l.startswith("+") and not l.startswith("+++ "):
31 l.startswith("-") and not l.startswith("--- ")): 31 added += 1
32 lines += 1 32 elif l.startswith("-") and not l.startswith("--- "):
33 return lines 33 removed += 1
34 return (added, removed)
34 35
35 def countrate(ui, repo, amap, *pats, **opts): 36 def countrate(ui, repo, amap, *pats, **opts):
36 """Calculate stats""" 37 """Calculate stats"""
37 if opts.get('dateformat'): 38 if opts.get('dateformat'):
38 def getkey(ctx): 39 def getkey(ctx):
69 ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,)) 70 ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,))
70 return 71 return
71 72
72 ctx1 = parents[0] 73 ctx1 = parents[0]
73 lines = changedlines(ui, repo, ctx1, ctx, fns) 74 lines = changedlines(ui, repo, ctx1, ctx, fns)
74 rate[key] = rate.get(key, 0) + lines 75 rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)]
75 76
76 if opts.get('progress'): 77 if opts.get('progress'):
77 count += 1 78 count += 1
78 newpct = int(100.0 * count / max(len(repo), 1)) 79 newpct = int(100.0 * count / max(len(repo), 1))
79 if pct < newpct: 80 if pct < newpct:
141 142
142 rate = countrate(ui, repo, amap, *pats, **opts).items() 143 rate = countrate(ui, repo, amap, *pats, **opts).items()
143 if not rate: 144 if not rate:
144 return 145 return
145 146
146 sortkey = ((not opts.get('sort')) and (lambda x: -x[1]) or None) 147 sortkey = ((not opts.get('sort')) and (lambda x: -sum(x[1])) or None)
147 rate.sort(key=sortkey) 148 rate.sort(key=sortkey)
148 149
149 # Be careful not to have a zero maxcount (issue833) 150 # Be careful not to have a zero maxcount (issue833)
150 maxcount = float(max(v for k, v in rate)) or 1.0 151 maxcount = float(max(sum(v) for k, v in rate)) or 1.0
151 maxname = max(len(k) for k, v in rate) 152 maxname = max(len(k) for k, v in rate)
152 153
153 ttywidth = util.termwidth() 154 ttywidth = util.termwidth()
154 ui.debug("assuming %i character terminal\n" % ttywidth) 155 ui.debug("assuming %i character terminal\n" % ttywidth)
155 width = ttywidth - maxname - 2 - 6 - 2 - 2 156 width = ttywidth - maxname - 2 - 2 - 2
156 157
157 for date, count in rate: 158 if opts.get('diffstat'):
158 print "%s %6d %s" % (pad(date, maxname), count, 159 width -= 15
159 "*" * int(count * width / maxcount)) 160 def format(name, (added, removed)):
161 return "%s %15s %s%s\n" % (pad(name, maxname),
162 '+%d/-%d' % (added, removed),
163 '+' * charnum(added),
164 '-' * charnum(removed))
165 else:
166 width -= 6
167 def format(name, count):
168 return "%s %6d %s\n" % (pad(name, maxname), sum(count),
169 '*' * charnum(sum(count)))
170
171 def charnum(count):
172 return int(round(count*width/maxcount))
173
174 for name, count in rate:
175 ui.write(format(name, count))
160 176
161 177
162 cmdtable = { 178 cmdtable = {
163 "churn": 179 "churn":
164 (churn, 180 (churn,
167 ('t', 'template', '{author|email}', _('template to group changesets')), 183 ('t', 'template', '{author|email}', _('template to group changesets')),
168 ('f', 'dateformat', '', 184 ('f', 'dateformat', '',
169 _('strftime-compatible format for grouping by date')), 185 _('strftime-compatible format for grouping by date')),
170 ('c', 'changesets', False, _('count rate by number of changesets')), 186 ('c', 'changesets', False, _('count rate by number of changesets')),
171 ('s', 'sort', False, _('sort by key (default: sort by count)')), 187 ('s', 'sort', False, _('sort by key (default: sort by count)')),
188 ('', 'diffstat', False, _('display added/removed lines separately')),
172 ('', 'aliases', '', _('file with email aliases')), 189 ('', 'aliases', '', _('file with email aliases')),
173 ('', 'progress', None, _('show progress'))], 190 ('', 'progress', None, _('show progress'))],
174 _("hg churn [-d DATE] [-r REV] [--aliases FILE] [--progress] [FILE]")), 191 _("hg churn [-d DATE] [-r REV] [--aliases FILE] [--progress] [FILE]")),
175 } 192 }