#!/usr/bin/env python import sys, math, random, os, re, signal, tempfile, time from heapq import heappush, heappop from sets import Set from gitMergeCommon import * def mergeMerge(a, b): print 'Running merge-script HEAD', b.sha, '...' [out, code] = runProgram(['git-merge-script', 'HEAD', b.sha, 'merge message'], returnCode=True, pipeOutput=False) if code == 0: return True else: return False def gitResolveMerge(a, b): print 'Running git resolve HEAD', b.sha, '...' [out, code] = runProgram(['git', 'resolve', 'HEAD', b.sha, 'merge message'], returnCode=True, pipeOutput=False) if code == 0: return True else: return False def doWork(graph, commits): print 'commits:', repr(commits) result = [] totalMergeTime = 0 totalResolveTime = 0 numCommits = 0 try: for commit in graph.commits: if len(commits) > 0 and not (commit.sha in commits): continue if len(commit.parents) > 1: res = commit.sha + ' : ' if len(commit.parents) == 2: numCommits += 1 print '---------------------------------------' print 'Testing commit', commit.sha, '(tree)', commit.tree() a = commit.parents[0] b = commit.parents[1] runProgram(['git-reset-script', '--hard', a.sha]) print 'Running git resolve...' stdout.flush() startTime = time.time() resResolve = gitResolveMerge(a, b) timeResolve = time.time() - startTime totalResolveTime += timeResolve if resResolve: resolveHead = Commit(runProgram(['git-rev-parse', '--verify', 'HEAD']).rstrip(), [a, b]) runProgram(['git-reset-script', '--hard', a.sha]) print 'Running merge...' stdout.flush() startTime = time.time() resMerge = mergeMerge(a, b) timeMerge = time.time() - startTime totalMergeTime += timeMerge if resMerge: mergeHead = Commit(runProgram(['git-rev-parse', '--verify', 'HEAD']).rstrip(), [a, b]) res += 'time r: ' + str(int(timeResolve)) + ' m: ' + str(int(timeMerge)) + '\t' if resResolve and resMerge: if resolveHead.tree() == mergeHead.tree(): res += 'Identical result' else: res += 'Non-identical results! resolve: ' + resolveHead.sha + \ ' merge: ' + mergeHead.sha else: if resResolve: res += 'resolve succeeded (' + resolveHead.sha + '), ' else: res += 'resolve failed, ' if resMerge: res += 'merge succeeded (' + mergeHead.sha + ')' else: res += 'merge failed' else: res += 'Ignoring octupus merge' print res result.append(res) stdout.flush() finally: print '\n\n\nResults:' for r in result: print r print 'Avg resolve time:', float(totalResolveTime) / numCommits print 'Avg merge time:', float(totalMergeTime) / numCommits def writeHead(head, sha): if sha[-1] != '\n': sha += '\n' try: f = open(os.environ['GIT_DIR'] + '/' + head, 'w') f.write(sha) f.close() except IOError, e: print 'Failed to write to', os.environ['GIT_DIR'] + '/' + head + ':', e.strerror sys.exit(1) return True stdout = sys.stdout setupEnvironment() repoValid() head = runProgram(['git-rev-parse', '--verify', 'HEAD^0']).rstrip() print 'Building graph...' stdout.flush() graph = buildGraph([head]) print 'Graph building done.' stdout.flush() print 'Processing', len(graph.commits), 'commits (' + \ str(len([x for x in graph.commits if len(x.parents) > 1])) + ' merge commits)...' originalHead = open('.git/HEAD', 'r').read() print 'Original head:', originalHead stdout.flush() writeHead('original-head', originalHead) try: doWork(graph, sys.argv[1:]) finally: writeHead('HEAD', originalHead)