Skip to content

Commit 5a3b731

Browse files
committed
Submodule now uses a specialized method to remove its trees to allow read-only files to be removed on windows as well
1 parent 963bbd7 commit 5a3b731

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

git/objects/submodule/base.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
Iterable,
1919
join_path_native,
2020
to_native_path_linux,
21+
rmtree
2122
)
2223

2324
from git.db.interface import RemoteProgress
@@ -35,8 +36,6 @@
3536
import sys
3637
import time
3738

38-
import shutil
39-
4039
__all__ = ["Submodule", "UpdateProgress"]
4140

4241

@@ -634,7 +633,7 @@ def remove(self, module=True, force=False, configuration=True, dry_run=False):
634633
if os.path.islink(mp):
635634
method = os.remove
636635
elif os.path.isdir(mp):
637-
method = shutil.rmtree
636+
method = rmtree
638637
elif os.path.exists(mp):
639638
raise AssertionError("Cannot forcibly delete repository as it was neither a link, nor a directory")
640639
#END handle brutal deletion
@@ -683,7 +682,7 @@ def remove(self, module=True, force=False, configuration=True, dry_run=False):
683682
if not dry_run:
684683
wtd = mod.working_tree_dir
685684
del(mod) # release file-handles (windows)
686-
shutil.rmtree(wtd)
685+
rmtree(wtd)
687686
# END delete tree if possible
688687
# END handle force
689688
# END handle module deletion

git/util.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
import errno
1313
import re
1414
import time
15+
import stat
16+
import shutil
1517
import tempfile
1618

1719
__all__ = ( "stream_copy", "join_path", "to_native_path_windows", "to_native_path_linux",
1820
"join_path_native", "Stats", "IndexFileSHA1Writer", "Iterable", "IterableList",
1921
"BlockingLockFile", "LockFile", 'Actor', 'get_user_id', 'assure_directory_exists',
20-
'RepoAliasMixin', 'LockedFD', 'LazyMixin' )
22+
'RepoAliasMixin', 'LockedFD', 'LazyMixin', 'rmtree' )
2123

2224
from cStringIO import StringIO
2325

@@ -147,6 +149,19 @@ def is_git_dir(d):
147149
os.readlink(headref).startswith('refs'))
148150
return False
149151

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)
150165

151166
def stream_copy(source, destination, chunk_size=512*1024):
152167
"""Copy all data from the source stream into the destination stream in chunks

0 commit comments

Comments
 (0)