Files
nvrl 0a0917ac56
Check and Windows preview / check (anvil) (push) Successful in 2m5s
Check and Windows preview / check (crucible) (push) Successful in 2m11s
Check and Windows preview / check (lathe) (push) Successful in 2m22s
Check and Windows preview / check (patina) (push) Successful in 2m50s
Check and Windows preview / check (rivet) (push) Successful in 46s
Check and Windows preview / check (temper) (push) Successful in 41s
Check and Windows preview / check (weld) (push) Successful in 39s
Check and Windows preview / previews (push) Failing after 24s
Check and Windows preview / windows (push) Skipped
chore: rename the suite to Bass Foundry
Set the CLAP vendor of all seven plugins to "Bass Foundry" and name the
combined preview ZIP bass-foundry-windows-x86_64.zip. CLAP IDs and saved
state stay unchanged.

Bring development.md and releases.md up to date with all seven products,
the shared crates, the test types, the steps to add a product and the
published releases. Add texture problems and seven texture plugin ideas
to ideas.md.
2026-11-06 08:01:02 +01:00

68 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""Package a combined preview bundle or an independently versioned plugin."""
import argparse
import hashlib
from pathlib import Path
import struct
import zipfile
from plugin_catalog import ROOT, archive_name, catalog, version
def pe_check(name, data):
if len(data) < 64 or data[:2] != b"MZ":
raise ValueError(f"{name}: expected Windows PE binary")
offset = struct.unpack_from("<I", data, 0x3C)[0]
if offset + 24 > len(data) or data[offset:offset+4] != b"PE\0\0" or struct.unpack_from("<H", data, offset+4)[0] != 0x8664:
raise ValueError(f"{name}: expected x86-64 Windows DLL")
if b"clap_entry\0" not in data:
raise ValueError(f"{name}: CLAP entry export missing")
def package(target="x86_64-pc-windows-gnu", plugin=None, root=ROOT):
products = catalog(root)
selected = {plugin: products[plugin]} if plugin else products
folder = root / "dist" / target
names = ["LICENSE", "docs/development.md", "docs/releases.md"]
for product in selected.values():
name = f"{product['name']}.clap"
pe_check(name, (folder / name).read_bytes())
names.append(name)
names.extend(p.relative_to(root).as_posix() for p in (root / product["documentation"]).rglob("*") if p.is_file())
names.extend(product.get("licenses", {}).values())
payload = {name: (folder / name).read_bytes() for name in sorted(set(names))}
if plugin:
product = selected[plugin]
release_version = version(plugin, root)
filename = archive_name(plugin, release_version)
payload["README.md"] = (
f"# {product['name']} {release_version}\n\n{product['description']}.\n\n"
f"Copy {product['name']}.clap into C:\\Program Files\\Common Files\\CLAP\\ "
"and rescan plugins in FL Studio 2024.1 or newer.\n\n"
f"See [{product['name']} guide]({product['documentation']}/README.md).\n"
).encode()
else:
filename = "bass-foundry-windows-x86_64.zip"
payload["README.md"] = (folder / "README.md").read_bytes()
checksums = "".join(f"{hashlib.sha256(data).hexdigest()} {name}\n" for name, data in sorted(payload.items()))
payload["SHA256SUMS"] = checksums.encode()
archive = root / "dist" / filename
with zipfile.ZipFile(archive, "w", compression=zipfile.ZIP_DEFLATED) as output:
for name, data in sorted(payload.items()):
info = zipfile.ZipInfo(name, date_time=(2020, 1, 1, 0, 0, 0))
info.compress_type = zipfile.ZIP_DEFLATED
info.external_attr = 0o100644 << 16
output.writestr(info, data)
# Stable ZIP metadata makes repeated packaging of identical files reproducible.
sidecar = archive.with_suffix(".zip.sha256")
sidecar.write_text(f"{hashlib.sha256(archive.read_bytes()).hexdigest()} {archive.name}\n", encoding="utf-8")
print(f"Packaged {archive}")
return archive
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--plugin", choices=catalog(), help="Omit for a combined development bundle")
parser.add_argument("--target", default="x86_64-pc-windows-gnu", choices=["x86_64-pc-windows-gnu", "x86_64-pc-windows-msvc"])
args = parser.parse_args()
package(args.target, args.plugin)
if __name__ == "__main__":
main()