from __future__ import annotations import json import pathlib import subprocess import sys import tempfile import unittest import zipfile SCRIPT = pathlib.Path(__file__).resolve().parents[1] / "scripts" / "bundle_zip.py" def run_cli(*args: str, cwd: pathlib.Path | None = None) -> subprocess.CompletedProcess[str]: return subprocess.run( [sys.executable, str(SCRIPT), *args], cwd=str(cwd) if cwd else None, text=True, capture_output=True, check=False, ) def write_file(path: pathlib.Path, text: str = "content") -> pathlib.Path: path.parent.mkdir(parents=True, exist_ok=True) path.write_text(text, encoding="utf-8") return path def write_file_list(path: pathlib.Path, files: list[str]) -> pathlib.Path: path.write_text("\n".join(files) + "\n", encoding="utf-8") return path class BundleZipTest(unittest.TestCase): def test_absolute_files_under_marker_create_source_relative_entries(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = pathlib.Path(tmp) / "the-mindscape-of-bro-tsong" first = write_file(root / "cards" / "card_index.md", "card") second = write_file(root / "cards" / "intellectual_archaeology.md", "ia") file_list = write_file_list(pathlib.Path(tmp) / "files.txt", [str(first), str(second)]) output = pathlib.Path(tmp) / "bundle.zip" result = run_cli( "--file-list", str(file_list), "--relative-root-marker", "the-mindscape-of-bro-tsong", "--output", str(output), "--verify", "--json", ) self.assertEqual(result.returncode, 0, result.stderr) summary = json.loads(result.stdout) self.assertEqual(summary["status"], "PASS") self.assertEqual( summary["entries"], ["cards/card_index.md", "cards/intellectual_archaeology.md"], ) with zipfile.ZipFile(output) as archive: self.assertEqual(archive.namelist(), summary["entries"]) def test_mixed_absolute_and_cwd_relative_files_create_correct_entries(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = pathlib.Path(tmp) / "repo" absolute_file = write_file(root / "cards" / "absolute.md") relative_file = write_file(root / "notes" / "relative.md") file_list = write_file_list( root / "files.txt", [str(absolute_file), r"notes\relative.md"], ) output = pathlib.Path(tmp) / "mixed.zip" result = run_cli( "--file-list", str(file_list), "--relative-root-marker", "repo", "--output", str(output), "--verify", "--json", cwd=root, ) self.assertEqual(result.returncode, 0, result.stderr) summary = json.loads(result.stdout) self.assertEqual(summary["entries"], ["cards/absolute.md", "notes/relative.md"]) def test_existing_destination_zip_is_replaced_after_validation(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = pathlib.Path(tmp) / "repo" source = write_file(root / "src" / "new.md", "new") file_list = write_file_list(pathlib.Path(tmp) / "files.txt", [str(source)]) output = pathlib.Path(tmp) / "bundle.zip" with zipfile.ZipFile(output, "w") as archive: archive.writestr("old.txt", "old") result = run_cli( "--file-list", str(file_list), "--relative-root-marker", "repo", "--output", str(output), "--verify", "--json", ) self.assertEqual(result.returncode, 0, result.stderr) with zipfile.ZipFile(output) as archive: self.assertEqual(archive.namelist(), ["src/new.md"]) self.assertEqual(archive.read("src/new.md"), b"new") def test_missing_source_fails_before_existing_output_is_touched(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = pathlib.Path(tmp) / "repo" missing = root / "missing.md" file_list = write_file_list(pathlib.Path(tmp) / "files.txt", [str(missing)]) output = pathlib.Path(tmp) / "bundle.zip" with zipfile.ZipFile(output, "w") as archive: archive.writestr("old.txt", "old") result = run_cli( "--file-list", str(file_list), "--relative-root-marker", "repo", "--output", str(output), "--json", ) self.assertNotEqual(result.returncode, 0) summary = json.loads(result.stdout) self.assertEqual(summary["status"], "FAIL") self.assertIn("does not exist", summary["errors"][0]) with zipfile.ZipFile(output) as archive: self.assertEqual(archive.namelist(), ["old.txt"]) def test_file_outside_root_marker_fails(self) -> None: with tempfile.TemporaryDirectory() as tmp: outside = write_file(pathlib.Path(tmp) / "outside" / "file.md") file_list = write_file_list(pathlib.Path(tmp) / "files.txt", [str(outside)]) result = run_cli( "--file-list", str(file_list), "--relative-root-marker", "repo", "--output", str(pathlib.Path(tmp) / "bundle.zip"), "--json", ) self.assertNotEqual(result.returncode, 0) summary = json.loads(result.stdout) self.assertEqual(summary["status"], "FAIL") self.assertIn("root marker", summary["errors"][0]) def test_duplicate_relative_entries_fail(self) -> None: with tempfile.TemporaryDirectory() as tmp: first = write_file(pathlib.Path(tmp) / "left" / "repo" / "same.md", "first") second = write_file(pathlib.Path(tmp) / "right" / "repo" / "same.md", "second") file_list = write_file_list(pathlib.Path(tmp) / "files.txt", [str(first), str(second)]) result = run_cli( "--file-list", str(file_list), "--relative-root-marker", "repo", "--output", str(pathlib.Path(tmp) / "bundle.zip"), "--json", ) self.assertNotEqual(result.returncode, 0) summary = json.loads(result.stdout) self.assertEqual(summary["status"], "FAIL") self.assertIn("Duplicate zip entry", "\n".join(summary["errors"])) def test_output_path_matching_source_file_fails(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = pathlib.Path(tmp) / "repo" source = write_file(root / "bundle.zip") file_list = write_file_list(pathlib.Path(tmp) / "files.txt", [str(source)]) result = run_cli( "--file-list", str(file_list), "--relative-root-marker", "repo", "--output", str(source), "--json", ) self.assertNotEqual(result.returncode, 0) summary = json.loads(result.stdout) self.assertEqual(summary["status"], "FAIL") self.assertIn("same as a source file", "\n".join(summary["errors"])) if __name__ == "__main__": unittest.main()