2 files changed
@@ -0,0 +1,17 @@ | |||
| 1 | + #!/bin/sh | ||
| 2 | + | ||
| 3 | + set -e | ||
| 4 | + | ||
| 5 | + mkdir dir1 | ||
| 6 | + touch dir1/file | ||
| 7 | + chmod -w dir1/file | ||
| 8 | + printf 'Permissions BEFORE rmtree call:\n' | ||
| 9 | + ls -l dir1/file | ||
| 10 | + printf '\n' | ||
| 11 | + | ||
| 12 | + mkdir dir2 | ||
| 13 | + ln -s ../dir1/file dir2/symlink | ||
| 14 | + chmod -w dir2 | ||
| 15 | + python -c 'from git.util import rmtree; rmtree("dir2")' || true | ||
| 16 | + printf '\nPermissions AFTER rmtree call:\n' | ||
| 17 | + ls -l dir1/file | ||
@@ -105,6 +105,35 @@ def test_deletes_dir_with_readonly_files(self, tmp_path): | |||
| 105 | 105 | ||
| 106 | 106 | assert not td.exists() | |
| 107 | 107 | ||
| 108 | + @pytest.mark.skipif( | ||
| 109 | + sys.platform == "cygwin", | ||
| 110 | + reason="Cygwin can't set the permissions that make the test meaningful.", | ||
| 111 | + ) | ||
| 112 | + def test_avoids_changing_permissions_outside_tree(self, tmp_path: pathlib.Path): | ||
| 113 | + # Automatically works on Windows, but on Unix requires either special handling | ||
| 114 | + # or refraining from attempting to fix PermissionError by making chmod calls. | ||
| 115 | + | ||
| 116 | + dir1 = tmp_path / "dir1" | ||
| 117 | + dir1.mkdir() | ||
| 118 | + (dir1 / "file").write_bytes(b"") | ||
| 119 | + (dir1 / "file").chmod(stat.S_IRUSR) | ||
| 120 | + old_mode = (dir1 / "file").stat().st_mode | ||
| 121 | + | ||
| 122 | + dir2 = tmp_path / "dir2" | ||
| 123 | + dir2.mkdir() | ||
| 124 | + (dir2 / "symlink").symlink_to(dir1 / "file") | ||
| 125 | + dir2.chmod(stat.S_IRUSR | stat.S_IXUSR) | ||
| 126 | + | ||
| 127 | + try: | ||
| 128 | + rmtree(dir2) | ||
| 129 | + except PermissionError: | ||
| 130 | + pass # On Unix, dir2 is not writable, so dir2/symlink may not be deleted. | ||
| 131 | + except SkipTest as ex: | ||
| 132 | + self.fail(f"rmtree unexpectedly attempts skip: {ex!r}") | ||
| 133 | + | ||
| 134 | + new_mode = (dir1 / "file").stat().st_mode | ||
| 135 | + assert old_mode == new_mode, f"Should stay {old_mode:#o}, became {new_mode:#o}." | ||
| 136 | + | ||
| 108 | 137 | @pytest.mark.skipif( | |
| 109 | 138 | sys.platform == "cygwin", | |
| 110 | 139 | reason="Cygwin can't set the permissions that make the test meaningful.", | |
0 commit comments