Skip to content

Commit 2fe7f3c

Browse files
committed
Test current expected behavior of git.util.rmtree
1 parent 683a3ee commit 2fe7f3c

File tree

1 file changed

+63
-7
lines changed

1 file changed

+63
-7
lines changed

‎test/test_util.py‎

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
# the BSD License: https://opensource.org/license/bsd-3-clause/
66

77
importos
8+
importpathlib
89
importpickle
10+
importstat
911
importsys
1012
importtempfile
1113
importtime
12-
fromunittestimportmock, skipUnless
14+
fromunittestimportSkipTest, mock, skipIf, skipUnless
1315
fromdatetimeimportdatetime
1416

1517
importddt
@@ -19,25 +21,26 @@
1921
fromgit.compatimportis_win
2022
fromgit.objects.utilimport (
2123
altz_to_utctz_str,
22-
utctz_to_altz,
23-
verify_utctz,
24+
from_timestamp,
2425
parse_date,
2526
tzoffset,
26-
from_timestamp,
27+
utctz_to_altz,
28+
verify_utctz,
2729
)
2830
fromtest.libimport (
2931
TestBase,
3032
with_rw_repo,
3133
)
3234
fromgit.utilimport (
33-
LockFile,
34-
BlockingLockFile,
35-
get_user_id,
3635
Actor,
36+
BlockingLockFile,
3737
IterableList,
38+
LockFile,
3839
cygpath,
3940
decygpath,
41+
get_user_id,
4042
remove_password_if_present,
43+
rmtree,
4144
)
4245

4346

@@ -85,6 +88,59 @@ def setup(self):
8588
"array": [42],
8689
}
8790

91+
deftest_rmtree_deletes_nested_dir_with_files(self):
92+
withtempfile.TemporaryDirectory() asparent:
93+
td=pathlib.Path(parent, "testdir")
94+
fordintd, td/"q", td/"s":
95+
d.mkdir()
96+
forfintd/"p", td/"q"/"w", td/"q"/"x", td/"r", td/"s"/"y", td/"s"/"z":
97+
f.write_bytes(b"")
98+
99+
try:
100+
rmtree(td)
101+
exceptSkipTestasex:
102+
self.fail(f"rmtree unexpectedly attempts skip: {ex!r}")
103+
104+
self.assertFalse(td.exists())
105+
106+
@skipIf(sys.platform=="cygwin", "Cygwin can't set the permissions that make the test meaningful.")
107+
deftest_rmtree_deletes_dir_with_readonly_files(self):
108+
# Automatically works on Unix, but requires special handling on Windows.
109+
withtempfile.TemporaryDirectory() asparent:
110+
td=pathlib.Path(parent, "testdir")
111+
fordintd, td/"sub":
112+
d.mkdir()
113+
forfintd/"x", td/"sub"/"y":
114+
f.write_bytes(b"")
115+
f.chmod(0)
116+
117+
try:
118+
rmtree(td)
119+
exceptSkipTestasex:
120+
self.fail(f"rmtree unexpectedly attempts skip: {ex!r}")
121+
122+
self.assertFalse(td.exists())
123+
124+
@skipIf(sys.platform=="cygwin", "Cygwin can't set the permissions that make the test meaningful.")
125+
@skipIf(sys.version_info< (3, 8), "In 3.7, TemporaryDirectory doesn't clean up after weird permissions.")
126+
deftest_rmtree_can_wrap_exceptions(self):
127+
withtempfile.TemporaryDirectory() asparent:
128+
td=pathlib.Path(parent, "testdir")
129+
td.mkdir()
130+
(td/"x").write_bytes(b"")
131+
(td/"x").chmod(stat.S_IRUSR) # Set up PermissionError on Windows.
132+
td.chmod(stat.S_IRUSR|stat.S_IXUSR) # Set up PermissionError on Unix.
133+
134+
# Access the module through sys.modules so it is unambiguous which module's
135+
# attribute we patch: the original git.util, not git.index.util even though
136+
# git.index.util "replaces" git.util and is what "import git.util" gives us.
137+
withmock.patch.object(sys.modules["git.util"], "HIDE_WINDOWS_KNOWN_ERRORS", True):
138+
# Disable common chmod functions so the callback can't fix the problem.
139+
withmock.patch.object(os, "chmod"), mock.patch.object(pathlib.Path, "chmod"):
140+
# Now we can see how an intractable PermissionError is treated.
141+
withself.assertRaises(SkipTest):
142+
rmtree(td)
143+
88144
# FIXME: Mark only the /proc-prefixing cases xfail, somehow (or fix them).
89145
@pytest.mark.xfail(
90146
reason="Many return paths prefixed /proc/cygdrive instead.",

0 commit comments

Comments
(0)