-
-
Save rcpao-enmotus/51d8e586c1edf9b3563dd67336e77449 to your computer and use it in GitHub Desktop.
Display diff between two commits.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import sys, subprocess, os | |
TOOLS = ['bcompare', 'meld'] | |
HEAD = 'HEAD' | |
TMP = '/tmp/' | |
execute = lambda command: subprocess.check_output(command) | |
which = lambda tool: execute(['which', tool]).strip() | |
def getTool(): | |
for tool in TOOLS: | |
try: | |
out = which(tool) | |
if tool in out: | |
return tool | |
except subprocess.CalledProcessError: | |
pass | |
return None | |
def printUsageAndExit(): | |
print 'Usage: python bdiff.py <project> <commit_one> <commit_two>' | |
print 'Example: python bdiff.py <project> 0 1' | |
print 'Example: python bdiff.py <project> fhejk7fe d78ewg9we' | |
print 'Example: python bdiff.py <project> 0 d78ewg9we' | |
print 'Example: python bdiff.py <project> HEAD d78ewg9we' | |
print 'Example: python bdiff.py <project> HEAD-4 87' | |
sys.exit(0) | |
def revParse(name, position): | |
if '-' in position: | |
position.replace('-', '~') | |
command = ['git', '-C', name, 'rev-parse', position] | |
return execute(command).strip() | |
def getCommitId(name, position): | |
index = -1; | |
command = ['git', '-C', name, 'log', '--pretty=format:"%h"', '--abbrev=7'] | |
reverse = ['--reverse'] | |
if position == HEAD: | |
return revParse(name, position) | |
elif HEAD in position and ('-' in position or '~' in position): | |
try: | |
return revParse(name, position) | |
except ValueError: | |
print "Error in parsing commit ids!" | |
sys.exit(0) | |
elif HEAD in position: | |
print "Error in parsing commit ids!" | |
sys.exit(-1) | |
elif '-' in position: | |
commitid = position.split()[0][:7] | |
index = execute(command).splitlines().index(commitid) | |
try: | |
index -= int(position.split()[1]) | |
except ValueError: | |
print "Unable to paser the input!" | |
sys.exit(-1) | |
elif position.isdigit(): | |
command.extend(reverse) | |
index = int(position) | |
else: | |
return position | |
if index >= 0: | |
logs = execute(command).splitlines() | |
return logs[index].strip() | |
else: return None | |
dir_name = lambda commit: (commit if commit else '0') | |
tmp = lambda name: (TMP + dir_name(name)) | |
def validate(name, commit): | |
if not commit: | |
print "Nothing to do, exit!" | |
return False | |
try: | |
if commit: | |
execute(['git', '-C', name, 'cat-file', '-t', commit]) | |
except subprocess.CalledProcessError: | |
return False | |
return True | |
cleanup = lambda commit: execute(['rm', '-rf', tmp(commit)]) | |
def checkoutCommit(name, commit): | |
if commit: | |
execute(['git', 'clone', name, tmp(commit)]) | |
execute(['git', '-C', tmp(commit), 'checkout', commit]) | |
else: | |
execute(['mkdir', tmp('0')]) | |
def compare(tool, commit1, commit2): | |
execute([tool, tmp(commit1), tmp(commit2)]) | |
def parseOpt(): | |
if len(sys.argv) is 2: | |
return os.getcwd(), sys.argv[1]+'-1', sys.argv[1] | |
elif len(sys.argv) is 3: | |
return os.getcwd(), sys.argv[1], sys.argv[2] | |
elif len(sys.argv) is 4: | |
return sys.argv[1], sys.argv[2], sys.argv[3] | |
else: printUsageAndExit() | |
if __name__ == '__main__': | |
tool = getTool() | |
if not tool: | |
print "No GUI diff tools, install bcompare or meld" | |
sys.exit(0) | |
name, first, second = parseOpt() | |
commit1, commit2 = getCommitId(name, first), getCommitId(name, second) | |
if validate(name, commit1) and validate(name, commit2) is False: | |
sys.exit(0) | |
cleanup(commit1), cleanup(commit2) | |
try: | |
checkoutCommit(name, commit1), checkoutCommit(name, commit2) | |
compare(tool, commit1, commit2) | |
except KeyboardInterrupt: | |
pass | |
finally: | |
cleanup(commit1), cleanup(commit2) | |
sys.exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It is assumed 'meld' is installed:
local_git_dir$ bdiff.py . 15d3c2ec3d007a5f0a6387a4998dc6fbcd9d93f5 c182600f5ff2491964af59c32933efa73575949d
or
local_git_dir$ bdiff.py . HEAD c182600f5ff2491964af59c32933efa73575949d
or
$ bdiff.py local_git_dir HEAD c182600f5ff2491964af59c32933efa73575949d
The following will all error out (even after replacing "catch" with "except"):
$ bdiff.py local_git_dir 0 1
$ bdiff.py local_git_dir HEAD HEAD-1