|
| 1 | +#!/usr/bin/env bash |
| 2 | +# SPDX-License-Identifier: MPL-2.0 |
| 3 | +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) |
| 4 | +# |
| 5 | +# fetch-cartridges.sh — populate a host-local cartridge cache from the canonical |
| 6 | +# hyperpolymath/boj-server-cartridges registry, for on-demand consumption by the |
| 7 | +# Elixir catalog (BojRest.Catalog reads cartridge.json under <root>/*/). |
| 8 | +# |
| 9 | +# This is the runtime half of the cartridge-extraction migration (boj-server#158 |
| 10 | +# landed the catalog fallback chain; this script supplies the fetch the chain |
| 11 | +# expects). It is additive: nothing invokes it until the catalog default is |
| 12 | +# flipped to BOJ_CARTRIDGES_PATH, so it can ship ahead of that flip. |
| 13 | +# |
| 14 | +# The registry stores cartridges under a hybrid taxonomy |
| 15 | +# cartridges/domains/<domain>/<name>/ |
| 16 | +# cartridges/cross-cutting/<category>/<name>/ |
| 17 | +# whereas the catalog expects a flat <root>/<name>/. This script flattens the |
| 18 | +# tree as it populates the cache; cartridge names are unique across the registry, |
| 19 | +# so the flatten cannot collide. |
| 20 | +# |
| 21 | +# Usage: |
| 22 | +# scripts/fetch-cartridges.sh [target-dir] |
| 23 | +# Environment: |
| 24 | +# BOJ_CARTRIDGES_PATH target cache dir (default: $HOME/.boj/cartridges); |
| 25 | +# overridden by the positional argument when given. |
| 26 | +# BOJ_CARTRIDGES_REF git ref to fetch (default: main). |
| 27 | +# BOJ_CARTRIDGES_REPO source repo URL (default: the canonical GitHub registry). |
| 28 | + |
| 29 | +set -euo pipefail |
| 30 | + |
| 31 | +TARGET="${1:-${BOJ_CARTRIDGES_PATH:-$HOME/.boj/cartridges}}" |
| 32 | +REF="${BOJ_CARTRIDGES_REF:-main}" |
| 33 | +REPO="${BOJ_CARTRIDGES_REPO:-https://github.com/hyperpolymath/boj-server-cartridges.git}" |
| 34 | + |
| 35 | +# Shallow-clone the registry into a scratch dir; remove it on any exit. |
| 36 | +WORK="$(mktemp -d)" |
| 37 | +trap 'rm -rf "$WORK"' EXIT |
| 38 | + |
| 39 | +echo "Fetching cartridges from $REPO@$REF" |
| 40 | +git clone --depth 1 --branch "$REF" "$REPO" "$WORK/registry" |
| 41 | + |
| 42 | +SRC="$WORK/registry/cartridges" |
| 43 | +if [ ! -d "$SRC" ]; then |
| 44 | + echo "error: no cartridges/ directory in the registry checkout" >&2 |
| 45 | + exit 1 |
| 46 | +fi |
| 47 | + |
| 48 | +# Stage the flattened tree beside the target, then swap it in, so a concurrent |
| 49 | +# reader never observes a half-populated cache. |
| 50 | +STAGE="$(mktemp -d "${TARGET%/}.stage.XXXXXX" 2>/dev/null || mktemp -d)" |
| 51 | +trap 'rm -rf "$WORK" "$STAGE"' EXIT |
| 52 | + |
| 53 | +count=0 |
| 54 | +# Every directory that holds a cartridge.json is a cartridge root, at whatever |
| 55 | +# depth the taxonomy nests it. Find them and copy each to <stage>/<name>/. |
| 56 | +while IFS= read -r manifest; do |
| 57 | + cart_dir="$(dirname "$manifest")" |
| 58 | + name="$(basename "$cart_dir")" |
| 59 | + if [ -e "$STAGE/$name" ]; then |
| 60 | + echo "warning: duplicate cartridge name '$name' — keeping first, skipping $cart_dir" >&2 |
| 61 | + continue |
| 62 | + fi |
| 63 | + cp -r "$cart_dir" "$STAGE/$name" |
| 64 | + count=$((count + 1)) |
| 65 | +done < <(find "$SRC" -type f -name cartridge.json | sort) |
| 66 | + |
| 67 | +echo "Flattened $count cartridges" |
| 68 | + |
| 69 | +# Atomic-ish swap: move the old cache aside, move the new one in, drop the old. |
| 70 | +mkdir -p "$(dirname "$TARGET")" |
| 71 | +if [ -e "$TARGET" ]; then |
| 72 | + OLD="$(mktemp -d "${TARGET%/}.old.XXXXXX" 2>/dev/null || mktemp -d)" |
| 73 | + rm -rf "$OLD" |
| 74 | + mv "$TARGET" "$OLD" |
| 75 | + mv "$STAGE" "$TARGET" |
| 76 | + rm -rf "$OLD" |
| 77 | +else |
| 78 | + mv "$STAGE" "$TARGET" |
| 79 | +fi |
| 80 | + |
| 81 | +echo "Cartridge cache ready at $TARGET ($count cartridges)" |
| 82 | +echo "Point boj-server at it with: export BOJ_CARTRIDGES_PATH=$TARGET" |
0 commit comments