hgext/churn.py
changeset 9669 9b127e888640
parent 9665 1de5ebfa5585
child 9670 7d56b6ffef72
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 }