blob: 3f7ad78b466d02cf5ba4d09f2e7ae42089fb739e [file] [log] [blame]
David James8c846492011-01-25 17:07:29 -08001#!/usr/bin/python
David Jamesb619a782012-07-25 19:37:57 -07002# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
David James8c846492011-01-25 17:07:29 -08003# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
Brian Harringaf019fb2012-05-10 15:06:13 -07006"""This script is used to upload host prebuilts as well as board BINHOSTS.
David James8c846492011-01-25 17:07:29 -08007
David James015af872012-06-19 15:24:36 -07008Prebuilts are uploaded using gsutil to Google Storage. After these prebuilts
9are successfully uploaded, a file is updated with the proper BINHOST version.
David James8c846492011-01-25 17:07:29 -080010
11To read more about prebuilts/binhost binary packages please refer to:
David James015af872012-06-19 15:24:36 -070012http://goto/chromeos-prebuilts
David James8c846492011-01-25 17:07:29 -080013
14Example of uploading prebuilt amd64 host files to Google Storage:
David Jamesc5cbd472012-06-19 16:25:45 -070015upload_prebuilts -p /b/cbuild/build -s -u gs://chromeos-prebuilt
David James8c846492011-01-25 17:07:29 -080016
17Example of uploading x86-dogfood binhosts to Google Storage:
David Jamesc5cbd472012-06-19 16:25:45 -070018upload_prebuilts -b x86-dogfood -p /b/cbuild/build/ -u gs://chromeos-prebuilt -g
David James8c846492011-01-25 17:07:29 -080019
David James8c846492011-01-25 17:07:29 -080020"""
21
Chris Sosa1dc96132012-05-11 15:40:50 -070022import datetime
23import multiprocessing
24import optparse
25import os
26import sys
Chris Sosa1dc96132012-05-11 15:40:50 -070027
David James015af872012-06-19 15:24:36 -070028from chromite.buildbot import cbuildbot_background as bg
Zdenek Behan33a34112012-09-10 21:07:51 +020029from chromite.buildbot import constants
Chris Sosa1dc96132012-05-11 15:40:50 -070030from chromite.lib import cros_build_lib
Brian Harring7904b482012-08-08 02:54:12 -070031from chromite.lib import gs
Brian Harringaf019fb2012-05-10 15:06:13 -070032from chromite.lib import osutils
David James32faafe2012-06-08 14:25:03 -070033from chromite.lib import binpkg
Chris Sosa1dc96132012-05-11 15:40:50 -070034
David James015af872012-06-19 15:24:36 -070035# How many times to retry uploads.
36_RETRIES = 10
37
38# Multiplier for how long to sleep (in seconds) between retries; will delay
39# (1*sleep) the first time, then (2*sleep), continuing via attempt * sleep.
40_SLEEP_TIME = 60
41
David James8c846492011-01-25 17:07:29 -080042_HOST_PACKAGES_PATH = 'chroot/var/lib/portage/pkgs'
David James05bcb2b2011-02-09 09:25:47 -080043_CATEGORIES_PATH = 'chroot/etc/portage/categories'
David James615e5b52011-06-03 11:10:15 -070044_PYM_PATH = 'chroot/usr/lib/portage/pym'
David James4058b0d2011-12-08 21:24:50 -080045_HOST_ARCH = 'amd64'
David James8c846492011-01-25 17:07:29 -080046_BOARD_PATH = 'chroot/build/%(board)s'
David James4058b0d2011-12-08 21:24:50 -080047_REL_BOARD_PATH = 'board/%(target)s/%(version)s'
48_REL_HOST_PATH = 'host/%(host_arch)s/%(target)s/%(version)s'
Zdenek Behan33a34112012-09-10 21:07:51 +020049_SDK_GS_BUCKET = 'gs://chromiumos-sdk'
David James8c846492011-01-25 17:07:29 -080050# Private overlays to look at for builds to filter
51# relative to build path
52_PRIVATE_OVERLAY_DIR = 'src/private-overlays'
Scott Zawalskiab1bed32011-03-16 15:24:24 -070053_GOOGLESTORAGE_ACL_FILE = 'googlestorage_acl.xml'
David Jamesce619292011-11-08 11:42:36 -080054_BINHOST_BASE_URL = 'https://commondatastorage.googleapis.com/chromeos-prebuilt'
David James8c846492011-01-25 17:07:29 -080055_PREBUILT_BASE_DIR = 'src/third_party/chromiumos-overlay/chromeos/config/'
56# Created in the event of new host targets becoming available
57_PREBUILT_MAKE_CONF = {'amd64': os.path.join(_PREBUILT_BASE_DIR,
58 'make.conf.amd64-host')}
59_BINHOST_CONF_DIR = 'src/third_party/chromiumos-overlay/chromeos/binhost'
60
61
David James4058b0d2011-12-08 21:24:50 -080062class BuildTarget(object):
63 """A board/variant/profile tuple."""
64
65 def __init__(self, board_variant, profile=None):
66 self.board_variant = board_variant
67 self.board, _, self.variant = board_variant.partition('_')
68 self.profile = profile
69
70 def __str__(self):
71 if self.profile:
72 return '%s_%s' % (self.board_variant, self.profile)
73 else:
74 return self.board_variant
75
76 def __eq__(self, other):
77 return str(other) == str(self)
78
79 def __hash__(self):
80 return hash(str(self))
81
82
David James8c846492011-01-25 17:07:29 -080083def UpdateLocalFile(filename, value, key='PORTAGE_BINHOST'):
84 """Update the key in file with the value passed.
85 File format:
86 key="value"
87 Note quotes are added automatically
88
89 Args:
90 filename: Name of file to modify.
91 value: Value to write with the key.
92 key: The variable key to update. (Default: PORTAGE_BINHOST)
93 """
94 if os.path.exists(filename):
95 file_fh = open(filename)
96 else:
97 file_fh = open(filename, 'w+')
98 file_lines = []
99 found = False
100 keyval_str = '%(key)s=%(value)s'
101 for line in file_fh:
102 # Strip newlines from end of line. We already add newlines below.
103 line = line.rstrip("\n")
104
105 if len(line.split('=')) != 2:
106 # Skip any line that doesn't fit key=val.
107 file_lines.append(line)
108 continue
109
110 file_var, file_val = line.split('=')
111 if file_var == key:
112 found = True
David James20b2b6f2011-11-18 15:11:58 -0800113 print 'Updating %s=%s to %s="%s"' % (file_var, file_val, key, value)
David James8c846492011-01-25 17:07:29 -0800114 value = '"%s"' % value
115 file_lines.append(keyval_str % {'key': key, 'value': value})
116 else:
117 file_lines.append(keyval_str % {'key': file_var, 'value': file_val})
118
119 if not found:
Brian Harring2a014302012-05-12 00:53:33 -0700120 value = '"%s"' % value
David James8c846492011-01-25 17:07:29 -0800121 file_lines.append(keyval_str % {'key': key, 'value': value})
122
123 file_fh.close()
124 # write out new file
Brian Harringaf019fb2012-05-10 15:06:13 -0700125 osutils.WriteFile(filename, '\n'.join(file_lines) + '\n')
David James8c846492011-01-25 17:07:29 -0800126
127
David James27fa7d12011-06-29 17:24:14 -0700128def RevGitFile(filename, value, retries=5, key='PORTAGE_BINHOST', dryrun=False):
David James8c846492011-01-25 17:07:29 -0800129 """Update and push the git file.
130
131 Args:
132 filename: file to modify that is in a git repo already
133 value: string representing the version of the prebuilt that has been
134 uploaded.
135 retries: The number of times to retry before giving up, default: 5
136 key: The variable key to update in the git file.
137 (Default: PORTAGE_BINHOST)
138 """
139 prebuilt_branch = 'prebuilt_branch'
David James1b6e67a2011-05-19 21:32:38 -0700140 cwd = os.path.abspath(os.path.dirname(filename))
Brian Harring609dc4e2012-05-07 02:17:44 -0700141 commit = cros_build_lib.RunGitCommand(
142 cwd, ['rev-parse', 'HEAD']).output.rstrip()
David James8c846492011-01-25 17:07:29 -0800143 description = 'Update %s="%s" in %s' % (key, value, filename)
144 print description
David James66009462012-03-25 10:08:38 -0700145
David James8c846492011-01-25 17:07:29 -0800146 try:
David James66009462012-03-25 10:08:38 -0700147 cros_build_lib.CreatePushBranch(prebuilt_branch, cwd)
David James8c846492011-01-25 17:07:29 -0800148 UpdateLocalFile(filename, value, key)
Brian Harring609dc4e2012-05-07 02:17:44 -0700149 cros_build_lib.RunGitCommand(cwd, ['add', filename])
150 cros_build_lib.RunGitCommand(cwd, ['commit', '-m', description])
151 cros_build_lib.GitPushWithRetry(prebuilt_branch, cwd, dryrun=dryrun,
David James66009462012-03-25 10:08:38 -0700152 retries=retries)
David James8c846492011-01-25 17:07:29 -0800153 finally:
David James1b6e67a2011-05-19 21:32:38 -0700154 cros_build_lib.RunCommand(['git', 'checkout', commit], cwd=cwd)
David James8c846492011-01-25 17:07:29 -0800155
156
157def GetVersion():
158 """Get the version to put in LATEST and update the git version with."""
159 return datetime.datetime.now().strftime('%d.%m.%y.%H%M%S')
160
161
David James015af872012-06-19 15:24:36 -0700162def _GsUpload(local_file, remote_file, acl):
David James8c846492011-01-25 17:07:29 -0800163 """Upload to GS bucket.
164
165 Args:
David Jamesfd0b0852011-02-23 11:15:36 -0800166 args: a tuple of three arguments that contains local_file, remote_file, and
167 the acl used for uploading the file.
David James8c846492011-01-25 17:07:29 -0800168
169 Returns:
170 Return the arg tuple of two if the upload failed
171 """
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700172 CANNED_ACLS = ['public-read', 'private', 'bucket-owner-read',
173 'authenticated-read', 'bucket-owner-full-control',
174 'public-read-write']
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700175 if acl in CANNED_ACLS:
Brian Harring7904b482012-08-08 02:54:12 -0700176 cmd = [gs.GSUTIL_BIN, 'cp', '-a', acl, local_file, remote_file]
David James015af872012-06-19 15:24:36 -0700177 acl_cmd = None
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700178 else:
179 # For private uploads we assume that the overlay board is set up properly
David James015af872012-06-19 15:24:36 -0700180 # and a googlestore_acl.xml is present. Otherwise, this script errors.
Brian Harring7904b482012-08-08 02:54:12 -0700181 cmd = [gs.GSUTIL_BIN, 'cp', '-a', 'private', local_file, remote_file]
182 acl_cmd = [gs.GSUTIL_BIN, 'setacl', acl, remote_file]
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700183
David Jamesc5cbd472012-06-19 16:25:45 -0700184 cros_build_lib.RunCommandWithRetries(_RETRIES, cmd, print_cmd=True,
185 sleep=_SLEEP_TIME,
186 redirect_stdout=True,
187 redirect_stderr=True)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700188 if acl_cmd:
189 # Apply the passed in ACL xml file to the uploaded object.
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700190 cros_build_lib.RunCommandWithRetries(_RETRIES, acl_cmd, print_cmd=False,
David James015af872012-06-19 15:24:36 -0700191 sleep=_SLEEP_TIME)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700192
193
David Jamesfd0b0852011-02-23 11:15:36 -0800194def RemoteUpload(acl, files, pool=10):
David James8c846492011-01-25 17:07:29 -0800195 """Upload to google storage.
196
197 Create a pool of process and call _GsUpload with the proper arguments.
198
199 Args:
David Jamesfd0b0852011-02-23 11:15:36 -0800200 acl: The canned acl used for uploading. acl can be one of: "public-read",
201 "public-read-write", "authenticated-read", "bucket-owner-read",
202 "bucket-owner-full-control", or "private".
David James8c846492011-01-25 17:07:29 -0800203 files: dictionary with keys to local files and values to remote path.
204 pool: integer of maximum proesses to have at the same time.
205
206 Returns:
207 Return a set of tuple arguments of the failed uploads
208 """
David James015af872012-06-19 15:24:36 -0700209 tasks = [[key, value, acl] for key, value in files.iteritems()]
210 bg.RunTasksInProcessPool(_GsUpload, tasks, pool)
David James8c846492011-01-25 17:07:29 -0800211
212
213def GenerateUploadDict(base_local_path, base_remote_path, pkgs):
214 """Build a dictionary of local remote file key pairs to upload.
215
216 Args:
217 base_local_path: The base path to the files on the local hard drive.
218 remote_path: The base path to the remote paths.
219 pkgs: The packages to upload.
220
221 Returns:
222 Returns a dictionary of local_path/remote_path pairs
223 """
224 upload_files = {}
225 for pkg in pkgs:
226 suffix = pkg['CPV'] + '.tbz2'
227 local_path = os.path.join(base_local_path, suffix)
228 assert os.path.exists(local_path)
229 remote_path = '%s/%s' % (base_remote_path.rstrip('/'), suffix)
230 upload_files[local_path] = remote_path
231
232 return upload_files
233
234def GetBoardPathFromCrosOverlayList(build_path, target):
235 """Use the cros_overlay_list to determine the path to the board overlay
236 Args:
237 build_path: The path to the root of the build directory
238 target: The target that we are looking for, could consist of board and
239 board_variant, we handle that properly
240 Returns:
241 The last line from cros_overlay_list as a string
242 """
Chris Sosa471532a2011-02-01 15:10:06 -0800243 script_dir = os.path.join(build_path, 'src/platform/dev/host')
David James4058b0d2011-12-08 21:24:50 -0800244 cmd = ['./cros_overlay_list', '--board', target.board]
245 if target.variant:
246 cmd += ['--variant', target.variant]
David James8c846492011-01-25 17:07:29 -0800247
248 cmd_output = cros_build_lib.RunCommand(cmd, redirect_stdout=True,
249 cwd=script_dir)
250 # We only care about the last entry
251 return cmd_output.output.splitlines().pop()
252
253
254def DeterminePrebuiltConfFile(build_path, target):
255 """Determine the prebuilt.conf file that needs to be updated for prebuilts.
256
257 Args:
258 build_path: The path to the root of the build directory
259 target: String representation of the board. This includes host and board
260 targets
261
262 Returns
263 A string path to a prebuilt.conf file to be updated.
264 """
David James4058b0d2011-12-08 21:24:50 -0800265 if _HOST_ARCH == target:
David James8c846492011-01-25 17:07:29 -0800266 # We are host.
267 # Without more examples of hosts this is a kludge for now.
268 # TODO(Scottz): as new host targets come online expand this to
269 # work more like boards.
Chris Sosa471532a2011-02-01 15:10:06 -0800270 make_path = _PREBUILT_MAKE_CONF[target]
David James8c846492011-01-25 17:07:29 -0800271 else:
272 # We are a board
273 board = GetBoardPathFromCrosOverlayList(build_path, target)
274 make_path = os.path.join(board, 'prebuilt.conf')
275
276 return make_path
277
278
279def UpdateBinhostConfFile(path, key, value):
280 """Update binhost config file file with key=value.
281
282 Args:
283 path: Filename to update.
284 key: Key to update.
285 value: New value for key.
286 """
287 cwd = os.path.dirname(os.path.abspath(path))
288 filename = os.path.basename(path)
Brian Harringaf019fb2012-05-10 15:06:13 -0700289 osutils.SafeMakedirs(cwd)
Brian Harring22edb442012-05-11 23:55:18 -0700290 osutils.WriteFile(path, '', mode='a')
David James8c846492011-01-25 17:07:29 -0800291 UpdateLocalFile(path, value, key)
Chris Sosac13bba52011-05-24 15:14:09 -0700292 cros_build_lib.RunCommand(['git', 'add', filename], cwd=cwd)
David James20b2b6f2011-11-18 15:11:58 -0800293 description = 'Update %s="%s" in %s' % (key, value, filename)
Peter Mayo193f68f2011-04-19 19:08:21 -0400294 cros_build_lib.RunCommand(['git', 'commit', '-m', description], cwd=cwd)
David James8c846492011-01-25 17:07:29 -0800295
296
David Jamesce093af2011-02-23 15:21:58 -0800297def _GrabAllRemotePackageIndexes(binhost_urls):
David James05bcb2b2011-02-09 09:25:47 -0800298 """Grab all of the packages files associated with a list of binhost_urls.
299
David James05bcb2b2011-02-09 09:25:47 -0800300 Args:
301 binhost_urls: The URLs for the directories containing the Packages files we
302 want to grab.
David James05bcb2b2011-02-09 09:25:47 -0800303
304 Returns:
305 A list of PackageIndex objects.
306 """
307 pkg_indexes = []
308 for url in binhost_urls:
David James32faafe2012-06-08 14:25:03 -0700309 pkg_index = binpkg.GrabRemotePackageIndex(url)
David James05bcb2b2011-02-09 09:25:47 -0800310 if pkg_index:
311 pkg_indexes.append(pkg_index)
David James05bcb2b2011-02-09 09:25:47 -0800312 return pkg_indexes
313
314
David James05bcb2b2011-02-09 09:25:47 -0800315
David Jamesc0f158a2011-02-22 16:07:29 -0800316class PrebuiltUploader(object):
317 """Synchronize host and board prebuilts."""
David James8c846492011-01-25 17:07:29 -0800318
David James615e5b52011-06-03 11:10:15 -0700319 def __init__(self, upload_location, acl, binhost_base_url,
David James32b0b2f2011-07-13 20:56:50 -0700320 pkg_indexes, build_path, packages, skip_upload,
David James4058b0d2011-12-08 21:24:50 -0800321 binhost_conf_dir, debug, target, slave_targets):
David Jamesc0f158a2011-02-22 16:07:29 -0800322 """Constructor for prebuilt uploader object.
David James8c846492011-01-25 17:07:29 -0800323
David Jamesc0f158a2011-02-22 16:07:29 -0800324 This object can upload host or prebuilt files to Google Storage.
David James8c846492011-01-25 17:07:29 -0800325
David Jamesc0f158a2011-02-22 16:07:29 -0800326 Args:
327 upload_location: The upload location.
David Jamesfd0b0852011-02-23 11:15:36 -0800328 acl: The canned acl used for uploading to Google Storage. acl can be one
329 of: "public-read", "public-read-write", "authenticated-read",
330 "bucket-owner-read", "bucket-owner-full-control", or "private". If
331 we are not uploading to Google Storage, this parameter is unused.
332 binhost_base_url: The URL used for downloading the prebuilts.
David Jamesc0f158a2011-02-22 16:07:29 -0800333 pkg_indexes: Old uploaded prebuilts to compare against. Instead of
334 uploading duplicate files, we just link to the old files.
David James615e5b52011-06-03 11:10:15 -0700335 build_path: The path to the directory containing the chroot.
336 packages: Packages to upload.
David James32b0b2f2011-07-13 20:56:50 -0700337 skip_upload: Don't actually upload the tarballs.
338 binhost_conf_dir: Directory where to store binhost.conf files.
339 debug: Don't push or upload prebuilts.
David James4058b0d2011-12-08 21:24:50 -0800340 target: BuildTarget managed by this builder.
341 slave_targets: List of BuildTargets managed by slave builders.
David Jamesc0f158a2011-02-22 16:07:29 -0800342 """
343 self._upload_location = upload_location
David Jamesfd0b0852011-02-23 11:15:36 -0800344 self._acl = acl
David Jamesc0f158a2011-02-22 16:07:29 -0800345 self._binhost_base_url = binhost_base_url
346 self._pkg_indexes = pkg_indexes
David James615e5b52011-06-03 11:10:15 -0700347 self._build_path = build_path
348 self._packages = set(packages)
David James8ece7ee2011-06-29 16:02:30 -0700349 self._skip_upload = skip_upload
David James32b0b2f2011-07-13 20:56:50 -0700350 self._binhost_conf_dir = binhost_conf_dir
David James27fa7d12011-06-29 17:24:14 -0700351 self._debug = debug
David James4058b0d2011-12-08 21:24:50 -0800352 self._target = target
353 self._slave_targets = slave_targets
David James615e5b52011-06-03 11:10:15 -0700354
355 def _ShouldFilterPackage(self, pkg):
356 if not self._packages:
357 return False
358 pym_path = os.path.abspath(os.path.join(self._build_path, _PYM_PATH))
David James710b7dc2012-02-07 16:49:59 -0800359 sys.path.insert(0, pym_path)
David James615e5b52011-06-03 11:10:15 -0700360 import portage.versions
361 cat, pkgname = portage.versions.catpkgsplit(pkg['CPV'])[0:2]
362 cp = '%s/%s' % (cat, pkgname)
363 return pkgname not in self._packages and cp not in self._packages
David James8c846492011-01-25 17:07:29 -0800364
David Jamesc0f158a2011-02-22 16:07:29 -0800365 def _UploadPrebuilt(self, package_path, url_suffix):
366 """Upload host or board prebuilt files to Google Storage space.
David James8c846492011-01-25 17:07:29 -0800367
David Jamesc0f158a2011-02-22 16:07:29 -0800368 Args:
369 package_path: The path to the packages dir.
David Jamesce093af2011-02-23 15:21:58 -0800370 url_suffix: The remote subdirectory where we should upload the packages.
David Jamesa3bba142011-05-26 21:24:20 -0700371
David Jamesc0f158a2011-02-22 16:07:29 -0800372 """
David James8c846492011-01-25 17:07:29 -0800373
David Jamesc0f158a2011-02-22 16:07:29 -0800374 # Process Packages file, removing duplicates and filtered packages.
David James32faafe2012-06-08 14:25:03 -0700375 pkg_index = binpkg.GrabLocalPackageIndex(package_path)
David Jamesc0f158a2011-02-22 16:07:29 -0800376 pkg_index.SetUploadLocation(self._binhost_base_url, url_suffix)
David James615e5b52011-06-03 11:10:15 -0700377 pkg_index.RemoveFilteredPackages(self._ShouldFilterPackage)
David Jamesc0f158a2011-02-22 16:07:29 -0800378 uploads = pkg_index.ResolveDuplicateUploads(self._pkg_indexes)
David James05bcb2b2011-02-09 09:25:47 -0800379
David Jamesc0f158a2011-02-22 16:07:29 -0800380 # Write Packages file.
381 tmp_packages_file = pkg_index.WriteToNamedTemporaryFile()
David James05bcb2b2011-02-09 09:25:47 -0800382
David Jamesc0f158a2011-02-22 16:07:29 -0800383 remote_location = '%s/%s' % (self._upload_location.rstrip('/'), url_suffix)
David James015af872012-06-19 15:24:36 -0700384 assert remote_location.startswith('gs://')
David James05bcb2b2011-02-09 09:25:47 -0800385
David James015af872012-06-19 15:24:36 -0700386 # Build list of files to upload.
387 upload_files = GenerateUploadDict(package_path, remote_location, uploads)
388 remote_file = '%s/Packages' % remote_location.rstrip('/')
389 upload_files[tmp_packages_file.name] = remote_file
390
391 RemoteUpload(self._acl, upload_files)
David James8c846492011-01-25 17:07:29 -0800392
Zdenek Behan62a57792012-08-31 15:09:08 +0200393 def _UploadBoardTarball(self, board_path, url_suffix, version, prepackaged):
David James8fa34ea2011-04-15 13:00:20 -0700394 """Upload a tarball of the board at the specified path to Google Storage.
395
396 Args:
397 board_path: The path to the board dir.
398 url_suffix: The remote subdirectory where we should upload the packages.
Zdenek Behan5ad96c02011-06-23 01:04:06 +0200399 version: The version of the board.
Zdenek Behan62a57792012-08-31 15:09:08 +0200400 prepackaged: If given, a tarball that has been packaged outside of this
401 script and should be used.
David James8fa34ea2011-04-15 13:00:20 -0700402 """
403 remote_location = '%s/%s' % (self._upload_location.rstrip('/'), url_suffix)
404 assert remote_location.startswith('gs://')
405 cwd, boardname = os.path.split(board_path.rstrip(os.path.sep))
Zdenek Behan33a34112012-09-10 21:07:51 +0200406 with osutils.TempDirContextManager() as tmpdir:
Zdenek Behan62a57792012-08-31 15:09:08 +0200407 if prepackaged is None:
408 tarfile = os.path.join(tmpdir, '%s.tbz2' % boardname)
409 bzip2 = cros_build_lib.FindCompressor(cros_build_lib.COMP_BZIP2)
410 cmd = ['tar', '-I', bzip2, '-cf', tarfile]
411 excluded_paths = ('usr/lib/debug', 'usr/local/autotest', 'packages',
412 'tmp')
Zdenek Behanaa52cea2012-05-30 01:31:11 +0200413 cmd.extend('--exclude=%s/*' % path for path in excluded_paths)
Zdenek Behan62a57792012-08-31 15:09:08 +0200414 cmd.append('.')
415 cros_build_lib.SudoRunCommand(cmd, cwd=os.path.join(cwd, boardname))
416 else:
417 tarfile = prepackaged
418
David James8fa34ea2011-04-15 13:00:20 -0700419 remote_tarfile = '%s/%s.tbz2' % (remote_location.rstrip('/'), boardname)
Zdenek Behan33a34112012-09-10 21:07:51 +0200420 version_str = version
Zdenek Behan5ad96c02011-06-23 01:04:06 +0200421 # FIXME(zbehan): Temporary hack to upload amd64-host chroots to a
422 # different gs bucket. The right way is to do the upload in a separate
423 # pass of this script.
Zdenek Behan33a34112012-09-10 21:07:51 +0200424 if boardname == constants.CHROOT_BUILDER_BOARD:
Zdenek Behanaf3c9002011-06-24 10:07:40 +0200425 # FIXME(zbehan): Why does version contain the prefix "chroot-"?
Zdenek Behan33a34112012-09-10 21:07:51 +0200426 version_str = version[len('chroot-'):]
Zdenek Behanaf3c9002011-06-24 10:07:40 +0200427 remote_tarfile = \
Zdenek Behanaa52cea2012-05-30 01:31:11 +0200428 '%s/cros-sdk-%s.tar.xz' % (_SDK_GS_BUCKET, version_str)
Zdenek Behan33a34112012-09-10 21:07:51 +0200429 # For SDK, also upload the manifest which is guaranteed to exist
430 # by the builderstage.
431 _GsUpload(tarfile + '.Manifest', remote_tarfile + '.Manifest',
432 self._acl)
433 # Finally, also update the pointer to the latest SDK on which polling
434 # scripts rely.
435 pointerfile = os.path.join(tmpdir, 'cros-sdk-latest.conf')
436 remote_pointerfile = '%s/cros-sdk-latest.conf' % _SDK_GS_BUCKET
Zdenek Behanaa52cea2012-05-30 01:31:11 +0200437 osutils.WriteFile(pointerfile, 'LATEST_SDK="%s"' % version_str)
Zdenek Behan33a34112012-09-10 21:07:51 +0200438 _GsUpload(pointerfile, remote_pointerfile, self._acl)
David James015af872012-06-19 15:24:36 -0700439 _GsUpload(tarfile, remote_tarfile, self._acl)
Zdenek Behan33a34112012-09-10 21:07:51 +0200440
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700441 def _GetTargets(self):
442 """Retuns the list of targets to use."""
443 targets = self._slave_targets[:]
444 if self._target:
445 targets.append(self._target)
446
447 return targets
448
449 def SyncHostPrebuilts(self, version, key, git_sync, sync_binhost_conf):
David Jamesc0f158a2011-02-22 16:07:29 -0800450 """Synchronize host prebuilt files.
David James05bcb2b2011-02-09 09:25:47 -0800451
David Jamesc0f158a2011-02-22 16:07:29 -0800452 This function will sync both the standard host packages, plus the host
453 packages associated with all targets that have been "setup" with the
454 current host's chroot. For instance, if this host has been used to build
455 x86-generic, it will sync the host packages associated with
456 'i686-pc-linux-gnu'. If this host has also been used to build arm-generic,
457 it will also sync the host packages associated with
458 'armv7a-cros-linux-gnueabi'.
David James05bcb2b2011-02-09 09:25:47 -0800459
David Jamesc0f158a2011-02-22 16:07:29 -0800460 Args:
David Jamesc0f158a2011-02-22 16:07:29 -0800461 version: A unique string, intended to be included in the upload path,
462 which identifies the version number of the uploaded prebuilts.
463 key: The variable key to update in the git file.
464 git_sync: If set, update make.conf of target to reference the latest
465 prebuilt packages generated here.
466 sync_binhost_conf: If set, update binhost config file in
467 chromiumos-overlay for the host.
468 """
David Jamese2488642011-11-14 16:15:20 -0800469 # Slave boards are listed before the master board so that the master board
470 # takes priority (i.e. x86-generic preflight host prebuilts takes priority
471 # over preflight host prebuilts from other builders.)
472 binhost_urls = []
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700473 for target in self._GetTargets():
David James4058b0d2011-12-08 21:24:50 -0800474 url_suffix = _REL_HOST_PATH % {'version': version,
475 'host_arch': _HOST_ARCH,
476 'target': target}
David Jamese2488642011-11-14 16:15:20 -0800477 packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
David James05bcb2b2011-02-09 09:25:47 -0800478
David James4058b0d2011-12-08 21:24:50 -0800479 if self._target == target and not self._skip_upload and not self._debug:
David Jamese2488642011-11-14 16:15:20 -0800480 # Upload prebuilts.
481 package_path = os.path.join(self._build_path, _HOST_PACKAGES_PATH)
482 self._UploadPrebuilt(package_path, packages_url_suffix)
David James8ece7ee2011-06-29 16:02:30 -0700483
David Jamese2488642011-11-14 16:15:20 -0800484 # Record URL where prebuilts were uploaded.
485 binhost_urls.append('%s/%s/' % (self._binhost_base_url.rstrip('/'),
486 packages_url_suffix.rstrip('/')))
487
David James20b2b6f2011-11-18 15:11:58 -0800488 binhost = ' '.join(binhost_urls)
David James8ece7ee2011-06-29 16:02:30 -0700489 if git_sync:
490 git_file = os.path.join(self._build_path,
David James4058b0d2011-12-08 21:24:50 -0800491 _PREBUILT_MAKE_CONF[_HOST_ARCH])
David Jamese2488642011-11-14 16:15:20 -0800492 RevGitFile(git_file, binhost, key=key, dryrun=self._debug)
David James8ece7ee2011-06-29 16:02:30 -0700493 if sync_binhost_conf:
David James32b0b2f2011-07-13 20:56:50 -0700494 binhost_conf = os.path.join(self._build_path, self._binhost_conf_dir,
David James4058b0d2011-12-08 21:24:50 -0800495 'host', '%s-%s.conf' % (_HOST_ARCH, key))
David Jamese2488642011-11-14 16:15:20 -0800496 UpdateBinhostConfFile(binhost_conf, key, binhost)
David Jamesc0f158a2011-02-22 16:07:29 -0800497
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700498 def SyncBoardPrebuilts(self, version, key, git_sync, sync_binhost_conf,
Zdenek Behan62a57792012-08-31 15:09:08 +0200499 upload_board_tarball, prepackaged_board):
David Jamesc0f158a2011-02-22 16:07:29 -0800500 """Synchronize board prebuilt files.
501
502 Args:
David Jamesc0f158a2011-02-22 16:07:29 -0800503 version: A unique string, intended to be included in the upload path,
504 which identifies the version number of the uploaded prebuilts.
505 key: The variable key to update in the git file.
506 git_sync: If set, update make.conf of target to reference the latest
507 prebuilt packages generated here.
508 sync_binhost_conf: If set, update binhost config file in
509 chromiumos-overlay for the current board.
David James8fa34ea2011-04-15 13:00:20 -0700510 upload_board_tarball: Include a tarball of the board in our upload.
Zdenek Behan62a57792012-08-31 15:09:08 +0200511 prepackaged_board: A tarball of the board built outside of this script.
David Jamesc0f158a2011-02-22 16:07:29 -0800512 """
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700513 for target in self._GetTargets():
David Jamese2488642011-11-14 16:15:20 -0800514 board_path = os.path.join(self._build_path,
David James4058b0d2011-12-08 21:24:50 -0800515 _BOARD_PATH % {'board': target.board_variant})
David Jamese2488642011-11-14 16:15:20 -0800516 package_path = os.path.join(board_path, 'packages')
David James4058b0d2011-12-08 21:24:50 -0800517 url_suffix = _REL_BOARD_PATH % {'target': target, 'version': version}
David Jamese2488642011-11-14 16:15:20 -0800518 packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
David James8fa34ea2011-04-15 13:00:20 -0700519
David James4058b0d2011-12-08 21:24:50 -0800520 if self._target == target and not self._skip_upload and not self._debug:
David Jamese2488642011-11-14 16:15:20 -0800521 # Upload board tarballs in the background.
522 if upload_board_tarball:
523 tar_process = multiprocessing.Process(target=self._UploadBoardTarball,
524 args=(board_path, url_suffix,
Zdenek Behan62a57792012-08-31 15:09:08 +0200525 version,
526 prepackaged_board))
David Jamese2488642011-11-14 16:15:20 -0800527 tar_process.start()
David James8fa34ea2011-04-15 13:00:20 -0700528
David Jamese2488642011-11-14 16:15:20 -0800529 # Upload prebuilts.
530 self._UploadPrebuilt(package_path, packages_url_suffix)
David James8fa34ea2011-04-15 13:00:20 -0700531
David Jamese2488642011-11-14 16:15:20 -0800532 # Make sure we finished uploading the board tarballs.
533 if upload_board_tarball:
534 tar_process.join()
535 assert tar_process.exitcode == 0
536 # TODO(zbehan): This should be done cleaner.
Zdenek Behan33a34112012-09-10 21:07:51 +0200537 if target.board == constants.CHROOT_BUILDER_BOARD:
David Jamese2488642011-11-14 16:15:20 -0800538 sdk_conf = os.path.join(self._build_path, self._binhost_conf_dir,
David James8ece7ee2011-06-29 16:02:30 -0700539 'host/sdk_version.conf')
Zdenek Behan33a34112012-09-10 21:07:51 +0200540 RevGitFile(sdk_conf, version[len('chroot-'):],
David Jamese2488642011-11-14 16:15:20 -0800541 key='SDK_LATEST_VERSION', dryrun=self._debug)
David Jamesc0f158a2011-02-22 16:07:29 -0800542
David Jamese2488642011-11-14 16:15:20 -0800543 # Record URL where prebuilts were uploaded.
544 url_value = '%s/%s/' % (self._binhost_base_url.rstrip('/'),
545 packages_url_suffix.rstrip('/'))
546
547 if git_sync:
David James4058b0d2011-12-08 21:24:50 -0800548 git_file = DeterminePrebuiltConfFile(self._build_path, target)
David Jamese2488642011-11-14 16:15:20 -0800549 RevGitFile(git_file, url_value, key=key, dryrun=self._debug)
550 if sync_binhost_conf:
551 binhost_conf = os.path.join(self._build_path, self._binhost_conf_dir,
David James4058b0d2011-12-08 21:24:50 -0800552 'target', '%s-%s.conf' % (target, key))
David Jamese2488642011-11-14 16:15:20 -0800553 UpdateBinhostConfFile(binhost_conf, key, url_value)
David James05bcb2b2011-02-09 09:25:47 -0800554
555
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700556def Usage(parser, msg):
David James8c846492011-01-25 17:07:29 -0800557 """Display usage message and parser help then exit with 1."""
558 print >> sys.stderr, msg
559 parser.print_help()
560 sys.exit(1)
561
David James4058b0d2011-12-08 21:24:50 -0800562
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700563def _AddSlaveBoard(_option, _opt_str, value, parser):
564 """Callback that adds a slave board to the list of slave targets."""
David James4058b0d2011-12-08 21:24:50 -0800565 parser.values.slave_targets.append(BuildTarget(value))
566
567
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700568def _AddSlaveProfile(_option, _opt_str, value, parser):
569 """Callback that adds a slave profile to the list of slave targets."""
David James4058b0d2011-12-08 21:24:50 -0800570 if not parser.values.slave_targets:
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700571 Usage(parser, 'Must specify --slave-board before --slave-profile')
David James4058b0d2011-12-08 21:24:50 -0800572 if parser.values.slave_targets[-1].profile is not None:
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700573 Usage(parser, 'Cannot specify --slave-profile twice for same board')
David James4058b0d2011-12-08 21:24:50 -0800574 parser.values.slave_targets[-1].profile = value
575
576
David Jamesc0f158a2011-02-22 16:07:29 -0800577def ParseOptions():
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700578 """Returns options given by the user and the target specified.
579
580 Returns a tuple containing a parsed options object and BuildTarget.
581 target instance is None if no board is specified.
582 """
David James8c846492011-01-25 17:07:29 -0800583 parser = optparse.OptionParser()
584 parser.add_option('-H', '--binhost-base-url', dest='binhost_base_url',
585 default=_BINHOST_BASE_URL,
586 help='Base URL to use for binhost in make.conf updates')
587 parser.add_option('', '--previous-binhost-url', action='append',
588 default=[], dest='previous_binhost_url',
589 help='Previous binhost URL')
590 parser.add_option('-b', '--board', dest='board', default=None,
591 help='Board type that was built on this machine')
Zdenek Behan62a57792012-08-31 15:09:08 +0200592 parser.add_option('-B', '--prepackaged-tarball', dest='prepackaged_tarball',
593 default=None,
594 help='Board tarball prebuilt outside of this script.')
David James4058b0d2011-12-08 21:24:50 -0800595 parser.add_option('', '--profile', dest='profile', default=None,
596 help='Profile that was built on this machine')
597 parser.add_option('', '--slave-board', default=[], action='callback',
598 dest='slave_targets', type='string',
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700599 callback=_AddSlaveBoard,
David James4058b0d2011-12-08 21:24:50 -0800600 help='Board type that was built on a slave machine. To '
601 'add a profile to this board, use --slave-profile.')
602 parser.add_option('', '--slave-profile', action='callback', type='string',
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700603 callback=_AddSlaveProfile,
David James4058b0d2011-12-08 21:24:50 -0800604 help='Board profile that was built on a slave machine. '
605 'Applies to previous slave board.')
David James8c846492011-01-25 17:07:29 -0800606 parser.add_option('-p', '--build-path', dest='build_path',
David James05bcb2b2011-02-09 09:25:47 -0800607 help='Path to the directory containing the chroot')
David James615e5b52011-06-03 11:10:15 -0700608 parser.add_option('', '--packages', action='append',
609 default=[], dest='packages',
610 help='Only include the specified packages. '
611 '(Default is to include all packages.)')
David James8c846492011-01-25 17:07:29 -0800612 parser.add_option('-s', '--sync-host', dest='sync_host',
613 default=False, action='store_true',
614 help='Sync host prebuilts')
615 parser.add_option('-g', '--git-sync', dest='git_sync',
616 default=False, action='store_true',
David Jamese2488642011-11-14 16:15:20 -0800617 help='Enable git version sync (This commits to a repo.) '
618 'This is used by full builders to commit directly '
619 'to board overlays.')
David James8c846492011-01-25 17:07:29 -0800620 parser.add_option('-u', '--upload', dest='upload',
621 default=None,
622 help='Upload location')
623 parser.add_option('-V', '--prepend-version', dest='prepend_version',
624 default=None,
625 help='Add an identifier to the front of the version')
626 parser.add_option('-f', '--filters', dest='filters', action='store_true',
627 default=False,
628 help='Turn on filtering of private ebuild packages')
629 parser.add_option('-k', '--key', dest='key',
630 default='PORTAGE_BINHOST',
631 help='Key to update in make.conf / binhost.conf')
David James8ece7ee2011-06-29 16:02:30 -0700632 parser.add_option('', '--set-version', dest='set_version',
633 default=None,
634 help='Specify the version string')
David James8c846492011-01-25 17:07:29 -0800635 parser.add_option('', '--sync-binhost-conf', dest='sync_binhost_conf',
636 default=False, action='store_true',
David Jamese2488642011-11-14 16:15:20 -0800637 help='Update binhost.conf in chromiumos-overlay or '
638 'chromeos-overlay. Commit the changes, but don\'t '
639 'push them. This is used for preflight binhosts.')
David James32b0b2f2011-07-13 20:56:50 -0700640 parser.add_option('', '--binhost-conf-dir', dest='binhost_conf_dir',
641 default=_BINHOST_CONF_DIR,
642 help='Directory to commit binhost config with '
643 '--sync-binhost-conf.')
David Jamesfd0b0852011-02-23 11:15:36 -0800644 parser.add_option('-P', '--private', dest='private', action='store_true',
645 default=False, help='Mark gs:// uploads as private.')
David James8ece7ee2011-06-29 16:02:30 -0700646 parser.add_option('', '--skip-upload', dest='skip_upload',
647 action='store_true', default=False,
648 help='Skip upload step.')
David James8fa34ea2011-04-15 13:00:20 -0700649 parser.add_option('', '--upload-board-tarball', dest='upload_board_tarball',
650 action='store_true', default=False,
651 help='Upload board tarball to Google Storage.')
David James27fa7d12011-06-29 17:24:14 -0700652 parser.add_option('', '--debug', dest='debug',
653 action='store_true', default=False,
654 help='Don\'t push or upload prebuilts.')
David James8c846492011-01-25 17:07:29 -0800655
656 options, args = parser.parse_args()
David James8c846492011-01-25 17:07:29 -0800657 if not options.build_path:
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700658 Usage(parser, 'Error: you need provide a chroot path')
David James8ece7ee2011-06-29 16:02:30 -0700659 if not options.upload and not options.skip_upload:
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700660 Usage(parser, 'Error: you need to provide an upload location using -u')
David James8ece7ee2011-06-29 16:02:30 -0700661 if not options.set_version and options.skip_upload:
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700662 Usage(parser, 'Error: If you are using --skip-upload, you must specify a '
David James8ece7ee2011-06-29 16:02:30 -0700663 'version number using --set-version.')
David James9417f272011-05-26 13:24:47 -0700664 if args:
David Jamesc5cbd472012-06-19 16:25:45 -0700665 Usage(parser, 'Error: invalid arguments passed to upload_prebuilts: '
666 '%r' % args)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700667
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700668 target = None
669 if options.board:
670 target = BuildTarget(options.board, options.profile)
671
672 if target in options.slave_targets:
673 Usage(parser, 'Error: --board/--profile must not also be a slave target.')
David Jamese2488642011-11-14 16:15:20 -0800674
David James4058b0d2011-12-08 21:24:50 -0800675 if len(set(options.slave_targets)) != len(options.slave_targets):
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700676 Usage(parser, 'Error: --slave-boards must not have duplicates.')
David Jamese2488642011-11-14 16:15:20 -0800677
David James4058b0d2011-12-08 21:24:50 -0800678 if options.slave_targets and options.git_sync:
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700679 Usage(parser, 'Error: --slave-boards is not compatible with --git-sync')
David Jamese2488642011-11-14 16:15:20 -0800680
David James8ece7ee2011-06-29 16:02:30 -0700681 if (options.upload_board_tarball and options.skip_upload and
682 options.board == 'amd64-host'):
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700683 Usage(parser, 'Error: --skip-upload is not compatible with '
David James8ece7ee2011-06-29 16:02:30 -0700684 '--upload-board-tarball and --board=amd64-host')
David James8fa34ea2011-04-15 13:00:20 -0700685
David James8ece7ee2011-06-29 16:02:30 -0700686 if (options.upload_board_tarball and not options.skip_upload and
687 not options.upload.startswith('gs://')):
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700688 Usage(parser, 'Error: --upload-board-tarball only works with gs:// URLs.\n'
David James8fa34ea2011-04-15 13:00:20 -0700689 '--upload must be a gs:// URL.')
690
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700691 if options.private:
692 if options.sync_host:
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700693 Usage(parser, 'Error: --private and --sync-host/-s cannot be specified '
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700694 'together, we do not support private host prebuilts')
695
David James8ece7ee2011-06-29 16:02:30 -0700696 if not options.upload or not options.upload.startswith('gs://'):
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700697 Usage(parser, 'Error: --private is only valid for gs:// URLs.\n'
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700698 '--upload must be a gs:// URL.')
699
700 if options.binhost_base_url != _BINHOST_BASE_URL:
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700701 Usage(parser, 'Error: when using --private the --binhost-base-url '
David Jamese2488642011-11-14 16:15:20 -0800702 'is automatically derived.')
David James27fa7d12011-06-29 17:24:14 -0700703
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700704 return options, target
David Jamesc0f158a2011-02-22 16:07:29 -0800705
David Jamesc5cbd472012-06-19 16:25:45 -0700706def main(_argv):
David Jamesdb401072011-06-10 12:17:16 -0700707 # Set umask to a sane value so that files created as root are readable.
708 os.umask(022)
709
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700710 options, target = ParseOptions()
David Jamesc0f158a2011-02-22 16:07:29 -0800711
David James05bcb2b2011-02-09 09:25:47 -0800712 # Calculate a list of Packages index files to compare against. Whenever we
713 # upload a package, we check to make sure it's not already stored in one of
714 # the packages files we uploaded. This list of packages files might contain
715 # both board and host packages.
David Jamesce093af2011-02-23 15:21:58 -0800716 pkg_indexes = _GrabAllRemotePackageIndexes(options.previous_binhost_url)
David James8c846492011-01-25 17:07:29 -0800717
David James8ece7ee2011-06-29 16:02:30 -0700718 if options.set_version:
719 version = options.set_version
720 else:
721 version = GetVersion()
David Jamesc0f158a2011-02-22 16:07:29 -0800722 if options.prepend_version:
723 version = '%s-%s' % (options.prepend_version, version)
724
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700725 acl = 'public-read'
726 binhost_base_url = options.binhost_base_url
727
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700728 if target and options.private:
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700729 binhost_base_url = options.upload
730 board_path = GetBoardPathFromCrosOverlayList(options.build_path,
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700731 target)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700732 acl = os.path.join(board_path, _GOOGLESTORAGE_ACL_FILE)
733
734 uploader = PrebuiltUploader(options.upload, acl, binhost_base_url,
David James615e5b52011-06-03 11:10:15 -0700735 pkg_indexes, options.build_path,
David James27fa7d12011-06-29 17:24:14 -0700736 options.packages, options.skip_upload,
David Jamese2488642011-11-14 16:15:20 -0800737 options.binhost_conf_dir, options.debug,
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700738 target, options.slave_targets)
David Jamesc0f158a2011-02-22 16:07:29 -0800739
David James8c846492011-01-25 17:07:29 -0800740 if options.sync_host:
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700741 uploader.SyncHostPrebuilts(version, options.key, options.git_sync,
742 options.sync_binhost_conf)
David James8c846492011-01-25 17:07:29 -0800743
Chris Sosa62c8ff52012-06-04 15:03:12 -0700744 if options.board or options.slave_targets:
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700745 uploader.SyncBoardPrebuilts(version, options.key, options.git_sync,
746 options.sync_binhost_conf,
Zdenek Behan62a57792012-08-31 15:09:08 +0200747 options.upload_board_tarball,
748 options.prepackaged_tarball)