Patchwork [7,of,9] patch: add a diffhunks function yielding (diffheaders, hunks)

login
register
mail settings
Submitter Denis Laxalde
Date March 6, 2017, 9:38 a.m.
Message ID <2b3bbcb8cca52db9e0da.1488793105@sh77.tls.logilab.fr>
Download mbox | patch
Permalink /patch/18932/
State Accepted
Headers show

Comments

Denis Laxalde - March 6, 2017, 9:38 a.m.
# HG changeset patch
# User Denis Laxalde <denis.laxalde@logilab.fr>
# Date 1488558011 -3600
#      Fri Mar 03 17:20:11 2017 +0100
# Node ID 2b3bbcb8cca52db9e0dae20dbf028b67a39abc7c
# Parent  07ea362d18b8d2b046822894ecdaded1dc889429
# Available At http://hg.logilab.org/users/dlaxalde/hg
#              hg pull http://hg.logilab.org/users/dlaxalde/hg -r 2b3bbcb8cca5
# EXP-Topic diffhunks
patch: add a diffhunks function yielding (diffheaders, hunks)

trydiff function now yield (header, hunks) tuple that are processed by
diffhunks(). Then diff() is a wrapper around diffhunks().
Denis Laxalde - March 6, 2017, 9:52 a.m.
Denis Laxalde a écrit :
> # HG changeset patch
> # User Denis Laxalde <denis.laxalde@logilab.fr>
> # Date 1488558011 -3600
> #      Fri Mar 03 17:20:11 2017 +0100
> # Node ID 2b3bbcb8cca52db9e0dae20dbf028b67a39abc7c
> # Parent  07ea362d18b8d2b046822894ecdaded1dc889429
> # Available At http://hg.logilab.org/users/dlaxalde/hg
> #              hg pull http://hg.logilab.org/users/dlaxalde/hg -r 2b3bbcb8cca5
> # EXP-Topic diffhunks
> patch: add a diffhunks function yielding (diffheaders, hunks)

It seems to me that this function could replace the combined use of
patch.diff() + patch.parsepatch() that occurs in cmdutil.dorecord for
instance: 
https://www.mercurial-scm.org/repo/hg/file/4.1.1/mercurial/cmdutil.py#l166
Also, I did not make use of existing "patch" data structures (classes
header and hunk in patch module in particular), but it might be worth
considering using them, in particular if we make cmdutil.dorecord() use
patch.diffhunks().

Patch

diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -2213,8 +2213,8 @@  def difffeatureopts(ui, opts=None, untru
 
     return mdiff.diffopts(**buildopts)
 
-def diff(repo, node1=None, node2=None, match=None, changes=None, opts=None,
-         losedatafn=None, prefix='', relroot='', copy=None):
+def diff(repo, node1=None, node2=None, match=None, changes=None,
+         opts=None, losedatafn=None, prefix='', relroot='', copy=None):
     '''yields diff of changes to files between two nodes, or node and
     working directory.
 
@@ -2237,6 +2237,24 @@  def diff(repo, node1=None, node2=None, m
 
     copy, if not empty, should contain mappings {dst@y: src@x} of copy
     information.'''
+    for header, hunks in diffhunks(repo, node1=node1, node2=node2, match=match,
+                                   changes=changes, opts=opts,
+                                   losedatafn=losedatafn, prefix=prefix,
+                                   relroot=relroot, copy=copy):
+        text = ''.join(sum((list(hlines) for hrange, hlines in hunks), []))
+        if header and (text or len(header) > 1):
+            yield '\n'.join(header) + '\n'
+        if text:
+            yield text
+
+def diffhunks(repo, node1=None, node2=None, match=None, changes=None,
+              opts=None, losedatafn=None, prefix='', relroot='', copy=None):
+    """Yield diff of changes to files in the form of (`header`, `hunks`) tuples
+    where `header` is a list of diff headers and `hunks` is an iterable of
+    (`hunkrange`, `hunklines`) tuples.
+
+    See diff() for the meaning of parameters.
+    """
 
     if opts is None:
         opts = mdiff.defaultopts
@@ -2537,6 +2555,7 @@  def trydiff(repo, revs, ctx1, ctx2, modi
             if text:
                 header.append('index %s..%s' %
                               (gitindex(content1), gitindex(content2)))
+            hunks = (None, [text]),
         else:
             if opts.git and opts.index > 0:
                 flag = flag1
@@ -2551,11 +2570,7 @@  def trydiff(repo, revs, ctx1, ctx2, modi
                                             content2, date2,
                                             path1, path2, opts=opts)
             header.extend(uheaders)
-            text = ''.join(sum((list(hlines) for hrange, hlines in hunks), []))
-        if header and (text or len(header) > 1):
-            yield '\n'.join(header) + '\n'
-        if text:
-            yield text
+        yield header, hunks
 
 def diffstatsum(stats):
     maxfile, maxtotal, addtotal, removetotal, binary = 0, 0, 0, 0, False