Patchwork [10,of,10,RESEND] hgweb: use patch.diffhunks in webutil.diffs to simplify the algorithm

login
register
mail settings
Submitter Denis Laxalde
Date March 9, 2017, 8:08 a.m.
Message ID <e46d8c7684398f1ea1ce.1489046887@sh77.tls.logilab.fr>
Download mbox | patch
Permalink /patch/19060/
State Accepted
Headers show

Comments

Denis Laxalde - March 9, 2017, 8:08 a.m.
# HG changeset patch
# User Denis Laxalde <denis.laxalde@logilab.fr>
# Date 1488788913 -3600
#      Mon Mar 06 09:28:33 2017 +0100
# Node ID e46d8c7684398f1ea1ceab0d8ea5ed5561cd0680
# Parent  48a6d7717d8cde08abd448c392724cf8cb4b5282
# Available At http://hg.logilab.org/users/dlaxalde/hg
#              hg pull http://hg.logilab.org/users/dlaxalde/hg -r e46d8c768439
# EXP-Topic diffhunks
hgweb: use patch.diffhunks in webutil.diffs to simplify the algorithm

Function patch.diffhunks yields items for a "block" (i.e. a file) as a whole
so take advantage of this to simplify the algorithm and avoid parsing diff
lines to determine whether we're starting a new "block" or not. Thus we drop
to external block counter and rely on diffhunks iterations instead.
We also take advantage of the fact that patch.diffhunks() yields *lines* of
hunks (instead of a string) to avoid building a list that is ''.join-ed into a
string that is then split.

As lines in 'header' returned by patch.diffhunks() have no trailing new line,
we need to insert it ourselves to match template expectations.
Augie Fackler - March 10, 2017, 12:05 a.m.
On Thu, Mar 09, 2017 at 09:08:07AM +0100, Denis Laxalde wrote:
> # HG changeset patch
> # User Denis Laxalde <denis.laxalde@logilab.fr>
> # Date 1488788913 -3600
> #      Mon Mar 06 09:28:33 2017 +0100
> # Node ID e46d8c7684398f1ea1ceab0d8ea5ed5561cd0680
> # Parent  48a6d7717d8cde08abd448c392724cf8cb4b5282
> # Available At http://hg.logilab.org/users/dlaxalde/hg
> #              hg pull http://hg.logilab.org/users/dlaxalde/hg -r e46d8c768439
> # EXP-Topic diffhunks
> hgweb: use patch.diffhunks in webutil.diffs to simplify the algorithm

Queued this, thanks.

>
> Function patch.diffhunks yields items for a "block" (i.e. a file) as a whole
> so take advantage of this to simplify the algorithm and avoid parsing diff
> lines to determine whether we're starting a new "block" or not. Thus we drop
> to external block counter and rely on diffhunks iterations instead.
> We also take advantage of the fact that patch.diffhunks() yields *lines* of
> hunks (instead of a string) to avoid building a list that is ''.join-ed into a
> string that is then split.
>
> As lines in 'header' returned by patch.diffhunks() have no trailing new line,
> we need to insert it ourselves to match template expectations.
>
> diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
> --- a/mercurial/hgweb/webutil.py
> +++ b/mercurial/hgweb/webutil.py
> @@ -412,15 +412,8 @@ def listfilediffs(tmpl, files, node, max
>
>  def diffs(repo, tmpl, ctx, basectx, files, parity, style):
>
> -    def countgen():
> -        start = 1
> -        while True:
> -            yield start
> -            start += 1
> -
> -    blockcount = countgen()
> -    def prettyprintlines(diff, blockno):
> -        for lineno, l in enumerate(diff.splitlines(True), 1):
> +    def prettyprintlines(lines, blockno):
> +        for lineno, l in enumerate(lines, 1):
>              difflineno = "%d.%d" % (blockno, lineno)
>              if l.startswith('+'):
>                  ltype = "difflineplus"
> @@ -445,19 +438,16 @@ def diffs(repo, tmpl, ctx, basectx, file
>      node1 = basectx.node()
>      node2 = ctx.node()
>
> -    block = []
> -    for chunk in patch.diff(repo, node1, node2, m, opts=diffopts):
> -        if chunk.startswith('diff') and block:
> -            blockno = next(blockcount)
> +    diffhunks = patch.diffhunks(repo, node1, node2, m, opts=diffopts)
> +    for blockno, (header, hunks) in enumerate(diffhunks, 1):
> +        if style != 'raw':
> +            header = header[1:]
> +        lines = [h + '\n' for h in header]
> +        for hunkrange, hunklines in hunks:
> +            lines.extend(hunklines)
> +        if lines:
>              yield tmpl('diffblock', parity=next(parity), blockno=blockno,
> -                       lines=prettyprintlines(''.join(block), blockno))
> -            block = []
> -        if chunk.startswith('diff') and style != 'raw':
> -            chunk = ''.join(chunk.splitlines(True)[1:])
> -        block.append(chunk)
> -    blockno = next(blockcount)
> -    yield tmpl('diffblock', parity=next(parity), blockno=blockno,
> -               lines=prettyprintlines(''.join(block), blockno))
> +                       lines=prettyprintlines(lines, blockno))
>
>  def compare(tmpl, context, leftlines, rightlines):
>      '''Generator function that provides side-by-side comparison data.'''
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Patch

diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -412,15 +412,8 @@  def listfilediffs(tmpl, files, node, max
 
 def diffs(repo, tmpl, ctx, basectx, files, parity, style):
 
-    def countgen():
-        start = 1
-        while True:
-            yield start
-            start += 1
-
-    blockcount = countgen()
-    def prettyprintlines(diff, blockno):
-        for lineno, l in enumerate(diff.splitlines(True), 1):
+    def prettyprintlines(lines, blockno):
+        for lineno, l in enumerate(lines, 1):
             difflineno = "%d.%d" % (blockno, lineno)
             if l.startswith('+'):
                 ltype = "difflineplus"
@@ -445,19 +438,16 @@  def diffs(repo, tmpl, ctx, basectx, file
     node1 = basectx.node()
     node2 = ctx.node()
 
-    block = []
-    for chunk in patch.diff(repo, node1, node2, m, opts=diffopts):
-        if chunk.startswith('diff') and block:
-            blockno = next(blockcount)
+    diffhunks = patch.diffhunks(repo, node1, node2, m, opts=diffopts)
+    for blockno, (header, hunks) in enumerate(diffhunks, 1):
+        if style != 'raw':
+            header = header[1:]
+        lines = [h + '\n' for h in header]
+        for hunkrange, hunklines in hunks:
+            lines.extend(hunklines)
+        if lines:
             yield tmpl('diffblock', parity=next(parity), blockno=blockno,
-                       lines=prettyprintlines(''.join(block), blockno))
-            block = []
-        if chunk.startswith('diff') and style != 'raw':
-            chunk = ''.join(chunk.splitlines(True)[1:])
-        block.append(chunk)
-    blockno = next(blockcount)
-    yield tmpl('diffblock', parity=next(parity), blockno=blockno,
-               lines=prettyprintlines(''.join(block), blockno))
+                       lines=prettyprintlines(lines, blockno))
 
 def compare(tmpl, context, leftlines, rightlines):
     '''Generator function that provides side-by-side comparison data.'''