[PATCH] hgweb: side-by-side comparison functionality

Michał Sznajder michalsznajder at gmail.com
Tue Jul 10 03:54:17 CDT 2012


Thanks for sending a final version. I hope it will be included into 2.3
since it was already reviewed at least once on the list.

Michał Sznajder

On Mon, Jul 9, 2012 at 8:23 AM,  <wujek.srujek at gmail.com> wrote:
> # HG changeset patch
> # User wujek srujek
> # Date 1341760622 -7200
> # Node ID 957eaa8e01979360a5560eff3bbd86baa72cb31c
> # Parent  2e13c1bd34dc6afda8fc7cfa22a8cd658276724f
> hgweb: side-by-side comparison functionality
>
> Adds new web command to the core, ``comparison``, which enables colorful
> side-by-side change display, which for some might be much easier to work with
> than the standard line diff output. The idea how to implement comes from the
> SonicHq extension.
> The web interface gets a new link to call the comparison functionality. It lets
> users configure the amount of context lines around change blocks, or to show
> full files - check help (also in this changeset) for details and defaults. The
> setting in hgrc can be overridden by adding ``context=<value>`` to the request
> query string. The comparison creates addressable lines, so as to enable sharing
> links to specific lines, just as standard diff does.
> Incorporates updates to all web related styles.
>
> Known limitations:
> * the column diff is done against the first parent, just as the standard diff
> * this change allows examining diffs for single files only (as I am not sure if
>   examining the whole changeset in this way would be helpful)
> * syntax highlighting of the output changes is not performed (enabling the
>   highlight extension has no influence on it)
>
> diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
> --- a/mercurial/help/config.txt
> +++ b/mercurial/help/config.txt
> @@ -1377,6 +1377,12 @@
>  ``errorlog``
>      Where to output the error log. Default is stderr.
>
> +``comparisoncontext``
> +    Number of lines of context to show in side-by-side file comparison. If
> +    negative or the value ``full``, whole files are shown. Default is 5.
> +    This setting can be overridden by a ``context`` request parameter to the
> +    ``comparison`` command, taking the same values.
> +
>  ``hidden``
>      Whether to hide the repository in the hgwebdir index.
>      Default is False.
> diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
> --- a/mercurial/hgweb/webcommands.py
> +++ b/mercurial/hgweb/webcommands.py
> @@ -22,7 +22,7 @@
>  __all__ = [
>     'log', 'rawfile', 'file', 'changelog', 'shortlog', 'changeset', 'rev',
>     'manifest', 'tags', 'bookmarks', 'branches', 'summary', 'filediff', 'diff',
> -   'annotate', 'filelog', 'archive', 'static', 'graph', 'help',
> +   'comparison', 'annotate', 'filelog', 'archive', 'static', 'graph', 'help',
>  ]
>
>  def log(web, req, tmpl):
> @@ -586,6 +586,31 @@
>
>  diff = filediff
>
> +def comparison(web, req, tmpl):
> +    ctx = webutil.changectx(web.repo, req)
> +    path = webutil.cleanpath(web.repo, req.form['file'][0])
> +    rename = path in ctx and webutil.renamelink(ctx[path]) or []
> +
> +    parsecontext = lambda v: v == 'full' and -1 or int(v)
> +    if 'context' in req.form:
> +        context = parsecontext(req.form['context'][0])
> +    else:
> +        context = parsecontext(web.config('web', 'comparisoncontext', '5'))
> +
> +    comparison = webutil.compare(tmpl, ctx, path, context)
> +    return tmpl('filecomparison',
> +                file=path,
> +                node=hex(ctx.node()),
> +                rev=ctx.rev(),
> +                date=ctx.date(),
> +                desc=ctx.description(),
> +                author=ctx.user(),
> +                rename=rename,
> +                branch=webutil.nodebranchnodefault(ctx),
> +                parent=webutil.parents(ctx),
> +                child=webutil.children(ctx),
> +                comparison=comparison)
> +
>  def annotate(web, req, tmpl):
>      fctx = webutil.filectx(web.repo, req)
>      f = fctx.path()
> diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
> --- a/mercurial/hgweb/webutil.py
> +++ b/mercurial/hgweb/webutil.py
> @@ -6,10 +6,11 @@
>  # This software may be used and distributed according to the terms of the
>  # GNU General Public License version 2 or any later version.
>
> -import os, copy
> +import os, mimetypes, copy
>  from mercurial import match, patch, scmutil, error, ui, util
>  from mercurial.i18n import _
>  from mercurial.node import hex, nullid
> +import difflib
>
>  def up(p):
>      if p[0] != "/":
> @@ -220,6 +221,92 @@
>      yield tmpl('diffblock', parity=parity.next(), blockno=blockno,
>                 lines=prettyprintlines(''.join(block), blockno))
>
> +def compare(tmpl, ctx, path, context):
> +    '''Generator function that provides side-by-side comparison data.'''
> +
> +    def filelines(f):
> +        if util.binary(f.data()):
> +            mt = mimetypes.guess_type(f.path())[0]
> +            if not mt:
> +                mt = 'application/octet-stream'
> +            return [_('(binary file %s, hash: %s)') % (mt, hex(f.filenode()))]
> +        return f.data().splitlines()
> +
> +    def compline(type, leftlineno, leftline, rightlineno, rightline):
> +        lineid = leftlineno and ("l%s" % leftlineno) or ''
> +        lineid += rightlineno and ("r%s" % rightlineno) or ''
> +        return tmpl('comparisonline',
> +                    type=type,
> +                    lineid=lineid,
> +                    leftlinenumber="% 6s" % (leftlineno or ''),
> +                    leftline=leftline or '',
> +                    rightlinenumber="% 6s" % (rightlineno or ''),
> +                    rightline=rightline or '')
> +
> +    def getblock(opcodes):
> +        for type, llo, lhi, rlo, rhi in opcodes:
> +            len1 = lhi - llo
> +            len2 = rhi - rlo
> +            count = min(len1, len2)
> +            for i in xrange(count):
> +                yield compline(type=type,
> +                               leftlineno=llo + i + 1,
> +                               leftline=leftlines[llo + i],
> +                               rightlineno=rlo + i + 1,
> +                               rightline=rightlines[rlo + i])
> +            if len1 > len2:
> +                for i in xrange(llo + count, lhi):
> +                    yield compline(type=type,
> +                                   leftlineno=i + 1,
> +                                   leftline=leftlines[i],
> +                                   rightlineno=None,
> +                                   rightline=None)
> +            elif len2 > len1:
> +                for i in xrange(rlo + count, rhi):
> +                    yield compline(type=type,
> +                                   leftlineno=None,
> +                                   leftline=None,
> +                                   rightlineno=i + 1,
> +                                   rightline=rightlines[i])
> +
> +    if path in ctx:
> +        fctx = ctx[path]
> +        rightrev = fctx.filerev()
> +        rightnode = fctx.filenode()
> +        rightlines = filelines(fctx)
> +        parents = fctx.parents()
> +        if not parents:
> +            leftrev = -1
> +            leftnode = nullid
> +            leftlines = ()
> +        else:
> +            pfctx = parents[0]
> +            leftrev = pfctx.filerev()
> +            leftnode = pfctx.filenode()
> +            leftlines = filelines(pfctx)
> +    else:
> +        rightrev = -1
> +        rightnode = nullid
> +        rightlines = ()
> +        fctx = ctx.parents()[0][path]
> +        leftrev = fctx.filerev()
> +        leftnode = fctx.filenode()
> +        leftlines = filelines(fctx)
> +
> +    s = difflib.SequenceMatcher(None, leftlines, rightlines)
> +    if context < 0:
> +        blocks = [tmpl('comparisonblock', lines=getblock(s.get_opcodes()))]
> +    else:
> +        blocks = (tmpl('comparisonblock', lines=getblock(oc))
> +                     for oc in s.get_grouped_opcodes(n=context))
> +
> +    yield tmpl('comparison',
> +               leftrev=leftrev,
> +               leftnode=hex(leftnode),
> +               rightrev=rightrev,
> +               rightnode=hex(rightnode),
> +               blocks=blocks)
> +
>  def diffstatgen(ctx):
>      '''Generator function that provides the diffstat data.'''
>
> diff --git a/mercurial/templates/coal/map b/mercurial/templates/coal/map
> --- a/mercurial/templates/coal/map
> +++ b/mercurial/templates/coal/map
> @@ -63,6 +63,7 @@
>  filerevision = ../paper/filerevision.tmpl
>  fileannotate = ../paper/fileannotate.tmpl
>  filediff = ../paper/filediff.tmpl
> +filecomparison = ../paper/filecomparison.tmpl
>  filelog = ../paper/filelog.tmpl
>  fileline = '
>    <div class="parity{parity} source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</div>'
> @@ -83,6 +84,26 @@
>  difflineat = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="atline">{line|escape}</span>'
>  diffline = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}'
>
> +comparison = '
> +  <table class="bigtable">
> +    <thead class="header">
> +      <tr>
> +        <th>{leftrev}:{leftnode|short}</th>
> +        <th>{rightrev}:{rightnode|short}</th>
> +      </tr>
> +    </thead>
> +    {blocks}
> +  </table>'
> +comparisonblock ='
> +  <tbody class="block">
> +  {lines}
> +  </tbody>'
> +comparisonline = '
> +  <tr>
> +    <td class="source {type}"><a href="#{lineid}" id="{lineid}">{leftlinenumber}</a> {leftline|escape}</td>
> +    <td class="source {type}"><a href="#{lineid}" id="{lineid}">{rightlinenumber}</a> {rightline|escape}</td>
> +  </tr>'
> +
>  changelogparent = '
>    <tr>
>      <th class="parent">parent {rev}:</th>
> diff --git a/mercurial/templates/gitweb/fileannotate.tmpl b/mercurial/templates/gitweb/fileannotate.tmpl
> --- a/mercurial/templates/gitweb/fileannotate.tmpl
> +++ b/mercurial/templates/gitweb/fileannotate.tmpl
> @@ -26,6 +26,7 @@
>  <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a> |
>  annotate |
>  <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
> +<a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a> |
>  <a href="{url}raw-annotate/{node|short}/{file|urlescape}">raw</a> |
>  <a href="{url}help{sessionvars%urlparameter}">help</a>
>  <br/>
> diff --git a/mercurial/templates/gitweb/filediff.tmpl b/mercurial/templates/gitweb/filecomparison.tmpl
> copy from mercurial/templates/gitweb/filediff.tmpl
> copy to mercurial/templates/gitweb/filecomparison.tmpl
> --- a/mercurial/templates/gitweb/filediff.tmpl
> +++ b/mercurial/templates/gitweb/filecomparison.tmpl
> @@ -1,5 +1,5 @@
>  {header}
> -<title>{repo|escape}: diff {file|escape}</title>
> +<title>{repo|escape}: comparison {file|escape}</title>
>  <link rel="alternate" type="application/atom+xml"
>     href="{url}atom-log" title="Atom feed for {repo|escape}"/>
>  <link rel="alternate" type="application/rss+xml"
> @@ -8,7 +8,7 @@
>  <body>
>
>  <div class="page_header">
> -<a href="{logourl}" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / diff
> +<a href="{logourl}" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / comparison
>  </div>
>
>  <div class="page_nav">
> @@ -25,7 +25,8 @@
>  <a href="{url}file/tip/{file|urlescape}{sessionvars%urlparameter}">latest</a> |
>  <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a> |
>  <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> |
> -diff |
> +<a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
> +comparison |
>  <a href="{url}raw-diff/{node|short}/{file|urlescape}">raw</a> |
>  <a href="{url}help{sessionvars%urlparameter}">help</a>
>  <br/>
> @@ -38,14 +39,25 @@
>  <tr>
>   <td>changeset {rev}</td>
>   <td style="font-family:monospace"><a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>
> -{parent%filediffparent}
> -{child%filediffchild}
> +{parent%filecompparent}
> +{child%filecompchild}
>  </table>
>
>  <div class="list_head"></div>
>
>  <div class="page_body">
> -{diff}
> +
> +<div class="legend">
> +  <span class="legendinfo equal">equal</span>
> +  <span class="legendinfo delete">deleted</span>
> +  <span class="legendinfo insert">inserted</span>
> +  <span class="legendinfo replace">replaced</span>
> +</div>
> +
> +<div class="comparison">
> +{comparison}
> +</div>
> +
>  </div>
>
>  {footer}
> diff --git a/mercurial/templates/gitweb/filediff.tmpl b/mercurial/templates/gitweb/filediff.tmpl
> --- a/mercurial/templates/gitweb/filediff.tmpl
> +++ b/mercurial/templates/gitweb/filediff.tmpl
> @@ -26,6 +26,7 @@
>  <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a> |
>  <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> |
>  diff |
> +<a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a> |
>  <a href="{url}raw-diff/{node|short}/{file|urlescape}">raw</a> |
>  <a href="{url}help{sessionvars%urlparameter}">help</a>
>  <br/>
> diff --git a/mercurial/templates/gitweb/filelog.tmpl b/mercurial/templates/gitweb/filelog.tmpl
> --- a/mercurial/templates/gitweb/filelog.tmpl
> +++ b/mercurial/templates/gitweb/filelog.tmpl
> @@ -23,6 +23,7 @@
>  revisions |
>  <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> |
>  <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
> +<a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a> |
>  <a href="{url}rss-log/tip/{file|urlescape}">rss</a> |
>  <a href="{url}help{sessionvars%urlparameter}">help</a>
>  <br/>
> diff --git a/mercurial/templates/gitweb/filerevision.tmpl b/mercurial/templates/gitweb/filerevision.tmpl
> --- a/mercurial/templates/gitweb/filerevision.tmpl
> +++ b/mercurial/templates/gitweb/filerevision.tmpl
> @@ -26,6 +26,7 @@
>  <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a> |
>  <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> |
>  <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
> +<a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a> |
>  <a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a> |
>  <a href="{url}help{sessionvars%urlparameter}">help</a>
>  <br/>
> diff --git a/mercurial/templates/gitweb/map b/mercurial/templates/gitweb/map
> --- a/mercurial/templates/gitweb/map
> +++ b/mercurial/templates/gitweb/map
> @@ -26,6 +26,7 @@
>        <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> |
>        <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> |
>        <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
> +      <a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a> |
>        <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a>
>      </td>
>    </tr>'
> @@ -37,6 +38,7 @@
>        file |
>        annotate |
>        <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
> +      <a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a> |
>        <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a>
>      </td>
>    </tr>'
> @@ -81,6 +83,7 @@
>  filerevision = filerevision.tmpl
>  fileannotate = fileannotate.tmpl
>  filediff = filediff.tmpl
> +filecomparison = filecomparison.tmpl
>  filelog = filelog.tmpl
>  fileline = '
>    <div style="font-family:monospace" class="parity{parity}">
> @@ -99,6 +102,27 @@
>  difflineminus = '<span style="color:#cc0000;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
>  difflineat = '<span style="color:#990099;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
>  diffline = '<span><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
> +
> +comparison = '
> +  <table style="border-collapse:collapse;">
> +    <thead class="header">
> +      <tr>
> +        <th>{leftrev}:{leftnode|short}</th>
> +        <th>{rightrev}:{rightnode|short}</th>
> +      </tr>
> +    </thead>
> +    {blocks}
> +  </table>'
> +comparisonblock ='
> +  <tbody class="block">
> +  {lines}
> +  </tbody>'
> +comparisonline = '
> +  <tr style="font-family:monospace">
> +    <td class="{type}"><pre><a class="linenr" href="#{lineid}" id="{lineid}">{leftlinenumber}</a> {leftline|escape}</pre></td>
> +    <td class="{type}"><pre><a class="linenr" href="#{lineid}" id="{lineid}">{rightlinenumber}</a> {rightline|escape}</pre></td>
> +  </tr>'
> +
>  changelogparent = '
>    <tr>
>      <th class="parent">parent {rev}:</th>
> @@ -203,6 +227,15 @@
>        </a>
>      </td>
>    </tr>'
> +filecompparent = '
> +  <tr>
> +    <td>parent {rev}</td>
> +    <td style="font-family:monospace">
> +      <a class="list" href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
> +        {node|short}
> +      </a>
> +    </td>
> +  </tr>'
>  filelogparent = '
>    <tr>
>      <td align="right">parent {rev}: </td>
> @@ -215,6 +248,13 @@
>        <a class="list" href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a>
>      </td>
>    </tr>'
> +filecompchild = '
> +  <tr>
> +    <td>child {rev}</td>
> +    <td style="font-family:monospace">
> +      <a class="list" href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a>
> +    </td>
> +  </tr>'
>  filelogchild = '
>    <tr>
>      <td align="right">child {rev}: </td>
> diff --git a/mercurial/templates/monoblue/fileannotate.tmpl b/mercurial/templates/monoblue/fileannotate.tmpl
> --- a/mercurial/templates/monoblue/fileannotate.tmpl
> +++ b/mercurial/templates/monoblue/fileannotate.tmpl
> @@ -35,6 +35,7 @@
>          <li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a></li>
>          <li class="current">annotate</li>
>          <li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
> +        <li><a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a></li>
>          <li><a href="{url}raw-annotate/{node|short}/{file|urlescape}">raw</a></li>
>      </ul>
>
> diff --git a/mercurial/templates/monoblue/filediff.tmpl b/mercurial/templates/monoblue/filecomparison.tmpl
> copy from mercurial/templates/monoblue/filediff.tmpl
> copy to mercurial/templates/monoblue/filecomparison.tmpl
> --- a/mercurial/templates/monoblue/filediff.tmpl
> +++ b/mercurial/templates/monoblue/filecomparison.tmpl
> @@ -1,5 +1,5 @@
>  {header}
> -<title>{repo|escape}: diff {file|escape}</title>
> +<title>{repo|escape}: comparison {file|escape}</title>
>      <link rel="alternate" type="application/atom+xml" href="{url}atom-log" title="Atom feed for {repo|escape}"/>
>      <link rel="alternate" type="application/rss+xml" href="{url}rss-log" title="RSS feed for {repo|escape}"/>
>  </head>
> @@ -7,7 +7,7 @@
>  <body>
>  <div id="container">
>      <div class="page-header">
> -        <h1><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / file diff</h1>
> +        <h1><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / file comparison</h1>
>
>          <form action="{url}log">
>              {sessionvars%hiddenformentry}
> @@ -34,23 +34,31 @@
>          <li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
>          <li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a></li>
>          <li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
> -        <li class="current">diff</li>
> +        <li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
> +        <li class="current">comparison</li>
>          <li><a href="{url}raw-diff/{node|short}/{file|urlescape}">raw</a></li>
>      </ul>
>
> -    <h2 class="no-link no-border">diff: {file|escape}</h2>
> +    <h2 class="no-link no-border">comparison: {file|escape}</h2>
>      <h3 class="changeset">{file|escape}</h3>
>
>      <dl class="overview">
>          {branch%filerevbranch}
>          <dt>changeset {rev}</dt>
>          <dd><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></dd>
> -        {parent%filediffparent}
> -        {child%filediffchild}
> +        {parent%filecompparent}
> +        {child%filecompchild}
>      </dl>
>
> -    <div class="diff">
> -    {diff}
> +    <div class="legend">
> +      <span class="legendinfo equal">equal</span>
> +      <span class="legendinfo delete">deleted</span>
> +      <span class="legendinfo insert">inserted</span>
> +      <span class="legendinfo replace">replaced</span>
> +    </div>
> +
> +    <div class="comparison">
> +    {comparison}
>      </div>
>
>  {footer}
> diff --git a/mercurial/templates/monoblue/filediff.tmpl b/mercurial/templates/monoblue/filediff.tmpl
> --- a/mercurial/templates/monoblue/filediff.tmpl
> +++ b/mercurial/templates/monoblue/filediff.tmpl
> @@ -35,6 +35,7 @@
>          <li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a></li>
>          <li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
>          <li class="current">diff</li>
> +        <li><a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a></li>
>          <li><a href="{url}raw-diff/{node|short}/{file|urlescape}">raw</a></li>
>      </ul>
>
> diff --git a/mercurial/templates/monoblue/filelog.tmpl b/mercurial/templates/monoblue/filelog.tmpl
> --- a/mercurial/templates/monoblue/filelog.tmpl
> +++ b/mercurial/templates/monoblue/filelog.tmpl
> @@ -35,6 +35,7 @@
>          <li class="current">revisions</li>
>          <li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
>          <li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
> +        <li><a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a></li>
>          <li><a href="{url}rss-log/tip/{file|urlescape}">rss</a></li>
>      </ul>
>
> diff --git a/mercurial/templates/monoblue/filerevision.tmpl b/mercurial/templates/monoblue/filerevision.tmpl
> --- a/mercurial/templates/monoblue/filerevision.tmpl
> +++ b/mercurial/templates/monoblue/filerevision.tmpl
> @@ -35,6 +35,7 @@
>          <li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a></li>
>          <li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
>          <li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
> +        <li><a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a></li>
>          <li><a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a></li>
>      </ul>
>
> diff --git a/mercurial/templates/monoblue/map b/mercurial/templates/monoblue/map
> --- a/mercurial/templates/monoblue/map
> +++ b/mercurial/templates/monoblue/map
> @@ -26,6 +26,7 @@
>        <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> |
>        <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> |
>        <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
> +      <a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a> |
>        <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a>
>      </td>
>    </tr>'
> @@ -37,6 +38,7 @@
>        file |
>        annotate |
>        <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
> +      <a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a> |
>        <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a>
>      </td>
>    </tr>'
> @@ -74,6 +76,7 @@
>  filerevision = filerevision.tmpl
>  fileannotate = fileannotate.tmpl
>  filediff = filediff.tmpl
> +filecomparison = filecomparison.tmpl
>  filelog = filelog.tmpl
>  fileline = '
>    <div style="font-family:monospace" class="parity{parity}">
> @@ -94,6 +97,27 @@
>  difflineminus = '<span style="color:#cc0000;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
>  difflineat = '<span style="color:#990099;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
>  diffline = '<span><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
> +
> +comparison = '
> +  <table class="bigtable">
> +    <thead class="header">
> +      <tr>
> +        <th>{leftrev}:{leftnode|short}</th>
> +        <th>{rightrev}:{rightnode|short}</th>
> +      </tr>
> +    </thead>
> +    {blocks}
> +  </table>'
> +comparisonblock ='
> +  <tbody class="block">
> +  {lines}
> +  </tbody>'
> +comparisonline = '
> +  <tr>
> +    <td class="source {type}"><a class="linenr" href="#{lineid}" id="{lineid}">{leftlinenumber}</a> {leftline|escape}</td>
> +    <td class="source {type}"><a class="linenr" href="#{lineid}" id="{lineid}">{rightlinenumber}</a> {rightline|escape}</td>
> +  </tr>'
> +
>  changelogparent = '
>    <tr>
>      <th class="parent">parent {rev}:</th>
> @@ -176,6 +200,9 @@
>  filediffparent = '
>    <dt>parent {rev}</dt>
>    <dd><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></dd>'
> +filecompparent = '
> +  <dt>parent {rev}</dt>
> +  <dd><a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></dd>'
>  filelogparent = '
>    <tr>
>      <td align="right">parent {rev}: </td>
> @@ -184,6 +211,9 @@
>  filediffchild = '
>    <dt>child {rev}</dt>
>    <dd><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></dd>'
> +filecompchild = '
> +  <dt>child {rev}</dt>
> +  <dd><a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></dd>'
>  filelogchild = '
>    <tr>
>      <td align="right">child {rev}: </td>
> diff --git a/mercurial/templates/paper/fileannotate.tmpl b/mercurial/templates/paper/fileannotate.tmpl
> --- a/mercurial/templates/paper/fileannotate.tmpl
> +++ b/mercurial/templates/paper/fileannotate.tmpl
> @@ -25,6 +25,7 @@
>  <li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
>  <li><a href="{url}file/tip/{file|urlescape}{sessionvars%urlparameter}">latest</a></li>
>  <li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
> +<li><a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a></li>
>  <li class="active">annotate</li>
>  <li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
>  <li><a href="{url}raw-annotate/{node|short}/{file|urlescape}">raw</a></li>
> diff --git a/mercurial/templates/paper/filediff.tmpl b/mercurial/templates/paper/filecomparison.tmpl
> copy from mercurial/templates/paper/filediff.tmpl
> copy to mercurial/templates/paper/filecomparison.tmpl
> --- a/mercurial/templates/paper/filediff.tmpl
> +++ b/mercurial/templates/paper/filecomparison.tmpl
> @@ -1,5 +1,5 @@
>  {header}
> -<title>{repo|escape}: {file|escape} diff</title>
> +<title>{repo|escape}: {file|escape} comparison</title>
>  </head>
>  <body>
>
> @@ -23,7 +23,8 @@
>  <ul>
>  <li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
>  <li><a href="{url}file/tip/{file|urlescape}{sessionvars%urlparameter}">latest</a></li>
> -<li class="active">diff</li>
> +<li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
> +<li class="active">comparison</li>
>  <li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
>  <li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
>  <li><a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a></li>
> @@ -35,7 +36,7 @@
>
>  <div class="main">
>  <h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
> -<h3>diff {file|escape} @ {rev}:{node|short}</h3>
> +<h3>comparison {file|escape} @ {rev}:{node|short}</h3>
>
>  <form class="search" action="{url}log">
>  <p>{sessionvars%hiddenformentry}</p>
> @@ -67,9 +68,16 @@
>  </table>
>
>  <div class="overflow">
> -<div class="sourcefirst">   line diff</div>
> +<div class="sourcefirst">   comparison</div>
> +<div class="legend">
> +  <span class="legendinfo equal">equal</span>
> +  <span class="legendinfo delete">deleted</span>
> +  <span class="legendinfo insert">inserted</span>
> +  <span class="legendinfo replace">replaced</span>
> +</div>
>
> -{diff}
> +{comparison}
> +
>  </div>
>  </div>
>  </div>
> diff --git a/mercurial/templates/paper/filediff.tmpl b/mercurial/templates/paper/filediff.tmpl
> --- a/mercurial/templates/paper/filediff.tmpl
> +++ b/mercurial/templates/paper/filediff.tmpl
> @@ -24,6 +24,7 @@
>  <li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
>  <li><a href="{url}file/tip/{file|urlescape}{sessionvars%urlparameter}">latest</a></li>
>  <li class="active">diff</li>
> +<li><a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a></li>
>  <li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
>  <li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
>  <li><a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a></li>
> diff --git a/mercurial/templates/paper/filelog.tmpl b/mercurial/templates/paper/filelog.tmpl
> --- a/mercurial/templates/paper/filelog.tmpl
> +++ b/mercurial/templates/paper/filelog.tmpl
> @@ -27,6 +27,7 @@
>  <ul>
>  <li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
>  <li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
> +<li><a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a></li>
>  <li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
>  <li class="active">file log</li>
>  <li><a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a></li>
> diff --git a/mercurial/templates/paper/filerevision.tmpl b/mercurial/templates/paper/filerevision.tmpl
> --- a/mercurial/templates/paper/filerevision.tmpl
> +++ b/mercurial/templates/paper/filerevision.tmpl
> @@ -23,6 +23,7 @@
>  <li class="active">file</li>
>  <li><a href="{url}file/tip/{file|urlescape}{sessionvars%urlparameter}">latest</a></li>
>  <li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
> +<li><a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a></li>
>  <li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
>  <li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
>  <li><a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a></li>
> diff --git a/mercurial/templates/paper/map b/mercurial/templates/paper/map
> --- a/mercurial/templates/paper/map
> +++ b/mercurial/templates/paper/map
> @@ -62,6 +62,7 @@
>  filerevision = filerevision.tmpl
>  fileannotate = fileannotate.tmpl
>  filediff = filediff.tmpl
> +filecomparison = filecomparison.tmpl
>  filelog = filelog.tmpl
>  fileline = '
>    <div class="parity{parity} source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</div>'
> @@ -82,6 +83,26 @@
>  difflineat = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="atline">{line|escape}</span>'
>  diffline = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}'
>
> +comparison = '
> +  <table class="bigtable">
> +    <thead class="header">
> +      <tr>
> +        <th>{leftrev}:{leftnode|short}</th>
> +        <th>{rightrev}:{rightnode|short}</th>
> +      </tr>
> +    </thead>
> +    {blocks}
> +  </table>'
> +comparisonblock ='
> +  <tbody class="block">
> +  {lines}
> +  </tbody>'
> +comparisonline = '
> +  <tr>
> +    <td class="source {type}"><a href="#{lineid}" id="{lineid}">{leftlinenumber}</a> {leftline|escape}</td>
> +    <td class="source {type}"><a href="#{lineid}" id="{lineid}">{rightlinenumber}</a> {rightline|escape}</td>
> +  </tr>'
> +
>  changelogparent = '
>    <tr>
>      <th class="parent">parent {rev}:</th>
> diff --git a/mercurial/templates/static/style-coal.css b/mercurial/templates/static/style-coal.css
> --- a/mercurial/templates/static/style-coal.css
> +++ b/mercurial/templates/static/style-coal.css
> @@ -286,3 +286,40 @@
>         position: relative;
>         top: -3px;
>  }
> +
> +/* Comparison */
> +.legend {
> +    padding: 1.5% 0 1.5% 0;
> +}
> +
> +.legendinfo {
> +    border: 1px solid #999;
> +    font-size: 80%;
> +    text-align: center;
> +    padding: 0.5%;
> +}
> +
> +.equal {
> +    background-color: #ffffff;
> +}
> +
> +.delete {
> +    background-color: black;
> +    color: white;
> +}
> +
> +.insert {
> +    background-color: #d0d0d0;
> +}
> +
> +.replace {
> +    background-color: #f9f9f9;
> +}
> +
> +.header {
> +    text-align: center;
> +}
> +
> +.block {
> +    border-top: 1px solid #999;
> +}
> diff --git a/mercurial/templates/static/style-gitweb.css b/mercurial/templates/static/style-gitweb.css
> --- a/mercurial/templates/static/style-gitweb.css
> +++ b/mercurial/templates/static/style-gitweb.css
> @@ -126,3 +126,43 @@
>         top: -3px;
>         font-style: italic;
>  }
> +
> +/* Comparison */
> +.legend {
> +    padding: 1.5% 0 1.5% 0;
> +}
> +
> +.legendinfo {
> +    border: 1px solid #d9d8d1;
> +    font-size: 80%;
> +    text-align: center;
> +    padding: 0.5%;
> +}
> +
> +.equal {
> +    background-color: #ffffff;
> +}
> +
> +.delete {
> +    background-color: #ffc5ce;
> +}
> +
> +.insert {
> +    background-color: #c5ffc4;
> +}
> +
> +.replace {
> +    background-color: #ffff99;
> +}
> +
> +.comparison {
> +    overflow-x: auto;
> +}
> +
> +.header th {
> +    text-align: center;
> +}
> +
> +.block {
> +    border-top: 1px solid #d9d8d1;
> +}
> diff --git a/mercurial/templates/static/style-monoblue.css b/mercurial/templates/static/style-monoblue.css
> --- a/mercurial/templates/static/style-monoblue.css
> +++ b/mercurial/templates/static/style-monoblue.css
> @@ -477,3 +477,49 @@
>         position: relative;
>  }
>  /** end of canvas **/
> +
> +/** comparison **/
> +.legend {
> +    margin-left: 20px;
> +    padding: 1.5% 0 1.5% 0;
> +}
> +
> +.legendinfo {
> +    border: 1px solid #999;
> +    font-size: 80%;
> +    text-align: center;
> +    padding: 0.5%;
> +}
> +
> +.equal {
> +    background-color: #ffffff;
> +}
> +
> +.delete {
> +    background-color: #ffc5ce;
> +}
> +
> +.insert {
> +    background-color: #c5ffc4;
> +}
> +
> +.replace {
> +    background-color: #ffff99;
> +}
> +
> +.comparison {
> +    overflow-x: auto;
> +}
> +
> +.comparison table td {
> +    padding: 0px 5px;
> +}
> +
> +.header th {
> +    font-weight: bold;
> +}
> +
> +.block {
> +    border-top: 1px solid #999;
> +}
> +/** end of comparison **/
> diff --git a/mercurial/templates/static/style-paper.css b/mercurial/templates/static/style-paper.css
> --- a/mercurial/templates/static/style-paper.css
> +++ b/mercurial/templates/static/style-paper.css
> @@ -275,3 +275,39 @@
>         position: relative;
>         top: -3px;
>  }
> +
> +/* Comparison */
> +.legend {
> +    padding: 1.5% 0 1.5% 0;
> +}
> +
> +.legendinfo {
> +    border: 1px solid #999;
> +    font-size: 80%;
> +    text-align: center;
> +    padding: 0.5%;
> +}
> +
> +.equal {
> +    background-color: #ffffff;
> +}
> +
> +.delete {
> +    background-color: #ffc5ce;
> +}
> +
> +.insert {
> +    background-color: #c5ffc4;
> +}
> +
> +.replace {
> +    background-color: #ffff99;
> +}
> +
> +.header {
> +    text-align: center;
> +}
> +
> +.block {
> +    border-top: 1px solid #999;
> +}
> diff --git a/tests/test-hgweb-commands.t b/tests/test-hgweb-commands.t
> --- a/tests/test-hgweb-commands.t
> +++ b/tests/test-hgweb-commands.t
> @@ -605,6 +605,7 @@
>    <li class="active">file</li>
>    <li><a href="/file/tip/foo">latest</a></li>
>    <li><a href="/diff/a4f92ed23982/foo">diff</a></li>
> +  <li><a href="/comparison/a4f92ed23982/foo">comparison</a></li>
>    <li><a href="/annotate/a4f92ed23982/foo">annotate</a></li>
>    <li><a href="/log/a4f92ed23982/foo">file log</a></li>
>    <li><a href="/raw-file/a4f92ed23982/foo">raw</a></li>
> diff --git a/tests/test-hgweb-diffs.t b/tests/test-hgweb-diffs.t
> --- a/tests/test-hgweb-diffs.t
> +++ b/tests/test-hgweb-diffs.t
> @@ -227,6 +227,7 @@
>    <li><a href="/file/559edbd9ed20/b">file</a></li>
>    <li><a href="/file/tip/b">latest</a></li>
>    <li class="active">diff</li>
> +  <li><a href="/comparison/559edbd9ed20/b">comparison</a></li>
>    <li><a href="/annotate/559edbd9ed20/b">annotate</a></li>
>    <li><a href="/log/559edbd9ed20/b">file log</a></li>
>    <li><a href="/raw-file/559edbd9ed20/b">raw</a></li>
> @@ -491,6 +492,7 @@
>    <li><a href="/file/559edbd9ed20/a">file</a></li>
>    <li><a href="/file/tip/a">latest</a></li>
>    <li class="active">diff</li>
> +  <li><a href="/comparison/559edbd9ed20/a">comparison</a></li>
>    <li><a href="/annotate/559edbd9ed20/a">annotate</a></li>
>    <li><a href="/log/559edbd9ed20/a">file log</a></li>
>    <li><a href="/raw-file/559edbd9ed20/a">raw</a></li>
> @@ -549,6 +551,378 @@
>    </body>
>    </html>
>
> +
> +comparison new file
> +
> +  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/0/a'
> +  200 Script output follows
> +
> +  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
> +  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
> +  <head>
> +  <link rel="icon" href="/static/hgicon.png" type="image/png" />
> +  <meta name="robots" content="index, nofollow" />
> +  <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
> +  <script type="text/javascript" src="/static/mercurial.js"></script>
> +
> +  <title>test: a comparison</title>
> +  </head>
> +  <body>
> +
> +  <div class="container">
> +  <div class="menu">
> +  <div class="logo">
> +  <a href="http://mercurial.selenic.com/">
> +  <img src="/static/hglogo.png" alt="mercurial" /></a>
> +  </div>
> +  <ul>
> +  <li><a href="/shortlog/0cd96de13884">log</a></li>
> +  <li><a href="/graph/0cd96de13884">graph</a></li>
> +  <li><a href="/tags">tags</a></li>
> +  <li><a href="/bookmarks">bookmarks</a></li>
> +  <li><a href="/branches">branches</a></li>
> +  </ul>
> +  <ul>
> +  <li><a href="/rev/0cd96de13884">changeset</a></li>
> +  <li><a href="/file/0cd96de13884">browse</a></li>
> +  </ul>
> +  <ul>
> +  <li><a href="/file/0cd96de13884/a">file</a></li>
> +  <li><a href="/file/tip/a">latest</a></li>
> +  <li><a href="/diff/0cd96de13884/a">diff</a></li>
> +  <li class="active">comparison</li>
> +  <li><a href="/annotate/0cd96de13884/a">annotate</a></li>
> +  <li><a href="/log/0cd96de13884/a">file log</a></li>
> +  <li><a href="/raw-file/0cd96de13884/a">raw</a></li>
> +  </ul>
> +  <ul>
> +  <li><a href="/help">help</a></li>
> +  </ul>
> +  </div>
> +
> +  <div class="main">
> +  <h2><a href="/">test</a></h2>
> +  <h3>comparison a @ 0:0cd96de13884</h3>
> +
> +  <form class="search" action="/log">
> +  <p></p>
> +  <p><input name="rev" id="search1" type="text" size="30" /></p>
> +  <div id="hint">find changesets by author, revision,
> +  files, or words in the commit message</div>
> +  </form>
> +
> +  <div class="description">a</div>
> +
> +  <table id="changesetEntry">
> +  <tr>
> +   <th>author</th>
> +   <td>test</td>
> +  </tr>
> +  <tr>
> +   <th>date</th>
> +   <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
> +  </tr>
> +  <tr>
> +   <th>parents</th>
> +   <td></td>
> +  </tr>
> +  <tr>
> +   <th>children</th>
> +   <td><a href="/file/559edbd9ed20/a">559edbd9ed20</a> </td>
> +  </tr>
> +
> +  </table>
> +
> +  <div class="overflow">
> +  <div class="sourcefirst">   comparison</div>
> +  <div class="legend">
> +    <span class="legendinfo equal">equal</span>
> +    <span class="legendinfo delete">deleted</span>
> +    <span class="legendinfo insert">inserted</span>
> +    <span class="legendinfo replace">replaced</span>
> +  </div>
> +
> +
> +  <table class="bigtable">
> +  <thead class="header">
> +  <tr>
> +  <th>-1:000000000000</th>
> +  <th>0:b789fdd96dc2</th>
> +  </tr>
> +  </thead>
> +
> +  <tbody class="block">
> +
> +  <tr>
> +  <td class="source insert"><a href="#r1" id="r1">      </a> </td>
> +  <td class="source insert"><a href="#r1" id="r1">     1</a> a</td>
> +  </tr>
> +  </tbody>
> +  </table>
> +
> +  </div>
> +  </div>
> +  </div>
> +
> +  <script type="text/javascript">process_dates()</script>
> +
> +
> +  </body>
> +  </html>
> +
> +
> +comparison existing file
> +
> +  $ hg up
> +  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ echo a >> a
> +  $ hg ci -mc
> +  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/tip/a'
> +  200 Script output follows
> +
> +  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
> +  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
> +  <head>
> +  <link rel="icon" href="/static/hgicon.png" type="image/png" />
> +  <meta name="robots" content="index, nofollow" />
> +  <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
> +  <script type="text/javascript" src="/static/mercurial.js"></script>
> +
> +  <title>test: a comparison</title>
> +  </head>
> +  <body>
> +
> +  <div class="container">
> +  <div class="menu">
> +  <div class="logo">
> +  <a href="http://mercurial.selenic.com/">
> +  <img src="/static/hglogo.png" alt="mercurial" /></a>
> +  </div>
> +  <ul>
> +  <li><a href="/shortlog/d73db4d812ff">log</a></li>
> +  <li><a href="/graph/d73db4d812ff">graph</a></li>
> +  <li><a href="/tags">tags</a></li>
> +  <li><a href="/bookmarks">bookmarks</a></li>
> +  <li><a href="/branches">branches</a></li>
> +  </ul>
> +  <ul>
> +  <li><a href="/rev/d73db4d812ff">changeset</a></li>
> +  <li><a href="/file/d73db4d812ff">browse</a></li>
> +  </ul>
> +  <ul>
> +  <li><a href="/file/d73db4d812ff/a">file</a></li>
> +  <li><a href="/file/tip/a">latest</a></li>
> +  <li><a href="/diff/d73db4d812ff/a">diff</a></li>
> +  <li class="active">comparison</li>
> +  <li><a href="/annotate/d73db4d812ff/a">annotate</a></li>
> +  <li><a href="/log/d73db4d812ff/a">file log</a></li>
> +  <li><a href="/raw-file/d73db4d812ff/a">raw</a></li>
> +  </ul>
> +  <ul>
> +  <li><a href="/help">help</a></li>
> +  </ul>
> +  </div>
> +
> +  <div class="main">
> +  <h2><a href="/">test</a></h2>
> +  <h3>comparison a @ 2:d73db4d812ff</h3>
> +
> +  <form class="search" action="/log">
> +  <p></p>
> +  <p><input name="rev" id="search1" type="text" size="30" /></p>
> +  <div id="hint">find changesets by author, revision,
> +  files, or words in the commit message</div>
> +  </form>
> +
> +  <div class="description">c</div>
> +
> +  <table id="changesetEntry">
> +  <tr>
> +   <th>author</th>
> +   <td>test</td>
> +  </tr>
> +  <tr>
> +   <th>date</th>
> +   <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
> +  </tr>
> +  <tr>
> +   <th>parents</th>
> +   <td><a href="/file/559edbd9ed20/a">559edbd9ed20</a> </td>
> +  </tr>
> +  <tr>
> +   <th>children</th>
> +   <td></td>
> +  </tr>
> +
> +  </table>
> +
> +  <div class="overflow">
> +  <div class="sourcefirst">   comparison</div>
> +  <div class="legend">
> +    <span class="legendinfo equal">equal</span>
> +    <span class="legendinfo delete">deleted</span>
> +    <span class="legendinfo insert">inserted</span>
> +    <span class="legendinfo replace">replaced</span>
> +  </div>
> +
> +
> +  <table class="bigtable">
> +  <thead class="header">
> +  <tr>
> +  <th>0:b789fdd96dc2</th>
> +  <th>1:a80d06849b33</th>
> +  </tr>
> +  </thead>
> +
> +  <tbody class="block">
> +
> +  <tr>
> +  <td class="source equal"><a href="#l1r1" id="l1r1">     1</a> a</td>
> +  <td class="source equal"><a href="#l1r1" id="l1r1">     1</a> a</td>
> +  </tr>
> +  <tr>
> +  <td class="source insert"><a href="#r2" id="r2">      </a> </td>
> +  <td class="source insert"><a href="#r2" id="r2">     2</a> a</td>
> +  </tr>
> +  </tbody>
> +  </table>
> +
> +  </div>
> +  </div>
> +  </div>
> +
> +  <script type="text/javascript">process_dates()</script>
> +
> +
> +  </body>
> +  </html>
> +
> +
> +comparison removed file
> +
> +  $ hg rm a
> +  $ hg ci -md
> +  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/tip/a'
> +  200 Script output follows
> +
> +  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
> +  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
> +  <head>
> +  <link rel="icon" href="/static/hgicon.png" type="image/png" />
> +  <meta name="robots" content="index, nofollow" />
> +  <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
> +  <script type="text/javascript" src="/static/mercurial.js"></script>
> +
> +  <title>test: a comparison</title>
> +  </head>
> +  <body>
> +
> +  <div class="container">
> +  <div class="menu">
> +  <div class="logo">
> +  <a href="http://mercurial.selenic.com/">
> +  <img src="/static/hglogo.png" alt="mercurial" /></a>
> +  </div>
> +  <ul>
> +  <li><a href="/shortlog/20e80271eb7a">log</a></li>
> +  <li><a href="/graph/20e80271eb7a">graph</a></li>
> +  <li><a href="/tags">tags</a></li>
> +  <li><a href="/bookmarks">bookmarks</a></li>
> +  <li><a href="/branches">branches</a></li>
> +  </ul>
> +  <ul>
> +  <li><a href="/rev/20e80271eb7a">changeset</a></li>
> +  <li><a href="/file/20e80271eb7a">browse</a></li>
> +  </ul>
> +  <ul>
> +  <li><a href="/file/20e80271eb7a/a">file</a></li>
> +  <li><a href="/file/tip/a">latest</a></li>
> +  <li><a href="/diff/20e80271eb7a/a">diff</a></li>
> +  <li class="active">comparison</li>
> +  <li><a href="/annotate/20e80271eb7a/a">annotate</a></li>
> +  <li><a href="/log/20e80271eb7a/a">file log</a></li>
> +  <li><a href="/raw-file/20e80271eb7a/a">raw</a></li>
> +  </ul>
> +  <ul>
> +  <li><a href="/help">help</a></li>
> +  </ul>
> +  </div>
> +
> +  <div class="main">
> +  <h2><a href="/">test</a></h2>
> +  <h3>comparison a @ 3:20e80271eb7a</h3>
> +
> +  <form class="search" action="/log">
> +  <p></p>
> +  <p><input name="rev" id="search1" type="text" size="30" /></p>
> +  <div id="hint">find changesets by author, revision,
> +  files, or words in the commit message</div>
> +  </form>
> +
> +  <div class="description">d</div>
> +
> +  <table id="changesetEntry">
> +  <tr>
> +   <th>author</th>
> +   <td>test</td>
> +  </tr>
> +  <tr>
> +   <th>date</th>
> +   <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
> +  </tr>
> +  <tr>
> +   <th>parents</th>
> +   <td><a href="/file/d73db4d812ff/a">d73db4d812ff</a> </td>
> +  </tr>
> +  <tr>
> +   <th>children</th>
> +   <td></td>
> +  </tr>
> +
> +  </table>
> +
> +  <div class="overflow">
> +  <div class="sourcefirst">   comparison</div>
> +  <div class="legend">
> +    <span class="legendinfo equal">equal</span>
> +    <span class="legendinfo delete">deleted</span>
> +    <span class="legendinfo insert">inserted</span>
> +    <span class="legendinfo replace">replaced</span>
> +  </div>
> +
> +
> +  <table class="bigtable">
> +  <thead class="header">
> +  <tr>
> +  <th>1:a80d06849b33</th>
> +  <th>-1:000000000000</th>
> +  </tr>
> +  </thead>
> +
> +  <tbody class="block">
> +
> +  <tr>
> +  <td class="source delete"><a href="#l1" id="l1">     1</a> a</td>
> +  <td class="source delete"><a href="#l1" id="l1">      </a> </td>
> +  </tr>
> +  <tr>
> +  <td class="source delete"><a href="#l2" id="l2">     2</a> a</td>
> +  <td class="source delete"><a href="#l2" id="l2">      </a> </td>
> +  </tr>
> +  </tbody>
> +  </table>
> +
> +  </div>
> +  </div>
> +  </div>
> +
> +  <script type="text/javascript">process_dates()</script>
> +
> +
> +  </body>
> +  </html>
> +
> +
>    $ cd ..
>
>  test import rev as raw-rev
> diff --git a/tests/test-hgweb-filelog.t b/tests/test-hgweb-filelog.t
> --- a/tests/test-hgweb-filelog.t
> +++ b/tests/test-hgweb-filelog.t
> @@ -148,6 +148,7 @@
>    <ul>
>    <li><a href="/file/01de2d66a28d/a">file</a></li>
>    <li><a href="/diff/01de2d66a28d/a">diff</a></li>
> +  <li><a href="/comparison/01de2d66a28d/a">comparison</a></li>
>    <li><a href="/annotate/01de2d66a28d/a">annotate</a></li>
>    <li class="active">file log</li>
>    <li><a href="/raw-file/01de2d66a28d/a">raw</a></li>
> @@ -249,6 +250,7 @@
>    <ul>
>    <li><a href="/file/01de2d66a28d/a">file</a></li>
>    <li><a href="/diff/01de2d66a28d/a">diff</a></li>
> +  <li><a href="/comparison/01de2d66a28d/a">comparison</a></li>
>    <li><a href="/annotate/01de2d66a28d/a">annotate</a></li>
>    <li class="active">file log</li>
>    <li><a href="/raw-file/01de2d66a28d/a">raw</a></li>
> @@ -350,6 +352,7 @@
>    <ul>
>    <li><a href="/file/5ed941583260/a">file</a></li>
>    <li><a href="/diff/5ed941583260/a">diff</a></li>
> +  <li><a href="/comparison/5ed941583260/a">comparison</a></li>
>    <li><a href="/annotate/5ed941583260/a">annotate</a></li>
>    <li class="active">file log</li>
>    <li><a href="/raw-file/5ed941583260/a">raw</a></li>
> @@ -446,6 +449,7 @@
>    <ul>
>    <li><a href="/file/5ed941583260/a">file</a></li>
>    <li><a href="/diff/5ed941583260/a">diff</a></li>
> +  <li><a href="/comparison/5ed941583260/a">comparison</a></li>
>    <li><a href="/annotate/5ed941583260/a">annotate</a></li>
>    <li class="active">file log</li>
>    <li><a href="/raw-file/5ed941583260/a">raw</a></li>
> diff --git a/tests/test-hgweb-removed.t b/tests/test-hgweb-removed.t
> --- a/tests/test-hgweb-removed.t
> +++ b/tests/test-hgweb-removed.t
> @@ -171,6 +171,7 @@
>    <li><a href="/file/c78f6c5cbea9/a">file</a></li>
>    <li><a href="/file/tip/a">latest</a></li>
>    <li class="active">diff</li>
> +  <li><a href="/comparison/c78f6c5cbea9/a">comparison</a></li>
>    <li><a href="/annotate/c78f6c5cbea9/a">annotate</a></li>
>    <li><a href="/log/c78f6c5cbea9/a">file log</a></li>
>    <li><a href="/raw-file/c78f6c5cbea9/a">raw</a></li>
> diff --git a/tests/test-hgweb.t b/tests/test-hgweb.t
> --- a/tests/test-hgweb.t
> +++ b/tests/test-hgweb.t
> @@ -437,6 +437,46 @@
>         top: -3px;
>         font-style: italic;
>    }
> +
> +  /* Comparison */
> +  .legend {
> +      padding: 1.5% 0 1.5% 0;
> +  }
> +
> +  .legendinfo {
> +      border: 1px solid #d9d8d1;
> +      font-size: 80%;
> +      text-align: center;
> +      padding: 0.5%;
> +  }
> +
> +  .equal {
> +      background-color: #ffffff;
> +  }
> +
> +  .delete {
> +      background-color: #ffc5ce;
> +  }
> +
> +  .insert {
> +      background-color: #c5ffc4;
> +  }
> +
> +  .replace {
> +      background-color: #ffff99;
> +  }
> +
> +  .comparison {
> +      overflow-x: auto;
> +  }
> +
> +  .header th {
> +      text-align: center;
> +  }
> +
> +  .block {
> +      border-top: 1px solid #d9d8d1;
> +  }
>    304 Not Modified
>
>
> diff --git a/tests/test-highlight.t b/tests/test-highlight.t
> --- a/tests/test-highlight.t
> +++ b/tests/test-highlight.t
> @@ -92,6 +92,7 @@
>    <li class="active">file</li>
>    <li><a href="/file/tip/primes.py">latest</a></li>
>    <li><a href="/diff/853dcd4de2a6/primes.py">diff</a></li>
> +  <li><a href="/comparison/853dcd4de2a6/primes.py">comparison</a></li>
>    <li><a href="/annotate/853dcd4de2a6/primes.py">annotate</a></li>
>    <li><a href="/log/853dcd4de2a6/primes.py">file log</a></li>
>    <li><a href="/raw-file/853dcd4de2a6/primes.py">raw</a></li>
> @@ -222,6 +223,7 @@
>    <li><a href="/file/853dcd4de2a6/primes.py">file</a></li>
>    <li><a href="/file/tip/primes.py">latest</a></li>
>    <li><a href="/diff/853dcd4de2a6/primes.py">diff</a></li>
> +  <li><a href="/comparison/853dcd4de2a6/primes.py">comparison</a></li>
>    <li class="active">annotate</li>
>    <li><a href="/log/853dcd4de2a6/primes.py">file log</a></li>
>    <li><a href="/raw-annotate/853dcd4de2a6/primes.py">raw</a></li>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel


More information about the Mercurial-devel mailing list