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 |