fetch: cargo_vendor_dir per-receta — no pisar el vendor/ propio del proyecto
`cargo vendor vendor` borra lo que no reconoce del dir destino; proyectos que commitean su PROPIO vendor/ (mise → vendor/aqua-registry, 3.1MB que build.rs lee) lo perdían → build.rs falla 'No such file'. Nuevo campo opcional [source] cargo_vendor_dir (default 'vendor', sin cambios para las ~200 recetas selladas) manda el vendoreo cargo a otro dir; el .cargo/config.toml que emite cargo vendor ya apunta ahí. mise.toml usa '.hammer-cargo-vendor'. Validado en vivo: aqua-registry sobrevive + compila 591 crates pasando los muros previos (openssl vía rustls + AR). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -206,7 +206,7 @@ fn verify_sha256(path: &Path, expected: &str) -> hammer_core::Result<()> {
|
||||
/// (plan C.2 #5). Ver `docs/runbooks/stage1-vm-boot.md` §8.
|
||||
///
|
||||
/// Un crate sin deps de crates.io produce un config vacío y ningún `vendor/`: inocuo.
|
||||
pub fn vendor_cargo_deps(src: &Path) -> hammer_core::Result<()> {
|
||||
pub fn vendor_cargo_deps(src: &Path, vendor_dir: &str) -> hammer_core::Result<()> {
|
||||
let locked = src.join("Cargo.lock").is_file();
|
||||
let mut args: Vec<&str> = vec!["vendor"];
|
||||
if locked {
|
||||
@@ -218,7 +218,10 @@ pub fn vendor_cargo_deps(src: &Path) -> hammer_core::Result<()> {
|
||||
tiempo (deps no pineadas). Committear el lock en la fuente para fijarlo (plan C.2 #5)."
|
||||
);
|
||||
}
|
||||
args.push("vendor");
|
||||
// Directorio de salida (default `vendor`; override per-receta vía `[source] cargo_vendor_dir`
|
||||
// para no pisar un `vendor/` propio del proyecto). `cargo vendor` emite el `[source.*]` a stdout
|
||||
// apuntando a ESTE dir, así que el `.cargo/config.toml` que persistimos abajo resuelve solo.
|
||||
args.push(vendor_dir);
|
||||
let output = Command::new("cargo")
|
||||
.current_dir(src)
|
||||
.args(&args)
|
||||
@@ -358,7 +361,7 @@ mod tests {
|
||||
return;
|
||||
}
|
||||
|
||||
vendor_cargo_deps(src).unwrap();
|
||||
vendor_cargo_deps(src, "vendor").unwrap();
|
||||
assert!(src.join(".cargo/config.toml").is_file(), "debe escribir el config de vendoring");
|
||||
}
|
||||
|
||||
@@ -382,7 +385,7 @@ mod tests {
|
||||
return;
|
||||
}
|
||||
// No debe fallar por falta de --locked; genera el lock y escribe el config.
|
||||
vendor_cargo_deps(src).unwrap();
|
||||
vendor_cargo_deps(src, "vendor").unwrap();
|
||||
assert!(src.join(".cargo/config.toml").is_file());
|
||||
assert!(src.join("Cargo.lock").is_file(), "vendor sin --locked genera el lock");
|
||||
}
|
||||
|
||||
@@ -209,7 +209,10 @@ pub fn build(
|
||||
// Extractor de workspaces (Etapa G): si el root es virtual, resuelve `-p <pkg>` del bin.
|
||||
inject_cargo_package_selector(&mut eff_recipe, &src_tree);
|
||||
tracing::info!("cargo: vendoreando deps para build offline");
|
||||
fetch::vendor_cargo_deps(&src_tree)?;
|
||||
fetch::vendor_cargo_deps(
|
||||
&src_tree,
|
||||
eff_recipe.source.cargo_vendor_dir.as_deref().unwrap_or("vendor"),
|
||||
)?;
|
||||
}
|
||||
|
||||
// Recetas Go: análogo a Cargo. Si el árbol trae `go.mod`, vendoreamos los módulos (red en el
|
||||
|
||||
@@ -60,6 +60,12 @@ pub struct Source {
|
||||
#[serde(default = "default_strip")]
|
||||
pub strip_components: usize,
|
||||
// --- común ---
|
||||
/// Destino del vendoreo cargo (default `vendor`). Override per-receta para proyectos que
|
||||
/// commitean su PROPIO `vendor/` (p.ej. mise → `vendor/aqua-registry`): `cargo vendor` borra
|
||||
/// lo que no reconoce, así que se vendorea a un subdir aparte para no pisarlo. El fragmento
|
||||
/// `.cargo/config.toml` que emite `cargo vendor` ya apunta al dir que se le pasa.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub cargo_vendor_dir: Option<String>,
|
||||
#[serde(default)]
|
||||
pub patches: Vec<String>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user