changeset 28638:44319097e7b9

crecord: re-enable reviewing a patch before comitting it The "r" option for this feature was copied into Mercurial from crecord, but the actual implementation never made it into hg until now. It's a moderately useful feature that allows the user to edit the patch in a text editor before comitting it for good. This requires a test, so we must also enable a corresponding testing 'R' option that skips the confirmation dialogue. In addition, we also need a help text for the editor when reviewing the final patch. As for why this is a useful feature if we can already edit hunks in an editor, I would like to offer the following points: * editing hunks does not show the entire patch all at once ** furthermore, the hunk "tree" in the TUI has no root that could be selected for edition * it is helpful to be able to see the entire final patch for confirmation ** within this view, the unselected hunks are hidden, which is visusally cleaner ** this works as a final review of the complete result, which is a bit more difficult to do conceptually via hunk editing * this feature was already in crecord, so it was an oversight to not bring it to core * it works and is consistent with editing hunks
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Sun, 20 Mar 2016 21:08:17 -0400
parents 4874b8efe7d2
children 64ed9f904532
files mercurial/cmdutil.py mercurial/crecord.py tests/test-commit-interactive-curses.t
diffstat 3 files changed, 98 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/cmdutil.py	Sun Mar 20 18:24:59 2016 -0400
+++ b/mercurial/cmdutil.py	Sun Mar 20 21:08:17 2016 -0400
@@ -207,6 +207,17 @@
             dopatch = fp.tell()
             fp.seek(0)
 
+            # 2.5 optionally review / modify patch in text editor
+            if opts.get('review', False):
+                patchtext = (crecordmod.diffhelptext
+                             + crecordmod.patchhelptext
+                             + fp.read())
+                reviewedpatch = ui.edit(patchtext, "",
+                                        extra={"suffix": ".diff"})
+                fp.truncate(0)
+                fp.write(reviewedpatch)
+                fp.seek(0)
+
             [os.unlink(repo.wjoin(c)) for c in newlyaddedandmodifiedfiles]
             # 3a. apply filtered patch to clean repo  (clean)
             if backups:
--- a/mercurial/crecord.py	Sun Mar 20 18:24:59 2016 -0400
+++ b/mercurial/crecord.py	Sun Mar 20 21:08:17 2016 -0400
@@ -43,6 +43,13 @@
 # of the hunk are removed, then the edit is aborted and the hunk is left
 # unchanged.
 """)
+
+patchhelptext = _("""#
+# If the patch applies cleanly, the edited patch will immediately
+# be finalised. If it does not apply cleanly, rejects files will be
+# generated. You can use those when you try again.
+""")
+
 try:
     import curses
     import fcntl
@@ -1595,10 +1602,14 @@
         elif keypressed in ["c"]:
             if self.confirmcommit():
                 return True
+        elif test and keypressed in ['X']:
+            return True
         elif keypressed in ["r"]:
             if self.confirmcommit(review=True):
+                self.opts['review'] = True
                 return True
-        elif test and keypressed in ['X']:
+        elif test and keypressed in ['R']:
+            self.opts['review'] = True
             return True
         elif keypressed in [' '] or (test and keypressed in ["TOGGLE"]):
             self.toggleapply()
--- a/tests/test-commit-interactive-curses.t	Sun Mar 20 18:24:59 2016 -0400
+++ b/tests/test-commit-interactive-curses.t	Sun Mar 20 21:08:17 2016 -0400
@@ -223,7 +223,82 @@
   foo
   hello world
 
+Testing the review option. The entire final filtered patch should show
+up in the editor and be editable. We will unselect the second file and
+the first hunk of the third file. During review, we will decide that
+"lower" sounds better than "bottom", and the final commit should
+reflect this edition.
 
+  $ hg update -C .
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo "top" > c
+  $ cat x >> c
+  $ echo "bottom" >> c
+  $ mv c x
+  $ echo "third a" >> a
+  $ echo "we will unselect this" >> b
+
+  $ cat > editor.sh <<EOF
+  > cat "\$1"
+  > cat "\$1" | sed s/bottom/lower/ > tmp
+  > mv tmp "\$1"
+  > EOF
+  $ cat > testModeCommands <<EOF
+  > KEY_DOWN
+  > TOGGLE
+  > KEY_DOWN
+  > f
+  > KEY_DOWN
+  > TOGGLE
+  > R
+  > EOF
+
+  $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit  -i -m "review hunks" -d "0 0"
+  # To remove '-' lines, make them ' ' lines (context).
+  # To remove '+' lines, delete them.
+  # Lines starting with # will be removed from the patch.
+  #
+  # If the patch applies cleanly, the edited patch will immediately
+  # be finalised. If it does not apply cleanly, rejects files will be
+  # generated. You can use those when you try again.
+  diff --git a/a b/a
+  --- a/a
+  +++ b/a
+  @@ -1,2 +1,3 @@
+   a
+   a
+  +third a
+  diff --git a/x b/x
+  --- a/x
+  +++ b/x
+  @@ -1,2 +1,3 @@
+   foo
+   hello world
+  +bottom
+
+  $ hg cat -r . a
+  a
+  a
+  third a
+
+  $ hg cat -r . b
+  x
+  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+  10
+  y
+
+  $ hg cat -r . x
+  foo
+  hello world
+  lower
 Check ui.interface logic for the chunkselector
 
 The default interface is text