mercurial/mdiff.py
changeset 30717 3eeb8e138e5c
parent 30023 ff17dff99295
child 30788 d1901c4c8ec0
--- a/mercurial/mdiff.py	Fri Jan 06 16:19:41 2017 +0000
+++ b/mercurial/mdiff.py	Tue Jan 03 18:15:58 2017 +0100
@@ -113,6 +113,45 @@
         s1 = i1
         s2 = i2
 
+def blocksinrange(blocks, rangeb):
+    """filter `blocks` like (a1, a2, b1, b2) from items outside line range
+    `rangeb` from ``(b1, b2)`` point of view.
+
+    Return `filteredblocks, rangea` where:
+
+    * `filteredblocks` is list of ``block = (a1, a2, b1, b2), stype`` items of
+      `blocks` that are inside `rangeb` from ``(b1, b2)`` point of view; a
+      block ``(b1, b2)`` being inside `rangeb` if
+      ``rangeb[0] < b2 and b1 < rangeb[1]``;
+    * `rangea` is the line range w.r.t. to ``(a1, a2)`` parts of `blocks`.
+    """
+    lbb, ubb = rangeb
+    lba, uba = None, None
+    filteredblocks = []
+    for block in blocks:
+        (a1, a2, b1, b2), stype = block
+        if lbb >= b1 and ubb <= b2 and stype == '=':
+            # rangeb is within a single "=" hunk, restrict back linerange1
+            # by offsetting rangeb
+            lba = lbb - b1 + a1
+            uba = ubb - b1 + a1
+        else:
+            if b1 <= lbb < b2:
+                if stype == '=':
+                    lba = a2 - (b2 - lbb)
+                else:
+                    lba = a1
+            if b1 < ubb <= b2:
+                if stype == '=':
+                    uba = a1 + (ubb - b1)
+                else:
+                    uba = a2
+        if lbb < b2 and b1 < ubb:
+            filteredblocks.append(block)
+    if lba is None or uba is None or uba < lba:
+        raise error.Abort(_('line range exceeds file size'))
+    return filteredblocks, (lba, uba)
+
 def allblocks(text1, text2, opts=None, lines1=None, lines2=None):
     """Return (block, type) tuples, where block is an mdiff.blocks
     line entry. type is '=' for blocks matching exactly one another