Patchwork D6125: revert: option to choose what to keep, not what to discard

login
register
mail settings
Submitter phabricator
Date March 19, 2019, 6:33 p.m.
Message ID <e8250f4f83c43db56d6759f385ea663a@localhost.localdomain>
Download mbox | patch
Permalink /patch/39337/
State Not Applicable
Headers show

Comments

phabricator - March 19, 2019, 6:33 p.m.
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGc1d83d916e85: revert: option to choose what to keep, not what to discard (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6125?vs=14480&id=14563

REVISION DETAIL
  https://phab.mercurial-scm.org/D6125

AFFECTED FILES
  mercurial/cmdutil.py
  mercurial/configitems.py
  mercurial/crecord.py
  mercurial/patch.py
  tests/test-revert-interactive.t

CHANGE DETAILS




To: martinvonz, #hg-reviewers, pulkit
Cc: pulkit, mercurial-devel

Patch

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
@@ -444,4 +444,52 @@ 
   > EOF
   add back removed file a (Yn)? n
   $ ls
+  $ hg revert -a
+  undeleting a
   $ cd ..
+
+Test "keep" mode
+
+  $ cat <<EOF >> $HGRCPATH
+  > [experimental]
+  > revert.interactive.select-to-keep = true
+  > EOF
+
+  $ cd repo
+  $ printf "x\na\ny\n" > a
+  $ hg diff
+  diff -r cb9a9f314b8b a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,1 +1,3 @@
+  +x
+   a
+  +y
+  $ cat > $TESTTMP/editor.sh << '__EOF__'
+  > echo "+new line" >> "$1"
+  > __EOF__
+
+  $ HGEDITOR="\"sh\" \"${TESTTMP}/editor.sh\"" hg revert -i  <<EOF
+  > y
+  > n
+  > e
+  > EOF
+  diff --git a/a b/a
+  2 hunks, 2 lines changed
+  examine changes to 'a'? [Ynesfdaq?] y
+  
+  @@ -1,1 +1,2 @@
+  +x
+   a
+  keep change 1/2 to 'a'? [Ynesfdaq?] n
+  
+  @@ -1,1 +2,2 @@
+   a
+  +y
+  keep change 2/2 to 'a'? [Ynesfdaq?] e
+  
+  reverting a
+  $ cat a
+  a
+  y
+  new line
diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -1012,11 +1012,13 @@ 
         'multiple': {
             'apply': _("apply change %d/%d to '%s'?"),
             'discard': _("discard change %d/%d to '%s'?"),
+            'keep': _("keep change %d/%d to '%s'?"),
             'record': _("record change %d/%d to '%s'?"),
         },
         'single': {
             'apply': _("apply this change to '%s'?"),
             'discard': _("discard this change to '%s'?"),
+            'keep': _("keep this change to '%s'?"),
             'record': _("record this change to '%s'?"),
         },
         'help': {
@@ -1040,6 +1042,16 @@ 
                          '$$ Discard &all changes to all remaining files'
                          '$$ &Quit, discarding no changes'
                          '$$ &? (display help)'),
+            'keep': _('[Ynesfdaq?]'
+                         '$$ &Yes, keep this change'
+                         '$$ &No, skip this change'
+                         '$$ &Edit this change manually'
+                         '$$ &Skip remaining changes to this file'
+                         '$$ Keep remaining changes to this &file'
+                         '$$ &Done, skip remaining changes and files'
+                         '$$ Keep &all changes to all remaining files'
+                         '$$ &Quit, keeping all changes'
+                         '$$ &? (display help)'),
             'record': _('[Ynesfdaq?]'
                         '$$ &Yes, record this change'
                         '$$ &No, skip this change'
diff --git a/mercurial/crecord.py b/mercurial/crecord.py
--- a/mercurial/crecord.py
+++ b/mercurial/crecord.py
@@ -566,6 +566,7 @@ 
 _headermessages = { # {operation: text}
     'apply': _('Select hunks to apply'),
     'discard': _('Select hunks to discard'),
+    'keep': _('Select hunks to keep'),
     None: _('Select hunks to record'),
 }
 
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -595,6 +595,9 @@ 
 coreconfigitem('experimental', 'removeemptydirs',
     default=True,
 )
+coreconfigitem('experimental', 'revert.interactive.select-to-keep',
+    default=False,
+)
 coreconfigitem('experimental', 'revisions.prefixhexnode',
     default=False,
 )
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -3176,22 +3176,25 @@ 
                                          configprefix='revert.interactive.')
         diffopts.nodates = True
         diffopts.git = True
-        operation = 'discard'
-        reversehunks = True
-        if node != parent:
-            operation = 'apply'
-            reversehunks = False
-        if reversehunks:
+        operation = 'apply'
+        if node == parent:
+            if repo.ui.configbool('experimental',
+                                  'revert.interactive.select-to-keep'):
+                operation = 'keep'
+            else:
+                operation = 'discard'
+
+        if operation == 'apply':
+            diff = patch.diff(repo, None, ctx.node(), m, opts=diffopts)
+        else:
             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, opts = recordfilter(repo.ui, originalchunks,
                                         operation=operation)
-            if reversehunks:
+            if operation == 'discard':
                 chunks = patch.reversehunks(chunks)
 
         except error.PatchError as err:
@@ -3205,6 +3208,7 @@ 
         # chunks are serialized per file, but files aren't sorted
         for f in sorted(set(c.header.filename() for c in chunks if ishunk(c))):
             prntstatusmsg('revert', f)
+        files = set()
         for c in chunks:
             if ishunk(c):
                 abs = c.header.filename()
@@ -3214,6 +3218,10 @@ 
                     bakname = scmutil.backuppath(repo.ui, repo, abs)
                     util.copyfile(target, bakname)
                     tobackup.remove(abs)
+                if abs not in files:
+                    files.add(abs)
+                    if operation == 'keep':
+                        checkout(abs)
             c.write(fp)
         dopatch = fp.tell()
         fp.seek(0)