Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Side by Side Diff: tools/bisect-builds.py

Issue 7468020: Update bisect-builds.py to automatically determine download server. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Snapshot Build Bisect Tool 6 """Snapshot Build Bisect Tool
7 7
8 This script bisects a snapshot archive using binary search. It starts at 8 This script bisects a snapshot archive using binary search. It starts at
9 a bad revision (it will try to guess HEAD) and asks for a last known-good 9 a bad revision (it will try to guess HEAD) and asks for a last known-good
10 revision. It will then binary search across this revision range by downloading, 10 revision. It will then binary search across this revision range by downloading,
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 def ParseDirectoryIndexRecent(context): 197 def ParseDirectoryIndexRecent(context):
198 """Parses the recent builds directory listing into a list of revision 198 """Parses the recent builds directory listing into a list of revision
199 numbers.""" 199 numbers."""
200 handle = urllib.urlopen(context.GetListingURLRecent()) 200 handle = urllib.urlopen(context.GetListingURLRecent())
201 document = handle.read() 201 document = handle.read()
202 202
203 # Looking for: <a href="92976/">92976/</a> 203 # Looking for: <a href="92976/">92976/</a>
204 return re.findall(r"<a href=\"(\d+)/\">\1/</a>", document) 204 return re.findall(r"<a href=\"(\d+)/\">\1/</a>", document)
205 205
206 206
207 def GetRevList(context): 207 def GetRevList(context, revlist):
208 """Gets the list of revision numbers between |good_revision| and 208 """Gets the list of revision numbers between |good_revision| and
209 |bad_revision| of the |context|.""" 209 |bad_revision| of the |context|."""
Nico 2011/07/21 16:17:31 Update docstring.
jbates 2011/07/21 17:36:01 Done.
210 # Download the revlist and filter for just the range between good and bad. 210 # Download the revlist and filter for just the range between good and bad.
211 rev_range = range(context.good_revision, context.bad_revision) 211 rev_range = range(context.good_revision, context.bad_revision)
212 revisions = []
213 if context.use_recent:
214 revisions = ParseDirectoryIndexRecent(context)
215 else:
216 revisions = ParseDirectoryIndex(context)
217 revlist = map(int, revisions)
218 revlist = filter(lambda r: r in rev_range, revlist) 212 revlist = filter(lambda r: r in rev_range, revlist)
219 revlist.sort() 213 revlist.sort()
220 return revlist 214 return revlist
221 215
222 216
223 def TryRevision(context, rev, profile, args): 217 def TryRevision(context, rev, profile, args):
224 """Downloads revision |rev|, unzips it, and opens it for the user to test. 218 """Downloads revision |rev|, unzips it, and opens it for the user to test.
225 |profile| is the profile to use.""" 219 |profile| is the profile to use."""
226 # Do this in a temp dir so we don't collide with user files. 220 # Do this in a temp dir so we don't collide with user files.
227 cwd = os.getcwd() 221 cwd = os.getcwd()
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 choices = choices, 332 choices = choices,
339 help = 'The buildbot archive to bisect [%s].' % 333 help = 'The buildbot archive to bisect [%s].' %
340 '|'.join(choices)) 334 '|'.join(choices))
341 parser.add_option('-b', '--bad', type = 'int', 335 parser.add_option('-b', '--bad', type = 'int',
342 help = 'The bad revision to bisect to.') 336 help = 'The bad revision to bisect to.')
343 parser.add_option('-g', '--good', type = 'int', 337 parser.add_option('-g', '--good', type = 'int',
344 help = 'The last known good revision to bisect from.') 338 help = 'The last known good revision to bisect from.')
345 parser.add_option('-p', '--profile', '--user-data-dir', type = 'str', 339 parser.add_option('-p', '--profile', '--user-data-dir', type = 'str',
346 help = 'Profile to use; this will not reset every run. ' + 340 help = 'Profile to use; this will not reset every run. ' +
347 'Defaults to a clean profile.', default = 'profile') 341 'Defaults to a clean profile.', default = 'profile')
348 parser.add_option('-r', '--recent',
349 dest = "recent",
350 default = False,
351 action = "store_true",
352 help = 'Use recent builds from about the last 2 months ' +
353 'for higher granularity bisecting.')
354 (opts, args) = parser.parse_args() 342 (opts, args) = parser.parse_args()
355 343
356 if opts.archive is None: 344 if opts.archive is None:
357 print 'Error: missing required parameter: --archive' 345 print 'Error: missing required parameter: --archive'
358 print 346 print
359 parser.print_help() 347 parser.print_help()
360 return 1 348 return 1
361 349
362 if opts.bad and opts.good and (opts.good > opts.bad): 350 if opts.bad and opts.good and (opts.good > opts.bad):
363 print ('The good revision (%d) must precede the bad revision (%d).\n' % 351 print ('The good revision (%d) must precede the bad revision (%d).\n' %
364 (opts.good, opts.bad)) 352 (opts.good, opts.bad))
365 parser.print_help() 353 parser.print_help()
366 return 1 354 return 1
367 355
368 # Create the context. Initialize 0 for the revisions as they are set below. 356 # Create the context. Initialize 0 for the revisions as they are set below.
369 context = PathContext(opts.archive, 0, 0, opts.recent) 357 context = PathContext(opts.archive, 0, 0, False)
Nico 2011/07/21 16:17:31 Name parameter (|..., use_recent=False)|) – more r
jbates 2011/07/21 17:36:01 Done.
370 358
371 # Pick a starting point, try to get HEAD for this. 359 # Pick a starting point, try to get HEAD for this.
372 if opts.bad: 360 if opts.bad:
373 bad_rev = opts.bad 361 bad_rev = opts.bad
374 else: 362 else:
375 bad_rev = 0 363 bad_rev = 0
376 try: 364 try:
377 # Location of the latest build revision number 365 # Location of the latest build revision number
378 nh = urllib.urlopen(context.GetLastChangeURL()) 366 nh = urllib.urlopen(context.GetLastChangeURL())
379 latest = int(nh.read()) 367 latest = int(nh.read())
(...skipping 13 matching lines...) Expand all
393 good_rev = 0 381 good_rev = 0
394 try: 382 try:
395 good_rev = int(raw_input('Last known good [0]: ')) 383 good_rev = int(raw_input('Last known good [0]: '))
396 except Exception, e: 384 except Exception, e:
397 pass 385 pass
398 386
399 # Set the input parameters now that they've been validated. 387 # Set the input parameters now that they've been validated.
400 context.good_revision = good_rev 388 context.good_revision = good_rev
401 context.bad_revision = bad_rev 389 context.bad_revision = bad_rev
402 390
391 # Get recent revision list and check whether it's sufficient.
392 all_revs_recent = map(int, ParseDirectoryIndexRecent(context))
393 all_revs_recent.sort()
Nico 2011/07/21 16:17:31 I think you want all_revs_recent = all_revs_re
jbates 2011/07/21 17:36:01 Done.
394 # Skipping 0 since it might be deleted off the server soon:
395 oldest_recent_rev = all_revs_recent[1]
Nico 2011/07/21 16:17:31 and then use [0] here
jbates 2011/07/21 17:36:01 Done.
396 if good_rev >= oldest_recent_rev:
397 # The range is within recent builds, so switch on use_recent.
398 context.use_recent = True
399 elif bad_rev >= oldest_recent_rev:
400 # The range spans both old and recent builds.
401 # If oldest_recent_rev is good, we bisect the recent builds.
402 context.use_recent = True # set True to test recent build
Nico 2011/07/21 16:17:31 Remove comment
jbates 2011/07/21 17:36:01 Done.
403 TryRevision(context, oldest_recent_rev, opts.profile, args)
404 if AskIsGoodBuild(oldest_recent_rev):
405 # context.use_recent is True
406 context.good_revision = oldest_recent_rev
407 else:
408 context.use_recent = False
409 context.bad_revision = oldest_recent_rev
410
411 all_revs = []
412 if context.use_recent:
413 all_revs = all_revs_recent
Nico 2011/07/21 16:17:31 This includes 0 -- probably not intentional? (henc
jbates 2011/07/21 17:36:01 0 would be filtered out before bisecting, but I li
414 else:
415 all_revs = map(int, ParseDirectoryIndex(context))
416
403 # Get a list of revisions to bisect across. 417 # Get a list of revisions to bisect across.
404 revlist = GetRevList(context) 418 revlist = GetRevList(context, all_revs)
405 if len(revlist) < 2: # Don't have enough builds to bisect 419 if len(revlist) < 2: # Don't have enough builds to bisect
406 print 'We don\'t have enough builds to bisect. revlist: %s' % revlist 420 print 'We don\'t have enough builds to bisect. revlist: %s' % revlist
407 sys.exit(1) 421 sys.exit(1)
408 422
409 (last_known_good_rev, first_known_bad_rev) = Bisect( 423 (last_known_good_rev, first_known_bad_rev) = Bisect(
410 revlist, context, args, opts.profile) 424 revlist, context, args, opts.profile)
411 425
412 # We're done. Let the user know the results in an official manner. 426 # We're done. Let the user know the results in an official manner.
413 print('You are probably looking for build %d.' % first_known_bad_rev) 427 print('You are probably looking for build %d.' % first_known_bad_rev)
414 print('CHANGELOG URL:') 428 print('CHANGELOG URL:')
415 print(CHANGELOG_URL % (last_known_good_rev, first_known_bad_rev)) 429 print(CHANGELOG_URL % (last_known_good_rev, first_known_bad_rev))
416 print('Built at revision:') 430 print('Built at revision:')
417 print(BUILD_VIEWVC_URL % first_known_bad_rev) 431 print(BUILD_VIEWVC_URL % first_known_bad_rev)
418 432
419 if __name__ == '__main__': 433 if __name__ == '__main__':
420 sys.exit(main()) 434 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698