| 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1398 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform) | 1396 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform) |
| 1399 if not fetch_build: | 1397 if not fetch_build: |
| 1400 return False | 1398 return False |
| 1401 | 1399 |
| 1402 # Create a unique ID for each build request posted to try server builders. | 1400 # Create a unique ID for each build request posted to try server builders. |
| 1403 # This ID is added to "Reason" property of the build. | 1401 # This ID is added to "Reason" property of the build. |
| 1404 build_request_id = GetSHA1HexDigest( | 1402 build_request_id = GetSHA1HexDigest( |
| 1405 '%s-%s-%s' % (git_revision, patch, time.time())) | 1403 '%s-%s-%s' % (git_revision, patch, time.time())) |
| 1406 | 1404 |
| 1407 # Reverts any changes to DEPS file. | 1405 # Reverts any changes to DEPS file. |
| 1408 self.source_control.CheckoutFileAtRevision( | 1406 source_control.CheckoutFileAtRevision( |
| 1409 bisect_utils.FILE_DEPS, git_revision, cwd=self.src_cwd) | 1407 bisect_utils.FILE_DEPS, git_revision, cwd=self.src_cwd) |
| 1410 | 1408 |
| 1411 bot_name, build_timeout = GetBuilderNameAndBuildTime( | 1409 bot_name, build_timeout = GetBuilderNameAndBuildTime( |
| 1412 self.opts.target_platform, self.opts.target_arch) | 1410 self.opts.target_platform, self.opts.target_arch) |
| 1413 target_file = None | 1411 target_file = None |
| 1414 try: | 1412 try: |
| 1415 # Execute try job request to build revision with patch. | 1413 # Execute try job request to build revision with patch. |
| 1416 _BuilderTryjob(git_revision, bot_name, build_request_id, patch) | 1414 _BuilderTryjob(git_revision, bot_name, build_request_id, patch) |
| 1417 target_file, error_msg = _WaitUntilBuildIsReady( | 1415 target_file, error_msg = _WaitUntilBuildIsReady( |
| 1418 fetch_build, bot_name, self.opts.builder_host, | 1416 fetch_build, bot_name, self.opts.builder_host, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1445 | 1443 |
| 1446 Returns: | 1444 Returns: |
| 1447 Updated DEPS content as string if deps key is found, otherwise None. | 1445 Updated DEPS content as string if deps key is found, otherwise None. |
| 1448 """ | 1446 """ |
| 1449 # Check whether the depot and revision pattern in DEPS file vars | 1447 # Check whether the depot and revision pattern in DEPS file vars |
| 1450 # e.g. for webkit the format is "webkit_revision": "12345". | 1448 # e.g. for webkit the format is "webkit_revision": "12345". |
| 1451 deps_revision = re.compile(r'(?<="%s": ")([0-9]+)(?=")' % deps_key, | 1449 deps_revision = re.compile(r'(?<="%s": ")([0-9]+)(?=")' % deps_key, |
| 1452 re.MULTILINE) | 1450 re.MULTILINE) |
| 1453 new_data = None | 1451 new_data = None |
| 1454 if re.search(deps_revision, deps_contents): | 1452 if re.search(deps_revision, deps_contents): |
| 1455 commit_position = self.source_control.GetCommitPosition( | 1453 commit_position = source_control.GetCommitPosition( |
| 1456 git_revision, self.depot_registry.GetDepotDir(depot)) | 1454 git_revision, self.depot_registry.GetDepotDir(depot)) |
| 1457 if not commit_position: | 1455 if not commit_position: |
| 1458 print 'Could not determine commit position for %s' % git_revision | 1456 print 'Could not determine commit position for %s' % git_revision |
| 1459 return None | 1457 return None |
| 1460 # Update the revision information for the given depot | 1458 # Update the revision information for the given depot |
| 1461 new_data = re.sub(deps_revision, str(commit_position), deps_contents) | 1459 new_data = re.sub(deps_revision, str(commit_position), deps_contents) |
| 1462 else: | 1460 else: |
| 1463 # Check whether the depot and revision pattern in DEPS file vars | 1461 # Check whether the depot and revision pattern in DEPS file vars |
| 1464 # e.g. for webkit the format is "webkit_revision": "559a6d4ab7a84c539..". | 1462 # e.g. for webkit the format is "webkit_revision": "559a6d4ab7a84c539..". |
| 1465 deps_revision = re.compile( | 1463 deps_revision = re.compile( |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1536 raise RuntimeError('DEPS file does not exists.[%s]' % deps_file_path) | 1534 raise RuntimeError('DEPS file does not exists.[%s]' % deps_file_path) |
| 1537 # Get current chromium revision (git hash). | 1535 # Get current chromium revision (git hash). |
| 1538 cmd = ['rev-parse', 'HEAD'] | 1536 cmd = ['rev-parse', 'HEAD'] |
| 1539 chromium_sha = bisect_utils.CheckRunGit(cmd).strip() | 1537 chromium_sha = bisect_utils.CheckRunGit(cmd).strip() |
| 1540 if not chromium_sha: | 1538 if not chromium_sha: |
| 1541 raise RuntimeError('Failed to determine Chromium revision for %s' % | 1539 raise RuntimeError('Failed to determine Chromium revision for %s' % |
| 1542 revision) | 1540 revision) |
| 1543 if ('chromium' in DEPOT_DEPS_NAME[depot]['from'] or | 1541 if ('chromium' in DEPOT_DEPS_NAME[depot]['from'] or |
| 1544 'v8' in DEPOT_DEPS_NAME[depot]['from']): | 1542 'v8' in DEPOT_DEPS_NAME[depot]['from']): |
| 1545 # Checkout DEPS file for the current chromium revision. | 1543 # Checkout DEPS file for the current chromium revision. |
| 1546 if self.source_control.CheckoutFileAtRevision( | 1544 if source_control.CheckoutFileAtRevision( |
| 1547 bisect_utils.FILE_DEPS, chromium_sha, cwd=self.src_cwd): | 1545 bisect_utils.FILE_DEPS, chromium_sha, cwd=self.src_cwd): |
| 1548 if self.UpdateDeps(revision, depot, deps_file_path): | 1546 if self.UpdateDeps(revision, depot, deps_file_path): |
| 1549 diff_command = [ | 1547 diff_command = [ |
| 1550 'diff', | 1548 'diff', |
| 1551 '--src-prefix=', | 1549 '--src-prefix=', |
| 1552 '--dst-prefix=', | 1550 '--dst-prefix=', |
| 1553 '--no-ext-diff', | 1551 '--no-ext-diff', |
| 1554 bisect_utils.FILE_DEPS, | 1552 bisect_utils.FILE_DEPS, |
| 1555 ] | 1553 ] |
| 1556 diff_text = bisect_utils.CheckRunGit(diff_command, cwd=self.src_cwd) | 1554 diff_text = bisect_utils.CheckRunGit(diff_command, cwd=self.src_cwd) |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1611 Then until crrev.com/276628 *both* (android-chromium-testshell and | 1609 Then until crrev.com/276628 *both* (android-chromium-testshell and |
| 1612 android-chrome-shell) work. After that rev 276628 *only* | 1610 android-chrome-shell) work. After that rev 276628 *only* |
| 1613 android-chrome-shell works. The bisect_perf_regression.py script should | 1611 android-chrome-shell works. The bisect_perf_regression.py script should |
| 1614 handle these cases and set appropriate browser type based on revision. | 1612 handle these cases and set appropriate browser type based on revision. |
| 1615 """ | 1613 """ |
| 1616 if self.opts.target_platform in ['android']: | 1614 if self.opts.target_platform in ['android']: |
| 1617 # When its a third_party depot, get the chromium revision. | 1615 # When its a third_party depot, get the chromium revision. |
| 1618 if depot != 'chromium': | 1616 if depot != 'chromium': |
| 1619 revision = bisect_utils.CheckRunGit( | 1617 revision = bisect_utils.CheckRunGit( |
| 1620 ['rev-parse', 'HEAD'], cwd=self.src_cwd).strip() | 1618 ['rev-parse', 'HEAD'], cwd=self.src_cwd).strip() |
| 1621 commit_position = self.source_control.GetCommitPosition(revision, | 1619 commit_position = source_control.GetCommitPosition(revision, |
| 1622 cwd=self.src_cwd) | 1620 cwd=self.src_cwd) |
| 1623 if not commit_position: | 1621 if not commit_position: |
| 1624 return command_to_run | 1622 return command_to_run |
| 1625 cmd_re = re.compile('--browser=(?P<browser_type>\S+)') | 1623 cmd_re = re.compile('--browser=(?P<browser_type>\S+)') |
| 1626 matches = cmd_re.search(command_to_run) | 1624 matches = cmd_re.search(command_to_run) |
| 1627 if bisect_utils.IsStringInt(commit_position) and matches: | 1625 if bisect_utils.IsStringInt(commit_position) and matches: |
| 1628 cmd_browser = matches.group('browser_type') | 1626 cmd_browser = matches.group('browser_type') |
| 1629 if commit_position <= 274857 and cmd_browser == 'android-chrome-shell': | 1627 if commit_position <= 274857 and cmd_browser == 'android-chrome-shell': |
| 1630 return command_to_run.replace(cmd_browser, | 1628 return command_to_run.replace(cmd_browser, |
| 1631 'android-chromium-testshell') | 1629 'android-chromium-testshell') |
| 1632 elif (commit_position >= 276628 and | 1630 elif (commit_position >= 276628 and |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1796 """ | 1794 """ |
| 1797 revisions_to_sync = [[depot, revision]] | 1795 revisions_to_sync = [[depot, revision]] |
| 1798 | 1796 |
| 1799 is_base = ((depot == 'chromium') or (depot == 'cros') or | 1797 is_base = ((depot == 'chromium') or (depot == 'cros') or |
| 1800 (depot == 'android-chrome')) | 1798 (depot == 'android-chrome')) |
| 1801 | 1799 |
| 1802 # Some SVN depots were split into multiple git depots, so we need to | 1800 # Some SVN depots were split into multiple git depots, so we need to |
| 1803 # figure out for each mirror which git revision to grab. There's no | 1801 # figure out for each mirror which git revision to grab. There's no |
| 1804 # guarantee that the SVN revision will exist for each of the dependent | 1802 # guarantee that the SVN revision will exist for each of the dependent |
| 1805 # depots, so we have to grep the git logs and grab the next earlier one. | 1803 # depots, so we have to grep the git logs and grab the next earlier one. |
| 1806 if (not is_base | 1804 if not is_base and DEPOT_DEPS_NAME[depot]['depends']: |
| 1807 and DEPOT_DEPS_NAME[depot]['depends'] | 1805 commit_position = source_control.GetCommitPosition(revision) |
| 1808 and self.source_control.IsGit()): | |
| 1809 commit_position = self.source_control.GetCommitPosition(revision) | |
| 1810 | 1806 |
| 1811 for d in DEPOT_DEPS_NAME[depot]['depends']: | 1807 for d in DEPOT_DEPS_NAME[depot]['depends']: |
| 1812 self.depot_registry.ChangeToDepotDir(d) | 1808 self.depot_registry.ChangeToDepotDir(d) |
| 1813 | 1809 |
| 1814 dependant_rev = self.source_control.ResolveToRevision( | 1810 dependant_rev = source_control.ResolveToRevision( |
| 1815 commit_position, d, DEPOT_DEPS_NAME, -1000) | 1811 commit_position, d, DEPOT_DEPS_NAME, -1000) |
| 1816 | 1812 |
| 1817 if dependant_rev: | 1813 if dependant_rev: |
| 1818 revisions_to_sync.append([d, dependant_rev]) | 1814 revisions_to_sync.append([d, dependant_rev]) |
| 1819 | 1815 |
| 1820 num_resolved = len(revisions_to_sync) | 1816 num_resolved = len(revisions_to_sync) |
| 1821 num_needed = len(DEPOT_DEPS_NAME[depot]['depends']) | 1817 num_needed = len(DEPOT_DEPS_NAME[depot]['depends']) |
| 1822 | 1818 |
| 1823 self.depot_registry.ChangeToDepotDir(depot) | 1819 self.depot_registry.ChangeToDepotDir(depot) |
| 1824 | 1820 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1891 if not builder.SetupAndroidBuildEnvironment(self.opts, | 1887 if not builder.SetupAndroidBuildEnvironment(self.opts, |
| 1892 path_to_src=self.src_cwd): | 1888 path_to_src=self.src_cwd): |
| 1893 return False | 1889 return False |
| 1894 | 1890 |
| 1895 if depot == 'cros': | 1891 if depot == 'cros': |
| 1896 return self.CreateCrosChroot() | 1892 return self.CreateCrosChroot() |
| 1897 else: | 1893 else: |
| 1898 return self.RunGClientHooks() | 1894 return self.RunGClientHooks() |
| 1899 return True | 1895 return True |
| 1900 | 1896 |
| 1901 def ShouldSkipRevision(self, depot, revision): | 1897 @staticmethod |
| 1898 def ShouldSkipRevision(depot, revision): |
| 1902 """Checks whether a particular revision can be safely skipped. | 1899 """Checks whether a particular revision can be safely skipped. |
| 1903 | 1900 |
| 1904 Some commits can be safely skipped (such as a DEPS roll), since the tool | 1901 Some commits can be safely skipped (such as a DEPS roll), since the tool |
| 1905 is git based those changes would have no effect. | 1902 is git based those changes would have no effect. |
| 1906 | 1903 |
| 1907 Args: | 1904 Args: |
| 1908 depot: The depot being bisected. | 1905 depot: The depot being bisected. |
| 1909 revision: Current revision we're synced to. | 1906 revision: Current revision we're synced to. |
| 1910 | 1907 |
| 1911 Returns: | 1908 Returns: |
| 1912 True if we should skip building/testing this revision. | 1909 True if we should skip building/testing this revision. |
| 1913 """ | 1910 """ |
| 1914 if depot == 'chromium': | 1911 if depot == 'chromium': |
| 1915 if self.source_control.IsGit(): | 1912 cmd = ['diff-tree', '--no-commit-id', '--name-only', '-r', revision] |
| 1916 cmd = ['diff-tree', '--no-commit-id', '--name-only', '-r', revision] | 1913 output = bisect_utils.CheckRunGit(cmd) |
| 1917 output = bisect_utils.CheckRunGit(cmd) | |
| 1918 | 1914 |
| 1919 files = output.splitlines() | 1915 files = output.splitlines() |
| 1920 | 1916 |
| 1921 if len(files) == 1 and files[0] == 'DEPS': | 1917 if len(files) == 1 and files[0] == 'DEPS': |
| 1922 return True | 1918 return True |
| 1923 | 1919 |
| 1924 return False | 1920 return False |
| 1925 | 1921 |
| 1926 def RunTest(self, revision, depot, command, metric, skippable=False): | 1922 def RunTest(self, revision, depot, command, metric, skippable=False): |
| 1927 """Performs a full sync/build/run of the specified revision. | 1923 """Performs a full sync/build/run of the specified revision. |
| 1928 | 1924 |
| 1929 Args: | 1925 Args: |
| 1930 revision: The revision to sync to. | 1926 revision: The revision to sync to. |
| 1931 depot: The depot that's being used at the moment (src, webkit, etc.) | 1927 depot: The depot that's being used at the moment (src, webkit, etc.) |
| 1932 command: The command to execute the performance test. | 1928 command: The command to execute the performance test. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2015 | 2011 |
| 2016 if sync_client: | 2012 if sync_client: |
| 2017 self.PerformPreBuildCleanup() | 2013 self.PerformPreBuildCleanup() |
| 2018 | 2014 |
| 2019 # When using gclient to sync, you need to specify the depot you | 2015 # When using gclient to sync, you need to specify the depot you |
| 2020 # want so that all the dependencies sync properly as well. | 2016 # want so that all the dependencies sync properly as well. |
| 2021 # i.e. gclient sync src@<SHA1> | 2017 # i.e. gclient sync src@<SHA1> |
| 2022 if sync_client == 'gclient': | 2018 if sync_client == 'gclient': |
| 2023 revision = '%s@%s' % (DEPOT_DEPS_NAME[depot]['src'], revision) | 2019 revision = '%s@%s' % (DEPOT_DEPS_NAME[depot]['src'], revision) |
| 2024 | 2020 |
| 2025 sync_success = self.source_control.SyncToRevision(revision, sync_client) | 2021 sync_success = source_control.SyncToRevision(revision, sync_client) |
| 2026 if not sync_success: | 2022 if not sync_success: |
| 2027 return False | 2023 return False |
| 2028 | 2024 |
| 2029 return True | 2025 return True |
| 2030 | 2026 |
| 2031 def _CheckIfRunPassed(self, current_value, known_good_value, known_bad_value): | 2027 def _CheckIfRunPassed(self, current_value, known_good_value, known_bad_value): |
| 2032 """Given known good and bad values, decide if the current_value passed | 2028 """Given known good and bad values, decide if the current_value passed |
| 2033 or failed. | 2029 or failed. |
| 2034 | 2030 |
| 2035 Args: | 2031 Args: |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2213 good_svn_revision: Last known good svn revision. | 2209 good_svn_revision: Last known good svn revision. |
| 2214 | 2210 |
| 2215 Returns: | 2211 Returns: |
| 2216 A tuple with the new bad and good revisions. | 2212 A tuple with the new bad and good revisions. |
| 2217 """ | 2213 """ |
| 2218 # DONOT perform nudge because at revision 291563 .DEPS.git was removed | 2214 # DONOT perform nudge because at revision 291563 .DEPS.git was removed |
| 2219 # and source contain only DEPS file for dependency changes. | 2215 # and source contain only DEPS file for dependency changes. |
| 2220 if good_svn_revision >= 291563: | 2216 if good_svn_revision >= 291563: |
| 2221 return (bad_revision, good_revision) | 2217 return (bad_revision, good_revision) |
| 2222 | 2218 |
| 2223 if self.source_control.IsGit() and self.opts.target_platform == 'chromium': | 2219 if self.opts.target_platform == 'chromium': |
| 2224 changes_to_deps = self.source_control.QueryFileRevisionHistory( | 2220 changes_to_deps = source_control.QueryFileRevisionHistory( |
| 2225 bisect_utils.FILE_DEPS, good_revision, bad_revision) | 2221 bisect_utils.FILE_DEPS, good_revision, bad_revision) |
| 2226 | 2222 |
| 2227 if changes_to_deps: | 2223 if changes_to_deps: |
| 2228 # DEPS file was changed, search from the oldest change to DEPS file to | 2224 # DEPS file was changed, search from the oldest change to DEPS file to |
| 2229 # bad_revision to see if there are matching .DEPS.git changes. | 2225 # bad_revision to see if there are matching .DEPS.git changes. |
| 2230 oldest_deps_change = changes_to_deps[-1] | 2226 oldest_deps_change = changes_to_deps[-1] |
| 2231 changes_to_gitdeps = self.source_control.QueryFileRevisionHistory( | 2227 changes_to_gitdeps = source_control.QueryFileRevisionHistory( |
| 2232 bisect_utils.FILE_DEPS_GIT, oldest_deps_change, bad_revision) | 2228 bisect_utils.FILE_DEPS_GIT, oldest_deps_change, bad_revision) |
| 2233 | 2229 |
| 2234 if len(changes_to_deps) != len(changes_to_gitdeps): | 2230 if len(changes_to_deps) != len(changes_to_gitdeps): |
| 2235 # Grab the timestamp of the last DEPS change | 2231 # Grab the timestamp of the last DEPS change |
| 2236 cmd = ['log', '--format=%ct', '-1', changes_to_deps[0]] | 2232 cmd = ['log', '--format=%ct', '-1', changes_to_deps[0]] |
| 2237 output = bisect_utils.CheckRunGit(cmd) | 2233 output = bisect_utils.CheckRunGit(cmd) |
| 2238 commit_time = int(output) | 2234 commit_time = int(output) |
| 2239 | 2235 |
| 2240 # Try looking for a commit that touches the .DEPS.git file in the | 2236 # Try looking for a commit that touches the .DEPS.git file in the |
| 2241 # next 15 minutes after the DEPS file change. | 2237 # next 15 minutes after the DEPS file change. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2257 self, target_depot, good_revision, bad_revision): | 2253 self, target_depot, good_revision, bad_revision): |
| 2258 """Checks that |good_revision| is an earlier revision than |bad_revision|. | 2254 """Checks that |good_revision| is an earlier revision than |bad_revision|. |
| 2259 | 2255 |
| 2260 Args: | 2256 Args: |
| 2261 good_revision: Number/tag of the known good revision. | 2257 good_revision: Number/tag of the known good revision. |
| 2262 bad_revision: Number/tag of the known bad revision. | 2258 bad_revision: Number/tag of the known bad revision. |
| 2263 | 2259 |
| 2264 Returns: | 2260 Returns: |
| 2265 True if the revisions are in the proper order (good earlier than bad). | 2261 True if the revisions are in the proper order (good earlier than bad). |
| 2266 """ | 2262 """ |
| 2267 if self.source_control.IsGit() and target_depot != 'cros': | 2263 if target_depot != 'cros': |
| 2268 cwd = self.depot_registry.GetDepotDir(target_depot) | 2264 cwd = self.depot_registry.GetDepotDir(target_depot) |
| 2269 good_position = self.source_control.GetCommitPosition(good_revision, cwd) | 2265 good_position = source_control.GetCommitPosition(good_revision, cwd) |
| 2270 bad_position = self.source_control.GetCommitPosition(bad_revision, cwd) | 2266 bad_position = source_control.GetCommitPosition(bad_revision, cwd) |
| 2271 else: | 2267 else: |
| 2272 # CrOS and SVN use integers. | 2268 # CrOS and SVN use integers. |
| 2273 good_position = int(good_revision) | 2269 good_position = int(good_revision) |
| 2274 bad_position = int(bad_revision) | 2270 bad_position = int(bad_revision) |
| 2275 | 2271 |
| 2276 return good_position <= bad_position | 2272 return good_position <= bad_position |
| 2277 | 2273 |
| 2278 def CanPerformBisect(self, good_revision, bad_revision): | 2274 def CanPerformBisect(self, good_revision, bad_revision): |
| 2279 """Checks whether a given revision is bisectable. | 2275 """Checks whether a given revision is bisectable. |
| 2280 | 2276 |
| 2281 Checks for following: | 2277 Checks for following: |
| 2282 1. Non-bisectable revsions for android bots (refer to crbug.com/385324). | 2278 1. Non-bisectable revsions for android bots (refer to crbug.com/385324). |
| 2283 2. Non-bisectable revsions for Windows bots (refer to crbug.com/405274). | 2279 2. Non-bisectable revsions for Windows bots (refer to crbug.com/405274). |
| 2284 | 2280 |
| 2285 Args: | 2281 Args: |
| 2286 good_revision: Known good revision. | 2282 good_revision: Known good revision. |
| 2287 bad_revision: Known bad revision. | 2283 bad_revision: Known bad revision. |
| 2288 | 2284 |
| 2289 Returns: | 2285 Returns: |
| 2290 A dictionary indicating the result. If revision is not bisectable, | 2286 A dictionary indicating the result. If revision is not bisectable, |
| 2291 this will contain the field "error", otherwise None. | 2287 this will contain the field "error", otherwise None. |
| 2292 """ | 2288 """ |
| 2293 if self.opts.target_platform == 'android': | 2289 if self.opts.target_platform == 'android': |
| 2294 good_revision = self.source_control.GetCommitPosition(good_revision) | 2290 good_revision = source_control.GetCommitPosition(good_revision) |
| 2295 if (bisect_utils.IsStringInt(good_revision) | 2291 if (bisect_utils.IsStringInt(good_revision) |
| 2296 and good_revision < 265549): | 2292 and good_revision < 265549): |
| 2297 return {'error': ( | 2293 return {'error': ( |
| 2298 'Bisect cannot continue for the given revision range.\n' | 2294 'Bisect cannot continue for the given revision range.\n' |
| 2299 'It is impossible to bisect Android regressions ' | 2295 'It is impossible to bisect Android regressions ' |
| 2300 'prior to r265549, which allows the bisect bot to ' | 2296 'prior to r265549, which allows the bisect bot to ' |
| 2301 'rely on Telemetry to do apk installation of the most recently ' | 2297 'rely on Telemetry to do apk installation of the most recently ' |
| 2302 'built local ChromeShell(refer to crbug.com/385324).\n' | 2298 'built local ChromeShell(refer to crbug.com/385324).\n' |
| 2303 'Please try bisecting revisions greater than or equal to r265549.')} | 2299 'Please try bisecting revisions greater than or equal to r265549.')} |
| 2304 | 2300 |
| 2305 if bisect_utils.IsWindowsHost(): | 2301 if bisect_utils.IsWindowsHost(): |
| 2306 good_revision = self.source_control.GetCommitPosition(good_revision) | 2302 good_revision = source_control.GetCommitPosition(good_revision) |
| 2307 bad_revision = self.source_control.GetCommitPosition(bad_revision) | 2303 bad_revision = source_control.GetCommitPosition(bad_revision) |
| 2308 if (bisect_utils.IsStringInt(good_revision) and | 2304 if (bisect_utils.IsStringInt(good_revision) and |
| 2309 bisect_utils.IsStringInt(bad_revision)): | 2305 bisect_utils.IsStringInt(bad_revision)): |
| 2310 if (289987 <= good_revision < 290716 or | 2306 if (289987 <= good_revision < 290716 or |
| 2311 289987 <= bad_revision < 290716): | 2307 289987 <= bad_revision < 290716): |
| 2312 return {'error': ('Oops! Revision between r289987 and r290716 are ' | 2308 return {'error': ('Oops! Revision between r289987 and r290716 are ' |
| 2313 'marked as dead zone for Windows due to ' | 2309 'marked as dead zone for Windows due to ' |
| 2314 'crbug.com/405274. Please try another range.')} | 2310 'crbug.com/405274. Please try another range.')} |
| 2315 | 2311 |
| 2316 return None | 2312 return None |
| 2317 | 2313 |
| 2318 def Run(self, command_to_run, bad_revision_in, good_revision_in, metric): | 2314 def Run(self, command_to_run, bad_revision_in, good_revision_in, metric): |
| 2319 """Given known good and bad revisions, run a binary search on all | 2315 """Given known good and bad revisions, run a binary search on all |
| 2320 intermediate revisions to determine the CL where the performance regression | 2316 intermediate revisions to determine the CL where the performance regression |
| 2321 occurred. | 2317 occurred. |
| 2322 | 2318 |
| 2323 Args: | 2319 Args: |
| 2324 command_to_run: Specify the command to execute the performance test. | 2320 command_to_run: Specify the command to execute the performance test. |
| 2325 good_revision: Number/tag of the known good revision. | 2321 good_revision: Number/tag of the known good revision. |
| 2326 bad_revision: Number/tag of the known bad revision. | 2322 bad_revision: Number/tag of the known bad revision. |
| 2327 metric: The performance metric to monitor. | 2323 metric: The performance metric to monitor. |
| 2328 | 2324 |
| 2329 Returns: | 2325 Returns: |
| 2330 A BisectResults object. | 2326 A BisectResults object. |
| 2331 """ | 2327 """ |
| 2332 results = BisectResults(self.depot_registry, self.source_control) | 2328 results = BisectResults(self.depot_registry) |
| 2333 | 2329 |
| 2334 # Choose depot to bisect first | 2330 # Choose depot to bisect first |
| 2335 target_depot = 'chromium' | 2331 target_depot = 'chromium' |
| 2336 if self.opts.target_platform == 'cros': | 2332 if self.opts.target_platform == 'cros': |
| 2337 target_depot = 'cros' | 2333 target_depot = 'cros' |
| 2338 elif self.opts.target_platform == 'android-chrome': | 2334 elif self.opts.target_platform == 'android-chrome': |
| 2339 target_depot = 'android-chrome' | 2335 target_depot = 'android-chrome' |
| 2340 | 2336 |
| 2341 cwd = os.getcwd() | 2337 cwd = os.getcwd() |
| 2342 self.depot_registry.ChangeToDepotDir(target_depot) | 2338 self.depot_registry.ChangeToDepotDir(target_depot) |
| 2343 | 2339 |
| 2344 # If they passed SVN revisions, we can try match them to git SHA1 hashes. | 2340 # If they passed SVN revisions, we can try match them to git SHA1 hashes. |
| 2345 bad_revision = self.source_control.ResolveToRevision( | 2341 bad_revision = source_control.ResolveToRevision( |
| 2346 bad_revision_in, target_depot, DEPOT_DEPS_NAME, 100) | 2342 bad_revision_in, target_depot, DEPOT_DEPS_NAME, 100) |
| 2347 good_revision = self.source_control.ResolveToRevision( | 2343 good_revision = source_control.ResolveToRevision( |
| 2348 good_revision_in, target_depot, DEPOT_DEPS_NAME, -100) | 2344 good_revision_in, target_depot, DEPOT_DEPS_NAME, -100) |
| 2349 | 2345 |
| 2350 os.chdir(cwd) | 2346 os.chdir(cwd) |
| 2351 if bad_revision is None: | 2347 if bad_revision is None: |
| 2352 results.error = 'Couldn\'t resolve [%s] to SHA1.' % bad_revision_in | 2348 results.error = 'Couldn\'t resolve [%s] to SHA1.' % bad_revision_in |
| 2353 return results | 2349 return results |
| 2354 | 2350 |
| 2355 if good_revision is None: | 2351 if good_revision is None: |
| 2356 results.error = 'Couldn\'t resolve [%s] to SHA1.' % good_revision_in | 2352 results.error = 'Couldn\'t resolve [%s] to SHA1.' % good_revision_in |
| 2357 return results | 2353 return results |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2603 level = 'high' | 2599 level = 'high' |
| 2604 else: | 2600 else: |
| 2605 level = 'low' | 2601 level = 'low' |
| 2606 warning = ' and warnings' | 2602 warning = ' and warnings' |
| 2607 if not self.warnings: | 2603 if not self.warnings: |
| 2608 warning = '' | 2604 warning = '' |
| 2609 return confidence_status % {'level': level, 'warning': warning} | 2605 return confidence_status % {'level': level, 'warning': warning} |
| 2610 | 2606 |
| 2611 def _GetViewVCLinkFromDepotAndHash(self, revision_id, depot): | 2607 def _GetViewVCLinkFromDepotAndHash(self, revision_id, depot): |
| 2612 """Gets link to the repository browser.""" | 2608 """Gets link to the repository browser.""" |
| 2613 info = self.source_control.QueryRevisionInfo(revision_id, | 2609 info = source_control.QueryRevisionInfo(revision_id, |
| 2614 self.depot_registry.GetDepotDir(depot)) | 2610 self.depot_registry.GetDepotDir(depot)) |
| 2615 if depot and DEPOT_DEPS_NAME[depot].has_key('viewvc'): | 2611 if depot and DEPOT_DEPS_NAME[depot].has_key('viewvc'): |
| 2616 try: | 2612 try: |
| 2617 # Format is "git-svn-id: svn://....@123456 <other data>" | 2613 # Format is "git-svn-id: svn://....@123456 <other data>" |
| 2618 svn_line = [i for i in info['body'].splitlines() if 'git-svn-id:' in i] | 2614 svn_line = [i for i in info['body'].splitlines() if 'git-svn-id:' in i] |
| 2619 svn_revision = svn_line[0].split('@') | 2615 svn_revision = svn_line[0].split('@') |
| 2620 svn_revision = svn_revision[1].split(' ')[0] | 2616 svn_revision = svn_revision[1].split(' ')[0] |
| 2621 return DEPOT_DEPS_NAME[depot]['viewvc'] + svn_revision | 2617 return DEPOT_DEPS_NAME[depot]['viewvc'] + svn_revision |
| 2622 except IndexError: | 2618 except IndexError: |
| 2623 return '' | 2619 return '' |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2712 | 2708 |
| 2713 # If confidence is too low, don't bother outputting good/bad. | 2709 # If confidence is too low, don't bother outputting good/bad. |
| 2714 if not confidence: | 2710 if not confidence: |
| 2715 state_str = '' | 2711 state_str = '' |
| 2716 state_str = state_str.center(13, ' ') | 2712 state_str = state_str.center(13, ' ') |
| 2717 | 2713 |
| 2718 cl_link = self._GetViewVCLinkFromDepotAndHash(current_id, | 2714 cl_link = self._GetViewVCLinkFromDepotAndHash(current_id, |
| 2719 current_data['depot']) | 2715 current_data['depot']) |
| 2720 if not cl_link: | 2716 if not cl_link: |
| 2721 cl_link = current_id | 2717 cl_link = current_id |
| 2722 commit_position = self.source_control.GetCommitPosition( | 2718 commit_position = source_control.GetCommitPosition( |
| 2723 current_id, self.depot_registry.GetDepotDir(current_data['depot'])) | 2719 current_id, self.depot_registry.GetDepotDir(current_data['depot'])) |
| 2724 commit_position = str(commit_position) | 2720 commit_position = str(commit_position) |
| 2725 if not commit_position: | 2721 if not commit_position: |
| 2726 commit_position = '' | 2722 commit_position = '' |
| 2727 self._PrintTestedCommitsEntry(current_data, commit_position, cl_link, | 2723 self._PrintTestedCommitsEntry(current_data, commit_position, cl_link, |
| 2728 state_str) | 2724 state_str) |
| 2729 | 2725 |
| 2730 def _PrintReproSteps(self): | 2726 def _PrintReproSteps(self): |
| 2731 """Prints out a section of the results explaining how to run the test. | 2727 """Prints out a section of the results explaining how to run the test. |
| 2732 | 2728 |
| (...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3216 bisect_utils.CreateBisectDirectoryAndSetupDepot(opts, custom_deps) | 3212 bisect_utils.CreateBisectDirectoryAndSetupDepot(opts, custom_deps) |
| 3217 | 3213 |
| 3218 os.chdir(os.path.join(os.getcwd(), 'src')) | 3214 os.chdir(os.path.join(os.getcwd(), 'src')) |
| 3219 | 3215 |
| 3220 if not RemoveBuildFiles(opts.target_build_type): | 3216 if not RemoveBuildFiles(opts.target_build_type): |
| 3221 raise RuntimeError('Something went wrong removing the build files.') | 3217 raise RuntimeError('Something went wrong removing the build files.') |
| 3222 | 3218 |
| 3223 if not _IsPlatformSupported(): | 3219 if not _IsPlatformSupported(): |
| 3224 raise RuntimeError('Sorry, this platform isn\'t supported yet.') | 3220 raise RuntimeError('Sorry, this platform isn\'t supported yet.') |
| 3225 | 3221 |
| 3226 # Check what source control method is being used, and create a | 3222 if not source_control.IsInGitRepository(): |
| 3227 # SourceControl object if possible. | |
| 3228 source_control = source_control_module.DetermineAndCreateSourceControl(opts) | |
| 3229 | |
| 3230 if not source_control: | |
| 3231 raise RuntimeError( | 3223 raise RuntimeError( |
| 3232 'Sorry, only the git workflow is supported at the moment.') | 3224 'Sorry, only the git workflow is supported at the moment.') |
| 3233 | 3225 |
| 3234 # gClient sync seems to fail if you're not in master branch. | 3226 # gClient sync seems to fail if you're not in master branch. |
| 3235 if (not source_control.IsInProperBranch() and | 3227 if (not source_control.IsInProperBranch() and |
| 3236 not opts.debug_ignore_sync and | 3228 not opts.debug_ignore_sync and |
| 3237 not opts.working_directory): | 3229 not opts.working_directory): |
| 3238 raise RuntimeError('You must switch to master branch to run bisection.') | 3230 raise RuntimeError('You must switch to master branch to run bisection.') |
| 3239 bisect_test = BisectPerformanceMetrics(source_control, opts) | 3231 bisect_test = BisectPerformanceMetrics(opts) |
| 3240 try: | 3232 try: |
| 3241 bisect_results = bisect_test.Run(opts.command, | 3233 bisect_results = bisect_test.Run(opts.command, |
| 3242 opts.bad_revision, | 3234 opts.bad_revision, |
| 3243 opts.good_revision, | 3235 opts.good_revision, |
| 3244 opts.metric) | 3236 opts.metric) |
| 3245 if bisect_results.error: | 3237 if bisect_results.error: |
| 3246 raise RuntimeError(bisect_results.error) | 3238 raise RuntimeError(bisect_results.error) |
| 3247 bisect_test.FormatAndPrintResults(bisect_results) | 3239 bisect_test.FormatAndPrintResults(bisect_results) |
| 3248 return 0 | 3240 return 0 |
| 3249 finally: | 3241 finally: |
| 3250 bisect_test.PerformCleanup() | 3242 bisect_test.PerformCleanup() |
| 3251 except RuntimeError, e: | 3243 except RuntimeError, e: |
| 3252 if opts.output_buildbot_annotations: | 3244 if opts.output_buildbot_annotations: |
| 3253 # The perf dashboard scrapes the "results" step in order to comment on | 3245 # The perf dashboard scrapes the "results" step in order to comment on |
| 3254 # bugs. If you change this, please update the perf dashboard as well. | 3246 # bugs. If you change this, please update the perf dashboard as well. |
| 3255 bisect_utils.OutputAnnotationStepStart('Results') | 3247 bisect_utils.OutputAnnotationStepStart('Results') |
| 3256 print 'Error: %s' % e.message | 3248 print 'Error: %s' % e.message |
| 3257 if opts.output_buildbot_annotations: | 3249 if opts.output_buildbot_annotations: |
| 3258 bisect_utils.OutputAnnotationStepClosed() | 3250 bisect_utils.OutputAnnotationStepClosed() |
| 3259 return 1 | 3251 return 1 |
| 3260 | 3252 |
| 3261 | 3253 |
| 3262 if __name__ == '__main__': | 3254 if __name__ == '__main__': |
| 3263 sys.exit(main()) | 3255 sys.exit(main()) |
| OLD | NEW |