| OLD | NEW |
| 1 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """ Set of basic operations/utilities that are used by the build. """ | 5 """ Set of basic operations/utilities that are used by the build. """ |
| 6 | 6 |
| 7 import copy | 7 import copy |
| 8 import errno | 8 import errno |
| 9 import fnmatch | 9 import fnmatch |
| 10 import glob | 10 import glob |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 try: | 259 try: |
| 260 win32api = __import__('win32api') | 260 win32api = __import__('win32api') |
| 261 win32con = __import__('win32con') | 261 win32con = __import__('win32con') |
| 262 win32_api_avail = True | 262 win32_api_avail = True |
| 263 except ImportError: | 263 except ImportError: |
| 264 pass | 264 pass |
| 265 remove_with_retry = RemoveWithRetry_win | 265 remove_with_retry = RemoveWithRetry_win |
| 266 else: | 266 else: |
| 267 remove_with_retry = RemoveWithRetry_non_win | 267 remove_with_retry = RemoveWithRetry_non_win |
| 268 | 268 |
| 269 def RmTreeOnError(function, path, excinfo): |
| 270 """This works around a problem whereby python 2.x on Windows has no ability |
| 271 to check for symbolic links. os.path.islink always returns False. But |
| 272 shutil.rmtree will fail if invoked on a symbolic link whose target was |
| 273 deleted before the link. E.g., reproduce like this: |
| 274 > mkdir test |
| 275 > mkdir test\1 |
| 276 > mklink /D test\current test\1 |
| 277 > python -c "import chromium_utils; chromium_utils.RemoveDirectory('test')" |
| 278 To avoid this issue, we pass this error-handling function to rmtree. If |
| 279 we see the exact sort of failure, we ignore it. All other failures we re- |
| 280 raise. |
| 281 """ |
| 282 |
| 283 exception_type = excinfo[0] |
| 284 exception_value = excinfo[1] |
| 285 # If shutil.rmtree encounters a symbolic link on Windows, os.listdir will |
| 286 # fail with a WindowsError exception with an ENOENT errno (i.e., file not |
| 287 # found). We'll ignore that error. Note that WindowsError is not defined |
| 288 # for non-Windows platforms, so we use OSError (of which it is a subclass) |
| 289 # to avoid lint complaints about an undefined global on non-Windows |
| 290 # platforms. |
| 291 if (function is os.listdir) and issubclass(exception_type, OSError): |
| 292 if exception_value.errno == errno.ENOENT: |
| 293 # File does not exist, and we're trying to delete, so we can ignore the |
| 294 # failure. |
| 295 print "WARNING: Failed to list %s during rmtree. Ignoring.\n" % path |
| 296 else: |
| 297 raise |
| 298 else: |
| 299 raise |
| 300 |
| 269 for root, dirs, files in os.walk(file_path, topdown=False): | 301 for root, dirs, files in os.walk(file_path, topdown=False): |
| 270 # For POSIX: making the directory writable guarantees removability. | 302 # For POSIX: making the directory writable guarantees removability. |
| 271 # Windows will ignore the non-read-only bits in the chmod value. | 303 # Windows will ignore the non-read-only bits in the chmod value. |
| 272 os.chmod(root, 0770) | 304 os.chmod(root, 0770) |
| 273 for name in files: | 305 for name in files: |
| 274 remove_with_retry(os.remove, os.path.join(root, name)) | 306 remove_with_retry(os.remove, os.path.join(root, name)) |
| 275 for name in dirs: | 307 for name in dirs: |
| 276 remove_with_retry(shutil.rmtree, os.path.join(root, name)) | 308 remove_with_retry(lambda p: shutil.rmtree(p, onerror=RmTreeOnError), |
| 309 os.path.join(root, name)) |
| 277 | 310 |
| 278 remove_with_retry(os.rmdir, file_path) | 311 remove_with_retry(os.rmdir, file_path) |
| 279 | 312 |
| 280 | 313 |
| 281 def CopyFileToDir(src_path, dest_dir): | 314 def CopyFileToDir(src_path, dest_dir): |
| 282 """Copies the file found at src_path to the same filename within the | 315 """Copies the file found at src_path to the same filename within the |
| 283 dest_dir directory. | 316 dest_dir directory. |
| 284 | 317 |
| 285 Raises PathNotFound if either the file or the directory is not found. | 318 Raises PathNotFound if either the file or the directory is not found. |
| 286 """ | 319 """ |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 | 749 |
| 717 def ListMasters(): | 750 def ListMasters(): |
| 718 """Returns all the masters found.""" | 751 """Returns all the masters found.""" |
| 719 # Look for "internal" masters first. | 752 # Look for "internal" masters first. |
| 720 path_internal = os.path.join(os.path.dirname(__file__), '..', '..', '..', | 753 path_internal = os.path.join(os.path.dirname(__file__), '..', '..', '..', |
| 721 'build_internal', 'masters/*/master.cfg') | 754 'build_internal', 'masters/*/master.cfg') |
| 722 path = os.path.join(os.path.dirname(__file__), '..', '..', | 755 path = os.path.join(os.path.dirname(__file__), '..', '..', |
| 723 'masters/*/master.cfg') | 756 'masters/*/master.cfg') |
| 724 filenames = glob.glob(path_internal) + glob.glob(path) | 757 filenames = glob.glob(path_internal) + glob.glob(path) |
| 725 return [os.path.abspath(os.path.dirname(f)) for f in filenames] | 758 return [os.path.abspath(os.path.dirname(f)) for f in filenames] |
| OLD | NEW |