Files
spotifast/packaging/release-names.py
T
Carmine Paolino ce469046ba Use Spotifast package and download names with upgrade compatibility
Publish canonical AUR, Homebrew and native package names while retaining existing application identities and updater-compatible archives. Announce the AUR move in packaging-only revisions of the old packages.

Keep 0.8.0 application bytes unchanged. Cover both release filename sets in checksums and validate native Linux package replacement against pinned old-package fixtures.
2026-09-14 17:21:50 +02:00

51 lines
2.0 KiB
Python

#!/usr/bin/env python3
"""Publish Spotifast filenames and byte-identical names for older updaters."""
import argparse
import hashlib
from pathlib import Path
import re
import shutil
def prepare(directory, tag):
if not re.fullmatch(r"v\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?", tag):
raise ValueError("Expected a release tag")
pairs = {}
for path in directory.iterdir():
for prefix in ("spotifast-", "fastpotify-"):
if path.name.startswith(prefix + tag + "-"):
if not path.is_file() or path.is_symlink():
raise ValueError(f"Expected a regular release file: {path.name}")
suffix = path.name[len(prefix):]
pairs[suffix] = (
directory / ("spotifast-" + suffix),
directory / ("fastpotify-" + suffix),
)
if not pairs:
raise ValueError("No release downloads found")
# Check every pair before writing, so conflicting inputs never get replaced.
def digest(path):
with path.open("rb") as stream:
return hashlib.file_digest(stream, "sha256").hexdigest()
for canonical, legacy in pairs.values():
if canonical.exists() and legacy.exists() and digest(canonical) != digest(legacy):
raise ValueError(f"Different bytes for {canonical.name} and {legacy.name}")
for canonical, legacy in pairs.values():
if not canonical.exists():
shutil.copyfile(legacy, canonical)
elif not legacy.exists():
shutil.copyfile(canonical, legacy)
files = sorted(path for pair in pairs.values() for path in pair)
manifest = "".join(f"{digest(path)} {path.name}\n" for path in files)
(directory / "checksums.txt").write_text(manifest)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("directory", type=Path)
parser.add_argument("tag")
args = parser.parse_args()
prepare(args.directory, args.tag)