|
5 | 5 | # the BSD License: https://opensource.org/license/bsd-3-clause/
|
6 | 6 |
|
7 | 7 | importos
|
| 8 | +importpathlib |
8 | 9 | importpickle
|
| 10 | +importstat |
9 | 11 | importsys
|
10 | 12 | importtempfile
|
11 | 13 | importtime
|
12 |
| -fromunittestimportmock,skipUnless |
| 14 | +fromunittestimportSkipTest,mock,skipIf,skipUnless |
13 | 15 | fromdatetimeimportdatetime
|
14 | 16 |
|
15 | 17 | importddt
|
|
19 | 21 | fromgit.compatimportis_win
|
20 | 22 | fromgit.objects.utilimport (
|
21 | 23 | altz_to_utctz_str,
|
22 |
| -utctz_to_altz, |
23 |
| -verify_utctz, |
| 24 | +from_timestamp, |
24 | 25 | parse_date,
|
25 | 26 | tzoffset,
|
26 |
| -from_timestamp, |
| 27 | +utctz_to_altz, |
| 28 | +verify_utctz, |
27 | 29 | )
|
28 | 30 | fromtest.libimport (
|
29 | 31 | TestBase,
|
30 | 32 | with_rw_repo,
|
31 | 33 | )
|
32 | 34 | fromgit.utilimport (
|
33 |
| -LockFile, |
34 |
| -BlockingLockFile, |
35 |
| -get_user_id, |
36 | 35 | Actor,
|
| 36 | +BlockingLockFile, |
37 | 37 | IterableList,
|
| 38 | +LockFile, |
38 | 39 | cygpath,
|
39 | 40 | decygpath,
|
| 41 | +get_user_id, |
40 | 42 | remove_password_if_present,
|
| 43 | +rmtree, |
41 | 44 | )
|
42 | 45 |
|
43 | 46 |
|
@@ -85,6 +88,59 @@ def setup(self):
|
85 | 88 | "array": [42],
|
86 | 89 | }
|
87 | 90 |
|
| 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 | + |
88 | 144 | # FIXME: Mark only the /proc-prefixing cases xfail, somehow (or fix them).
|
89 | 145 | @pytest.mark.xfail(
|
90 | 146 | reason="Many return paths prefixed /proc/cygdrive instead.",
|
|