GIT 1.1.5
[gitweb.git] / git-merge-recursive.py
index 1bf73f336d4c34011b9cfe5a13b88a1f657d3f4e..56c3641abbe872bd44ec6c7745e6bc3705874869 100755 (executable)
@@ -3,11 +3,13 @@
 # Copyright (C) 2005 Fredrik Kuivinen
 #
 
-import sys, math, random, os, re, signal, tempfile, stat, errno, traceback
+import sys
+sys.path.append('''@@GIT_PYTHON_PATH@@''')
+
+import math, random, os, re, signal, tempfile, stat, errno, traceback
 from heapq import heappush, heappop
 from sets import Set
 
-sys.path.append('''@@GIT_PYTHON_PATH@@''')
 from gitMergeCommon import *
 
 outputIndent = 0
@@ -96,7 +98,7 @@ def merge(h1, h2, branch1Name, branch2Name, graph, callDepth=0):
 def getFilesAndDirs(tree):
     files = Set()
     dirs = Set()
-    out = runProgram(['git-ls-tree', '-r', '-z', tree])
+    out = runProgram(['git-ls-tree', '-r', '-z', '-t', tree])
     for l in out.split('\0'):
         m = getFilesRE.match(l)
         if m:
@@ -243,7 +245,7 @@ def updateFileExt(sha, mode, path, updateCache, updateWd):
 
             try:
                 createDir = not stat.S_ISDIR(os.lstat(p).st_mode)
-            except
+            except OSError:
                 createDir = True
             
             if createDir:
@@ -278,6 +280,24 @@ def updateFileExt(sha, mode, path, updateCache, updateWd):
         runProgram(['git-update-index', '--add', '--cacheinfo',
                     '0%o' % mode, sha, path])
 
+def setIndexStages(path,
+                   oSHA1, oMode,
+                   aSHA1, aMode,
+                   bSHA1, bMode,
+                   clear=True):
+    istring = []
+    if clear:
+        istring.append("0 " + ("0" * 40) + "\t" + path + "\0")
+    if oMode:
+        istring.append("%o %s %d\t%s\0" % (oMode, oSHA1, 1, path))
+    if aMode:
+        istring.append("%o %s %d\t%s\0" % (aMode, aSHA1, 2, path))
+    if bMode:
+        istring.append("%o %s %d\t%s\0" % (bMode, bSHA1, 3, path))
+
+    runProgram(['git-update-index', '-z', '--index-info'],
+               input="".join(istring))
+
 def removeFile(clean, path):
     updateCache = cacheOnly or clean
     updateWd = not cacheOnly
@@ -291,6 +311,10 @@ def removeFile(clean, path):
         except OSError, e:
             if e.errno != errno.ENOENT and e.errno != errno.EISDIR:
                 raise
+        try:
+            os.removedirs(os.path.dirname(path))
+        except OSError:
+            pass
 
 def uniquePath(path, branch):
     def fileExists(path):
@@ -554,7 +578,7 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB):
             continue
 
         ren1.processed = True
-        removeFile(True, ren1.srcName)
+
         if ren2:
             # Renamed in 1 and renamed in 2
             assert(ren1.srcName == ren2.srcName)
@@ -582,11 +606,19 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB):
                            'adding as', dstName2, 'instead.')
                     removeFile(False, ren2.dstName)
                 else:
-                    dstName2 = ren1.dstName
+                    dstName2 = ren2.dstName
+                setIndexStages(dstName1,
+                               None, None,
+                               ren1.dstSha, ren1.dstMode,
+                              None, None)
+                setIndexStages(dstName2,
+                               None, None,
+                               None, None,
+                               ren2.dstSha, ren2.dstMode)
 
-                updateFile(False, ren1.dstSha, ren1.dstMode, dstName1)
-                updateFile(False, ren2.dstSha, ren2.dstMode, dstName2)
             else:
+                removeFile(True, ren1.srcName)
+
                 [resSha, resMode, clean, merge] = \
                          mergeFile(ren1.srcName, ren1.srcSha, ren1.srcMode,
                                    ren1.dstName, ren1.dstSha, ren1.dstMode,
@@ -605,10 +637,15 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB):
                     cleanMerge = False
 
                     if not cacheOnly:
-                        updateFileExt(ren1.dstSha, ren1.dstMode, ren1.dstName,
-                                      updateCache=True, updateWd=False)
+                        setIndexStages(ren1.dstName,
+                                       ren1.srcSha, ren1.srcMode,
+                                       ren1.dstSha, ren1.dstMode,
+                                       ren2.dstSha, ren2.dstMode)
+
                 updateFile(clean, resSha, resMode, ren1.dstName)
         else:
+            removeFile(True, ren1.srcName)
+
             # Renamed in 1, maybe changed in 2
             if renamesA == renames1:
                 stage = 3
@@ -666,11 +703,24 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB):
                 tryMerge = True
 
             if tryMerge:
+
+                oName, oSHA1, oMode = ren1.srcName, ren1.srcSha, ren1.srcMode
+                aName, bName = ren1.dstName, ren1.srcName
+                aSHA1, bSHA1 = ren1.dstSha, srcShaOtherBranch
+                aMode, bMode = ren1.dstMode, srcModeOtherBranch
+                aBranch, bBranch = branchName1, branchName2
+
+                if renamesA != renames1:
+                    aName, bName = bName, aName
+                    aSHA1, bSHA1 = bSHA1, aSHA1
+                    aMode, bMode = bMode, aMode
+                    aBranch, bBranch = bBranch, aBranch
+
                 [resSha, resMode, clean, merge] = \
-                         mergeFile(ren1.srcName, ren1.srcSha, ren1.srcMode,
-                                   ren1.dstName, ren1.dstSha, ren1.dstMode,
-                                   ren1.srcName, srcShaOtherBranch, srcModeOtherBranch,
-                                   branchName1, branchName2)
+                         mergeFile(oName, oSHA1, oMode,
+                                   aName, aSHA1, aMode,
+                                   bName, bSHA1, bMode,
+                                   aBranch, bBranch);
 
                 if merge or not clean:
                     output('Renaming', fmtRename(ren1.srcName, ren1.dstName))
@@ -684,8 +734,11 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB):
                     cleanMerge = False
 
                     if not cacheOnly:
-                        updateFileExt(ren1.dstSha, ren1.dstMode, ren1.dstName,
-                                      updateCache=True, updateWd=False)
+                        setIndexStages(ren1.dstName,
+                                       oSHA1, oMode,
+                                       aSHA1, aMode,
+                                       bSHA1, bMode)
+
                 updateFile(clean, resSha, resMode, ren1.dstName)
 
     return cleanMerge
@@ -822,8 +875,6 @@ def processEntry(entry, branch1Name, branch2Name):
             if cacheOnly:
                 updateFile(False, sha, mode, path)
             else:
-                updateFileExt(aSha, aMode, path,
-                              updateCache=True, updateWd=False)
                 updateFileExt(sha, mode, path, updateCache=False, updateWd=True)
     else:
         die("ERROR: Fatal merge failure, shouldn't happen.")