Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: tools/bisect-builds.py

Issue 378713002: Added an option to run bisect-builds.py from git checkout so that 'Downloading list of know… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Snapshot Build Bisect Tool 6 """Snapshot Build Bisect Tool
7 7
8 This script bisects a snapshot archive using binary search. It starts at 8 This script bisects a snapshot archive using binary search. It starts at
9 a bad revision (it will try to guess HEAD) and asks for a last known-good 9 a bad revision (it will try to guess HEAD) and asks for a last known-good
10 revision. It will then binary search across this revision range by downloading, 10 revision. It will then binary search across this revision range by downloading,
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 import urllib 72 import urllib
73 from distutils.version import LooseVersion 73 from distutils.version import LooseVersion
74 from xml.etree import ElementTree 74 from xml.etree import ElementTree
75 import zipfile 75 import zipfile
76 76
77 77
78 class PathContext(object): 78 class PathContext(object):
79 """A PathContext is used to carry the information used to construct URLs and 79 """A PathContext is used to carry the information used to construct URLs and
80 paths when dealing with the storage server and archives.""" 80 paths when dealing with the storage server and archives."""
81 def __init__(self, base_url, platform, good_revision, bad_revision, 81 def __init__(self, base_url, platform, good_revision, bad_revision,
82 is_official, is_aura, flash_path = None): 82 is_official, is_aura, use_local_repo, flash_path = None):
83 super(PathContext, self).__init__() 83 super(PathContext, self).__init__()
84 # Store off the input parameters. 84 # Store off the input parameters.
85 self.base_url = base_url 85 self.base_url = base_url
86 self.platform = platform # What's passed in to the '-a/--archive' option. 86 self.platform = platform # What's passed in to the '-a/--archive' option.
87 self.good_revision = good_revision 87 self.good_revision = good_revision
88 self.bad_revision = bad_revision 88 self.bad_revision = bad_revision
89 self.is_official = is_official 89 self.is_official = is_official
90 self.is_aura = is_aura 90 self.is_aura = is_aura
91 self.flash_path = flash_path 91 self.flash_path = flash_path
92 # Dictionary which stores svn revision number as key and it's 92 # Dictionary which stores svn revision number as key and it's
93 # corresponding git hash as value. This data is populated in 93 # corresponding git hash as value. This data is populated in
94 # _FetchAndParse and used later in GetDownloadURL while downloading 94 # _FetchAndParse and used later in GetDownloadURL while downloading
95 # the build. 95 # the build.
96 self.githash_svn_dict = {} 96 self.githash_svn_dict = {}
97 97
98 # The name of the ZIP file in a revision directory on the server. 98 # The name of the ZIP file in a revision directory on the server.
99 self.archive_name = None 99 self.archive_name = None
100 100
101 # If the script is run from a local Chromium checkout,
102 # "--use-local-repo" option can be used to make the script run faster.
103 # It uses "git svn find-rev <SHA1>" command to convert git hash to svn
104 # revision number.
105 self.use_local_repo = use_local_repo
106
101 # Set some internal members: 107 # Set some internal members:
102 # _listing_platform_dir = Directory that holds revisions. Ends with a '/'. 108 # _listing_platform_dir = Directory that holds revisions. Ends with a '/'.
103 # _archive_extract_dir = Uncompressed directory in the archive_name file. 109 # _archive_extract_dir = Uncompressed directory in the archive_name file.
104 # _binary_name = The name of the executable to run. 110 # _binary_name = The name of the executable to run.
105 if self.platform in ('linux', 'linux64', 'linux-arm'): 111 if self.platform in ('linux', 'linux64', 'linux-arm'):
106 self._binary_name = 'chrome' 112 self._binary_name = 'chrome'
107 elif self.platform == 'mac': 113 elif self.platform == 'mac':
108 self.archive_name = 'chrome-mac.zip' 114 self.archive_name = 'chrome-mac.zip'
109 self._archive_extract_dir = 'chrome-mac' 115 self._archive_extract_dir = 'chrome-mac'
110 elif self.platform == 'win': 116 elif self.platform == 'win':
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 _FetchAndParse(self.GetListingURL()) 252 _FetchAndParse(self.GetListingURL())
247 # If the result list was truncated, refetch with the next marker. Do this 253 # If the result list was truncated, refetch with the next marker. Do this
248 # until an entire directory listing is done. 254 # until an entire directory listing is done.
249 while next_marker: 255 while next_marker:
250 next_url = self.GetListingURL(next_marker) 256 next_url = self.GetListingURL(next_marker)
251 (new_revisions, next_marker, new_dict) = _FetchAndParse(next_url) 257 (new_revisions, next_marker, new_dict) = _FetchAndParse(next_url)
252 revisions.extend(new_revisions) 258 revisions.extend(new_revisions)
253 self.githash_svn_dict.update(new_dict) 259 self.githash_svn_dict.update(new_dict)
254 return revisions 260 return revisions
255 261
256 def GetSVNRevisionFromGitHash(self, git_sha1, depot='chromium'): 262 def _GetSVNRevisionFromGitHashWithoutGitCheckout(self, git_sha1, depot):
257 json_url = GITHASH_TO_SVN_URL[depot] % git_sha1 263 json_url = GITHASH_TO_SVN_URL[depot] % git_sha1
258 try: 264 try:
259 response = urllib.urlopen(json_url) 265 response = urllib.urlopen(json_url)
260 except urllib.HTTPError as error: 266 except urllib.HTTPError as error:
261 msg = 'HTTP Error %d for %s' % (error.getcode(), git_sha1) 267 msg = 'HTTP Error %d for %s' % (error.getcode(), git_sha1)
262 return None 268 return None
263 data = json.loads(response.read()[4:]) 269 data = json.loads(response.read()[4:])
264 if 'message' in data: 270 if 'message' in data:
265 message = data['message'].split('\n') 271 message = data['message'].split('\n')
266 message = [line for line in message if line.strip()] 272 message = [line for line in message if line.strip()]
267 search_pattern = re.compile(SEARCH_PATTERN[depot]) 273 search_pattern = re.compile(SEARCH_PATTERN[depot])
268 result = search_pattern.search(message[len(message)-1]) 274 result = search_pattern.search(message[len(message)-1])
269 if result: 275 if result:
270 return result.group(1) 276 return result.group(1)
271 print 'Failed to get svn revision number for %s' % git_sha1 277 print 'Failed to get svn revision number for %s' % git_sha1
272 return None 278 return None
273 279
280 def _GetSVNRevisionFromGitHashFromGitCheckout(self, git_sha1, depot):
281 def _RunGit(command, path):
282 command = ['git'] + command
283 if path:
284 original_path = os.getcwd()
285 os.chdir(path)
286 shell = sys.platform.startswith('win')
287 proc = subprocess.Popen(command, shell=shell, stdout=subprocess.PIPE,
288 stderr=subprocess.PIPE)
289 (output, _) = proc.communicate()
290
291 if path:
292 os.chdir(original_path)
293 return (output, proc.returncode)
294
295 path = None
296 if depot == 'blink':
297 path = os.path.join(os.getcwd(), 'third_party', 'WebKit')
298 if os.path.basename(os.getcwd()) == 'src':
299 command = ['svn', 'find-rev', git_sha1]
300 (git_output, return_code) = _RunGit(command, path)
301 if not return_code:
302 return git_output.strip('\n')
303 return None
304 else:
305 print ('Script should be run from src folder. ' +
306 'Eg: python tools/bisect-builds.py -g 280588 -b 280590' +
307 '--archive linux64 --use-local-repo')
308 sys.exit(1)
309
310 def GetSVNRevisionFromGitHash(self, git_sha1, depot='chromium'):
311 if not self.use_local_repo:
312 return self._GetSVNRevisionFromGitHashWithoutGitCheckout(git_sha1, depot)
313 else:
314 return self._GetSVNRevisionFromGitHashFromGitCheckout(git_sha1, depot)
315
274 def GetRevList(self): 316 def GetRevList(self):
275 """Gets the list of revision numbers between self.good_revision and 317 """Gets the list of revision numbers between self.good_revision and
276 self.bad_revision.""" 318 self.bad_revision."""
277 # Download the revlist and filter for just the range between good and bad. 319 # Download the revlist and filter for just the range between good and bad.
278 minrev = min(self.good_revision, self.bad_revision) 320 minrev = min(self.good_revision, self.bad_revision)
279 maxrev = max(self.good_revision, self.bad_revision) 321 maxrev = max(self.good_revision, self.bad_revision)
280 revlist_all = map(int, self.ParseDirectoryIndex()) 322 revlist_all = map(int, self.ParseDirectoryIndex())
281 323
282 revlist = [x for x in revlist_all if x >= int(minrev) and x <= int(maxrev)] 324 revlist = [x for x in revlist_all if x >= int(minrev) and x <= int(maxrev)]
283 revlist.sort() 325 revlist.sort()
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 must have been started previously.""" 548 must have been started previously."""
507 print "Downloading revision %s..." % str(self.rev) 549 print "Downloading revision %s..." % str(self.rev)
508 self.progress_event.set() # Display progress of download. 550 self.progress_event.set() # Display progress of download.
509 self.thread.join() 551 self.thread.join()
510 552
511 553
512 def Bisect(base_url, 554 def Bisect(base_url,
513 platform, 555 platform,
514 official_builds, 556 official_builds,
515 is_aura, 557 is_aura,
558 use_local_repo,
516 good_rev=0, 559 good_rev=0,
517 bad_rev=0, 560 bad_rev=0,
518 num_runs=1, 561 num_runs=1,
519 command="%p %a", 562 command="%p %a",
520 try_args=(), 563 try_args=(),
521 profile=None, 564 profile=None,
522 flash_path=None, 565 flash_path=None,
523 interactive=True, 566 interactive=True,
524 evaluate=AskIsGoodBuild): 567 evaluate=AskIsGoodBuild):
525 """Given known good and known bad revisions, run a binary search on all 568 """Given known good and known bad revisions, run a binary search on all
(...skipping 23 matching lines...) Expand all
549 is run on rev 75. 592 is run on rev 75.
550 593
551 - If rev 50 is bad, the download of rev 75 is cancelled, and the next test 594 - If rev 50 is bad, the download of rev 75 is cancelled, and the next test
552 is run on rev 25. 595 is run on rev 25.
553 """ 596 """
554 597
555 if not profile: 598 if not profile:
556 profile = 'profile' 599 profile = 'profile'
557 600
558 context = PathContext(base_url, platform, good_rev, bad_rev, 601 context = PathContext(base_url, platform, good_rev, bad_rev,
559 official_builds, is_aura, flash_path) 602 official_builds, is_aura, use_local_repo, flash_path)
560 cwd = os.getcwd() 603 cwd = os.getcwd()
561 604
562 print "Downloading list of known revisions..." 605 print "Downloading list of known revisions..."
563 _GetDownloadPath = lambda rev: os.path.join(cwd, 606 _GetDownloadPath = lambda rev: os.path.join(cwd,
564 '%s-%s' % (str(rev), context.archive_name)) 607 '%s-%s' % (str(rev), context.archive_name))
565 if official_builds: 608 if official_builds:
566 revlist = context.GetOfficialBuildsList() 609 revlist = context.GetOfficialBuildsList()
567 else: 610 else:
568 revlist = context.GetRevList() 611 revlist = context.GetRevList()
569 612
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 parser.add_option('-l', '--blink', action='store_true', 881 parser.add_option('-l', '--blink', action='store_true',
839 help = 'Use Blink bisect instead of Chromium. ') 882 help = 'Use Blink bisect instead of Chromium. ')
840 parser.add_option('', '--not-interactive', action='store_true', 883 parser.add_option('', '--not-interactive', action='store_true',
841 help = 'Use command exit code to tell good/bad revision.', 884 help = 'Use command exit code to tell good/bad revision.',
842 default=False) 885 default=False)
843 parser.add_option('--aura', 886 parser.add_option('--aura',
844 dest='aura', 887 dest='aura',
845 action='store_true', 888 action='store_true',
846 default=False, 889 default=False,
847 help='Allow the script to bisect aura builds') 890 help='Allow the script to bisect aura builds')
891 parser.add_option('--use-local-repo',
892 dest='use_local_repo',
893 action='store_true',
894 default=False,
895 help='Allow the script to convert git SHA1 to SVN ' +
896 'revision using "git svn find-rev <SHA1>" ' +
897 'command from a Chromium checkout.')
848 898
849 (opts, args) = parser.parse_args() 899 (opts, args) = parser.parse_args()
850 900
851 if opts.archive is None: 901 if opts.archive is None:
852 print 'Error: missing required parameter: --archive' 902 print 'Error: missing required parameter: --archive'
853 print 903 print
854 parser.print_help() 904 parser.print_help()
855 return 1 905 return 1
856 906
857 if opts.aura: 907 if opts.aura:
858 if opts.archive != 'win' or not opts.official_builds: 908 if opts.archive != 'win' or not opts.official_builds:
859 print 'Error: Aura is supported only on Windows platform '\ 909 print 'Error: Aura is supported only on Windows platform '\
860 'and official builds.' 910 'and official builds.'
861 return 1 911 return 1
862 912
863 if opts.blink: 913 if opts.blink:
864 base_url = WEBKIT_BASE_URL 914 base_url = WEBKIT_BASE_URL
865 else: 915 else:
866 base_url = CHROMIUM_BASE_URL 916 base_url = CHROMIUM_BASE_URL
867 917
868 # Create the context. Initialize 0 for the revisions as they are set below. 918 # Create the context. Initialize 0 for the revisions as they are set below.
869 context = PathContext(base_url, opts.archive, 0, 0, 919 context = PathContext(base_url, opts.archive, 0, 0,
870 opts.official_builds, opts.aura, None) 920 opts.official_builds, opts.aura, opts.use_local_repo,
921 None)
871 # Pick a starting point, try to get HEAD for this. 922 # Pick a starting point, try to get HEAD for this.
872 if opts.bad: 923 if opts.bad:
873 bad_rev = opts.bad 924 bad_rev = opts.bad
874 else: 925 else:
875 bad_rev = '999.0.0.0' 926 bad_rev = '999.0.0.0'
876 if not opts.official_builds: 927 if not opts.official_builds:
877 bad_rev = GetChromiumRevision(context, context.GetLastChangeURL()) 928 bad_rev = GetChromiumRevision(context, context.GetLastChangeURL())
878 929
879 # Find out when we were good. 930 # Find out when we were good.
880 if opts.good: 931 if opts.good:
(...skipping 13 matching lines...) Expand all
894 good_rev = int(good_rev) 945 good_rev = int(good_rev)
895 bad_rev = int(bad_rev) 946 bad_rev = int(bad_rev)
896 947
897 if opts.times < 1: 948 if opts.times < 1:
898 print('Number of times to run (%d) must be greater than or equal to 1.' % 949 print('Number of times to run (%d) must be greater than or equal to 1.' %
899 opts.times) 950 opts.times)
900 parser.print_help() 951 parser.print_help()
901 return 1 952 return 1
902 953
903 (min_chromium_rev, max_chromium_rev) = Bisect( 954 (min_chromium_rev, max_chromium_rev) = Bisect(
904 base_url, opts.archive, opts.official_builds, opts.aura, good_rev, 955 base_url, opts.archive, opts.official_builds, opts.aura,
905 bad_rev, opts.times, opts.command, args, opts.profile, opts.flash_path, 956 opts.use_local_repo, good_rev, bad_rev, opts.times, opts.command,
906 not opts.not_interactive) 957 args, opts.profile, opts.flash_path, not opts.not_interactive)
907 958
908 # Get corresponding blink revisions. 959 # Get corresponding blink revisions.
909 try: 960 try:
910 min_blink_rev = GetBlinkRevisionForChromiumRevision(context, 961 min_blink_rev = GetBlinkRevisionForChromiumRevision(context,
911 min_chromium_rev) 962 min_chromium_rev)
912 max_blink_rev = GetBlinkRevisionForChromiumRevision(context, 963 max_blink_rev = GetBlinkRevisionForChromiumRevision(context,
913 max_chromium_rev) 964 max_chromium_rev)
914 except Exception, e: 965 except Exception, e:
915 # Silently ignore the failure. 966 # Silently ignore the failure.
916 min_blink_rev, max_blink_rev = 0, 0 967 min_blink_rev, max_blink_rev = 0, 0
(...skipping 21 matching lines...) Expand all
938 "you might also want to do a Blink bisect.") 989 "you might also want to do a Blink bisect.")
939 990
940 print 'CHANGELOG URL:' 991 print 'CHANGELOG URL:'
941 if opts.official_builds: 992 if opts.official_builds:
942 print OFFICIAL_CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) 993 print OFFICIAL_CHANGELOG_URL % (min_chromium_rev, max_chromium_rev)
943 else: 994 else:
944 print ' ' + CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) 995 print ' ' + CHANGELOG_URL % (min_chromium_rev, max_chromium_rev)
945 996
946 if __name__ == '__main__': 997 if __name__ == '__main__':
947 sys.exit(main()) 998 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698