Patchwork [05,of,11] mdiff: make unidiff filter hunks out of specified line ranges

login
register
mail settings
Submitter Denis Laxalde
Date Feb. 22, 2017, 3:09 p.m.
Message ID <9090c35a37b14e5e09d0.1487776199@sh77.tls.logilab.fr>
Download mbox | patch
Permalink /patch/18706/
State Accepted
Delegated to: Yuya Nishihara
Headers show

Comments

Denis Laxalde - Feb. 22, 2017, 3:09 p.m.
# HG changeset patch
# User Denis Laxalde <denis.laxalde@logilab.fr>
# Date 1484921181 -3600
#      Fri Jan 20 15:06:21 2017 +0100
# Node ID 9090c35a37b14e5e09d0911d4794b65ee9ed35de
# Parent  4d83e067c9c6e0f5fb7b126a9739aa9dd8113af4
# EXP-Topic linerange-log/hgweb-filelog
mdiff: make unidiff filter hunks out of specified line ranges

We add two range parameters to filter diff blocks coming from allblocks()
which starting/ending line are out of specified line range.

This will be used by patch.diff() to make it possible to build a diff with
only hunks in a specified range of lines while preserving correct line number
information.
Yuya Nishihara - Feb. 24, 2017, 4:21 p.m.
On Wed, 22 Feb 2017 16:09:59 +0100, Denis Laxalde wrote:
> # HG changeset patch
> # User Denis Laxalde <denis.laxalde@logilab.fr>
> # Date 1484921181 -3600
> #      Fri Jan 20 15:06:21 2017 +0100
> # Node ID 9090c35a37b14e5e09d0911d4794b65ee9ed35de
> # Parent  4d83e067c9c6e0f5fb7b126a9739aa9dd8113af4
> # EXP-Topic linerange-log/hgweb-filelog
> mdiff: make unidiff filter hunks out of specified line ranges

> @@ -258,7 +260,7 @@ def unidiff(a, ad, b, bd, fn1, fn2, opts
>  # creates a headerless unified diff
>  # t1 and t2 are the text to be diffed
>  # l1 and l2 are the text broken up into lines
> -def _unidiff(t1, t2, l1, l2, opts=defaultopts):
> +def _unidiff(t1, t2, l1, l2, opts=defaultopts, range1=None, range2=None):
>      def contextend(l, len):
>          ret = l + opts.context
>          if ret > len:
> @@ -315,6 +317,10 @@ def _unidiff(t1, t2, l1, l2, opts=defaul
>      ignoredlines = 0
>      for s, stype in allblocks(t1, t2, opts, l1, l2):
>          a1, a2, b1, b2 = s
> +        if range1 is not None and not (range1[0] < a2 and a1 < range1[1]):
> +            continue
> +        if range2 is not None and not (range2[0] < b2 and b1 < range2[1]):
> +            continue

Maybe range1/range2 could be specified as a function to filter blocks so
that we can apply e.g. blocksinrange() as needed. But that would slightly
complicate the next patch. I don't know which is better.

The change looks good.

Patch

diff --git a/mercurial/mdiff.py b/mercurial/mdiff.py
--- a/mercurial/mdiff.py
+++ b/mercurial/mdiff.py
@@ -195,7 +195,8 @@  def allblocks(text1, text2, opts=None, l
             yield s, type
         yield s1, '='
 
-def unidiff(a, ad, b, bd, fn1, fn2, opts=defaultopts):
+def unidiff(a, ad, b, bd, fn1, fn2, opts=defaultopts,
+            rangea=None, rangeb=None):
     def datetag(date, fn=None):
         if not opts.git and not opts.nodates:
             return '\t%s\n' % date
@@ -242,7 +243,8 @@  def unidiff(a, ad, b, bd, fn1, fn2, opts
     else:
         al = splitnewlines(a)
         bl = splitnewlines(b)
-        l = list(_unidiff(a, b, al, bl, opts=opts))
+        l = list(_unidiff(a, b, al, bl, opts=opts,
+                          range1=rangea, range2=rangeb))
         if not l:
             return ""
 
@@ -258,7 +260,7 @@  def unidiff(a, ad, b, bd, fn1, fn2, opts
 # creates a headerless unified diff
 # t1 and t2 are the text to be diffed
 # l1 and l2 are the text broken up into lines
-def _unidiff(t1, t2, l1, l2, opts=defaultopts):
+def _unidiff(t1, t2, l1, l2, opts=defaultopts, range1=None, range2=None):
     def contextend(l, len):
         ret = l + opts.context
         if ret > len:
@@ -315,6 +317,10 @@  def _unidiff(t1, t2, l1, l2, opts=defaul
     ignoredlines = 0
     for s, stype in allblocks(t1, t2, opts, l1, l2):
         a1, a2, b1, b2 = s
+        if range1 is not None and not (range1[0] < a2 and a1 < range1[1]):
+            continue
+        if range2 is not None and not (range2[0] < b2 and b1 < range2[1]):
+            continue
         if stype != '!':
             if stype == '~':
                 # The diff context lines are based on t1 content. When