Chromium Code Reviews| 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 30 matching lines...) Expand all Loading... | |
| 41 BASEDIR = os.path.dirname(os.path.abspath(__file__)) | 41 BASEDIR = os.path.dirname(os.path.abspath(__file__)) |
| 42 DEPOT_TOOLS_PATH = os.path.join(BASEDIR, '..') | 42 DEPOT_TOOLS_PATH = os.path.join(BASEDIR, '..') |
| 43 sys.path.append(DEPOT_TOOLS_PATH) | 43 sys.path.append(DEPOT_TOOLS_PATH) |
| 44 try: | 44 try: |
| 45 import download_from_google_storage | 45 import download_from_google_storage |
| 46 except ImportError: | 46 except ImportError: |
| 47 # Allow use of utility functions in this script from package_from_installed | 47 # Allow use of utility functions in this script from package_from_installed |
| 48 # on bare VM that doesn't have a full depot_tools. | 48 # on bare VM that doesn't have a full depot_tools. |
| 49 pass | 49 pass |
| 50 | 50 |
| 51 if sys.platform != 'cygwin': | 51 if sys.platform == 'win32': |
| 52 import ctypes.wintypes | 52 import ctypes.wintypes |
| 53 GetFileAttributes = ctypes.windll.kernel32.GetFileAttributesW | 53 GetFileAttributes = ctypes.windll.kernel32.GetFileAttributesW |
| 54 GetFileAttributes.argtypes = (ctypes.wintypes.LPWSTR,) | 54 GetFileAttributes.argtypes = (ctypes.wintypes.LPWSTR,) |
| 55 GetFileAttributes.restype = ctypes.wintypes.DWORD | 55 GetFileAttributes.restype = ctypes.wintypes.DWORD |
|
Nico
2015/06/12 05:29:05
This won't work on non-win…
| |
| 56 FILE_ATTRIBUTE_HIDDEN = 0x2 | 56 FILE_ATTRIBUTE_HIDDEN = 0x2 |
| 57 FILE_ATTRIBUTE_SYSTEM = 0x4 | 57 FILE_ATTRIBUTE_SYSTEM = 0x4 |
| 58 | 58 |
| 59 | |
| 60 def IsHidden(file_path): | 59 def IsHidden(file_path): |
| 61 """Returns whether the given |file_path| has the 'system' or 'hidden' | 60 """Returns whether the given |file_path| has the 'system' or 'hidden' |
| 62 attribute set.""" | 61 attribute set.""" |
| 62 if sys.platform != 'win32': | |
| 63 return False | |
|
Nico
2015/06/12 05:29:05
…so I have to do this, which means the hashes will
scottmg
2015/06/12 16:59:12
I had forgotten why. The long ago rationale was he
Nico
2015/06/12 17:04:29
No, I just saw that the hash didn't match and figu
| |
| 63 p = GetFileAttributes(file_path) | 64 p = GetFileAttributes(file_path) |
| 64 assert p != 0xffffffff | 65 assert p != 0xffffffff |
| 65 return bool(p & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) | 66 return bool(p & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) |
| 66 | 67 |
| 67 | 68 |
| 68 def GetFileList(root): | 69 def GetFileList(root): |
| 69 """Gets a normalized list of files under |root|.""" | 70 """Gets a normalized list of files under |root|.""" |
| 70 assert not os.path.isabs(root) | 71 assert not os.path.isabs(root) |
| 71 assert os.path.normpath(root) == root | 72 assert os.path.normpath(root) == root |
|
scottmg
2015/06/12 16:59:12
It seems like posix.normpath vs. nt.normpath might
| |
| 72 file_list = [] | 73 file_list = [] |
| 73 for base, _, files in os.walk(root): | 74 for base, _, files in os.walk(root): |
| 74 paths = [os.path.join(base, f) for f in files] | 75 paths = [os.path.join(base, f) for f in files] |
| 75 file_list.extend(x.lower() for x in paths if not IsHidden(x)) | 76 file_list.extend(x.lower() for x in paths if not IsHidden(x)) |
| 76 return sorted(file_list) | 77 return sorted(file_list) |
| 77 | 78 |
| 78 | 79 |
| 79 def MakeTimestampsFileName(root): | 80 def MakeTimestampsFileName(root): |
| 80 return os.path.join(root, '..', '.timestamps') | 81 return os.path.join(root, '..', '.timestamps') |
| 81 | 82 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 137 return True | 138 return True |
| 138 return subprocess.call( | 139 return subprocess.call( |
| 139 ['git', '-c', 'core.askpass=true', 'remote', 'show', | 140 ['git', '-c', 'core.askpass=true', 'remote', 'show', |
| 140 'https://chrome-internal.googlesource.com/chrome/src-internal/'], | 141 'https://chrome-internal.googlesource.com/chrome/src-internal/'], |
| 141 shell=True, stdin=nul, stdout=nul, stderr=nul) == 0 | 142 shell=True, stdin=nul, stdout=nul, stderr=nul) == 0 |
| 142 | 143 |
| 143 | 144 |
| 144 def LooksLikeGoogler(): | 145 def LooksLikeGoogler(): |
| 145 """Checks for a USERDOMAIN environment variable of 'GOOGLE', which | 146 """Checks for a USERDOMAIN environment variable of 'GOOGLE', which |
| 146 probably implies the current user is a Googler.""" | 147 probably implies the current user is a Googler.""" |
| 147 return os.environ.get('USERDOMAIN').upper() == 'GOOGLE' | 148 return os.environ.get('USERDOMAIN', '').upper() == 'GOOGLE' |
| 148 | 149 |
| 149 | 150 |
| 150 def CanAccessToolchainBucket(): | 151 def CanAccessToolchainBucket(): |
| 151 """Checks whether the user has access to gs://chrome-wintoolchain/.""" | 152 """Checks whether the user has access to gs://chrome-wintoolchain/.""" |
| 152 gsutil = download_from_google_storage.Gsutil( | 153 gsutil = download_from_google_storage.Gsutil( |
| 153 download_from_google_storage.GSUTIL_DEFAULT_PATH, boto_path=None) | 154 download_from_google_storage.GSUTIL_DEFAULT_PATH, boto_path=None) |
| 154 code, _, _ = gsutil.check_call('ls', 'gs://chrome-wintoolchain/') | 155 code, _, _ = gsutil.check_call('ls', 'gs://chrome-wintoolchain/') |
| 155 return code == 0 | 156 return code == 0 |
| 156 | 157 |
| 157 | 158 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 def DoTreeMirror(target_dir, tree_sha1): | 210 def DoTreeMirror(target_dir, tree_sha1): |
| 210 """In order to save temporary space on bots that do not have enough space to | 211 """In order to save temporary space on bots that do not have enough space to |
| 211 download ISOs, unpack them, and copy to the target location, the whole tree | 212 download ISOs, unpack them, and copy to the target location, the whole tree |
| 212 is uploaded as a zip to internal storage, and then mirrored here.""" | 213 is uploaded as a zip to internal storage, and then mirrored here.""" |
| 213 temp_dir, local_zip = DownloadUsingGsutil(tree_sha1 + '.zip') | 214 temp_dir, local_zip = DownloadUsingGsutil(tree_sha1 + '.zip') |
| 214 sys.stdout.write('Extracting %s...\n' % local_zip) | 215 sys.stdout.write('Extracting %s...\n' % local_zip) |
| 215 sys.stdout.flush() | 216 sys.stdout.flush() |
| 216 with zipfile.ZipFile(local_zip, 'r', zipfile.ZIP_DEFLATED, True) as zf: | 217 with zipfile.ZipFile(local_zip, 'r', zipfile.ZIP_DEFLATED, True) as zf: |
| 217 zf.extractall(target_dir) | 218 zf.extractall(target_dir) |
| 218 if temp_dir: | 219 if temp_dir: |
| 219 subprocess.check_call('rmdir /s/q "%s"' % temp_dir, shell=True) | 220 shutil.rmtree(temp_dir, ignore_errors=True) |
|
scottmg
2015/06/12 16:59:12
This function is terrible, and fails for files mar
Nico
2015/06/12 17:04:29
TIL! Could the onerror handler in the first reply
scottmg
2015/06/12 17:13:56
Looks like it, but it seems longer than an if win:
| |
| 220 | 221 |
| 221 | 222 |
| 222 def main(): | 223 def main(): |
| 223 if not sys.platform.startswith(('cygwin', 'win32')): | 224 #if not sys.platform.startswith(('cygwin', 'win32')): |
| 224 return 0 | 225 #return 0 |
| 225 | 226 |
| 226 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) | 227 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) |
| 227 parser.add_option('--output-json', metavar='FILE', | 228 parser.add_option('--output-json', metavar='FILE', |
| 228 help='write information about toolchain to FILE') | 229 help='write information about toolchain to FILE') |
| 229 options, args = parser.parse_args() | 230 options, args = parser.parse_args() |
| 230 | 231 |
| 231 if sys.platform == 'cygwin': | 232 if sys.platform == 'cygwin': |
| 232 # This script requires Windows Python, so invoke with depot_tools' Python. | 233 # This script requires Windows Python, so invoke with depot_tools' Python. |
| 233 def winpath(path): | 234 def winpath(path): |
| 234 return subprocess.check_output(['cygpath', '-w', path]).strip() | 235 return subprocess.check_output(['cygpath', '-w', path]).strip() |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 273 print('Please follow the instructions at ' | 274 print('Please follow the instructions at ' |
| 274 'http://www.chromium.org/developers/how-tos/' | 275 'http://www.chromium.org/developers/how-tos/' |
| 275 'build-instructions-windows') | 276 'build-instructions-windows') |
| 276 return 1 | 277 return 1 |
| 277 print('Windows toolchain out of date or doesn\'t exist, updating (Pro)...') | 278 print('Windows toolchain out of date or doesn\'t exist, updating (Pro)...') |
| 278 print(' current_hash: %s' % current_hash) | 279 print(' current_hash: %s' % current_hash) |
| 279 print(' desired_hashes: %s' % ', '.join(desired_hashes)) | 280 print(' desired_hashes: %s' % ', '.join(desired_hashes)) |
| 280 sys.stdout.flush() | 281 sys.stdout.flush() |
| 281 DelayBeforeRemoving(target_dir) | 282 DelayBeforeRemoving(target_dir) |
| 282 # This stays resident and will make the rmdir below fail. | 283 # This stays resident and will make the rmdir below fail. |
| 283 with open(os.devnull, 'wb') as nul: | 284 if sys.platform in ('win32', 'cygwin'): |
| 284 subprocess.call(['taskkill', '/f', '/im', 'mspdbsrv.exe'], | 285 with open(os.devnull, 'wb') as nul: |
| 285 stdin=nul, stdout=nul, stderr=nul) | 286 subprocess.call(['taskkill', '/f', '/im', 'mspdbsrv.exe'], |
| 287 stdin=nul, stdout=nul, stderr=nul) | |
| 286 if os.path.isdir(target_dir): | 288 if os.path.isdir(target_dir): |
| 287 subprocess.check_call('rmdir /s/q "%s"' % target_dir, shell=True) | 289 shutil.rmtree(target_dir, ignore_errors=True); |
| 288 | 290 |
| 289 DoTreeMirror(target_dir, desired_hashes[0]) | 291 DoTreeMirror(target_dir, desired_hashes[0]) |
| 290 | 292 |
| 291 got_new_toolchain = True | 293 got_new_toolchain = True |
| 292 | 294 |
| 293 win_sdk = os.path.join(abs_target_dir, 'win_sdk') | 295 win_sdk = os.path.join(abs_target_dir, 'win_sdk') |
| 294 try: | 296 try: |
| 295 with open(os.path.join(target_dir, 'VS_VERSION'), 'rb') as f: | 297 with open(os.path.join(target_dir, 'VS_VERSION'), 'rb') as f: |
| 296 vs_version = f.read().strip() | 298 vs_version = f.read().strip() |
| 297 except IOError: | 299 except IOError: |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 327 | 329 |
| 328 if options.output_json: | 330 if options.output_json: |
| 329 shutil.copyfile(os.path.join(target_dir, '..', 'data.json'), | 331 shutil.copyfile(os.path.join(target_dir, '..', 'data.json'), |
| 330 options.output_json) | 332 options.output_json) |
| 331 | 333 |
| 332 return 0 | 334 return 0 |
| 333 | 335 |
| 334 | 336 |
| 335 if __name__ == '__main__': | 337 if __name__ == '__main__': |
| 336 sys.exit(main()) | 338 sys.exit(main()) |
| OLD | NEW |