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

Side by Side Diff: tools/update_reference_build.py

Issue 33353002: Add option to download reference build from internal storage. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month 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 # 2 #
3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """Updates the Chrome reference builds. 7 """Updates the Chrome reference builds.
8 8
9 Use -r option to update a Chromium reference build, or -b option for Chrome 9 Use -r option to update a Chromium reference build, or -b option for Chrome
10 official builds. 10 official builds.
(...skipping 16 matching lines...) Expand all
27 import time 27 import time
28 import urllib 28 import urllib
29 import urllib2 29 import urllib2
30 import zipfile 30 import zipfile
31 31
32 # Example chromium build location: 32 # Example chromium build location:
33 # gs://chromium-browser-snapshots/Linux/228977/chrome-linux.zip 33 # gs://chromium-browser-snapshots/Linux/228977/chrome-linux.zip
34 CHROMIUM_URL_FMT = ('http://commondatastorage.googleapis.com/' 34 CHROMIUM_URL_FMT = ('http://commondatastorage.googleapis.com/'
35 'chromium-browser-snapshots/%s/%s/%s') 35 'chromium-browser-snapshots/%s/%s/%s')
36 36
37 # Example Chrome build location (no public wed URL's): 37 # Chrome official build storage
38 # https://wiki.corp.google.com/twiki/bin/view/Main/ChromeOfficialBuilds
39
40 # Internal Google archive of official Chrome builds, example:
41 # http://master.chrome.corp.google.com/official_builds/32.0.1677.0/precise32bit/
42 CHROME_INTERNAL_URL_FMT = ('http://master.chrome.corp.google.com/'
43 'official_builds/%s/%s/%s')
tonyg 2013/10/21 19:20:06 I'm not sure we should check in a corp url. Can we
shadi 2013/10/21 19:53:53 Done.
44
45 # Google storage location (no public web URL's), example:
38 # gs://chrome-archive/30/30.0.1595.0/precise32bit/chrome-precise32bit.zip 46 # gs://chrome-archive/30/30.0.1595.0/precise32bit/chrome-precise32bit.zip
39 CHROME_URL_FMT = ('gs://chrome-archive/%s/%s/%s/%s') 47 CHROME_GS_URL_FMT = ('gs://chrome-archive/%s/%s/%s/%s')
40 48
41 49
42 class BuildUpdater(object): 50 class BuildUpdater(object):
43 _PLATFORM_FILES_MAP = { 51 _PLATFORM_FILES_MAP = {
44 'Win': [ 52 'Win': [
45 'chrome-win32.zip', 53 'chrome-win32.zip',
46 'chrome-win32-syms.zip', 54 'chrome-win32-syms.zip',
47 ], 55 ],
48 'Mac': [ 56 'Mac': [
49 'chrome-mac.zip', 57 'chrome-mac.zip',
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 'Linux': 'chrome_linux', 92 'Linux': 'chrome_linux',
85 'Linux_x64': 'chrome_linux64', 93 'Linux_x64': 'chrome_linux64',
86 'Win': 'chrome_win', 94 'Win': 'chrome_win',
87 'Mac': 'chrome_mac', 95 'Mac': 'chrome_mac',
88 } 96 }
89 97
90 def __init__(self, options): 98 def __init__(self, options):
91 self._platforms = options.platforms.split(',') 99 self._platforms = options.platforms.split(',')
92 self._revision = options.build_number or int(options.revision) 100 self._revision = options.build_number or int(options.revision)
93 self._use_build_number = bool(options.build_number) 101 self._use_build_number = bool(options.build_number)
102 self._use_gs = options.use_gs
94 103
95 @staticmethod 104 @staticmethod
96 def _GetCmdStatusAndOutput(args, cwd=None, shell=False): 105 def _GetCmdStatusAndOutput(args, cwd=None, shell=False):
97 """Executes a subprocess and returns its exit code and output. 106 """Executes a subprocess and returns its exit code and output.
98 107
99 Args: 108 Args:
100 args: A string or a sequence of program arguments. 109 args: A string or a sequence of program arguments.
101 cwd: If not None, the subprocess's current directory will be changed to 110 cwd: If not None, the subprocess's current directory will be changed to
102 |cwd| before it's executed. 111 |cwd| before it's executed.
103 shell: Whether to execute args as a shell command. 112 shell: Whether to execute args as a shell command.
104 113
105 Returns: 114 Returns:
106 The tuple (exit code, output). 115 The tuple (exit code, output).
107 """ 116 """
108 logging.info(str(args) + ' ' + (cwd or '')) 117 logging.info(str(args) + ' ' + (cwd or ''))
109 p = subprocess.Popen(args=args, cwd=cwd, stdout=subprocess.PIPE, 118 p = subprocess.Popen(args=args, cwd=cwd, stdout=subprocess.PIPE,
110 stderr=subprocess.PIPE, shell=shell) 119 stderr=subprocess.PIPE, shell=shell)
111 stdout, stderr = p.communicate() 120 stdout, stderr = p.communicate()
112 exit_code = p.returncode 121 exit_code = p.returncode
113 if stderr: 122 if stderr:
114 logging.critical(stderr) 123 logging.critical(stderr)
115 logging.info(stdout) 124 logging.info(stdout)
116 return (exit_code, stdout) 125 return (exit_code, stdout)
117 126
118 def _GetBuildUrl(self, platform, revision, filename): 127 def _GetBuildUrl(self, platform, revision, filename):
119 if self._use_build_number: 128 if self._use_build_number:
120 release = revision[:revision.find('.')] 129 # Chrome Google storage bucket.
121 return (CHROME_URL_FMT % 130 if self._use_gs:
122 (release, revision, self._BUILD_PLATFORM_MAP[platform], filename)) 131 release = revision[:revision.find('.')]
132 return (CHROME_GS_URL_FMT % (
133 release,
134 revision,
135 self._BUILD_PLATFORM_MAP[platform],
136 filename))
137 # Chrome internal archive.
138 return (CHROME_INTERNAL_URL_FMT % (
139 revision,
140 self._BUILD_PLATFORM_MAP[platform],
141 filename))
142 # Chromium archive.
123 return CHROMIUM_URL_FMT % (urllib.quote_plus(platform), revision, filename) 143 return CHROMIUM_URL_FMT % (urllib.quote_plus(platform), revision, filename)
124 144
125 def _FindBuildRevision(self, platform, revision, filename): 145 def _FindBuildRevision(self, platform, revision, filename):
126 # TODO(shadi): Iterate over build numbers to find a valid one. 146 # TODO(shadi): Iterate over build numbers to find a valid one.
127 if self._use_build_number: 147 if self._use_build_number:
128 return (revision 148 return (revision
129 if self._DoesChromeBuildExist(platform, revision, filename) else 149 if self._DoesBuildExist(platform, revision, filename) else None)
130 None)
131 150
132 MAX_REVISIONS_PER_BUILD = 100 151 MAX_REVISIONS_PER_BUILD = 100
133 for revision_guess in xrange(revision, revision + MAX_REVISIONS_PER_BUILD): 152 for revision_guess in xrange(revision, revision + MAX_REVISIONS_PER_BUILD):
134 if self._DoesChromiumBuildExist(platform, revision_guess, filename): 153 if self._DoesBuildExist(platform, revision_guess, filename):
135 return revision_guess 154 return revision_guess
136 else: 155 else:
137 time.sleep(.1) 156 time.sleep(.1)
138 return None 157 return None
139 158
140 def _DoesChromiumBuildExist(self, platform, build_number, filename): 159 def _DoesBuildExist(self, platform, build_number, filename):
141 url = self._GetBuildUrl(platform, build_number, filename) 160 url = self._GetBuildUrl(platform, build_number, filename)
161 if self._use_gs:
162 return self._DoesGSFileExist(url)
163
142 r = urllib2.Request(url) 164 r = urllib2.Request(url)
143 r.get_method = lambda: 'HEAD' 165 r.get_method = lambda: 'HEAD'
144 try: 166 try:
145 urllib2.urlopen(r) 167 urllib2.urlopen(r)
146 return True 168 return True
147 except urllib2.HTTPError, err: 169 except urllib2.HTTPError, err:
148 if err.code == 404: 170 if err.code == 404:
149 return False 171 return False
150 172
151 def _DoesChromeBuildExist(self, platform, build_number, filename): 173 def _DoesGSFileExist(self, gs_file_name):
152 release = build_number[:build_number.find('.')]
153 gs_file = (CHROME_URL_FMT %
154 (release,
155 build_number,
156 self._BUILD_PLATFORM_MAP[platform],
157 filename))
158 (exit_code, stdout) = BuildUpdater._GetCmdStatusAndOutput( 174 (exit_code, stdout) = BuildUpdater._GetCmdStatusAndOutput(
159 ['gsutil', 'ls', gs_file]) 175 ['gsutil', 'ls', gs_file_name])
160
161 return not exit_code 176 return not exit_code
162 177
163 def _GetPlatformFiles(self, platform): 178 def _GetPlatformFiles(self, platform):
164 if self._use_build_number: 179 if self._use_build_number:
165 return BuildUpdater._CHROME_PLATFORM_FILES_MAP[platform] 180 return BuildUpdater._CHROME_PLATFORM_FILES_MAP[platform]
166 return BuildUpdater._PLATFORM_FILES_MAP[platform] 181 return BuildUpdater._PLATFORM_FILES_MAP[platform]
167 182
168 def _DownloadBuilds(self): 183 def _DownloadBuilds(self):
169 for platform in self._platforms: 184 for platform in self._platforms:
170 for f in self._GetPlatformFiles(platform): 185 for f in self._GetPlatformFiles(platform):
171 output = os.path.join('dl', platform, 186 output = os.path.join('dl', platform,
172 '%s_%s_%s' % (platform, self._revision, f)) 187 '%s_%s_%s' % (platform, self._revision, f))
173 if os.path.exists(output): 188 if os.path.exists(output):
174 logging.info('%s alread exists, skipping download' % output) 189 logging.info('%s alread exists, skipping download', output)
175 continue 190 continue
176 build_revision = self._FindBuildRevision(platform, self._revision, f) 191 build_revision = self._FindBuildRevision(platform, self._revision, f)
177 if not build_revision: 192 if not build_revision:
178 logging.critical('Failed to find %s build for r%s\n' % ( 193 logging.critical('Failed to find %s build for r%s\n', platform,
179 platform, self._revision)) 194 self._revision)
180 sys.exit(1) 195 sys.exit(1)
181 dirname = os.path.dirname(output) 196 dirname = os.path.dirname(output)
182 if dirname and not os.path.exists(dirname): 197 if dirname and not os.path.exists(dirname):
183 os.makedirs(dirname) 198 os.makedirs(dirname)
184 url = self._GetBuildUrl(platform, build_revision, f) 199 url = self._GetBuildUrl(platform, build_revision, f)
185 self._DownloadFile(url, output) 200 self._DownloadFile(url, output)
186 201
187 def _DownloadFile(self, url, output): 202 def _DownloadFile(self, url, output):
188 logging.info('Downloading %s, saving to %s' % (url, output)) 203 logging.info('Downloading %s, saving to %s', url, output)
189 if self._use_build_number: 204 if self._use_build_number and self._use_gs:
190 BuildUpdater._GetCmdStatusAndOutput(['gsutil', 'cp', url, output]) 205 BuildUpdater._GetCmdStatusAndOutput(['gsutil', 'cp', url, output])
191 else: 206 else:
192 r = urllib2.urlopen(url) 207 r = urllib2.urlopen(url)
193 with file(output, 'wb') as f: 208 with file(output, 'wb') as f:
194 f.write(r.read()) 209 f.write(r.read())
195 210
196 def _FetchSvnRepos(self): 211 def _FetchSvnRepos(self):
197 if not os.path.exists('reference_builds'): 212 if not os.path.exists('reference_builds'):
198 os.makedirs('reference_builds') 213 os.makedirs('reference_builds')
199 BuildUpdater._GetCmdStatusAndOutput( 214 BuildUpdater._GetCmdStatusAndOutput(
200 ['gclient', 'config', 215 ['gclient', 'config',
201 'svn://svn.chromium.org/chrome/trunk/deps/reference_builds'], 216 'svn://svn.chromium.org/chrome/trunk/deps/reference_builds'],
202 'reference_builds') 217 'reference_builds')
203 BuildUpdater._GetCmdStatusAndOutput( 218 BuildUpdater._GetCmdStatusAndOutput(
204 ['gclient', 'sync'], 'reference_builds') 219 ['gclient', 'sync'], 'reference_builds')
205 220
206 def _UnzipFile(self, dl_file, dest_dir): 221 def _UnzipFile(self, dl_file, dest_dir):
207 if not zipfile.is_zipfile(dl_file): 222 if not zipfile.is_zipfile(dl_file):
208 return False 223 return False
209 logging.info('Opening %s' % dl_file) 224 logging.info('Opening %s', dl_file)
210 with zipfile.ZipFile(dl_file, 'r') as z: 225 with zipfile.ZipFile(dl_file, 'r') as z:
211 for content in z.namelist(): 226 for content in z.namelist():
212 dest = os.path.join(dest_dir, content[content.find('/')+1:]) 227 dest = os.path.join(dest_dir, content[content.find('/')+1:])
213 # Create dest parent dir if it does not exist. 228 # Create dest parent dir if it does not exist.
214 if not os.path.isdir(os.path.dirname(dest)): 229 if not os.path.isdir(os.path.dirname(dest)):
215 os.makedirs(os.path.dirname(dest)) 230 os.makedirs(os.path.dirname(dest))
216 # If dest is just a dir listing, do nothing. 231 # If dest is just a dir listing, do nothing.
217 if not os.path.basename(dest): 232 if not os.path.basename(dest):
218 continue 233 continue
219 with z.open(content) as unzipped_content: 234 with z.open(content) as unzipped_content:
220 logging.info('Extracting %s to %s (%s)' % (content, dest, dl_file)) 235 logging.info('Extracting %s to %s (%s)', content, dest, dl_file)
221 with file(dest, 'wb') as dest_file: 236 with file(dest, 'wb') as dest_file:
222 dest_file.write(unzipped_content.read()) 237 dest_file.write(unzipped_content.read())
223 permissions = z.getinfo(content).external_attr >> 16 238 permissions = z.getinfo(content).external_attr >> 16
224 if permissions: 239 if permissions:
225 os.chmod(dest, permissions) 240 os.chmod(dest, permissions)
226 return True 241 return True
227 242
228 def _ClearDir(self, dir): 243 def _ClearDir(self, dir):
229 """Clears all files in |dir| except for hidden files and folders.""" 244 """Clears all files in |dir| except for hidden files and folders."""
230 for root, dirs, files in os.walk(dir): 245 for root, dirs, files in os.walk(dir):
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 self._ExtractBuilds() 286 self._ExtractBuilds()
272 self._SvnAddAndRemove() 287 self._SvnAddAndRemove()
273 288
274 289
275 def ParseOptions(argv): 290 def ParseOptions(argv):
276 parser = optparse.OptionParser() 291 parser = optparse.OptionParser()
277 usage = 'usage: %prog <options>' 292 usage = 'usage: %prog <options>'
278 parser.set_usage(usage) 293 parser.set_usage(usage)
279 parser.add_option('-b', dest='build_number', 294 parser.add_option('-b', dest='build_number',
280 help='Chrome official build number to pick up.') 295 help='Chrome official build number to pick up.')
281 parser.add_option('-r', dest='revision', 296 parser.add_option('--gs', dest='use_gs', action='store_true', default=False,
282 help='Revision to pick up.') 297 help='Use Google storage for official builds. Used with -b '
298 'option. Default is false (i.e. use internal storage.')
283 parser.add_option('-p', dest='platforms', 299 parser.add_option('-p', dest='platforms',
284 default='Win,Mac,Linux,Linux_x64', 300 default='Win,Mac,Linux,Linux_x64',
285 help='Comma separated list of platforms to download ' 301 help='Comma separated list of platforms to download '
286 '(as defined by the chromium builders).') 302 '(as defined by the chromium builders).')
303 parser.add_option('-r', dest='revision',
304 help='Revision to pick up.')
305
287 (options, _) = parser.parse_args(argv) 306 (options, _) = parser.parse_args(argv)
288 if not options.revision and not options.build_number: 307 if not options.revision and not options.build_number:
289 logging.critical('Must specify either -r or -b.\n') 308 logging.critical('Must specify either -r or -b.\n')
290 sys.exit(1) 309 sys.exit(1)
291 if options.revision and options.build_number: 310 if options.revision and options.build_number:
292 logging.critical('Must specify either -r or -b but not both.\n') 311 logging.critical('Must specify either -r or -b but not both.\n')
293 sys.exit(1) 312 sys.exit(1)
313 if options.use_gs and not options.build_number:
314 logging.critical('Can only use --gs with -b option.\n')
315 sys.exit(1)
294 316
295 return options 317 return options
296 318
297 319
298 def main(argv): 320 def main(argv):
299 logging.getLogger().setLevel(logging.DEBUG) 321 logging.getLogger().setLevel(logging.DEBUG)
300 options = ParseOptions(argv) 322 options = ParseOptions(argv)
301 b = BuildUpdater(options) 323 b = BuildUpdater(options)
302 b.DownloadAndUpdateBuilds() 324 b.DownloadAndUpdateBuilds()
303 logging.info('Successfully updated reference builds. Move to ' 325 logging.info('Successfully updated reference builds. Move to '
304 'reference_builds/reference_builds and make a change with gcl.') 326 'reference_builds/reference_builds and make a change with gcl.')
305 327
306 if __name__ == '__main__': 328 if __name__ == '__main__':
307 sys.exit(main(sys.argv)) 329 sys.exit(main(sys.argv))
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