[PATCH] Add a --reverse option to patch

Brendan Cully brendan at kublai.com
Tue Aug 28 11:29:43 CDT 2007


# HG changeset patch
# User Brendan Cully <brendan at kublai.com>
# Date 1188318573 25200
# Node ID 9cd31d86bd4ead172e706e1c46b6cba9fea5ff44
# Parent  8040f2e4cad04e82cf7b67b7d671024f3a9af90f
Add a --reverse option to patch.
This is necessary to create a reverse diff based on the working
directory, because only one revision is given in this case. It is also
useful for the rdiff extension, where -r flags are interpreted in
order as local revision, remote revision.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1019,7 +1019,7 @@ def diff(ui, repo, *pats, **opts):
     fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
 
     patch.diff(repo, node1, node2, fns, match=matchfn,
-               opts=patch.diffopts(ui, opts))
+               opts=patch.diffopts(ui, opts), reverse=opts['reverse'])
 
 def export(ui, repo, *changesets, **opts):
     """dump the header and diffs for one or more changesets
@@ -2886,6 +2886,7 @@ table = {
            _('ignore changes in the amount of white space')),
           ('B', 'ignore-blank-lines', None,
            _('ignore changes whose lines are all blank')),
+          ('', 'reverse', None, _('reverse patch direction'))
          ] + walkopts,
          _('hg diff [OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
     "^export":
diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -1103,7 +1103,7 @@ def b85diff(to, tn):
     return ''.join(ret)
 
 def diff(repo, node1=None, node2=None, files=None, match=util.always,
-         fp=None, changes=None, opts=None):
+         fp=None, changes=None, opts=None, reverse=False):
     '''print diff of changes to files between two nodes, or node and
     working directory.
 
@@ -1145,6 +1145,8 @@ def diff(repo, node1=None, node2=None, f
     if not modified and not added and not removed:
         return
 
+    execf1 = man1.execf
+    linkf1 = man1.linkf
     if node2:
         ctx2 = context.changectx(repo, node2)
         execf2 = ctx2.manifest().execf
@@ -1158,6 +1160,12 @@ def diff(repo, node1=None, node2=None, f
             execf2 = mc.execf
             linkf2 = mc.linkf
 
+    if reverse:
+        node1, ctx1, node2, ctx2 = node2, ctx2, node1, ctx1
+        execf1, linkf1, execf2, linkf2 = execf2, linkf2, execf1, linkf1
+        added, removed = removed, added
+        man1 = ctx1.manifest()
+        
     # returns False if there was no rename between ctx1 and ctx2
     # returns None if the file was created between ctx1 and ctx2
     # returns the (file, node) present in ctx1 that was renamed to f in ctx2
@@ -1225,7 +1233,7 @@ def diff(repo, node1=None, node2=None, f
                 mode = gitmode(execf2(f), linkf2(f))
                 if f in copied:
                     a = copied[f]
-                    omode = gitmode(man1.execf(a), man1.linkf(a))
+                    omode = gitmode(execf1(a), linkf1(a))
                     addmodehdr(header, omode, mode)
                     if a in removed and a not in gone:
                         op = 'rename'
@@ -1243,10 +1251,10 @@ def diff(repo, node1=None, node2=None, f
                 if f in srcs:
                     dodiff = False
                 else:
-                    mode = gitmode(man1.execf(f), man1.linkf(f))
+                    mode = gitmode(execf1(f), linkf1(f))
                     header.append('deleted file mode %s\n' % mode)
             else:
-                omode = gitmode(man1.execf(f), man1.linkf(f))
+                omode = gitmode(execf1(f), linkf1(f))
                 nmode = gitmode(execf2(f), linkf2(f))
                 addmodehdr(header, omode, nmode)
                 if util.binary(to) or util.binary(tn):


More information about the Mercurial-devel mailing list