X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=git-merge-recursive.py;h=1bf73f336d4c34011b9cfe5a13b88a1f657d3f4e;hb=a0fa2a10b401aa4c8b13d176a5e3e3b7c455208f;hp=626d85493a64d798dedbdc52b2b0f68d56d447fd;hpb=29504118f8528f658fd0bfc02d8d78d4c01dc2cc;p=git.git diff --git a/git-merge-recursive.py b/git-merge-recursive.py index 626d8549..1bf73f33 100755 --- a/git-merge-recursive.py +++ b/git-merge-recursive.py @@ -1,4 +1,7 @@ #!/usr/bin/python +# +# Copyright (C) 2005 Fredrik Kuivinen +# import sys, math, random, os, re, signal, tempfile, stat, errno, traceback from heapq import heappush, heappop @@ -7,6 +10,11 @@ from sets import Set sys.path.append('''@@GIT_PYTHON_PATH@@''') from gitMergeCommon import * +outputIndent = 0 +def output(*args): + sys.stdout.write(' '*outputIndent) + printList(args) + originalIndexFile = os.environ.get('GIT_INDEX_FILE', os.environ.get('GIT_DIR', '.git') + '/index') temporaryIndexFile = os.environ.get('GIT_DIR', '.git') + \ @@ -41,27 +49,27 @@ def merge(h1, h2, branch1Name, branch2Name, graph, callDepth=0): assert(isinstance(h1, Commit) and isinstance(h2, Commit)) assert(isinstance(graph, Graph)) - def infoMsg(*args): - sys.stdout.write(' '*callDepth) - printList(args) + global outputIndent - infoMsg('Merging:') - infoMsg(h1) - infoMsg(h2) + output('Merging:') + output(h1) + output(h2) sys.stdout.flush() ca = getCommonAncestors(graph, h1, h2) - infoMsg('found', len(ca), 'common ancestor(s):') + output('found', len(ca), 'common ancestor(s):') for x in ca: - infoMsg(x) + output(x) sys.stdout.flush() mergedCA = ca[0] for h in ca[1:]: + outputIndent = callDepth+1 [mergedCA, dummy] = merge(mergedCA, h, - 'Temporary shared merge branch 1', - 'Temporary shared merge branch 2', + 'Temporary merge branch 1', + 'Temporary merge branch 2', graph, callDepth+1) + outputIndent = callDepth assert(isinstance(mergedCA, Commit)) global cacheOnly @@ -116,7 +124,7 @@ def mergeTrees(head, merge, common, branch1Name, branch2Name): assert(isSha(head) and isSha(merge) and isSha(common)) if common == merge: - print 'Already uptodate!' + output('Already uptodate!') return [head, True] if cacheOnly: @@ -207,7 +215,7 @@ def mergeFile(oPath, oSha, oMode, aPath, aSha, aMode, bPath, bSha, bMode, os.unlink(orig) os.unlink(src1) os.unlink(src2) - + clean = (code == 0) else: assert(stat.S_ISLNK(aMode) and stat.S_ISLNK(bMode)) @@ -295,13 +303,14 @@ def uniquePath(path, branch): else: raise - newPath = path + '_' + branch + branch = branch.replace('/', '_') + newPath = path + '~' + branch suffix = 0 while newPath in currentFileSet or \ newPath in currentDirectorySet or \ fileExists(newPath): suffix += 1 - newPath = path + '_' + branch + '_' + str(suffix) + newPath = path + '~' + branch + '_' + str(suffix) currentFileSet.add(newPath) return newPath @@ -553,23 +562,24 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB): ren2.processed = True if ren1.dstName != ren2.dstName: - print 'CONFLICT (rename/rename): Rename', \ - fmtRename(path, ren1.dstName), 'in branch', branchName1, \ - 'rename', fmtRename(path, ren2.dstName), 'in', branchName2 + output('CONFLICT (rename/rename): Rename', + fmtRename(path, ren1.dstName), 'in branch', branchName1, + 'rename', fmtRename(path, ren2.dstName), 'in', + branchName2) cleanMerge = False if ren1.dstName in currentDirectorySet: dstName1 = uniquePath(ren1.dstName, branchName1) - print ren1.dstName, 'is a directory in', branchName2, \ - 'adding as', dstName1, 'instead.' + output(ren1.dstName, 'is a directory in', branchName2, + 'adding as', dstName1, 'instead.') removeFile(False, ren1.dstName) else: dstName1 = ren1.dstName if ren2.dstName in currentDirectorySet: dstName2 = uniquePath(ren2.dstName, branchName2) - print ren2.dstName, 'is a directory in', branchName1, \ - 'adding as', dstName2, 'instead.' + output(ren2.dstName, 'is a directory in', branchName1, + 'adding as', dstName2, 'instead.') removeFile(False, ren2.dstName) else: dstName2 = ren1.dstName @@ -577,18 +587,21 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB): updateFile(False, ren1.dstSha, ren1.dstMode, dstName1) updateFile(False, ren2.dstSha, ren2.dstMode, dstName2) else: - print 'Renaming', fmtRename(path, ren1.dstName) [resSha, resMode, clean, merge] = \ mergeFile(ren1.srcName, ren1.srcSha, ren1.srcMode, ren1.dstName, ren1.dstSha, ren1.dstMode, ren2.dstName, ren2.dstSha, ren2.dstMode, branchName1, branchName2) + if merge or not clean: + output('Renaming', fmtRename(path, ren1.dstName)) + if merge: - print 'Auto-merging', ren1.dstName + output('Auto-merging', ren1.dstName) if not clean: - print 'CONFLICT (content): merge conflict in', ren1.dstName + output('CONFLICT (content): merge conflict in', + ren1.dstName) cleanMerge = False if not cacheOnly: @@ -612,25 +625,25 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB): if ren1.dstName in currentDirectorySet: newPath = uniquePath(ren1.dstName, branchName1) - print 'CONFLICT (rename/directory): Rename', \ - fmtRename(ren1.srcName, ren1.dstName), 'in', branchName1,\ - 'directory', ren1.dstName, 'added in', branchName2 - print 'Renaming', ren1.srcName, 'to', newPath, 'instead' + output('CONFLICT (rename/directory): Rename', + fmtRename(ren1.srcName, ren1.dstName), 'in', branchName1, + 'directory', ren1.dstName, 'added in', branchName2) + output('Renaming', ren1.srcName, 'to', newPath, 'instead') cleanMerge = False removeFile(False, ren1.dstName) updateFile(False, ren1.dstSha, ren1.dstMode, newPath) elif srcShaOtherBranch == None: - print 'CONFLICT (rename/delete): Rename', \ - fmtRename(ren1.srcName, ren1.dstName), 'in', \ - branchName1, 'and deleted in', branchName2 + output('CONFLICT (rename/delete): Rename', + fmtRename(ren1.srcName, ren1.dstName), 'in', + branchName1, 'and deleted in', branchName2) cleanMerge = False updateFile(False, ren1.dstSha, ren1.dstMode, ren1.dstName) elif dstShaOtherBranch: newPath = uniquePath(ren1.dstName, branchName2) - print 'CONFLICT (rename/add): Rename', \ - fmtRename(ren1.srcName, ren1.dstName), 'in', \ - branchName1 + '.', ren1.dstName, 'added in', branchName2 - print 'Adding as', newPath, 'instead' + output('CONFLICT (rename/add): Rename', + fmtRename(ren1.srcName, ren1.dstName), 'in', + branchName1 + '.', ren1.dstName, 'added in', branchName2) + output('Adding as', newPath, 'instead') updateFile(False, dstShaOtherBranch, dstModeOtherBranch, newPath) cleanMerge = False tryMerge = True @@ -638,12 +651,12 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB): dst2 = renames2.getDst(ren1.dstName) newPath1 = uniquePath(ren1.dstName, branchName1) newPath2 = uniquePath(dst2.dstName, branchName2) - print 'CONFLICT (rename/rename): Rename', \ - fmtRename(ren1.srcName, ren1.dstName), 'in', \ - branchName1+'. Rename', \ - fmtRename(dst2.srcName, dst2.dstName), 'in', branchName2 - print 'Renaming', ren1.srcName, 'to', newPath1, 'and', \ - dst2.srcName, 'to', newPath2, 'instead' + output('CONFLICT (rename/rename): Rename', + fmtRename(ren1.srcName, ren1.dstName), 'in', + branchName1+'. Rename', + fmtRename(dst2.srcName, dst2.dstName), 'in', branchName2) + output('Renaming', ren1.srcName, 'to', newPath1, 'and', + dst2.srcName, 'to', newPath2, 'instead') removeFile(False, ren1.dstName) updateFile(False, ren1.dstSha, ren1.dstMode, newPath1) updateFile(False, dst2.dstSha, dst2.dstMode, newPath2) @@ -653,18 +666,21 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB): tryMerge = True if tryMerge: - print 'Renaming', fmtRename(ren1.srcName, ren1.dstName) [resSha, resMode, clean, merge] = \ mergeFile(ren1.srcName, ren1.srcSha, ren1.srcMode, ren1.dstName, ren1.dstSha, ren1.dstMode, ren1.srcName, srcShaOtherBranch, srcModeOtherBranch, branchName1, branchName2) + if merge or not clean: + output('Renaming', fmtRename(ren1.srcName, ren1.dstName)) + if merge: - print 'Auto-merging', ren1.dstName + output('Auto-merging', ren1.dstName) if not clean: - print 'CONFLICT (rename/modify): Merge conflict in', ren1.dstName + output('CONFLICT (rename/modify): Merge conflict in', + ren1.dstName) cleanMerge = False if not cacheOnly: @@ -709,21 +725,21 @@ def processEntry(entry, branch1Name, branch2Name): (not aSha and bSha == oSha): # Deleted in both or deleted in one and unchanged in the other if aSha: - print 'Removing', path + output('Removing', path) removeFile(True, path) else: # Deleted in one and changed in the other cleanMerge = False if not aSha: - print 'CONFLICT (delete/modify):', path, 'deleted in', \ - branch1Name, 'and modified in', branch2Name + '.', \ - 'Version', branch2Name, 'of', path, 'left in tree.' + output('CONFLICT (delete/modify):', path, 'deleted in', + branch1Name, 'and modified in', branch2Name + '.', + 'Version', branch2Name, 'of', path, 'left in tree.') mode = bMode sha = bSha else: - print 'CONFLICT (modify/delete):', path, 'deleted in', \ - branch2Name, 'and modified in', branch1Name + '.', \ - 'Version', branch1Name, 'of', path, 'left in tree.' + output('CONFLICT (modify/delete):', path, 'deleted in', + branch2Name, 'and modified in', branch1Name + '.', + 'Version', branch1Name, 'of', path, 'left in tree.') mode = aMode sha = aSha @@ -750,14 +766,14 @@ def processEntry(entry, branch1Name, branch2Name): if path in currentDirectorySet: cleanMerge = False newPath = uniquePath(path, addBranch) - print 'CONFLICT (' + conf + '):', \ - 'There is a directory with name', path, 'in', \ - otherBranch + '. Adding', path, 'as', newPath + output('CONFLICT (' + conf + '):', + 'There is a directory with name', path, 'in', + otherBranch + '. Adding', path, 'as', newPath) removeFile(False, path) updateFile(False, sha, mode, newPath) else: - print 'Adding', path + output('Adding', path) updateFile(True, sha, mode, path) elif not oSha and aSha and bSha: @@ -767,10 +783,10 @@ def processEntry(entry, branch1Name, branch2Name): if aSha == bSha: if aMode != bMode: cleanMerge = False - print 'CONFLICT: File', path, \ - 'added identically in both branches, but permissions', \ - 'conflict', '0%o' % aMode, '->', '0%o' % bMode - print 'CONFLICT: adding with permission:', '0%o' % aMode + output('CONFLICT: File', path, + 'added identically in both branches, but permissions', + 'conflict', '0%o' % aMode, '->', '0%o' % bMode) + output('CONFLICT: adding with permission:', '0%o' % aMode) updateFile(False, aSha, aMode, path) else: @@ -780,9 +796,9 @@ def processEntry(entry, branch1Name, branch2Name): cleanMerge = False newPath1 = uniquePath(path, branch1Name) newPath2 = uniquePath(path, branch2Name) - print 'CONFLICT (add/add): File', path, \ - 'added non-identically in both branches. Adding as', \ - newPath1, 'and', newPath2, 'instead.' + output('CONFLICT (add/add): File', path, + 'added non-identically in both branches. Adding as', + newPath1, 'and', newPath2, 'instead.') removeFile(False, path) updateFile(False, aSha, aMode, newPath1) updateFile(False, bSha, bMode, newPath2) @@ -791,7 +807,7 @@ def processEntry(entry, branch1Name, branch2Name): # # case D: Modified in both, but differently. # - print 'Auto-merging', path + output('Auto-merging', path) [sha, mode, clean, dummy] = \ mergeFile(path, oSha, oMode, path, aSha, aMode, @@ -801,7 +817,7 @@ def processEntry(entry, branch1Name, branch2Name): updateFile(True, sha, mode, path) else: cleanMerge = False - print 'CONFLICT (content): Merge conflict in', path + output('CONFLICT (content): Merge conflict in', path) if cacheOnly: updateFile(False, sha, mode, path)