f37 -> f39
[infrastructure.git] / scripts / diff-rec.py
1 #!/usr/bin/python
2
3 import os, os.path
4 import subprocess
5 import re
6
7 from optparse import OptionParser
8
9 def report_stderr(stderrdata):
10     if stderrdata: 
11         print "STDERR BEG (%d chars)",len(stderrdata)
12         print stderrdata
13         print "STDERR END (%d chars)",len(stderrdata)
14
15 def git_update (dir):
16     os.chdir(dir)
17     print "git pull in %s"%dir
18     prog=subprocess.Popen(["git","pull"],stdout=subprocess.PIPE, stderr=subprocess.PIPE)
19     try:
20         (stdoutdata, stderrdata) = prog.communicate()
21     except KeyboardInterrupt:
22         raise Exception, "Interrupted by user"
23     prog.wait()
24     print stdoutdata,
25     report_stderr(stderrdata)
26
27
28 # this is ad hoc for sfa diffing ..
29 excludes=[ "*.git*", "*~" ]
30 excludes+= [ "*.pyc", "*.png", "*.pdf", "*.out" , "*.DS_Store", "*.lint" ]
31 excludes+= [ "listfiles.sh", "python.*" ]
32 excludes+= [ "*HEAD", "*txt" ]
33 excludes+= [ "*slab*", "senslab" ]
34
35 def run_diff(options):
36     dir1=options.left_dir
37     dir2=options.right_dir
38     command=["diff","-r",]
39     for exclude in excludes:
40         command += [ "-x", "%s"%exclude]
41     command += [dir1,dir2]
42     prog=subprocess.Popen(command,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
43     print "diffing -r %s %s"%(dir1,dir2)
44     try:
45         (stdoutdata, stderrdata) = prog.communicate()
46     except KeyboardInterrupt:
47         raise Exception, "Interrupted by user"
48     prog.wait()
49     report_stderr(stderrdata)
50
51     re_only_left =re.compile("^Only in %s[:/]"%dir1)
52     re_only_right=re.compile("^Only in %s[:/]"%dir2)
53     re_binary    =re.compile("^Binary files %s.* and %s.*"%(dir1,dir2))
54     re_start_diff=re.compile("diff -r.*%s/(?P<path>.*) %s/(?P=path)"%(dir1,dir2))
55
56     only_left=[]
57     only_right=[]
58     ignored=[]
59     
60     class Context:
61         def __init__ (self,diffs): 
62             self.current_path=''
63             self.current_diff=[]
64             self.diffs=diffs
65         def close_diff(self):
66             if self.current_path: self.diffs[self.current_path]=self.current_diff
67             elif self.current_diff: print """----------
68 WARNING, diff with no path %s
69 ----------"""%self.current_diff
70             self.current_path=''
71             self.current_diff=[]
72         def set_path (self,path):
73             self.current_path=path
74         def insert_line(self,line):
75             self.current_diff.append(line)
76
77     ### parse
78     diffs={}
79     context=Context(diffs)
80     for line in stdoutdata.split("\n"):
81         m=re_only_left.match(line)
82         if m: 
83             context.close_diff()
84             only_left.append(line)
85             continue
86         m=re_only_right.match(line)
87         if m: 
88             context.close_diff()
89             only_right.append(line)
90             continue
91         m=re_binary.match(line)
92         if m:
93             context.close_diff()
94             ignored.append(line)
95             continue
96         m=re_start_diff.match(line)
97         if m:
98             context.close_diff()
99             context.set_path(m.group('path'))
100             continue
101         context.insert_line(line)
102         
103     ### ignore some entries - maybe not needed if we're smart with diff
104         
105     # print report
106     print "< < < < < %d old files/dirs"%len(only_left)
107     for l in only_left:  print "< < < < < ",l
108     print "> > > > > %d new files/dirs"%len(only_right)
109     for l in only_right: print "> > > > > ",l
110     print "= = = = = %d files"%len(diffs)
111     for (path,contents) in diffs.iteritems():
112         if options.verbose:
113             print "= = = = =  Diffs in path %s"%path
114             for line in contents: print line
115         else:
116             print "Diffs in path %s (%d lines)"%(path,len(contents))
117             
118
119 left_default=os.path.expanduser("~/git/sfa")
120 right_default=os.path.expanduser("~/git/sfa-generic")
121
122 def main ():
123     parser=OptionParser()
124     parser.add_option("-g","--git",action='store_true',dest='git',default=False,
125                       help="run git pull before diffing")
126     parser.add_option("-l","--left",action='store',dest='left_dir',default=left_default,
127                       help="left dir, default=%s"%left_default)
128     parser.add_option("-r","--right",action='store',dest='right_dir',default=right_default,
129                       help="right dir, default=%s"%right_default)
130     parser.add_option("-v","--verbose",action='store_true',dest='verbose',default=False,
131                       help="Show actual diff contents")
132     (options,args)=parser.parse_args()
133     if options.git:
134         git_update(options.left_dir)
135         git_update(options.right_dir)
136     run_diff(options)
137
138 if __name__ == "__main__":
139     main()