|
12 | 12 | import errno |
13 | 13 | import re |
14 | 14 | import time |
| 15 | +import stat |
| 16 | +import shutil |
15 | 17 | import tempfile |
16 | 18 |
|
17 | 19 | __all__ = ( "stream_copy", "join_path", "to_native_path_windows", "to_native_path_linux", |
18 | 20 | "join_path_native", "Stats", "IndexFileSHA1Writer", "Iterable", "IterableList", |
19 | 21 | "BlockingLockFile", "LockFile", 'Actor', 'get_user_id', 'assure_directory_exists', |
20 | | - 'RepoAliasMixin', 'LockedFD', 'LazyMixin' ) |
| 22 | + 'RepoAliasMixin', 'LockedFD', 'LazyMixin', 'rmtree' ) |
21 | 23 |
|
22 | 24 | from cStringIO import StringIO |
23 | 25 |
|
@@ -147,6 +149,19 @@ def is_git_dir(d): |
147 | 149 | os.readlink(headref).startswith('refs')) |
148 | 150 | return False |
149 | 151 |
|
| 152 | +def rmtree(path): |
| 153 | + """Remove the given recursively. |
| 154 | + :note: we use shutil rmtree but adjust its behaviour to see whether files that |
| 155 | + couldn't be deleted are read-only. Windows will not remove them in that case""" |
| 156 | + def onerror(func, path, exc_info): |
| 157 | + if not os.access(path, os.W_OK): |
| 158 | + # Is the error an access error ? |
| 159 | + os.chmod(path, stat.S_IWUSR) |
| 160 | + func(path) |
| 161 | + else: |
| 162 | + raise |
| 163 | + # END end onerror |
| 164 | + return shutil.rmtree(path, False, onerror) |
150 | 165 |
|
151 | 166 | def stream_copy(source, destination, chunk_size=512*1024): |
152 | 167 | """Copy all data from the source stream into the destination stream in chunks |
|
0 commit comments