| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/env 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, |
| 11 unzipping, and opening Chromium for you. After testing the specific revision, | 11 unzipping, and opening Chromium for you. After testing the specific revision, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 38 import re | 38 import re |
| 39 import shutil | 39 import shutil |
| 40 import subprocess | 40 import subprocess |
| 41 import sys | 41 import sys |
| 42 import tempfile | 42 import tempfile |
| 43 import threading | 43 import threading |
| 44 import urllib | 44 import urllib |
| 45 from xml.etree import ElementTree | 45 from xml.etree import ElementTree |
| 46 import zipfile | 46 import zipfile |
| 47 | 47 |
| 48 |
| 48 class PathContext(object): | 49 class PathContext(object): |
| 49 """A PathContext is used to carry the information used to construct URLs and | 50 """A PathContext is used to carry the information used to construct URLs and |
| 50 paths when dealing with the storage server and archives.""" | 51 paths when dealing with the storage server and archives.""" |
| 51 def __init__(self, platform, good_revision, bad_revision): | 52 def __init__(self, platform, good_revision, bad_revision): |
| 52 super(PathContext, self).__init__() | 53 super(PathContext, self).__init__() |
| 53 # Store off the input parameters. | 54 # Store off the input parameters. |
| 54 self.platform = platform # What's passed in to the '-a/--archive' option. | 55 self.platform = platform # What's passed in to the '-a/--archive' option. |
| 55 self.good_revision = good_revision | 56 self.good_revision = good_revision |
| 56 self.bad_revision = bad_revision | 57 self.bad_revision = bad_revision |
| 57 | 58 |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 (stdout, stderr) = subproc.communicate() | 261 (stdout, stderr) = subproc.communicate() |
| 261 | 262 |
| 262 os.chdir(cwd) | 263 os.chdir(cwd) |
| 263 try: | 264 try: |
| 264 shutil.rmtree(tempdir, True) | 265 shutil.rmtree(tempdir, True) |
| 265 except Exception, e: | 266 except Exception, e: |
| 266 pass | 267 pass |
| 267 | 268 |
| 268 return (subproc.returncode, stdout, stderr) | 269 return (subproc.returncode, stdout, stderr) |
| 269 | 270 |
| 271 |
| 270 def AskIsGoodBuild(rev, status, stdout, stderr): | 272 def AskIsGoodBuild(rev, status, stdout, stderr): |
| 271 """Ask the user whether build |rev| is good or bad.""" | 273 """Ask the user whether build |rev| is good or bad.""" |
| 272 # Loop until we get a response that we can parse. | 274 # Loop until we get a response that we can parse. |
| 273 while True: | 275 while True: |
| 274 response = raw_input('Revision %d is [(g)ood/(b)ad/(q)uit]: ' % int(rev)) | 276 response = raw_input('Revision %d is [(g)ood/(b)ad/(q)uit]: ' % int(rev)) |
| 275 if response and response in ('g', 'b'): | 277 if response and response in ('g', 'b'): |
| 276 return response == 'g' | 278 return response == 'g' |
| 277 if response and response == 'q': | 279 if response and response == 'q': |
| 278 raise SystemExit() | 280 raise SystemExit() |
| 279 | 281 |
| 282 |
| 280 def Bisect(platform, | 283 def Bisect(platform, |
| 281 good_rev=0, | 284 good_rev=0, |
| 282 bad_rev=0, | 285 bad_rev=0, |
| 283 try_args=(), | 286 try_args=(), |
| 284 profile=None, | 287 profile=None, |
| 285 predicate=AskIsGoodBuild): | 288 predicate=AskIsGoodBuild): |
| 286 """Given known good and known bad revisions, run a binary search on all | 289 """Given known good and known bad revisions, run a binary search on all |
| 287 archived revisions to determine the last known good revision. | 290 archived revisions to determine the last known good revision. |
| 288 | 291 |
| 289 @param platform Which build to download/run ('mac', 'win', 'linux64', etc.). | 292 @param platform Which build to download/run ('mac', 'win', 'linux64', etc.). |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 print('You are probably looking for build %d.' % first_known_bad_rev) | 530 print('You are probably looking for build %d.' % first_known_bad_rev) |
| 528 if last_known_good_webkit_rev != first_known_bad_webkit_rev: | 531 if last_known_good_webkit_rev != first_known_bad_webkit_rev: |
| 529 print 'WEBKIT CHANGELOG URL:' | 532 print 'WEBKIT CHANGELOG URL:' |
| 530 print WEBKIT_CHANGELOG_URL % (first_known_bad_webkit_rev, | 533 print WEBKIT_CHANGELOG_URL % (first_known_bad_webkit_rev, |
| 531 last_known_good_webkit_rev) | 534 last_known_good_webkit_rev) |
| 532 print 'CHANGELOG URL:' | 535 print 'CHANGELOG URL:' |
| 533 print CHANGELOG_URL % (last_known_good_rev, first_known_bad_rev) | 536 print CHANGELOG_URL % (last_known_good_rev, first_known_bad_rev) |
| 534 print 'Built at revision:' | 537 print 'Built at revision:' |
| 535 print BUILD_VIEWVC_URL % first_known_bad_rev | 538 print BUILD_VIEWVC_URL % first_known_bad_rev |
| 536 | 539 |
| 540 |
| 537 if __name__ == '__main__': | 541 if __name__ == '__main__': |
| 538 sys.exit(main()) | 542 sys.exit(main()) |
| OLD | NEW |