gioser

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1184Shell 70Rust 62Markdown 501503 Definiciones

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>

b580c5bfc5b134c64a571136441f585c025deaaf · por sergio · (hace 3 meses) · padre cee652717 · ver el árbol en este commit

Delta semántico · 5

crates/hammer-build/src/fetch.rs

crates/hammer-build/src/lib.rs

  • cambió por dentro fn build pub

crates/hammer-core/src/recipe.rs

  • cambió de firma struct Source pub

4 archivos · +20 −5

diff --git a/crates/hammer-build/src/fetch.rs b/crates/hammer-build/src/fetch.rs
index 2b85694e..d1c17bab 100644
--- a/crates/hammer-build/src/fetch.rs
+++ b/crates/hammer-build/src/fetch.rs
@@ -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");
     }
diff --git a/crates/hammer-build/src/lib.rs b/crates/hammer-build/src/lib.rs
index 0b65a8f1..1c9ee52d 100644
--- a/crates/hammer-build/src/lib.rs
+++ b/crates/hammer-build/src/lib.rs
@@ -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
diff --git a/crates/hammer-core/src/recipe.rs b/crates/hammer-core/src/recipe.rs
index 0df369d1..d565e54f 100644
--- a/crates/hammer-core/src/recipe.rs
+++ b/crates/hammer-core/src/recipe.rs
@@ -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>,
 }
diff --git a/tandas/deferred-openssl-xcb/mise.toml b/tandas/deferred-openssl-xcb/mise.toml
index ec4cbc10..4c928145 100644
--- a/tandas/deferred-openssl-xcb/mise.toml
+++ b/tandas/deferred-openssl-xcb/mise.toml
@@ -8,6 +8,9 @@ version = "2026.7.0"
 [source]
 repo   = "https://github.com/jdx/mise"
 commit = "857b73f6a6b39a3bc90c44119a1e86ee11bd7273"
+# mise commitea su PROPIO vendor/aqua-registry (registry.yml 3.1MB que build.rs lee). El
+# `cargo vendor` de hammer, por defecto en `vendor/`, lo borraría. Lo mandamos aparte.
+cargo_vendor_dir = ".hammer-cargo-vendor"
 
 [build]
 compiler = "zig-cc"