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

Side by Side Diff: build/build-bisect.py

Issue 201023: Make the build-bisect tool work with non-Mac archives. (Closed)
Patch Set: Created 11 years, 3 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
« 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/python2.5 1 #!/usr/bin/python2.5
2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2009 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 the Mac 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,
11 unzipping, and opening Chromium for you. After testing the specific revision, 11 unzipping, and opening Chromium for you. After testing the specific revision,
12 it will ask you whether it is good or bad before continuing the search. 12 it will ask you whether it is good or bad before continuing the search.
13
14 Currently this only works on Mac, but with some effort it could be ported to
15 other platforms.
16 """ 13 """
17 14
18 # Base URL to download snapshots from. 15 # Base URL to download snapshots from.
19 BUILD_BASE_URL = \ 16 BUILD_BASE_URL = "http://build.chromium.org/buildbot/snapshots/"
20 "http://build.chromium.org/buildbot/snapshots/chromium-rel-mac"
21 17
22 # Location of the latest build revision number 18 # The type (platform) of the build archive. This is what's passed in to the
23 BUILD_LATEST_URL = "%s/LATEST" % BUILD_BASE_URL 19 # '-a/--archive' option.
20 BUILD_ARCHIVE_TYPE = ''
21
22 # The selected archive to bisect.
23 BUILD_ARCHIVE_DIR = ''
24 24
25 # The location of the builds. 25 # The location of the builds.
26 BUILD_ARCHIVE_URL = "/%d/" 26 BUILD_ARCHIVE_URL = "/%d/"
27 27
28 # Name of the build archive. 28 # Name of the build archive.
29 BUILD_ZIP_NAME = "chrome-mac.zip" 29 BUILD_ZIP_NAME = ''
30 30
31 # Directory name inside the archive. 31 # Directory name inside the archive.
32 BUILD_DIR_NAME = "chrome-mac" 32 BUILD_DIR_NAME = ''
33 33
34 # Name of the executable. 34 # Name of the executable.
35 BUILD_EXE_NAME = "Chromium.app" 35 BUILD_EXE_NAME = ''
36 36
37 # URL to the ViewVC commit page. 37 # URL to the ViewVC commit page.
38 BUILD_VIEWVC_URL = "http://src.chromium.org/viewvc/chrome?view=rev&revision=%d" 38 BUILD_VIEWVC_URL = "http://src.chromium.org/viewvc/chrome?view=rev&revision=%d"
39 39
40 ############################################################################### 40 ###############################################################################
41 41
42 import math 42 import math
43 import optparse
43 import os 44 import os
44 import re 45 import re
45 import shutil 46 import shutil
46 import sys 47 import sys
48 import tempfile
47 import urllib 49 import urllib
48 50
51 def SetArchiveVars(archive):
52 """Set a bunch of global variables appropriate for the specified archive."""
53 global BUILD_ARCHIVE_TYPE
54 global BUILD_ARCHIVE_DIR
55 global BUILD_ZIP_NAME
56 global BUILD_DIR_NAME
57 global BUILD_EXE_NAME
58 global BUILD_BASE_URL
59
60 BUILD_ARCHIVE_TYPE = archive
61 BUILD_ARCHIVE_DIR = 'chromium-rel-' + BUILD_ARCHIVE_TYPE
62
63 if BUILD_ARCHIVE_TYPE in ('linux', 'linux-64'):
64 BUILD_ZIP_NAME = 'chrome-linux.zip'
65 BUILD_DIR_NAME = 'chrome-linux'
66 BUILD_EXE_NAME = "chrome"
67 elif BUILD_ARCHIVE_TYPE in ('mac'):
68 BUILD_ZIP_NAME = 'chrome-mac.zip'
69 BUILD_DIR_NAME = 'chrome-mac'
70 BUILD_EXE_NAME = "Chromium.app"
71 elif BUILD_ARCHIVE_TYPE in ('xp'):
72 BUILD_ZIP_NAME = 'chrome-win32.zip'
73 BUILD_DIR_NAME = 'chrome-win32'
74 BUILD_EXE_NAME = "chrome.exe"
75
76 BUILD_BASE_URL += BUILD_ARCHIVE_DIR
77
49 def ParseDirectoryIndex(url): 78 def ParseDirectoryIndex(url):
50 """Parses the HTML directory listing into a list of revision numbers.""" 79 """Parses the HTML directory listing into a list of revision numbers."""
51 handle = urllib.urlopen(url) 80 handle = urllib.urlopen(url)
52 dirindex = handle.read() 81 dirindex = handle.read()
53 handle.close() 82 handle.close()
54 return re.findall(r'<a href="([0-9]*)/">\1/</a>', dirindex) 83 return re.findall(r'<a href="([0-9]*)/">\1/</a>', dirindex)
55 84
56 def GetRevList(good, bad): 85 def GetRevList(good, bad):
57 """Gets the list of revision numbers between |good| and |bad|.""" 86 """Gets the list of revision numbers between |good| and |bad|."""
58 # Download the main revlist. 87 # Download the main revlist.
59 revlist = ParseDirectoryIndex(BUILD_BASE_URL) 88 revlist = ParseDirectoryIndex(BUILD_BASE_URL)
60 revlist = map(int, revlist) 89 revlist = map(int, revlist)
61 revlist = filter(lambda r: range(good, bad).__contains__(int(r)), revlist) 90 revlist = filter(lambda r: range(good, bad).__contains__(int(r)), revlist)
62 revlist.sort() 91 revlist.sort()
63 return revlist 92 return revlist
64 93
65 def TryRevision(rev): 94 def TryRevision(rev):
66 """Downloads revision |rev|, unzips it, and opens it for the user to test.""" 95 """Downloads revision |rev|, unzips it, and opens it for the user to test."""
67 # Clear anything that's currently there. 96 # Do this in a temp dir so we don't collide with user files.
68 try: 97 cwd = os.getcwd()
69 os.remove(BUILD_ZIP_NAME) 98 tempdir = tempfile.mkdtemp(prefix='bisect_tmp')
70 shutil.rmtree(BUILD_DIR_NAME, True) 99 os.chdir(tempdir)
71 except Exception, e:
72 pass
73 100
74 # Download the file. 101 # Download the file.
75 download_url = BUILD_BASE_URL + (BUILD_ARCHIVE_URL % rev) + BUILD_ZIP_NAME 102 download_url = BUILD_BASE_URL + (BUILD_ARCHIVE_URL % rev) + BUILD_ZIP_NAME
76 try: 103 try:
104 print 'Fetching ' + download_url
77 urllib.urlretrieve(download_url, BUILD_ZIP_NAME) 105 urllib.urlretrieve(download_url, BUILD_ZIP_NAME)
78 except Exception, e: 106 except Exception, e:
79 print("Could not retrieve the download. Sorry.") 107 print("Could not retrieve the download. Sorry.")
80 print("Tried to get: %s" % download_url)
81 sys.exit(-1) 108 sys.exit(-1)
82 109
83 # Unzip the file. 110 # Unzip the file.
111 print 'Unzipping ...'
84 os.system("unzip -q %s" % BUILD_ZIP_NAME) 112 os.system("unzip -q %s" % BUILD_ZIP_NAME)
85 113
86 # Tell Finder to open the app. 114 # Tell the system to open the app.
87 os.system("open %s/%s" % (BUILD_DIR_NAME, BUILD_EXE_NAME)) 115 print 'Running %s/%s/%s' % (os.getcwd(), BUILD_DIR_NAME, BUILD_EXE_NAME)
116 if BUILD_ARCHIVE_TYPE in ('linux', 'linux-64'):
117 os.system("%s/%s" % (BUILD_DIR_NAME, BUILD_EXE_NAME))
118 elif BUILD_ARCHIVE_TYPE in ('mac'):
119 os.system("open %s/%s" % (BUILD_DIR_NAME, BUILD_EXE_NAME))
120 elif BUILD_ARCHIVE_TYPE in ('xp'):
121 # TODO(mmoss) Does Windows need 'start' or something?
122 os.system("%s/%s" % (BUILD_DIR_NAME, BUILD_EXE_NAME))
123
124 os.chdir(cwd)
125 print 'Cleaning temp dir ...'
126 try:
127 shutil.rmtree(tempdir, True)
128 except Exception, e:
129 pass
88 130
89 def AskIsGoodBuild(rev): 131 def AskIsGoodBuild(rev):
90 """Annoyingly ask the user whether build |rev| is good or bad.""" 132 """Annoyingly ask the user whether build |rev| is good or bad."""
91 while True: 133 while True:
92 check = raw_input("Build %d [g/b]: " % int(rev))[0] 134 check = raw_input("\nBuild %d is [(g)ood/(b)ad]: " % int(rev))[0]
93 if (check == "g" or check == "b"): 135 if (check == "g" or check == "b"):
94 return (check == "g") 136 return (check == "g")
95 else: 137 else:
96 print("Just answer the question...") 138 print("Just answer the question...")
97 139
98 def main(): 140 def main():
99 print("chrome-bisect: Perform binary search on the snapshot builds") 141 usage = ('%prog [options]\n'
142 'Perform binary search on the snapshot builds.')
143 parser = optparse.OptionParser(usage=usage)
144 parser.add_option('-a', '--archive',
145 choices = ['mac', 'xp', 'linux', 'linux-64'],
146 help = 'The buildbot archive to bisect.')
147 parser.add_option('-b', '--bad', type = 'int',
148 help = 'The bad revision to bisect to.')
149 parser.add_option('-g', '--good', type = 'int',
150 help = 'The last known good revision to bisect from.')
151 (opts, args) = parser.parse_args()
152
153 if opts.archive is None:
154 parser.print_help()
155 return 1
156
157 if opts.bad and opts.good and (opts.good > opts.bad):
158 print ('The good revision (%d) must precede the bad revision (%d).\n' %
159 (opts.good, opts.bad))
160 parser.print_help()
161 return 1
162
163 SetArchiveVars(opts.archive)
100 164
101 # Pick a starting point, try to get HEAD for this. 165 # Pick a starting point, try to get HEAD for this.
102 bad_rev = 0 166 if opts.bad:
103 try: 167 bad_rev = opts.bad
104 nh = urllib.urlopen(BUILD_LATEST_URL) 168 else:
105 latest = int(nh.read()) 169 bad_rev = 0
106 nh.close() 170 try:
107 bad_rev = raw_input("Bad revision [HEAD:%d]: " % latest) 171 # Location of the latest build revision number
108 if (bad_rev == ""): 172 BUILD_LATEST_URL = "%s/LATEST" % (BUILD_BASE_URL)
109 bad_rev = latest 173 nh = urllib.urlopen(BUILD_LATEST_URL)
110 bad_rev = int(bad_rev) 174 latest = int(nh.read())
111 except Exception, e: 175 nh.close()
112 print("Could not determine latest revision. This could be bad...") 176 bad_rev = raw_input("Bad revision [HEAD:%d]: " % latest)
113 bad_rev = int(raw_input("Bad revision: ")) 177 if (bad_rev == ""):
178 bad_rev = latest
179 bad_rev = int(bad_rev)
180 except Exception, e:
181 print("Could not determine latest revision. This could be bad...")
182 bad_rev = int(raw_input("Bad revision: "))
114 183
115 # Find out when we were good. 184 # Find out when we were good.
116 good_rev = 0 185 if opts.good:
117 try: 186 good_rev = opts.good
118 good_rev = int(raw_input("Last known good [0]: ")) 187 else:
119 except Exception, e: 188 good_rev = 0
120 pass 189 try:
190 good_rev = int(raw_input("Last known good [0]: "))
191 except Exception, e:
192 pass
121 193
122 # Get a list of revisions to bisect across. 194 # Get a list of revisions to bisect across.
123 revlist = GetRevList(good_rev, bad_rev) 195 revlist = GetRevList(good_rev, bad_rev)
124 196
125 # If we don't have a |good_rev|, set it to be the first revision possible. 197 # If we don't have a |good_rev|, set it to be the first revision possible.
126 if good_rev == 0: 198 if good_rev == 0:
127 good_rev = revlist[0] 199 good_rev = revlist[0]
128 200
129 # These are indexes of |revlist|. 201 # These are indexes of |revlist|.
130 good = 0 202 good = 0
(...skipping 19 matching lines...) Expand all
150 good = test + 1 222 good = test + 1
151 else: 223 else:
152 bad = test 224 bad = test
153 225
154 # We're done. Let the user know the results in an official manner. 226 # We're done. Let the user know the results in an official manner.
155 print("You are probably looking for build %d." % revlist[bad]) 227 print("You are probably looking for build %d." % revlist[bad])
156 print("This is the ViewVC URL for the potential bustage:") 228 print("This is the ViewVC URL for the potential bustage:")
157 print(BUILD_VIEWVC_URL % revlist[bad]) 229 print(BUILD_VIEWVC_URL % revlist[bad])
158 230
159 if __name__ == '__main__': 231 if __name__ == '__main__':
160 main() 232 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