feat(tooling): add-custom-mod.sh — host local jars as packwiz external files
Copies a local jar under pack/custom/ (served by caddy), sha256s it, writes pack/mods/<slug>.pw.toml per packwiz "Other external files", then packwiz refresh. Cautious: halts on bad side, whitespace in filename, or existing entry without --force. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
105
tooling/add-custom-mod.sh
Executable file
105
tooling/add-custom-mod.sh
Executable file
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env bash
|
||||
# add-custom-mod.sh — add a LOCAL jar to the packwiz pack as an "external file".
|
||||
#
|
||||
# Implements the "Other external files" flow from
|
||||
# https://packwiz.infra.link/tutorials/creating/adding-mods/ : a hand-written
|
||||
# <slug>.pw.toml that points at a stable download URL + sha256, then refresh.
|
||||
#
|
||||
# Since the jar is local (no public URL), we HOST it on the caddy pack server:
|
||||
# the jar is copied under pack/custom/ — caddy serves pack/ at
|
||||
# http://pack.${BASE_DOMAIN}/ — so the metadata's download url is
|
||||
# http://pack.${BASE_DOMAIN}/custom/<filename>
|
||||
# which is exactly what minecraft fetches via PACKWIZ_URL on install.
|
||||
#
|
||||
# Usage:
|
||||
# tooling/add-custom-mod.sh <path/to/mod.jar> [--name "Nice Name"]
|
||||
# [--side both|client|server] [--force]
|
||||
#
|
||||
# Defaults: name = jar filename without .jar, side = both.
|
||||
# Cautious: halts on missing tool/var, bad side, whitespace in filename, or an
|
||||
# existing metadata/custom jar (unless --force).
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.." # repo root
|
||||
|
||||
# ---- helpers ---------------------------------------------------------------
|
||||
log() { printf '\n\033[1;32m==>\033[0m %s\n' "$*"; }
|
||||
warn() { printf '\033[1;33m!!\033[0m %s\n' "$*" >&2; }
|
||||
die() { printf '\033[1;31mxx\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
slugify() { # lowercase, non-alnum -> hyphen, squeeze + trim hyphens
|
||||
printf '%s' "$1" | tr '[:upper:]' '[:lower:]' \
|
||||
| sed -E 's/[^a-z0-9]+/-/g; s/-+/-/g; s/^-//; s/-$//'
|
||||
}
|
||||
|
||||
# ---- args ------------------------------------------------------------------
|
||||
JAR=""; NAME=""; SIDE="both"; FORCE=0
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--name) NAME="${2:?--name needs a value}"; shift 2 ;;
|
||||
--side) SIDE="${2:?--side needs a value}"; shift 2 ;;
|
||||
--force) FORCE=1; shift ;;
|
||||
-h|--help) sed -n '2,18p' "$0"; exit 0 ;;
|
||||
-*) die "unknown flag: $1" ;;
|
||||
*) [ -z "$JAR" ] || die "only one jar at a time (got extra: $1)"; JAR="$1"; shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ -n "$JAR" ] || die "no jar given. usage: tooling/add-custom-mod.sh <mod.jar> [--name N] [--side both|client|server]"
|
||||
[ -f "$JAR" ] || die "jar not found: $JAR"
|
||||
case "$SIDE" in both|client|server) ;; *) die "invalid --side '$SIDE' (both|client|server)" ;; esac
|
||||
|
||||
# ---- preflight -------------------------------------------------------------
|
||||
command -v packwiz >/dev/null 2>&1 || die "missing required tool: packwiz (https://packwiz.infra.link)"
|
||||
command -v sha256sum >/dev/null 2>&1 || die "missing required tool: sha256sum"
|
||||
[ -f .env ] || die ".env not found (copy .env.example and fill it)"
|
||||
# shellcheck disable=SC1091
|
||||
set -a; . ./.env; set +a
|
||||
: "${BASE_DOMAIN:?BASE_DOMAIN unset in .env}"
|
||||
[ -f pack/pack.toml ] || die "pack/pack.toml not found — run from a packwiz pack (see plan/04-packwiz.md)"
|
||||
|
||||
FILENAME="$(basename -- "$JAR")"
|
||||
case "$FILENAME" in *.jar) ;; *) die "not a .jar: $FILENAME" ;; esac
|
||||
case "$FILENAME" in *[[:space:]]*) die "filename has whitespace: '$FILENAME' — rename it (URL-unsafe)" ;; esac
|
||||
|
||||
[ -n "$NAME" ] || NAME="${FILENAME%.jar}"
|
||||
SLUG="$(slugify "$NAME")"
|
||||
[ -n "$SLUG" ] || die "could not derive a slug from name '$NAME'"
|
||||
|
||||
META="pack/mods/${SLUG}.pw.toml"
|
||||
DEST="pack/custom/${FILENAME}"
|
||||
URL="http://pack.${BASE_DOMAIN}/custom/${FILENAME}"
|
||||
|
||||
if [ "$FORCE" -ne 1 ]; then
|
||||
[ -e "$META" ] && die "metadata exists: $META (use --force to overwrite)"
|
||||
[ -e "$DEST" ] && die "hosted jar exists: $DEST (use --force to overwrite)"
|
||||
fi
|
||||
|
||||
# ---- write -----------------------------------------------------------------
|
||||
HASH="$(sha256sum -- "$JAR" | cut -d' ' -f1)"
|
||||
|
||||
mkdir -p pack/custom pack/mods
|
||||
cp -- "$JAR" "$DEST"
|
||||
|
||||
cat > "$META" <<EOF
|
||||
name = "${NAME}"
|
||||
filename = "${FILENAME}"
|
||||
side = "${SIDE}"
|
||||
|
||||
[download]
|
||||
url = "${URL}"
|
||||
hash-format = "sha256"
|
||||
hash = "${HASH}"
|
||||
EOF
|
||||
|
||||
log "wrote $META"
|
||||
echo " hosted jar : $DEST -> $URL"
|
||||
echo " side : $SIDE"
|
||||
echo " sha256 : $HASH"
|
||||
|
||||
# ---- refresh ---------------------------------------------------------------
|
||||
# packwiz refresh rebuilds index.toml (and pack.toml's index hash) so the new
|
||||
# .pw.toml is picked up. Must run inside the pack dir.
|
||||
( cd pack && packwiz refresh )
|
||||
log "packwiz refresh done — '${NAME}' added to the pack"
|
||||
echo " commit pack/custom/${FILENAME}, ${META}, pack/index.toml, pack/pack.toml"
|
||||
Reference in New Issue
Block a user