From: Thierry Parmentelat Date: Tue, 25 Oct 2011 08:59:33 +0000 (+0200) Subject: utility to examine recursive differences X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=3d7b652e8f350204eee9737d1b380069f1d6252f;p=infrastructure.git utility to examine recursive differences --- diff --git a/scripts/diff-rec.py b/scripts/diff-rec.py new file mode 100755 index 0000000..089ee5f --- /dev/null +++ b/scripts/diff-rec.py @@ -0,0 +1,135 @@ +#!/usr/bin/python + +import os, os.path +import subprocess +import re + +from optparse import OptionParser + +def report_stderr(stderrdata): + if stderrdata: + print "STDERR BEG (%d chars)",len(stderrdata) + print stderrdata + print "STDERR END (%d chars)",len(stderrdata) + +def git_update (dir): + os.chdir(dir) + print "git pull in %s"%dir + prog=subprocess.Popen(["git","pull"],stdout=subprocess.PIPE, stderr=subprocess.PIPE) + try: + (stdoutdata, stderrdata) = prog.communicate() + except KeyboardInterrupt: + raise Exception, "Interrupted by user" + prog.wait() + print stdoutdata, + report_stderr(stderrdata) + + +excludes=[ "*.git*", "*~" ] +excludes+= [ "*.pyc", "*.png", "*.pdf", "*.out" , "*.DS_Store", "*.lint" ] +excludes+= [ "listfiles.sh", "python.*" ] +def run_diff(options): + dir1=options.left_dir + dir2=options.right_dir + command=["diff","-r",] + for exclude in excludes: + command += [ "-x", "%s"%exclude] + command += [dir1,dir2] + prog=subprocess.Popen(command,stdout=subprocess.PIPE, stderr=subprocess.PIPE) + print "diffing -r %s %s"%(dir1,dir2) + try: + (stdoutdata, stderrdata) = prog.communicate() + except KeyboardInterrupt: + raise Exception, "Interrupted by user" + prog.wait() + report_stderr(stderrdata) + + re_only_left =re.compile("^Only in %s[:/]"%dir1) + re_only_right=re.compile("^Only in %s[:/]"%dir2) + re_binary =re.compile("^Binary files %s.* and %s.*"%(dir1,dir2)) + re_start_diff=re.compile("diff -r.*%s/(?P.*) %s/(?P=path)"%(dir1,dir2)) + + only_left=[] + only_right=[] + ignored=[] + + class Context: + def __init__ (self,diffs): + self.current_path='' + self.current_diff=[] + self.diffs=diffs + def close_diff(self): + if self.current_path: self.diffs[self.current_path]=self.current_diff + elif self.current_diff: print """---------- +WARNING, diff with no path %s +----------"""%self.current_diff + self.current_path='' + self.current_diff=[] + def set_path (self,path): + self.current_path=path + def insert_line(self,line): + self.current_diff.append(line) + + ### parse + diffs={} + context=Context(diffs) + for line in stdoutdata.split("\n"): + m=re_only_left.match(line) + if m: + context.close_diff() + only_left.append(line) + continue + m=re_only_right.match(line) + if m: + context.close_diff() + only_right.append(line) + continue + m=re_binary.match(line) + if m: + context.close_diff() + ignored.append(line) + continue + m=re_start_diff.match(line) + if m: + context.close_diff() + context.set_path(m.group('path')) + continue + context.insert_line(line) + + ### ignore some entries - maybe not needed if we're smart with diff + + # print report + print "< < < < < %d old files/dirs"%len(only_left) + for l in only_left: print "< < < < < ",l + print "> > > > > %d new files/dirs"%len(only_right) + for l in only_right: print "> > > > > ",l + print "= = = = = %d files"%len(diffs) + for (path,contents) in diffs.iteritems(): + if options.verbose: + print "= = = = = Diffs in path %s"%path + for line in contents: print line + else: + print "Diffs in path %s (%d lines)"%(path,len(contents)) + + +left_default=os.path.expanduser("~/git/sfa") +right_default=os.path.expanduser("~/git/sfa-generic") + +def main (): + parser=OptionParser() + parser.add_option("-g","--git",action='store_true',dest='git',default=False, + help="run git pull before diffing") + parser.add_option("-l","--left",action='store',dest='left_dir',default=left_default, + help="left dir, default=%s"%left_default) + parser.add_option("-r","--right",action='store',dest='right_dir',default=right_default, + help="right dir, default=%s"%right_default) + parser.add_option("-v","--verbose",action='store_true',dest='verbose',default=False, + help="Show actual diff contents") + (options,args)=parser.parse_args() + if options.git: + git_update(options.left_dir) + git_update(options.right_dir) + run_diff(options) + +if __name__ == "__main__": + main()