Skip to content

Instantly share code, notes, and snippets.

@debedb
Created January 13, 2020 23:01
Embed
What would you like to do?
JAR diff
import argparse
import os
import sets
import subprocess
import sys
import tempfile
"""
Assumes procyon:
https://bitbucket.org/mstrobel/procyon/downloads/
Sample usage:
python jardiff.py --procyon ~/gg/procyon-decompiler-0.5.36.jar ~/gg/fe ~/gg/bf
"""
args = None
def main():
global args
parser = argparse.ArgumentParser()
parser.add_argument("--procyon", help="location of procyon JAR")
parser.add_argument("first")
parser.add_argument("second")
args = parser.parse_args()
if os.path.isdir(args.first):
dir1 = args.first
else:
if not(args.first.endswith(".jar")):
print "Expected either a JAR or dir as first argument"
sys.exit(1)
raise Exceptino("TODO unjar")
if os.path.isdir(args.second):
dir2 = args.second
else:
if not(args.second.endswith(".jar")):
print "Expected either a JAR or dir as first argument"
sys.exit(1)
raise Exceptino("TODO unjar")
compare_dirs(dir1, dir2)
def walker(files, dirname, fnames):
for fname in fnames:
abs_fname = os.path.join(dirname, fname)
if os.path.isdir(abs_fname):
os.path.walk(abs_fname, walker, files)
else:
files.append(abs_fname)
def get_all_files(dir):
print "Getting files from %s" % dir
files = []
os.path.walk(dir, walker, files)
# Make them relative
files = [f[len(dir)+1:] for f in files]
return files
def compare_dirs(dir1, dir2):
print "Comparing %s vs %s" % (dir1, dir2)
files1 = get_all_files(dir1)
files2 = get_all_files(dir2)
in2only = sets.Set(files2) - sets.Set(files1)
if in2only:
print "Files in %s but not in %s" % (dir2, dir1)
print "\n\t".join(list(in2only))
print
for f in files1:
if f not in files2:
print "%s not in %s" % (f, dir2)
continue
f1 = os.path.join(dir1, f)
f2 = os.path.join(dir2, f)
# TODO really this should check checksum, not size
s1 = os.stat(f1).st_size
s2 = os.stat(f2).st_size
if s1 != s2:
print "Different: %s (%s vs %s)" % (f, s1, s2)
if f.endswith(".class"):
f1java = tempfile.NamedTemporaryFile(suffix='.java', delete=False)
f1java.write("")
f1java.close()
cmd = "java -jar %s %s > %s" % (args.procyon, f1, f1java.name)
# print cmd
subprocess.check_call(cmd, shell=True)
f2java = tempfile.NamedTemporaryFile(suffix='.java', delete=False)
f2java.write("")
f2java.close()
cmd = "java -jar %s %s > %s" % (args.procyon, f2, f2java.name)
# print cmd
subprocess.check_call(cmd, shell=True)
diff_cmd = ["diff","-Z",f1java.name, f2java.name]
print "Executing %s" % " ".join(diff_cmd)
try:
subprocess.check_output(diff_cmd)
except subprocess.CalledProcessError, cpe:
if cpe.returncode == 1:
# diff will return 1 if files are different
diff = cpe.output
print diff
else:
# we already know it will not return 0 because they are different
# so it can only be 2 - trouble
raise
os.unlink(f1java.name)
os.unlink(f2java.name)
else:
print "\tDo not know how to diff"
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment