diff: pass a diff hunks filter function from changeset_printer to patch.diff()
authorDenis Laxalde <denis.laxalde@logilab.fr>
Fri, 06 Oct 2017 14:45:17 +0200
changeset 34856 890afefa7296
parent 34855 35c6a54ec1ff
child 34857 84c6b9384d6a
diff: pass a diff hunks filter function from changeset_printer to patch.diff() We add a 'hunksfilterfn' keyword argument in all functions of the call stack from changeset_printer.show() to patch.diff(). This is a callable that will be used to filter out hunks by line range and will be used in the "-L/--line-range" option of "hg log" command introduced in the following changesets.
mercurial/cmdutil.py
mercurial/patch.py
--- a/mercurial/cmdutil.py	Thu Oct 05 21:20:08 2017 +0200
+++ b/mercurial/cmdutil.py	Fri Oct 06 14:45:17 2017 +0200
@@ -1494,7 +1494,7 @@
 
 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
                    changes=None, stat=False, fp=None, prefix='',
-                   root='', listsubrepos=False):
+                   root='', listsubrepos=False, hunksfilterfn=None):
     '''show diff or diffstat.'''
     if fp is None:
         write = ui.write
@@ -1522,14 +1522,16 @@
         if not ui.plain():
             width = ui.termwidth()
         chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
-                            prefix=prefix, relroot=relroot)
+                            prefix=prefix, relroot=relroot,
+                            hunksfilterfn=hunksfilterfn)
         for chunk, label in patch.diffstatui(util.iterlines(chunks),
                                              width=width):
             write(chunk, label=label)
     else:
         for chunk, label in patch.diffui(repo, node1, node2, match,
                                          changes, diffopts, prefix=prefix,
-                                         relroot=relroot):
+                                         relroot=relroot,
+                                         hunksfilterfn=hunksfilterfn):
             write(chunk, label=label)
 
     if listsubrepos:
@@ -1591,16 +1593,17 @@
         if self.footer:
             self.ui.write(self.footer)
 
-    def show(self, ctx, copies=None, matchfn=None, **props):
+    def show(self, ctx, copies=None, matchfn=None, hunksfilterfn=None,
+             **props):
         props = pycompat.byteskwargs(props)
         if self.buffered:
             self.ui.pushbuffer(labeled=True)
-            self._show(ctx, copies, matchfn, props)
+            self._show(ctx, copies, matchfn, hunksfilterfn, props)
             self.hunk[ctx.rev()] = self.ui.popbuffer()
         else:
-            self._show(ctx, copies, matchfn, props)
-
-    def _show(self, ctx, copies, matchfn, props):
+            self._show(ctx, copies, matchfn, hunksfilterfn, props)
+
+    def _show(self, ctx, copies, matchfn, hunksfilterfn, props):
         '''show a single changeset or file revision'''
         changenode = ctx.node()
         rev = ctx.rev()
@@ -1714,7 +1717,7 @@
                               label='log.summary')
         self.ui.write("\n")
 
-        self.showpatch(ctx, matchfn)
+        self.showpatch(ctx, matchfn, hunksfilterfn=hunksfilterfn)
 
     def _showobsfate(self, ctx):
         obsfate = templatekw.showobsfate(repo=self.repo, ctx=ctx, ui=self.ui)
@@ -1729,7 +1732,7 @@
         '''empty method used by extension as a hook point
         '''
 
-    def showpatch(self, ctx, matchfn):
+    def showpatch(self, ctx, matchfn, hunksfilterfn=None):
         if not matchfn:
             matchfn = self.matchfn
         if matchfn:
@@ -1740,12 +1743,14 @@
             prev = ctx.p1().node()
             if stat:
                 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
-                               match=matchfn, stat=True)
+                               match=matchfn, stat=True,
+                               hunksfilterfn=hunksfilterfn)
             if diff:
                 if stat:
                     self.ui.write("\n")
                 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
-                               match=matchfn, stat=False)
+                               match=matchfn, stat=False,
+                               hunksfilterfn=hunksfilterfn)
             self.ui.write("\n")
 
 class jsonchangeset(changeset_printer):
@@ -1762,7 +1767,7 @@
         else:
             self.ui.write("[]\n")
 
-    def _show(self, ctx, copies, matchfn, props):
+    def _show(self, ctx, copies, matchfn, hunksfilterfn, props):
         '''show a single changeset or file revision'''
         rev = ctx.rev()
         if rev is None:
@@ -1896,7 +1901,7 @@
             self.footer += templater.stringify(self.t(self._parts['docfooter']))
         return super(changeset_templater, self).close()
 
-    def _show(self, ctx, copies, matchfn, props):
+    def _show(self, ctx, copies, matchfn, hunksfilterfn, props):
         '''show a single changeset or file revision'''
         props = props.copy()
         props.update(templatekw.keywords)
@@ -1928,7 +1933,7 @@
         # write changeset metadata, then patch if requested
         key = self._parts[self._tref]
         self.ui.write(templater.stringify(self.t(key, **props)))
-        self.showpatch(ctx, matchfn)
+        self.showpatch(ctx, matchfn, hunksfilterfn=hunksfilterfn)
 
         if self._parts['footer']:
             if not self.footer:
--- a/mercurial/patch.py	Thu Oct 05 21:20:08 2017 +0200
+++ b/mercurial/patch.py	Fri Oct 06 14:45:17 2017 +0200
@@ -2296,7 +2296,8 @@
     return mdiff.diffopts(**pycompat.strkwargs(buildopts))
 
 def diff(repo, node1=None, node2=None, match=None, changes=None,
-         opts=None, losedatafn=None, prefix='', relroot='', copy=None):
+         opts=None, losedatafn=None, prefix='', relroot='', copy=None,
+         hunksfilterfn=None):
     '''yields diff of changes to files between two nodes, or node and
     working directory.
 
@@ -2318,12 +2319,18 @@
     patterns that fall outside it will be ignored.
 
     copy, if not empty, should contain mappings {dst@y: src@x} of copy
-    information.'''
+    information.
+
+    hunksfilterfn, if not None, should be a function taking a filectx and
+    hunks generator that may yield filtered hunks.
+    '''
     for fctx1, fctx2, hdr, hunks in diffhunks(
             repo, node1=node1, node2=node2,
             match=match, changes=changes, opts=opts,
             losedatafn=losedatafn, prefix=prefix, relroot=relroot, copy=copy,
     ):
+        if hunksfilterfn is not None:
+            hunks = hunksfilterfn(fctx2, hunks)
         text = ''.join(sum((list(hlines) for hrange, hlines in hunks), []))
         if hdr and (text or len(hdr) > 1):
             yield '\n'.join(hdr) + '\n'