186 lines
6.8 KiB
Bash
186 lines
6.8 KiB
Bash
# kama.sh — shared core library for the Kama package manager
|
|
#
|
|
# Sources make.conf, provides helpers, and implements the fetch/build/
|
|
# install/temp-dep logic. All the messy bits live here so recipes stay clean.
|
|
|
|
PREFIX="\033[1;36m[ kama ]\033[0m"
|
|
|
|
# --- config ---------------------------------------------------------
|
|
# Where the package recipe repository lives (kama-packages repo).
|
|
PKGDIR="${PKGDIR:-$SELF_DIR/../kama-packages}"
|
|
# merge a make.conf if one is provided
|
|
MAKE_CONF="${MAKE_CONF:-/etc/kama/make.conf}"
|
|
[ -f "$MAKE_CONF" ] && . "$MAKE_CONF"
|
|
|
|
ROOT="${ROOT:-/tmp/keru/root}"
|
|
CACHEDIR="${CACHEDIR:-/var/cache/kama}"
|
|
SRCDIR="$CACHEDIR/src"
|
|
DLDIR="$CACHEDIR/dl"
|
|
STAGEDIR="$CACHEDIR/stage"
|
|
|
|
# --- message helpers -------------------------------------------------
|
|
msg() { printf '%b %s\n' "$PREFIX" "$*"; }
|
|
warn() { printf '%b \033[1;33mwarning:\033[0m %s\n' "$PREFIX" "$*"; }
|
|
die() { printf '%b \033[1;31merror:\033[0m %s\n' "$PREFIX" "$*" >&2; exit 1; }
|
|
|
|
# --- easy/advanced tier mapping --------------------------------------
|
|
# If a recipe defines the easy-tier `build`/`install` sugar (and doesn't
|
|
# define the advanced pkg_* forms), alias them. This keeps simple recipes
|
|
# simple and gives advanced recipes full control.
|
|
map_tiers() {
|
|
# map build -> pkg_build unless pkg_build is overridden
|
|
if declare -f build >/dev/null 2>&1 && ! declare -f pkg_build >/dev/null 2>&1; then
|
|
pkg_build() { build; }
|
|
fi
|
|
if declare -f install >/dev/null 2>&1 && ! declare -f pkg_install >/dev/null 2>&1; then
|
|
pkg_install() { install; }
|
|
fi
|
|
# advanced recipes may define pkg_build/pkg_install directly — leave as-is
|
|
}
|
|
|
|
# --- default fetch: download + auto-extract -----------------------------
|
|
default_fetch() {
|
|
local tarball="$DLDIR/$(basename "$url")"
|
|
mkdir -p "$DLDIR" "$SRCDIR"
|
|
if [ ! -f "$tarball" ]; then
|
|
msg "downloading $url"
|
|
wget -q --show-progress "$SOURCE_MIRROR/$(basename "$url")" -O "$tarball" \
|
|
|| wget -q --show-progress "$url" -O "$tarball" \
|
|
|| die "download failed for $name"
|
|
else
|
|
msg "using cached source for $name"
|
|
fi
|
|
|
|
local s="$SRCDIR/$name"
|
|
rm -rf "$s"; mkdir -p "$s"
|
|
msg "extracting $name"
|
|
case "$tarball" in
|
|
*.tar.gz|*.tgz) tar xf "$tarball" -C "$s" --strip-components=1 ;;
|
|
*.tar.xz|*.txz) tar xJf "$tarball" -C "$s" --strip-components=1 ;;
|
|
*.tar.bz2|*.tbz2) tar xjf "$tarball" -C "$s" --strip-components=1 ;;
|
|
*.tar) tar xf "$tarball" -C "$s" --strip-components=1 ;;
|
|
*.zip) unzip -q "$tarball" -d "$s.tmp" && \
|
|
mv "$s.tmp"/*/* "$s/" ; rm -rf "$s.tmp" ;;
|
|
*) die "unsupported archive type: $tarball" ;;
|
|
esac
|
|
}
|
|
|
|
# --- locate a recipe --------------------------------------------------
|
|
find_recipe() {
|
|
local pkg="$1"
|
|
for rec in \
|
|
"$PKGDIR/$pkg/PKGBUILD" \
|
|
"$PKGDIR/$pkg.sh" \
|
|
"$PKGDIR/$pkg"/*.sh ; do
|
|
[ -f "$rec" ] && { printf '%s' "$rec"; return 0; }
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# --- fetch + extract source -------------------------------------------
|
|
# --- fetch + extract source -------------------------------------------
|
|
kama_fetch() {
|
|
[ $# -ge 1 ] || die "fetch: missing package name"
|
|
for pkg in "$@"; do
|
|
local recipe; recipe="$(find_recipe "$pkg")" || die "no recipe for '$pkg'"
|
|
msg "fetching source for $pkg"
|
|
. "$recipe"
|
|
map_tiers
|
|
|
|
local src="$SRCDIR/$name"
|
|
if [ -d "$src" ] && [ -n "$(ls -A "$src" 2>/dev/null)" ]; then
|
|
msg "using cached source for $pkg"
|
|
continue
|
|
fi
|
|
|
|
# advanced recipe overrides pkg_fetch -> use it; otherwise default_fetch
|
|
if declare -f pkg_fetch >/dev/null 2>&1; then
|
|
pkg_fetch
|
|
else
|
|
default_fetch
|
|
fi
|
|
[ -d "$src" ] && [ -n "$(ls -A "$src" 2>/dev/null)" ] \
|
|
|| die "fetch produced no source for $pkg"
|
|
done
|
|
}
|
|
|
|
# --- stage-build a single recipe ---------------------------------------
|
|
kama_build() {
|
|
[ $# -ge 1 ] || die "build: missing package name"
|
|
for pkg in "$@"; do
|
|
local recipe; recipe="$(find_recipe "$pkg")" || die "no recipe for '$pkg'"
|
|
msg "building $pkg"
|
|
. "$recipe"
|
|
map_tiers
|
|
|
|
local src="$SRCDIR/$name"
|
|
local pkgdir="$STAGEDIR/$name"
|
|
[ -d "$src" ] && [ -n "$(ls -A "$src" 2>/dev/null)" ] || kama_fetch "$pkg"
|
|
|
|
rm -rf "$pkgdir"; mkdir -p "$pkgdir"
|
|
( cd "$src" && pkg_build ) || die "build failed for $pkg"
|
|
msg "staging install for $pkg"
|
|
( cd "$src" && pkg_install ) || die "install failed for $pkg"
|
|
( cd "$src" && pkg_post ) || die "post-install failed for $pkg"
|
|
pkg_split || true
|
|
done
|
|
}
|
|
|
|
# --- install staging dir into ROOT --------------------------------------
|
|
install_staged() {
|
|
local pkg="$1"
|
|
local pkgdir="$STAGEDIR/$pkg"
|
|
[ -d "$pkgdir" ] || die "nothing staged for '$pkg'"
|
|
msg "installing $pkg into \$ROOT"
|
|
( cd "$pkgdir" && cp -a . "$ROOT" )
|
|
}
|
|
|
|
# --- high-level: make a package (deps + build + install + purge) --------
|
|
kama_make() {
|
|
[ $# -ge 1 ] || die "make: missing package name"
|
|
for pkg in "$@"; do
|
|
local recipe; recipe="$(find_recipe "$pkg")" || die "no recipe for '$pkg'"
|
|
. "$recipe"
|
|
|
|
# temp deps: build, stage, install, then purge after
|
|
if [ -n "${deps+x}" ] && [ ${#deps[@]} -gt 0 ]; then
|
|
msg "building temp deps for $pkg: ${deps[*]}"
|
|
kama_make "${deps[@]}"
|
|
fi
|
|
|
|
kama_build "$pkg"
|
|
install_staged "$pkg"
|
|
|
|
if [ "${PURGE_TEMP_DEPS:-1}" = "1" ] && [ -n "${deps+x}" ] && [ ${#deps[@]} -gt 0 ]; then
|
|
msg "purging temp deps for $pkg: ${deps[*]}"
|
|
kama_purge "${deps[@]}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# --- show recipe metadata ------------------------------------------------
|
|
kama_info() {
|
|
[ $# -ge 1 ] || die "info: missing package name"
|
|
local recipe; recipe="$(find_recipe "$1")" || die "no recipe for '$1'"
|
|
. "$recipe"
|
|
printf 'name : %s\n' "$name"
|
|
printf 'version : %s\n' "$version"
|
|
printf 'url : %s\n' "$url"
|
|
printf 'deps : %s\n' "${deps[*]:-}"
|
|
printf 'runtime_deps: %s\n' "${runtime_deps[*]:-}"
|
|
}
|
|
|
|
# --- purge temp deps from ROOT --------------------------------------------
|
|
# NOTE: This is intentionally naive for the scaffold. A real implementation
|
|
# tracks what each recipe installed and removes exactly that, plus clears the
|
|
# staged dir. For now it clears the stage so a re-make re-pulls.
|
|
kama_purge() {
|
|
for pkg in "$@"; do
|
|
msg "purging temp dep '$pkg' (stage)"
|
|
rm -rf "$STAGEDIR/$pkg"
|
|
done
|
|
}
|
|
|
|
# --- init ----------------------------------------------------------------
|
|
mkdir -p "$ROOT" "$CACHEDIR" "$SRCDIR" "$DLDIR" "$STAGEDIR"
|