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

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 self.use_local_repo = use_local_repo
Robert Sesek 2014/07/08 18:52:58 nit: blank line before and a comment about what th
pshenoy 2014/07/08 19:58:19 Done.
100 101
101 # Set some internal members: 102 # Set some internal members:
102 # _listing_platform_dir = Directory that holds revisions. Ends with a '/'. 103 # _listing_platform_dir = Directory that holds revisions. Ends with a '/'.
103 # _archive_extract_dir = Uncompressed directory in the archive_name file. 104 # _archive_extract_dir = Uncompressed directory in the archive_name file.
104 # _binary_name = The name of the executable to run. 105 # _binary_name = The name of the executable to run.
105 if self.platform in ('linux', 'linux64', 'linux-arm'): 106 if self.platform in ('linux', 'linux64', 'linux-arm'):
106 self._binary_name = 'chrome' 107 self._binary_name = 'chrome'
107 elif self.platform == 'mac': 108 elif self.platform == 'mac':
108 self.archive_name = 'chrome-mac.zip' 109 self.archive_name = 'chrome-mac.zip'
109 self._archive_extract_dir = 'chrome-mac' 110 self._archive_extract_dir = 'chrome-mac'
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 _FetchAndParse(self.GetListingURL()) 247 _FetchAndParse(self.GetListingURL())
247 # If the result list was truncated, refetch with the next marker. Do this 248 # If the result list was truncated, refetch with the next marker. Do this
248 # until an entire directory listing is done. 249 # until an entire directory listing is done.
249 while next_marker: 250 while next_marker:
250 next_url = self.GetListingURL(next_marker) 251 next_url = self.GetListingURL(next_marker)
251 (new_revisions, next_marker, new_dict) = _FetchAndParse(next_url) 252 (new_revisions, next_marker, new_dict) = _FetchAndParse(next_url)
252 revisions.extend(new_revisions) 253 revisions.extend(new_revisions)
253 self.githash_svn_dict.update(new_dict) 254 self.githash_svn_dict.update(new_dict)
254 return revisions 255 return revisions
255 256
256 def GetSVNRevisionFromGitHash(self, git_sha1, depot='chromium'): 257 def _GetSVNRevisionFromGitHashWithoutGitCheckout(self, git_sha1, depot):
257 json_url = GITHASH_TO_SVN_URL[depot] % git_sha1 258 json_url = GITHASH_TO_SVN_URL[depot] % git_sha1
258 try: 259 try:
259 response = urllib.urlopen(json_url) 260 response = urllib.urlopen(json_url)
260 except urllib.HTTPError as error: 261 except urllib.HTTPError as error:
261 msg = 'HTTP Error %d for %s' % (error.getcode(), git_sha1) 262 msg = 'HTTP Error %d for %s' % (error.getcode(), git_sha1)
262 return None 263 return None
263 data = json.loads(response.read()[4:]) 264 data = json.loads(response.read()[4:])
264 if 'message' in data: 265 if 'message' in data:
265 message = data['message'].split('\n') 266 message = data['message'].split('\n')
266 message = [line for line in message if line.strip()] 267 message = [line for line in message if line.strip()]
267 search_pattern = re.compile(SEARCH_PATTERN[depot]) 268 search_pattern = re.compile(SEARCH_PATTERN[depot])
268 result = search_pattern.search(message[len(message)-1]) 269 result = search_pattern.search(message[len(message)-1])
269 if result: 270 if result:
270 return result.group(1) 271 return result.group(1)
271 print 'Failed to get svn revision number for %s' % git_sha1 272 print 'Failed to get svn revision number for %s' % git_sha1
272 return None 273 return None
273 274
275 def _GetSVNRevisionFromGitHashFromGitCheckout(self, git_sha1, depot):
276 def _RunGit(command, path):
277 command = ['git'] + command
278 if path:
279 original_path = os.getcwd()
280 os.chdir(path)
281 shell = sys.platform.startswith('win')
282 proc = subprocess.Popen(command, shell=shell, stdout=subprocess.PIPE,
283 stderr=subprocess.PIPE)
284 (output, _) = proc.communicate()
285
286 if path:
287 os.chdir(original_path)
288 return (output, proc.returncode)
289
290 path = None
291 if depot == 'blink':
292 path = os.path.join(os.getcwd(), 'third_party', 'WebKit')
293 if os.path.basename(os.getcwd()) == 'src':
294 command = []
295 command.append('svn')
Robert Sesek 2014/07/08 18:52:58 Why .append() these things? command = ['svn', 'fin
pshenoy 2014/07/08 19:58:19 Done.
296 command.append('find-rev')
297 command.append(git_sha1)
298 (git_output, return_code) = _RunGit(command, path)
299 if not return_code:
300 return git_output.strip('\n')
301 return None
302 else:
303 print ('Script should be run from src folder. ' +
304 'Eg: python tools/bisect-builds.py -g 280588 -b 280590' +
305 '--archive linux64 --git')
Robert Sesek 2014/07/08 18:52:58 --use-local-repo
pshenoy 2014/07/08 19:58:19 Done.
306 sys.exit(0)
Robert Sesek 2014/07/08 18:52:58 Code 1 for errors
pshenoy 2014/07/08 19:58:19 Done.
307
308 def GetSVNRevisionFromGitHash(self, git_sha1, depot='chromium'):
309 if not self.use_local_repo:
310 return self._GetSVNRevisionFromGitHashWithoutGitCheckout(git_sha1, depot)
311 else:
312 return self._GetSVNRevisionFromGitHashFromGitCheckout(git_sha1, depot)
313
274 def GetRevList(self): 314 def GetRevList(self):
275 """Gets the list of revision numbers between self.good_revision and 315 """Gets the list of revision numbers between self.good_revision and
276 self.bad_revision.""" 316 self.bad_revision."""
277 # Download the revlist and filter for just the range between good and bad. 317 # Download the revlist and filter for just the range between good and bad.
278 minrev = min(self.good_revision, self.bad_revision) 318 minrev = min(self.good_revision, self.bad_revision)
279 maxrev = max(self.good_revision, self.bad_revision) 319 maxrev = max(self.good_revision, self.bad_revision)
280 revlist_all = map(int, self.ParseDirectoryIndex()) 320 revlist_all = map(int, self.ParseDirectoryIndex())
281 321
282 revlist = [x for x in revlist_all if x >= int(minrev) and x <= int(maxrev)] 322 revlist = [x for x in revlist_all if x >= int(minrev) and x <= int(maxrev)]
283 revlist.sort() 323 revlist.sort()
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 must have been started previously.""" 546 must have been started previously."""
507 print "Downloading revision %s..." % str(self.rev) 547 print "Downloading revision %s..." % str(self.rev)
508 self.progress_event.set() # Display progress of download. 548 self.progress_event.set() # Display progress of download.
509 self.thread.join() 549 self.thread.join()
510 550
511 551
512 def Bisect(base_url, 552 def Bisect(base_url,
513 platform, 553 platform,
514 official_builds, 554 official_builds,
515 is_aura, 555 is_aura,
556 use_local_repo,
516 good_rev=0, 557 good_rev=0,
517 bad_rev=0, 558 bad_rev=0,
518 num_runs=1, 559 num_runs=1,
519 command="%p %a", 560 command="%p %a",
520 try_args=(), 561 try_args=(),
521 profile=None, 562 profile=None,
522 flash_path=None, 563 flash_path=None,
523 interactive=True, 564 interactive=True,
524 evaluate=AskIsGoodBuild): 565 evaluate=AskIsGoodBuild):
525 """Given known good and known bad revisions, run a binary search on all 566 """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. 590 is run on rev 75.
550 591
551 - If rev 50 is bad, the download of rev 75 is cancelled, and the next test 592 - If rev 50 is bad, the download of rev 75 is cancelled, and the next test
552 is run on rev 25. 593 is run on rev 25.
553 """ 594 """
554 595
555 if not profile: 596 if not profile:
556 profile = 'profile' 597 profile = 'profile'
557 598
558 context = PathContext(base_url, platform, good_rev, bad_rev, 599 context = PathContext(base_url, platform, good_rev, bad_rev,
559 official_builds, is_aura, flash_path) 600 official_builds, is_aura, use_local_repo, flash_path)
560 cwd = os.getcwd() 601 cwd = os.getcwd()
561 602
562 print "Downloading list of known revisions..." 603 print "Downloading list of known revisions..."
563 _GetDownloadPath = lambda rev: os.path.join(cwd, 604 _GetDownloadPath = lambda rev: os.path.join(cwd,
564 '%s-%s' % (str(rev), context.archive_name)) 605 '%s-%s' % (str(rev), context.archive_name))
565 if official_builds: 606 if official_builds:
566 revlist = context.GetOfficialBuildsList() 607 revlist = context.GetOfficialBuildsList()
567 else: 608 else:
568 revlist = context.GetRevList() 609 revlist = context.GetRevList()
569 610
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 parser.add_option('-l', '--blink', action='store_true', 879 parser.add_option('-l', '--blink', action='store_true',
839 help = 'Use Blink bisect instead of Chromium. ') 880 help = 'Use Blink bisect instead of Chromium. ')
840 parser.add_option('', '--not-interactive', action='store_true', 881 parser.add_option('', '--not-interactive', action='store_true',
841 help = 'Use command exit code to tell good/bad revision.', 882 help = 'Use command exit code to tell good/bad revision.',
842 default=False) 883 default=False)
843 parser.add_option('--aura', 884 parser.add_option('--aura',
844 dest='aura', 885 dest='aura',
845 action='store_true', 886 action='store_true',
846 default=False, 887 default=False,
847 help='Allow the script to bisect aura builds') 888 help='Allow the script to bisect aura builds')
889 parser.add_option('--use-local-repo',
890 dest='use_local_repo',
891 action='store_true',
892 default=False,
893 help='Allow the script to convert git SHA1 to SVN ' +
894 'revision using "git svn find-rev <SHA1>" ' +
895 'command.')
Robert Sesek 2014/07/08 18:52:58 "from a Chromium checkout."
pshenoy 2014/07/08 19:58:19 Done.
848 896
849 (opts, args) = parser.parse_args() 897 (opts, args) = parser.parse_args()
850 898
851 if opts.archive is None: 899 if opts.archive is None:
852 print 'Error: missing required parameter: --archive' 900 print 'Error: missing required parameter: --archive'
853 print 901 print
854 parser.print_help() 902 parser.print_help()
855 return 1 903 return 1
856 904
857 if opts.aura: 905 if opts.aura:
858 if opts.archive != 'win' or not opts.official_builds: 906 if opts.archive != 'win' or not opts.official_builds:
859 print 'Error: Aura is supported only on Windows platform '\ 907 print 'Error: Aura is supported only on Windows platform '\
860 'and official builds.' 908 'and official builds.'
861 return 1 909 return 1
862 910
863 if opts.blink: 911 if opts.blink:
864 base_url = WEBKIT_BASE_URL 912 base_url = WEBKIT_BASE_URL
865 else: 913 else:
866 base_url = CHROMIUM_BASE_URL 914 base_url = CHROMIUM_BASE_URL
867 915
868 # Create the context. Initialize 0 for the revisions as they are set below. 916 # Create the context. Initialize 0 for the revisions as they are set below.
869 context = PathContext(base_url, opts.archive, 0, 0, 917 context = PathContext(base_url, opts.archive, 0, 0,
870 opts.official_builds, opts.aura, None) 918 opts.official_builds, opts.aura, opts.use_local_repo,
919 None)
871 # Pick a starting point, try to get HEAD for this. 920 # Pick a starting point, try to get HEAD for this.
872 if opts.bad: 921 if opts.bad:
873 bad_rev = opts.bad 922 bad_rev = opts.bad
874 else: 923 else:
875 bad_rev = '999.0.0.0' 924 bad_rev = '999.0.0.0'
876 if not opts.official_builds: 925 if not opts.official_builds:
877 bad_rev = GetChromiumRevision(context, context.GetLastChangeURL()) 926 bad_rev = GetChromiumRevision(context, context.GetLastChangeURL())
878 927
879 # Find out when we were good. 928 # Find out when we were good.
880 if opts.good: 929 if opts.good:
(...skipping 13 matching lines...) Expand all
894 good_rev = int(good_rev) 943 good_rev = int(good_rev)
895 bad_rev = int(bad_rev) 944 bad_rev = int(bad_rev)
896 945
897 if opts.times < 1: 946 if opts.times < 1:
898 print('Number of times to run (%d) must be greater than or equal to 1.' % 947 print('Number of times to run (%d) must be greater than or equal to 1.' %
899 opts.times) 948 opts.times)
900 parser.print_help() 949 parser.print_help()
901 return 1 950 return 1
902 951
903 (min_chromium_rev, max_chromium_rev) = Bisect( 952 (min_chromium_rev, max_chromium_rev) = Bisect(
904 base_url, opts.archive, opts.official_builds, opts.aura, good_rev, 953 base_url, opts.archive, opts.official_builds, opts.aura,
905 bad_rev, opts.times, opts.command, args, opts.profile, opts.flash_path, 954 opts.use_local_repo, good_rev, bad_rev, opts.times, opts.command,
906 not opts.not_interactive) 955 args, opts.profile, opts.flash_path, not opts.not_interactive)
907 956
908 # Get corresponding blink revisions. 957 # Get corresponding blink revisions.
909 try: 958 try:
910 min_blink_rev = GetBlinkRevisionForChromiumRevision(context, 959 min_blink_rev = GetBlinkRevisionForChromiumRevision(context,
911 min_chromium_rev) 960 min_chromium_rev)
912 max_blink_rev = GetBlinkRevisionForChromiumRevision(context, 961 max_blink_rev = GetBlinkRevisionForChromiumRevision(context,
913 max_chromium_rev) 962 max_chromium_rev)
914 except Exception, e: 963 except Exception, e:
915 # Silently ignore the failure. 964 # Silently ignore the failure.
916 min_blink_rev, max_blink_rev = 0, 0 965 min_blink_rev, max_blink_rev = 0, 0
(...skipping 21 matching lines...) Expand all
938 "you might also want to do a Blink bisect.") 987 "you might also want to do a Blink bisect.")
939 988
940 print 'CHANGELOG URL:' 989 print 'CHANGELOG URL:'
941 if opts.official_builds: 990 if opts.official_builds:
942 print OFFICIAL_CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) 991 print OFFICIAL_CHANGELOG_URL % (min_chromium_rev, max_chromium_rev)
943 else: 992 else:
944 print ' ' + CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) 993 print ' ' + CHANGELOG_URL % (min_chromium_rev, max_chromium_rev)
945 994
946 if __name__ == '__main__': 995 if __name__ == '__main__':
947 sys.exit(main()) 996 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