[PATCH V2] revert: add an experimental config to use inverted selection
Laurent Charignon
lcharignon at fb.com
Sat May 30 00:24:10 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 4a7fffdf3e2e7edb9ce2f319572319dc3f255f30
# Parent a4acf019dd5b72e91a1b1321d80d298033be8111
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]
invertedinteractive=True
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -3138,10 +3138,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',
+ 'invertedinteractive',
+ 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
@@ -1383,6 +1383,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,3 +1,4 @@
+ ... +firstline
+ ... c
+ ... 1
+ ... 2
+ ... @@ -5,3 +6,4 @@
+ ... 4
+ ... 5
+ ... d
+ ... +lastline"""
+
+ After parsepatch hunks look like: [header1, header2, ...]:
+ >>> hunks = parsepatch(rawpatch)
+
+ After filterpatch hunks look like: [header1, hunk1, hunk2, header2...]
+ We expand the list of headers by appending their respective hunks:
+ >>> hunkscomingfromfilterpatch = []
+ >>> for h in hunks:
+ ... hunkscomingfromfilterpatch.append(h)
+ ... hunkscomingfromfilterpatch.extend(h.hunks)
+
+ Actual hunk inversion:
+ >>> reversedhunks = reversehunks(hunkscomingfromfilterpatch)
+
+ Printing the hunk and checking the result:
+ >>> 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
+ @@ -5,4 +6,3 @@
+ 4
+ 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,64 @@
4
5
b
+
+Check the experimental config to invert the selection:
+ $ cat <<EOF >> $HGRCPATH
+ > [experimental]
+ > invertedinteractive=True
+ > EOF
+
+
+ $ hg up -C .
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ cat folder1/g > tmp
+ $ echo 'firstline' > folder1/g
+ $ cat tmp >> folder1/g
+ $ echo 'lastline' >> folder1/g
+ $ hg diff --nodates
+ diff -r 5a858e056dc0 folder1/g
+ --- a/folder1/g
+ +++ b/folder1/g
+ @@ -1,3 +1,4 @@
+ +firstline
+ c
+ 1
+ 2
+ @@ -5,3 +6,4 @@
+ 4
+ 5
+ d
+ +lastline
+ $ hg revert -i <<EOF
+ > y
+ > y
+ > n
+ > EOF
+ reverting folder1/g (glob)
+ diff --git a/folder1/g b/folder1/g
+ 2 hunks, 2 lines changed
+ examine changes to 'folder1/g'? [Ynesfdaq?] y
+
+ @@ -1,3 +1,4 @@
+ +firstline
+ c
+ 1
+ 2
+ record change 1/2 to 'folder1/g'? [Ynesfdaq?] y
+
+ @@ -5,3 +6,4 @@
+ 4
+ 5
+ d
+ +lastline
+ record change 2/2 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