[PATCH 1 of 3 RFC v2] web: provide diffstat summary to the changeset page

Matt Mackall mpm at selenic.com
Thu May 19 16:42:23 CDT 2011


On Thu, 2011-05-19 at 21:19 +0800, Steven Brown wrote:
> # HG changeset patch
> # User Steven Brown <StevenGBrown at gmail.com>
> # Date 1305809487 -28800
> # Node ID de31c212265a9a89b67451e72dec11f2fb280968
> # Parent  a75e0f4ba0ab91277b654416d93abd12aa50b940
> web: provide diffstat summary to the changeset page
> 
> Add the diffstat keyword to the filenodelink template.
> 
> diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
> --- a/mercurial/hgweb/webcommands.py
> +++ b/mercurial/hgweb/webcommands.py
> @@ -257,11 +257,13 @@
>  
>      files = []
>      parity = paritygen(web.stripecount)
> +    diffstats = webutil.diffstatfunc(web.repo, ctx)
>      for f in ctx.files():
>          template = f in ctx and 'filenodelink' or 'filenolink'
>          files.append(tmpl(template,
>                            node=ctx.hex(), file=f,
> -                          parity=parity.next()))
> +                          parity=parity.next(),
> +                          diffstat=lambda **x: diffstats(x['file'])))
>  
>      parity = paritygen(web.stripecount)
>      style = web.config('web', 'style', 'paper')
> diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
> --- a/mercurial/hgweb/webutil.py
> +++ b/mercurial/hgweb/webutil.py
> @@ -7,7 +7,7 @@
>  # GNU General Public License version 2 or any later version.
>  
>  import os, copy
> -from mercurial import match, patch, scmutil, error, ui
> +from mercurial import match, patch, scmutil, error, ui, util
>  from mercurial.node import hex, nullid
>  
>  def up(p):
> @@ -211,6 +211,18 @@
>      yield tmpl('diffblock', parity=parity.next(),
>                 lines=prettyprintlines(''.join(block)))
>  
> +def diffstatfunc(repo, ctx):
> +    ''''Return a function that provides the diffstat histogram for a file.'''
> +
> +    hist = {}
> +    def func(filename):
> +        if not hist:
> +            lines = util.iterlines(ctx.diff())
> +            diffopts = patch.diffopts(repo.ui, untrusted=True)
> +            hist.update(patch.diffstatdict(lines, git=diffopts.git))
> +        return hist.get(filename)
> +    return func
> +
>  class sessionvars(object):
>      def __init__(self, vars, start='?'):
>          self.start = start
> diff --git a/mercurial/patch.py b/mercurial/patch.py
> --- a/mercurial/patch.py
> +++ b/mercurial/patch.py
> @@ -1736,8 +1736,11 @@
>          yield (filename, adds, removes, isbinary)
>  
>  def diffstat(lines, width=80, git=False):
> +    stats = list(diffstatdata(lines))
> +    return _diffstat(stats, width, git)
> +
> +def _diffstat(stats, width=80, git=False):
>      output = []
> -    stats = list(diffstatdata(lines))
>  
>      maxtotal, maxname = 0, 0
>      totaladds, totalremoves = 0, 0
> @@ -1805,3 +1808,13 @@
>          else:
>              yield (line, '')
>          yield ('\n', '')
> +
> +def diffstatdict(lines, **kw):
> +    '''Return a dictionary of file names to diffstat histograms.'''
> +
> +    stats = list(diffstatdata(lines))
> +    hist = {}
> +    for stat, line in zip(stats, _diffstat(stats, **kw).splitlines()):
> +        filename = stat[0]
> +        hist[filename] = line[1 + len(filename):].lstrip()[1:]
> +    return hist

This patch looks mostly good, but this part in patch.py looks fishy.
It seems we're generating a diffstat data set, then rendering it into
text to get all the line lengths right, then parsing the text again.

Seems like it'd be better to have an intermediate diffstathist function
that generated a dict of filename->(add, remove) tuples where plus/minus
are scaled such that the max add+remove = 1.0.

Then hgweb or diffstat() could decide how to render this. Then hgweb,
for instance, could use spans and colors to render a graphical, scalable
bar chart rather than using monospaced text. 

-- 
Mathematics is the supreme nostalgia of our time.




More information about the Mercurial-devel mailing list