diff mercurial/patch.py @ 2934:2f190e998eb3

Teach mq about git patches
author Brendan Cully <brendan@kublai.com>
date Wed, 16 Aug 2006 19:49:45 -0700
parents 439fd013360d
children 6ba3409f9725
line wrap: on
line diff
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -343,10 +343,27 @@ def diff(repo, node1=None, node2=None, f
 
     if not node1:
         node1 = repo.dirstate.parents()[0]
+
+    clcache = {}
+    def getchangelog(n):
+        if n not in clcache:
+            clcache[n] = repo.changelog.read(n)
+        return clcache[n]
+    mcache = {}
+    def getmanifest(n):
+        if n not in mcache:
+            mcache[n] = repo.manifest.read(n)
+        return mcache[n]
+    fcache = {}
+    def getfile(f):
+        if f not in fcache:
+            fcache[f] = repo.file(f)
+        return fcache[f]
+
     # reading the data for node1 early allows it to play nicely
     # with repo.status and the revlog cache.
-    change = repo.changelog.read(node1)
-    mmap = repo.manifest.read(change[0])
+    change = getchangelog(node1)
+    mmap = getmanifest(change[0])
     date1 = util.datestr(change[2])
 
     if not changes:
@@ -367,17 +384,32 @@ def diff(repo, node1=None, node2=None, f
     if not modified and not added and not removed:
         return
 
+    def renamedbetween(f, n1, n2):
+        r1, r2 = map(repo.changelog.rev, (n1, n2))
+        src = None
+        while r2 > r1:
+            cl = getchangelog(n2)[0]
+            m = getmanifest(cl)
+            try:
+                src = getfile(f).renamed(m[f])
+            except KeyError:
+                return None
+            if src:
+                f = src[0]
+            n2 = repo.changelog.parents(n2)[0]
+            r2 = repo.changelog.rev(n2)
+        return src
+
     if node2:
-        change = repo.changelog.read(node2)
-        mmap2 = repo.manifest.read(change[0])
+        change = getchangelog(node2)
+        mmap2 = getmanifest(change[0])
         _date2 = util.datestr(change[2])
         def date2(f):
             return _date2
         def read(f):
-            return repo.file(f).read(mmap2[f])
+            return getfile(f).read(mmap2[f])
         def renamed(f):
-            src = repo.file(f).renamed(mmap2[f])
-            return src and src[0] or None
+            return renamedbetween(f, node1, node2)
     else:
         tz = util.makedate()[1]
         _date2 = util.datestr()
@@ -390,7 +422,18 @@ def diff(repo, node1=None, node2=None, f
         def read(f):
             return repo.wread(f)
         def renamed(f):
-            return repo.dirstate.copies.get(f)
+            src = repo.dirstate.copies.get(f)
+            parent = repo.dirstate.parents()[0]
+            if src:
+                f = src[0]
+            of = renamedbetween(f, node1, parent)
+            if of:
+                return of
+            elif src:
+                cl = getchangelog(parent)[0]
+                return (src, getmanifest(cl)[src])
+            else:
+                return None
 
     if repo.ui.quiet:
         r = None
@@ -404,7 +447,7 @@ def diff(repo, node1=None, node2=None, f
             src = renamed(f)
             if src:
                 copied[f] = src
-        srcs = [x[1] for x in copied.items()]
+        srcs = [x[1][0] for x in copied.items()]
 
     all = modified + added + removed
     all.sort()
@@ -413,7 +456,7 @@ def diff(repo, node1=None, node2=None, f
         tn = None
         dodiff = True
         if f in mmap:
-            to = repo.file(f).read(mmap[f])
+            to = getfile(f).read(mmap[f])
         if f not in removed:
             tn = read(f)
         if opts.git:
@@ -432,13 +475,13 @@ def diff(repo, node1=None, node2=None, f
                 else:
                     mode = gitmode(util.is_exec(repo.wjoin(f), None))
                 if f in copied:
-                    a = copied[f]
+                    a, arev = copied[f]
                     omode = gitmode(mmap.execf(a))
                     addmodehdr(header, omode, mode)
                     op = a in removed and 'rename' or 'copy'
                     header.append('%s from %s\n' % (op, a))
                     header.append('%s to %s\n' % (op, f))
-                    to = repo.file(a).read(mmap[a])
+                    to = getfile(a).read(arev)
                 else:
                     header.append('new file mode %s\n' % mode)
             elif f in removed: