Skip to content

Instantly share code, notes, and snippets.

@rcpao-enmotus
Forked from jacobabrahamb4/bdiff.py
Last active October 9, 2019 20:54
Show Gist options
  • Save rcpao-enmotus/51d8e586c1edf9b3563dd67336e77449 to your computer and use it in GitHub Desktop.
Save rcpao-enmotus/51d8e586c1edf9b3563dd67336e77449 to your computer and use it in GitHub Desktop.
Display diff between two commits.
#!/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)
@rcpao-enmotus
Copy link
Author

rcpao-enmotus commented Oct 9, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment