imagen↔repo: install hidrata userland del repo firmado + 2 fixes de path
Cierra el lazo Etapa F+G: el userland del producto se arma vía `hammer install
--repo --prefix --require-signed` desde el repo firmado, no del bootstrap
hardcodeado. scripts/product-userland-from-repo.sh hidrata un set curado (13+
tools validados estáticos del repo).
Dos bugs reales del path install/pack encontrados+arreglados:
1. pack derivaba target_bin=/usr/bin/{name}; para paquetes con binario≠nombre
(ripgrep→rg, repgrep→rgr) quedaba mal y el sanity-check de install fallaba.
Ahora pack lo deriva del flag `--bin <X>` de la receta Cargo.
2. La reproducción del source_patch derivaba el NOMBRE de la receta del
target_bin ⇒ "rg" ≠ "ripgrep" del corpus ⇒ no cache-hit ⇒ rebuild + dup en
el store (find_by_hash ambiguo). build_source_patch/run_apply ahora reciben
el nombre del paquete (install/bootstrap lo pasan; apply=None) ⇒ cache-hit
del artefacto del corpus, sin duplicar.
(El "EACCES" inicial era sólo --store ausente: DEFAULT_STORE=/store root-only.)
hammer-build 49/49 tests ok; ripgrep install validado e2e (rg hidratado).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -829,7 +829,7 @@ pub fn install_components_from_repo(
|
||||
let mutation = source_patch_of(&swm).ok_or_else(|| {
|
||||
Error::Other(format!("'{name}' no es un paquete source_patch"))
|
||||
})?;
|
||||
let hash = hammer_build::swm_bridge::build_source_patch(mutation, cfg, store, None)?;
|
||||
let hash = hammer_build::swm_bridge::build_source_patch(mutation, cfg, store, None, Some(name))?;
|
||||
tracing::info!(%name, %hash, "product: componente reproducido desde el repo firmado");
|
||||
out.push((name.to_string(), hash));
|
||||
}
|
||||
|
||||
@@ -26,9 +26,14 @@ pub fn build_source_patch(
|
||||
cfg: &BuildConfig,
|
||||
store: &Store,
|
||||
scratch_root: Option<&Path>,
|
||||
name: Option<&str>,
|
||||
) -> hammer_core::Result<ArtifactHash> {
|
||||
let catalog_dir = catalog_dir_for(cfg, scratch_root);
|
||||
let recipe = recipe_from_source_patch(mutation, None, &catalog_dir)?;
|
||||
// El NOMBRE de la receta sintetizada decide el sufijo del store (`<hash>-<name>`) Y la
|
||||
// clave de cache-hit (`store.has(hash, name)`). Si quien llama conoce el nombre del paquete
|
||||
// (p.ej. `install ripgrep`), lo pasa: así reproduce como "ripgrep" y cache-hitea el artefacto
|
||||
// del corpus, en vez de derivar "rg" del target_bin y sellar un duplicado bajo otro nombre.
|
||||
let recipe = recipe_from_source_patch(mutation, name, &catalog_dir)?;
|
||||
|
||||
let expected = match mutation {
|
||||
Mutation::SourcePatch { expected_hash, .. } => expected_hash.clone(),
|
||||
@@ -358,7 +363,7 @@ mod tests {
|
||||
let d = tempfile::tempdir().unwrap();
|
||||
let store = Store::open(d.path().join("store")).unwrap();
|
||||
let cfg = BuildConfig::defaults_for_store(store.root());
|
||||
let err = build_source_patch(&m, &cfg, &store, None).unwrap_err().to_string();
|
||||
let err = build_source_patch(&m, &cfg, &store, None, None).unwrap_err().to_string();
|
||||
assert!(err.contains("source_patch"), "{err}");
|
||||
}
|
||||
|
||||
@@ -388,7 +393,7 @@ mod tests {
|
||||
let cfg = BuildConfig::defaults_for_store(store.root());
|
||||
let scratch = d.path().join("scratch");
|
||||
// Falla (no hay rootfs), pero el patch ya debe estar descargado.
|
||||
let _ = build_source_patch(&m, &cfg, &store, Some(&scratch));
|
||||
let _ = build_source_patch(&m, &cfg, &store, Some(&scratch), None);
|
||||
// El patch se materializa como `{label}-{source_key}.patch` (label = derive_name del
|
||||
// target_bin) para no colisionar entre deps en el catálogo.
|
||||
let landed = scratch.join("swm-recipes").join(format!("x-{commit}.patch"));
|
||||
|
||||
@@ -795,6 +795,7 @@ fn main() -> anyhow::Result<()> {
|
||||
skip_source_patch,
|
||||
base_ref.as_deref(),
|
||||
state_root.as_deref(),
|
||||
None, // `apply` aplica un .swm genérico: no conoce el nombre del paquete
|
||||
)?;
|
||||
}
|
||||
Cmd::SwmVerify { file, base_ref, trust } => {
|
||||
@@ -1326,9 +1327,19 @@ fn run_pack(
|
||||
Some(buf)
|
||||
};
|
||||
|
||||
let target_bin = target_bin
|
||||
.map(|s| s.to_string())
|
||||
.unwrap_or_else(|| format!("/usr/bin/{}", recipe.name));
|
||||
// target_bin: `--target-bin` manda. Si no, y la receta Cargo declara `--bin <X>`, el binario
|
||||
// instalado es X (no el nombre del paquete: ripgrep→rg, repgrep→rgr) ⇒ derivamos de ahí. Sólo
|
||||
// si no hay `--bin`, caemos a `/usr/bin/{name}` (correcto para C y para name==bin).
|
||||
let target_bin = target_bin.map(|s| s.to_string()).unwrap_or_else(|| {
|
||||
let bin = recipe
|
||||
.build
|
||||
.flags
|
||||
.windows(2)
|
||||
.find(|w| w[0] == "--bin")
|
||||
.map(|w| w[1].clone())
|
||||
.unwrap_or_else(|| recipe.name.clone());
|
||||
format!("/usr/bin/{bin}")
|
||||
});
|
||||
|
||||
// expected_hash: `--expected` manda; si no, `--build` lo sella construyendo de verdad en el
|
||||
// lab; si ninguno, el paquete sale sin ancla de verificación (válido, sólo más débil).
|
||||
@@ -1624,6 +1635,7 @@ fn run_install(
|
||||
skip_source_patch,
|
||||
base_ref,
|
||||
state_root,
|
||||
Some(&pkg_name), // reproduce con el nombre del paquete ⇒ cache-hit del corpus, sin duplicar
|
||||
)?;
|
||||
|
||||
// Registrar en la DB de instalados (salvo dry-run de schema). Permite `hammer uninstall`.
|
||||
@@ -1981,6 +1993,10 @@ fn run_apply(
|
||||
skip_source_patch: bool,
|
||||
base_ref: Option<&std::path::Path>,
|
||||
state_root: Option<&std::path::Path>,
|
||||
// Nombre del paquete (sólo lo sabe `install`): si está, la reproducción del source_patch usa
|
||||
// ESE nombre para la receta sintetizada ⇒ cache-hitea el artefacto del corpus (`<hash>-name`)
|
||||
// en vez de derivar el nombre del target_bin y sellar un duplicado (ripgrep→rg). `apply` pasa None.
|
||||
pkg_name: Option<&str>,
|
||||
) -> anyhow::Result<Vec<PathBuf>> {
|
||||
let swm = load_swm(file)?;
|
||||
swm.verify_schema()?;
|
||||
@@ -2020,7 +2036,7 @@ fn run_apply(
|
||||
}
|
||||
let store = hammer_core::Store::open(store_path)?;
|
||||
let cfg = hammer_build::BuildConfig::from_env_or_defaults(store.root());
|
||||
let hash = hammer_build::build_source_patch(m, &cfg, &store, None)?;
|
||||
let hash = hammer_build::build_source_patch(m, &cfg, &store, None, pkg_name)?;
|
||||
let artifact = store.find_by_hash(hash.as_str())?;
|
||||
let into = hammer_core::apply::rebase_path("/", prefix);
|
||||
let report = hammer_build::run_hydrate(
|
||||
|
||||
@@ -392,7 +392,7 @@ fn run_compile(recipe: RecipeInline, store_root: PathBuf, tx: Sender<Event>) {
|
||||
}
|
||||
};
|
||||
let cfg = hammer_build::BuildConfig::from_env_or_defaults(store.root());
|
||||
match hammer_build::build_source_patch(&mutation, &cfg, &store, None) {
|
||||
match hammer_build::build_source_patch(&mutation, &cfg, &store, None, None) {
|
||||
Ok(h) => {
|
||||
let _ = tx.send(Event::BuildReady {
|
||||
recipe: name,
|
||||
|
||||
Reference in New Issue
Block a user