]> git.lyx.org Git - lyx.git/blob - development/keystest/cache-bisect.py
Adding binary path for Homebrew on MacOS-arm64 (bug 12619).
[lyx.git] / development / keystest / cache-bisect.py
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 import os
5 from subprocess import call, check_call
6 from random import randrange
7 import getpass
8
9
10 outfilename = "/tmp/cache-bisect." + getpass.getuser() + ".log"
11 outfile = open(outfilename, 'w')
12 print 'BBBISECT_BEGIN'
13 #print >> outfile, 'BBBISECT_BEGIN'
14 #print >> outfile, 'BBBISECT_BEGIN'
15 #print >> outfile, 'BBBISECT_BEGIN'
16 #print >> outfile, 'BBBISECT_BEGIN'
17 #print >> outfile, 'BBBISECT_BEGIN'
18 #print 'BBBISECT_BEGIN'
19
20 source_dir = '/mnt/big/xp/src/lyx-1.6.x-bisect'  # must NOT end in a slash
21 cache_dir = source_dir + '.cache/'  # must end in a slash
22 source_dir = '/mnt/big/xp/src/lyx-1.6.x-bisect2'  # must NOT end in a slash
23
24 #make_cmd = 'autoconf && ./configure && cd src && echo __________ `pwd` && sleep 9 && make'
25 make_cmd = 'rm -rf autom4te.cache && autoconf && ./configure && cd src && make'
26
27 reverse_search = True
28 reverse_search = False
29 must_make = True  # If we fail to make the file, we could this a "bad" rather than "canot test"
30 must_make = False
31
32 # ToDo:
33 # replace .tmp with .partial_copy and .not_yet_made
34
35
36 def set_revision(new_v, tmp_d):
37     #check_call(['svn', 'up', '-r' + new_v, '--force'], cwd=tmp_d)
38     os.system ('cd "'+tmp_d+'" && yes tf | svn up -r'+new_v+'--force')
39
40 def cmp_version(x, y):
41     return cmp(int(x), int(y))
42
43
44 def get_cached_versions():
45     vers = [f for f in os.listdir(cache_dir) if not f.count('.')]
46     vers.sort(cmp_version)
47     return vers
48
49
50 def version_in_range(v, lo, hi):
51     if cmp_version(v, lo) < 0:
52         return False
53     elif cmp_version(v, hi) > 0:
54         return False
55     return True
56
57 def killall_p (s):
58     # Unlike killall, this searchs within command parameters, as well as the
59     # command name
60
61         #os.system("kPID=`ps a | grep '"+s+"' | grep -v grep | sed 's/^ *//g'|  sed 's/ .*$//'`
62     os.system("(kPID=`ps a | grep '"+s+
63     "' | grep -v grep | sed 's/^ *//g'|  sed 's/ .*$//'`\n\
64         echo kPID $kPID "+s+"\n\
65         echo kill $kPID\n\
66         kill $kPID\n\
67         sleep 0.1\n\
68         echo kill -9 $kPID\n\
69         kill -9 $kPID) 2> /dev/null")
70
71 def clean_up ():
72     killall_p("autolyx")
73     killall_p("lyx")
74     killall_p("keytest.py")
75     killall_p("xclip")
76
77 def filter_versions(vers, lo, hi):
78     return [v for v in vers if cmp]
79
80
81 def ver2dir(v):
82     return cache_dir + v
83
84
85 def make_ver(new_v, old_v=None, alt_v=None):
86     print 'MAKING', new_v, old_v, alt_v
87     new_d = ver2dir(new_v)
88     if old_v is None:
89         old_d = source_dir
90     else:
91         old_d = ver2dir(old_v)
92     fail_d = new_d + '.fail'
93     tmp_d = new_d + '.tmp'
94     if os.path.exists(cache_dir + fail_d):
95         return 1
96     if os.path.exists(new_d):
97         return 0
98     if not os.path.exists(tmp_d):
99         if not os.path.exists(old_d):
100             old_d = old_d + '.tmp'
101         call(['rm', '-rf', tmp_d + '.cp'])
102         call(['cp', '-rvu', old_d, tmp_d + '.cp'])
103         check_call(['mv', tmp_d + '.cp', tmp_d])
104         set_revision(new_v, tmp_d)
105     call('pwd && sleep 5 && echo ' + make_cmd, cwd=tmp_d, shell=True)
106     result = call(make_cmd, cwd=tmp_d, shell=True)
107     if result == 0:
108         print 'Make successful'
109         check_call(['mv', tmp_d, new_d])
110     return result
111
112
113 def change_after(cmd, v):
114     result = run_cmd(cmd, v)
115     ca = result_after(result)
116     print >> outfile, 'BISECT_change_after', v, ca
117     print 'BISECT_change_after', v, ca
118     return ca
119
120
121 def change_before(cmd, v):
122     result = run_cmd(cmd, v)
123     cb = result_before(result)
124     print >> outfile, 'BISECT_change_before', v, cb
125     print 'BISECT_change_before', v, cb
126     return cb
127
128
129 def result_after(i):
130     if reverse_search:
131         return result_bad(i)
132     else:
133         return result_good(i)
134
135
136 def result_before(i):
137     if reverse_search:
138         return result_good(i)
139     else:
140         return result_bad(i)
141
142
143 def result_good(i):
144     return i == 0
145
146
147 def result_bad(i):
148     return not result_ugly(i) and not result_good(i)
149
150
151 def result_ugly(i):
152     return i == 125  # Like git, we treat 125 as "We cannot test this version"
153
154
155 def run_cmd(cmd, v):
156     #result = call('pwd ; echo SS ' + cmd, shell=True, cwd=ver2dir(v))
157     print "CMD", cmd
158     print "V2D", ver2dir(v)
159     os
160     #result = subprocess.call(cmd, shell=True, cwd=ver2dir(v))
161     result = call(cmd, cwd=ver2dir(v))
162     clean_up()
163     print cmd, result
164     return result
165
166
167 def do_bisect(cmd, vers, build):
168     lo = 0
169     hi = len(vers) - 1
170     m = (lo + hi) / 2
171
172     print lo, hi, m
173     print vers[lo], vers[hi], vers[m]
174     print vers
175
176     print >> outfile, 'VERS', final_vers
177
178     while len(vers) > 2:
179         print 'i', lo, hi, m, cmd
180         print 'v', vers[lo], vers[hi], vers[m], cmd
181         print vers
182
183         print '#ugly = Nonese'
184
185         if build or must_make:
186             ugly = False
187             result = make_ver(vers[m], vers[lo], vers[hi])
188             print 'AMKE RESULT', result
189             if not must_make:
190                 if result > 0 and not must_make:
191                     ugly = True  # Not good, or bad, just ugly.
192                 else:
193                     result = run_cmd(cmd, vers[m])
194         if not ugly:
195             if result > 127:
196                 os._exit(1)
197             ugly = result_ugly(result)
198         if ugly:
199             print vers[m] + ' is UGLY'
200             del vers[m]
201             hi = len(vers) - 1
202             m = randrange(0, len(vers))
203         else:
204             if result_after(result):
205                 print vers[m] + ' is AFTER'
206                 del vers[lo:m]
207             else:
208                 print vers[m] + ' is BEFORE'
209                 del vers[m + 1:hi + 1]
210             hi = len(vers) - 1
211             m = (lo + hi) / 2
212
213         print 'VERS REMAINING:', vers
214
215     return vers
216
217
218 def check_bisect(cmd, vers):
219     lo = 0
220     hi = len(vers) - 1
221     l = vers[lo]
222     h = vers[hi]
223     if make_ver(l):
224         return False
225     if make_ver(h):
226         return False
227     if change_before(cmd, l):
228         print 'Cannot bisect, change before ' + l\
229              + ' or regression test invalid'
230         return False
231     if change_after(cmd, h):
232         print 'Cannot bisect, change after ' + h\
233              + ' or regression test invalid'
234         return False
235     return True
236
237
238 def do_check_bisect(cmd, vers, build):
239     print vers
240     if check_bisect(cmd, vers):
241         return do_bisect(cmd, vers, build)
242     else:
243         return
244
245
246 def open_and_readlines(fname):
247     f = open(fname, 'r')
248     lines = f.readlines()
249     for i in range(0, len(lines)):
250         lines[i] = lines[i].rstrip('\n')
251     return lines
252
253
254 def get_versions_between(l, h):
255     vers = [f for f in open_and_readlines('all_versions')
256             if version_in_range(f, l, h)]
257     vers.sort(cmp_version)
258     return vers
259
260
261 def get_cached_versions_between(l, h):
262     vers = [f for f in get_cached_versions() if version_in_range(f, l, h)]
263     vers.sort(cmp_version)
264     print 'BTWN', l, h, vers
265     return vers
266
267
268 def two_level_bisect(cmd, LO, HI):
269     if make_ver(LO):
270         return False
271     if make_ver(HI):
272         return False
273     vers = get_cached_versions_between(LO, HI)
274     print 'CACHED_VERSIONS', vers
275     vers = do_check_bisect(cmd, vers, False)
276     print 'Closest Cached Versions', vers
277     if vers is None:
278         return
279     if len(vers) != 2:
280         return
281     vers = get_versions_between(vers[0], vers[1])
282     print 'BETWEEN VERSIONS', vers
283     vers = do_check_bisect(cmd, vers, True)
284
285
286 def multisect(cmd, vers):
287     i = 1
288     while i < len(vers):
289         print >> outfile, 'MULTISECT', vers[i]
290         print 'MULTISECT', vers[i]
291         if not ( make_ver(vers[i], vers[i-1])==0 and change_after(cmd, vers[i]) ) :
292             i = i + 1
293         else:
294             return two_level_bisect(cmd, vers[i], vers[0])
295
296
297 print 'BISECT_BEGIN'
298 print >> outfile, 'BISECT_BEGIN'
299 outfile.flush()
300 #final_vers = multisect('$TEST_COMMAND', ['30614', '27418', '23000'])
301 cmd = os.sys.argv
302 del cmd[0]
303
304 VERS = os.environ.get('MULTISECT_VERS')
305 if VERS is None:
306     VERS = ['30614', '27418', '23000']
307 else:
308     VERS = VERS.split()
309
310 final_vers = multisect(cmd, VERS)
311 #final_vers = two_level_bisect('true', "21107","23000")
312 #final_vers = do_bisect('true', get_versions_between("21107","23000"),True)
313 outfile.flush()
314 print
315 print >> outfile, 'BISECT_FINAL', final_vers
316 print 'BISECT_FINAL', final_vers
317 os.system('echo BISECT_BEGIN >> /tmp/adsfadsf.log')
318 os.system('echo BISECT_FINAL >> /tmp/adsfadsf.log')
319
320 clean_up()
321 os._exit(0)