takana: las variables de entorno leen las dos formas, gana la nueva

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.
This commit is contained in:
Sergio
2026-09-09 19:14:49 +00:00
parent 8c2cb10414
commit 1c3e185167
50 changed files with 203 additions and 107 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
//! cliente, completamos el handshake y ejercitamos los caminos no-pesados (`query`, errores).
//!
//! `compile` real no se ejercita aquí — depende del lab + red, ya cubierto por el e2e de
//! grep gated en `HAMMER_NETWORK_TESTS`. Lo que sí verificamos es que un `compile` SIN la
//! grep gated en `TAKANA_NETWORK_TESTS`. Lo que sí verificamos es que un `compile` SIN la
//! capacidad devuelve `Error{code:"no_cap"}`, lo que prueba el dispatcher + el gate.
// El binario no expone una API pública; importamos sus módulos privados desde
+7 -7
View File
@@ -78,8 +78,8 @@ pub struct ClaudeConfig {
}
impl ClaudeConfig {
/// Construye desde env vars: `ANTHROPIC_API_KEY` (obligatoria), `HAMMER_LLM_MODEL`,
/// `HAMMER_LLM_BASE_URL`, `HAMMER_LLM_EFFORT`.
/// Construye desde env vars: `ANTHROPIC_API_KEY` (obligatoria), `TAKANA_LLM_MODEL`,
/// `TAKANA_LLM_BASE_URL`, `TAKANA_LLM_EFFORT`.
pub fn from_env() -> Result<Self, TranslateError> {
let api_key = std::env::var("ANTHROPIC_API_KEY").map_err(|_| {
TranslateError::Model(
@@ -89,12 +89,12 @@ impl ClaudeConfig {
})?;
Ok(Self {
api_key,
model: std::env::var("HAMMER_LLM_MODEL")
.unwrap_or_else(|_| "claude-opus-4-8".into()),
model: takana_core::env::var("TAKANA_LLM_MODEL")
.unwrap_or_else(|| "claude-opus-4-8".into()),
max_tokens: 8192,
base_url: std::env::var("HAMMER_LLM_BASE_URL")
.unwrap_or_else(|_| "https://api.anthropic.com".into()),
effort: std::env::var("HAMMER_LLM_EFFORT").unwrap_or_else(|_| "high".into()),
base_url: takana_core::env::var("TAKANA_LLM_BASE_URL")
.unwrap_or_else(|| "https://api.anthropic.com".into()),
effort: takana_core::env::var("TAKANA_LLM_EFFORT").unwrap_or_else(|| "high".into()),
})
}
}
+7 -1
View File
@@ -1324,7 +1324,13 @@ fi
# NOTA: el initramfs debe empaquetarse con `cpio --owner=root:root`. Si los ficheros del toolchain
# quedan con el uid del que armó el builder (p. ej. 1000), ese uid no está mapeado en el userns de
# bwrap (que mapea sólo 0→0) y el copy-up de overlay falla con EACCES al crear /opt/zig. Ver §8c.
export HAMMER_ROOTFS=/toolchain # el sandbox de build: el toolchain (variante a, desde Alpine)
# Se exportan LAS DOS formas a propósito (ADR 0016): el binario que corre acá adentro es
# `/usr/bin/hammer`, que puede ser el pinado del baseline y sólo conoce los nombres viejos.
# Un lector nuevo prefiere TAKANA_*; uno viejo usa HAMMER_*. Las dos se retiran en la etapa 6.
export TAKANA_ROOTFS=/toolchain # el sandbox de build: el toolchain (variante a, desde Alpine)
export TAKANA_WORK=/work
export TAKANA_CACHE=
export HAMMER_ROOTFS=/toolchain
export HAMMER_WORK=/work
export HAMMER_CACHE=
echo ">> rebuild stage1 (toolchain in-rootfs, semilla $SEED_HASH)"
+9 -9
View File
@@ -32,7 +32,7 @@ fn find_lab_upward(start: &Path) -> Option<PathBuf> {
/// Resuelve dónde vive el lab SIN atarlo a dónde vive el store.
///
/// Orden, de más explícito a más adivinado:
/// 1. `HAMMER_LAB` — el operador manda.
/// 1. `TAKANA_LAB` — el operador manda.
/// 2. Hermano del store (`<store>/../.dev-fs`) **si existe**. Preserva exactamente el
/// comportamiento histórico en la topología normal (lab y store en la raíz del proyecto).
/// 3. Hacia arriba desde el CWD. Ésta es la que desacopla: cubre el caso en que el store fue
@@ -40,7 +40,7 @@ fn find_lab_upward(start: &Path) -> Option<PathBuf> {
/// 4. `None` ⇒ el llamador cae al default histórico, para que los mensajes de error sigan
/// apuntando a un lugar previsible en vez de a la nada.
fn resolve_lab_dir(store_root: &Path) -> Option<PathBuf> {
if let Some(v) = std::env::var_os("HAMMER_LAB") {
if let Some(v) = takana_core::env::var_os("TAKANA_LAB") {
return Some(PathBuf::from(v));
}
if let Some(parent) = store_root.parent() {
@@ -92,27 +92,27 @@ impl BuildConfig {
}
}
/// Lee overrides desde entorno (`HAMMER_LAB`, `HAMMER_ROOTFS`, `HAMMER_ZIG`, `HAMMER_WORK`,
/// `HAMMER_CACHE`). `HAMMER_CACHE=""` (vacío) desactiva la caché.
/// Lee overrides desde entorno (`TAKANA_LAB`, `TAKANA_ROOTFS`, `TAKANA_ZIG`, `TAKANA_WORK`,
/// `TAKANA_CACHE`). `TAKANA_CACHE=""` (vacío) desactiva la caché.
///
/// Es el constructor que HUELE EL ENTORNO (env + CWD); `defaults_for_store` se mantiene pura.
/// `HAMMER_LAB` mueve el lab entero de una; los `HAMMER_ROOTFS`/`HAMMER_ZIG`/`HAMMER_CACHE`
/// `TAKANA_LAB` mueve el lab entero de una; los `TAKANA_ROOTFS`/`TAKANA_ZIG`/`TAKANA_CACHE`
/// siguen pisando pieza por pieza y ganan sobre él.
pub fn from_env_or_defaults(store_root: &Path) -> Self {
let mut cfg = match resolve_lab_dir(store_root) {
Some(lab) => Self::defaults_for_store_with_lab(store_root, &lab),
None => Self::defaults_for_store(store_root),
};
if let Ok(v) = std::env::var("HAMMER_ROOTFS") {
if let Some(v) = takana_core::env::var("TAKANA_ROOTFS") {
cfg.rootfs = PathBuf::from(v);
}
if let Ok(v) = std::env::var("HAMMER_ZIG") {
if let Some(v) = takana_core::env::var("TAKANA_ZIG") {
cfg.zig_dir = PathBuf::from(v);
}
if let Ok(v) = std::env::var("HAMMER_WORK") {
if let Some(v) = takana_core::env::var("TAKANA_WORK") {
cfg.work_root = PathBuf::from(v);
}
if let Ok(v) = std::env::var("HAMMER_CACHE") {
if let Some(v) = takana_core::env::var("TAKANA_CACHE") {
cfg.cache_root = if v.is_empty() { None } else { Some(PathBuf::from(v)) };
}
cfg
+10 -10
View File
@@ -387,7 +387,7 @@ fn salida_git(args: &[&str], cwd: &Path) -> takana_core::Result<String> {
///
/// # Por qué una lista y no una URL (ADR 0014)
///
/// El ADR 0013 dejó `HAMMER_MIRROR` con un solo valor y con eso el mecanismo que existe para no
/// El ADR 0013 dejó `TAKANA_MIRROR` con un solo valor y con eso el mecanismo que existe para no
/// depender de 79 servidores ajenos pasaba a depender de **uno nuestro**: el mismo fallo, con
/// nuestro nombre encima. La identidad del objeto es su `sha256`/`commit`, así que un origen de más
/// no añade confianza que verificar — sólo un sitio más donde mirar. Añadirlos es gratis y no
@@ -402,9 +402,9 @@ fn salida_git(args: &[&str], cwd: &Path) -> takana_core::Result<String> {
/// se reproduce y se depura — pero objetos distintos se reparten entre todos, así que una tanda del
/// corpus **ejercita la lista entera**. Tras el elegido se recorren los demás como respaldo.
fn bases_de_mirror(var: &str, clave: &str) -> Vec<String> {
match std::env::var(var) {
Ok(raw) => rotar_bases(&raw, clave),
Err(_) => Vec::new(),
match takana_core::env::var(var) {
Some(raw) => rotar_bases(&raw, clave),
None => Vec::new(),
}
}
@@ -466,10 +466,10 @@ fn rotar_bases(raw: &str, clave: &str) -> Vec<String> {
/// La verificación sigue siendo criptográfica: git comprueba cada objeto contra su SHA al
/// desempaquetar, y el commit de la receta es la identidad. Un bundle alterado no pasa.
fn hidratar_desde_bundle(commit: &str, destino: &Path) -> bool {
// `HAMMER_MIRROR_GIT` es una LISTA (ADR 0014): se prueban todos los orígenes antes de rendirse
// `TAKANA_MIRROR_GIT` es una LISTA (ADR 0014): se prueban todos los orígenes antes de rendirse
// y caer a upstream. Un bundle que no está en uno puede estar en otro, y la verificación la
// hace git contra el SHA venga de donde venga.
bases_de_mirror("HAMMER_MIRROR_GIT", commit)
bases_de_mirror("TAKANA_MIRROR_GIT", commit)
.iter()
.any(|base| hidratar_desde_bundle_en(base, commit, destino))
}
@@ -623,13 +623,13 @@ fn fetch_tarball(
/// Un mirror silencioso **con** vigía separado detecta el bit-rot; uno silencioso **sin** vigía lo
/// entierra, que es como el grafo de wlr pasó 17 días anunciando un 121/121 que ya era falso.
///
/// `HAMMER_MIRROR` es una **lista** de prefijos de URL separada por comas, de cualquier esquema que
/// `TAKANA_MIRROR` es una **lista** de prefijos de URL separada por comas, de cualquier esquema que
/// curl entienda (`file://`, `https://`, `sftp://`…); el objeto se busca por contenido en
/// `{base}/{sha256}.tar` en cada uno, en el orden que dicta [`bases_de_mirror`].
/// `HAMMER_MIRROR_KEY`, si está, se pasa como `--key` (Storage Box por sftp). Sin `HAMMER_MIRROR`
/// `TAKANA_MIRROR_KEY`, si está, se pasa como `--key` (Storage Box por sftp). Sin `TAKANA_MIRROR`
/// el comportamiento es el de siempre: derecho a upstream.
fn fetch_con_mirror(url: &str, sha256: &str, dst: &Path) -> takana_core::Result<()> {
for base in bases_de_mirror("HAMMER_MIRROR", sha256) {
for base in bases_de_mirror("TAKANA_MIRROR", sha256) {
let espejo = format!("{base}/{sha256}.tar");
// Un fallo acá NO es un error: es el caso normal la primera vez que se ve una fuente, y
// también el caso normal cuando un origen de la lista todavía no tiene ese objeto. Se
@@ -649,7 +649,7 @@ fn descargar(url: &str, dst: &Path) -> takana_core::Result<()> {
let mut cmd = Command::new("curl");
cmd.args(["-fL", "--retry", "3", "--connect-timeout", "30"]);
// Clave para el mirror por sftp (Storage Box). Inocua para http/file.
if let Ok(key) = std::env::var("HAMMER_MIRROR_KEY") {
if let Some(key) = takana_core::env::var("TAKANA_MIRROR_KEY") {
if !key.is_empty() {
cmd.arg("--key").arg(&key);
}
+2 -2
View File
@@ -453,10 +453,10 @@ mod tests {
}
/// Camino feliz real: requiere patchelf + un ELF de verdad. Gated como el resto de tests
/// dependientes del host (`HAMMER_HOST_ELF_TESTS=1`).
/// dependientes del host (`TAKANA_HOST_ELF_TESTS=1`).
#[test]
fn hydrate_dynamic_patchea_elf_real() {
if std::env::var("HAMMER_HOST_ELF_TESTS").is_err() {
if takana_core::env::var("TAKANA_HOST_ELF_TESTS").is_none() {
return;
}
let host_bin = std::path::Path::new("/bin/sh");
+1 -1
View File
@@ -197,7 +197,7 @@ pub fn build(
// `docs/state/lab-toolchain.lock` ni de una ruta derivada del store. Derivarla del padre del
// store ya mordió una vez (ver `BuildConfig::defaults_for_store_with_lab`): al anclar el store
// de un worker a un volumen, el lab se buscaba donde no estaba. `cfg.rootfs` respeta
// `HAMMER_LAB`/`HAMMER_ROOTFS` y es la única fuente que no puede desincronizarse del build.
// `TAKANA_LAB`/`TAKANA_ROOTFS` y es la única fuente que no puede desincronizarse del build.
let lab = takana_core::lab::LabFingerprint::from_rootfs(&cfg.rootfs)?;
let h = artifact_hash(recipe, store, &lab)?;
if store.has(&h, &recipe.name) {
+3 -3
View File
@@ -3,7 +3,7 @@
//!
//! Doblemente gateado para no penalizar `cargo test` por defecto:
//! - Requiere `.dev-fs/` bootstrapeado (rootfs Alpine + zig + cache).
//! - Requiere `HAMMER_NETWORK_TESTS=1` (descarga ~3 MB del tarball de GNU).
//! - Requiere `TAKANA_NETWORK_TESTS=1` (descarga ~3 MB del tarball de GNU).
//!
//! Comparte la dev cache (`.dev-fs/cache`) para que la segunda corrida en una máquina dada
//! reuse los objetos de musl y termine en segundos.
@@ -44,9 +44,9 @@ fn skip_with_reason(reason: &str) -> bool {
}
fn should_skip(cfg: &BuildConfig) -> bool {
if std::env::var("HAMMER_NETWORK_TESTS").ok().as_deref() != Some("1") {
if takana_core::env::var("TAKANA_NETWORK_TESTS").as_deref() != Some("1") {
return skip_with_reason(
"HAMMER_NETWORK_TESTS != 1 (este test descarga ~3 MB de ftp.gnu.org y compila ~30s).",
"TAKANA_NETWORK_TESTS != 1 (este test descarga ~3 MB de ftp.gnu.org y compila ~30s).",
);
}
if !cfg.rootfs.join("bin/busybox").is_file() {
+6 -6
View File
@@ -13,11 +13,11 @@ use takana_core::kernel::KernelConfig;
use serde::Serialize;
/// Dónde busca el árbol de Kconfig si no se pasa `--kconfig`.
const KCONFIG_ENV: &str = "HAMMER_KCONFIG_ROOT";
const KCONFIG_ENV: &str = "TAKANA_KCONFIG_ROOT";
/// Ídem para el catálogo de bundles.
const CATALOG_ENV: &str = "HAMMER_KERNEL_BUNDLES";
const CATALOG_ENV: &str = "TAKANA_KERNEL_BUNDLES";
/// Ídem para el contrato de capacidades (SDD 25 §4).
const CONTRACT_ENV: &str = "HAMMER_KERNEL_CONTRACT";
const CONTRACT_ENV: &str = "TAKANA_KERNEL_CONTRACT";
/// Sitios donde buscarlo sin que nadie diga nada: el del repo y el del sistema instalado.
const CATALOG_DEFAULTS: &[&str] = &[
"docs/state/kernel-bundles.toml",
@@ -316,7 +316,7 @@ fn kconfig_root(flag: Option<PathBuf>) -> Result<PathBuf> {
if let Some(p) = flag {
return Ok(p);
}
match std::env::var_os(KCONFIG_ENV) {
match takana_core::env::var_os(KCONFIG_ENV) {
Some(v) => Ok(PathBuf::from(v)),
None => anyhow::bail!(
"falta el árbol de fuentes del kernel: pasá --kconfig <dir> o exportá {KCONFIG_ENV}"
@@ -329,7 +329,7 @@ fn catalog_path(flag: Option<PathBuf>) -> Result<PathBuf> {
if let Some(p) = flag {
return Ok(p);
}
if let Some(v) = std::env::var_os(CATALOG_ENV) {
if let Some(v) = takana_core::env::var_os(CATALOG_ENV) {
return Ok(PathBuf::from(v));
}
for c in CATALOG_DEFAULTS {
@@ -348,7 +348,7 @@ fn contract_path(flag: Option<PathBuf>) -> Result<PathBuf> {
if let Some(p) = flag {
return Ok(p);
}
if let Some(v) = std::env::var_os(CONTRACT_ENV) {
if let Some(v) = takana_core::env::var_os(CONTRACT_ENV) {
return Ok(PathBuf::from(v));
}
for c in CONTRACT_DEFAULTS {
+1 -1
View File
@@ -358,7 +358,7 @@ enum Cmd {
catalog: Option<PathBuf>,
/// Activa el traductor LLM real (Claude API). Requiere `ANTHROPIC_API_KEY` en el env
/// y un binario compilado con `--features llm-claude`. Modelo por defecto:
/// `claude-opus-4-8` (sobreescribible con `HAMMER_LLM_MODEL`).
/// `claude-opus-4-8` (sobreescribible con `TAKANA_LLM_MODEL`).
#[arg(long)]
llm: bool,
/// Re-rootea las mutaciones bajo este prefix en vez de abrir overlay. Útil para
+4 -4
View File
@@ -25,8 +25,8 @@ use serde::{Deserialize, Serialize};
/// Raíz del espacio de nombres de qorpa. Deliberadamente **fuera** del store.
pub const DEFAULT_ROOT: &str = "/var/lib/hammer/qorpa";
/// Para correr sin root (tests, laptop). Mismo patrón que `HAMMER_KCONFIG_ROOT`.
pub const ROOT_ENV: &str = "HAMMER_QORPA_ROOT";
/// Para correr sin root (tests, laptop). Mismo patrón que `TAKANA_KCONFIG_ROOT`.
pub const ROOT_ENV: &str = "TAKANA_QORPA_ROOT";
/// El manifiesto de la imagen. No confundir con `instancia.toml`, que describe una INSTANCIA.
const IMAGE_MANIFEST: &str = "image.toml";
/// El árbol desempacado dentro del directorio de la imagen.
@@ -56,7 +56,7 @@ pub enum QorpaCmd {
/// Dónde está el rootfs DENTRO del archivo, si la detección automática no acierta.
#[arg(long)]
subdir: Option<String>,
/// Raíz de qorpa (default: `$HAMMER_QORPA_ROOT` o `/var/lib/hammer/qorpa`).
/// Raíz de qorpa (default: `$TAKANA_QORPA_ROOT` o `/var/lib/hammer/qorpa`).
#[arg(long)]
root: Option<PathBuf>,
},
@@ -226,7 +226,7 @@ pub fn run(cmd: QorpaCmd, store: &Path) -> Result<()> {
}
fn resolve_root(flag: Option<PathBuf>) -> PathBuf {
flag.or_else(|| std::env::var_os(ROOT_ENV).map(PathBuf::from))
flag.or_else(|| takana_core::env::var_os(ROOT_ENV).map(PathBuf::from))
.unwrap_or_else(|| PathBuf::from(DEFAULT_ROOT))
}
+1 -1
View File
@@ -3,7 +3,7 @@
//! coinciden con lo esperado.
//!
//! NO ejercitamos `source_patch` porque arrastra todo el lab (red + sandbox); para esos
//! casos existen los tests gated en `HAMMER_NETWORK_TESTS`. Aquí cubrimos los caminos puros
//! casos existen los tests gated en `TAKANA_NETWORK_TESTS`. Aquí cubrimos los caminos puros
//! de hammer-core: `verify_schema`, `verify_base`, `apply_config_edit`, `apply_file_drop`.
use std::collections::BTreeMap;
+72
View File
@@ -0,0 +1,72 @@
//! Lectura de variables de entorno del proyecto durante el renombre `hammer` → `takana`.
//!
//! # Por qué existe esto en vez de un `sed`
//!
//! Las variables de entorno del proyecto **no son superficie interna**: son contrato de usuario,
//! del mismo tipo que un verbo de CLI. Hay knobs del instalador entre ellas (`HAMMER_TZ`,
//! `HAMMER_KEYMAP`, `HAMMER_HOSTNAME`), el entorno del worker las trae puestas desde perfiles de
//! shell y units de systemd que **viven fuera del repo**, y `mirror-env.sh` exporta las del espejo.
//! Un renombre duro no falla ruidosamente: la variable simplemente no aparece, se toma el valor por
//! defecto y el build se comporta distinto sin que nada lo diga.
//!
//! Por eso valen las dos formas: **`TAKANA_X` gana; si no está, se cae a `HAMMER_X`** (ADR 0016).
//! La caída se retira en la etapa 6 del renombre, cuando no queden entornos con la forma vieja.
/// Lee una variable aceptando el nombre nuevo y, si falta, el viejo.
///
/// Se le pasa el nombre **canónico** (`TAKANA_…`) para que un `grep` del nombre nuevo encuentre
/// todas las lecturas; el nombre viejo se deriva cambiando el prefijo.
pub fn var(nombre: &str) -> Option<String> {
con_caida(nombre, |n| std::env::var(n).ok())
}
/// Igual que [`var`], para valores que no tienen por qué ser UTF-8 (rutas).
pub fn var_os(nombre: &str) -> Option<std::ffi::OsString> {
con_caida(nombre, |n: &str| std::env::var_os(n))
}
fn con_caida<T>(nombre: &str, leer: impl Fn(&str) -> Option<T>) -> Option<T> {
if let Some(v) = leer(nombre) {
return Some(v);
}
let viejo = format!("HAMMER_{}", nombre.strip_prefix("TAKANA_")?);
leer(&viejo)
}
#[cfg(test)]
mod tests {
// Cada test usa un nombre propio: el entorno del proceso es estado COMPARTIDO entre tests que
// corren en hilos, y reusar el mismo nombre los hace pisarse de forma intermitente.
#[test]
fn prefiere_el_nombre_nuevo_sobre_el_viejo() {
std::env::set_var("TAKANA_PRUEBA_A", "nuevo");
std::env::set_var("HAMMER_PRUEBA_A", "viejo");
assert_eq!(super::var("TAKANA_PRUEBA_A").as_deref(), Some("nuevo"));
}
#[test]
fn cae_al_viejo_cuando_el_nuevo_no_esta() {
std::env::set_var("HAMMER_PRUEBA_B", "viejo");
assert_eq!(super::var("TAKANA_PRUEBA_B").as_deref(), Some("viejo"));
}
#[test]
fn sin_ninguna_de_las_dos_no_hay_valor() {
assert_eq!(super::var("TAKANA_PRUEBA_C_QUE_NO_EXISTE"), None);
}
#[test]
fn un_nombre_sin_prefijo_no_inventa_una_caida() {
std::env::set_var("HAMMER_PRUEBA_D", "viejo");
assert_eq!(super::var("PRUEBA_D"), None);
}
#[test]
fn var_os_tambien_cae() {
std::env::set_var("HAMMER_PRUEBA_E", "viejo");
assert_eq!(
super::var_os("TAKANA_PRUEBA_E").as_deref(),
Some(std::ffi::OsStr::new("viejo"))
);
}
}
+1 -1
View File
@@ -118,7 +118,7 @@ impl LabFingerprint {
crate::Error::Other(anyhow::anyhow!(
"no pude leer el apk db del lab en {}: {e}. \
El toolchain entra en el ArtifactHash, así que sin rootfs no se puede calcular \
un hash comparable (corré scripts/bootstrap-devfs.sh, o apuntá HAMMER_ROOTFS)",
un hash comparable (corré scripts/bootstrap-devfs.sh, o apuntá TAKANA_ROOTFS)",
db.display()
))
})?;
+1
View File
@@ -8,6 +8,7 @@ pub mod apply;
pub mod caps;
pub mod compat;
pub mod differs;
pub mod env;
pub mod hash;
pub mod installed;
pub mod kernel;
+4 -4
View File
@@ -693,10 +693,10 @@ mod tests {
}
/// Sanity con un binario real del host: `/bin/sh` casi seguro existe y es ELF.
/// Gated por `HAMMER_HOST_ELF_TESTS=1` para no acoplar el suite a Linux/Alpine.
/// Gated por `TAKANA_HOST_ELF_TESTS=1` para no acoplar el suite a Linux/Alpine.
#[test]
fn parse_elf_real_host_binary() {
if std::env::var("HAMMER_HOST_ELF_TESTS").is_err() {
if crate::env::var("TAKANA_HOST_ELF_TESTS").is_none() {
return;
}
let candidates = ["/bin/sh", "/usr/bin/sh", "/bin/ls", "/usr/bin/ls"];
@@ -715,10 +715,10 @@ mod tests {
}
/// Exports sobre una librería compartida real del host (una `.so` con `.dynsym`). Gated
/// igual que arriba: pide `HAMMER_HOST_ELF_TESTS=1`. Verifica que extraemos ≥1 símbolo.
/// igual que arriba: pide `TAKANA_HOST_ELF_TESTS=1`. Verifica que extraemos ≥1 símbolo.
#[test]
fn parse_exports_real_host_lib() {
if std::env::var("HAMMER_HOST_ELF_TESTS").is_err() {
if crate::env::var("TAKANA_HOST_ELF_TESTS").is_none() {
return;
}
let candidates = [
+7 -7
View File
@@ -7,7 +7,7 @@
//! en distros con AppArmor; algunos kernels también requieren la opción `userxattr` en el
//! mount). Por eso este test está doblemente gateado:
//! - Requiere `bwrap` y overlayfs en el kernel.
//! - Requiere `HAMMER_OVERLAY_TESTS=1` — el dev confirma que su entorno admite el
//! - Requiere `TAKANA_OVERLAY_TESTS=1` — el dev confirma que su entorno admite el
//! mount unprivilegiado, o corre el test bajo `sudo`.
//!
//! Sin esos requisitos el test salta limpio; los aspectos puros (layout, slug, parsing del
@@ -36,13 +36,13 @@ fn overlayfs_supported() -> bool {
/// reenviando los args originales. Si ya estamos dentro del sandbox (env marker set),
/// no re-anidamos.
fn run_inside_userns_or_skip(phase: &str, scratch: &Path) -> bool {
if std::env::var("HAMMER_OVERLAY_IN_SANDBOX").is_ok() {
if takana_core::env::var("TAKANA_OVERLAY_IN_SANDBOX").is_some() {
// Ya estamos dentro — el caller ejecuta la lógica real.
return false;
}
if std::env::var("HAMMER_OVERLAY_TESTS").ok().as_deref() != Some("1") {
if takana_core::env::var("TAKANA_OVERLAY_TESTS").as_deref() != Some("1") {
eprintln!(
"SKIP: HAMMER_OVERLAY_TESTS != 1 (overlayfs en user-ns suele estar denegado por \
"SKIP: TAKANA_OVERLAY_TESTS != 1 (overlayfs en user-ns suele estar denegado por \
el kernel; setea la var cuando tu host lo permita o corre con sudo)."
);
return true;
@@ -72,7 +72,7 @@ fn run_inside_userns_or_skip(phase: &str, scratch: &Path) -> bool {
.arg(scratch)
.arg(scratch)
.arg("--setenv")
.arg("HAMMER_OVERLAY_IN_SANDBOX")
.arg("TAKANA_OVERLAY_IN_SANDBOX")
.arg("1")
.arg("--setenv")
.arg("OVERLAY_TEST_SCRATCH")
@@ -154,7 +154,7 @@ fn body_try_commit_discard() {
#[test]
fn overlay_try_commit_discard_inside_userns() {
if std::env::var("HAMMER_OVERLAY_IN_SANDBOX").is_ok() {
if takana_core::env::var("TAKANA_OVERLAY_IN_SANDBOX").is_some() {
body_try_commit_discard();
return;
}
@@ -220,7 +220,7 @@ fn body_nested_stack() {
#[test]
fn overlay_nested_stack_inside_userns() {
if std::env::var("HAMMER_OVERLAY_IN_SANDBOX").is_ok() {
if takana_core::env::var("TAKANA_OVERLAY_IN_SANDBOX").is_some() {
body_nested_stack();
return;
}
+17 -7
View File
@@ -14,8 +14,8 @@
//! generaciones tipo NixOS que seleccionar, sino una reparación determinista del estado a medias.
//!
//! Paths del producto (overridables por entorno para tests):
//! `HAMMER_RECOVER_ROOT=/` `HAMMER_RECOVER_STORE=/store`
//! `HAMMER_RECOVER_STATE=/var/lib/hammer/upgrades` `HAMMER_RECOVER_JOURNAL=/var/lib/hammer/journal`
//! `TAKANA_RECOVER_ROOT=/` `TAKANA_RECOVER_STORE=/store`
//! `TAKANA_RECOVER_STATE=/var/lib/hammer/upgrades` `TAKANA_RECOVER_JOURNAL=/var/lib/hammer/journal`
//! Flag: `--rollback` fuerza deshacer en vez de completar.
//!
//! NUNCA sale con código ≠0 por un fallo de recuperación: es un hook de arranque, no debe abortar el
@@ -23,16 +23,26 @@
use std::path::PathBuf;
/// Lee la variable aceptando el nombre nuevo y, si falta, el viejo (ADR 0016).
///
/// La caída va inline y no por `takana_core::env`: este es un mini-binario que se copia a
/// `/usr/sbin` de los sistemas instalados, y no vale la pena arrastrarle una dep entera por
/// dos líneas. Se retira junto con el resto de las caídas en la etapa 6.
fn env_path(key: &str, default: &str) -> PathBuf {
std::env::var(key).map(PathBuf::from).unwrap_or_else(|_| PathBuf::from(default))
let viejo = key.strip_prefix("TAKANA_").map(|s| format!("HAMMER_{s}"));
std::env::var(key)
.ok()
.or_else(|| viejo.and_then(|v| std::env::var(v).ok()))
.map(PathBuf::from)
.unwrap_or_else(|| PathBuf::from(default))
}
fn main() {
let force_rollback = std::env::args().skip(1).any(|a| a == "--rollback");
let root = env_path("HAMMER_RECOVER_ROOT", "/");
let store = env_path("HAMMER_RECOVER_STORE", "/store");
let state = env_path("HAMMER_RECOVER_STATE", "/var/lib/hammer/upgrades");
let journal_dir = env_path("HAMMER_RECOVER_JOURNAL", "/var/lib/hammer/journal");
let root = env_path("TAKANA_RECOVER_ROOT", "/");
let store = env_path("TAKANA_RECOVER_STORE", "/store");
let state = env_path("TAKANA_RECOVER_STATE", "/var/lib/hammer/upgrades");
let journal_dir = env_path("TAKANA_RECOVER_JOURNAL", "/var/lib/hammer/journal");
match takana_upgrade::pending(&state) {
Ok(None) => {
+1 -1
View File
@@ -12,7 +12,7 @@ PKG="${1:?uso: alpine-import.sh <pkg> [main|community]}"
REPO="${2:-main}"
BRANCH="${ALPINE_BRANCH:-master}"
OUTDIR="${OUTDIR:-.}"
HAMMER="${HAMMER:-cargo run -q -p takana-cli --}"
HAMMER="${TAKANA:-${HAMMER:-cargo run -q -p takana-cli --}}"
BASE="https://gitlab.alpinelinux.org/alpine/aports/-/raw/${BRANCH}/${REPO}/${PKG}"
apk=$(curl -fsSL "${BASE}/APKBUILD") || { echo "no encontré ${REPO}/${PKG} en aports@${BRANCH}" >&2; exit 1; }
+1 -1
View File
@@ -23,7 +23,7 @@ STORE="${STORE:-./store}"
REPO="${REPO:-$ROOT/dist/repo}"
KEY="${KEY:-$ROOT/dist/keys/release.ed25519}"
DISTRO="${DISTRO:-dev}"
HAMMER="${HAMMER:-$ROOT/target/release/takana}"
HAMMER="${TAKANA:-${HAMMER:-$ROOT/target/release/takana}}"
PROMOTE="${PROMOTE:-1}"
JOBS="${JOBS:-$(( $(nproc) - 2 ))}"; [ "$JOBS" -ge 1 ] || JOBS=1
+1 -1
View File
@@ -21,7 +21,7 @@
set -uo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT"
RFS="${RFS:-work/cosmic-rootfs}"; STORE="${STORE:-./store}"; LINK="${LINK:-static}"
HAMMER="${HAMMER:-./target/release/takana}"; KEEP="${KEEP:-0}"
HAMMER="${TAKANA:-${HAMMER:-./target/release/takana}}"; KEEP="${KEEP:-0}"
if [ $# -gt 0 ]; then
TARGETS=("$@")
+1 -1
View File
@@ -19,7 +19,7 @@
#
# Sale con el MISMO código que `hammer build` (transparente para el llamador).
set -u
HAMMER="${HAMMER:-./target/release/takana}"
HAMMER="${TAKANA:-${HAMMER:-./target/release/takana}}"
STORE="${STORE:-./store}"
UMBRAL="${UMBRAL_TIEMPO:-3}"
f="${1:?uso: build-timed.sh <receta.toml>}"
+2 -2
View File
@@ -25,12 +25,12 @@
# /opt/hammer/scripts/farm/campana-deuda.sh <recetas…>'
# ssh root@<ip> 'journalctl -u campana-deuda -f'
set -u
HAMMER_DIR="${HAMMER_DIR:-/opt/hammer}"
HAMMER_DIR="${TAKANA_DIR:-${HAMMER_DIR:-/opt/hammer}}"
# Ruta absoluta a MÍ MISMO antes del `cd`: acá el `cd` va a HAMMER_DIR, que ni siquiera tiene por
# qué contener a este script, así que un `$0` relativo se pierde seguro.
YO="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
cd "$HAMMER_DIR"
HAMMER="${HAMMER:-$HAMMER_DIR/target/release/takana}"
HAMMER="${TAKANA:-${HAMMER:-$HAMMER_DIR/target/release/takana}}"
STORE="${STORE:-$HAMMER_DIR/store}"
LOG="${LOG:-/var/log/campana-deuda.log}"
+1 -1
View File
@@ -78,7 +78,7 @@ if [ -s "$FLEET_FIJA" ]; then
{ grep -vE '^[[:space:]]*(#|$)' "$FLEET_FIJA" || true; cat "$FLEET" 2>/dev/null || true; } \
| awk 'NF && !visto[$1]++' > "$FLEET.seed" && mv "$FLEET.seed" "$FLEET"
fi
HAMMER="${HAMMER:-$ROOT/target/release/takana}"
HAMMER="${TAKANA:-${HAMMER:-$ROOT/target/release/takana}}"
# Workers efímeros reciclan IPs ⇒ no fijar known_hosts (hub-and-spoke, worker sin secretos).
SSH="ssh -i $SSH_KEY -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o BatchMode=yes -o LogLevel=ERROR -o ConnectTimeout=15"
+1 -1
View File
@@ -9,7 +9,7 @@
#
# Lo lanza systemd (hammer-farm.service). Manual: JOBS=2 ./scripts/farm/farm-worker-loop.sh
set -uo pipefail
HAMMER_DIR="${HAMMER_DIR:-/opt/hammer}"
HAMMER_DIR="${TAKANA_DIR:-${HAMMER_DIR:-/opt/hammer}}"
cd "$HAMMER_DIR"
. "$HOME/.cargo/env" 2>/dev/null || true
# JOBS=1 MIENTRAS EL ADR 0012 ESTÉ SIN DECIDIR (2026-07-22). `build-farm.sh` usa `xargs -P$JOBS`, y
+1 -1
View File
@@ -10,7 +10,7 @@
set -u
MI_NOMBRE="${1:?uso: harkaq-campana-vol.sh <mi-nombre>}"
HAMMER_DIR="${HAMMER_DIR:-/opt/hammer}"
HAMMER_DIR="${TAKANA_DIR:-${HAMMER_DIR:-/opt/hammer}}"
cd "$HAMMER_DIR"
LISTA="${LISTA:-work/harkaq-cola.txt}"
VOL_OUT="/mnt/cosecha"
+1 -1
View File
@@ -18,7 +18,7 @@
# script existe para no tener.
set -u
HAMMER_DIR="${HAMMER_DIR:-/opt/hammer}"
HAMMER_DIR="${TAKANA_DIR:-${HAMMER_DIR:-/opt/hammer}}"
cd "$HAMMER_DIR"
LISTA="${1:-work/harkaq-cola.txt}"
OUT="work/harkaq-campana"
+1 -1
View File
@@ -29,7 +29,7 @@ STORE="${STORE:-$ROOT/store}"
REPO="${REPO:-$ROOT/dist/repo}"
KEY="${KEY:-$ROOT/dist/keys/release.ed25519}"
DISTRO="${DISTRO:-dev}"
HAMMER="${HAMMER:-$ROOT/target/release/takana}"
HAMMER="${TAKANA:-${HAMMER:-$ROOT/target/release/takana}}"
SEAL_TIMEOUT="${SEAL_TIMEOUT:-60}"
QUEUE="recipes/incoming-go"
REVIEW="tandas/needs-review-weekend"
+1 -1
View File
@@ -13,7 +13,7 @@
# Salidas: work/migra-zig/{migrable,matraca}.txt
set -u
cd "$(dirname "$0")/../.."
HAMMER="${HAMMER:-./target/debug/hammer}"
HAMMER="${TAKANA:-${HAMMER:-./target/debug/hammer}}"
OUT="work/migra-zig"; mkdir -p "$OUT"
# ACUMULA entre corridas (no trunca): probar las 47 no cabe en un timeout, así que se corre por
# lotes y cada lote SUMA. `reg` evita duplicar una receta ya clasificada en una corrida previa.
+1 -1
View File
@@ -27,7 +27,7 @@
set -u
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT"
HAMMER="${HAMMER:-$ROOT/target/release/takana}"
HAMMER="${TAKANA:-${HAMMER:-$ROOT/target/release/takana}}"
STORE="${STORE:-$ROOT/store}"
DRY="${DRY:-0}"
# El stack GUI no construye en el laptop (zig-skew rompe cairo). Default: saltarlo salvo que se pida.
+1 -1
View File
@@ -21,7 +21,7 @@
# /opt/hammer/scripts/farm/tandas.sh "gui:pixman,cairo" …'
# ssh root@<ip> 'tail -f /var/log/tandas.log'
set -u
HAMMER_DIR="${HAMMER_DIR:-/opt/hammer}"
HAMMER_DIR="${TAKANA_DIR:-${HAMMER_DIR:-/opt/hammer}}"
cd "$HAMMER_DIR"
LOG="${LOG:-/var/log/tandas.log}"
ESPERA="${ESPERA:-30}"
+1 -1
View File
@@ -41,7 +41,7 @@
# evita el zig-skew: el worker usa EXACTAMENTE las versiones del hub.
set -euo pipefail
HAMMER_DIR="${HAMMER_DIR:-/opt/hammer}"
HAMMER_DIR="${TAKANA_DIR:-${HAMMER_DIR:-/opt/hammer}}"
cd "$HAMMER_DIR"
# ── detección de familia ────────────────────────────────────────────────────────────────────
+9 -3
View File
@@ -20,8 +20,14 @@
# La ruta lleva `/~/` a propósito. curl interpreta lo que sigue al host en una URL `sftp://` como
# ruta ABSOLUTA del servidor, así que `…:23/hammer/fuentes` busca en la raíz y devuelve
# «(78) Could not open remote file for reading» aunque el fichero exista. `/~/` lo ancla al home.
export HAMMER_MIRROR="${HAMMER_MIRROR:-sftp://u647150@u647150.your-storagebox.de:23/~/hammer/fuentes}"
# ADR 0016: se exportan las DOS formas. Se acepta la vieja como entrada (hay entornos que la
# traen puesta desde perfiles y units fuera del repo) y se deja también puesta, porque un
# binario viejo —worker sin recompilar, imagen pinada— sólo conoce ésa.
export TAKANA_MIRROR="${TAKANA_MIRROR:-${HAMMER_MIRROR:-sftp://u647150@u647150.your-storagebox.de:23/~/hammer/fuentes}}"
export HAMMER_MIRROR="$TAKANA_MIRROR"
# Fuentes git: bundles shallow por commit. Variable APARTE de HAMMER_MIRROR porque son dos espacios
# de nombres distintos —`{sha256}.tar` vs `{commit}.bundle`— y se pueblan y se pierden por separado.
export HAMMER_MIRROR_GIT="${HAMMER_MIRROR_GIT:-sftp://u647150@u647150.your-storagebox.de:23/~/hammer/fuentes-git}"
export HAMMER_MIRROR_KEY="${HAMMER_MIRROR_KEY:-$HOME/.ssh/github5}"
export TAKANA_MIRROR_GIT="${TAKANA_MIRROR_GIT:-${HAMMER_MIRROR_GIT:-sftp://u647150@u647150.your-storagebox.de:23/~/hammer/fuentes-git}}"
export HAMMER_MIRROR_GIT="$TAKANA_MIRROR_GIT"
export TAKANA_MIRROR_KEY="${TAKANA_MIRROR_KEY:-${HAMMER_MIRROR_KEY:-$HOME/.ssh/github5}}"
export HAMMER_MIRROR_KEY="$TAKANA_MIRROR_KEY"
+1 -1
View File
@@ -18,7 +18,7 @@
set -uo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT"
RFS="${RFS:-work/gnome-rootfs}"; STORE="${STORE:-./store}"; LINK="${LINK:-static}"
HAMMER="${HAMMER:-./target/release/takana}"; KEEP="${KEEP:-0}"
HAMMER="${TAKANA:-${HAMMER:-./target/release/takana}}"; KEEP="${KEEP:-0}"
# Por defecto se hidratan DOS raíces, no una. accountsservice no es dep de build de gnome-shell —no
# aparece en su meson.build ni en su cierre— sino dep de RUNTIME: la capa JS del shell hace
# `imports.gi.AccountsService` y gjs resuelve el typelib al arrancar. Todo lo que el shell carga por
+9 -8
View File
@@ -25,7 +25,8 @@
# particiona+instala. Es la cara humana del instalador (el /init del ISO installer lo lanza).
# DESATENDIDO (con device): hammer-install /dev/vdb [ROOT_MB] [STORE_MB]
# Autoinstalador (lo usa iso-install-test.sh con AUTO_INSTALL). La config sale de env:
# HAMMER_HOSTNAME / HAMMER_ROOT_PW / HAMMER_ROOT_AUTHKEYS / HAMMER_TZ / HAMMER_KEYMAP.
# TAKANA_HOSTNAME / TAKANA_ROOT_PW / TAKANA_ROOT_AUTHKEYS / TAKANA_TZ / TAKANA_KEYMAP.
# Los nombres viejos HAMMER_* se siguen aceptando (ADR 0016); gana el nuevo si están los dos.
set -eu
DEV="${1:-}"
@@ -132,11 +133,11 @@ apply_post_install_config() {
}
# ---- recolección de config: interactiva (TUI) o desde env (desatendido) ----
CFG_HOSTNAME="${HAMMER_HOSTNAME:-hammer}"
CFG_ROOT_AUTHKEYS="${HAMMER_ROOT_AUTHKEYS:-}"
CFG_ROOT_HASH="${HAMMER_ROOT_HASH:-}"
CFG_TZ="${HAMMER_TZ:-}"
CFG_KEYMAP="${HAMMER_KEYMAP:-us}"
CFG_HOSTNAME="${TAKANA_HOSTNAME:-${HAMMER_HOSTNAME:-takana}}"
CFG_ROOT_AUTHKEYS="${TAKANA_ROOT_AUTHKEYS:-${HAMMER_ROOT_AUTHKEYS:-}}"
CFG_ROOT_HASH="${TAKANA_ROOT_HASH:-${HAMMER_ROOT_HASH:-}}"
CFG_TZ="${TAKANA_TZ:-${HAMMER_TZ:-}}"
CFG_KEYMAP="${TAKANA_KEYMAP:-${HAMMER_KEYMAP:-us}}"
interactive_setup() {
echo
@@ -250,8 +251,8 @@ fi
ROOT_MB="${ROOT_MB:-1500}"
STORE_MB="${STORE_MB:-400}"
# En modo desatendido con contraseña por env, derivar el hash acá (interactivo ya lo hizo).
if [ -z "$CFG_ROOT_HASH" ] && [ -n "${HAMMER_ROOT_PW:-}" ] && have_cryptpw; then
CFG_ROOT_HASH=$(printf '%s' "$HAMMER_ROOT_PW" | bb cryptpw -m sha512 2>/dev/null || true)
if [ -z "$CFG_ROOT_HASH" ] && [ -n "${TAKANA_ROOT_PW:-${HAMMER_ROOT_PW:-}}" ] && have_cryptpw; then
CFG_ROOT_HASH=$(printf '%s' "${TAKANA_ROOT_PW:-$HAMMER_ROOT_PW}" | bb cryptpw -m sha512 2>/dev/null || true)
fi
# --- gancho de prueba: valida TUI + config sin tocar disco (HAMMER_INSTALL_DRYRUN=1) ---
+1 -1
View File
@@ -23,7 +23,7 @@ set -euo pipefail
RECETA="${1:?uso: harkaq-trace-build.sh <receta.toml> [store] [outdir]}"
STORE="${2:-./store}"
OUT="${3:-/tmp/harkaq-trace-pilot}"
HAMMER="${HAMMER:-./target/release/takana}"
HAMMER="${TAKANA:-${HAMMER:-./target/release/takana}}"
TRACE="${TRACE:-/tmp/harkaq-trace}"
NORM="${NORM:-scripts/harkaq/harkaq-trace-norm.py}"
mkdir -p "$OUT"; rm -f "$OUT"/traza-fase-*.txt "$OUT"/canonica.txt "$OUT"/resumen.txt
+1 -1
View File
@@ -144,7 +144,7 @@ mkdir -p "$ROOT_TREE/store" "$ROOT_TREE/var/lib/hammer"
# CLI `hammer` (static musl) para el menú de arranque por grafo (ADR 0010): el hook de init lo invoca
# como `hammer boot menu`. El producto trae arje-zero/hammerd pero NO el CLI ⇒ lo inyectamos acá si
# está compilado (igual patrón que hammer-recover). Opcional: sin él, el wrapper saltea el menú.
HAMMER_MUSL="${HAMMER_MUSL:-$ROOT/target/x86_64-unknown-linux-musl/release/hammer}"
HAMMER_MUSL="${TAKANA_MUSL:-${HAMMER_MUSL:-$ROOT/target/x86_64-unknown-linux-musl/release/hammer}}"
if [ -x "$HAMMER_MUSL" ]; then
cp "$HAMMER_MUSL" "$ROOT_TREE/usr/bin/hammer"; chmod 0755 "$ROOT_TREE/usr/bin/hammer"
echo " + CLI hammer (static musl) para el menú de arranque por grafo"
+1 -1
View File
@@ -9,7 +9,7 @@
set -uo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT"
STORE="${STORE:-./store}"; RFS="${RFS:-work/kde-store-rootfs}"; LINK="${LINK:-static}"
HAMMER="${HAMMER:-./target/release/takana}"
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"
+1 -1
View File
@@ -16,7 +16,7 @@ REPO="${REPO:-work/repo-kde}"; TRUST="${TRUST:-dist/keys}"; STORE="${STORE:-./st
RFS="${RFS:-work/kde-rootfs}"
# TARGETS = uno o varios paquetes tope (unión de cierres). TARGET (singular) sigue soportado.
TARGETS="${TARGETS:-${TARGET:-qt6-qtdeclarative}}"
HAMMER="${HAMMER:-./target/release/takana}"
HAMMER="${TAKANA:-${HAMMER:-./target/release/takana}}"
DB="$RFS/var/lib/hammer/installed.json"
# cierre transitivo de TODOS los targets, leído del índice (deps + aliases ya resuelven). Excluimos
+1 -1
View File
@@ -15,7 +15,7 @@
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}"
RFS="${RFS:-work/kde-store-rootfs}"; HAMMER="${TAKANA:-${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)}"
+1 -1
View File
@@ -23,7 +23,7 @@ ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
STORE="${STORE:-./store}"
DEVFS="${DEVFS:-.dev-fs/alpine}"
RFS="${RFS:-work/mirada-rootfs}"
HAMMER="${HAMMER:-target/release/takana}"
HAMMER="${TAKANA:-${HAMMER:-target/release/takana}}"
PACKAGE="${PACKAGE:-1}"
[ -d "$DEVFS" ] || { echo "no existe $DEVFS (corré scripts/bootstrap-devfs.sh)" >&2; exit 1; }
+1 -1
View File
@@ -9,7 +9,7 @@ set -eu
ATTR="${1:?uso: nix-import.sh <attr-de-nixpkgs> (ej: hello, jq, ripgrep)}"
NIXPKGS="${NIXPKGS:-nixpkgs}"
HAMMER="${HAMMER:-cargo run -q -p takana-cli --}"
HAMMER="${TAKANA:-${HAMMER:-cargo run -q -p takana-cli --}}"
# NIX_STORE: si el /nix/store del sistema no es escribible (install single-user incompleta), apuntá
# a un store local, p.ej. NIX_STORE="local?root=$HOME/.nixstore".
STORE_OPT=""
+1 -1
View File
@@ -6,7 +6,7 @@
#
# Ej: scripts/pin-recipes.sh recipes/*.toml | find recipes -name '*.toml' | xargs scripts/pin-recipes.sh
set -eu
HAMMER="${HAMMER:-cargo run -q -p takana-cli --}"
HAMMER="${TAKANA:-${HAMMER:-cargo run -q -p takana-cli --}}"
[ "$#" -gt 0 ] || { echo "uso: pin-recipes.sh <recipe.toml...>" >&2; exit 1; }
pinned=0; skipped=0; failed=""
+1 -1
View File
@@ -18,7 +18,7 @@
set -eu
QORPA_ROOT="${HAMMER_QORPA_ROOT:-/var/lib/hammer/qorpa}"
HAMMER="${HAMMER_BIN:-./target/release/takana}"
HAMMER="${TAKANA_BIN:-${HAMMER_BIN:-./target/release/takana}}"
ID="${1:-arch-probe}"
export HAMMER_QORPA_ROOT="$QORPA_ROOT"
+1 -1
View File
@@ -21,7 +21,7 @@
set -eu
QORPA_ROOT="${HAMMER_QORPA_ROOT:-/var/lib/hammer/qorpa}"
HAMMER="${HAMMER_BIN:-./target/release/takana}"
HAMMER="${TAKANA_BIN:-${HAMMER_BIN:-./target/release/takana}}"
ID="${1:-sniper-probe}"
UBUNTU_URL="https://cdimage.ubuntu.com/ubuntu-base/releases/24.04/release/ubuntu-base-24.04.3-base-amd64.tar.gz"
+1 -1
View File
@@ -31,7 +31,7 @@
set -uo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
HAMMER="${HAMMER:-$ROOT/target/release/takana}"
HAMMER="${TAKANA:-${HAMMER:-$ROOT/target/release/takana}}"
STORE="${STORE:-./store}"
LOCK="$ROOT/work/.farm-build.lock"
LOG="${LOG:-$ROOT/work/reconstruccion.log}"
+1 -1
View File
@@ -241,7 +241,7 @@ fi
# kernel): un /init PID1 que copia el rootfs a un tmpfs y hace `switch_root`, dejando `/` como un
# mount tmpfs real (pivotable). El kernel debe arrancar con rdinit=/init (ver APPEND abajo). Off por
# defecto ⇒ el camino del kernel host queda intacto (rdinit=/sbin/init directo).
if [[ "${HAMMER_KERNEL:-0}" == 1 ]]; then
if [[ "${TAKANA_KERNEL:-${HAMMER_KERNEL:-0}}" == 1 ]]; then
say "HAMMER_KERNEL: inyectar /init wrapper (copy-to-tmpfs + switch_root, escapa del rootfs)"
cat > work/builder-rootfs/init <<'INIT'
#!/bin/sh
+1 -1
View File
@@ -37,7 +37,7 @@ set -eu
HUB="$(cd "$(dirname "$0")/.." && pwd)"
cd "$HUB"
STORE="${STORE:-$PWD/store}"
HAMMER="${HAMMER:-$HUB/target/release/takana}"
HAMMER="${TAKANA:-${HAMMER:-$HUB/target/release/takana}}"
if [ $# -gt 0 ]; then
recetas=""
+1 -1
View File
@@ -38,7 +38,7 @@
# Env: STORE (def ./store) HAMMER (def ./target/release/takana) JOBS (def 8)
set -uo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
STORE="${STORE:-./store}"; HAMMER="${HAMMER:-./target/release/takana}"; JOBS="${JOBS:-8}"
STORE="${STORE:-./store}"; HAMMER="${TAKANA:-${HAMMER:-./target/release/takana}}"; JOBS="${JOBS:-8}"
APLICAR=0; HUERFANOS=0
for a in "$@"; do
case "$a" in
+1 -1
View File
@@ -48,7 +48,7 @@
# Env: STORE (def ./store) N (def 30, tamaño de la muestra)
set -uo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
STORE="${STORE:-./store}"; HAMMER="${HAMMER:-./target/release/takana}"; N="${N:-30}"
STORE="${STORE:-./store}"; HAMMER="${TAKANA:-${HAMMER:-./target/release/takana}}"; N="${N:-30}"
# ── EL LOCK LO TOMA EL SCRIPT, Y ANTES DE TOCAR NADA ───────────────────────────────────────────
# Este script llama a `hammer build`, y la regla 1 del repo es que todo build va envuelto en el