aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/test_vendor_libghostty_vt.py36
-rw-r--r--scripts/vendor_libghostty_vt.py14
2 files changed, 46 insertions, 4 deletions
diff --git a/scripts/test_vendor_libghostty_vt.py b/scripts/test_vendor_libghostty_vt.py
index 9dcdbb2d..ad5c8d5e 100644
--- a/scripts/test_vendor_libghostty_vt.py
+++ b/scripts/test_vendor_libghostty_vt.py
@@ -8,7 +8,11 @@ import unittest
from pathlib import Path
from unittest import mock
-from scripts.vendor_libghostty_vt import ensure_dist_archive, parse_archive_root
+from scripts.vendor_libghostty_vt import (
+ ensure_dist_archive,
+ parse_archive_root,
+ require_clean_checkout,
+)
class VendorLibghosttyVtTests(unittest.TestCase):
@@ -30,16 +34,44 @@ class VendorLibghosttyVtTests(unittest.TestCase):
dist.mkdir(parents=True)
(dist / "libghostty-vt-1.3.2-main-+deadbeef0.tar.gz").write_bytes(b"stale")
+ def git_output(command: list[str], **_kwargs: object) -> str:
+ if command[1] == "status":
+ return ""
+ return "0123456789abcdef\n"
+
with (
mock.patch("scripts.vendor_libghostty_vt.subprocess.run"),
mock.patch(
"scripts.vendor_libghostty_vt.subprocess.check_output",
- return_value="0123456789abcdef\n",
+ side_effect=git_output,
),
):
with self.assertRaisesRegex(FileNotFoundError, "HEAD 012345678"):
ensure_dist_archive(repo)
+ def test_require_clean_checkout_rejects_tracked_and_untracked_changes(self) -> None:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ repo = Path(temp_dir)
+ with mock.patch(
+ "scripts.vendor_libghostty_vt.subprocess.check_output",
+ return_value=" M src/terminal.zig\n?? local.patch\n",
+ ):
+ with self.assertRaisesRegex(ValueError, "refusing to vendor from dirty checkout"):
+ require_clean_checkout(repo)
+
+ def test_ensure_dist_archive_rejects_checkout_dirtied_by_build(self) -> None:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ repo = Path(temp_dir)
+ with (
+ mock.patch("scripts.vendor_libghostty_vt.subprocess.run"),
+ mock.patch(
+ "scripts.vendor_libghostty_vt.subprocess.check_output",
+ side_effect=["", "0123456789abcdef\n", " M generated.txt\n"],
+ ),
+ ):
+ with self.assertRaisesRegex(ValueError, "refusing to vendor from dirty checkout"):
+ ensure_dist_archive(repo)
+
def test_vendored_tree_contains_required_upstream_files(self) -> None:
root = Path(__file__).resolve().parent.parent / "vendor" / "libghostty-vt"
required = [
diff --git a/scripts/vendor_libghostty_vt.py b/scripts/vendor_libghostty_vt.py
index b493de03..7bd234d4 100644
--- a/scripts/vendor_libghostty_vt.py
+++ b/scripts/vendor_libghostty_vt.py
@@ -12,7 +12,6 @@ from pathlib import Path
@dataclass
class VendorMetadata:
- source_repo: str
source_commit: str
dist_archive: str
extracted_dir: str
@@ -34,13 +33,25 @@ def git_head(repo: Path) -> str:
return subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=repo, text=True).strip()
+def require_clean_checkout(repo: Path) -> None:
+ status = subprocess.check_output(
+ ["git", "status", "--porcelain", "--untracked-files=all"],
+ cwd=repo,
+ text=True,
+ ).strip()
+ if status:
+ raise ValueError(f"refusing to vendor from dirty checkout {repo}:\n{status}")
+
+
def ensure_dist_archive(source_repo: Path) -> Path:
+ require_clean_checkout(source_repo)
head = git_head(source_repo)[:9]
subprocess.run(
["zig", "build", "dist", "-Demit-lib-vt", "-Doptimize=ReleaseFast"],
cwd=source_repo,
check=True,
)
+ require_clean_checkout(source_repo)
dist_dir = source_repo / "zig-out" / "dist"
archives = sorted(dist_dir.glob(f"libghostty-vt-*+{head}.tar.gz"))
if not archives:
@@ -69,7 +80,6 @@ def vendor_libghostty_vt(source_repo: Path, destination: Path) -> VendorMetadata
shutil.copytree(extracted, destination)
return VendorMetadata(
- source_repo=str(source_repo),
source_commit=git_head(source_repo),
dist_archive=archive.name,
extracted_dir=root,