 Chromium Code Reviews
 Chromium Code Reviews Issue 28313002:
  Add Flash binary path option to bisect script.  (Closed) 
  Base URL: https://src.chromium.org/chrome/trunk/src/
    
  
    Issue 28313002:
  Add Flash binary path option to bisect script.  (Closed) 
  Base URL: https://src.chromium.org/chrome/trunk/src/| OLD | NEW | 
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python | 
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 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 11 matching lines...) Expand all Loading... | |
| 22 # Changelogs URL. | 22 # Changelogs URL. | 
| 23 CHANGELOG_URL = 'http://build.chromium.org/f/chromium/' \ | 23 CHANGELOG_URL = 'http://build.chromium.org/f/chromium/' \ | 
| 24 'perf/dashboard/ui/changelog.html?' \ | 24 'perf/dashboard/ui/changelog.html?' \ | 
| 25 'url=/trunk/src&range=%d%%3A%d' | 25 'url=/trunk/src&range=%d%%3A%d' | 
| 26 | 26 | 
| 27 # Official Changelogs URL. | 27 # Official Changelogs URL. | 
| 28 OFFICIAL_CHANGELOG_URL = 'http://omahaproxy.appspot.com/'\ | 28 OFFICIAL_CHANGELOG_URL = 'http://omahaproxy.appspot.com/'\ | 
| 29 'changelog?old_version=%s&new_version=%s' | 29 'changelog?old_version=%s&new_version=%s' | 
| 30 | 30 | 
| 31 # DEPS file URL. | 31 # DEPS file URL. | 
| 32 DEPS_FILE= 'http://src.chromium.org/viewvc/chrome/trunk/src/DEPS?revision=%d' | 32 DEPS_FILE = 'http://src.chromium.org/viewvc/chrome/trunk/src/DEPS?revision=%d' | 
| 33 # Blink Changelogs URL. | 33 # Blink Changelogs URL. | 
| 34 BLINK_CHANGELOG_URL = 'http://build.chromium.org/f/chromium/' \ | 34 BLINK_CHANGELOG_URL = 'http://build.chromium.org/f/chromium/' \ | 
| 35 'perf/dashboard/ui/changelog_blink.html?' \ | 35 'perf/dashboard/ui/changelog_blink.html?' \ | 
| 36 'url=/trunk&range=%d%%3A%d' | 36 'url=/trunk&range=%d%%3A%d' | 
| 37 | 37 | 
| 38 DONE_MESSAGE_GOOD_MIN = 'You are probably looking for a change made after %s ' \ | 38 DONE_MESSAGE_GOOD_MIN = 'You are probably looking for a change made after %s ' \ | 
| 39 '(known good), but no later than %s (first known bad).' | 39 '(known good), but no later than %s (first known bad).' | 
| 40 DONE_MESSAGE_GOOD_MAX = 'You are probably looking for a change made after %s ' \ | 40 DONE_MESSAGE_GOOD_MAX = 'You are probably looking for a change made after %s ' \ | 
| 41 '(known bad), but no later than %s (first known good).' | 41 '(known bad), but no later than %s (first known good).' | 
| 42 | 42 | 
| 43 ############################################################################### | 43 ############################################################################### | 
| 44 | 44 | 
| 45 import json | 45 import json | 
| 46 import math | |
| 47 import optparse | 46 import optparse | 
| 48 import os | 47 import os | 
| 49 import pipes | |
| 50 import re | 48 import re | 
| 51 import shlex | 49 import shlex | 
| 52 import shutil | 50 import shutil | 
| 53 import subprocess | 51 import subprocess | 
| 54 import sys | 52 import sys | 
| 55 import tempfile | 53 import tempfile | 
| 56 import threading | 54 import threading | 
| 57 import urllib | 55 import urllib | 
| 58 from distutils.version import LooseVersion | 56 from distutils.version import LooseVersion | 
| 59 from xml.etree import ElementTree | 57 from xml.etree import ElementTree | 
| 60 import zipfile | 58 import zipfile | 
| 61 | 59 | 
| 62 | 60 | 
| 63 class PathContext(object): | 61 class PathContext(object): | 
| 64 """A PathContext is used to carry the information used to construct URLs and | 62 """A PathContext is used to carry the information used to construct URLs and | 
| 65 paths when dealing with the storage server and archives.""" | 63 paths when dealing with the storage server and archives.""" | 
| 66 def __init__(self, base_url, platform, good_revision, bad_revision, | 64 def __init__(self, base_url, platform, good_revision, bad_revision, | 
| 67 is_official, is_aura): | 65 is_official, is_aura, flash_path = None): | 
| 68 super(PathContext, self).__init__() | 66 super(PathContext, self).__init__() | 
| 69 # Store off the input parameters. | 67 # Store off the input parameters. | 
| 70 self.base_url = base_url | 68 self.base_url = base_url | 
| 71 self.platform = platform # What's passed in to the '-a/--archive' option. | 69 self.platform = platform # What's passed in to the '-a/--archive' option. | 
| 72 self.good_revision = good_revision | 70 self.good_revision = good_revision | 
| 73 self.bad_revision = bad_revision | 71 self.bad_revision = bad_revision | 
| 74 self.is_official = is_official | 72 self.is_official = is_official | 
| 75 self.is_aura = is_aura | 73 self.is_aura = is_aura | 
| 74 self.flash_path = flash_path | |
| 76 | 75 | 
| 77 # The name of the ZIP file in a revision directory on the server. | 76 # The name of the ZIP file in a revision directory on the server. | 
| 78 self.archive_name = None | 77 self.archive_name = None | 
| 79 | 78 | 
| 80 # Set some internal members: | 79 # Set some internal members: | 
| 81 # _listing_platform_dir = Directory that holds revisions. Ends with a '/'. | 80 # _listing_platform_dir = Directory that holds revisions. Ends with a '/'. | 
| 82 # _archive_extract_dir = Uncompressed directory in the archive_name file. | 81 # _archive_extract_dir = Uncompressed directory in the archive_name file. | 
| 83 # _binary_name = The name of the executable to run. | 82 # _binary_name = The name of the executable to run. | 
| 84 if self.platform in ('linux', 'linux64', 'linux-arm'): | 83 if self.platform in ('linux', 'linux64', 'linux-arm'): | 
| 85 self._binary_name = 'chrome' | 84 self._binary_name = 'chrome' | 
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 # If we are bisecting only official builds (without --aura), | 279 # If we are bisecting only official builds (without --aura), | 
| 281 # we can not include builds which ends with '.1' or '.2' since | 280 # we can not include builds which ends with '.1' or '.2' since | 
| 282 # they have different folder hierarchy inside. | 281 # they have different folder hierarchy inside. | 
| 283 elif (not self.IsAuraBuild(str(build_number)) and | 282 elif (not self.IsAuraBuild(str(build_number)) and | 
| 284 not self.IsASANBuild(str(build_number))): | 283 not self.IsASANBuild(str(build_number))): | 
| 285 final_list.append(str(build_number)) | 284 final_list.append(str(build_number)) | 
| 286 except urllib.HTTPError, e: | 285 except urllib.HTTPError, e: | 
| 287 pass | 286 pass | 
| 288 return final_list | 287 return final_list | 
| 289 | 288 | 
| 290 def UnzipFilenameToDir(filename, dir): | 289 def UnzipFilenameToDir(filename, directory): | 
| 291 """Unzip |filename| to directory |dir|.""" | 290 """Unzip |filename| to |directory|.""" | 
| 292 cwd = os.getcwd() | 291 cwd = os.getcwd() | 
| 293 if not os.path.isabs(filename): | 292 if not os.path.isabs(filename): | 
| 294 filename = os.path.join(cwd, filename) | 293 filename = os.path.join(cwd, filename) | 
| 295 zf = zipfile.ZipFile(filename) | 294 zf = zipfile.ZipFile(filename) | 
| 296 # Make base. | 295 # Make base. | 
| 297 if not os.path.isdir(dir): | 296 if not os.path.isdir(directory): | 
| 298 os.mkdir(dir) | 297 os.mkdir(directory) | 
| 299 os.chdir(dir) | 298 os.chdir(directory) | 
| 300 # Extract files. | 299 # Extract files. | 
| 301 for info in zf.infolist(): | 300 for info in zf.infolist(): | 
| 302 name = info.filename | 301 name = info.filename | 
| 303 if name.endswith('/'): # dir | 302 if name.endswith('/'): # dir | 
| 304 if not os.path.isdir(name): | 303 if not os.path.isdir(name): | 
| 305 os.makedirs(name) | 304 os.makedirs(name) | 
| 306 else: # file | 305 else: # file | 
| 307 dir = os.path.dirname(name) | 306 directory = os.path.dirname(name) | 
| 308 if not os.path.isdir(dir): | 307 if not os.path.isdir(directory): | 
| 309 os.makedirs(dir) | 308 os.makedirs(directory) | 
| 310 out = open(name, 'wb') | 309 out = open(name, 'wb') | 
| 311 out.write(zf.read(name)) | 310 out.write(zf.read(name)) | 
| 312 out.close() | 311 out.close() | 
| 313 # Set permissions. Permission info in external_attr is shifted 16 bits. | 312 # Set permissions. Permission info in external_attr is shifted 16 bits. | 
| 314 os.chmod(name, info.external_attr >> 16L) | 313 os.chmod(name, info.external_attr >> 16L) | 
| 315 os.chdir(cwd) | 314 os.chdir(cwd) | 
| 316 | 315 | 
| 317 | 316 | 
| 318 def FetchRevision(context, rev, filename, quit_event=None, progress_event=None): | 317 def FetchRevision(context, rev, filename, quit_event=None, progress_event=None): | 
| 319 """Downloads and unzips revision |rev|. | 318 """Downloads and unzips revision |rev|. | 
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 355 print "Trying revision %s..." % str(revision) | 354 print "Trying revision %s..." % str(revision) | 
| 356 | 355 | 
| 357 # Create a temp directory and unzip the revision into it. | 356 # Create a temp directory and unzip the revision into it. | 
| 358 cwd = os.getcwd() | 357 cwd = os.getcwd() | 
| 359 tempdir = tempfile.mkdtemp(prefix='bisect_tmp') | 358 tempdir = tempfile.mkdtemp(prefix='bisect_tmp') | 
| 360 UnzipFilenameToDir(zipfile, tempdir) | 359 UnzipFilenameToDir(zipfile, tempdir) | 
| 361 os.chdir(tempdir) | 360 os.chdir(tempdir) | 
| 362 | 361 | 
| 363 # Run the build as many times as specified. | 362 # Run the build as many times as specified. | 
| 364 testargs = ['--user-data-dir=%s' % profile] + args | 363 testargs = ['--user-data-dir=%s' % profile] + args | 
| 364 if context.flash_path: | |
| 365 testargs.append('--flag-switches-begin') | |
| 
Robert Sesek
2013/11/08 18:35:44
Why do you need --flag-switches-begin?
 
