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

Steven Brown stevengbrown at gmail.com
Sun May 22 12:06:11 CDT 2011


On 23 May 2011 00:31, Matt Mackall <mpm at selenic.com> wrote:

> On Mon, 2011-05-23 at 00:25 +0800, Steven Brown wrote:
> > On 22 May 2011 04:25, Matt Mackall <mpm at selenic.com> wrote:
> > > On Thu, 2011-05-19 at 16:42 -0500, Matt Mackall wrote:
> > >> 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.
> > >
> > > I ended up hacking on this a bit, and now there's a diffstatsum
> function
> > > that does the bit that's needed here. Now you can divide the adds and
> > > removes in the stat data by the total of adds+removes from the sum to
> > > scale it.
> >
> > Great. It even simplifies the existing code.
> >
> > >> 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.
> > >
> > > So now what's needed is a way to provide the data to hgweb in a way
> that
> > > it can be rendered nicely.
> > >
> > > Thoughts?
> > >
> > > --
> > > Mathematics is the supreme nostalgia of our time.
> > >
> >
> > This is what I now have in mind for the UI.
> >
> > coal, paper and spartan: Add an expand link to the list of files. A plus
> > symbol will do. When clicked, it expands to display the 'file',
> 'annotate',
> > 'diff' and 'revisions' links for each file (like monoblue) and also the
> > diffstat summary. If necessary, this expanded view could be loaded as a
> > separate page to avoid slowing down the initial page load.
> >
> > monoblue: Add the diffstat summary to the existing HTML table of files.
> >
> > gitweb: No changes. It is intended to look like git's gitweb.
> >
> > The diffstat summary will show the total number of changes for each file
> > followed by a horizontal bar chart:
> >
> >     --------------------
> > 33  |               |  |
> >     --------------------
> >
> >       ^               ^
> >       Adds (Green)    Removes (Red)
> >
> > How does this sound?
>
> Excellent.
>
> So it seems the templater will need to get at least
>
> (file, total, addpct, removepct)
>
>
> --
> Mathematics is the supreme nostalgia of our time.
>
>
>
Perhaps we should give it (file, adds, removes, scale) instead, which would
allow the number of adds and removes to be displayed without rounding
errors. For example, a style may choose to display this information in a
tool-tip.

It also needs parity (for the row stripes) and node (for the links).
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20110523/7de88948/attachment.htm>


More information about the Mercurial-devel mailing list