OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2013 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 """Performance Test Bisect Tool | 6 """Performance Test Bisect Tool |
7 | 7 |
8 This script bisects a series of changelists using binary search. It starts at | 8 This script bisects a series of changelists using binary search. It starts at |
9 a bad revision where a performance metric has regressed, and asks for a last | 9 a bad revision where a performance metric has regressed, and asks for a last |
10 known-good revision. It will then binary search across this revision range by | 10 known-good revision. It will then binary search across this revision range by |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 else: | 199 else: |
200 logging.info('File gs://%s/%s not found in cloud storage.', | 200 logging.info('File gs://%s/%s not found in cloud storage.', |
201 bucket_name, source_path) | 201 bucket_name, source_path) |
202 except Exception as e: | 202 except Exception as e: |
203 logging.warn('Something went wrong while fetching file from cloud: %s', e) | 203 logging.warn('Something went wrong while fetching file from cloud: %s', e) |
204 if os.path.exists(target_file): | 204 if os.path.exists(target_file): |
205 os.remove(target_file) | 205 os.remove(target_file) |
206 return None | 206 return None |
207 | 207 |
208 | 208 |
209 # This is copied from build/scripts/common/chromium_utils.py. | |
210 def MaybeMakeDirectory(*path): | |
211 """Creates an entire path, if it doesn't already exist.""" | |
212 file_path = os.path.join(*path) | |
213 try: | |
214 os.makedirs(file_path) | |
215 except OSError as e: | |
216 if e.errno != errno.EEXIST: | |
217 return False | |
218 return True | |
219 | |
220 | |
221 # This was copied from build/scripts/common/chromium_utils.py. | 209 # This was copied from build/scripts/common/chromium_utils.py. |
222 def ExtractZip(filename, output_dir, verbose=True): | 210 def ExtractZip(filename, output_dir, verbose=True): |
223 """ Extract the zip archive in the output directory.""" | 211 """ Extract the zip archive in the output directory.""" |
224 MaybeMakeDirectory(output_dir) | 212 MaybeMakeDirectory(output_dir) |
225 | 213 |
226 # On Linux and Mac, we use the unzip command as it will | 214 # On Linux and Mac, we use the unzip command as it will |
227 # handle links and file bits (executable), which is much | 215 # handle links and file bits (executable), which is much |
228 # easier then trying to do that with ZipInfo options. | 216 # easier then trying to do that with ZipInfo options. |
229 # | 217 # |
230 # The Mac Version of unzip unfortunately does not support Zip64, whereas | 218 # The Mac Version of unzip unfortunately does not support Zip64, whereas |
(...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1268 diff_text = bisect_utils.CheckRunGit(diff_command, cwd=self.src_cwd) | 1256 diff_text = bisect_utils.CheckRunGit(diff_command, cwd=self.src_cwd) |
1269 return (chromium_sha, ChangeBackslashToSlashInPatch(diff_text)) | 1257 return (chromium_sha, ChangeBackslashToSlashInPatch(diff_text)) |
1270 else: | 1258 else: |
1271 raise RuntimeError( | 1259 raise RuntimeError( |
1272 'Failed to update DEPS file for chromium: [%s]' % chromium_sha) | 1260 'Failed to update DEPS file for chromium: [%s]' % chromium_sha) |
1273 else: | 1261 else: |
1274 raise RuntimeError( | 1262 raise RuntimeError( |
1275 'DEPS checkout Failed for chromium revision : [%s]' % chromium_sha) | 1263 'DEPS checkout Failed for chromium revision : [%s]' % chromium_sha) |
1276 return (None, None) | 1264 return (None, None) |
1277 | 1265 |
1278 def _ObtainBuild(self, depot, revision=None): | 1266 def ObtainBuild(self, depot, revision=None): |
1279 """Obtains a build by either downloading or building directly. | 1267 """Obtains a build by either downloading or building directly. |
1280 | 1268 |
1281 Args: | 1269 Args: |
1282 depot: Dependency repository name. | 1270 depot: Dependency repository name. |
1283 revision: A git commit hash. If None is given, the currently checked-out | 1271 revision: A git commit hash. If None is given, the currently checked-out |
1284 revision is built. | 1272 revision is built. |
1285 | 1273 |
1286 Returns: | 1274 Returns: |
1287 True for success. | 1275 True for success. |
1288 """ | 1276 """ |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1606 Args: | 1594 Args: |
1607 revision: The revision to sync to. | 1595 revision: The revision to sync to. |
1608 depot: The depot that's being used at the moment (src, webkit, etc.) | 1596 depot: The depot that's being used at the moment (src, webkit, etc.) |
1609 command: The command to execute the performance test. | 1597 command: The command to execute the performance test. |
1610 metric: The performance metric being tested. | 1598 metric: The performance metric being tested. |
1611 | 1599 |
1612 Returns: | 1600 Returns: |
1613 On success, a tuple containing the results of the performance test. | 1601 On success, a tuple containing the results of the performance test. |
1614 Otherwise, a tuple with the error message. | 1602 Otherwise, a tuple with the error message. |
1615 """ | 1603 """ |
| 1604 logging.info('Running RunTest with rev "%s", command "%s"', |
| 1605 revision, command) |
1616 # Decide which sync program to use. | 1606 # Decide which sync program to use. |
1617 sync_client = None | 1607 sync_client = None |
1618 if depot == 'chromium' or depot == 'android-chrome': | 1608 if depot == 'chromium' or depot == 'android-chrome': |
1619 sync_client = 'gclient' | 1609 sync_client = 'gclient' |
1620 | 1610 |
1621 # Decide what depots will need to be synced to what revisions. | 1611 # Decide what depots will need to be synced to what revisions. |
1622 revisions_to_sync = self._FindAllRevisionsToSync(revision, depot) | 1612 revisions_to_sync = self._FindAllRevisionsToSync(revision, depot) |
1623 if not revisions_to_sync: | 1613 if not revisions_to_sync: |
1624 return ('Failed to resolve dependent depots.', BUILD_RESULT_FAIL) | 1614 return ('Failed to resolve dependent depots.', BUILD_RESULT_FAIL) |
1625 | 1615 |
1626 # Do the syncing for all depots. | 1616 # Do the syncing for all depots. |
1627 if not self.opts.debug_ignore_sync: | 1617 if not self.opts.debug_ignore_sync: |
1628 if not self._SyncAllRevisions(revisions_to_sync, sync_client): | 1618 if not self._SyncAllRevisions(revisions_to_sync, sync_client): |
1629 return ('Failed to sync: [%s]' % str(revision), BUILD_RESULT_FAIL) | 1619 return ('Failed to sync: [%s]' % str(revision), BUILD_RESULT_FAIL) |
1630 | 1620 |
1631 # Try to do any post-sync steps. This may include "gclient runhooks". | 1621 # Try to do any post-sync steps. This may include "gclient runhooks". |
1632 if not self._RunPostSync(depot): | 1622 if not self._RunPostSync(depot): |
1633 return ('Failed to run [gclient runhooks].', BUILD_RESULT_FAIL) | 1623 return ('Failed to run [gclient runhooks].', BUILD_RESULT_FAIL) |
1634 | 1624 |
1635 # Skip this revision if it can be skipped. | 1625 # Skip this revision if it can be skipped. |
1636 if skippable and self.ShouldSkipRevision(depot, revision): | 1626 if skippable and self.ShouldSkipRevision(depot, revision): |
1637 return ('Skipped revision: [%s]' % str(revision), | 1627 return ('Skipped revision: [%s]' % str(revision), |
1638 BUILD_RESULT_SKIPPED) | 1628 BUILD_RESULT_SKIPPED) |
1639 | 1629 |
1640 # Obtain a build for this revision. This may be done by requesting a build | 1630 # Obtain a build for this revision. This may be done by requesting a build |
1641 # from another builder, waiting for it and downloading it. | 1631 # from another builder, waiting for it and downloading it. |
1642 start_build_time = time.time() | 1632 start_build_time = time.time() |
1643 build_success = self._ObtainBuild(depot, revision) | 1633 build_success = self.ObtainBuild(depot, revision) |
1644 if not build_success: | 1634 if not build_success: |
1645 return ('Failed to build revision: [%s]' % str(revision), | 1635 return ('Failed to build revision: [%s]' % str(revision), |
1646 BUILD_RESULT_FAIL) | 1636 BUILD_RESULT_FAIL) |
1647 after_build_time = time.time() | 1637 after_build_time = time.time() |
1648 | 1638 |
1649 # Possibly alter the command. | 1639 # Possibly alter the command. |
1650 command = self.GetCompatibleCommand(command, revision, depot) | 1640 command = self.GetCompatibleCommand(command, revision, depot) |
1651 | 1641 |
1652 # Run the command and get the results. | 1642 # Run the command and get the results. |
1653 results = self.RunPerformanceTestAndParseResults(command, metric) | 1643 results = self.RunPerformanceTestAndParseResults(command, metric) |
(...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2416 opts: The options parsed from the command line. | 2406 opts: The options parsed from the command line. |
2417 | 2407 |
2418 Returns: | 2408 Returns: |
2419 True if the platform and build system are supported. | 2409 True if the platform and build system are supported. |
2420 """ | 2410 """ |
2421 # Haven't tested the script out on any other platforms yet. | 2411 # Haven't tested the script out on any other platforms yet. |
2422 supported = ['posix', 'nt'] | 2412 supported = ['posix', 'nt'] |
2423 return os.name in supported | 2413 return os.name in supported |
2424 | 2414 |
2425 | 2415 |
| 2416 def RemoveBuildFiles(build_type): |
| 2417 """Removes build files from previous runs.""" |
| 2418 out_dir = os.path.join('out', build_type) |
| 2419 build_dir = os.path.join('build', build_type) |
| 2420 logging.info('Removing build files in "%s" and "%s".', |
| 2421 os.path.abspath(out_dir), os.path.abspath(build_dir)) |
| 2422 try: |
| 2423 RemakeDirectoryTree(out_dir) |
| 2424 RemakeDirectoryTree(build_dir) |
| 2425 except Exception as e: |
| 2426 raise RuntimeError('Got error in RemoveBuildFiles: %s' % e) |
| 2427 |
| 2428 |
2426 def RemakeDirectoryTree(path_to_dir): | 2429 def RemakeDirectoryTree(path_to_dir): |
2427 """Removes a directory tree and replaces it with an empty one. | 2430 """Removes a directory tree and replaces it with an empty one. |
2428 | 2431 |
2429 Returns True if successful, False otherwise. | 2432 Returns True if successful, False otherwise. |
2430 """ | 2433 """ |
2431 if not RemoveDirectoryTree(path_to_dir): | 2434 RemoveDirectoryTree(path_to_dir) |
2432 return False | 2435 MaybeMakeDirectory(path_to_dir) |
2433 return MaybeMakeDirectory(path_to_dir) | |
2434 | 2436 |
2435 | 2437 |
2436 def RemoveDirectoryTree(path_to_dir): | 2438 def RemoveDirectoryTree(path_to_dir): |
2437 """Removes a directory tree. Returns True if successful or False otherwise.""" | 2439 """Removes a directory tree. Returns True if successful or False otherwise.""" |
2438 try: | 2440 try: |
2439 if os.path.exists(path_to_dir): | 2441 if os.path.exists(path_to_dir): |
2440 shutil.rmtree(path_to_dir) | 2442 shutil.rmtree(path_to_dir) |
2441 except OSError, e: | 2443 except OSError, e: |
2442 if e.errno != errno.ENOENT: | 2444 if e.errno != errno.ENOENT: |
2443 return False | 2445 raise |
2444 return True | |
2445 | 2446 |
2446 | 2447 |
2447 def RemoveBuildFiles(build_type): | 2448 # This is copied from build/scripts/common/chromium_utils.py. |
2448 """Removes build files from previous runs.""" | 2449 def MaybeMakeDirectory(*path): |
2449 out_dir = os.path.join('out', build_type) | 2450 """Creates an entire path, if it doesn't already exist.""" |
2450 build_dir = os.path.join('build', build_type) | 2451 file_path = os.path.join(*path) |
2451 return RemakeDirectoryTree(out_dir) and RemakeDirectoryTree(build_dir) | 2452 try: |
| 2453 os.makedirs(file_path) |
| 2454 except OSError as e: |
| 2455 if e.errno != errno.EEXIST: |
| 2456 raise |
2452 | 2457 |
2453 | 2458 |
2454 class BisectOptions(object): | 2459 class BisectOptions(object): |
2455 """Options to be used when running bisection.""" | 2460 """Options to be used when running bisection.""" |
2456 def __init__(self): | 2461 def __init__(self): |
2457 super(BisectOptions, self).__init__() | 2462 super(BisectOptions, self).__init__() |
2458 | 2463 |
2459 self.target_platform = 'chromium' | 2464 self.target_platform = 'chromium' |
2460 self.build_preference = None | 2465 self.build_preference = None |
2461 self.good_revision = None | 2466 self.good_revision = None |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2535 @staticmethod | 2540 @staticmethod |
2536 def _AddBuildOptionsGroup(parser): | 2541 def _AddBuildOptionsGroup(parser): |
2537 group = parser.add_argument_group('Build options') | 2542 group = parser.add_argument_group('Build options') |
2538 group.add_argument('-w', '--working_directory', | 2543 group.add_argument('-w', '--working_directory', |
2539 help='Path to the working directory where the script ' | 2544 help='Path to the working directory where the script ' |
2540 'will do an initial checkout of the chromium depot. The ' | 2545 'will do an initial checkout of the chromium depot. The ' |
2541 'files will be placed in a subdirectory "bisect" under ' | 2546 'files will be placed in a subdirectory "bisect" under ' |
2542 'working_directory and that will be used to perform the ' | 2547 'working_directory and that will be used to perform the ' |
2543 'bisection. This parameter is optional, if it is not ' | 2548 'bisection. This parameter is optional, if it is not ' |
2544 'supplied, the script will work from the current depot.') | 2549 'supplied, the script will work from the current depot.') |
2545 group.add_argument('--build_preference', type='choice', | 2550 group.add_argument('--build_preference', type=str, |
2546 choices=['msvs', 'ninja', 'make'], | 2551 choices=['msvs', 'ninja', 'make'], |
2547 help='The preferred build system to use. On linux/mac ' | 2552 help='The preferred build system to use. On linux/mac ' |
2548 'the options are make/ninja. On Windows, the ' | 2553 'the options are make/ninja. On Windows, the ' |
2549 'options are msvs/ninja.') | 2554 'options are msvs/ninja.') |
2550 group.add_argument('--target_platform', type='choice', default='chromium', | 2555 group.add_argument('--target_platform', type=str, default='chromium', |
2551 choices=['chromium', 'android', 'android-chrome'], | 2556 choices=['chromium', 'android', 'android-chrome'], |
2552 help='The target platform. Choices are "chromium" ' | 2557 help='The target platform. Choices are "chromium" ' |
2553 '(current platform), or "android". If you specify ' | 2558 '(current platform), or "android". If you specify ' |
2554 'something other than "chromium", you must be ' | 2559 'something other than "chromium", you must be ' |
2555 'properly set up to build that platform.') | 2560 'properly set up to build that platform.') |
2556 group.add_argument('--no_custom_deps', dest='no_custom_deps', | 2561 group.add_argument('--no_custom_deps', dest='no_custom_deps', |
2557 action='store_true', default=False, | 2562 action='store_true', default=False, |
2558 help='Run the script with custom_deps or not.') | 2563 help='Run the script with custom_deps or not.') |
2559 group.add_argument('--extra_src', | 2564 group.add_argument('--extra_src', |
2560 help='Path to a script which can be used to modify the ' | 2565 help='Path to a script which can be used to modify the ' |
2561 'bisect script\'s behavior.') | 2566 'bisect script\'s behavior.') |
2562 group.add_argument('--use_goma', action='store_true', | 2567 group.add_argument('--use_goma', action='store_true', |
2563 help='Add a bunch of extra threads for goma, and enable ' | 2568 help='Add a bunch of extra threads for goma, and enable ' |
2564 'goma') | 2569 'goma') |
2565 group.add_argument('--goma_dir', | 2570 group.add_argument('--goma_dir', |
2566 help='Path to goma tools (or system default if not ' | 2571 help='Path to goma tools (or system default if not ' |
2567 'specified).') | 2572 'specified).') |
2568 group.add_argument('--goma_threads', type=int, default='64', | 2573 group.add_argument('--goma_threads', type=int, default='64', |
2569 help='Number of threads for goma, only if using goma.') | 2574 help='Number of threads for goma, only if using goma.') |
2570 group.add_argument('--output_buildbot_annotations', action='store_true', | 2575 group.add_argument('--output_buildbot_annotations', action='store_true', |
2571 help='Add extra annotation output for buildbot.') | 2576 help='Add extra annotation output for buildbot.') |
2572 group.add_argument('--gs_bucket', default='', dest='gs_bucket', | 2577 group.add_argument('--gs_bucket', default='', dest='gs_bucket', |
2573 help='Name of Google Storage bucket to upload or ' | 2578 help='Name of Google Storage bucket to upload or ' |
2574 'download build. e.g., chrome-perf') | 2579 'download build. e.g., chrome-perf') |
2575 group.add_argument('--target_arch', type='choice', default='ia32', | 2580 group.add_argument('--target_arch', type=str, default='ia32', |
2576 dest='target_arch', choices=['ia32', 'x64', 'arm'], | 2581 dest='target_arch', choices=['ia32', 'x64', 'arm'], |
2577 help='The target build architecture. Choices are "ia32" ' | 2582 help='The target build architecture. Choices are "ia32" ' |
2578 '(default), "x64" or "arm".') | 2583 '(default), "x64" or "arm".') |
2579 group.add_argument('--target_build_type', type='choice', default='Release', | 2584 group.add_argument('--target_build_type', type=str, default='Release', |
2580 choices=['Release', 'Debug'], | 2585 choices=['Release', 'Debug'], |
2581 help='The target build type. Choices are "Release" ' | 2586 help='The target build type. Choices are "Release" ' |
2582 '(default), or "Debug".') | 2587 '(default), or "Debug".') |
2583 group.add_argument('--builder_host', dest='builder_host', | 2588 group.add_argument('--builder_host', dest='builder_host', |
2584 help='Host address of server to produce build by ' | 2589 help='Host address of server to produce build by ' |
2585 'posting try job request.') | 2590 'posting try job request.') |
2586 group.add_argument('--builder_port', dest='builder_port', type='int', | 2591 group.add_argument('--builder_port', dest='builder_port', type=int, |
2587 help='HTTP port of the server to produce build by ' | 2592 help='HTTP port of the server to produce build by ' |
2588 'posting try job request.') | 2593 'posting try job request.') |
2589 | 2594 |
2590 @staticmethod | 2595 @staticmethod |
2591 def _AddDebugOptionsGroup(parser): | 2596 def _AddDebugOptionsGroup(parser): |
2592 group = parser.add_argument_group('Debug options') | 2597 group = parser.add_argument_group('Debug options') |
2593 group.add_argument('--debug_ignore_build', action='store_true', | 2598 group.add_argument('--debug_ignore_build', action='store_true', |
2594 help='DEBUG: Don\'t perform builds.') | 2599 help='DEBUG: Don\'t perform builds.') |
2595 group.add_argument('--debug_ignore_sync', action='store_true', | 2600 group.add_argument('--debug_ignore_sync', action='store_true', |
2596 help='DEBUG: Don\'t perform syncs.') | 2601 help='DEBUG: Don\'t perform syncs.') |
2597 group.add_argument('--debug_ignore_perf_test', action='store_true', | 2602 group.add_argument('--debug_ignore_perf_test', action='store_true', |
2598 help='DEBUG: Don\'t perform performance tests.') | 2603 help='DEBUG: Don\'t perform performance tests.') |
2599 group.add_argument('--debug_ignore_regression_confidence', | 2604 group.add_argument('--debug_ignore_regression_confidence', |
2600 action='store_true', | 2605 action='store_true', |
2601 help='DEBUG: Don\'t score the confidence of the initial ' | 2606 help='DEBUG: Don\'t score the confidence of the initial ' |
2602 'good and bad revisions\' test results.') | 2607 'good and bad revisions\' test results.') |
2603 group.add_argument('--debug_fake_first_test_mean', type='int', default='0', | 2608 group.add_argument('--debug_fake_first_test_mean', type=int, default='0', |
2604 help='DEBUG: When faking performance tests, return this ' | 2609 help='DEBUG: When faking performance tests, return this ' |
2605 'value as the mean of the first performance test, ' | 2610 'value as the mean of the first performance test, ' |
2606 'and return a mean of 0.0 for further tests.') | 2611 'and return a mean of 0.0 for further tests.') |
2607 return group | 2612 return group |
2608 | 2613 |
2609 @classmethod | 2614 @classmethod |
2610 def _CreateCommandLineParser(cls): | 2615 def _CreateCommandLineParser(cls): |
2611 """Creates a parser with bisect options. | 2616 """Creates a parser with bisect options. |
2612 | 2617 |
2613 Returns: | 2618 Returns: |
2614 An instance of optparse.OptionParser. | 2619 An instance of optparse.OptionParser. |
2615 """ | 2620 """ |
2616 usage = ('%prog [options] [-- chromium-options]\n' | 2621 usage = ('%prog [options] [-- chromium-options]\n' |
2617 'Perform binary search on revision history to find a minimal ' | 2622 'Perform binary search on revision history to find a minimal ' |
2618 'range of revisions where a performance metric regressed.\n') | 2623 'range of revisions where a performance metric regressed.\n') |
2619 | 2624 |
2620 parser = argparse.ArgumentParser(usage=usage) | 2625 parser = argparse.ArgumentParser(usage=usage) |
2621 cls._AddBisectOptionsGroup(parser) | 2626 cls._AddBisectOptionsGroup(parser) |
2622 cls._AddBuildOptionsGroup(parser) | 2627 cls._AddBuildOptionsGroup(parser) |
2623 cls._AddDebugOptionsGroup(parser) | 2628 cls._AddDebugOptionsGroup(parser) |
2624 return parser | 2629 return parser |
2625 | 2630 |
2626 def ParseCommandLine(self): | 2631 def ParseCommandLine(self): |
2627 """Parses the command line for bisect options.""" | 2632 """Parses the command line for bisect options.""" |
2628 parser = self._CreateCommandLineParser() | 2633 parser = self._CreateCommandLineParser() |
2629 opts, _ = parser.parse_args() | 2634 opts = parser.parse_args() |
2630 | 2635 |
2631 try: | 2636 try: |
2632 if (not opts.metric and | 2637 if (not opts.metric and |
2633 opts.bisect_mode != bisect_utils.BISECT_MODE_RETURN_CODE): | 2638 opts.bisect_mode != bisect_utils.BISECT_MODE_RETURN_CODE): |
2634 raise RuntimeError('missing required parameter: --metric') | 2639 raise RuntimeError('missing required parameter: --metric') |
2635 | 2640 |
2636 if opts.gs_bucket: | 2641 if opts.gs_bucket: |
2637 if not cloud_storage.List(opts.gs_bucket): | 2642 if not cloud_storage.List(opts.gs_bucket): |
2638 raise RuntimeError('Invalid Google Storage: gs://%s' % opts.gs_bucket) | 2643 raise RuntimeError('Invalid Google Storage: gs://%s' % opts.gs_bucket) |
2639 if not opts.builder_host: | 2644 if not opts.builder_host: |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2713 raise RuntimeError('Invalid or missing --extra_src.') | 2718 raise RuntimeError('Invalid or missing --extra_src.') |
2714 bisect_utils.AddAdditionalDepotInfo(extra_src.GetAdditionalDepotInfo()) | 2719 bisect_utils.AddAdditionalDepotInfo(extra_src.GetAdditionalDepotInfo()) |
2715 | 2720 |
2716 if opts.working_directory: | 2721 if opts.working_directory: |
2717 custom_deps = bisect_utils.DEFAULT_GCLIENT_CUSTOM_DEPS | 2722 custom_deps = bisect_utils.DEFAULT_GCLIENT_CUSTOM_DEPS |
2718 if opts.no_custom_deps: | 2723 if opts.no_custom_deps: |
2719 custom_deps = None | 2724 custom_deps = None |
2720 bisect_utils.CreateBisectDirectoryAndSetupDepot(opts, custom_deps) | 2725 bisect_utils.CreateBisectDirectoryAndSetupDepot(opts, custom_deps) |
2721 | 2726 |
2722 os.chdir(os.path.join(os.getcwd(), 'src')) | 2727 os.chdir(os.path.join(os.getcwd(), 'src')) |
2723 | 2728 RemoveBuildFiles(opts.target_build_type) |
2724 if not RemoveBuildFiles(opts.target_build_type): | |
2725 raise RuntimeError('Something went wrong removing the build files.') | |
2726 | 2729 |
2727 if not _IsPlatformSupported(): | 2730 if not _IsPlatformSupported(): |
2728 raise RuntimeError('Sorry, this platform isn\'t supported yet.') | 2731 raise RuntimeError('Sorry, this platform isn\'t supported yet.') |
2729 | 2732 |
2730 if not source_control.IsInGitRepository(): | 2733 if not source_control.IsInGitRepository(): |
2731 raise RuntimeError( | 2734 raise RuntimeError( |
2732 'Sorry, only the git workflow is supported at the moment.') | 2735 'Sorry, only the git workflow is supported at the moment.') |
2733 | 2736 |
2734 # gClient sync seems to fail if you're not in master branch. | 2737 # gClient sync seems to fail if you're not in master branch. |
2735 if (not source_control.IsInProperBranch() and | 2738 if (not source_control.IsInProperBranch() and |
2736 not opts.debug_ignore_sync and | 2739 not opts.debug_ignore_sync and |
2737 not opts.working_directory): | 2740 not opts.working_directory): |
2738 raise RuntimeError('You must switch to master branch to run bisection.') | 2741 raise RuntimeError('You must switch to master branch to run bisection.') |
2739 bisect_test = BisectPerformanceMetrics(opts, os.getcwd()) | 2742 bisect_test = BisectPerformanceMetrics(opts, os.getcwd()) |
2740 try: | 2743 try: |
2741 results = bisect_test.Run(opts.command, opts.bad_revision, | 2744 results = bisect_test.Run(opts.command, opts.bad_revision, |
2742 opts.good_revision, opts.metric) | 2745 opts.good_revision, opts.metric) |
2743 if results.error: | 2746 if results.error: |
2744 raise RuntimeError(results.error) | 2747 raise RuntimeError(results.error) |
2745 bisect_test.printer.FormatAndPrintResults(results) | 2748 bisect_test.printer.FormatAndPrintResults(results) |
2746 return 0 | 2749 return 0 |
2747 finally: | 2750 finally: |
2748 bisect_test.PerformCleanup() | 2751 bisect_test.PerformCleanup() |
2749 except RuntimeError, e: | 2752 except RuntimeError as e: |
2750 if opts.output_buildbot_annotations: | 2753 if opts.output_buildbot_annotations: |
2751 # The perf dashboard scrapes the "results" step in order to comment on | 2754 # The perf dashboard scrapes the "results" step in order to comment on |
2752 # bugs. If you change this, please update the perf dashboard as well. | 2755 # bugs. If you change this, please update the perf dashboard as well. |
2753 bisect_utils.OutputAnnotationStepStart('Results') | 2756 bisect_utils.OutputAnnotationStepStart('Results') |
2754 print 'Error: ', e.message | 2757 print 'Runtime Error: %s' % e |
2755 logging.warn('A RuntimeError was caught: %s', e.message) | |
2756 if opts.output_buildbot_annotations: | 2758 if opts.output_buildbot_annotations: |
2757 bisect_utils.OutputAnnotationStepClosed() | 2759 bisect_utils.OutputAnnotationStepClosed() |
2758 return 1 | 2760 return 1 |
2759 | 2761 |
2760 | 2762 |
2761 if __name__ == '__main__': | 2763 if __name__ == '__main__': |
2762 sys.exit(main()) | 2764 sys.exit(main()) |
OLD | NEW |