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

Laurent Charignon lcharignon at fb.com
Mon Jun 1 15:17:21 CDT 2015


> On Jun 1, 2015, at 11:17 AM, Laurent Charignon <lcharignon at fb.com> wrote:
> 
> # HG changeset patch
> # User Laurent Charignon <lcharignon at fb.com>
> # Date 1432930312 25200
> #      Fri May 29 13:11:52 2015 -0700
> # Node ID c929901771de740fc7ffc8c8822dc288c119d9bb
> # 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,84 @@
>             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"""
> +    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
> +    @@ -1,5 +2,7 @@
> +     c
> +     1
> +     2
> +    +3
> +    +4
> +     5
> +     d
> +    @@ -6,3 +5,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-doctest.py b/tests/test-doctest.py
> --- a/tests/test-doctest.py
> +++ b/tests/test-doctest.py
> @@ -5,6 +5,7 @@
> import doctest
> 
> def testmod(name, optionflags=0, testtarget=None):
> +    sys.path.insert(1,"..")

Please discard this hunk, it needs a proper fix and it was a temporary hack to test locally.
Without it I was not able to run the doc test against the local mercurial, does anyone have a workaround/tip for this?

>     __import__(name)
>     mod = sys.modules[name]
>     if testtarget is not None:
> 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,78 @@
>   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
> +  $ cat folder1/g > tmp
> +  $ echo 'firstline' > folder1/g
> +  $ cat tmp | egrep -v "3|4" >> folder1/g
> +  $ echo 'lastline' >> folder1/g
> +  $ hg diff --nodates
> +  diff -r 5a858e056dc0 folder1/g
> +  --- a/folder1/g
> +  +++ b/folder1/g
> +  @@ -1,7 +1,7 @@
> +  +firstline
> +   c
> +   1
> +   2
> +  -3
> +  -4
> +   5
> +   d
> +  +lastline
> +  $ hg revert -i <<EOF
> +  > y
> +  > y
> +  > n
> +  > n
> +  > EOF
> +  reverting folder1/g (glob)
> +  diff --git a/folder1/g b/folder1/g
> +  3 hunks, 4 lines changed
> +  examine changes to 'folder1/g'? [Ynesfdaq?] y
> +  
> +  @@ -1,3 +1,4 @@
> +  +firstline
> +   c
> +   1
> +   2
> +  record change 1/3 to 'folder1/g'? [Ynesfdaq?] y
> +  
> +  @@ -1,7 +2,5 @@
> +   c
> +   1
> +   2
> +  -3
> +  -4
> +   5
> +   d
> +  record change 2/3 to 'folder1/g'? [Ynesfdaq?] n
> +  
> +  @@ -6,2 +5,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
> +  @@ -1,7 +1,6 @@
> +   c
> +   1
> +   2
> +  -3
> +  -4
> +   5
> +   d
> +  +lastline
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> https://selenic.com/mailman/listinfo/mercurial-devel



More information about the Mercurial-devel mailing list