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 815Rust 56Shell 37Markdown 291229 Definitions

Etapa G capa-de-adaptación #2: Alpine import build-ready (sha256 auto + traducción abuild)

Mueve las recetas de Alpine de "importan" a "casi buildean":
- alpine_import.rs: translate_abuild() en las fases — substituye $pkgdir→/out (el DESTDIR del lab),
  $pkgname→nombre, $pkgver→versión. NO toca $CBUILD/$CHOST/--shared (juicio por-paquete, marcado).
  +1 test.
- scripts/alpine-import.sh: baja el tarball UNA vez y calcula el sha256 (Alpine publica sha512,
  hammer pide sha256), reemplazando el FIXME ⇒ receta lista sin tocar el hash a mano.
- VALIDADO real: import bzip2 → sha256 ab5a0317… resuelto, 5 parches musl bajados, install
  traducido a /out. Recipe build-ready (sin $pkgdir ni FIXME en código). 31 suites verde.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

8e6c878d3a90d0a4652c0662724cd40d1e93859b · by sergio · (4 months ago) · parent 2d81bc6ea · browse the tree at this commit

Semantic delta · 4

crates/hammer-cli/src/alpine_import.rs

2 files · +44 −4

diff --git a/crates/hammer-cli/src/alpine_import.rs b/crates/hammer-cli/src/alpine_import.rs
index f370897d..4c53c5d5 100644
--- a/crates/hammer-cli/src/alpine_import.rs
+++ b/crates/hammer-cli/src/alpine_import.rs
@@ -105,10 +105,12 @@ pub fn recipe_from_apkbuild(text: &str) -> Result<String, String> {
         } else {
             let mut s = String::from("\n[build.phases]\n");
             if let Some(b) = compile {
-                s.push_str(&format!("# de build() de Alpine (abuild: CHOST/--shared/etc; adaptá a estático):\ncompile = {}\n", toml_multiline(&b)));
+                let t = translate_abuild(&b, &pkgname, &version);
+                s.push_str(&format!("# de build() de Alpine (traducido; revisá $CBUILD/$CHOST/--shared para estático):\ncompile = {}\n", toml_multiline(&t)));
             }
             if let Some(p) = install {
-                s.push_str(&format!("# de package() de Alpine (usa $pkgdir → ajustá a /out):\ninstall = {}\n", toml_multiline(&p)));
+                let t = translate_abuild(&p, &pkgname, &version);
+                s.push_str(&format!("# de package() de Alpine (traducido $pkgdir→/out):\ninstall = {}\n", toml_multiline(&t)));
             }
             s
         }
@@ -245,6 +247,19 @@ fn func_body(text: &str, name: &str) -> Option<String> {
     }
 }
 
+/// Traduce las variables de abuild a su equivalente en el lab de hammer. Substituciones SEGURAS
+/// (inequívocas): `$pkgdir`→`/out` (el DESTDIR del lab), `$pkgname`→nombre, `$pkgver`→versión.
+/// NO toca `$CBUILD/$CHOST/$srcdir/$builddir` ni `--shared` (juicio por-paquete; quedan para el
+/// humano, marcados en el comentario de la fase). `make DESTDIR="$pkgdir"` → `make DESTDIR="/out"`.
+fn translate_abuild(body: &str, name: &str, version: &str) -> String {
+    body.replace("${pkgdir}", "/out")
+        .replace("$pkgdir", "/out")
+        .replace("${pkgname}", name)
+        .replace("$pkgname", name)
+        .replace("${pkgver}", version)
+        .replace("$pkgver", version)
+}
+
 /// Primer hash de un bloque `sha512sums="<hash>  <fichero>\n..."`.
 fn first_sha(block: &str) -> String {
     block
@@ -305,9 +320,21 @@ package() {
         assert!(recipe.deps.build.contains(&"openssl".to_string()));
         assert!(recipe.deps.build.contains(&"linux-headers".to_string()));
         assert!(recipe.deps.build.contains(&"bar".to_string()));
-        // fases capturadas de build()/package():
+        // fases capturadas de build()/package() y TRADUCIDAS: $pkgdir → /out.
         assert!(recipe.build.phases.compile.as_deref().unwrap().contains("./configure"));
-        assert!(recipe.build.phases.install.as_deref().unwrap().contains("DESTDIR"));
+        let install = recipe.build.phases.install.as_deref().unwrap();
+        assert!(install.contains("DESTDIR=\"/out\""), "instala a /out: {install}");
+        assert!(!install.contains("$pkgdir"), "no debe quedar $pkgdir: {install}");
+    }
+
+    #[test]
+    fn translate_abuild_substitutes_vars() {
+        let body = "make DESTDIR=\"$pkgdir\" install\ncp x ${pkgdir}/usr/share/$pkgname/\necho $pkgver";
+        let t = translate_abuild(body, "foo", "2.5");
+        assert!(t.contains("DESTDIR=\"/out\""));
+        assert!(t.contains("/out/usr/share/foo/"));
+        assert!(t.contains("echo 2.5"));
+        assert!(!t.contains("$pkg"));
     }
 
     #[test]
diff --git a/scripts/alpine-import.sh b/scripts/alpine-import.sh
index 900a3a50..ab1e82dd 100755
--- a/scripts/alpine-import.sh
+++ b/scripts/alpine-import.sh
@@ -17,6 +17,19 @@ 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; }
 toml=$(printf '%s' "$apk" | $HAMMER import-alpine -)
+
+# sha256 automático: Alpine publica sha512, pero hammer pide sha256. Bajamos el tarball UNA vez y
+# lo calculamos, reemplazando el FIXME ⇒ receta lista para `pack --build` sin tocar el hash a mano.
+url=$(printf '%s\n' "$toml" | sed -n 's/^tarball = "\(.*\)"$/\1/p' | head -1)
+if [ -n "$url" ]; then
+  sha=$(curl -fsSL "$url" 2>/dev/null | sha256sum | cut -d' ' -f1)
+  if [ -n "$sha" ] && [ "$sha" != "$(printf '' | sha256sum | cut -d' ' -f1)" ]; then
+    toml=$(printf '%s\n' "$toml" | sed "s|FIXME-sha256|$sha|")
+    echo "  sha256 calculado: $sha" >&2
+  else
+    echo "  ⚠ no pude bajar el tarball para sha256 (queda FIXME): $url" >&2
+  fi
+fi
 printf '%s\n' "$toml"
 
 # Bajar los .patch referenciados (los parches de musl que hacen al paquete compilar).