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

Side by Side Diff: tools/update_reference_build.py

Issue 502593002: Update the update_reference_builds script. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Make version required Created 6 years, 4 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 # 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 To update Chromium (unofficial) reference build, use the -r option and give a
10 Chromium SVN revision number, like 228977. To update a Chrome (official) build,
11 use the -v option and give a Chrome version number like 30.0.1595.0.
12
13 If you're getting a Chrome build, you can give the flag --gs to fetch from
14 Google Storage. Otherwise, it will be fetched from go/chrome_official_builds.
15
16 Before running this script, you should first verify that you are authenticated 9 Before running this script, you should first verify that you are authenticated
17 for SVN. You can do this by running: 10 for SVN. You can do this by running:
18 $ svn ls svn://svn.chromium.org/chrome/trunk/deps/reference_builds 11 $ svn ls svn://svn.chromium.org/chrome/trunk/deps/reference_builds
19 You may need to get your SVN password from https://chromium-access.appspot.com/. 12 You may need to get your SVN password from https://chromium-access.appspot.com/.
20 13
21 Usage: 14 Usage:
22 $ cd /tmp 15 $ cd /tmp
23 $ /path/to/update_reference_build.py --gs -v <version> 16 $ /path/to/update_reference_build.py VERSION # e.g. 37.0.2062.94
24 $ cd reference_builds/reference_builds 17 $ cd reference_builds/reference_builds
25 $ gcl change 18 $ gcl change
26 $ gcl upload <change> 19 $ gcl upload <change>
27 $ gcl commit <change> 20 $ gcl commit <change>
28 """ 21 """
29 22
30 import logging 23 import logging
31 import optparse 24 import optparse
32 import os 25 import os
33 import shutil 26 import shutil
34 import subprocess 27 import subprocess
35 import sys 28 import sys
36 import time 29 import time
37 import urllib 30 import urllib
38 import urllib2 31 import urllib2
39 import zipfile 32 import zipfile
40 33
41 # Example chromium build location:
42 # gs://chromium-browser-snapshots/Linux/228977/chrome-linux.zip
43 CHROMIUM_URL_FMT = ('http://commondatastorage.googleapis.com/'
44 'chromium-browser-snapshots/%s/%s/%s')
45
46 # Chrome official build storage
47 # https://wiki.corp.google.com/twiki/bin/view/Main/ChromeOfficialBuilds
48
49 # Internal Google archive of official Chrome builds, example:
50 # https://goto.google.com/chrome_official_builds/
51 # 32.0.1677.0/precise32bit/chrome-precise32bit.zip
52 CHROME_INTERNAL_URL_FMT = ('http://master.chrome.corp.google.com/'
53 'official_builds/%s/%s/%s')
54 34
55 # Google storage location (no public web URL's), example: 35 # Google storage location (no public web URL's), example:
56 # gs://chrome-archive/30/30.0.1595.0/precise32bit/chrome-precise32bit.zip 36 # gs://chrome-unsigned/desktop-*/30.0.1595.0/precise32/chrome-precise32.zip
57 CHROME_GS_URL_FMT = ('gs://chrome-archive/%s/%s/%s/%s') 37 CHROME_GS_URL_FMT = ('gs://chrome-unsigned/desktop-*/%s/%s/%s')
58 38
59 39
60 class BuildUpdater(object): 40 class BuildUpdater(object):
61 _PLATFORM_FILES_MAP = { 41 _CHROME_PLATFORM_FILES_MAP = {
62 'Win': [ 42 'Win': [
63 'chrome-win32.zip', 43 'chrome-win.zip',
64 'chrome-win32-syms.zip',
65 ], 44 ],
66 'Mac': [ 45 'Mac': [
67 'chrome-mac.zip', 46 'chrome-mac.zip',
68 ], 47 ],
69 'Linux': [ 48 'Linux': [
70 'chrome-linux.zip', 49 'chrome-precise32.zip',
71 ], 50 ],
72 'Linux_x64': [ 51 'Linux_x64': [
73 'chrome-linux.zip', 52 'chrome-precise64.zip',
74 ],
75 }
76
77 _CHROME_PLATFORM_FILES_MAP = {
78 'Win': [
79 'chrome-win32.zip',
80 'chrome-win32-syms.zip',
81 ],
82 'Mac': [
83 'chrome-mac.zip',
84 ],
85 'Linux': [
86 'chrome-precise32bit.zip',
87 ],
88 'Linux_x64': [
89 'chrome-precise64bit.zip',
90 ], 53 ],
91 } 54 }
92 55
93 # Map of platform names to gs:// Chrome build names. 56 # Map of platform names to gs:// Chrome build names.
94 _BUILD_PLATFORM_MAP = { 57 _BUILD_PLATFORM_MAP = {
95 'Linux': 'precise32bit', 58 'Linux': 'precise32',
96 'Linux_x64': 'precise64bit', 59 'Linux_x64': 'precise64',
97 'Win': 'win', 60 'Win': 'win',
98 'Mac': 'mac', 61 'Mac': 'mac',
99 } 62 }
100 63
101 _PLATFORM_DEST_MAP = { 64 _PLATFORM_DEST_MAP = {
102 'Linux': 'chrome_linux', 65 'Linux': 'chrome_linux',
103 'Linux_x64': 'chrome_linux64', 66 'Linux_x64': 'chrome_linux64',
104 'Win': 'chrome_win', 67 'Win': 'chrome_win',
105 'Mac': 'chrome_mac', 68 'Mac': 'chrome_mac',
106 } 69 }
107 70
108 def __init__(self, options): 71 def __init__(self, version, options):
72 self._version = version
109 self._platforms = options.platforms.split(',') 73 self._platforms = options.platforms.split(',')
110 self._version_or_revision = options.version or int(options.revision)
111 self._use_official_version = bool(options.version)
112 self._use_gs = options.use_gs
113 74
114 @staticmethod 75 @staticmethod
115 def _GetCmdStatusAndOutput(args, cwd=None, shell=False): 76 def _GetCmdStatusAndOutput(args, cwd=None, shell=False):
116 """Executes a subprocess and returns its exit code and output. 77 """Executes a subprocess and returns its exit code and output.
117 78
118 Args: 79 Args:
119 args: A string or a sequence of program arguments. 80 args: A string or a sequence of program arguments.
120 cwd: If not None, the subprocess's current directory will be changed to 81 cwd: If not None, the subprocess's current directory will be changed to
121 |cwd| before it's executed. 82 |cwd| before it's executed.
122 shell: Whether to execute args as a shell command. 83 shell: Whether to execute args as a shell command.
123 84
124 Returns: 85 Returns:
125 The tuple (exit code, output). 86 The tuple (exit code, output).
126 """ 87 """
127 logging.info(str(args) + ' ' + (cwd or '')) 88 logging.info(str(args) + ' ' + (cwd or ''))
128 p = subprocess.Popen(args=args, cwd=cwd, stdout=subprocess.PIPE, 89 p = subprocess.Popen(args=args, cwd=cwd, stdout=subprocess.PIPE,
129 stderr=subprocess.PIPE, shell=shell) 90 stderr=subprocess.PIPE, shell=shell)
130 stdout, stderr = p.communicate() 91 stdout, stderr = p.communicate()
131 exit_code = p.returncode 92 exit_code = p.returncode
132 if stderr: 93 if stderr:
133 logging.critical(stderr) 94 logging.critical(stderr)
134 logging.info(stdout) 95 logging.info(stdout)
135 return (exit_code, stdout) 96 return (exit_code, stdout)
136 97
137 def _GetBuildUrl(self, platform, version_or_revision, filename): 98 def _GetBuildUrl(self, platform, version, filename):
138 """Returns the URL for fetching one file. 99 """Returns the URL for fetching one file.
139 100
140 Args: 101 Args:
141 platform: Platform name, must be a key in |self._BUILD_PLATFORM_MAP|. 102 platform: Platform name, must be a key in |self._BUILD_PLATFORM_MAP|.
142 version_or_revision: Either an SVN revision, e.g. 234567, or a Chrome 103 version: A Chrome version number, e.g. 30.0.1600.1.
143 version number, e.g. 30.0.1600.1.
144 filename: Name of the file to fetch. 104 filename: Name of the file to fetch.
145 105
146 Returns: 106 Returns:
147 The URL for fetching a file. This may be a GS or HTTP URL. 107 The URL for fetching a file. This may be a GS or HTTP URL.
148 """ 108 """
149 if self._use_official_version: 109 return CHROME_GS_URL_FMT % (
150 # Chrome Google storage bucket. 110 version, self._BUILD_PLATFORM_MAP[platform], filename)
151 version = version_or_revision
152 if self._use_gs:
153 release = version[:version.find('.')]
154 return (CHROME_GS_URL_FMT % (
155 release,
156 version,
157 self._BUILD_PLATFORM_MAP[platform],
158 filename))
159 # Chrome internal archive.
160 return (CHROME_INTERNAL_URL_FMT % (
161 version,
162 self._BUILD_PLATFORM_MAP[platform],
163 filename))
164 # Chromium archive.
165 revision = version_or_revision
166 return CHROMIUM_URL_FMT % (urllib.quote_plus(platform), revision, filename)
167 111
168 def _FindBuildVersionOrRevision( 112 def _FindBuildVersion(self, platform, version, filename):
169 self, platform, version_or_revision, filename): 113 """Searches for a version where a filename can be found.
170 """Searches for a version or revision where a filename can be found.
171 114
172 Args: 115 Args:
173 platform: Platform name. 116 platform: Platform name.
174 version_or_revision: Either Chrome version or Chromium revision. 117 version: A Chrome version number, e.g. 30.0.1600.1.
175 filename: Filename to look for. 118 filename: Filename to look for.
176 119
177 Returns: 120 Returns:
178 A version or revision where the file could be found, or None. 121 A version where the file could be found, or None.
179 """ 122 """
180 # TODO(shadi): Iterate over official versions to find a valid one. 123 # TODO(shadi): Iterate over official versions to find a valid one.
181 if self._use_official_version: 124 return (version
182 version = version_or_revision 125 if self._DoesBuildExist(platform, version, filename) else None)
183 return (version
184 if self._DoesBuildExist(platform, version, filename) else None)
185
186 revision = version_or_revision
187 MAX_REVISIONS_PER_BUILD = 100
188 for revision_guess in xrange(revision, revision + MAX_REVISIONS_PER_BUILD):
189 if self._DoesBuildExist(platform, revision_guess, filename):
190 return revision_guess
191 else:
192 time.sleep(.1)
193 return None
194 126
195 def _DoesBuildExist(self, platform, version, filename): 127 def _DoesBuildExist(self, platform, version, filename):
196 """Checks whether a file can be found for the given Chrome version. 128 """Checks whether a file can be found for the given Chrome version.
197 129
198 Args: 130 Args:
199 platform: Platform name. 131 platform: Platform name.
200 version: Chrome version number, e.g. 30.0.1600.1. 132 version: Chrome version number, e.g. 30.0.1600.1.
201 filename: Filename to look for. 133 filename: Filename to look for.
202 134
203 Returns: 135 Returns:
204 True if the file could be found, False otherwise. 136 True if the file could be found, False otherwise.
205 """ 137 """
206 url = self._GetBuildUrl(platform, version, filename) 138 url = self._GetBuildUrl(platform, version, filename)
207 if self._use_gs: 139 return self._DoesGSFileExist(url)
208 return self._DoesGSFileExist(url)
209
210 request = urllib2.Request(url)
211 request.get_method = lambda: 'HEAD'
212 try:
213 urllib2.urlopen(request)
214 return True
215 except urllib2.HTTPError, err:
216 if err.code == 404:
217 return False
218 140
219 def _DoesGSFileExist(self, gs_file_name): 141 def _DoesGSFileExist(self, gs_file_name):
220 """Returns True if the GS file can be found, False otherwise.""" 142 """Returns True if the GS file can be found, False otherwise."""
221 exit_code = BuildUpdater._GetCmdStatusAndOutput( 143 exit_code = BuildUpdater._GetCmdStatusAndOutput(
222 ['gsutil', 'ls', gs_file_name])[0] 144 ['gsutil', 'ls', gs_file_name])[0]
223 return not exit_code 145 return not exit_code
224 146
225 def _GetPlatformFiles(self, platform): 147 def _GetPlatformFiles(self, platform):
226 """Returns a list of filenames to fetch for the given platform.""" 148 """Returns a list of filenames to fetch for the given platform."""
227 if self._use_official_version: 149 return BuildUpdater._CHROME_PLATFORM_FILES_MAP[platform]
228 return BuildUpdater._CHROME_PLATFORM_FILES_MAP[platform]
229 return BuildUpdater._PLATFORM_FILES_MAP[platform]
230 150
231 def _DownloadBuilds(self): 151 def _DownloadBuilds(self):
232 for platform in self._platforms: 152 for platform in self._platforms:
233 for filename in self._GetPlatformFiles(platform): 153 for filename in self._GetPlatformFiles(platform):
234 output = os.path.join('dl', platform, 154 output = os.path.join('dl', platform,
235 '%s_%s_%s' % (platform, 155 '%s_%s_%s' % (platform,
236 self._version_or_revision, 156 self._version,
237 filename)) 157 filename))
238 if os.path.exists(output): 158 if os.path.exists(output):
239 logging.info('%s alread exists, skipping download', output) 159 logging.info('%s alread exists, skipping download', output)
240 continue 160 continue
241 version_or_revision = self._FindBuildVersionOrRevision( 161 version = self._FindBuildVersion(platform, self._version, filename)
242 platform, self._version_or_revision, filename) 162 if not version:
243 if not version_or_revision:
244 logging.critical('Failed to find %s build for r%s\n', platform, 163 logging.critical('Failed to find %s build for r%s\n', platform,
245 self._version_or_revision) 164 self._version)
246 sys.exit(1) 165 sys.exit(1)
247 dirname = os.path.dirname(output) 166 dirname = os.path.dirname(output)
248 if dirname and not os.path.exists(dirname): 167 if dirname and not os.path.exists(dirname):
249 os.makedirs(dirname) 168 os.makedirs(dirname)
250 url = self._GetBuildUrl(platform, version_or_revision, filename) 169 url = self._GetBuildUrl(platform, version, filename)
251 self._DownloadFile(url, output) 170 self._DownloadFile(url, output)
252 171
253 def _DownloadFile(self, url, output): 172 def _DownloadFile(self, url, output):
254 logging.info('Downloading %s, saving to %s', url, output) 173 logging.info('Downloading %s, saving to %s', url, output)
255 if self._use_official_version and self._use_gs: 174 BuildUpdater._GetCmdStatusAndOutput(['gsutil', 'cp', url, output])
256 BuildUpdater._GetCmdStatusAndOutput(['gsutil', 'cp', url, output])
257 else:
258 response = urllib2.urlopen(url)
259 with file(output, 'wb') as f:
260 f.write(response.read())
261 175
262 def _FetchSvnRepos(self): 176 def _FetchSvnRepos(self):
263 if not os.path.exists('reference_builds'): 177 if not os.path.exists('reference_builds'):
264 os.makedirs('reference_builds') 178 os.makedirs('reference_builds')
265 BuildUpdater._GetCmdStatusAndOutput( 179 BuildUpdater._GetCmdStatusAndOutput(
266 ['gclient', 'config', 180 ['gclient', 'config',
267 'svn://svn.chromium.org/chrome/trunk/deps/reference_builds'], 181 'svn://svn.chromium.org/chrome/trunk/deps/reference_builds'],
268 'reference_builds') 182 'reference_builds')
269 BuildUpdater._GetCmdStatusAndOutput( 183 BuildUpdater._GetCmdStatusAndOutput(
270 ['gclient', 'sync'], 'reference_builds') 184 ['gclient', 'sync'], 'reference_builds')
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 261
348 def DownloadAndUpdateBuilds(self): 262 def DownloadAndUpdateBuilds(self):
349 self._DownloadBuilds() 263 self._DownloadBuilds()
350 self._FetchSvnRepos() 264 self._FetchSvnRepos()
351 self._ExtractBuilds() 265 self._ExtractBuilds()
352 self._SvnAddAndRemove() 266 self._SvnAddAndRemove()
353 267
354 268
355 def ParseOptions(argv): 269 def ParseOptions(argv):
356 parser = optparse.OptionParser() 270 parser = optparse.OptionParser()
357 usage = 'usage: %prog <options>' 271 parser.set_usage('Usage: %prog VERSION [-p PLATFORMS]')
358 parser.set_usage(usage)
359 parser.add_option('-v', dest='version',
360 help='Chrome official version to pick up '
361 '(e.g. 30.0.1600.1).')
362 parser.add_option('--gs', dest='use_gs', action='store_true', default=False,
363 help='Use Google storage for official builds. Used with -b '
364 'option. Default is false (i.e. use internal storage.')
365 parser.add_option('-p', dest='platforms', 272 parser.add_option('-p', dest='platforms',
366 default='Win,Mac,Linux,Linux_x64', 273 default='Win,Mac,Linux,Linux_x64',
367 help='Comma separated list of platforms to download ' 274 help='Comma separated list of platforms to download '
368 '(as defined by the chromium builders).') 275 '(as defined by the chromium builders).')
369 parser.add_option('-r', dest='revision',
370 help='Chromium revision to pick up (e.g. 234567).')
371 276
372 (options, _) = parser.parse_args(argv) 277 options, args = parser.parse_args(argv)
373 if not options.revision and not options.version: 278 if len(args) != 2:
374 logging.critical('Must specify either -r or -v.\n') 279 parser.print_help()
375 sys.exit(1) 280 sys.exit(1)
376 if options.revision and options.version: 281 version = args[1]
377 logging.critical('Must specify either -r or -v but not both.\n')
378 sys.exit(1)
379 if options.use_gs and not options.version:
380 logging.critical('Can only use --gs with -v option.\n')
381 sys.exit(1)
382 282
383 return options 283 return version, options
384 284
385 285
386 def main(argv): 286 def main(argv):
387 logging.getLogger().setLevel(logging.DEBUG) 287 logging.getLogger().setLevel(logging.DEBUG)
388 options = ParseOptions(argv) 288 version, options = ParseOptions(argv)
389 b = BuildUpdater(options) 289 b = BuildUpdater(version, options)
390 b.DownloadAndUpdateBuilds() 290 b.DownloadAndUpdateBuilds()
391 logging.info('Successfully updated reference builds. Move to ' 291 logging.info('Successfully updated reference builds. Move to '
392 'reference_builds/reference_builds and make a change with gcl.') 292 'reference_builds/reference_builds and make a change with gcl.')
393 293
394 if __name__ == '__main__': 294 if __name__ == '__main__':
395 sys.exit(main(sys.argv)) 295 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