changeset 9725:3f522d2fa633

diff: add --inverse option Most of the time, one can reverse a diff by swapping the revisions passed with -r but it happens that if you use the global -R, and diff against the tip of the current repo, you can't swap the revisions. One use-case for that is reviewing changes from a bundle before unbundling. One could also pipe the output of `hg diff` to a command line filter that reverses the diff, but that would remove the benefit from color diffs. Therefore, having an option in `hg diff` to reverse a diff is a good thing. The option flag selection was tricky. GNU patch uses -R/--reverse but -R is already used as a global option and --reverse would make --rev ambiguous.
author Yannick Gingras <ygingras@ygingras.net>
date Thu, 05 Nov 2009 15:18:56 +0100
parents 40ef3bf3e04a
children 430e59ff3437
files hgext/mq.py mercurial/commands.py mercurial/patch.py tests/test-debugcomplete.out tests/test-diff-inverse tests/test-diff-inverse.out tests/test-help.out tests/test-mq-qdiff tests/test-mq-qdiff.out
diffstat 9 files changed, 80 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/mq.py	Thu Nov 05 15:06:35 2009 +0100
+++ b/hgext/mq.py	Thu Nov 05 15:18:56 2009 +0100
@@ -1129,8 +1129,12 @@
             self.ui.write(_("no patches applied\n"))
             return
         qp = self.qparents(repo, top)
+        if opts.get('inverse'):
+            node1, node2 = None, qp
+        else:
+            node1, node2 = qp, None
         self._diffopts = patch.diffopts(self.ui, opts)
-        self.printdiff(repo, qp, files=pats, opts=opts)
+        self.printdiff(repo, node1, node2, files=pats, opts=opts)
 
     def refresh(self, repo, pats=None, **opts):
         if len(self.applied) == 0:
--- a/mercurial/commands.py	Thu Nov 05 15:06:35 2009 +0100
+++ b/mercurial/commands.py	Thu Nov 05 15:18:56 2009 +0100
@@ -1102,6 +1102,7 @@
     revs = opts.get('rev')
     change = opts.get('change')
     stat = opts.get('stat')
+    inv = opts.get('inverse')
 
     if revs and change:
         msg = _('cannot specify --rev and --change at the same time')
@@ -1112,6 +1113,9 @@
     else:
         node1, node2 = cmdutil.revpair(repo, revs)
 
+    if inv:
+        node1, node2 = node2, node1
+
     if stat:
         opts['unified'] = '0'
     diffopts = patch.diffopts(ui, opts)
@@ -3280,6 +3284,7 @@
 
 diffopts2 = [
     ('p', 'show-function', None, _('show which function each change is in')),
+    ('', 'inverse', None, _('produce a diff that undoes the changes')),
     ('w', 'ignore-all-space', None,
      _('ignore white space when comparing lines')),
     ('b', 'ignore-space-change', None,
--- a/mercurial/patch.py	Thu Nov 05 15:06:35 2009 +0100
+++ b/mercurial/patch.py	Thu Nov 05 15:18:56 2009 +0100
@@ -1216,7 +1216,7 @@
     if opts is None:
         opts = mdiff.defaultopts
 
-    if not node1:
+    if not node1 and not node2:
         node1 = repo.dirstate.parents()[0]
 
     def lrugetfilectx():
--- a/tests/test-debugcomplete.out	Thu Nov 05 15:06:35 2009 +0100
+++ b/tests/test-debugcomplete.out	Thu Nov 05 15:18:56 2009 +0100
@@ -167,7 +167,7 @@
 annotate: rev, follow, text, user, date, number, changeset, line-number, include, exclude
 clone: noupdate, updaterev, rev, pull, uncompressed, ssh, remotecmd
 commit: addremove, close-branch, include, exclude, message, logfile, date, user
-diff: rev, change, text, git, nodates, show-function, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
+diff: rev, change, text, git, nodates, show-function, inverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
 export: output, switch-parent, text, git, nodates
 forget: include, exclude
 init: ssh, remotecmd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-diff-inverse	Thu Nov 05 15:18:56 2009 +0100
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+hg init
+cat > a <<EOF
+a
+b
+c
+EOF
+hg ci -Am adda
+
+cat > a <<EOF
+d
+e
+f
+EOF
+hg ci -m moda
+
+hg diff --inverse -r0 -r1
+
+cat >> a <<EOF
+g
+h
+EOF
+hg diff --inverse --nodates
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-diff-inverse.out	Thu Nov 05 15:18:56 2009 +0100
@@ -0,0 +1,20 @@
+adding a
+diff -r 2855cdcfcbb7 -r 8e1805a3cf6e a
+--- a/a	Thu Jan 01 00:00:00 1970 +0000
++++ b/a	Thu Jan 01 00:00:00 1970 +0000
+@@ -1,3 +1,3 @@
+-d
+-e
+-f
++a
++b
++c
+diff -r 2855cdcfcbb7 a
+--- a/a
++++ b/a
+@@ -1,5 +1,3 @@
+ d
+ e
+ f
+-g
+-h
--- a/tests/test-help.out	Thu Nov 05 15:06:35 2009 +0100
+++ b/tests/test-help.out	Thu Nov 05 15:18:56 2009 +0100
@@ -237,6 +237,7 @@
  -g --git                  use git extended diff format
     --nodates              don't include dates in diff headers
  -p --show-function        show which function each change is in
+    --inverse              produce a diff that undoes the changes
  -w --ignore-all-space     ignore white space when comparing lines
  -b --ignore-space-change  ignore changes in the amount of white space
  -B --ignore-blank-lines   ignore changes whose lines are all blank
--- a/tests/test-mq-qdiff	Thu Nov 05 15:06:35 2009 +0100
+++ b/tests/test-mq-qdiff	Thu Nov 05 15:18:56 2009 +0100
@@ -55,5 +55,8 @@
 echo % qdiff -U 1 -B
 hg qdiff --nodates -U 1 -B
 
-echo qdiff -w
+echo % qdiff -w
 hg qdiff --nodates -w
+
+echo % qdiff --inverse
+hg qdiff --nodates --inverse
--- a/tests/test-mq-qdiff.out	Thu Nov 05 15:06:35 2009 +0100
+++ b/tests/test-mq-qdiff.out	Thu Nov 05 15:18:56 2009 +0100
@@ -76,7 +76,7 @@
 +hello  world
 +     goodbye world
  7
-qdiff -w
+% qdiff -w
 diff -r 35fb829491c1 lines
 --- a/lines
 +++ b/lines
@@ -86,3 +86,21 @@
  1
  2
  3
+% qdiff --inverse
+diff -r 35fb829491c1 lines
+--- a/lines
++++ b/lines
+@@ -1,11 +1,9 @@
+-
+-
+ 1
+ 2
+ 3
+ 4
+-hello  world
+-     goodbye world
++hello world
++goodbye world
+ 7
+ 8
+ 9