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

Side by Side Diff: build/android/play_services/update.py

Issue 1418833005: [gms updater] Fixes and tests to prepare activation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix merge arg declaration, fix sdk command Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « build/android/PRESUBMIT.py ('k') | build/android/play_services/update_test.py » ('j') | 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 # 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 client 7 Script to help uploading and downloading the Google Play services client
8 library to and from a Google Cloud storage. 8 library to and from a Google Cloud storage.
9 ''' 9 '''
10 10
(...skipping 19 matching lines...) Expand all
30 import download_from_google_storage 30 import download_from_google_storage
31 import upload_to_google_storage 31 import upload_to_google_storage
32 32
33 33
34 # Directory where the SHA1 files for the zip and the license are stored 34 # Directory where the SHA1 files for the zip and the license are stored
35 # It should be managed by git to provided information about new versions. 35 # It should be managed by git to provided information about new versions.
36 SHA1_DIRECTORY = os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'android', 36 SHA1_DIRECTORY = os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'android',
37 'play_services') 37 'play_services')
38 38
39 # Default bucket used for storing the files. 39 # Default bucket used for storing the files.
40 GMS_CLOUD_STORAGE = 'chrome-sdk-extras' 40 GMS_CLOUD_STORAGE = 'chromium-android-tools/play-services'
41 41
42 # Path to the default configuration file. It exposes the currently installed 42 # Path to the default configuration file. It exposes the currently installed
43 # version of the library in a human readable way. 43 # version of the library in a human readable way.
44 CONFIG_DEFAULT_PATH = os.path.join(constants.DIR_SOURCE_ROOT, 'build', 44 CONFIG_DEFAULT_PATH = os.path.join(constants.DIR_SOURCE_ROOT, 'build',
45 'android', 'play_services', 'config.json') 45 'android', 'play_services', 'config.json')
46 46
47 LICENSE_FILE_NAME = 'LICENSE' 47 LICENSE_FILE_NAME = 'LICENSE'
48 LIBRARY_FILE_NAME = 'google_play_services_library.zip' 48 LIBRARY_FILE_NAME = 'google_play_services_library.zip'
49 GMS_PACKAGE_ID = 'extra-google-google_play_services' # used by sdk manager 49 GMS_PACKAGE_ID = 'extra-google-google_play_services' # used by sdk manager
50 50
51 LICENSE_PATTERN = re.compile(r'^Pkg\.License=(?P<text>.*)$', re.MULTILINE) 51 LICENSE_PATTERN = re.compile(r'^Pkg\.License=(?P<text>.*)$', re.MULTILINE)
52 52
53 53
54 def Main(): 54 def Main(raw_args):
jbudorick 2015/11/04 16:56:32 nit: missed this before, but s/Main/main/
dgn 2015/11/04 18:43:58 Done.
55 parser = argparse.ArgumentParser( 55 parser = argparse.ArgumentParser(
56 description=__doc__ + 'Please see the subcommand help for more details.', 56 description=__doc__ + 'Please see the subcommand help for more details.',
57 formatter_class=utils.DefaultsRawHelpFormatter) 57 formatter_class=utils.DefaultsRawHelpFormatter)
58 subparsers = parser.add_subparsers(title='commands') 58 subparsers = parser.add_subparsers(title='commands')
59 59
60 # Download arguments 60 # Download arguments
61 parser_download = subparsers.add_parser( 61 parser_download = subparsers.add_parser(
62 'download', 62 'download',
63 help='download the library from the cloud storage', 63 help='download the library from the cloud storage',
64 description=Download.__doc__, 64 description=Download.__doc__,
65 formatter_class=utils.DefaultsRawHelpFormatter) 65 formatter_class=utils.DefaultsRawHelpFormatter)
66 parser_download.add_argument('-f', '--force',
67 action='store_true',
68 help=('run even if the local version is '
69 'already up to date'))
70 parser_download.set_defaults(func=Download) 66 parser_download.set_defaults(func=Download)
71 AddCommonArguments(parser_download) 67 AddArguments(parser_download, bucket=True, config=True, dry_run=True,
68 force=True, sdk_root=True, verbose=True)
jbudorick 2015/11/04 16:56:32 nit: indentation
dgn 2015/11/04 18:43:58 Done.
72 69
73 # SDK Update arguments 70 # SDK Update arguments
74 parser_sdk = subparsers.add_parser( 71 parser_sdk = subparsers.add_parser(
75 'sdk', 72 'sdk',
76 help='update the local sdk using the Android SDK Manager', 73 help='update the local sdk using the Android SDK Manager',
77 description=UpdateSdk.__doc__, 74 description=UpdateSdk.__doc__,
78 formatter_class=utils.DefaultsRawHelpFormatter) 75 formatter_class=utils.DefaultsRawHelpFormatter)
79 parser_sdk.add_argument('--sdk-root',
80 help=('base path to the Android SDK tools to use to '
81 'update the library'),
82 default=constants.ANDROID_SDK_ROOT)
83 parser_sdk.add_argument('-v', '--verbose',
84 action='store_true',
85 help='print debug information')
86 parser_sdk.set_defaults(func=UpdateSdk) 76 parser_sdk.set_defaults(func=UpdateSdk)
77 AddArguments(parser_sdk, verbose=True, sdk_root=True)
87 78
88 # Upload arguments 79 # Upload arguments
89 parser_upload = subparsers.add_parser( 80 parser_upload = subparsers.add_parser(
90 'upload', 81 'upload',
91 help='upload the library to the cloud storage', 82 help='upload the library to the cloud storage',
92 description=Upload.__doc__, 83 description=Upload.__doc__,
93 formatter_class=utils.DefaultsRawHelpFormatter) 84 formatter_class=utils.DefaultsRawHelpFormatter)
94 parser_upload.add_argument('-f', '--force', 85
95 action='store_true',
96 help=('run even if the checked in version is '
97 'already up to date'))
98 parser_upload.add_argument('--sdk-root',
99 help=('base path to the Android SDK tools to use '
100 'to update the library'),
101 default=constants.ANDROID_SDK_ROOT)
102 parser_upload.add_argument('--skip-git', 86 parser_upload.add_argument('--skip-git',
103 action='store_true', 87 action='store_true',
104 help="don't commit the changes at the end") 88 help="don't commit the changes at the end")
105 parser_upload.set_defaults(func=Upload) 89 parser_upload.set_defaults(func=Upload)
106 AddCommonArguments(parser_upload) 90 AddArguments(parser_upload, bucket=True, config=True, dry_run=True,
91 force=True, sdk_root=True, verbose=True)
jbudorick 2015/11/04 16:56:32 nit: indentation
dgn 2015/11/04 18:43:58 Done.
107 92
108 args = parser.parse_args() 93 args = parser.parse_args(raw_args)
109 if args.verbose: 94 if args.verbose:
110 logging.basicConfig(level=logging.DEBUG) 95 logging.basicConfig(level=logging.DEBUG)
111 logging_utils.ColorStreamHandler.MakeDefault() 96 logging_utils.ColorStreamHandler.MakeDefault(not _IsBotEnvironment())
112 return args.func(args) 97 return args.func(args)
113 98
114 99 def AddArguments(parser, bucket=False, config=False, dry_run=False,
jbudorick 2015/11/04 16:56:32 Split this into two functions without all of these
dgn 2015/11/04 18:43:58 Done.
115 def AddCommonArguments(parser): 100 force=False, sdk_root=False, verbose=False):
jbudorick 2015/11/04 16:56:32 nit: indentation
dgn 2015/11/04 18:43:58 Done.
116 ''' 101 '''
117 Defines the common arguments on subparser rather than the main one. This 102 Defines the common arguments on subparser rather than the main one. This
118 allows to put arguments after the command: `foo.py upload --debug --force` 103 allows to put arguments after the command: `foo.py upload --debug --force`
119 instead of `foo.py --debug upload --force` 104 instead of `foo.py --debug upload --force`
120 ''' 105 '''
121 106
122 parser.add_argument('--bucket', 107 if bucket:
123 help='name of the bucket where the files are stored', 108 parser.add_argument('--bucket',
124 default=GMS_CLOUD_STORAGE) 109 help='name of the bucket where the files are stored',
125 parser.add_argument('--config', 110 default=GMS_CLOUD_STORAGE)
126 help='JSON Configuration file', 111
127 default=CONFIG_DEFAULT_PATH) 112 if config:
128 parser.add_argument('--dry-run', 113 parser.add_argument('--config',
129 action='store_true', 114 help='JSON Configuration file',
130 help=('run the script in dry run mode. Files will be ' 115 default=CONFIG_DEFAULT_PATH)
131 'copied to a local directory instead of the cloud ' 116
132 'storage. The bucket name will be as path to that ' 117 if dry_run:
133 'directory relative to the repository root.')) 118 parser.add_argument('--dry-run',
134 parser.add_argument('-v', '--verbose', 119 action='store_true',
135 action='store_true', 120 help=('run the script in dry run mode. Files will be '
136 help='print debug information') 121 'copied to a local directory instead of the '
122 'cloud storage. The bucket name will be as path '
123 'to that directory relative to the repository '
124 'root.'))
125
126 if force:
127 parser.add_argument('-f', '--force',
128 action='store_true',
129 help=('run even if the library is already '
130 ' up to date'))
131
132 if sdk_root:
133 parser.add_argument('--sdk-root',
134 help=('base path to the Android SDK tools to use when'
135 'updating the library'),
136 default=constants.ANDROID_SDK_ROOT)
137
138 if verbose:
139 parser.add_argument('-v', '--verbose',
140 action='store_true',
141 help='print debug information')
137 142
138 143
139 def Download(args): 144 def Download(args):
140 ''' 145 '''
141 Downloads the Google Play services client library from a Google Cloud Storage 146 Downloads the Google Play services client library from a Google Cloud Storage
142 bucket and installs it to 147 bucket and installs it to
143 //third_party/android_tools/sdk/extras/google/google_play_services. 148 //third_party/android_tools/sdk/extras/google/google_play_services.
144 149
145 A license check will be made, and the user might have to accept the license 150 A license check will be made, and the user might have to accept the license
146 if that has not been done before. 151 if that has not been done before.
147 ''' 152 '''
148 153
149 paths = _InitPaths(constants.ANDROID_SDK_ROOT) 154 if not os.path.isdir(args.sdk_root):
155 logging.debug('Did not find the android sdk directory at "%s".',
156 args.sdk_root)
157 if not args.force:
158 logging.info('Skipping, not on an android checkout.')
159 return 0
160
161 paths = _InitPaths(args.sdk_root)
150 162
151 new_lib_zip_sha1 = os.path.join(SHA1_DIRECTORY, LIBRARY_FILE_NAME + '.sha1') 163 new_lib_zip_sha1 = os.path.join(SHA1_DIRECTORY, LIBRARY_FILE_NAME + '.sha1')
152 old_lib_zip_sha1 = os.path.join(paths.package, LIBRARY_FILE_NAME + '.sha1') 164 old_lib_zip_sha1 = os.path.join(paths.package, LIBRARY_FILE_NAME + '.sha1')
153 165
154 logging.debug('Comparing library hashes: %s and %s', new_lib_zip_sha1, 166 logging.debug('Comparing library hashes: %s and %s', new_lib_zip_sha1,
155 old_lib_zip_sha1) 167 old_lib_zip_sha1)
156 if utils.FileEquals(new_lib_zip_sha1, old_lib_zip_sha1) and not args.force: 168 if utils.FileEquals(new_lib_zip_sha1, old_lib_zip_sha1) and not args.force:
157 logging.debug('The Google Play services library is up to date.') 169 logging.info('Skipping, the Google Play services library is up to date.')
158 return 0 170 return 0
159 171
160 config = utils.ConfigParser(args.config) 172 config = utils.ConfigParser(args.config)
161 bucket_path = _VerifyBucketPathFormat(args.bucket, 173 bucket_path = _VerifyBucketPathFormat(args.bucket,
162 config.version_number, 174 config.version_number,
163 args.dry_run) 175 args.dry_run)
164 176
165 tmp_root = tempfile.mkdtemp() 177 tmp_root = tempfile.mkdtemp()
166 try: 178 try:
167 if not os.environ.get('CHROME_HEADLESS'): 179 # setup the destination directory
168 if not os.path.isdir(paths.package): 180 if not os.path.isdir(paths.package):
169 os.makedirs(paths.package) 181 os.makedirs(paths.package)
170 182
171 # download license file from bucket/{version_number}/license.sha1 183 # download license file from bucket/{version_number}/license.sha1
172 new_license = os.path.join(tmp_root, LICENSE_FILE_NAME) 184 new_license = os.path.join(tmp_root, LICENSE_FILE_NAME)
173 old_license = os.path.join(paths.package, LICENSE_FILE_NAME) 185 old_license = os.path.join(paths.package, LICENSE_FILE_NAME)
174 186
175 license_sha1 = os.path.join(SHA1_DIRECTORY, LICENSE_FILE_NAME + '.sha1') 187 license_sha1 = os.path.join(SHA1_DIRECTORY, LICENSE_FILE_NAME + '.sha1')
176 _DownloadFromBucket(bucket_path, license_sha1, new_license, 188 _DownloadFromBucket(bucket_path, license_sha1, new_license,
jbudorick 2015/11/04 16:56:32 This is now downloading the license on the bot whe
dgn 2015/11/04 18:43:58 Yes. It failed at some point where the paths were
177 args.verbose, args.dry_run) 189 args.verbose, args.dry_run)
178 if not _CheckLicenseAgreement(new_license, old_license): 190
191 if (not _IsBotEnvironment() and
192 not _CheckLicenseAgreement(new_license, old_license)):
179 logging.warning('Your version of the Google Play services library is ' 193 logging.warning('Your version of the Google Play services library is '
180 'not up to date. You might run into issues building ' 194 'not up to date. You might run into issues building '
181 'or running the app. Please run `%s download` to ' 195 'or running the app. Please run `%s download` to '
182 'retry downloading it.', __file__) 196 'retry downloading it.', __file__)
183 return 0 197 return 0
184 198
185 new_lib_zip = os.path.join(tmp_root, LIBRARY_FILE_NAME) 199 new_lib_zip = os.path.join(tmp_root, LIBRARY_FILE_NAME)
186 _DownloadFromBucket(bucket_path, new_lib_zip_sha1, new_lib_zip, 200 _DownloadFromBucket(bucket_path, new_lib_zip_sha1, new_lib_zip,
187 args.verbose, args.dry_run) 201 args.verbose, args.dry_run)
188 202
189 # We remove only the library itself. Users having a SDK manager installed 203 # We remove the library itself. Users having a SDK manager installed
190 # library before will keep the documentation and samples from it. 204 # library before will keep the documentation and samples from it.
191 shutil.rmtree(paths.lib, ignore_errors=True) 205 shutil.rmtree(paths.lib, ignore_errors=True)
192 os.makedirs(paths.lib) 206 os.makedirs(paths.lib)
193 207
208 # We also remove source.properties so that the SDK manager doesn't fail
209 # recognizing that it didn't install the local version.
210 source_prop = os.path.join(paths.package, 'source.properties')
211 if os.path.isfile(source_prop):
212 os.remove(source_prop)
213
194 logging.debug('Extracting the library to %s', paths.lib) 214 logging.debug('Extracting the library to %s', paths.lib)
195 with zipfile.ZipFile(new_lib_zip, "r") as new_lib_zip_file: 215 with zipfile.ZipFile(new_lib_zip, "r") as new_lib_zip_file:
196 new_lib_zip_file.extractall(paths.lib) 216 new_lib_zip_file.extractall(paths.lib)
197 217
198 logging.debug('Copying %s to %s', new_license, old_license) 218 logging.debug('Copying %s to %s', new_license, old_license)
199 shutil.copy(new_license, old_license) 219 shutil.copy(new_license, old_license)
200 220
201 logging.debug('Copying %s to %s', new_lib_zip_sha1, old_lib_zip_sha1) 221 logging.debug('Copying %s to %s', new_lib_zip_sha1, old_lib_zip_sha1)
202 shutil.copy(new_lib_zip_sha1, old_lib_zip_sha1) 222 shutil.copy(new_lib_zip_sha1, old_lib_zip_sha1)
203 223
224 logging.info('Update complete.')
204 finally: 225 finally:
205 shutil.rmtree(tmp_root) 226 shutil.rmtree(tmp_root)
206 227
207 return 0 228 return 0
208 229
209 230
210 def UpdateSdk(args): 231 def UpdateSdk(args):
211 ''' 232 '''
212 Uses the Android SDK Manager to update or download the local Google Play 233 Uses the Android SDK Manager to update or download the local Google Play
213 services library. Its usual installation path is 234 services library. Its usual installation path is
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 print license_part 423 print license_part
403 sys.stdout.flush() 424 sys.stdout.flush()
404 425
405 # Need to put the prompt on a separate line otherwise the gclient hook buffer 426 # Need to put the prompt on a separate line otherwise the gclient hook buffer
406 # only prints it after we received an input. 427 # only prints it after we received an input.
407 print 'Do you accept the license? [y/n]: ' 428 print 'Do you accept the license? [y/n]: '
408 sys.stdout.flush() 429 sys.stdout.flush()
409 return raw_input('> ') in ('Y', 'y') 430 return raw_input('> ') in ('Y', 'y')
410 431
411 432
433 def _IsBotEnvironment():
434 return bool(os.environ.get('CHROME_HEADLESS'))
435
436
412 def _VerifyBucketPathFormat(bucket_name, version_number, is_dry_run): 437 def _VerifyBucketPathFormat(bucket_name, version_number, is_dry_run):
413 ''' 438 '''
414 Formats and checks the download/upload path depending on whether we are 439 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 440 running in dry run mode or not. Returns a supposedly safe path to use with
416 Gsutil. 441 Gsutil.
417 ''' 442 '''
418 443
419 if is_dry_run: 444 if is_dry_run:
420 bucket_path = os.path.abspath(os.path.join(bucket_name, 445 bucket_path = os.path.abspath(os.path.join(bucket_name,
421 str(version_number))) 446 str(version_number)))
(...skipping 25 matching lines...) Expand all
447 def call(self, *args): 472 def call(self, *args):
448 logging.debug('Calling command "%s"', str(args)) 473 logging.debug('Calling command "%s"', str(args))
449 return cmd_helper.GetCmdStatusOutputAndError(args) 474 return cmd_helper.GetCmdStatusOutputAndError(args)
450 475
451 def check_call(self, *args): 476 def check_call(self, *args):
452 logging.debug('Calling command "%s"', str(args)) 477 logging.debug('Calling command "%s"', str(args))
453 return cmd_helper.GetCmdStatusOutputAndError(args) 478 return cmd_helper.GetCmdStatusOutputAndError(args)
454 479
455 480
456 if __name__ == '__main__': 481 if __name__ == '__main__':
457 sys.exit(Main()) 482 sys.exit(Main(sys.argv[1:]))
jbudorick 2015/11/04 16:56:32 don't pass anything to Main, and don't pass anythi
dgn 2015/11/04 18:43:58 This is to allow providing arguments in the tests.
OLDNEW
« no previous file with comments | « build/android/PRESUBMIT.py ('k') | build/android/play_services/update_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698