#!/usr/bin/env bash # Fetch and unpack a MegaMek release, which is the thing this repository reads # and deliberately does not contain. # # ./scripts/fetch-megamek.sh 0.51.0 # ./scripts/fetch-megamek.sh 0.51.0 /somewhere/else # # Prints the install path on stdout, so it composes: # # MM_HOME="$(./scripts/fetch-megamek.sh 0.51.0)" # # It gets you the unit files, the art and the jar. It does not get you the # equipment catalogue: that is computed when MegaMek loads, comes out through # bridge/dump.sh, and needs a container. Every command here that prices a # design needs both, and says so. # # The digest is not optional and not ours to invent. Upstream publishes none, # so the table below holds digests taken from a fetch that was checked twice, # and a version that is not in it needs one passed in rather than being # trusted: # # HELM_MEGAMEK_SHA256= ./scripts/fetch-megamek.sh 0.52.0 # # arena pins the same release for the container a match runs in, in its # versions.env, and the digest here for 0.51.0 is that one. When they differ, # the match and the library are describing different games. set -euo pipefail usage() { echo "usage: scripts/fetch-megamek.sh [install-dir]" } # Releases this repository has been run against, and the digest of each # release tarball. Add a line when a version is taken, from a fetch you trust. sha256_for() { case "$1" in 0.51.0) echo "5d673cdaca0ead0e58d6e74db5b2d1e06bc25ccb5caaf332dad71624f6487b85" ;; *) echo "" ;; esac } version="${1:-}" if [ -z "$version" ]; then usage >&2 exit 2 fi if [ "$version" = "-h" ] || [ "$version" = "--help" ]; then usage exit 0 fi cache="${XDG_CACHE_HOME:-$HOME/.cache}/helm/megamek" dest="${2:-$cache/$version}" mkdir -p "$cache" # Already unpacked: say where and stop. The tree is 590MB and a release's bytes # never change, so re-fetching one is only ever wasted time. if [ -f "$dest/MegaMek.jar" ] && [ -d "$dest/data/mekfiles" ]; then echo "already unpacked" >&2 echo "$dest" exit 0 fi sha256="${HELM_MEGAMEK_SHA256:-$(sha256_for "$version")}" [ -n "$sha256" ] || { echo "no digest known for MegaMek $version." >&2 echo " Upstream publishes none, so take one from a fetch you trust and pass it:" >&2 echo " HELM_MEGAMEK_SHA256= $0 $version" >&2 echo " then add it to sha256_for() in this script." >&2 exit 1 } url="https://github.com/MegaMek/megamek/releases/download/v${version}/MegaMek-${version}.tar.gz" tarball="$cache/MegaMek-${version}.tar.gz" # Kept, and checked whether it was kept or fetched. The release is 639MB and # the check is what makes a cached copy safe to believe. if [ -f "$tarball" ] && echo "$sha256 $tarball" | sha256sum -c --status -; then echo "using $tarball" >&2 else echo "fetching $url" >&2 # A progress meter for a person watching 609MB arrive, and nothing at all # when this is a step inside something else. quiet="" [ -t 2 ] || quiet="-s" # To a partial name, moved into place only once the digest checks, so an # interrupted download is never mistaken for a release. # shellcheck disable=SC2086 # $quiet is one flag or nothing, deliberately curl -fSL $quiet --retry 3 --retry-connrefused -o "$tarball.part" "$url" if ! echo "$sha256 $tarball.part" | sha256sum -c --status -; then rm -f "$tarball.part" echo "digest mismatch for MegaMek $version" >&2 echo " expected $sha256" >&2 echo " refusing to unpack a tarball that is not the pinned release" >&2 exit 1 fi mv "$tarball.part" "$tarball" fi # Upstream's tarball does not spell the version the way the tag does — 0.51.0 # unpacks as MegaMek-0.51.00 — so the directory is found rather than assumed. staging="$(mktemp -d "$cache/unpack.XXXXXX")" trap 'rm -rf "$staging"' EXIT tar -xzf "$tarball" -C "$staging" root="$(find "$staging" -maxdepth 1 -type d -name 'MegaMek-*' | head -1)" [ -n "$root" ] || { echo "no MegaMek-* directory in the tarball; upstream changed its layout" >&2 exit 1 } mkdir -p "$(dirname "$dest")" rm -rf "$dest" mv "$root" "$dest" echo "unpacked MegaMek $version into $dest" >&2 echo >&2 echo "Reading the library needs nothing else:" >&2 echo " cargo build --release" >&2 echo " ./target/release/helm art --megamek $dest --out art.json" >&2 echo >&2 echo "Anything that prices a design also needs the equipment catalogue, which" >&2 echo "MegaMek computes at load time. That is what the bridge is for, and it" >&2 echo "runs a JDK in a container:" >&2 echo " ./bridge/dump.sh $dest /tmp/helm-bridge" >&2 echo " ./target/release/helm index --megamek $dest --bridge-dir /tmp/helm-bridge --out units.json" >&2 echo "$dest"