Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inherit HTTP cache file read/write permissions from cache directory #13070

Merged
merged 11 commits into from
Dec 9, 2024
1 change: 1 addition & 0 deletions news/11012.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Network cache file permissions will inherit the read/write permissions of the cache's directory with the exception of owner read/write permissions which will always be set. This feature enables sharing a cache in a multi-user environment.
3 changes: 3 additions & 0 deletions src/pip/_internal/network/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ def _write(self, path: str, data: bytes) -> None:
with adjacent_tmp_file(path) as f:
f.write(data)

# `& 0o666` selects the read/write permissions of the cache directory.
# `| 0o600` sets owner read/write permissions.
os.chmod(f.name, os.stat(self.directory).st_mode & 0o666 | 0o600)
JustinVanHeek marked this conversation as resolved.
Show resolved Hide resolved
replace(f.name, path)

def set(
Expand Down
13 changes: 13 additions & 0 deletions tests/unit/test_network_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,16 @@ def test_cache_hashes_are_same(self, cache_tmpdir: Path) -> None:
key = "test key"
fake_cache = Mock(FileCache, directory=cache.directory, encode=FileCache.encode)
assert cache._get_cache_path(key) == FileCache._fn(fake_cache, key)

@pytest.mark.skipif("sys.platform == 'win32'")
@pytest.mark.parametrize(
"perms, expected_perms", [(0o300, 0o600), (0o700, 0o600), (0o777, 0o666)]
)
def test_cache_inherits_perms(
self, cache_tmpdir: Path, perms: int, expected_perms: int
) -> None:
key = "foo"
with chmod(cache_tmpdir, perms):
cache = SafeFileCache(os.fspath(cache_tmpdir))
cache.set(key, b"bar")
assert (os.stat(cache._get_cache_path(key)).st_mode & 0o777) == expected_perms
Loading