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