ilja
2013/11/08 19:38:39
I will try this on Windows again, I thought it nee
 | |
| 365 # The sandbox must be run as root on Official Chrome, so bypass it. | 366 # The sandbox must be run as root on Official Chrome, so bypass it. | 
| 366 if context.is_official and context.platform.startswith('linux'): | 367 if (context.is_official and context.platform.startswith('linux') or | 
| 368 context.flash_path): | |
| 
Robert Sesek
2013/11/08 18:35:44
Is this the intended condition? Can you add anothe
 | |
| 367 testargs.append('--no-sandbox') | 369 testargs.append('--no-sandbox') | 
| 370 if context.flash_path: | |
| 371 testargs.append('--ppapi-flash-path=%s' % context.flash_path) | |
| 372 # We have to pass a large enough Flash version, which currently needs not | |
| 373 # be correct. Instead of requiring the user of the script to figure out and | |
| 374 # pass the correct version we just spoof it. | |
| 375 testargs.append('--ppapi-flash-version=99.9.999.999') | |
| 
enne (OOO)
2013/11/07 23:05:23
Is this impossible to do in Chrome?
 
ilja
2013/11/08 06:07:39
Yes. It actually is a command line parameter that
 | |
| 376 testargs.append('--flag-switches-end') | |
| 368 | 377 | 
| 369 runcommand = [] | 378 runcommand = [] | 
| 370 for token in shlex.split(command): | 379 for token in shlex.split(command): | 
| 371 if token == "%a": | 380 if token == "%a": | 
| 372 runcommand.extend(testargs) | 381 runcommand.extend(testargs) | 
| 373 else: | 382 else: | 
| 374 runcommand.append( \ | 383 runcommand.append( \ | 
| 375 token.replace('%p', context.GetLaunchPath()) \ | 384 token.replace('%p', context.GetLaunchPath()) \ | 
| 376 .replace('%s', ' '.join(testargs))) | 385 .replace('%s', ' '.join(testargs))) | 
| 377 | 386 | 
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 445 def Bisect(base_url, | 454 def Bisect(base_url, | 
| 446 platform, | 455 platform, | 
| 447 official_builds, | 456 official_builds, | 
| 448 is_aura, | 457 is_aura, | 
| 449 good_rev=0, | 458 good_rev=0, | 
| 450 bad_rev=0, | 459 bad_rev=0, | 
| 451 num_runs=1, | 460 num_runs=1, | 
| 452 command="%p %a", | 461 command="%p %a", | 
| 453 try_args=(), | 462 try_args=(), | 
| 454 profile=None, | 463 profile=None, | 
| 464 flash_path=None, | |
| 455 evaluate=AskIsGoodBuild): | 465 evaluate=AskIsGoodBuild): | 
| 456 """Given known good and known bad revisions, run a binary search on all | 466 """Given known good and known bad revisions, run a binary search on all | 
| 457 archived revisions to determine the last known good revision. | 467 archived revisions to determine the last known good revision. | 
| 458 | 468 | 
| 459 @param platform Which build to download/run ('mac', 'win', 'linux64', etc.). | 469 @param platform Which build to download/run ('mac', 'win', 'linux64', etc.). | 
| 460 @param official_builds Specify build type (Chromium or Official build). | 470 @param official_builds Specify build type (Chromium or Official build). | 
| 461 @param good_rev Number/tag of the known good revision. | 471 @param good_rev Number/tag of the known good revision. | 
| 462 @param bad_rev Number/tag of the known bad revision. | 472 @param bad_rev Number/tag of the known bad revision. | 
| 463 @param num_runs Number of times to run each build for asking good/bad. | 473 @param num_runs Number of times to run each build for asking good/bad. | 
| 464 @param try_args A tuple of arguments to pass to the test application. | 474 @param try_args A tuple of arguments to pass to the test application. | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 478 is run on rev 75. | 488 is run on rev 75. | 
| 479 | 489 | 
| 480 - If rev 50 is bad, the download of rev 75 is cancelled, and the next test | 490 - If rev 50 is bad, the download of rev 75 is cancelled, and the next test | 
| 481 is run on rev 25. | 491 is run on rev 25. | 
| 482 """ | 492 """ | 
| 483 | 493 | 
| 484 if not profile: | 494 if not profile: | 
| 485 profile = 'profile' | 495 profile = 'profile' | 
| 486 | 496 | 
| 487 context = PathContext(base_url, platform, good_rev, bad_rev, | 497 context = PathContext(base_url, platform, good_rev, bad_rev, | 
| 488 official_builds, is_aura) | 498 official_builds, is_aura, flash_path) | 
| 489 cwd = os.getcwd() | 499 cwd = os.getcwd() | 
| 490 | 500 | 
| 491 print "Downloading list of known revisions..." | 501 print "Downloading list of known revisions..." | 
| 492 _GetDownloadPath = lambda rev: os.path.join(cwd, | 502 _GetDownloadPath = lambda rev: os.path.join(cwd, | 
| 493 '%s-%s' % (str(rev), context.archive_name)) | 503 '%s-%s' % (str(rev), context.archive_name)) | 
| 494 if official_builds: | 504 if official_builds: | 
| 495 revlist = context.GetOfficialBuildsList() | 505 revlist = context.GetOfficialBuildsList() | 
| 496 else: | 506 else: | 
| 497 revlist = context.GetRevList() | 507 revlist = context.GetRevList() | 
| 498 | 508 | 
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 547 stderr = None | 557 stderr = None | 
| 548 try: | 558 try: | 
| 549 (status, stdout, stderr) = RunRevision(context, | 559 (status, stdout, stderr) = RunRevision(context, | 
| 550 rev, | 560 rev, | 
| 551 fetch.zipfile, | 561 fetch.zipfile, | 
| 552 profile, | 562 profile, | 
| 553 num_runs, | 563 num_runs, | 
| 554 command, | 564 command, | 
| 555 try_args) | 565 try_args) | 
| 556 except Exception, e: | 566 except Exception, e: | 
| 557 print >>sys.stderr, e | 567 print >> sys.stderr, e | 
| 558 | 568 | 
| 559 # Call the evaluate function to see if the current revision is good or bad. | 569 # Call the evaluate function to see if the current revision is good or bad. | 
| 560 # On that basis, kill one of the background downloads and complete the | 570 # On that basis, kill one of the background downloads and complete the | 
| 561 # other, as described in the comments above. | 571 # other, as described in the comments above. | 
| 562 try: | 572 try: | 
| 563 answer = evaluate(rev, official_builds, status, stdout, stderr) | 573 answer = evaluate(rev, official_builds, status, stdout, stderr) | 
| 564 if answer == 'g' and good_rev < bad_rev or \ | 574 if answer == 'g' and good_rev < bad_rev or \ | 
| 565 answer == 'b' and bad_rev < good_rev: | 575 answer == 'b' and bad_rev < good_rev: | 
| 566 fetch.Stop() | 576 fetch.Stop() | 
| 567 minrev = pivot | 577 minrev = pivot | 
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 714 help = 'The buildbot archive to bisect [%s].' % | 724 help = 'The buildbot archive to bisect [%s].' % | 
| 715 '|'.join(choices)) | 725 '|'.join(choices)) | 
| 716 parser.add_option('-o', action="store_true", dest='official_builds', | 726 parser.add_option('-o', action="store_true", dest='official_builds', | 
| 717 help = 'Bisect across official ' + | 727 help = 'Bisect across official ' + | 
| 718 'Chrome builds (internal only) instead of ' + | 728 'Chrome builds (internal only) instead of ' + | 
| 719 'Chromium archives.') | 729 'Chromium archives.') | 
| 720 parser.add_option('-b', '--bad', type = 'str', | 730 parser.add_option('-b', '--bad', type = 'str', | 
| 721 help = 'A bad revision to start bisection. ' + | 731 help = 'A bad revision to start bisection. ' + | 
| 722 'May be earlier or later than the good revision. ' + | 732 'May be earlier or later than the good revision. ' + | 
| 723 'Default is HEAD.') | 733 'Default is HEAD.') | 
| 734 parser.add_option('-f', '--flash_path', type = 'str', | |
| 735 help = 'Absolute path to a recent Adobe Pepper Flash ' + | |
| 736 'binary to be used in this bisection (e.g. ' + | |
| 737 'on Windows C:\...\pepflashplayer.dll and on Linux ' + | |
| 738 '/opt/google/chrome/PepperFlash/libpepflashplayer.so).') | |
| 724 parser.add_option('-g', '--good', type = 'str', | 739 parser.add_option('-g', '--good', type = 'str', | 
| 725 help = 'A good revision to start bisection. ' + | 740 help = 'A good revision to start bisection. ' + | 
| 726 'May be earlier or later than the bad revision. ' + | 741 'May be earlier or later than the bad revision. ' + | 
| 727 'Default is 0.') | 742 'Default is 0.') | 
| 728 parser.add_option('-p', '--profile', '--user-data-dir', type = 'str', | 743 parser.add_option('-p', '--profile', '--user-data-dir', type = 'str', | 
| 729 help = 'Profile to use; this will not reset every run. ' + | 744 help = 'Profile to use; this will not reset every run. ' + | 
| 730 'Defaults to a clean profile.', default = 'profile') | 745 'Defaults to a clean profile.', default = 'profile') | 
| 731 parser.add_option('-t', '--times', type = 'int', | 746 parser.add_option('-t', '--times', type = 'int', | 
| 732 help = 'Number of times to run each build before asking ' + | 747 help = 'Number of times to run each build before asking ' + | 
| 733 'if it\'s good or bad. Temporary profiles are reused.', | 748 'if it\'s good or bad. Temporary profiles are reused.', | 
| 734 default = 1) | 749 default = 1) | 
| 735 parser.add_option('-c', '--command', type = 'str', | 750 parser.add_option('-c', '--command', type = 'str', | 
| 736 help = 'Command to execute. %p and %a refer to Chrome ' + | 751 help = 'Command to execute. %p and %a refer to Chrome ' + | 
| 737 'executable and specified extra arguments respectively. ' + | 752 'executable and specified extra arguments respectively. ' + | 
| 738 'Use %s to specify all extra arguments as one string. ' + | 753 'Use %s to specify all extra arguments as one string. ' + | 
| 739 'Defaults to "%p %a". Note that any extra paths ' + | 754 'Defaults to "%p %a". Note that any extra paths ' + | 
| 740 'specified should be absolute.', | 755 'specified should be absolute.', | 
| 741 default = '%p %a'); | 756 default = '%p %a') | 
| 742 parser.add_option('-l', '--blink', action='store_true', | 757 parser.add_option('-l', '--blink', action='store_true', | 
| 743 help = 'Use Blink bisect instead of Chromium. ') | 758 help = 'Use Blink bisect instead of Chromium. ') | 
| 744 parser.add_option('--aura', | 759 parser.add_option('--aura', | 
| 745 dest='aura', | 760 dest='aura', | 
| 746 action='store_true', | 761 action='store_true', | 
| 747 default=False, | 762 default=False, | 
| 748 help='Allow the script to bisect aura builds') | 763 help='Allow the script to bisect aura builds') | 
| 749 | 764 | 
| 750 (opts, args) = parser.parse_args() | 765 (opts, args) = parser.parse_args() | 
| 751 | 766 | 
| 752 if opts.archive is None: | 767 if opts.archive is None: | 
| 753 print 'Error: missing required parameter: --archive' | 768 print 'Error: missing required parameter: --archive' | 
| 754 print | 769 print | 
| 755 parser.print_help() | 770 parser.print_help() | 
| 756 return 1 | 771 return 1 | 
| 757 | 772 | 
| 758 if opts.aura: | 773 if opts.aura: | 
| 759 if opts.archive != 'win' or not opts.official_builds: | 774 if opts.archive != 'win' or not opts.official_builds: | 
| 760 print 'Error: Aura is supported only on Windows platform '\ | 775 print 'Error: Aura is supported only on Windows platform '\ | 
| 761 'and official builds.' | 776 'and official builds.' | 
| 762 return 1 | 777 return 1 | 
| 763 | 778 | 
| 764 if opts.blink: | 779 if opts.blink: | 
| 765 base_url = WEBKIT_BASE_URL | 780 base_url = WEBKIT_BASE_URL | 
| 766 else: | 781 else: | 
| 767 base_url = CHROMIUM_BASE_URL | 782 base_url = CHROMIUM_BASE_URL | 
| 768 | 783 | 
| 769 # Create the context. Initialize 0 for the revisions as they are set below. | 784 # Create the context. Initialize 0 for the revisions as they are set below. | 
| 770 context = PathContext(base_url, opts.archive, 0, 0, | 785 context = PathContext(base_url, opts.archive, 0, 0, | 
| 771 opts.official_builds, opts.aura) | 786 opts.official_builds, opts.aura, None) | 
| 772 # Pick a starting point, try to get HEAD for this. | 787 # Pick a starting point, try to get HEAD for this. | 
| 773 if opts.bad: | 788 if opts.bad: | 
| 774 bad_rev = opts.bad | 789 bad_rev = opts.bad | 
| 775 else: | 790 else: | 
| 776 bad_rev = '999.0.0.0' | 791 bad_rev = '999.0.0.0' | 
| 777 if not opts.official_builds: | 792 if not opts.official_builds: | 
| 778 bad_rev = GetChromiumRevision(context.GetLastChangeURL()) | 793 bad_rev = GetChromiumRevision(context.GetLastChangeURL()) | 
| 779 | 794 | 
| 780 # Find out when we were good. | 795 # Find out when we were good. | 
| 781 if opts.good: | 796 if opts.good: | 
| 782 good_rev = opts.good | 797 good_rev = opts.good | 
| 783 else: | 798 else: | 
| 784 good_rev = '0.0.0.0' if opts.official_builds else 0 | 799 good_rev = '0.0.0.0' if opts.official_builds else 0 | 
| 785 | 800 | 
| 801 if opts.flash_path: | |
| 802 flash_path = opts.flash_path | |
| 803 msg = 'Could not find Flash binary at %s' % flash_path | |
| 804 assert os.path.exists(flash_path), msg | |
| 805 | |
| 786 if opts.official_builds: | 806 if opts.official_builds: | 
| 787 good_rev = LooseVersion(good_rev) | 807 good_rev = LooseVersion(good_rev) | 
| 788 bad_rev = LooseVersion(bad_rev) | 808 bad_rev = LooseVersion(bad_rev) | 
| 789 else: | 809 else: | 
| 790 good_rev = int(good_rev) | 810 good_rev = int(good_rev) | 
| 791 bad_rev = int(bad_rev) | 811 bad_rev = int(bad_rev) | 
| 792 | 812 | 
| 793 if opts.times < 1: | 813 if opts.times < 1: | 
| 794 print('Number of times to run (%d) must be greater than or equal to 1.' % | 814 print('Number of times to run (%d) must be greater than or equal to 1.' % | 
| 795 opts.times) | 815 opts.times) | 
| 796 parser.print_help() | 816 parser.print_help() | 
| 797 return 1 | 817 return 1 | 
| 798 | 818 | 
| 799 (min_chromium_rev, max_chromium_rev) = Bisect( | 819 (min_chromium_rev, max_chromium_rev) = Bisect( | 
| 800 base_url, opts.archive, opts.official_builds, opts.aura, good_rev, | 820 base_url, opts.archive, opts.official_builds, opts.aura, good_rev, | 
| 801 bad_rev, opts.times, opts.command, args, opts.profile) | 821 bad_rev, opts.times, opts.command, args, opts.profile, opts.flash_path) | 
| 802 | 822 | 
| 803 # Get corresponding blink revisions. | 823 # Get corresponding blink revisions. | 
| 804 try: | 824 try: | 
| 805 min_blink_rev = GetBlinkRevisionForChromiumRevision(context, | 825 min_blink_rev = GetBlinkRevisionForChromiumRevision(context, | 
| 806 min_chromium_rev) | 826 min_chromium_rev) | 
| 807 max_blink_rev = GetBlinkRevisionForChromiumRevision(context, | 827 max_blink_rev = GetBlinkRevisionForChromiumRevision(context, | 
| 808 max_chromium_rev) | 828 max_chromium_rev) | 
| 809 except Exception, e: | 829 except Exception, e: | 
| 810 # Silently ignore the failure. | 830 # Silently ignore the failure. | 
| 811 min_blink_rev, max_blink_rev = 0, 0 | 831 min_blink_rev, max_blink_rev = 0, 0 | 
| (...skipping 21 matching lines...) Expand all Loading... | |
| 833 "you might also want to do a Blink bisect.") | 853 "you might also want to do a Blink bisect.") | 
| 834 | 854 | 
| 835 print 'CHANGELOG URL:' | 855 print 'CHANGELOG URL:' | 
| 836 if opts.official_builds: | 856 if opts.official_builds: | 
| 837 print OFFICIAL_CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) | 857 print OFFICIAL_CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) | 
| 838 else: | 858 else: | 
| 839 print ' ' + CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) | 859 print ' ' + CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) | 
| 840 | 860 | 
| 841 if __name__ == '__main__': | 861 if __name__ == '__main__': | 
| 842 sys.exit(main()) | 862 sys.exit(main()) | 
| OLD | NEW |