Chromium Code Reviews| Index: tests/fake_repos.py |
| =================================================================== |
| --- tests/fake_repos.py (revision 48611) |
| +++ tests/fake_repos.py (working copy) |
| @@ -6,13 +6,15 @@ |
| """Generate fake repositories for testing.""" |
| import atexit |
| +import errno |
| import logging |
| import os |
| import pprint |
| import re |
| -import shutil |
| +import stat |
| import subprocess |
| import sys |
| +import time |
| import unittest |
| @@ -35,12 +37,71 @@ |
| subprocess.kill = kill_nix |
| -def rmtree(path): |
| - """Delete a directory.""" |
| - if os.path.exists(path): |
| - shutil.rmtree(path) |
| +def rmtree(*path): |
| + """Recursively removes a directory, even if it's marked read-only. |
| + Remove the directory located at *path, if it exists. |
| + shutil.rmtree() doesn't work on Windows if any of the files or directories |
| + are read-only, which svn repositories and some .svn files are. We need to |
| + be able to force the files to be writable (i.e., deletable) as we traverse |
| + the tree. |
| + |
| + Even with all this, Windows still sometimes fails to delete a file, citing |
| + a permission error (maybe something to do with antivirus scans or disk |
| + indexing). The best suggestion any of the user forums had was to wait a |
| + bit and try again, so we do that too. It's hand-waving, but sometimes it |
| + works. :/ |
| + """ |
| + file_path = os.path.join(*path) |
| + if not os.path.exists(file_path): |
| + return |
| + |
| + def RemoveWithRetry_win(rmfunc, path): |
| + os.chmod(path, stat.S_IWRITE) |
| + if win32_api_avail: |
| + win32api.SetFileAttributes(path, win32con.FILE_ATTRIBUTE_NORMAL) |
| + try: |
| + return rmfunc(path) |
| + except EnvironmentError, e: |
| + if e.errno != errno.EACCES: |
| + raise |
| + print 'Failed to delete %s: trying again' % repr(path) |
| + time.sleep(0.1) |
| + return rmfunc(path) |
| + |
| + def RemoveWithRetry_non_win(rmfunc, path): |
| + if os.path.islink(path): |
| + return os.remove(path) |
| + else: |
| + return rmfunc(path) |
| + |
| + win32_api_avail = False |
| + remove_with_retry = None |
| + if sys.platform.startswith('win'): |
|
bradn
2010/06/01 01:12:04
Pretty sure this is always win32, but anyways. Did
M-A Ruel
2010/06/01 01:26:27
You are right, it's just a copy-paste from scripts
|
| + # Some people don't have the APIs installed. In that case we'll do without. |
| + try: |
| + win32api = __import__('win32api') |
| + win32con = __import__('win32con') |
| + win32_api_avail = True |
| + except ImportError: |
| + pass |
| + remove_with_retry = RemoveWithRetry_win |
| + else: |
| + remove_with_retry = RemoveWithRetry_non_win |
| + |
| + for root, dirs, files in os.walk(file_path, topdown=False): |
| + # For POSIX: making the directory writable guarantees removability. |
| + # Windows will ignore the non-read-only bits in the chmod value. |
| + os.chmod(root, 0770) |
| + for name in files: |
| + remove_with_retry(os.remove, os.path.join(root, name)) |
| + for name in dirs: |
| + remove_with_retry(os.rmdir, os.path.join(root, name)) |
| + |
| + remove_with_retry(os.rmdir, file_path) |
| + |
| + |
| def write(path, content): |
| f = open(path, 'wb') |
| f.write(content) |
| @@ -69,7 +130,9 @@ |
| for d in filter(lambda x: x.startswith('.'), dirs): |
| dirs.remove(d) |
| for f in [join(root, f) for f in files if not f.startswith('.')]: |
| - tree[f[len(tree_root) + 1:]] = open(join(root, f), 'rb').read() |
| + filepath = f[len(tree_root) + 1:].replace(os.sep, '/') |
| + assert len(filepath), f |
| + tree[filepath] = open(join(root, f), 'rU').read() |
| return tree |
| @@ -92,7 +155,7 @@ |
| for k, v in tree.iteritems(): |
| if not k.startswith(old_root): |
| continue |
| - result[join(new_root, k[len(old_root) + 1:])] = v |
| + result[join(new_root, k[len(old_root) + 1:]).replace(os.sep, '/')] = v |
| return result |
| @@ -330,8 +393,10 @@ |
| def setUpGIT(self): |
| """Creates git repositories and start the servers.""" |
| if self.gitdaemon: |
| - return |
| + return True |
| self.setUp() |
| + if sys.platform == 'win32': |
| + return False |
| for repo in ['repo_%d' % r for r in range(1, 5)]: |
| check_call(['git', 'init', '-q', join(self.git_root, repo)]) |
| self.git_hashes[repo] = [] |
| @@ -424,6 +489,7 @@ |
| cmd.append('--listen=127.0.0.1') |
| logging.debug(cmd) |
| self.gitdaemon = Popen(cmd, cwd=self.repos_dir) |
| + return True |
| def _commit_svn(self, tree): |
| self._genTree(self.svn_root, tree) |