kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

ecosystem.sh (5303B)


      1 #!/usr/bin/env bash
      2 # scripts/ecosystem.sh — provision real-world C projects for the ecosystem gate.
      3 #
      4 # Fetches pinned, hash-verified upstream releases into the kit cache dir and
      5 # extracts them, so the integration tests (test/ecosystem/run.sh) run fully
      6 # offline against a reproducible source tree. The per-project metadata (URL,
      7 # version, sha256, layout) is the single source of truth in
      8 # test/ecosystem/recipes/<name>.recipe — this script just drives it.
      9 #
     10 # Cache dir resolution (matches driver/env's cache_dir convention):
     11 #   $KIT_ECO_CACHE                         (explicit override), else
     12 #   $XDG_CACHE_HOME/kit/ecosystem,         else
     13 #   $HOME/.cache/kit/ecosystem,            else
     14 #   <repo>/build/kit-cache/ecosystem
     15 #
     16 # Commands:
     17 #   list                      print recipe names, one per line
     18 #   cachedir                  print the resolved cache dir
     19 #   status                    show provisioned / missing per project
     20 #   entrydir <name>           print the cache entry dir for <name>
     21 #   srcdir   <name>           print the source root (entry/<ECO_SRCDIR>);
     22 #                             empty + exit 1 if not provisioned
     23 #   fetch <name>|all          download + verify sha256 + extract
     24 #   clean <name>|all          remove cache entries
     25 #
     26 # env: KIT_ECO_CACHE (cache override). No network except `fetch`.
     27 
     28 set -eu
     29 
     30 ROOT="$(cd "$(dirname "$0")/.." && pwd)"
     31 RECIPE_DIR="$ROOT/test/ecosystem/recipes"
     32 
     33 eco_cachedir() {
     34   if [ -n "${KIT_ECO_CACHE:-}" ]; then printf '%s\n' "$KIT_ECO_CACHE"; return; fi
     35   if [ -n "${XDG_CACHE_HOME:-}" ]; then printf '%s/kit/ecosystem\n' "$XDG_CACHE_HOME"; return; fi
     36   if [ -n "${HOME:-}" ]; then printf '%s/.cache/kit/ecosystem\n' "$HOME"; return; fi
     37   printf '%s/build/kit-cache/ecosystem\n' "$ROOT"
     38 }
     39 CACHE="$(eco_cachedir)"
     40 
     41 die() { printf 'ecosystem: %s\n' "$*" >&2; exit 1; }
     42 
     43 recipes() {
     44   for r in "$RECIPE_DIR"/*.recipe; do
     45     [ -e "$r" ] || continue
     46     basename "$r" .recipe
     47   done
     48 }
     49 
     50 recipe_path() {
     51   local p="$RECIPE_DIR/$1.recipe"
     52   [ -f "$p" ] || die "unknown project '$1' (see: $0 list)"
     53   printf '%s\n' "$p"
     54 }
     55 
     56 # Load a recipe's provisioning vars into the current shell. (Functions are
     57 # defined too but unused here.) Sets ECO_VERSION/URL/SHA256/SRCDIR.
     58 load_recipe() {
     59   ECO_VERSION=; ECO_URL=; ECO_SHA256=; ECO_SRCDIR=.
     60   # shellcheck disable=SC1090
     61   . "$(recipe_path "$1")"
     62   [ -n "$ECO_URL" ]    || die "$1: ECO_URL unset"
     63   [ -n "$ECO_SHA256" ] || die "$1: ECO_SHA256 unset"
     64 }
     65 
     66 entrydir() { load_recipe "$1"; printf '%s/%s-%s\n' "$CACHE" "$1" "$ECO_VERSION"; }
     67 
     68 srcdir() {
     69   local e; e="$(entrydir "$1")"
     70   load_recipe "$1"
     71   local s="$e/$ECO_SRCDIR"
     72   if [ -d "$s" ]; then printf '%s\n' "$s"; else return 1; fi
     73 }
     74 
     75 sha256_of() {
     76   if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | cut -d' ' -f1
     77   elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | cut -d' ' -f1
     78   else die "no sha256sum/shasum available"; fi
     79 }
     80 
     81 fetch_one() {
     82   local name="$1"
     83   load_recipe "$name"
     84   local entry; entry="$(entrydir "$name")"
     85   if [ -d "$entry/$ECO_SRCDIR" ]; then
     86     printf '  %-10s already provisioned (%s)\n' "$name" "$ECO_VERSION"
     87     return 0
     88   fi
     89   command -v curl >/dev/null 2>&1 || die "curl required for fetch"
     90 
     91   local tmp; tmp="$(mktemp -d "${TMPDIR:-/tmp}/kit-eco-$name.XXXXXX")"
     92   local ar="$tmp/archive"
     93 
     94   printf '  %-10s fetching %s\n' "$name" "$ECO_URL"
     95   curl -fsSL --retry 3 -o "$ar" "$ECO_URL" || die "$name: download failed"
     96 
     97   local got; got="$(sha256_of "$ar")"
     98   if [ "$got" != "$ECO_SHA256" ]; then
     99     die "$name: sha256 mismatch
    100     expected $ECO_SHA256
    101     got      $got"
    102   fi
    103 
    104   rm -rf "$entry"; mkdir -p "$entry"
    105   case "$ECO_URL" in
    106     *.zip)
    107       command -v unzip >/dev/null 2>&1 || die "unzip required for $name"
    108       unzip -q -o "$ar" -d "$entry" ;;
    109     *.tar.gz|*.tgz)
    110       tar xzf "$ar" -C "$entry" ;;
    111     *) die "$name: unknown archive type for $ECO_URL" ;;
    112   esac
    113 
    114   rm -rf "$tmp"
    115   [ -d "$entry/$ECO_SRCDIR" ] || die "$name: ECO_SRCDIR '$ECO_SRCDIR' not found after extract"
    116   printf '  %-10s OK %s -> %s\n' "$name" "$ECO_VERSION" "$entry/$ECO_SRCDIR"
    117 }
    118 
    119 cmd_fetch() {
    120   mkdir -p "$CACHE"
    121   if [ "${1:-all}" = all ]; then
    122     for n in $(recipes); do fetch_one "$n"; done
    123   else
    124     fetch_one "$1"
    125   fi
    126 }
    127 
    128 cmd_clean() {
    129   if [ "${1:-all}" = all ]; then
    130     for n in $(recipes); do rm -rf "$(entrydir "$n")"; done
    131     printf 'cleaned all ecosystem cache entries under %s\n' "$CACHE"
    132   else
    133     rm -rf "$(entrydir "$1")"; printf 'cleaned %s\n' "$1"
    134   fi
    135 }
    136 
    137 cmd_status() {
    138   printf 'cache: %s\n' "$CACHE"
    139   for n in $(recipes); do
    140     if srcdir "$n" >/dev/null 2>&1; then
    141       printf '  [x] %-10s %s\n' "$n" "$ECO_VERSION"
    142     else
    143       printf '  [ ] %-10s %s (run: %s fetch %s)\n' "$n" "$ECO_VERSION" "$0" "$n"
    144     fi
    145   done
    146 }
    147 
    148 main() {
    149   local cmd="${1:-status}"; shift || true
    150   case "$cmd" in
    151     list|recipes) recipes ;;
    152     cachedir)     printf '%s\n' "$CACHE" ;;
    153     status)       cmd_status ;;
    154     entrydir)     [ $# -ge 1 ] || die "entrydir <name>"; entrydir "$1" ;;
    155     srcdir)       [ $# -ge 1 ] || die "srcdir <name>"; srcdir "$1" || { printf '' ; exit 1; } ;;
    156     fetch)        cmd_fetch "${1:-all}" ;;
    157     clean)        cmd_clean "${1:-all}" ;;
    158     *) die "unknown command '$cmd' (list|cachedir|status|entrydir|srcdir|fetch|clean)" ;;
    159   esac
    160 }
    161 
    162 main "$@"