TAKANA_X con caída a HAMMER_X (ADR 0016). No es un sed: estas variables son
contrato de usuario —knobs del instalador, el entorno del worker, mirror-env.sh—
y viven en perfiles de shell y units FUERA del repo, así que un renombre duro no
falla ruidosamente: la variable no aparece, se toma el default y el build se
comporta distinto sin que nada lo diga.
Rust: takana_core::env::{var,var_os} toma el nombre canónico y deriva el viejo
cambiando el prefijo — se le pasa TAKANA_* para que un grep del nombre nuevo
encuentre todas las lecturas. 5 tests, con DOS controles negativos: sin ninguna
de las dos no hay valor, y un nombre sin prefijo no inventa una caída.
Migrados los 17 sitios directos y los indirectos que el grep no mostraba
(bases_de_mirror, las constantes de kernel_cmd, ROOT_ENV de qorpa, env_path de
recover). takana-recover lleva la caída inline: es un mini-binario que se copia
a /usr/sbin y no vale arrastrarle una dep entera por dos líneas.
Scripts: 30 lecturas pasan a default, manteniendo el
nombre INTERNO de la variable para no tocar sus 190 usos.
Y donde el script EXPORTA en vez de leer, se ponen LAS DOS (mirror-env.sh y el
fragmento in-VM de bootstrap): ahí el lector puede ser un binario viejo —worker
sin recompilar, el /usr/bin/hammer pinado del baseline— que sólo conoce HAMMER_*.
La caída sirve para lectores nuevos; los viejos necesitan que la vieja siga puesta.
Verificado de punta a punta con el binario, no sólo con unit tests: HAMMER_LAB
sigue surtiendo efecto, TAKANA_LAB hace lo mismo, y con las dos gana TAKANA_LAB.
605 tests en verde y el hash de zlib sigue en b3:dc363f26… , intacto.
Cambio de comportamiento que va aparte y hay que decir: el hostname por defecto
de una instalación nueva pasa de 'hammer' a 'takana' (sólo si no se fija ninguna
de las dos variables).
NO se tocan: las rutas /var/lib/hammer de sistemas instalados, el volid
HAMMER_LIVE del ISO, ni el namespace HARKAQ_*, que es de otro subsistema.
65 lines
3.3 KiB
Bash
65 lines
3.3 KiB
Bash
#!/usr/bin/env bash
|
|
# complete-closure.sh — completa el cierre RUNTIME de un FHS hidratado: escanea los `NEEDED` (DT_NEEDED)
|
|
# de cada ELF del rootfs y, por cada soname AUSENTE, proyecta del store SELLADO el artefacto que lo
|
|
# provee (`hammer hydrate`). Itera hasta punto fijo. Resuelve las deps runtime que el índice del repo NO
|
|
# lista (p.ej. libmount.so.1 de util-linux, dep de build de kcoreaddons pero .so runtime de libKF6CoreAddons).
|
|
#
|
|
# Sonames del SUSTRATO base (musl libc, loader, libgcc) NO se hidratan: los provee la base soberana del
|
|
# sistema destino. El resto se toma del store (mtime<CUTOFF = cosecha coherente).
|
|
set -uo pipefail
|
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT"
|
|
STORE="${STORE:-./store}"; RFS="${RFS:-work/kde-store-rootfs}"; LINK="${LINK:-static}"
|
|
HAMMER="${TAKANA:-${HAMMER:-./target/release/takana}}"
|
|
CUTOFF="${CUTOFF:-$(date -d 'today 00:00' +%s 2>/dev/null || echo 9999999999)}"
|
|
# sonames provistos por la base (no soberanos aún / runtime del sistema): no hidratar.
|
|
BASE_SONAMES="libc.so libc.musl-x86_64.so.1 ld-musl-x86_64.so.1 libc.so.6 ld-linux-x86-64.so.2 libm.so.6 libdl.so.2 libpthread.so.0 librt.so.1 libresolv.so.2"
|
|
|
|
is_base(){ case " $BASE_SONAMES " in *" $1 "*) return 0;; esac; return 1; }
|
|
|
|
# índice soname -> artefacto (hash) del store, sólo mtime<CUTOFF (set coherente).
|
|
echo "==> indexando sonames del store (mtime<$(date -d @$CUTOFF 2>/dev/null||echo $CUTOFF))…"
|
|
declare -A PROV
|
|
while IFS= read -r d; do
|
|
hash="${d##*/}"; hash="${hash%%-*}"
|
|
while IFS= read -r so; do
|
|
b="${so##*/}"
|
|
[ -z "${PROV[$b]:-}" ] && PROV[$b]="$hash"
|
|
done < <(find "$d" -name "*.so*" -printf '%f\n' 2>/dev/null)
|
|
done < <(find "$STORE" -maxdepth 1 -type d -name "*-*" -printf '%T@ %p\n' 2>/dev/null | awk -v c="$CUTOFF" '$1<c{print $2}')
|
|
echo " sonames en el store: ${#PROV[@]}"
|
|
|
|
round=0
|
|
while :; do
|
|
round=$((round+1))
|
|
# presentes en el rootfs
|
|
declare -A HAVE=()
|
|
while IFS= read -r f; do HAVE["${f##*/}"]=1; done < <(find "$RFS" -name "*.so*" 2>/dev/null)
|
|
# NEEDED de todos los ELF del rootfs
|
|
declare -A NEED=()
|
|
while IFS= read -r bin; do
|
|
while IFS= read -r n; do NEED["$n"]=1; done < <(readelf -d "$bin" 2>/dev/null | grep NEEDED | grep -oE '\[[^]]+\]' | tr -d '[]')
|
|
done < <(find "$RFS" -type f \( -name "*.so*" -o -path "*/bin/*" -o -path "*/libexec/*" \) 2>/dev/null)
|
|
# faltantes
|
|
missing=(); for n in "${!NEED[@]}"; do
|
|
[ -n "${HAVE[$n]:-}" ] && continue
|
|
is_base "$n" && continue
|
|
missing+=("$n")
|
|
done
|
|
if [ ${#missing[@]} -eq 0 ]; then echo "==> ronda $round: cierre COMPLETO, 0 sonames faltantes"; break; fi
|
|
echo "==> ronda $round: ${#missing[@]} sonames faltantes"
|
|
did=0; declare -A HYDRATED=()
|
|
for n in "${missing[@]}"; do
|
|
h="${PROV[$n]:-}"
|
|
if [ -z "$h" ]; then printf " ? %-32s (ningún artefacto lo provee)\n" "$n"; continue; fi
|
|
[ -n "${HYDRATED[$h]:-}" ] && continue
|
|
if "$HAMMER" --store "$STORE" hydrate "$h" --into "$RFS" --link "$LINK" >/dev/null 2>&1; then
|
|
printf " + %-32s ← %s\n" "$n" "${h:0:12}"; HYDRATED[$h]=1; did=$((did+1))
|
|
else
|
|
printf " ✗ %-32s hydrate falló (%s)\n" "$n" "${h:0:12}"
|
|
fi
|
|
done
|
|
unset HAVE NEED
|
|
[ $did -eq 0 ] && { echo "==> ronda $round: nada nuevo hidratado (faltantes irresolubles), corto"; break; }
|
|
done
|
|
echo "==> .so totales: $(find "$RFS" -name '*.so*'|wc -l); binarios: $(find "$RFS" -path '*/bin/*' -type f|wc -l)"
|