Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2015 The Chromium Authors. All rights reserved. | 2 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 ''' | 6 ''' |
| 7 Script to help uploading and downloading the Google Play services library to | 7 Script to help uploading and downloading the Google Play services library to |
| 8 and from a Google Cloud storage. | 8 and from a Google Cloud storage. |
| 9 ''' | 9 ''' |
| 10 | 10 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 40 # Default bucket used for storing the files. | 40 # Default bucket used for storing the files. |
| 41 GMS_CLOUD_STORAGE = 'chromium-android-tools/play-services' | 41 GMS_CLOUD_STORAGE = 'chromium-android-tools/play-services' |
| 42 | 42 |
| 43 # Path to the default configuration file. It exposes the currently installed | 43 # Path to the default configuration file. It exposes the currently installed |
| 44 # version of the library in a human readable way. | 44 # version of the library in a human readable way. |
| 45 CONFIG_DEFAULT_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'build', | 45 CONFIG_DEFAULT_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'build', |
| 46 'android', 'play_services', 'config.json') | 46 'android', 'play_services', 'config.json') |
| 47 | 47 |
| 48 LICENSE_FILE_NAME = 'LICENSE' | 48 LICENSE_FILE_NAME = 'LICENSE' |
| 49 ZIP_FILE_NAME = 'google_play_services_library.zip' | 49 ZIP_FILE_NAME = 'google_play_services_library.zip' |
| 50 GMS_PACKAGE_ID = 'extra-google-google_play_services' # used by sdk manager | 50 GMS_PACKAGE_ID = 'extra-google-m2repository' # used by sdk manager |
| 51 | 51 |
| 52 LICENSE_PATTERN = re.compile(r'^Pkg\.License=(?P<text>.*)$', re.MULTILINE) | 52 LICENSE_PATTERN = re.compile(r'^Pkg\.License=(?P<text>.*)$', re.MULTILINE) |
| 53 | 53 |
| 54 | 54 |
| 55 def main(raw_args): | 55 def main(raw_args): |
| 56 parser = argparse.ArgumentParser( | 56 parser = argparse.ArgumentParser( |
| 57 description=__doc__ + 'Please see the subcommand help for more details.', | 57 description=__doc__ + 'Please see the subcommand help for more details.', |
| 58 formatter_class=utils.DefaultsRawHelpFormatter) | 58 formatter_class=utils.DefaultsRawHelpFormatter) |
| 59 subparsers = parser.add_subparsers(title='commands') | 59 subparsers = parser.add_subparsers(title='commands') |
| 60 | 60 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 | 134 |
| 135 parser.add_argument('-f', '--force', | 135 parser.add_argument('-f', '--force', |
| 136 action='store_true', | 136 action='store_true', |
| 137 help='run even if the library is already up to date') | 137 help='run even if the library is already up to date') |
| 138 | 138 |
| 139 | 139 |
| 140 def Download(args): | 140 def Download(args): |
| 141 ''' | 141 ''' |
| 142 Downloads the Google Play services library from a Google Cloud Storage bucket | 142 Downloads the Google Play services library from a Google Cloud Storage bucket |
| 143 and installs it to | 143 and installs it to |
| 144 //third_party/android_tools/sdk/extras/google/google_play_services. | 144 //third_party/android_tools/sdk/extras/google/m2repository. |
| 145 | 145 |
| 146 A license check will be made, and the user might have to accept the license | 146 A license check will be made, and the user might have to accept the license |
| 147 if that has not been done before. | 147 if that has not been done before. |
| 148 ''' | 148 ''' |
| 149 | 149 |
| 150 if not os.path.isdir(args.sdk_root): | 150 if not os.path.isdir(args.sdk_root): |
| 151 logging.debug('Did not find the Android SDK root directory at "%s".', | 151 logging.debug('Did not find the Android SDK root directory at "%s".', |
| 152 args.sdk_root) | 152 args.sdk_root) |
| 153 if not args.force: | 153 if not args.force: |
| 154 logging.info('Skipping, not on an android checkout.') | 154 logging.info('Skipping, not on an android checkout.') |
| 155 return 0 | 155 return 0 |
| 156 | 156 |
| 157 config = utils.ConfigParser(args.config) | 157 config = utils.ConfigParser(args.config) |
| 158 paths = PlayServicesPaths(args.sdk_root, config.version_xml_path) | 158 paths = PlayServicesPaths(args.sdk_root, config.version_number, |
| 159 config.clients) | |
| 159 | 160 |
| 160 if os.path.isdir(paths.package) and not os.access(paths.package, os.W_OK): | 161 if os.path.isdir(paths.package) and not os.access(paths.package, os.W_OK): |
| 161 logging.error('Failed updating the Google Play Services library. ' | 162 logging.error('Failed updating the Google Play Services library. ' |
| 162 'The location is not writable. Please remove the ' | 163 'The location is not writable. Please remove the ' |
| 163 'directory (%s) and try again.', paths.package) | 164 'directory (%s) and try again.', paths.package) |
| 164 return -2 | 165 return -2 |
| 165 | 166 |
| 166 new_lib_zip_sha1 = os.path.join(SHA1_DIRECTORY, ZIP_FILE_NAME + '.sha1') | 167 new_lib_zip_sha1 = os.path.join(SHA1_DIRECTORY, ZIP_FILE_NAME + '.sha1') |
| 167 | 168 |
| 168 logging.debug('Comparing zip hashes: %s and %s', new_lib_zip_sha1, | 169 logging.debug('Comparing zip hashes: %s and %s', new_lib_zip_sha1, |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 195 'not up to date. You might run into issues building ' | 196 'not up to date. You might run into issues building ' |
| 196 'or running the app. Please run `%s download` to ' | 197 'or running the app. Please run `%s download` to ' |
| 197 'retry downloading it.', __file__) | 198 'retry downloading it.', __file__) |
| 198 return 0 | 199 return 0 |
| 199 | 200 |
| 200 new_lib_zip = os.path.join(tmp_root, ZIP_FILE_NAME) | 201 new_lib_zip = os.path.join(tmp_root, ZIP_FILE_NAME) |
| 201 _DownloadFromBucket(bucket_path, new_lib_zip_sha1, new_lib_zip, | 202 _DownloadFromBucket(bucket_path, new_lib_zip_sha1, new_lib_zip, |
| 202 args.verbose, args.dry_run) | 203 args.verbose, args.dry_run) |
| 203 | 204 |
| 204 try: | 205 try: |
| 206 # Remove the deprecated sdk directory. | |
| 207 deprecated_package_path = os.path.join(args.sdk_root, 'extras', 'google', | |
| 208 'google_play_services') | |
| 209 if os.path.exists(deprecated_package_path): | |
| 210 shutil.rmtree(deprecated_package_path) | |
| 211 | |
| 205 # We remove the current version of the Google Play services SDK. | 212 # We remove the current version of the Google Play services SDK. |
| 206 if os.path.exists(paths.package): | 213 if os.path.exists(paths.package): |
| 207 shutil.rmtree(paths.package) | 214 shutil.rmtree(paths.package) |
| 208 os.makedirs(paths.package) | 215 os.makedirs(paths.package) |
| 209 | 216 |
| 210 logging.debug('Extracting the library to %s', paths.lib) | 217 logging.debug('Extracting the library to %s', paths.package) |
| 211 with zipfile.ZipFile(new_lib_zip, "r") as new_lib_zip_file: | 218 with zipfile.ZipFile(new_lib_zip, "r") as new_lib_zip_file: |
| 212 new_lib_zip_file.extractall(paths.lib) | 219 new_lib_zip_file.extractall(paths.package) |
| 213 | 220 |
| 214 logging.debug('Copying %s to %s', new_license, paths.license) | 221 logging.debug('Copying %s to %s', new_license, paths.license) |
| 215 shutil.copy(new_license, paths.license) | 222 shutil.copy(new_license, paths.license) |
| 216 | 223 |
| 217 logging.debug('Copying %s to %s', new_lib_zip_sha1, paths.lib_zip_sha1) | 224 logging.debug('Copying %s to %s', new_lib_zip_sha1, paths.lib_zip_sha1) |
| 218 shutil.copy(new_lib_zip_sha1, paths.lib_zip_sha1) | 225 shutil.copy(new_lib_zip_sha1, paths.lib_zip_sha1) |
| 219 | 226 |
| 220 logging.info('Update complete.') | 227 logging.info('Update complete.') |
| 221 | 228 |
| 222 except Exception as e: # pylint: disable=broad-except | 229 except Exception as e: # pylint: disable=broad-except |
| 223 logging.error('Failed updating the Google Play Services library. ' | 230 logging.error('Failed updating the Google Play Services library. ' |
| 224 'An error occurred while installing the new version in ' | 231 'An error occurred while installing the new version in ' |
| 225 'the SDK directory: %s ', e) | 232 'the SDK directory: %s ', e) |
| 226 return -3 | 233 return -3 |
| 227 finally: | 234 finally: |
| 228 shutil.rmtree(tmp_root) | 235 shutil.rmtree(tmp_root) |
| 229 | 236 |
| 230 return 0 | 237 return 0 |
| 231 | 238 |
| 232 | 239 |
| 233 def UpdateSdk(args): | 240 def UpdateSdk(args): |
| 234 ''' | 241 ''' |
| 235 Uses the Android SDK Manager to download the latest Google Play services SDK | 242 Uses the Android SDK Manager to download the latest Google Play services SDK |
| 236 locally. Its usual installation path is | 243 locally. Its usual installation path is |
| 237 //third_party/android_tools/sdk/extras/google/google_play_services | 244 //third_party/android_tools/sdk/extras/google/m2repository |
| 238 ''' | 245 ''' |
| 239 | 246 |
| 240 # This should function should not run on bots and could fail for many user | 247 # This should function should not run on bots and could fail for many user |
| 241 # and setup related reasons. Also, exceptions here are not caught, so we | 248 # and setup related reasons. Also, exceptions here are not caught, so we |
| 242 # disable breakpad to avoid spamming the logs. | 249 # disable breakpad to avoid spamming the logs. |
| 243 breakpad.IS_ENABLED = False | 250 breakpad.IS_ENABLED = False |
| 244 | 251 |
| 252 # `android update sdk` fails if the library is not installed yet, but it does | |
| 253 # not allow to install it from scratch using the command line. We then create | |
| 254 # a fake outdated installation. | |
| 255 paths = PlayServicesPaths(args.sdk_root, 'no_version_number', []) | |
| 256 if not os.path.isfile(paths.source_prop): | |
| 257 if not os.path.exists(os.path.dirname(paths.source_prop)): | |
| 258 os.path.makedirs(os.path.dirname(paths.source_prop)) | |
| 259 with open(paths.source_prop, 'w') as prop_file: | |
| 260 prop_file.write('Pkg.Revision=0.0.0\n') | |
| 261 | |
| 245 sdk_manager = os.path.join(args.sdk_root, 'tools', 'android') | 262 sdk_manager = os.path.join(args.sdk_root, 'tools', 'android') |
| 246 cmd = [sdk_manager, 'update', 'sdk', '--no-ui', '--filter', GMS_PACKAGE_ID] | 263 cmd = [sdk_manager, 'update', 'sdk', '--no-ui', '--filter', GMS_PACKAGE_ID] |
| 247 cmd_helper.Call(cmd) | 264 cmd_helper.Call(cmd) |
| 248 # If no update is needed, it still returns successfully so we just do nothing | 265 # If no update is needed, it still returns successfully so we just do nothing |
| 249 | 266 |
| 250 return 0 | 267 return 0 |
| 251 | 268 |
| 252 | 269 |
| 253 def Upload(args): | 270 def Upload(args): |
| 254 ''' | 271 ''' |
| 255 Uploads the library from the local Google Play services SDK to a Google Cloud | 272 Uploads the library from the local Google Play services SDK to a Google Cloud |
| 256 storage bucket. | 273 storage bucket. |
| 257 | 274 |
| 258 By default, a local commit will be made at the end of the operation. | 275 By default, a local commit will be made at the end of the operation. |
| 259 ''' | 276 ''' |
| 260 | 277 |
| 261 # This should function should not run on bots and could fail for many user | 278 # This should function should not run on bots and could fail for many user |
| 262 # and setup related reasons. Also, exceptions here are not caught, so we | 279 # and setup related reasons. Also, exceptions here are not caught, so we |
| 263 # disable breakpad to avoid spamming the logs. | 280 # disable breakpad to avoid spamming the logs. |
| 264 breakpad.IS_ENABLED = False | 281 breakpad.IS_ENABLED = False |
| 265 | 282 |
| 266 config = utils.ConfigParser(args.config) | 283 config = utils.ConfigParser(args.config) |
| 267 paths = PlayServicesPaths(args.sdk_root, config.version_xml_path) | 284 paths = PlayServicesPaths(args.sdk_root, config.version_number, |
| 285 config.clients) | |
| 286 logging.debug('-- Loaded paths --\n%s\n------------------', paths) | |
| 268 | 287 |
| 269 if not args.skip_git and utils.IsRepoDirty(host_paths.DIR_SOURCE_ROOT): | 288 if not args.skip_git and utils.IsRepoDirty(host_paths.DIR_SOURCE_ROOT): |
| 270 logging.error('The repo is dirty. Please commit or stash your changes.') | 289 logging.error('The repo is dirty. Please commit or stash your changes.') |
| 271 return -1 | 290 return -1 |
| 272 | 291 |
| 273 new_version_number = utils.GetVersionNumberFromLibraryResources( | |
|
dgn
2016/08/05 16:09:04
We don't when we update it we get all the existing
| |
| 274 paths.version_xml) | |
| 275 logging.debug('comparing versions: new=%d, old=%s', | |
| 276 new_version_number, config.version_number) | |
| 277 if new_version_number <= config.version_number and not args.force: | |
| 278 logging.info('The checked in version of the library is already the latest ' | |
| 279 'one. No update is needed. Please rerun with --force to skip ' | |
| 280 'this check.') | |
| 281 return 0 | |
| 282 | 292 |
| 283 tmp_root = tempfile.mkdtemp() | 293 tmp_root = tempfile.mkdtemp() |
| 284 try: | 294 try: |
| 285 new_lib_zip = os.path.join(tmp_root, ZIP_FILE_NAME) | 295 new_lib_zip = os.path.join(tmp_root, ZIP_FILE_NAME) |
| 286 new_license = os.path.join(tmp_root, LICENSE_FILE_NAME) | 296 new_license = os.path.join(tmp_root, LICENSE_FILE_NAME) |
| 287 | 297 |
| 288 # need to strip '.zip' from the file name here | 298 _ZipLibrary(new_lib_zip, paths.client_paths, paths.package) |
| 289 shutil.make_archive(new_lib_zip[:-4], 'zip', paths.lib) | |
| 290 _ExtractLicenseFile(new_license, paths.source_prop) | 299 _ExtractLicenseFile(new_license, paths.source_prop) |
| 291 | 300 |
| 292 bucket_path = _VerifyBucketPathFormat(args.bucket, new_version_number, | 301 bucket_path = _VerifyBucketPathFormat(args.bucket, config.version_number, |
| 293 args.dry_run) | 302 args.dry_run) |
| 294 files_to_upload = [new_lib_zip, new_license] | 303 files_to_upload = [new_lib_zip, new_license] |
| 295 logging.debug('Uploading %s to %s', files_to_upload, bucket_path) | 304 logging.debug('Uploading %s to %s', files_to_upload, bucket_path) |
| 296 _UploadToBucket(bucket_path, files_to_upload, args.dry_run) | 305 _UploadToBucket(bucket_path, files_to_upload, args.dry_run) |
| 297 | 306 |
| 298 new_lib_zip_sha1 = os.path.join(SHA1_DIRECTORY, | 307 new_lib_zip_sha1 = os.path.join(SHA1_DIRECTORY, |
| 299 ZIP_FILE_NAME + '.sha1') | 308 ZIP_FILE_NAME + '.sha1') |
| 300 new_license_sha1 = os.path.join(SHA1_DIRECTORY, | 309 new_license_sha1 = os.path.join(SHA1_DIRECTORY, |
| 301 LICENSE_FILE_NAME + '.sha1') | 310 LICENSE_FILE_NAME + '.sha1') |
| 302 shutil.copy(new_lib_zip + '.sha1', new_lib_zip_sha1) | 311 shutil.copy(new_lib_zip + '.sha1', new_lib_zip_sha1) |
| 303 shutil.copy(new_license + '.sha1', new_license_sha1) | 312 shutil.copy(new_license + '.sha1', new_license_sha1) |
| 304 finally: | 313 finally: |
| 305 shutil.rmtree(tmp_root) | 314 shutil.rmtree(tmp_root) |
| 306 | 315 |
| 307 config.UpdateVersionNumber(new_version_number) | |
|
dgn
2016/08/05 16:09:04
We now use the config file as input rather than ou
| |
| 308 | |
| 309 if not args.skip_git: | 316 if not args.skip_git: |
| 310 commit_message = ('Update the Google Play services dependency to %s\n' | 317 commit_message = ('Update the Google Play services dependency to %s\n' |
| 311 '\n') % new_version_number | 318 '\n') % config.version_number |
| 312 utils.MakeLocalCommit(host_paths.DIR_SOURCE_ROOT, | 319 utils.MakeLocalCommit(host_paths.DIR_SOURCE_ROOT, |
| 313 [new_lib_zip_sha1, new_license_sha1, config.path], | 320 [new_lib_zip_sha1, new_license_sha1, config.path], |
| 314 commit_message) | 321 commit_message) |
| 315 | 322 |
| 316 return 0 | 323 return 0 |
| 317 | 324 |
| 318 | 325 |
| 319 def _DownloadFromBucket(bucket_path, sha1_file, destination, verbose, | 326 def _DownloadFromBucket(bucket_path, sha1_file, destination, verbose, |
| 320 is_dry_run): | 327 is_dry_run): |
| 321 '''Downloads the file designated by the provided sha1 from a cloud bucket.''' | 328 '''Downloads the file designated by the provided sha1 from a cloud bucket.''' |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 381 has been accepted. | 388 has been accepted. |
| 382 ''' | 389 ''' |
| 383 | 390 |
| 384 if utils.FileEquals(expected_license_path, actual_license_path): | 391 if utils.FileEquals(expected_license_path, actual_license_path): |
| 385 return True | 392 return True |
| 386 | 393 |
| 387 with open(expected_license_path) as license_file: | 394 with open(expected_license_path) as license_file: |
| 388 # Uses plain print rather than logging to make sure this is not formatted | 395 # Uses plain print rather than logging to make sure this is not formatted |
| 389 # by the logger. | 396 # by the logger. |
| 390 print ('Updating the Google Play services SDK to ' | 397 print ('Updating the Google Play services SDK to ' |
| 391 'version %d.' % version_number) | 398 'version %s.' % version_number) |
| 392 | 399 |
| 393 # The output is buffered when running as part of gclient hooks. We split | 400 # The output is buffered when running as part of gclient hooks. We split |
| 394 # the text here and flush is explicitly to avoid having part of it dropped | 401 # the text here and flush is explicitly to avoid having part of it dropped |
| 395 # out. | 402 # out. |
| 396 # Note: text contains *escaped* new lines, so we split by '\\n', not '\n'. | 403 # Note: text contains *escaped* new lines, so we split by '\\n', not '\n'. |
| 397 for license_part in license_file.read().split('\\n'): | 404 for license_part in license_file.read().split('\\n'): |
| 398 print license_part | 405 print license_part |
| 399 sys.stdout.flush() | 406 sys.stdout.flush() |
| 400 | 407 |
| 401 # Need to put the prompt on a separate line otherwise the gclient hook buffer | 408 # Need to put the prompt on a separate line otherwise the gclient hook buffer |
| 402 # only prints it after we received an input. | 409 # only prints it after we received an input. |
| 403 print 'Do you accept the license? [y/n]: ' | 410 print ('Do you accept the license for version %s of the Google Play services ' |
| 411 'client library? [y/n]: ' % version_number) | |
| 404 sys.stdout.flush() | 412 sys.stdout.flush() |
| 405 return raw_input('> ') in ('Y', 'y') | 413 return raw_input('> ') in ('Y', 'y') |
| 406 | 414 |
| 407 | 415 |
| 408 def _IsBotEnvironment(): | 416 def _IsBotEnvironment(): |
| 409 return bool(os.environ.get('CHROME_HEADLESS')) | 417 return bool(os.environ.get('CHROME_HEADLESS')) |
| 410 | 418 |
| 411 | 419 |
| 412 def _VerifyBucketPathFormat(bucket_name, version_number, is_dry_run): | 420 def _VerifyBucketPathFormat(bucket_name, version_number, is_dry_run): |
| 413 ''' | 421 ''' |
| 414 Formats and checks the download/upload path depending on whether we are | 422 Formats and checks the download/upload path depending on whether we are |
| 415 running in dry run mode or not. Returns a supposedly safe path to use with | 423 running in dry run mode or not. Returns a supposedly safe path to use with |
| 416 Gsutil. | 424 Gsutil. |
| 417 ''' | 425 ''' |
| 418 | 426 |
| 419 if is_dry_run: | 427 if is_dry_run: |
| 420 bucket_path = os.path.abspath(os.path.join(bucket_name, | 428 bucket_path = os.path.abspath(os.path.join(bucket_name, |
| 421 str(version_number))) | 429 str(version_number))) |
| 422 if not os.path.isdir(bucket_path): | 430 if not os.path.isdir(bucket_path): |
| 423 os.makedirs(bucket_path) | 431 os.makedirs(bucket_path) |
| 424 else: | 432 else: |
| 425 if bucket_name.startswith('gs://'): | 433 if bucket_name.startswith('gs://'): |
| 426 # We enforce the syntax without gs:// for consistency with the standalone | 434 # We enforce the syntax without gs:// for consistency with the standalone |
| 427 # download/upload scripts and to make dry run transition easier. | 435 # download/upload scripts and to make dry run transition easier. |
| 428 raise AttributeError('Please provide the bucket name without the gs:// ' | 436 raise AttributeError('Please provide the bucket name without the gs:// ' |
| 429 'prefix (e.g. %s)' % GMS_CLOUD_STORAGE) | 437 'prefix (e.g. %s)' % GMS_CLOUD_STORAGE) |
| 430 bucket_path = 'gs://%s/%d' % (bucket_name, version_number) | 438 bucket_path = 'gs://%s/%s' % (bucket_name, version_number) |
| 431 | 439 |
| 432 return bucket_path | 440 return bucket_path |
| 433 | 441 |
| 442 def _ZipLibrary(zip_name, files, zip_root): | |
| 443 zipf = zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) | |
|
agrieve
2016/08/05 18:59:28
nit: nicer to use with: for this.
with zipfile.Zi
dgn
2016/08/08 17:17:24
Done.
| |
| 444 for file_name in files: | |
| 445 zipf.write(file_name, os.path.relpath(file_name, zip_root)) | |
| 446 zipf.close() | |
| 447 | |
| 434 | 448 |
| 435 class PlayServicesPaths(object): | 449 class PlayServicesPaths(object): |
| 436 ''' | 450 ''' |
| 437 Describes the different paths to be used in the update process. | 451 Describes the different paths to be used in the update process. |
| 438 | 452 |
| 439 Filesystem hierarchy | Exposed property / notes | 453 Filesystem hierarchy | Exposed property / notes |
| 440 ---------------------------------------------------|------------------------- | 454 ---------------------------------------------------|------------------------- |
| 441 [sdk_root] | sdk_root / (1) | 455 [sdk_root] | sdk_root / (1) |
| 442 +- extras | | 456 +- extras | |
| 443 +- google | | 457 +- google | |
| 444 +- google_play_services | package / (2) | 458 +- m2repository | package / (2) |
| 445 +- source.properties | source_prop / (3) | 459 +- source.properties | source_prop / (3) |
| 446 +- LICENSE | license / (4) | 460 +- LICENSE | license / (4) |
| 447 +- google_play_services_library.zip.sha1 | lib_zip_sha1 / (5) | 461 +- google_play_services_library.zip.sha1 | lib_zip_sha1 / (5) |
| 448 +- libproject | | 462 +- com/google/android/gms/ | |
| 449 +- google-play-services_lib | lib / (6) | 463 +- [play-services-foo] | |
| 450 +- res | | 464 +- [X.Y.Z] | |
| 451 +- values | | 465 +- play-services-foo-X.Y.Z.aar | client_paths / (6) |
| 452 +- version.xml | version_xml (7) | |
| 453 | 466 |
| 454 Notes: | 467 Notes: |
| 455 | 468 |
| 456 1. sdk_root: Path provided as a parameter to the script (--sdk_root) | 469 1. sdk_root: Path provided as a parameter to the script (--sdk_root) |
| 457 2. package: This directory contains the Google Play services SDK itself. | 470 2. package: This directory contains the Google Play services SDK itself. |
| 458 When downloaded via the Android SDK manager, it will contain, | 471 When downloaded via the Android SDK manager, it will be a complete maven, |
| 459 documentation, samples and other files in addition to the library. When | 472 repository with the different versions of the library. When the update |
| 460 the update script downloads the library from our cloud storage, it is | 473 script downloads the library from our cloud storage, it is cleared. |
| 461 cleared. | |
| 462 3. source_prop: File created by the Android SDK manager that contains | 474 3. source_prop: File created by the Android SDK manager that contains |
| 463 the package information, such as the version info and the license. | 475 the package information, such as the version info and the license. |
| 464 4. license: File created by the update script. Contains the license accepted | 476 4. license: File created by the update script. Contains the license accepted |
| 465 by the user. | 477 by the user. |
| 466 5. lib_zip_sha1: sha1 of the library zip that has been installed by the | 478 5. lib_zip_sha1: sha1 of the library that has been installed by the |
| 467 update script. It is compared with the one required by the config file to | 479 update script. It is compared with the one required by the config file to |
| 468 check if an update is necessary. | 480 check if an update is necessary. |
| 469 6. lib: Contains the library itself: jar and resources. This is what is | 481 6. client_paths: The client library jars we care about. They are zipped |
| 470 downloaded from the cloud storage. | 482 zipped together and uploaded to the cloud storage. |
| 471 7. version_xml: File that contains the exact Google Play services library | |
| 472 version, the one that we track. The version looks like 811500, is used in | |
| 473 the code and the on-device APK, as opposed to the SDK package version | |
| 474 which looks like 27.0.0 and is used only by the Android SDK manager. | |
| 475 | 483 |
| 476 ''' | 484 ''' |
| 477 | 485 |
| 478 def __init__(self, sdk_root, version_xml_path): | 486 def __init__(self, sdk_root, version_number, client_names): |
| 479 relative_package = os.path.join('extras', 'google', 'google_play_services') | 487 ''' |
| 480 relative_lib = os.path.join(relative_package, 'libproject', | 488 sdk_root: path to the root of the sdk directory |
| 481 'google-play-services_lib') | 489 version_number: version of the library supposed to be installed locally. |
| 490 client_names: names of client libraries to be uploaded. See | |
| 491 utils.ConfigParser for more info. | |
| 492 ''' | |
| 493 relative_package = os.path.join('extras', 'google', 'm2repository') | |
| 482 self.sdk_root = sdk_root | 494 self.sdk_root = sdk_root |
| 495 self.version_number = version_number | |
| 483 | 496 |
| 484 self.package = os.path.join(sdk_root, relative_package) | 497 self.package = os.path.join(sdk_root, relative_package) |
| 485 self.lib_zip_sha1 = os.path.join(self.package, ZIP_FILE_NAME + '.sha1') | 498 self.lib_zip_sha1 = os.path.join(self.package, ZIP_FILE_NAME + '.sha1') |
| 486 self.license = os.path.join(self.package, LICENSE_FILE_NAME) | 499 self.license = os.path.join(self.package, LICENSE_FILE_NAME) |
| 487 self.source_prop = os.path.join(self.package, 'source.properties') | 500 self.source_prop = os.path.join(self.package, 'source.properties') |
| 488 | 501 |
| 489 self.lib = os.path.join(sdk_root, relative_lib) | 502 self.client_paths = [] |
| 490 self.version_xml = os.path.join(self.lib, version_xml_path) | 503 for client in client_names: |
| 504 self.client_paths.append(os.path.join( | |
| 505 self.package, 'com', 'google', 'android', 'gms', client, | |
| 506 version_number, '%s-%s.aar' % (client, version_number))) | |
| 507 | |
| 508 def __repr__(self): | |
| 509 return ("\nsdk_root: " + self.sdk_root + | |
| 510 "\nversion_number: " + self.version_number + | |
| 511 "\npackage: " + self.package + | |
| 512 "\nlib_zip_sha1: " + self.lib_zip_sha1 + | |
| 513 "\nlicense: " + self.license + | |
| 514 "\nsource_prop: " + self.source_prop + | |
| 515 "\nclient_paths: \n - " + '\n - '.join(self.client_paths)) | |
| 491 | 516 |
| 492 | 517 |
| 493 class DummyGsutil(download_from_google_storage.Gsutil): | 518 class DummyGsutil(download_from_google_storage.Gsutil): |
| 494 ''' | 519 ''' |
| 495 Class that replaces Gsutil to use a local directory instead of an online | 520 Class that replaces Gsutil to use a local directory instead of an online |
| 496 bucket. It relies on the fact that Gsutil commands are very similar to shell | 521 bucket. It relies on the fact that Gsutil commands are very similar to shell |
| 497 ones, so for the ones used here (ls, cp), it works to just use them with a | 522 ones, so for the ones used here (ls, cp), it works to just use them with a |
| 498 local directory. | 523 local directory. |
| 499 ''' | 524 ''' |
| 500 | 525 |
| 501 def __init__(self): | 526 def __init__(self): |
| 502 super(DummyGsutil, self).__init__( | 527 super(DummyGsutil, self).__init__( |
| 503 download_from_google_storage.GSUTIL_DEFAULT_PATH) | 528 download_from_google_storage.GSUTIL_DEFAULT_PATH) |
| 504 | 529 |
| 505 def call(self, *args): | 530 def call(self, *args): |
| 506 logging.debug('Calling command "%s"', str(args)) | 531 logging.debug('Calling command "%s"', str(args)) |
| 507 return cmd_helper.GetCmdStatusOutputAndError(args) | 532 return cmd_helper.GetCmdStatusOutputAndError(args) |
| 508 | 533 |
| 509 def check_call(self, *args): | 534 def check_call(self, *args): |
| 510 logging.debug('Calling command "%s"', str(args)) | 535 logging.debug('Calling command "%s"', str(args)) |
| 511 return cmd_helper.GetCmdStatusOutputAndError(args) | 536 return cmd_helper.GetCmdStatusOutputAndError(args) |
| 512 | 537 |
| 513 | 538 |
| 514 if __name__ == '__main__': | 539 if __name__ == '__main__': |
| 515 sys.exit(main(sys.argv[1:])) | 540 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |