[PATCH V3] record: add option to reverse chunks selection

Laurent Charignon lcharignon at fb.com
Mon Mar 16 13:00:00 CDT 2015


# HG changeset patch
# User Laurent Charignon <lcharignon at fb.com>
# Date 1426207981 25200
#      Thu Mar 12 17:53:01 2015 -0700
# Node ID 3cb4b1735fab9dae309e66cc0c22369432dac7c2
# Parent  897ab5f050bae8a33fa9a732db697f93ee03f330
record: add option to reverse chunks selection

This will be useful to support an interactive hg revert command

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -46,6 +46,8 @@
         raise util.Abort(_('running non-interactively, use %s instead') %
                          cmdsuggest)
 
+    reverse =  opts.get('reverse', False)
+
     # make sure username is set before going interactive
     if not opts.get('user'):
         ui.username() # raise exception, username not provided
@@ -84,6 +86,28 @@
         except patch.PatchError, err:
             raise util.Abort(_('error parsing patch: %s') % err)
 
+        if reverse:
+            # originalchunks looks like [hdr1, hdr2, ...]
+            # chunks looks like [hdr1, hunk1, hunk2, hdr2 ...]
+
+            # I) filter the hunks in the reverse set
+            newhunks = set(filter(ishunk, chunks))
+            oldhunks = set([hu for h in originalchunks for hu in h.hunks])
+            reversedhunks = list(oldhunks - newhunks)
+
+            # II) group them by headers
+            reversedhdrs = {}
+            for hu in reversedhunks:
+                if hu.header not in reversedhdrs:
+                    reversedhdrs[hu.header] = []
+                reversedhdrs[hu.header].append(hu)
+
+            # III) build the list of changes to apply
+            reversedchunks = []
+            for h in reversedhdrs.keys():
+                reversedchunks.append(h)
+                reversedchunks.extend(reversedhdrs[h])
+            chunks = reversedchunks
         contenders = set()
         for h in chunks:
             try:
diff --git a/tests/test-commit-interactive.t b/tests/test-commit-interactive.t
--- a/tests/test-commit-interactive.t
+++ b/tests/test-commit-interactive.t
@@ -1431,4 +1431,323 @@
   This is the second line
   This is the third line
 
