| 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 import zipfile | 47 import zipfile |
| 48 | 48 |
| 49 sys.path.append(os.path.join( | 49 sys.path.append(os.path.join( |
| 50 os.path.dirname(__file__), os.path.pardir, 'telemetry')) | 50 os.path.dirname(__file__), os.path.pardir, 'telemetry')) |
| 51 | 51 |
| 52 from bisect_results import BisectResults | 52 from bisect_results import BisectResults |
| 53 import bisect_utils | 53 import bisect_utils |
| 54 import builder | 54 import builder |
| 55 import math_utils | 55 import math_utils |
| 56 import request_build | 56 import request_build |
| 57 import source_control as source_control_module | 57 import source_control |
| 58 from telemetry.util import cloud_storage | 58 from telemetry.util import cloud_storage |
| 59 | 59 |
| 60 # Below is the map of "depot" names to information about each depot. Each depot | 60 # Below is the map of "depot" names to information about each depot. Each depot |
| 61 # is a repository, and in the process of bisecting, revision ranges in these | 61 # is a repository, and in the process of bisecting, revision ranges in these |
| 62 # repositories may also be bisected. | 62 # repositories may also be bisected. |
| 63 # | 63 # |
| 64 # Each depot information dictionary may contain: | 64 # Each depot information dictionary may contain: |
| 65 # src: Path to the working directory. | 65 # src: Path to the working directory. |
| 66 # recurse: True if this repository will get bisected. | 66 # recurse: True if this repository will get bisected. |
| 67 # depends: A list of other repositories that are actually part of the same | 67 # depends: A list of other repositories that are actually part of the same |
| (...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 950 bisect_utils.RunGit(['branch', '-D', BISECT_TRYJOB_BRANCH]) | 950 bisect_utils.RunGit(['branch', '-D', BISECT_TRYJOB_BRANCH]) |
| 951 | 951 |
| 952 | 952 |
| 953 class BisectPerformanceMetrics(object): | 953 class BisectPerformanceMetrics(object): |
| 954 """This class contains functionality to perform a bisection of a range of | 954 """This class contains functionality to perform a bisection of a range of |
| 955 revisions to narrow down where performance regressions may have occurred. | 955 revisions to narrow down where performance regressions may have occurred. |
| 956 | 956 |
| 957 The main entry-point is the Run method. | 957 The main entry-point is the Run method. |
| 958 """ | 958 """ |
| 959 | 959 |
| 960 def __init__(self, source_control, opts): | 960 def __init__(self, opts): |
| 961 super(BisectPerformanceMetrics, self).__init__() | 961 super(BisectPerformanceMetrics, self).__init__() |
| 962 | 962 |
| 963 self.opts = opts | 963 self.opts = opts |
| 964 self.source_control = source_control | |
| 965 | 964 |
| 966 # The src directory here is NOT the src/ directory for the repository | 965 # The src directory here is NOT the src/ directory for the repository |
| 967 # where the bisect script is running from. Instead, it's the src/ directory | 966 # where the bisect script is running from. Instead, it's the src/ directory |
| 968 # inside the bisect/ directory which is created before running. | 967 # inside the bisect/ directory which is created before running. |
| 969 self.src_cwd = os.getcwd() | 968 self.src_cwd = os.getcwd() |
| 970 | 969 |
| 971 self.depot_registry = DepotDirectoryRegistry(self.src_cwd) | 970 self.depot_registry = DepotDirectoryRegistry(self.src_cwd) |
| 972 self.cleanup_commands = [] | 971 self.cleanup_commands = [] |
| 973 self.warnings = [] | 972 self.warnings = [] |
| 974 self.builder = builder.Builder.FromOpts(opts) | 973 self.builder = builder.Builder.FromOpts(opts) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1007 assert not return_code, ('An error occurred while running ' | 1006 assert not return_code, ('An error occurred while running ' |
| 1008 '"%s"' % ' '.join(cmd)) | 1007 '"%s"' % ' '.join(cmd)) |
| 1009 | 1008 |
| 1010 os.chdir(cwd) | 1009 os.chdir(cwd) |
| 1011 | 1010 |
| 1012 revision_work_list = list(set( | 1011 revision_work_list = list(set( |
| 1013 [int(o) for o in output.split('\n') if bisect_utils.IsStringInt(o)])) | 1012 [int(o) for o in output.split('\n') if bisect_utils.IsStringInt(o)])) |
| 1014 revision_work_list = sorted(revision_work_list, reverse=True) | 1013 revision_work_list = sorted(revision_work_list, reverse=True) |
| 1015 else: | 1014 else: |
| 1016 cwd = self.depot_registry.GetDepotDir(depot) | 1015 cwd = self.depot_registry.GetDepotDir(depot) |
| 1017 revision_work_list = self.source_control.GetRevisionList(bad_revision, | 1016 revision_work_list = source_control.GetRevisionList(bad_revision, |
| 1018 good_revision, cwd=cwd) | 1017 good_revision, cwd=cwd) |
| 1019 | 1018 |
| 1020 return revision_work_list | 1019 return revision_work_list |
| 1021 | 1020 |
| 1022 def _GetV8BleedingEdgeFromV8TrunkIfMappable(self, revision): | 1021 def _GetV8BleedingEdgeFromV8TrunkIfMappable(self, revision): |
| 1023 commit_position = self.source_control.GetCommitPosition(revision) | 1022 commit_position = source_control.GetCommitPosition(revision) |
| 1024 | 1023 |
| 1025 if bisect_utils.IsStringInt(commit_position): | 1024 if bisect_utils.IsStringInt(commit_position): |
| 1026 # V8 is tricky to bisect, in that there are only a few instances when | 1025 # V8 is tricky to bisect, in that there are only a few instances when |
| 1027 # we can dive into bleeding_edge and get back a meaningful result. | 1026 # we can dive into bleeding_edge and get back a meaningful result. |
| 1028 # Try to detect a V8 "business as usual" case, which is when: | 1027 # Try to detect a V8 "business as usual" case, which is when: |
| 1029 # 1. trunk revision N has description "Version X.Y.Z" | 1028 # 1. trunk revision N has description "Version X.Y.Z" |
| 1030 # 2. bleeding_edge revision (N-1) has description "Prepare push to | 1029 # 2. bleeding_edge revision (N-1) has description "Prepare push to |
| 1031 # trunk. Now working on X.Y.(Z+1)." | 1030 # trunk. Now working on X.Y.(Z+1)." |
| 1032 # | 1031 # |
| 1033 # As of 01/24/2014, V8 trunk descriptions are formatted: | 1032 # As of 01/24/2014, V8 trunk descriptions are formatted: |
| 1034 # "Version 3.X.Y (based on bleeding_edge revision rZ)" | 1033 # "Version 3.X.Y (based on bleeding_edge revision rZ)" |
| 1035 # So we can just try parsing that out first and fall back to the old way. | 1034 # So we can just try parsing that out first and fall back to the old way. |
| 1036 v8_dir = self.depot_registry.GetDepotDir('v8') | 1035 v8_dir = self.depot_registry.GetDepotDir('v8') |
| 1037 v8_bleeding_edge_dir = self.depot_registry.GetDepotDir('v8_bleeding_edge') | 1036 v8_bleeding_edge_dir = self.depot_registry.GetDepotDir('v8_bleeding_edge') |
| 1038 | 1037 |
| 1039 revision_info = self.source_control.QueryRevisionInfo(revision, | 1038 revision_info = source_control.QueryRevisionInfo(revision, cwd=v8_dir) |
| 1040 cwd=v8_dir) | |
| 1041 | 1039 |
| 1042 version_re = re.compile("Version (?P<values>[0-9,.]+)") | 1040 version_re = re.compile("Version (?P<values>[0-9,.]+)") |
| 1043 | 1041 |
| 1044 regex_results = version_re.search(revision_info['subject']) | 1042 regex_results = version_re.search(revision_info['subject']) |
| 1045 | 1043 |
| 1046 if regex_results: | 1044 if regex_results: |
| 1047 git_revision = None | 1045 git_revision = None |
| 1048 | 1046 |
| 1049 # Look for "based on bleeding_edge" and parse out revision | 1047 # Look for "based on bleeding_edge" and parse out revision |
| 1050 if 'based on bleeding_edge' in revision_info['subject']: | 1048 if 'based on bleeding_edge' in revision_info['subject']: |
| 1051 try: | 1049 try: |
| 1052 bleeding_edge_revision = revision_info['subject'].split( | 1050 bleeding_edge_revision = revision_info['subject'].split( |
| 1053 'bleeding_edge revision r')[1] | 1051 'bleeding_edge revision r')[1] |
| 1054 bleeding_edge_revision = int(bleeding_edge_revision.split(')')[0]) | 1052 bleeding_edge_revision = int(bleeding_edge_revision.split(')')[0]) |
| 1055 git_revision = self.source_control.ResolveToRevision( | 1053 git_revision = source_control.ResolveToRevision( |
| 1056 bleeding_edge_revision, 'v8_bleeding_edge', DEPOT_DEPS_NAME, 1, | 1054 bleeding_edge_revision, 'v8_bleeding_edge', DEPOT_DEPS_NAME, 1, |
| 1057 cwd=v8_bleeding_edge_dir) | 1055 cwd=v8_bleeding_edge_dir) |
| 1058 return git_revision | 1056 return git_revision |
| 1059 except (IndexError, ValueError): | 1057 except (IndexError, ValueError): |
| 1060 pass | 1058 pass |
| 1061 | 1059 |
| 1062 if not git_revision: | 1060 if not git_revision: |
| 1063 # Wasn't successful, try the old way of looking for "Prepare push to" | 1061 # Wasn't successful, try the old way of looking for "Prepare push to" |
| 1064 git_revision = self.source_control.ResolveToRevision( | 1062 git_revision = source_control.ResolveToRevision( |
| 1065 int(commit_position) - 1, 'v8_bleeding_edge', DEPOT_DEPS_NAME, -1, | 1063 int(commit_position) - 1, 'v8_bleeding_edge', DEPOT_DEPS_NAME, -1, |
| 1066 cwd=v8_bleeding_edge_dir) | 1064 cwd=v8_bleeding_edge_dir) |
| 1067 | 1065 |
| 1068 if git_revision: | 1066 if git_revision: |
| 1069 revision_info = self.source_control.QueryRevisionInfo(git_revision, | 1067 revision_info = source_control.QueryRevisionInfo(git_revision, |
| 1070 cwd=v8_bleeding_edge_dir) | 1068 cwd=v8_bleeding_edge_dir) |
| 1071 | 1069 |
| 1072 if 'Prepare push to trunk' in revision_info['subject']: | 1070 if 'Prepare push to trunk' in revision_info['subject']: |
| 1073 return git_revision | 1071 return git_revision |
| 1074 return None | 1072 return None |
| 1075 | 1073 |
| 1076 def _GetNearestV8BleedingEdgeFromTrunk(self, revision, search_forward=True): | 1074 def _GetNearestV8BleedingEdgeFromTrunk(self, revision, search_forward=True): |
| 1077 cwd = self.depot_registry.GetDepotDir('v8') | 1075 cwd = self.depot_registry.GetDepotDir('v8') |
| 1078 cmd = ['log', '--format=%ct', '-1', revision] | 1076 cmd = ['log', '--format=%ct', '-1', revision] |
| 1079 output = bisect_utils.CheckRunGit(cmd, cwd=cwd) | 1077 output = bisect_utils.CheckRunGit(cmd, cwd=cwd) |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1270 | 1268 |
| 1271 Returns: | 1269 Returns: |
| 1272 Downloaded archive file path if exists, otherwise None. | 1270 Downloaded archive file path if exists, otherwise None. |
| 1273 """ | 1271 """ |
| 1274 # Source archive file path on cloud storage using Git revision. | 1272 # Source archive file path on cloud storage using Git revision. |
| 1275 source_file = GetRemoteBuildPath( | 1273 source_file = GetRemoteBuildPath( |
| 1276 revision, self.opts.target_platform, target_arch, patch_sha) | 1274 revision, self.opts.target_platform, target_arch, patch_sha) |
| 1277 downloaded_archive = FetchFromCloudStorage(gs_bucket, source_file, out_dir) | 1275 downloaded_archive = FetchFromCloudStorage(gs_bucket, source_file, out_dir) |
| 1278 if not downloaded_archive: | 1276 if not downloaded_archive: |
| 1279 # Get commit position for the given SHA. | 1277 # Get commit position for the given SHA. |
| 1280 commit_position = self.source_control.GetCommitPosition(revision) | 1278 commit_position = source_control.GetCommitPosition(revision) |
| 1281 if commit_position: | 1279 if commit_position: |
| 1282 # Source archive file path on cloud storage using SVN revision. | 1280 # Source archive file path on cloud storage using SVN revision. |
| 1283 source_file = GetRemoteBuildPath( | 1281 source_file = GetRemoteBuildPath( |
| 1284 commit_position, self.opts.target_platform, target_arch, patch_sha) | 1282 commit_position, self.opts.target_platform, target_arch, patch_sha) |
| 1285 return FetchFromCloudStorage(gs_bucket, source_file, out_dir) | 1283 return FetchFromCloudStorage(gs_bucket, source_file, out_dir) |
| 1286 return downloaded_archive | 1284 return downloaded_archive |
| 1287 | 1285 |
| 1288 def DownloadCurrentBuild(self, revision, depot, build_type='Release'): | 1286 def DownloadCurrentBuild(self, revision, depot, build_type='Release'): |
| 1289 """Downloads the build archive for the given revision. | 1287 """Downloads the build archive for the given revision. |
| 1290 | 1288 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1397 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform) | 1395 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform) |
| 1398 if not fetch_build: | 1396 if not fetch_build: |
| 1399 return False | 1397 return False |
| 1400 | 1398 |
| 1401 # Create a unique ID for each build request posted to try server builders. | 1399 # Create a unique ID for each build request posted to try server builders. |
| 1402 # This ID is added to "Reason" property of the build. | 1400 # This ID is added to "Reason" property of the build. |
| 1403 build_request_id = GetSHA1HexDigest( | 1401 build_request_id = GetSHA1HexDigest( |
| 1404 '%s-%s-%s' % (git_revision, patch, time.time())) | 1402 '%s-%s-%s' % (git_revision, patch, time.time())) |
| 1405 | 1403 |
| 1406 # Reverts any changes to DEPS file. | 1404 # Reverts any changes to DEPS file. |
| 1407 self.source_control.CheckoutFileAtRevision( | 1405 source_control.CheckoutFileAtRevision( |
| 1408 bisect_utils.FILE_DEPS, git_revision, cwd=self.src_cwd) | 1406 bisect_utils.FILE_DEPS, git_revision, cwd=self.src_cwd) |
| 1409 | 1407 |
| 1410 bot_name, build_timeout = GetBuilderNameAndBuildTime( | 1408 bot_name, build_timeout = GetBuilderNameAndBuildTime( |
| 1411 self.opts.target_platform, self.opts.target_arch) | 1409 self.opts.target_platform, self.opts.target_arch) |
| 1412 target_file = None | 1410 target_file = None |
| 1413 try: | 1411 try: |
| 1414 # Execute try job request to build revision with patch. | 1412 # Execute try job request to build revision with patch. |
| 1415 _BuilderTryjob(git_revision, bot_name, build_request_id, patch) | 1413 _BuilderTryjob(git_revision, bot_name, build_request_id, patch) |
| 1416 target_file, error_msg = _WaitUntilBuildIsReady( | 1414 target_file, error_msg = _WaitUntilBuildIsReady( |
| 1417 fetch_build, bot_name, self.opts.builder_host, | 1415 fetch_build, bot_name, self.opts.builder_host, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1444 | 1442 |
| 1445 Returns: | 1443 Returns: |
| 1446 Updated DEPS content as string if deps key is found, otherwise None. | 1444 Updated DEPS content as string if deps key is found, otherwise None. |
| 1447 """ | 1445 """ |
| 1448 # Check whether the depot and revision pattern in DEPS file vars | 1446 # Check whether the depot and revision pattern in DEPS file vars |
| 1449 # e.g. for webkit the format is "webkit_revision": "12345". | 1447 # e.g. for webkit the format is "webkit_revision": "12345". |
| 1450 deps_revision = re.compile(r'(?<="%s": ")([0-9]+)(?=")' % deps_key, | 1448 deps_revision = re.compile(r'(?<="%s": ")([0-9]+)(?=")' % deps_key, |
| 1451 re.MULTILINE) | 1449 re.MULTILINE) |
| 1452 new_data = None | 1450 new_data = None |
| 1453 if re.search(deps_revision, deps_contents): | 1451 if re.search(deps_revision, deps_contents): |
| 1454 commit_position = self.source_control.GetCommitPosition( | 1452 commit_position = source_control.GetCommitPosition( |
| 1455 git_revision, self.depot_registry.GetDepotDir(depot)) | 1453 git_revision, self.depot_registry.GetDepotDir(depot)) |
| 1456 if not commit_position: | 1454 if not commit_position: |
| 1457 print 'Could not determine commit position for %s' % git_revision | 1455 print 'Could not determine commit position for %s' % git_revision |
| 1458 return None | 1456 return None |
| 1459 # Update the revision information for the given depot | 1457 # Update the revision information for the given depot |
| 1460 new_data = re.sub(deps_revision, str(commit_position), deps_contents) | 1458 new_data = re.sub(deps_revision, str(commit_position), deps_contents) |
| 1461 else: | 1459 else: |
| 1462 # Check whether the depot and revision pattern in DEPS file vars | 1460 # Check whether the depot and revision pattern in DEPS file vars |
| 1463 # e.g. for webkit the format is "webkit_revision": "559a6d4ab7a84c539..". | 1461 # e.g. for webkit the format is "webkit_revision": "559a6d4ab7a84c539..". |
| 1464 deps_revision = re.compile( | 1462 deps_revision = re.compile( |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1535 raise RuntimeError('DEPS file does not exists.[%s]' % deps_file_path) | 1533 raise RuntimeError('DEPS file does not exists.[%s]' % deps_file_path) |
| 1536 # Get current chromium revision (git hash). | 1534 # Get current chromium revision (git hash). |
| 1537 cmd = ['rev-parse', 'HEAD'] | 1535 cmd = ['rev-parse', 'HEAD'] |
| 1538 chromium_sha = bisect_utils.CheckRunGit(cmd).strip() | 1536 chromium_sha = bisect_utils.CheckRunGit(cmd).strip() |
| 1539 if not chromium_sha: | 1537 if not chromium_sha: |
| 1540 raise RuntimeError('Failed to determine Chromium revision for %s' % | 1538 raise RuntimeError('Failed to determine Chromium revision for %s' % |
| 1541 revision) | 1539 revision) |
| 1542 if ('chromium' in DEPOT_DEPS_NAME[depot]['from'] or | 1540 if ('chromium' in DEPOT_DEPS_NAME[depot]['from'] or |
| 1543 'v8' in DEPOT_DEPS_NAME[depot]['from']): | 1541 'v8' in DEPOT_DEPS_NAME[depot]['from']): |
| 1544 # Checkout DEPS file for the current chromium revision. | 1542 # Checkout DEPS file for the current chromium revision. |
| 1545 if self.source_control.CheckoutFileAtRevision( | 1543 if source_control.CheckoutFileAtRevision( |
| 1546 bisect_utils.FILE_DEPS, chromium_sha, cwd=self.src_cwd): | 1544 bisect_utils.FILE_DEPS, chromium_sha, cwd=self.src_cwd): |
| 1547 if self.UpdateDeps(revision, depot, deps_file_path): | 1545 if self.UpdateDeps(revision, depot, deps_file_path): |
| 1548 diff_command = [ | 1546 diff_command = [ |
| 1549 'diff', | 1547 'diff', |
| 1550 '--src-prefix=', | 1548 '--src-prefix=', |
| 1551 '--dst-prefix=', | 1549 '--dst-prefix=', |
| 1552 '--no-ext-diff', | 1550 '--no-ext-diff', |
| 1553 bisect_utils.FILE_DEPS, | 1551 bisect_utils.FILE_DEPS, |
| 1554 ] | 1552 ] |
| 1555 diff_text = bisect_utils.CheckRunGit(diff_command, cwd=self.src_cwd) | 1553 diff_text = bisect_utils.CheckRunGit(diff_command, cwd=self.src_cwd) |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1610 Then until crrev.com/276628 *both* (android-chromium-testshell and | 1608 Then until crrev.com/276628 *both* (android-chromium-testshell and |
| 1611 android-chrome-shell) work. After that rev 276628 *only* | 1609 android-chrome-shell) work. After that rev 276628 *only* |
| 1612 android-chrome-shell works. The bisect_perf_regression.py script should | 1610 android-chrome-shell works. The bisect_perf_regression.py script should |
| 1613 handle these cases and set appropriate browser type based on revision. | 1611 handle these cases and set appropriate browser type based on revision. |
| 1614 """ | 1612 """ |
| 1615 if self.opts.target_platform in ['android']: | 1613 if self.opts.target_platform in ['android']: |
| 1616 # When its a third_party depot, get the chromium revision. | 1614 # When its a third_party depot, get the chromium revision. |
| 1617 if depot != 'chromium': | 1615 if depot != 'chromium': |
| 1618 revision = bisect_utils.CheckRunGit( | 1616 revision = bisect_utils.CheckRunGit( |
| 1619 ['rev-parse', 'HEAD'], cwd=self.src_cwd).strip() | 1617 ['rev-parse', 'HEAD'], cwd=self.src_cwd).strip() |
| 1620 commit_position = self.source_control.GetCommitPosition(revision, | 1618 commit_position = source_control.GetCommitPosition(revision, |
| 1621 cwd=self.src_cwd) | 1619 cwd=self.src_cwd) |
| 1622 if not commit_position: | 1620 if not commit_position: |
| 1623 return command_to_run | 1621 return command_to_run |
| 1624 cmd_re = re.compile('--browser=(?P<browser_type>\S+)') | 1622 cmd_re = re.compile('--browser=(?P<browser_type>\S+)') |
| 1625 matches = cmd_re.search(command_to_run) | 1623 matches = cmd_re.search(command_to_run) |
| 1626 if bisect_utils.IsStringInt(commit_position) and matches: | 1624 if bisect_utils.IsStringInt(commit_position) and matches: |
| 1627 cmd_browser = matches.group('browser_type') | 1625 cmd_browser = matches.group('browser_type') |
| 1628 if commit_position <= 274857 and cmd_browser == 'android-chrome-shell': | 1626 if commit_position <= 274857 and cmd_browser == 'android-chrome-shell': |
| 1629 return command_to_run.replace(cmd_browser, | 1627 return command_to_run.replace(cmd_browser, |
| 1630 'android-chromium-testshell') | 1628 'android-chromium-testshell') |
| 1631 elif (commit_position >= 276628 and | 1629 elif (commit_position >= 276628 and |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1795 """ | 1793 """ |
| 1796 revisions_to_sync = [[depot, revision]] | 1794 revisions_to_sync = [[depot, revision]] |
| 1797 | 1795 |
| 1798 is_base = ((depot == 'chromium') or (depot == 'cros') or | 1796 is_base = ((depot == 'chromium') or (depot == 'cros') or |
| 1799 (depot == 'android-chrome')) | 1797 (depot == 'android-chrome')) |
| 1800 | 1798 |
| 1801 # Some SVN depots were split into multiple git depots, so we need to | 1799 # Some SVN depots were split into multiple git depots, so we need to |
| 1802 # figure out for each mirror which git revision to grab. There's no | 1800 # figure out for each mirror which git revision to grab. There's no |
| 1803 # guarantee that the SVN revision will exist for each of the dependent | 1801 # guarantee that the SVN revision will exist for each of the dependent |
| 1804 # depots, so we have to grep the git logs and grab the next earlier one. | 1802 # depots, so we have to grep the git logs and grab the next earlier one. |
| 1805 if (not is_base | 1803 if not is_base and DEPOT_DEPS_NAME[depot]['depends']: |
| 1806 and DEPOT_DEPS_NAME[depot]['depends'] | 1804 commit_position = source_control.GetCommitPosition(revision) |
| 1807 and self.source_control.IsGit()): | |
| 1808 commit_position = self.source_control.GetCommitPosition(revision) | |
| 1809 | 1805 |
| 1810 for d in DEPOT_DEPS_NAME[depot]['depends']: | 1806 for d in DEPOT_DEPS_NAME[depot]['depends']: |
| 1811 self.depot_registry.ChangeToDepotDir(d) | 1807 self.depot_registry.ChangeToDepotDir(d) |
| 1812 | 1808 |
| 1813 dependant_rev = self.source_control.ResolveToRevision( | 1809 dependant_rev = source_control.ResolveToRevision( |
| 1814 commit_position, d, DEPOT_DEPS_NAME, -1000) | 1810 commit_position, d, DEPOT_DEPS_NAME, -1000) |
| 1815 | 1811 |
| 1816 if dependant_rev: | 1812 if dependant_rev: |
| 1817 revisions_to_sync.append([d, dependant_rev]) | 1813 revisions_to_sync.append([d, dependant_rev]) |
| 1818 | 1814 |
| 1819 num_resolved = len(revisions_to_sync) | 1815 num_resolved = len(revisions_to_sync) |
| 1820 num_needed = len(DEPOT_DEPS_NAME[depot]['depends']) | 1816 num_needed = len(DEPOT_DEPS_NAME[depot]['depends']) |
| 1821 | 1817 |
| 1822 self.depot_registry.ChangeToDepotDir(depot) | 1818 self.depot_registry.ChangeToDepotDir(depot) |
| 1823 | 1819 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1890 if not builder.SetupAndroidBuildEnvironment(self.opts, | 1886 if not builder.SetupAndroidBuildEnvironment(self.opts, |
| 1891 path_to_src=self.src_cwd): | 1887 path_to_src=self.src_cwd): |
| 1892 return False | 1888 return False |
| 1893 | 1889 |
| 1894 if depot == 'cros': | 1890 if depot == 'cros': |
| 1895 return self.CreateCrosChroot() | 1891 return self.CreateCrosChroot() |
| 1896 else: | 1892 else: |
| 1897 return self.RunGClientHooks() | 1893 return self.RunGClientHooks() |
| 1898 return True | 1894 return True |
| 1899 | 1895 |
| 1900 def ShouldSkipRevision(self, depot, revision): | 1896 @staticmethod |
| 1897 def ShouldSkipRevision(depot, revision): |
| 1901 """Checks whether a particular revision can be safely skipped. | 1898 """Checks whether a particular revision can be safely skipped. |
| 1902 | 1899 |
| 1903 Some commits can be safely skipped (such as a DEPS roll), since the tool | 1900 Some commits can be safely skipped (such as a DEPS roll), since the tool |
| 1904 is git based those changes would have no effect. | 1901 is git based those changes would have no effect. |
| 1905 | 1902 |
| 1906 Args: | 1903 Args: |
| 1907 depot: The depot being bisected. | 1904 depot: The depot being bisected. |
| 1908 revision: Current revision we're synced to. | 1905 revision: Current revision we're synced to. |
| 1909 | 1906 |
| 1910 Returns: | 1907 Returns: |
| 1911 True if we should skip building/testing this revision. | 1908 True if we should skip building/testing this revision. |
| 1912 """ | 1909 """ |
| 1913 if depot == 'chromium': | 1910 if depot == 'chromium': |
| 1914 if self.source_control.IsGit(): | 1911 cmd = ['diff-tree', '--no-commit-id', '--name-only', '-r', revision] |
| 1915 cmd = ['diff-tree', '--no-commit-id', '--name-only', '-r', revision] | 1912 output = bisect_utils.CheckRunGit(cmd) |
| 1916 output = bisect_utils.CheckRunGit(cmd) | |
| 1917 | 1913 |
| 1918 files = output.splitlines() | 1914 files = output.splitlines() |
| 1919 | 1915 |
| 1920 if len(files) == 1 and files[0] == 'DEPS': | 1916 if len(files) == 1 and files[0] == 'DEPS': |
| 1921 return True | 1917 return True |
| 1922 | 1918 |
| 1923 return False | 1919 return False |
| 1924 | 1920 |
| 1925 def RunTest(self, revision, depot, command, metric, skippable=False): | 1921 def RunTest(self, revision, depot, command, metric, skippable=False): |
| 1926 """Performs a full sync/build/run of the specified revision. | 1922 """Performs a full sync/build/run of the specified revision. |
| 1927 | 1923 |
| 1928 Args: | 1924 Args: |
| 1929 revision: The revision to sync to. | 1925 revision: The revision to sync to. |
| 1930 depot: The depot that's being used at the moment (src, webkit, etc.) | 1926 depot: The depot that's being used at the moment (src, webkit, etc.) |
| 1931 command: The command to execute the performance test. | 1927 command: The command to execute the performance test. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2014 | 2010 |
| 2015 if sync_client: | 2011 if sync_client: |
| 2016 self.PerformPreBuildCleanup() | 2012 self.PerformPreBuildCleanup() |
| 2017 | 2013 |
| 2018 # When using gclient to sync, you need to specify the depot you | 2014 # When using gclient to sync, you need to specify the depot you |
| 2019 # want so that all the dependencies sync properly as well. | 2015 # want so that all the dependencies sync properly as well. |
| 2020 # i.e. gclient sync src@<SHA1> | 2016 # i.e. gclient sync src@<SHA1> |
| 2021 if sync_client == 'gclient': | 2017 if sync_client == 'gclient': |
| 2022 revision = '%s@%s' % (DEPOT_DEPS_NAME[depot]['src'], revision) | 2018 revision = '%s@%s' % (DEPOT_DEPS_NAME[depot]['src'], revision) |
| 2023 | 2019 |
| 2024 sync_success = self.source_control.SyncToRevision(revision, sync_client) | 2020 sync_success = source_control.SyncToRevision(revision, sync_client) |
| 2025 if not sync_success: | 2021 if not sync_success: |
| 2026 return False | 2022 return False |
| 2027 | 2023 |
| 2028 return True | 2024 return True |
| 2029 | 2025 |
| 2030 def _CheckIfRunPassed(self, current_value, known_good_value, known_bad_value): | 2026 def _CheckIfRunPassed(self, current_value, known_good_value, known_bad_value): |
| 2031 """Given known good and bad values, decide if the current_value passed | 2027 """Given known good and bad values, decide if the current_value passed |
| 2032 or failed. | 2028 or failed. |
| 2033 | 2029 |
| 2034 Args: | 2030 Args: |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2212 good_svn_revision: Last known good svn revision. | 2208 good_svn_revision: Last known good svn revision. |
| 2213 | 2209 |
| 2214 Returns: | 2210 Returns: |
| 2215 A tuple with the new bad and good revisions. | 2211 A tuple with the new bad and good revisions. |
| 2216 """ | 2212 """ |
| 2217 # DONOT perform nudge because at revision 291563 .DEPS.git was removed | 2213 # DONOT perform nudge because at revision 291563 .DEPS.git was removed |
| 2218 # and source contain only DEPS file for dependency changes. | 2214 # and source contain only DEPS file for dependency changes. |
| 2219 if good_svn_revision >= 291563: | 2215 if good_svn_revision >= 291563: |
| 2220 return (bad_revision, good_revision) | 2216 return (bad_revision, good_revision) |
| 2221 | 2217 |
| 2222 if self.source_control.IsGit() and self.opts.target_platform == 'chromium': | 2218 if self.opts.target_platform == 'chromium': |
| 2223 changes_to_deps = self.source_control.QueryFileRevisionHistory( | 2219 changes_to_deps = source_control.QueryFileRevisionHistory( |
| 2224 bisect_utils.FILE_DEPS, good_revision, bad_revision) | 2220 bisect_utils.FILE_DEPS, good_revision, bad_revision) |
| 2225 | 2221 |
| 2226 if changes_to_deps: | 2222 if changes_to_deps: |
| 2227 # DEPS file was changed, search from the oldest change to DEPS file to | 2223 # DEPS file was changed, search from the oldest change to DEPS file to |
| 2228 # bad_revision to see if there are matching .DEPS.git changes. | 2224 # bad_revision to see if there are matching .DEPS.git changes. |
| 2229 oldest_deps_change = changes_to_deps[-1] | 2225 oldest_deps_change = changes_to_deps[-1] |
| 2230 changes_to_gitdeps = self.source_control.QueryFileRevisionHistory( | 2226 changes_to_gitdeps = source_control.QueryFileRevisionHistory( |
| 2231 bisect_utils.FILE_DEPS_GIT, oldest_deps_change, bad_revision) | 2227 bisect_utils.FILE_DEPS_GIT, oldest_deps_change, bad_revision) |
| 2232 | 2228 |
| 2233 if len(changes_to_deps) != len(changes_to_gitdeps): | 2229 if len(changes_to_deps) != len(changes_to_gitdeps): |
| 2234 # Grab the timestamp of the last DEPS change | 2230 # Grab the timestamp of the last DEPS change |
| 2235 cmd = ['log', '--format=%ct', '-1', changes_to_deps[0]] | 2231 cmd = ['log', '--format=%ct', '-1', changes_to_deps[0]] |
| 2236 output = bisect_utils.CheckRunGit(cmd) | 2232 output = bisect_utils.CheckRunGit(cmd) |
| 2237 commit_time = int(output) | 2233 commit_time = int(output) |
| 2238 | 2234 |
| 2239 # Try looking for a commit that touches the .DEPS.git file in the | 2235 # Try looking for a commit that touches the .DEPS.git file in the |
| 2240 # next 15 minutes after the DEPS file change. | 2236 # next 15 minutes after the DEPS file change. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2256 self, target_depot, good_revision, bad_revision): | 2252 self, target_depot, good_revision, bad_revision): |
| 2257 """Checks that |good_revision| is an earlier revision than |bad_revision|. | 2253 """Checks that |good_revision| is an earlier revision than |bad_revision|. |
| 2258 | 2254 |
| 2259 Args: | 2255 Args: |
| 2260 good_revision: Number/tag of the known good revision. | 2256 good_revision: Number/tag of the known good revision. |
| 2261 bad_revision: Number/tag of the known bad revision. | 2257 bad_revision: Number/tag of the known bad revision. |
| 2262 | 2258 |
| 2263 Returns: | 2259 Returns: |
| 2264 True if the revisions are in the proper order (good earlier than bad). | 2260 True if the revisions are in the proper order (good earlier than bad). |
| 2265 """ | 2261 """ |
| 2266 if self.source_control.IsGit() and target_depot != 'cros': | 2262 if target_depot != 'cros': |
| 2267 cwd = self.depot_registry.GetDepotDir(target_depot) | 2263 cwd = self.depot_registry.GetDepotDir(target_depot) |
| 2268 good_position = self.source_control.GetCommitPosition(good_revision, cwd) | 2264 good_position = source_control.GetCommitPosition(good_revision, cwd) |
| 2269 bad_position = self.source_control.GetCommitPosition(bad_revision, cwd) | 2265 bad_position = source_control.GetCommitPosition(bad_revision, cwd) |
| 2270 else: | 2266 else: |
| 2271 # CrOS and SVN use integers. | 2267 # CrOS and SVN use integers. |
| 2272 good_position = int(good_revision) | 2268 good_position = int(good_revision) |
| 2273 bad_position = int(bad_revision) | 2269 bad_position = int(bad_revision) |
| 2274 | 2270 |
| 2275 return good_position <= bad_position | 2271 return good_position <= bad_position |
| 2276 | 2272 |
| 2277 def CanPerformBisect(self, good_revision, bad_revision): | 2273 def CanPerformBisect(self, good_revision, bad_revision): |
| 2278 """Checks whether a given revision is bisectable. | 2274 """Checks whether a given revision is bisectable. |
| 2279 | 2275 |
| 2280 Checks for following: | 2276 Checks for following: |
| 2281 1. Non-bisectable revsions for android bots (refer to crbug.com/385324). | 2277 1. Non-bisectable revsions for android bots (refer to crbug.com/385324). |
| 2282 2. Non-bisectable revsions for Windows bots (refer to crbug.com/405274). | 2278 2. Non-bisectable revsions for Windows bots (refer to crbug.com/405274). |
| 2283 | 2279 |
| 2284 Args: | 2280 Args: |
| 2285 good_revision: Known good revision. | 2281 good_revision: Known good revision. |
| 2286 bad_revision: Known bad revision. | 2282 bad_revision: Known bad revision. |
| 2287 | 2283 |
| 2288 Returns: | 2284 Returns: |
| 2289 A dictionary indicating the result. If revision is not bisectable, | 2285 A dictionary indicating the result. If revision is not bisectable, |
| 2290 this will contain the field "error", otherwise None. | 2286 this will contain the field "error", otherwise None. |
| 2291 """ | 2287 """ |
| 2292 if self.opts.target_platform == 'android': | 2288 if self.opts.target_platform == 'android': |
| 2293 good_revision = self.source_control.GetCommitPosition(good_revision) | 2289 good_revision = source_control.GetCommitPosition(good_revision) |
| 2294 if (bisect_utils.IsStringInt(good_revision) | 2290 if (bisect_utils.IsStringInt(good_revision) |
| 2295 and good_revision < 265549): | 2291 and good_revision < 265549): |
| 2296 return {'error': ( | 2292 return {'error': ( |
| 2297 'Bisect cannot continue for the given revision range.\n' | 2293 'Bisect cannot continue for the given revision range.\n' |
| 2298 'It is impossible to bisect Android regressions ' | 2294 'It is impossible to bisect Android regressions ' |
| 2299 'prior to r265549, which allows the bisect bot to ' | 2295 'prior to r265549, which allows the bisect bot to ' |
| 2300 'rely on Telemetry to do apk installation of the most recently ' | 2296 'rely on Telemetry to do apk installation of the most recently ' |
| 2301 'built local ChromeShell(refer to crbug.com/385324).\n' | 2297 'built local ChromeShell(refer to crbug.com/385324).\n' |
| 2302 'Please try bisecting revisions greater than or equal to r265549.')} | 2298 'Please try bisecting revisions greater than or equal to r265549.')} |
| 2303 | 2299 |
| 2304 if bisect_utils.IsWindowsHost(): | 2300 if bisect_utils.IsWindowsHost(): |
| 2305 good_revision = self.source_control.GetCommitPosition(good_revision) | 2301 good_revision = source_control.GetCommitPosition(good_revision) |
| 2306 bad_revision = self.source_control.GetCommitPosition(bad_revision) | 2302 bad_revision = source_control.GetCommitPosition(bad_revision) |
| 2307 if (bisect_utils.IsStringInt(good_revision) and | 2303 if (bisect_utils.IsStringInt(good_revision) and |
| 2308 bisect_utils.IsStringInt(bad_revision)): | 2304 bisect_utils.IsStringInt(bad_revision)): |
| 2309 if (289987 <= good_revision < 290716 or | 2305 if (289987 <= good_revision < 290716 or |
| 2310 289987 <= bad_revision < 290716): | 2306 289987 <= bad_revision < 290716): |
| 2311 return {'error': ('Oops! Revision between r289987 and r290716 are ' | 2307 return {'error': ('Oops! Revision between r289987 and r290716 are ' |
| 2312 'marked as dead zone for Windows due to ' | 2308 'marked as dead zone for Windows due to ' |
| 2313 'crbug.com/405274. Please try another range.')} | 2309 'crbug.com/405274. Please try another range.')} |
| 2314 | 2310 |
| 2315 return None | 2311 return None |
| 2316 | 2312 |
| 2317 def Run(self, command_to_run, bad_revision_in, good_revision_in, metric): | 2313 def Run(self, command_to_run, bad_revision_in, good_revision_in, metric): |
| 2318 """Given known good and bad revisions, run a binary search on all | 2314 """Given known good and bad revisions, run a binary search on all |
| 2319 intermediate revisions to determine the CL where the performance regression | 2315 intermediate revisions to determine the CL where the performance regression |
| 2320 occurred. | 2316 occurred. |
| 2321 | 2317 |
| 2322 Args: | 2318 Args: |
| 2323 command_to_run: Specify the command to execute the performance test. | 2319 command_to_run: Specify the command to execute the performance test. |
| 2324 good_revision: Number/tag of the known good revision. | 2320 good_revision: Number/tag of the known good revision. |
| 2325 bad_revision: Number/tag of the known bad revision. | 2321 bad_revision: Number/tag of the known bad revision. |
| 2326 metric: The performance metric to monitor. | 2322 metric: The performance metric to monitor. |
| 2327 | 2323 |
| 2328 Returns: | 2324 Returns: |
| 2329 A BisectResults object. | 2325 A BisectResults object. |
| 2330 """ | 2326 """ |
| 2331 results = BisectResults(self.depot_registry, self.source_control) | 2327 results = BisectResults(self.depot_registry) |
| 2332 | 2328 |
| 2333 # Choose depot to bisect first | 2329 # Choose depot to bisect first |
| 2334 target_depot = 'chromium' | 2330 target_depot = 'chromium' |
| 2335 if self.opts.target_platform == 'cros': | 2331 if self.opts.target_platform == 'cros': |
| 2336 target_depot = 'cros' | 2332 target_depot = 'cros' |
| 2337 elif self.opts.target_platform == 'android-chrome': | 2333 elif self.opts.target_platform == 'android-chrome': |
| 2338 target_depot = 'android-chrome' | 2334 target_depot = 'android-chrome' |
| 2339 | 2335 |
| 2340 cwd = os.getcwd() | 2336 cwd = os.getcwd() |
| 2341 self.depot_registry.ChangeToDepotDir(target_depot) | 2337 self.depot_registry.ChangeToDepotDir(target_depot) |
| 2342 | 2338 |
| 2343 # If they passed SVN revisions, we can try match them to git SHA1 hashes. | 2339 # If they passed SVN revisions, we can try match them to git SHA1 hashes. |
| 2344 bad_revision = self.source_control.ResolveToRevision( | 2340 bad_revision = source_control.ResolveToRevision( |
| 2345 bad_revision_in, target_depot, DEPOT_DEPS_NAME, 100) | 2341 bad_revision_in, target_depot, DEPOT_DEPS_NAME, 100) |
| 2346 good_revision = self.source_control.ResolveToRevision( | 2342 good_revision = source_control.ResolveToRevision( |
| 2347 good_revision_in, target_depot, DEPOT_DEPS_NAME, -100) | 2343 good_revision_in, target_depot, DEPOT_DEPS_NAME, -100) |
| 2348 | 2344 |
| 2349 os.chdir(cwd) | 2345 os.chdir(cwd) |
| 2350 if bad_revision is None: | 2346 if bad_revision is None: |
| 2351 results.error = 'Couldn\'t resolve [%s] to SHA1.' % bad_revision_in | 2347 results.error = 'Couldn\'t resolve [%s] to SHA1.' % bad_revision_in |
| 2352 return results | 2348 return results |
| 2353 | 2349 |
| 2354 if good_revision is None: | 2350 if good_revision is None: |
| 2355 results.error = 'Couldn\'t resolve [%s] to SHA1.' % good_revision_in | 2351 results.error = 'Couldn\'t resolve [%s] to SHA1.' % good_revision_in |
| 2356 return results | 2352 return results |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2602 level = 'high' | 2598 level = 'high' |
| 2603 else: | 2599 else: |
| 2604 level = 'low' | 2600 level = 'low' |
| 2605 warning = ' and warnings' | 2601 warning = ' and warnings' |
| 2606 if not self.warnings: | 2602 if not self.warnings: |
| 2607 warning = '' | 2603 warning = '' |
| 2608 return confidence_status % {'level': level, 'warning': warning} | 2604 return confidence_status % {'level': level, 'warning': warning} |
| 2609 | 2605 |
| 2610 def _GetViewVCLinkFromDepotAndHash(self, revision_id, depot): | 2606 def _GetViewVCLinkFromDepotAndHash(self, revision_id, depot): |
| 2611 """Gets link to the repository browser.""" | 2607 """Gets link to the repository browser.""" |
| 2612 info = self.source_control.QueryRevisionInfo(revision_id, | 2608 info = source_control.QueryRevisionInfo(revision_id, |
| 2613 self.depot_registry.GetDepotDir(depot)) | 2609 self.depot_registry.GetDepotDir(depot)) |
| 2614 if depot and DEPOT_DEPS_NAME[depot].has_key('viewvc'): | 2610 if depot and DEPOT_DEPS_NAME[depot].has_key('viewvc'): |
| 2615 try: | 2611 try: |
| 2616 # Format is "git-svn-id: svn://....@123456 <other data>" | 2612 # Format is "git-svn-id: svn://....@123456 <other data>" |
| 2617 svn_line = [i for i in info['body'].splitlines() if 'git-svn-id:' in i] | 2613 svn_line = [i for i in info['body'].splitlines() if 'git-svn-id:' in i] |
| 2618 svn_revision = svn_line[0].split('@') | 2614 svn_revision = svn_line[0].split('@') |
| 2619 svn_revision = svn_revision[1].split(' ')[0] | 2615 svn_revision = svn_revision[1].split(' ')[0] |
| 2620 return DEPOT_DEPS_NAME[depot]['viewvc'] + svn_revision | 2616 return DEPOT_DEPS_NAME[depot]['viewvc'] + svn_revision |
| 2621 except IndexError: | 2617 except IndexError: |
| 2622 return '' | 2618 return '' |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2711 | 2707 |
| 2712 # If confidence is too low, don't bother outputting good/bad. | 2708 # If confidence is too low, don't bother outputting good/bad. |
| 2713 if not confidence: | 2709 if not confidence: |
| 2714 state_str = '' | 2710 state_str = '' |
| 2715 state_str = state_str.center(13, ' ') | 2711 state_str = state_str.center(13, ' ') |
| 2716 | 2712 |
| 2717 cl_link = self._GetViewVCLinkFromDepotAndHash(current_id, | 2713 cl_link = self._GetViewVCLinkFromDepotAndHash(current_id, |
| 2718 current_data['depot']) | 2714 current_data['depot']) |
| 2719 if not cl_link: | 2715 if not cl_link: |
| 2720 cl_link = current_id | 2716 cl_link = current_id |
| 2721 commit_position = self.source_control.GetCommitPosition( | 2717 commit_position = source_control.GetCommitPosition( |
| 2722 current_id, self.depot_registry.GetDepotDir(current_data['depot'])) | 2718 current_id, self.depot_registry.GetDepotDir(current_data['depot'])) |
| 2723 commit_position = str(commit_position) | 2719 commit_position = str(commit_position) |
| 2724 if not commit_position: | 2720 if not commit_position: |
| 2725 commit_position = '' | 2721 commit_position = '' |
| 2726 self._PrintTestedCommitsEntry(current_data, commit_position, cl_link, | 2722 self._PrintTestedCommitsEntry(current_data, commit_position, cl_link, |
| 2727 state_str) | 2723 state_str) |
| 2728 | 2724 |
| 2729 def _PrintReproSteps(self): | 2725 def _PrintReproSteps(self): |
| 2730 """Prints out a section of the results explaining how to run the test. | 2726 """Prints out a section of the results explaining how to run the test. |
| 2731 | 2727 |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3219 bisect_utils.CreateBisectDirectoryAndSetupDepot(opts, custom_deps) | 3215 bisect_utils.CreateBisectDirectoryAndSetupDepot(opts, custom_deps) |
| 3220 | 3216 |
| 3221 os.chdir(os.path.join(os.getcwd(), 'src')) | 3217 os.chdir(os.path.join(os.getcwd(), 'src')) |
| 3222 | 3218 |
| 3223 if not RemoveBuildFiles(opts.target_build_type): | 3219 if not RemoveBuildFiles(opts.target_build_type): |
| 3224 raise RuntimeError('Something went wrong removing the build files.') | 3220 raise RuntimeError('Something went wrong removing the build files.') |
| 3225 | 3221 |
| 3226 if not _IsPlatformSupported(): | 3222 if not _IsPlatformSupported(): |
| 3227 raise RuntimeError('Sorry, this platform isn\'t supported yet.') | 3223 raise RuntimeError('Sorry, this platform isn\'t supported yet.') |
| 3228 | 3224 |
| 3229 # Check what source control method is being used, and create a | 3225 if not source_control.IsInGitRepository(): |
| 3230 # SourceControl object if possible. | |
| 3231 source_control = source_control_module.DetermineAndCreateSourceControl(opts) | |
| 3232 | |
| 3233 if not source_control: | |
| 3234 raise RuntimeError( | 3226 raise RuntimeError( |
| 3235 'Sorry, only the git workflow is supported at the moment.') | 3227 'Sorry, only the git workflow is supported at the moment.') |
| 3236 | 3228 |
| 3237 # gClient sync seems to fail if you're not in master branch. | 3229 # gClient sync seems to fail if you're not in master branch. |
| 3238 if (not source_control.IsInProperBranch() and | 3230 if (not source_control.IsInProperBranch() and |
| 3239 not opts.debug_ignore_sync and | 3231 not opts.debug_ignore_sync and |
| 3240 not opts.working_directory): | 3232 not opts.working_directory): |
| 3241 raise RuntimeError('You must switch to master branch to run bisection.') | 3233 raise RuntimeError('You must switch to master branch to run bisection.') |
| 3242 bisect_test = BisectPerformanceMetrics(source_control, opts) | 3234 bisect_test = BisectPerformanceMetrics(opts) |
| 3243 try: | 3235 try: |
| 3244 bisect_results = bisect_test.Run(opts.command, | 3236 bisect_results = bisect_test.Run(opts.command, |
| 3245 opts.bad_revision, | 3237 opts.bad_revision, |
| 3246 opts.good_revision, | 3238 opts.good_revision, |
| 3247 opts.metric) | 3239 opts.metric) |
| 3248 if bisect_results.error: | 3240 if bisect_results.error: |
| 3249 raise RuntimeError(bisect_results.error) | 3241 raise RuntimeError(bisect_results.error) |
| 3250 bisect_test.FormatAndPrintResults(bisect_results) | 3242 bisect_test.FormatAndPrintResults(bisect_results) |
| 3251 return 0 | 3243 return 0 |
| 3252 finally: | 3244 finally: |
| 3253 bisect_test.PerformCleanup() | 3245 bisect_test.PerformCleanup() |
| 3254 except RuntimeError, e: | 3246 except RuntimeError, e: |
| 3255 if opts.output_buildbot_annotations: | 3247 if opts.output_buildbot_annotations: |
| 3256 # The perf dashboard scrapes the "results" step in order to comment on | 3248 # The perf dashboard scrapes the "results" step in order to comment on |
| 3257 # bugs. If you change this, please update the perf dashboard as well. | 3249 # bugs. If you change this, please update the perf dashboard as well. |
| 3258 bisect_utils.OutputAnnotationStepStart('Results') | 3250 bisect_utils.OutputAnnotationStepStart('Results') |
| 3259 print 'Error: %s' % e.message | 3251 print 'Error: %s' % e.message |
| 3260 if opts.output_buildbot_annotations: | 3252 if opts.output_buildbot_annotations: |
| 3261 bisect_utils.OutputAnnotationStepClosed() | 3253 bisect_utils.OutputAnnotationStepClosed() |
| 3262 return 1 | 3254 return 1 |
| 3263 | 3255 |
| 3264 | 3256 |
| 3265 if __name__ == '__main__': | 3257 if __name__ == '__main__': |
| 3266 sys.exit(main()) | 3258 sys.exit(main()) |
| OLD | NEW |