| 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 20 matching lines...) Expand all Loading... |
| 31 import json | 31 import json |
| 32 import optparse | 32 import optparse |
| 33 import os | 33 import os |
| 34 import shutil | 34 import shutil |
| 35 import subprocess | 35 import subprocess |
| 36 import sys | 36 import sys |
| 37 import time | 37 import time |
| 38 | 38 |
| 39 | 39 |
| 40 BASEDIR = os.path.dirname(os.path.abspath(__file__)) | 40 BASEDIR = os.path.dirname(os.path.abspath(__file__)) |
| 41 sys.path.append(os.path.join(BASEDIR, '..')) |
| 42 import download_from_google_storage |
| 41 | 43 |
| 42 | 44 |
| 43 GetFileAttributes = ctypes.windll.kernel32.GetFileAttributesW | 45 GetFileAttributes = ctypes.windll.kernel32.GetFileAttributesW |
| 44 GetFileAttributes.argtypes = (ctypes.wintypes.LPWSTR,) | 46 GetFileAttributes.argtypes = (ctypes.wintypes.LPWSTR,) |
| 45 GetFileAttributes.restype = ctypes.wintypes.DWORD | 47 GetFileAttributes.restype = ctypes.wintypes.DWORD |
| 46 FILE_ATTRIBUTE_HIDDEN = 0x2 | 48 FILE_ATTRIBUTE_HIDDEN = 0x2 |
| 47 FILE_ATTRIBUTE_SYSTEM = 0x4 | 49 FILE_ATTRIBUTE_SYSTEM = 0x4 |
| 48 | 50 |
| 49 | 51 |
| 50 def IsHidden(file_path): | 52 def IsHidden(file_path): |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 ['svn', 'ls', '--non-interactive', | 126 ['svn', 'ls', '--non-interactive', |
| 125 'svn://svn.chromium.org/chrome-internal/trunk/src-internal/'], | 127 'svn://svn.chromium.org/chrome-internal/trunk/src-internal/'], |
| 126 shell=True, stdin=nul, stdout=nul, stderr=nul) == 0: | 128 shell=True, stdin=nul, stdout=nul, stderr=nul) == 0: |
| 127 return True | 129 return True |
| 128 return subprocess.call( | 130 return subprocess.call( |
| 129 ['git', '-c', 'core.askpass=true', 'remote', 'show', | 131 ['git', '-c', 'core.askpass=true', 'remote', 'show', |
| 130 'https://chrome-internal.googlesource.com/chrome/src-internal/'], | 132 'https://chrome-internal.googlesource.com/chrome/src-internal/'], |
| 131 shell=True, stdin=nul, stdout=nul, stderr=nul) == 0 | 133 shell=True, stdin=nul, stdout=nul, stderr=nul) == 0 |
| 132 | 134 |
| 133 | 135 |
| 136 def LooksLikeGoogler(): |
| 137 """Checks for a USERDOMAIN environment variable of 'GOOGLE', which |
| 138 probably implies the current user is a Googler.""" |
| 139 return os.environ.get('USERDOMAIN').upper() == 'GOOGLE' |
| 140 |
| 141 |
| 142 def CanAccessToolchainBucket(): |
| 143 """Checks whether the user has access to gs://chrome-wintoolchain/.""" |
| 144 gsutil = download_from_google_storage.Gsutil( |
| 145 download_from_google_storage.GSUTIL_DEFAULT_PATH, boto_path=None) |
| 146 code, _, _ = gsutil.check_call('ls', 'gs://chrome-wintoolchain/') |
| 147 return code == 0 |
| 148 |
| 149 |
| 150 def ConfigureGsAccess(): |
| 151 """Starts the authentication flow for gs://, and confirms that it's |
| 152 accessible after completion, or retries indefinitely. |
| 153 """ |
| 154 while not CanAccessToolchainBucket(): |
| 155 print 'Access to gs://chrome-wintoolchain/ not configured.' |
| 156 print '-----------------------------------------------------------------' |
| 157 print |
| 158 print 'You appear to be a Googler.' |
| 159 print |
| 160 print 'I\'m sorry for the hassle, but you need to do a one-time manual' |
| 161 print 'authentication. Instructions will open in a new window. This is' |
| 162 print 'a run of "gsutil config".' |
| 163 print |
| 164 print 'NOTE: Just press Enter when asked for a "project-id".' |
| 165 print |
| 166 print '-----------------------------------------------------------------' |
| 167 print |
| 168 sys.stdout.flush() |
| 169 # gclient's buffering makes this hang if we're run from inside gclient |
| 170 # as is typical. So, spawn a new window for the config prompt. :( |
| 171 subprocess.check_call( |
| 172 ['start', '/wait', 'cmd', '/c', |
| 173 'download_from_google_storage', '--config'], |
| 174 shell=True) |
| 175 |
| 176 |
| 134 def DelayBeforeRemoving(target_dir): | 177 def DelayBeforeRemoving(target_dir): |
| 135 """A grace period before deleting the out of date toolchain directory.""" | 178 """A grace period before deleting the out of date toolchain directory.""" |
| 136 if (os.path.isdir(target_dir) and | 179 if (os.path.isdir(target_dir) and |
| 137 not bool(int(os.environ.get('CHROME_HEADLESS', '0')))): | 180 not bool(int(os.environ.get('CHROME_HEADLESS', '0')))): |
| 138 for i in range(9, 0, -1): | 181 for i in range(9, 0, -1): |
| 139 sys.stdout.write( | 182 sys.stdout.write( |
| 140 '\rRemoving old toolchain in %ds... (Ctrl-C to cancel)' % i) | 183 '\rRemoving old toolchain in %ds... (Ctrl-C to cancel)' % i) |
| 141 sys.stdout.flush() | 184 sys.stdout.flush() |
| 142 time.sleep(1) | 185 time.sleep(1) |
| 143 print | 186 print |
| (...skipping 16 matching lines...) Expand all Loading... |
| 160 os.chdir(os.path.normpath(os.path.join(BASEDIR))) | 203 os.chdir(os.path.normpath(os.path.join(BASEDIR))) |
| 161 toolchain_dir = '.' | 204 toolchain_dir = '.' |
| 162 target_dir = os.path.normpath(os.path.join(toolchain_dir, 'vs2013_files')) | 205 target_dir = os.path.normpath(os.path.join(toolchain_dir, 'vs2013_files')) |
| 163 | 206 |
| 164 # If the current hash doesn't match what we want in the file, nuke and pave. | 207 # If the current hash doesn't match what we want in the file, nuke and pave. |
| 165 # Typically this script is only run when the .sha1 one file is updated, but | 208 # Typically this script is only run when the .sha1 one file is updated, but |
| 166 # directly calling "gclient runhooks" will also run it, so we cache | 209 # directly calling "gclient runhooks" will also run it, so we cache |
| 167 # based on timestamps to make that case fast. | 210 # based on timestamps to make that case fast. |
| 168 current_hash = CalculateHash(target_dir) | 211 current_hash = CalculateHash(target_dir) |
| 169 if current_hash not in desired_hashes: | 212 if current_hash not in desired_hashes: |
| 170 should_get_pro = (os.path.isfile(os.path.join(BASEDIR, '.vspro')) or | 213 should_use_gs = False |
| 171 HaveSrcInternalAccess()) | 214 if (CanAccessToolchainBucket() or |
| 215 HaveSrcInternalAccess() or |
| 216 LooksLikeGoogler()): |
| 217 should_use_gs = True |
| 218 ConfigureGsAccess() |
| 172 print('Windows toolchain out of date or doesn\'t exist, updating (%s)...' % | 219 print('Windows toolchain out of date or doesn\'t exist, updating (%s)...' % |
| 173 ('Pro' if should_get_pro else 'Express')) | 220 ('Pro' if should_use_gs else 'Express')) |
| 174 print(' current_hash: %s' % current_hash) | 221 print(' current_hash: %s' % current_hash) |
| 175 print(' desired_hashes: %s' % ', '.join(desired_hashes)) | 222 print(' desired_hashes: %s' % ', '.join(desired_hashes)) |
| 223 sys.stdout.flush() |
| 176 DelayBeforeRemoving(target_dir) | 224 DelayBeforeRemoving(target_dir) |
| 177 # This stays resident and will make the rmdir below fail. | 225 # This stays resident and will make the rmdir below fail. |
| 178 with open(os.devnull, 'wb') as nul: | 226 with open(os.devnull, 'wb') as nul: |
| 179 subprocess.call(['taskkill', '/f', '/im', 'mspdbsrv.exe'], | 227 subprocess.call(['taskkill', '/f', '/im', 'mspdbsrv.exe'], |
| 180 stdin=nul, stdout=nul, stderr=nul) | 228 stdin=nul, stdout=nul, stderr=nul) |
| 181 if os.path.isdir(target_dir): | 229 if os.path.isdir(target_dir): |
| 182 subprocess.check_call('rmdir /s/q "%s"' % target_dir, shell=True) | 230 subprocess.check_call('rmdir /s/q "%s"' % target_dir, shell=True) |
| 183 args = [sys.executable, | 231 args = [sys.executable, |
| 184 'toolchain2013.py', | 232 'toolchain2013.py', |
| 185 '--targetdir', target_dir, | 233 '--targetdir', target_dir, |
| 186 '--sha1', desired_hashes[0]] | 234 '--sha1', desired_hashes[0]] |
| 187 if not should_get_pro: | 235 if should_use_gs: |
| 236 args.append('--use-gs') |
| 237 else: |
| 188 args.append('--express') | 238 args.append('--express') |
| 189 subprocess.check_call(args) | 239 subprocess.check_call(args) |
| 190 current_hash = CalculateHash(target_dir) | 240 current_hash = CalculateHash(target_dir) |
| 191 if current_hash not in desired_hashes: | 241 if current_hash not in desired_hashes: |
| 192 print >> sys.stderr, ( | 242 print >> sys.stderr, ( |
| 193 'Got wrong hash after pulling a new toolchain. ' | 243 'Got wrong hash after pulling a new toolchain. ' |
| 194 'Wanted one of \'%s\', got \'%s\'.' % ( | 244 'Wanted one of \'%s\', got \'%s\'.' % ( |
| 195 ', '.join(desired_hashes), current_hash)) | 245 ', '.join(desired_hashes), current_hash)) |
| 196 return 1 | 246 return 1 |
| 197 SaveTimestampsAndHash(target_dir, current_hash) | 247 SaveTimestampsAndHash(target_dir, current_hash) |
| 198 | 248 |
| 199 if options.output_json: | 249 if options.output_json: |
| 200 shutil.copyfile(os.path.join(target_dir, '..', 'data.json'), | 250 shutil.copyfile(os.path.join(target_dir, '..', 'data.json'), |
| 201 options.output_json) | 251 options.output_json) |
| 202 | 252 |
| 203 return 0 | 253 return 0 |
| 204 | 254 |
| 205 | 255 |
| 206 if __name__ == '__main__': | 256 if __name__ == '__main__': |
| 207 sys.exit(main()) | 257 sys.exit(main()) |
| OLD | NEW |