|
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.", |
|
0 commit comments