 Chromium Code Reviews
 Chromium Code Reviews Issue 2446001:
  Fix smoke tests on Windows.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools/
    
  
    Issue 2446001:
  Fix smoke tests on Windows.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools/| 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) |