Patchwork [08,of,10] patch: make parsepatch optionally trim context lines

login
register
mail settings
Submitter Jun Wu
Date July 5, 2017, 1:58 a.m.
Message ID <0f202460887f66efa3dd.1499219913@x1c>
Download mbox | patch
Permalink /patch/22004/
State Accepted
Headers show

Comments

Jun Wu - July 5, 2017, 1:58 a.m.
# HG changeset patch
# User Jun Wu <quark@fb.com>
# Date 1499211688 25200
#      Tue Jul 04 16:41:28 2017 -0700
# Node ID 0f202460887f66efa3ddbd1d9a7d8afca75c0114
# Parent  6c71bc31de7ef4d70e7b4322d433d90035621156
# Available At https://bitbucket.org/quark-zju/hg-draft
#              hg pull https://bitbucket.org/quark-zju/hg-draft -r 0f202460887f
patch: make parsepatch optionally trim context lines

Previously there is a suspicious `if False and delta > 0` which dates back
to the beginning of hgext/record.py (b2607267236d).

The "trimming context lines" feature could be useful (and is used by the
next patch). So let's enable it. This patch adds a new `maxcontext`
parameter to `recordhunk` and `parsepatch`, changing the `if False`
condition to respect it.

The old `trimcontext` implementation is also wrong - it does not update
`toline` correctly and it does not do the right thing for `before` context.
A doctest was added to guard us from making a similar mistake again.

Since `maxcontext` is set to `None` (unlimited), there is no behavior
change.
Augie Fackler - July 5, 2017, 10:26 p.m.
On Tue, Jul 04, 2017 at 06:58:33PM -0700, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu <quark@fb.com>
> # Date 1499211688 25200
> #      Tue Jul 04 16:41:28 2017 -0700
> # Node ID 0f202460887f66efa3ddbd1d9a7d8afca75c0114
> # Parent  6c71bc31de7ef4d70e7b4322d433d90035621156
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #              hg pull https://bitbucket.org/quark-zju/hg-draft -r 0f202460887f
> patch: make parsepatch optionally trim context lines

queued, thanks

Wow.

Patch

diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -923,16 +923,22 @@  class recordhunk(object):
     XXX shouldn't we merge this with the other hunk class?
     """
-    maxcontext = 3
 
-    def __init__(self, header, fromline, toline, proc, before, hunk, after):
-        def trimcontext(number, lines):
-            delta = len(lines) - self.maxcontext
-            if False and delta > 0:
-                return number + delta, lines[:self.maxcontext]
-            return number, lines
+    def __init__(self, header, fromline, toline, proc, before, hunk, after,
+                 maxcontext=None):
+        def trimcontext(lines, reverse=False):
+            if maxcontext is not None:
+                delta = len(lines) - maxcontext
+                if delta > 0:
+                    if reverse:
+                        return delta, lines[delta:]
+                    else:
+                        return delta, lines[:maxcontext]
+            return 0, lines
 
         self.header = header
-        self.fromline, self.before = trimcontext(fromline, before)
-        self.toline, self.after = trimcontext(toline, after)
+        trimedbefore, self.before = trimcontext(before, True)
+        self.fromline = fromline + trimedbefore
+        self.toline = toline + trimedbefore
+        _trimedafter, self.after = trimcontext(after, False)
         self.proc = proc
         self.hunk = hunk
@@ -1528,6 +1534,47 @@  def reversehunks(hunks):
     return newhunks
 
-def parsepatch(originalchunks):
-    """patch -> [] of headers -> [] of hunks """
+def parsepatch(originalchunks, maxcontext=None):
+    """patch -> [] of headers -> [] of hunks
+
+    If maxcontext is not None, trim context lines if necessary.
+
+    >>> rawpatch = '''diff --git a/folder1/g b/folder1/g
+    ... --- a/folder1/g
+    ... +++ b/folder1/g
+    ... @@ -1,8 +1,10 @@
+    ...  1
+    ...  2
+    ... -3
+    ...  4
+    ...  5
+    ...  6
+    ... +6.1
+    ... +6.2
+    ...  7
+    ...  8
+    ... +9'''
+    >>> out = util.stringio()
+    >>> headers = parsepatch([rawpatch], maxcontext=1)
+    >>> for header in headers:
+    ...     header.write(out)
+    ...     for hunk in header.hunks:
+    ...         hunk.write(out)
+    >>> print(out.getvalue())
+    diff --git a/folder1/g b/folder1/g
+    --- a/folder1/g
+    +++ b/folder1/g
+    @@ -2,3 +2,2 @@
+     2
+    -3
+     4
+    @@ -6,2 +5,4 @@
+     6
+    +6.1
+    +6.2
+     7
+    @@ -8,1 +9,2 @@
+     8
+    +9
+    """
     class parser(object):
         """patch parsing state machine"""
@@ -1551,5 +1598,5 @@  def parsepatch(originalchunks):
             if self.hunk:
                 h = recordhunk(self.header, self.fromline, self.toline,
-                        self.proc, self.before, self.hunk, context)
+                        self.proc, self.before, self.hunk, context, maxcontext)
                 self.header.hunks.append(h)
                 self.fromline += len(self.before) + h.removed