Files
iKeyMon/scripts/make_local_appcast.sh
2025-12-08 19:30:12 +01:00

76 lines
2.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Generate a local appcast that reuses the latest Sparkle entry but bumps the
# sparkle:version so Sparkle will reinstall the same build. Useful for testing
# updates without cutting a new release.
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
INPUT="${1:-$ROOT_DIR/Sparkle/appcast.xml}"
OUTPUT="${2:-$ROOT_DIR/Sparkle/appcast-local.xml}"
python3 - "$INPUT" "$OUTPUT" <<'PY'
import sys, xml.etree.ElementTree as ET, datetime, email.utils
if len(sys.argv) != 3:
sys.exit("Usage: make_local_appcast.sh [input] [output]")
src, dst = sys.argv[1], sys.argv[2]
tree = ET.parse(src)
root = tree.getroot()
channel = root.find("channel")
items = channel.findall("item") if channel is not None else []
if not items:
sys.exit("No items found in appcast")
latest = items[0]
enc = latest.find("enclosure")
if enc is None:
sys.exit("Latest item missing enclosure")
sparkle_ns = "{http://www.andymatuschak.org/xml-namespaces/sparkle}"
def get_text(tag):
el = latest.find(tag)
return el.text if el is not None else ""
short_version = get_text(f"{sparkle_ns}shortVersionString")
version_el = latest.find(f"{sparkle_ns}version")
try:
next_build = str(int(version_el.text) + 1000 if version_el is not None else 9999)
except ValueError:
next_build = "9999"
now_rfc822 = email.utils.format_datetime(datetime.datetime.now(datetime.timezone.utc))
new_item = ET.Element("item")
ET.SubElement(new_item, "title").text = f"{short_version} (reinstall)"
ET.SubElement(new_item, "pubDate").text = now_rfc822
sv = ET.SubElement(new_item, f"{sparkle_ns}shortVersionString")
sv.text = short_version
bv = ET.SubElement(new_item, f"{sparkle_ns}version")
bv.text = next_build
min_os = latest.find(f"{sparkle_ns}minimumSystemVersion")
if min_os is not None and min_os.text:
ET.SubElement(new_item, f"{sparkle_ns}minimumSystemVersion").text = min_os.text
new_enc = ET.SubElement(new_item, "enclosure")
for attr in ("url", "length", "type", f"{sparkle_ns}edSignature"):
if attr in enc.attrib:
new_enc.set(attr, enc.attrib[attr])
new_channel = ET.Element("channel")
title = channel.find("title")
ET.SubElement(new_channel, "title").text = title.text if title is not None else "Local"
new_channel.append(new_item)
new_root = ET.Element("rss", {
"version": "2.0",
"xmlns:sparkle": "http://www.andymatuschak.org/xml-namespaces/sparkle"
})
new_root.append(new_channel)
ET.indent(new_root, space=" ")
ET.ElementTree(new_root).write(dst, encoding="utf-8", xml_declaration=True)
print(f"✅ wrote {dst}")
PY