Files
takana/scripts/kde/hydrate-from-store.sh
T
Sergio 8730aad34e takana etapa 3b: las 49 invocaciones pasan a ./target/release/takana
Los llamadores EJECUTABLES: scripts/ (incluida toda la granja), los runbooks y
CLAUDE.md. Seguro porque la 3a ya garantiza que el worker emite los dos
binarios, y porque en farm-lab-sync.sh el cargo build remoto precede a la
invocación remota en el mismo script.

Verificado: sintaxis de los 49 (bash -n / py_compile — ojo que
why-differs-barrido.sh es Python con extensión .sh) y `takana hash` devuelve
hash real sobre el store.

NO se toca en esta etapa, a propósito:
- La variable de entorno HAMMER=. Es interfaz de los scripts entre sí y hay
  llamadores que la fijan; renombrarla va con la etapa 4.
- docs/evidencia/ y los HANDOFF: son REGISTRO de lo que se corrió ese día.
  Reescribir un comando dentro de una evidencia la falsifica.
- docs/state/: es generado, se regenera solo.
- Los ADR y los docs de diseño: texto, y `hammer` sigue funcionando. Van con
  la etapa 5, que es la de churn de texto.
2026-09-09 18:25:58 +00:00

65 lines
3.6 KiB
Bash

#!/usr/bin/env bash
# hydrate-from-store.sh — hidrata un FHS runtime KDE PROYECTANDO artefactos SELLADOS del store, SIN
# reproduce ni rebuild (`hammer hydrate <hash> --into`). Es la vía correcta para el escritorio completo:
# `install` reproduce-desde-fuente y el hashing determinista es frágil bajo el régimen dinámico (cada
# consumidor puede recomputar un hash distinto de qtbase → rebuild). Aquí se toma la salida ya sellada
# por la granja.
#
# Selección de hash por paquete: el artefacto store/<hash>-<name> MÁS RECIENTE con mtime ANTERIOR al
# CUTOFF (default: hoy) — i.e. la cosecha FINAL de la granja (set coherente, todo construido contra el
# mismo qtbase del cascade final), evitando los rebuilds ad-hoc de la sesión de hoy.
#
# Uso: TARGETS="plasma-workspace kwin ..." ./hydrate-from-store.sh
# Env: RFS (def work/kde-store-rootfs), REPO (def work/repo-kde), CUTOFF (epoch; def inicio de hoy),
# LINK (static|dynamic, def static), STORE (def ./store)
set -uo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT"
REPO="${REPO:-work/repo-kde}"; STORE="${STORE:-./store}"; LINK="${LINK:-static}"
RFS="${RFS:-work/kde-store-rootfs}"; HAMMER="${HAMMER:-./target/release/takana}"
TARGETS="${TARGETS:-${TARGET:-qt6-qtdeclarative}}"
# CUTOFF: por defecto medianoche de hoy (excluye rebuilds de la sesión). Pasá 9999999999 para no filtrar.
CUTOFF="${CUTOFF:-$(date -d 'today 00:00' +%s 2>/dev/null || echo 9999999999)}"
# cierre transitivo (nombres REALES qt6-*, no aliases: los artefactos del store se sellan por nombre real)
CLOSURE=$(python3 - "$REPO/index.json" $TARGETS <<'PY'
import json,sys
idx=json.load(open(sys.argv[1])); targets=sys.argv[2:]
by={p['name']:p for p in idx['packages']}
BUILD_ONLY={'cmake','samurai','meson','ninja','bison','flex','gperf','util-macros','xorgproto',
'xcb-proto','wayland-protocols','pkgconf','mako','markupsafe','packaging','python3','extra-cmake-modules',
'qttools','qt6-qttools','intltool','perl','perl-xml-parser','gettext-tiny','m4','autoconf','automake','libtool'}
def canon(n):
if n.startswith('qt') and not n.startswith('qt6-') and ('qt6-'+n) in by: return 'qt6-'+n
return n if n in by else ('qt6-'+n if 'qt6-'+n in by else n)
seen=set(); order=[]
def visit(n):
n=canon(n)
if n in seen or n not in by: return
seen.add(n)
for d in by[n].get('deps',[]): visit(d)
order.append(n)
for t in targets: visit(t)
for n in order:
if n not in BUILD_ONLY: print(n)
PY
)
rm -rf "$RFS"; mkdir -p "$RFS"
echo "==> hidratando desde el store SELLADO (cutoff<$(date -d @$CUTOFF 2>/dev/null||echo $CUTOFF)) → $RFS ($(echo "$CLOSURE"|wc -w) pkgs)"
ok=0; miss=0
for pkg in $CLOSURE; do
# artefacto <hash>-<pkg> más reciente con mtime < CUTOFF (nombre EXACTO, no substring)
hash=$(find "$STORE" -maxdepth 1 -type d -name "*-$pkg" -printf '%T@ %f\n' 2>/dev/null \
| awk -v c="$CUTOFF" '$1<c' | sort -rn | head -1 | awk '{print $2}' | sed "s/-$pkg\$//")
[ -z "$hash" ] && hash=$(find "$STORE" -maxdepth 1 -type d -name "*-$pkg" -printf '%T@ %f\n' 2>/dev/null \
| sort -rn | head -1 | awk '{print $2}' | sed "s/-$pkg\$//") # fallback: el más nuevo aunque sea de hoy
if [ -z "$hash" ]; then printf " ✗ %-24s (sin artefacto en el store)\n" "$pkg"; miss=$((miss+1)); continue; fi
if "$HAMMER" --store "$STORE" hydrate "$hash" --into "$RFS" --link "$LINK" >"$RFS/.hs-$pkg.log" 2>&1; then
printf " ✓ %-24s %s\n" "$pkg" "${hash:0:12}"; ok=$((ok+1))
else
printf " ✗ %-24s %s (ver .hs-%s.log)\n" "$pkg" "${hash:0:12}" "$pkg"; miss=$((miss+1))
fi
done
echo "==> $ok proyectados, $miss faltantes; .so totales: $(find "$RFS" -name '*.so*'|wc -l)"
rm -f "$RFS"/.hs-*.log 2>/dev/null || true