[PATCH V5] revert: add an experimental config to use inverted selection

Laurent Charignon lcharignon at fb.com
Wed Jun 3 19:55:52 UTC 2015


# HG changeset patch
# User Laurent Charignon <lcharignon at fb.com>
# Date 1432930312 25200
#      Fri May 29 13:11:52 2015 -0700
# Node ID eb5b0472bf1f40a7209752cbe668d821c5c4d2bc
# Parent  6084926366b979e81e5dcc84fa595965d4c07883
revert: add an experimental config to use inverted selection

We had a discussion on the list about the interactive ui for revert. This patch
adds a flag to allow people to test the second alternative (referred to as
proposition 2 on the mailing list). It effectively inverts the signs in the
diff displayed to match the output of hg diff. A test is added to show an
example.

By setting the following flag in the config, one can try proposition 2:
[experimental]
 revertalternateinteractivemode=True

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -3139,10 +3139,21 @@
         diffopts = patch.difffeatureopts(repo.ui, whitespace=True)
         diffopts.nodates = True
         diffopts.git = True
-        diff = patch.diff(repo, None, ctx.node(), m, opts=diffopts)
+        reversehunks =  repo.ui.configbool('experimental',
+                                           'revertalternateinteractivemode',
+                                           False)
+        if reversehunks:
+            diff = patch.diff(repo, ctx.node(), None, m, opts=diffopts)
+        else:
+            diff = patch.diff(repo, None, ctx.node(), m, opts=diffopts)
         originalchunks = patch.parsepatch(diff)
+
         try:
+
             chunks = recordfilter(repo.ui, originalchunks)
+            if reversehunks:
+                chunks = patch.reversehunks(chunks)
+
         except patch.PatchError, err:
             raise util.Abort(_('error parsing patch: %s') % err)
 
diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -1385,6 +1385,77 @@
             return s
     return s[:i]
 
+def reversehunks(hunks):
+    '''reverse the signs in the hunks given as argument
+
+    This function operates on hunks coming out of patch.filterpatch, that is
+    a list of the form: [header1, hunk1, hunk2, header2...]. Example usage:
+
+    >>> rawpatch = """diff --git a/folder1/g b/folder1/g
+    ... --- a/folder1/g
+    ... +++ b/folder1/g
+    ... @@ -1,7 +1,7 @@
+    ... +firstline
+    ...  c
+    ...  1
+    ...  2
+    ... + 3
+    ... -4
+    ...  5
+    ...  d
+    ... +lastline"""
+    >>> hunks = parsepatch(rawpatch)
+    >>> hunkscomingfromfilterpatch = []
+    >>> for h in hunks:
+    ...     hunkscomingfromfilterpatch.append(h)
+    ...     hunkscomingfromfilterpatch.extend(h.hunks)
+
+    >>> reversedhunks = reversehunks(hunkscomingfromfilterpatch)
+    >>> fp = cStringIO.StringIO()
+    >>> for c in reversedhunks:
+    ...      c.write(fp)
+    >>> fp.seek(0)
+    >>> reversedpatch = fp.read()
+    >>> print reversedpatch
+    diff --git a/folder1/g b/folder1/g
+    --- a/folder1/g
+    +++ b/folder1/g
+    @@ -1,4 +1,3 @@
+    -firstline
+     c
+     1
+     2
+    @@ -1,6 +2,6 @@
+     c
+     1
+     2
+    - 3
+    +4
+     5
+     d
+    @@ -5,3 +6,2 @@
+     5
+     d
+    -lastline
+
+    '''
+
+    import crecord as crecordmod
+    newhunks = []
+    for c in hunks:
+        if isinstance(c, crecordmod.uihunk):
+            # curses hunks encapsulate the record hunk in _hunk
+            c = c._hunk
+        if isinstance(c, recordhunk):
+            for j, line in enumerate(c.hunk):
+                if line.startswith("-"):
+                    c.hunk[j] = "+" + c.hunk[j][1:]
+                elif line.startswith("+"):
+                    c.hunk[j] = "-" + c.hunk[j][1:]
+            c.added, c.removed = c.removed, c.added
+        newhunks.append(c)
+    return newhunks
+
 def parsepatch(originalchunks):
     """patch -> [] of headers -> [] of hunks """
     class parser(object):
diff --git a/tests/test-revert-interactive.t b/tests/test-revert-interactive.t
--- a/tests/test-revert-interactive.t
+++ b/tests/test-revert-interactive.t
@@ -320,3 +320,74 @@
   4
   5
   b
+
+Check the experimental config to invert the selection:
+  $ cat <<EOF >> $HGRCPATH
+  > [experimental]
+  > revertalternateinteractivemode=True
+  > EOF
+
+
+  $ hg up -C .
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ printf 'firstline\nc\n1\n2\n3\n 3\n5\nd\nlastline\n' > folder1/g
+  $ hg diff --nodates
+  diff -r 5a858e056dc0 folder1/g
+  --- a/folder1/g
+  +++ b/folder1/g
+  @@ -1,7 +1,9 @@
+  +firstline
+   c
+   1
+   2
+   3
+  -4
+  + 3
+   5
+   d
+  +lastline
+  $ hg revert -i <<EOF
+  > y
+  > y
+  > y
+  > n
+  > EOF
+  reverting folder1/g (glob)
+  diff --git a/folder1/g b/folder1/g
+  3 hunks, 3 lines changed
+  examine changes to 'folder1/g'? [Ynesfdaq?] y
+  
+  @@ -1,4 +1,5 @@
+  +firstline
+   c
+   1
+   2
+   3
+  record change 1/3 to 'folder1/g'? [Ynesfdaq?] y
+  
+  @@ -1,7 +2,7 @@
+   c
+   1
+   2
+   3
+  -4
+  + 3
+   5
+   d
+  record change 2/3 to 'folder1/g'? [Ynesfdaq?] y
+  
+  @@ -6,2 +7,3 @@
+   5
+   d
+  +lastline
+  record change 3/3 to 'folder1/g'? [Ynesfdaq?] n
+  
+  $ hg diff --nodates
+  diff -r 5a858e056dc0 folder1/g
+  --- a/folder1/g
+  +++ b/folder1/g
+  @@ -5,3 +5,4 @@
+   4
+   5
+   d
+  +lastline


More information about the Mercurial-devel mailing list