-  $ cd ..
+  $ hg update -C .
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+
+Reverse recording setup
+
+  $ cat > reverse.py << EOF
+  > """A small extension that reverse the selection of interactive selection
+  > 
+  > used to test reversed interactive selection
+  > """
+  > 
+  > from mercurial import commands
+  > from mercurial import extensions
+  > 
+  > def uisetup(ui):
+  >   extensions.wrapcommand(commands.table, 'commit', commit)
+  > 
+  > def commit(orig, ui, repo, *pats, **opts):
+  >   opts["reverse"] = True
+  >   return orig(ui, repo, *pats, **opts)
+  > EOF
+
+  $ EXTPATH=`pwd`
+  $ cat << EOF >> $HGRCPATH
+  > [extensions]
+  > reverse=$EXTPATH/reverse.py
+  > [ui]
+  > interactive = true
+  > EOF
+
+Reverse selection; single hunk selected is reversed
+  $ seq 1 5 > newfile2
+  $ hg add newfile2
+  $ hg commit -i -m "reversehunk1" -d '24 0' << EOF
+  > y
+  > y
+  > EOF
+  diff --git a/newfile2 b/newfile2
+  new file mode 100644
+  examine changes to 'newfile2'? [Ynesfdaq?] y
+  
+  @@ -0,0 +1,5 @@
+  +1
+  +2
+  +3
+  +4
+  +5
+  record this change to 'newfile2'? [Ynesfdaq?] y
+  
+  no changes to record
+  $ hg tip
+  changeset:   30:7a3fbbb081ea
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:23 1970 +0000
+  summary:     edit-patch-new
+  
+Reverse selction; single hunk unselected is commited
+  $ hg commit -i -m "reversehunk1" -d '24 0' << EOF
+  > y
+  > n
+  > EOF
+  diff --git a/newfile2 b/newfile2
+  new file mode 100644
+  examine changes to 'newfile2'? [Ynesfdaq?] y
+  
+  @@ -0,0 +1,5 @@
+  +1
+  +2
+  +3
+  +4
+  +5
+  record this change to 'newfile2'? [Ynesfdaq?] n
+  
+  $ hg tip
+  changeset:   31:9089f22108a3
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:24 1970 +0000
+  summary:     reversehunk1
+  
+  $ hg cat -r tip newfile2
+  1
+  2
+  3
+  4
+  5
+
+Reverse selction; single file unselected is commited
+  $ seq 1 5 > newfile3
+  $ hg add newfile3
+  $ hg commit -i -m "reversehunk2" -d '24 0' << EOF
+  > n
+  > EOF
+  diff --git a/newfile3 b/newfile3
+  new file mode 100644
+  examine changes to 'newfile3'? [Ynesfdaq?] n
+  
+  $ hg tip
+  changeset:   32:4bbd32409494
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:24 1970 +0000
+  summary:     reversehunk2
+  
+  $ hg cat -r tip newfile3
+  1
+  2
+  3
+  4
+  5
+  $ cat newfile3
+  1
+  2
+  3
+  4
+  5
+
+Reverse selection; 1/2 hunk selected in one file, the other one is commited
+  $ echo 'firstline' > newfile2
+  $ seq 1 5 >> newfile2
+  $ echo 'secondline' >> newfile2
+  $ hg commit -i -m 'reversehunk2' -d '24 0' << EOF
+  > y
+  > n
+  > y
+  > EOF
+  diff --git a/newfile2 b/newfile2
+  2 hunks, 2 lines changed
+  examine changes to 'newfile2'? [Ynesfdaq?] y
+  
+  @@ -1,5 +1,6 @@
+  +firstline
+   1
+   2
+   3
+   4
+   5
+  record change 1/2 to 'newfile2'? [Ynesfdaq?] n
+  
+  @@ -1,5 +2,6 @@
+   1
+   2
+   3
+   4
+   5
+  +secondline
+  record change 2/2 to 'newfile2'? [Ynesfdaq?] y
+  
+  $ hg cat -r tip newfile2
+  firstline
+  1
+  2
+  3
+  4
+  5
+  $ cat newfile2
+  firstline
+  1
+  2
+  3
+  4
+  5
+  secondline
+  $ hg tip
+  changeset:   33:ecee780af033
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:24 1970 +0000
+  summary:     reversehunk2
+  
+Reverse selection; 1/2 hunk selected in one file with another file unselected
+  $ mv newfile3 tmp
+  $ echo 'firstline' > newfile3
+  $ cat tmp >> newfile3
+  $ rm tmp
+  $ echo 'secondline' >> newfile3
+  $ hg commit -i -m 'reversehunk3' -d '24 0' << EOF
+  > y
+  > n
+  > y
+  > n
+  > y
+  > EOF
+  diff --git a/newfile2 b/newfile2
+  1 hunks, 1 lines changed
+  examine changes to 'newfile2'? [Ynesfdaq?] y
+  
+  @@ -4,3 +4,4 @@
+   3
+   4
+   5
+  +secondline
+  record change 1/3 to 'newfile2'? [Ynesfdaq?] n
+  
+  diff --git a/newfile3 b/newfile3
+  2 hunks, 2 lines changed
+  examine changes to 'newfile3'? [Ynesfdaq?] y
+  
+  @@ -1,5 +1,6 @@
+  +firstline
+   1
+   2
+   3
+   4
+   5
+  record change 2/3 to 'newfile3'? [Ynesfdaq?] n
+  
+  @@ -1,5 +2,6 @@
+   1
+   2
+   3
+   4
+   5
+  +secondline
+  record change 3/3 to 'newfile3'? [Ynesfdaq?] y
+  
+  $ hg tip
+  changeset:   34:35f3773303b6
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:24 1970 +0000
+  summary:     reversehunk3
+  
+  $ hg cat -r tip newfile2
+  firstline
+  1
+  2
+  3
+  4
+  5
+  secondline
+  $ hg cat -r tip newfile3
+  firstline
+  1
+  2
+  3
+  4
+  5
+  $ cat newfile3
+  firstline
+  1
+  2
+  3
+  4
+  5
+  secondline
+  $ cat newfile2
+  firstline
+  1
+  2
+  3
+  4
+  5
+  secondline
+
+Reverse selection; 1/2 files selection
+  $ echo "lastline" >> newfile2
+  $ hg commit -i -m 'reversehunk3' -d '24 0' << EOF
+  > y
+  > y
+  > n
+  > EOF
+  diff --git a/newfile2 b/newfile2
+  1 hunks, 1 lines changed
+  examine changes to 'newfile2'? [Ynesfdaq?] y
+  
+  @@ -5,3 +5,4 @@
+   4
+   5
+   secondline
+  +lastline
+  record change 1/2 to 'newfile2'? [Ynesfdaq?] y
+  
+  diff --git a/newfile3 b/newfile3
+  1 hunks, 1 lines changed
+  examine changes to 'newfile3'? [Ynesfdaq?] n
+  
+  $ hg tip
+  changeset:   35:0520da855051
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:24 1970 +0000
+  summary:     reversehunk3
+  
+  $ hg cat -r tip newfile2
+  firstline
+  1
+  2
+  3
+  4
+  5
+  secondline
+  $ hg cat -r tip newfile3
+  firstline
+  1
+  2
+  3
+  4
+  5
+  secondline
+  $ cat newfile3
+  firstline
+  1
+  2
+  3
+  4
+  5
+  secondline
+  $ cat newfile2
+  firstline
+  1
+  2
+  3
+  4
+  5
+  secondline
+  lastline
+


More information about the Mercurial-devel mailing list