mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-14 08:18:36 +00:00
fix: zip extract permission bits (#2102)
* Restore Unix executable bits when extracting zip archives - SafeZipExtractor._extract_member now chmods each extracted file with the Unix mode stored in ZipInfo.external_attr (POSIX only, no-op when the archive carries no Unix attributes, e.g. Windows-authored zips). - stdlib zipfile never restores permission bits itself; a fix is tracked upstream at https://github.com/python/cpython/pull/150061. - Fixes archives with more than one executable losing their exec bit after extraction, e.g. the bundled JBR inside the Kotlin Language Server distribution (jbr/bin/java and native libs), which previously only had its single top-level launcher script chmod'd by the language-server code. Fixes oraios/serena#2100 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
1 parent
9fa4237107
commit
b83b655ced
3 files changed
+34
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import os
|
||||
import sys
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
@@ -90,6 +91,24 @@ def test_skip_on_error(monkeypatch, temp_zip_file: Path, tmp_path: Path) -> None
|
||||
assert (dest_dir / "folder" / "file3.txt").exists()
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Unix permission bits are not applicable on Windows")
|
||||
def test_restores_executable_permission(tmp_path: Path) -> None:
|
||||
"""Executable bits stored in the archive's external_attr should be restored on extraction."""
|
||||
zip_path = tmp_path / "exec.zip"
|
||||
with zipfile.ZipFile(zip_path, "w") as zipf:
|
||||
info = zipfile.ZipInfo("bin/tool")
|
||||
info.external_attr = 0o755 << 16
|
||||
zipf.writestr(info, "#!/bin/sh\necho hi\n")
|
||||
|
||||
dest_dir = tmp_path / "extracted"
|
||||
extractor = SafeZipExtractor(zip_path, dest_dir, verbose=False)
|
||||
extractor.extract_all()
|
||||
|
||||
extracted_file = dest_dir / "bin" / "tool"
|
||||
assert extracted_file.exists()
|
||||
assert os.stat(extracted_file).st_mode & 0o111
|
||||
|
||||
|
||||
@pytest.mark.skipif(not sys.platform.startswith("win"), reason="Windows-only test")
|
||||
def test_long_path_normalization(temp_zip_file: Path, tmp_path: Path) -> None:
|
||||
r"""Ensure _normalize_path adds \\?\\ prefix on Windows."""
|
||||
|
||||
Reference in new issue
Block a user