diff --git a/scripts/assemble_release.py b/scripts/assemble_release.py index 29050ad..8cbe168 100644 --- a/scripts/assemble_release.py +++ b/scripts/assemble_release.py @@ -29,6 +29,8 @@ def _download(url: str, expected_sha: str, label: str) -> bytes: def assemble(entry: dict, out: Path, index_dir: Path | None = None) -> Path: parts = entry.get("parts") or [] chunks: list[bytes] = [] + if not parts and entry.get("url"): + chunks = [_download(entry["url"], entry.get("sha256", ""), entry["url"].rsplit("/", 1)[-1])] for p in parts: name = p["url"].rsplit("/", 1)[-1] chunks.append(_download(p["url"], p["sha256"], name)) diff --git a/tests/test_assemble_release.py b/tests/test_assemble_release.py index 0d965b1..a59104a 100644 --- a/tests/test_assemble_release.py +++ b/tests/test_assemble_release.py @@ -59,6 +59,24 @@ def test_sha_mismatch_rejected(self): with self.assertRaisesRegex(ValueError, "sha256"): assemble(self._entry(base, self.bad_sha), out) + def test_single_url_entry_assembles_and_verifies(self): + base = self._serve(_files_handler({"x-1.0.zip": self.whole})) + d = tempfile.TemporaryDirectory() + self.addCleanup(d.cleanup) + out = Path(d.name) / "x.zip" + entry = {"url": f"{base}/x-1.0.zip", "sha256": self.sha, "filename": "x-1.0.zip"} + assemble(entry, out) + self.assertEqual(out.read_bytes(), self.whole) + + def test_single_url_entry_sha_mismatch_rejected(self): + base = self._serve(_files_handler({"x-1.0.zip": self.whole})) + d = tempfile.TemporaryDirectory() + self.addCleanup(d.cleanup) + out = Path(d.name) / "x.zip" + entry = {"url": f"{base}/x-1.0.zip", "sha256": self.bad_sha, "filename": "x-1.0.zip"} + with self.assertRaisesRegex(ValueError, "sha256"): + assemble(entry, out) + def test_part_sha_mismatch_rejected(self): parts = {"x.part-00": b"X" * 1024, "x.part-01": PART_B} base = self._serve(_files_handler(parts))