| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2013 The Chromium Authors. All rights reserved. | 2 # Copyright 2013 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 """Downloads and unpacks a toolchain for building on Windows. The contents are | 6 """Downloads and unpacks a toolchain for building on Windows. The contents are |
| 7 matched by sha1 which will be updated when the toolchain is updated. | 7 matched by sha1 which will be updated when the toolchain is updated. |
| 8 | 8 |
| 9 Having a toolchain script in depot_tools means that it's not versioned | 9 Having a toolchain script in depot_tools means that it's not versioned |
| 10 directly with the source code. That is, if the toolchain is upgraded, but | 10 directly with the source code. That is, if the toolchain is upgraded, but |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 | 140 |
| 141 | 141 |
| 142 def CanAccessToolchainBucket(): | 142 def CanAccessToolchainBucket(): |
| 143 """Checks whether the user has access to gs://chrome-wintoolchain/.""" | 143 """Checks whether the user has access to gs://chrome-wintoolchain/.""" |
| 144 gsutil = download_from_google_storage.Gsutil( | 144 gsutil = download_from_google_storage.Gsutil( |
| 145 download_from_google_storage.GSUTIL_DEFAULT_PATH, boto_path=None) | 145 download_from_google_storage.GSUTIL_DEFAULT_PATH, boto_path=None) |
| 146 code, _, _ = gsutil.check_call('ls', 'gs://chrome-wintoolchain/') | 146 code, _, _ = gsutil.check_call('ls', 'gs://chrome-wintoolchain/') |
| 147 return code == 0 | 147 return code == 0 |
| 148 | 148 |
| 149 | 149 |
| 150 def ConfigureGsAccess(): | 150 def RequestGsAuthentication(): |
| 151 """Starts the authentication flow for gs://, and confirms that it's | 151 """Requests that the user authenticate to be able to access gs:// as a |
| 152 accessible after completion, or retries indefinitely. | 152 Googler. This allows much faster downloads, and pulling (old) toolchains |
| 153 that match src/ revisions. |
| 153 """ | 154 """ |
| 154 while not CanAccessToolchainBucket(): | 155 print 'Access to gs://chrome-wintoolchain/ not configured.' |
| 155 print 'Access to gs://chrome-wintoolchain/ not configured.' | 156 print '-----------------------------------------------------------------' |
| 156 print '-----------------------------------------------------------------' | 157 print |
| 157 print | 158 print 'You appear to be a Googler.' |
| 158 print 'You appear to be a Googler.' | 159 print |
| 159 print | 160 print 'I\'m sorry for the hassle, but you need to do a one-time manual' |
| 160 print 'I\'m sorry for the hassle, but you need to do a one-time manual' | 161 print 'authentication. Please run:' |
| 161 print 'authentication. Instructions will open in a new window. This is' | 162 print |
| 162 print 'a run of "gsutil config".' | 163 print ' download_from_google_storage --config' |
| 163 print | 164 print |
| 164 print 'NOTE: Just press Enter when asked for a "project-id".' | 165 print 'and follow the instructions. NOTE: Just press Enter when asked for' |
| 165 print | 166 print 'a "project-id".' |
| 166 print '-----------------------------------------------------------------' | 167 print |
| 167 print | 168 print '-----------------------------------------------------------------' |
| 168 sys.stdout.flush() | 169 print |
| 169 # gclient's buffering makes this hang if we're run from inside gclient | 170 sys.stdout.flush() |
| 170 # as is typical. So, spawn a new window for the config prompt. :( | 171 sys.exit(1) |
| 171 subprocess.check_call( | |
| 172 ['start', '/wait', 'cmd', '/c', | |
| 173 'download_from_google_storage', '--config'], | |
| 174 shell=True) | |
| 175 | 172 |
| 176 | 173 |
| 177 def DelayBeforeRemoving(target_dir): | 174 def DelayBeforeRemoving(target_dir): |
| 178 """A grace period before deleting the out of date toolchain directory.""" | 175 """A grace period before deleting the out of date toolchain directory.""" |
| 179 if (os.path.isdir(target_dir) and | 176 if (os.path.isdir(target_dir) and |
| 180 not bool(int(os.environ.get('CHROME_HEADLESS', '0')))): | 177 not bool(int(os.environ.get('CHROME_HEADLESS', '0')))): |
| 181 for i in range(9, 0, -1): | 178 for i in range(9, 0, -1): |
| 182 sys.stdout.write( | 179 sys.stdout.write( |
| 183 '\rRemoving old toolchain in %ds... (Ctrl-C to cancel)' % i) | 180 '\rRemoving old toolchain in %ds... (Ctrl-C to cancel)' % i) |
| 184 sys.stdout.flush() | 181 sys.stdout.flush() |
| 185 time.sleep(1) | 182 time.sleep(1) |
| 186 print | 183 print |
| 187 | 184 |
| 188 | 185 |
| 189 def main(): | 186 def main(): |
| 190 if not sys.platform.startswith(('cygwin', 'win32')): | 187 if not sys.platform.startswith(('cygwin', 'win32')): |
| 191 return 0 | 188 return 0 |
| 192 | 189 |
| 193 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) | 190 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) |
| 194 parser.add_option('--output-json', metavar='FILE', | 191 parser.add_option('--output-json', metavar='FILE', |
| 195 help='write information about toolchain to FILE') | 192 help='write information about toolchain to FILE') |
| 196 options, args = parser.parse_args() | 193 options, args = parser.parse_args() |
| 197 | 194 |
| 198 # We assume that the Pro hash is the first one. | 195 # We assume that the Pro hash is the first one. |
| 199 desired_hashes = args | 196 desired_hashes = args |
| 197 if len(desired_hashes) == 0: |
| 198 sys.exit('Desired hashes are required.') |
| 200 | 199 |
| 201 # Move to depot_tools\win_toolchain where we'll store our files, and where | 200 # Move to depot_tools\win_toolchain where we'll store our files, and where |
| 202 # the downloader script is. | 201 # the downloader script is. |
| 203 os.chdir(os.path.normpath(os.path.join(BASEDIR))) | 202 os.chdir(os.path.normpath(os.path.join(BASEDIR))) |
| 204 toolchain_dir = '.' | 203 toolchain_dir = '.' |
| 205 target_dir = os.path.normpath(os.path.join(toolchain_dir, 'vs2013_files')) | 204 target_dir = os.path.normpath(os.path.join(toolchain_dir, 'vs2013_files')) |
| 206 | 205 |
| 207 # If the current hash doesn't match what we want in the file, nuke and pave. | 206 # If the current hash doesn't match what we want in the file, nuke and pave. |
| 208 # Typically this script is only run when the .sha1 one file is updated, but | 207 # Typically this script is only run when the .sha1 one file is updated, but |
| 209 # directly calling "gclient runhooks" will also run it, so we cache | 208 # directly calling "gclient runhooks" will also run it, so we cache |
| 210 # based on timestamps to make that case fast. | 209 # based on timestamps to make that case fast. |
| 211 current_hash = CalculateHash(target_dir) | 210 current_hash = CalculateHash(target_dir) |
| 212 if current_hash not in desired_hashes: | 211 if current_hash not in desired_hashes: |
| 213 should_use_gs = False | 212 should_use_gs = False |
| 214 if (CanAccessToolchainBucket() or | 213 if HaveSrcInternalAccess() or LooksLikeGoogler(): |
| 215 HaveSrcInternalAccess() or | |
| 216 LooksLikeGoogler()): | |
| 217 should_use_gs = True | 214 should_use_gs = True |
| 218 ConfigureGsAccess() | 215 if not CanAccessToolchainBucket(): |
| 216 RequestGsAuthentication() |
| 219 print('Windows toolchain out of date or doesn\'t exist, updating (%s)...' % | 217 print('Windows toolchain out of date or doesn\'t exist, updating (%s)...' % |
| 220 ('Pro' if should_use_gs else 'Express')) | 218 ('Pro' if should_use_gs else 'Express')) |
| 221 print(' current_hash: %s' % current_hash) | 219 print(' current_hash: %s' % current_hash) |
| 222 print(' desired_hashes: %s' % ', '.join(desired_hashes)) | 220 print(' desired_hashes: %s' % ', '.join(desired_hashes)) |
| 223 sys.stdout.flush() | 221 sys.stdout.flush() |
| 224 DelayBeforeRemoving(target_dir) | 222 DelayBeforeRemoving(target_dir) |
| 225 # This stays resident and will make the rmdir below fail. | 223 # This stays resident and will make the rmdir below fail. |
| 226 with open(os.devnull, 'wb') as nul: | 224 with open(os.devnull, 'wb') as nul: |
| 227 subprocess.call(['taskkill', '/f', '/im', 'mspdbsrv.exe'], | 225 subprocess.call(['taskkill', '/f', '/im', 'mspdbsrv.exe'], |
| 228 stdin=nul, stdout=nul, stderr=nul) | 226 stdin=nul, stdout=nul, stderr=nul) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 248 | 246 |
| 249 if options.output_json: | 247 if options.output_json: |
| 250 shutil.copyfile(os.path.join(target_dir, '..', 'data.json'), | 248 shutil.copyfile(os.path.join(target_dir, '..', 'data.json'), |
| 251 options.output_json) | 249 options.output_json) |
| 252 | 250 |
| 253 return 0 | 251 return 0 |
| 254 | 252 |
| 255 | 253 |
| 256 if __name__ == '__main__': | 254 if __name__ == '__main__': |
| 257 sys.exit(main()) | 255 sys.exit(main()) |
| OLD | NEW |