Bitácora

El día de compilación que estábamos cansados de perder

Toda biblioteca de Git en todo lenguaje acaba pidiéndote las mismas cuatro cosas: OpenSSL, libssh2, libcurl y perl para compilarlas. No porque tu programa las…

Toda biblioteca de Git en todo lenguaje acaba pidiéndote las mismas cuatro cosas: OpenSSL, libssh2, libcurl y perl para compilarlas. No porque tu programa las necesite, sino porque los transportes de libgit2 sí.

torii <command> 44 commands torii tui 17 views torii-core vcs · platforms · workspace · config · auth one library, both surfaces 7 platform clients github gitlab gitea bitbucket sourcehut radicle azure libgit2 (vendored) GIT_HTTPS=0 GIT_SSH=0 objects, refs, index pure-Rust transports rustls (https) · russh (ssh) since 0.6.0 build needs a C compiler no perl · no openssl-dev no libssh2-dev · no pkg-config one binary · MIT OR Apache-2.0

Qué se quitó

libgit2 sigue ahí —es una buena implementación de objetos, refs e índice, y reescribir eso sería vanidad—. Lo que se ha ido es su red: está vendorizada y compilada con GIT_HTTPS=0 GIT_SSH=0, así que las partes que arrastran la cadena de dependencias en C simplemente no se compilan.

El HTTPS es reqwest sobre rustls. El SSH es russh sobre aws-lc-rs. Los dos en Rust, los dos entran por cargo, y ninguno necesita un paquete del sistema.

Qué compra eso

Compilar torii desde fuente necesita un compilador de C y nada más. Ni openssl-dev, ni libssh2-dev, ni pkg-config, ni perl. Sobre el target musl con la feature static el resultado no enlaza ninguna biblioteca en tiempo de ejecución, que es lo que le permite correr en Alpine, en scratch y en una imagen busybox donde no hay nada instalado.

Los binarios ya construidos heredan la misma propiedad: cero dependencias en tiempo de ejecución no es una cifra de marketing en la portada, es la consecuencia de esta decisión.

Qué costó

Dos implementaciones de transporte que el mundo no lleva quince años machacando, y sería deshonesto fingir que eso sale gratis.

La cadena de autenticación SSH es agente, luego ed25519, luego RSA, con verificación de host contra known_hosts y confianza al primer uso para un host desconocido. Quedan dos huecos y merecen decirse claros: una clave privada cifrada necesita un agente, porque aún no hay pregunta de passphrase, y los alias de ~/.ssh/config no se parsean, así que el nombre de host real es el que funciona.

La validación de push contra Bitbucket, Gitea, Forgejo y Sourcehut sigue siendo razonada y no probada de extremo a extremo. Hablan el mismo Smart HTTP y el mismo SSH, así que debería funcionar; ese «debería» está trabajando de verdad en la frase, y hay tests de integración contra un servidor git local en la lista.

El que no resolvió

Hay un fallo que este cambio hizo más probable, no menos. La cadena de cripto que arrastra russh tiene un árbol genérico profundo, y monomorfizarlo puede desbordar la pila de 8 MB por defecto de rustc:

error: rustc interrupted by SIGSEGV, printing backtrace
... LlvmCodegenBackend ... compile_codegen_unit ...

Eso no es un fallo del crate, y no es algo que el crate pueda arreglar. El apaño es darle a rustc más pila y menos paralelismo:

RUST_MIN_STACK=67108864 cargo install gitorii --locked -j 1

La CI del propio proyecto también se lo comió, en un runner Arch autoalojado, y le dedicó una tarde antes de asentarse en una pila de 32 MB. Cuando un entorno de compilación te pelea con esta precisión, apunta el número que lo terminó: el comentario de la cabecera de .gitlab-ci.yml es esa nota.