From 4e4a2c8d2a8fcd80dc7423a1a9bea913d79d2b8b Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 9 Sep 2026 19:41:52 +0000 Subject: [PATCH] =?UTF-8?q?gnome:=20dash-to-panel,=20appindicator=20y=20gn?= =?UTF-8?q?ome-tweaks=20=E2=80=94=20y=20la=20lista=20de=20activas=20sale?= =?UTF-8?q?=20de=20las=20recetas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GNOME deja de ser la cáscara: tres extensiones y la app que el proyecto no instala y todo el mundo termina instalando. El perfil queda 190/190 con 28 raíces, deuda 0. dash-to-panel v73 junta dash, ventanas y bandeja en una sola barra (lo que más cambia el uso) appindicator v64 devuelve los ICONOS DE BANDEJA que GNOME quitó; sin ella las apps que usan StatusNotifierItem corren y no tienen dónde mostrarse blur-my-shell v72 (ya estaba; se le saca el override, ver abajo) gnome-tweaks 46.1 tema, iconos, cursor, tipografías, los botones de minimizar/maximizar que GNOME esconde, y el interruptor de las extensiones ⚠ LA LISTA DE ACTIVAS SE MUEVE A UN SOLO SITIO, y esto era una bomba de relojería. `enabled-extensions` es un ARRAY: un override de GSettings lo escribe ENTERO. Con la primera extensión el override vivía en su receta y funcionaba; con la segunda NO se habrían sumado — ganaría la que compile última (orden alfabético) y las otras quedarían instaladas y MUERTAS, sin un solo error. Ahora la arma `scripts/gnome/gnome-start-qemu.sh`, que ya compilaba los esquemas al arrancar, enumerando los uuid presentes en /usr/share/gnome-shell/extensions. La política es «lo que la imagen instala, se activa»; el dconf del usuario gana sobre el default. Una receta NO puede ser ese sitio: hammer exige `[source]` en toda receta («missing field `source`»), así que no hay forma de escribir una receta de pura política. Se probó el bloque contra un árbol de juguete: lista las dos extensiones, salta un directorio sin metadata.json, el override compila con stderr vacío y `gsettings get` devuelve las dos. Y si la lista cambia borra `gschemas.compiled` para forzar recompilación — sin eso, una imagen ya arrancada ignoraría la extensión nueva en silencio. ⚠ EL HALLAZGO CARO: `msgfmt` de gettext-tiny REVIENTA con las formas plurales del árabe. SIGILL, exit 132, «index 6 out of bounds for type 'size_t[6]'», y deja un .mo de 0 bytes. Reproducido FUERA de la receta con el binario sellado. No es el idioma sino el mensaje: blur-my-shell compila su ar.po sin problema porque no tiene NINGÚN plural (msgstr[5] = 0); el de tweaks tiene exactamente uno. Acá se saca `ar` del LINGUAS y se pierde la traducción de UNA app, con el diagnóstico escrito en la receta. ARREGLARLO ES OTRA UNIDAD DE TRABAJO: gettext-tiny la usan 108 recetas. Cada receta usa el mecanismo de SU upstream, que no es el mismo en las tres: blur-my-shell `make build` llama a `gnome-extensions pack` —el CLI que nuestro shell apaga— así que se copia el árbol a mano, con el layout LEÍDO del zip de EGO y comparado contra él (idéntico, sin sobras ni faltantes) dash-to-panel su Makefile tiene un `install` que honra DESTDIR y hace lo de un paquete de distro: gschema y locale a los directorios GLOBALES. ⚠ `VERSION=73` se pasa a mano porque sin ella el Makefile hace `git describe` y el árbol viene por `git archive`, sin `.git` ⇒ metadata quedaría con el marcador "version": 9999 appindicator meson. ⚠ `-Dlocal_install=disabled` explícito: en `auto` decide mirando si el uid es 0, o sea que hoy acierta POR ACCIDENTE — y si el lab dejara de correr como root instalaría en $HOME/.local y el artefacto sellaría vacío. Y `jq` va en deps aunque sea JavaScript puro: su meson saca el uuid del metadata.json con jq ⚠ gnome-tweaks NO costó ninguna receta nueva, y eso hubo que medirlo: su meson declara siete deps mínimas de runtime y las siete ya estaban selladas. La que parecía traer una cadena de Python entera —`pygobject-3.0`— la provee `py3-gobject`, que YA ESTABA en el corpus con otro nombre y publica `pygobject-3.0.pc`. El nombre no es el hecho, otra vez. Sí costó dos deps que el configure reclamó y que son el patrón `.pc Requires` → `[deps].build`: `appstream` (la pide `libadwaita-1.pc` y el error culpa a libadwaita, que está bien instalada) y `desktop-file-utils` (meson la busca como PROGRAMA para `update-desktop-database`). Sus deps de RUNTIME —python3 y py3-gobject— van declaradas: es una app de Python, si no están en la imagen se instala y no arranca, y ningún build lo delata. Las cuatro licencias, verificadas en la fuente pineada y NINGUNA leída del COPYING —cuyo apéndice «How to Apply» trae siempre la frase «or any later version»—: blur-my-shell del README del commit, dash-to-panel y appindicator de la cabecera de sus fuentes, gnome-tweaks de su etiqueta SPDX. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01LCt3ettR4Z7b6wPCBmbvEV --- docs/state/build-state-gnome.json | 247 +++++++++++++----- docs/state/drenaje.json | 2 +- docs/state/targets.toml | 15 ++ .../gnome-shell-extension-appindicator.toml | 65 +++++ .../gnome-shell-extension-blur-my-shell.toml | 27 +- .../gnome-shell-extension-dash-to-panel.toml | 69 +++++ recipes/incoming-gnome/gnome-tweaks.toml | 97 +++++++ scripts/gnome/gnome-start-qemu.sh | 39 +++ 8 files changed, 481 insertions(+), 80 deletions(-) create mode 100644 recipes/incoming-gnome/gnome-shell-extension-appindicator.toml create mode 100644 recipes/incoming-gnome/gnome-shell-extension-dash-to-panel.toml create mode 100644 recipes/incoming-gnome/gnome-tweaks.toml diff --git a/docs/state/build-state-gnome.json b/docs/state/build-state-gnome.json index 83e02025..73246257 100644 --- a/docs/state/build-state-gnome.json +++ b/docs/state/build-state-gnome.json @@ -1,16 +1,16 @@ { "schema": "hammer-build-state/1", "totals": { - "recipes": 921, - "nodes": 923, - "sealed": 921, + "recipes": 924, + "nodes": 926, + "sealed": 924, "ajeno": 2 }, "by_class": { "ajeno": 2, "c": 272, "go": 362, - "gui": 48, + "gui": 51, "kernel": 6, "rust": 233 }, @@ -21,7 +21,7 @@ "ajeno": 2 }, "incoming-gnome": { - "sealed": 64 + "sealed": 67 } }, "by_profile": { @@ -36,9 +36,9 @@ "sealed": 80 }, "escritorio-gnome": { - "raices": 25, - "clausura": 183, - "sealed": 183 + "raices": 28, + "clausura": 190, + "sealed": 190 }, "escritorio-mirada": { "raices": 17, @@ -46,7 +46,7 @@ "sealed": 41 } }, - "sin_perfil": 661, + "sin_perfil": 660, "orphan_deps": [], "topo_ok": true, "nodes": { @@ -500,7 +500,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 6 + "dependientes_total": 7 }, "argo-rollouts": { "iname": "argo-rollouts", @@ -1356,6 +1356,7 @@ "unblocks": 0, "perfiles": [ "cli", + "escritorio-gnome", "escritorio-sway" ], "dependientes_total": 4 @@ -1530,7 +1531,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 9 + "dependientes_total": 10 }, "caligula": { "iname": "caligula", @@ -3102,7 +3103,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 10 + "dependientes_total": 11 }, "curlie": { "iname": "curlie", @@ -3391,7 +3392,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 0 + "dependientes_total": 1 }, "devspace": { "iname": "devspace", @@ -4236,7 +4237,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 66 + "dependientes_total": 67 }, "expat-shared": { "iname": "expat-shared", @@ -4809,7 +4810,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 22 + "dependientes_total": 23 }, "foot": { "iname": "foot", @@ -4935,7 +4936,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 26 + "dependientes_total": 27 }, "freeze": { "iname": "freeze", @@ -4979,7 +4980,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 31 + "dependientes_total": 32 }, "fselect": { "iname": "fselect", @@ -5206,7 +5207,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 8 + "dependientes_total": 9 }, "gdk-pixbuf-shared": { "iname": "gdk-pixbuf-shared", @@ -5360,7 +5361,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 104 + "dependientes_total": 107 }, "gh": { "iname": "gh", @@ -5450,7 +5451,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 25 + "dependientes_total": 26 }, "gi-foreign-typelibs": { "iname": "gi-foreign-typelibs", @@ -5992,7 +5993,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 43 + "dependientes_total": 46 }, "glib-introspected": { "iname": "glib-introspected", @@ -6021,7 +6022,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 29 + "dependientes_total": 30 }, "glib-shared": { "iname": "glib-shared", @@ -6245,6 +6246,35 @@ ], "dependientes_total": 0 }, + "gnome-shell-extension-appindicator": { + "iname": "gnome-shell-extension-appindicator", + "version": "64", + "link": "dynamic", + "compiler": "zig-cc", + "deps": [ + "gettext-tiny", + "glib", + "jq", + "libffi", + "meson", + "pcre2", + "pkgconf", + "python3", + "samurai", + "zlib" + ], + "cls": "gui", + "queue": "incoming-gnome", + "foreign": false, + "hash": "b3:624995cae88d2a8997a3ea601569b83d3c255bf5dabfba34d8662bd1d8769683", + "state": "sealed", + "blocked_by": [], + "unblocks": 0, + "perfiles": [ + "escritorio-gnome" + ], + "dependientes_total": 0 + }, "gnome-shell-extension-blur-my-shell": { "iname": "gnome-shell-extension-blur-my-shell", "version": "72", @@ -6260,7 +6290,98 @@ "cls": "gui", "queue": "incoming-gnome", "foreign": false, - "hash": "b3:6b39a579c1d58e333c9c1d27875ba015705a340b883638afcde166fd6e6ac9d9", + "hash": "b3:c6fc6933317d86357e01d2cb056873f1713be64a349775d366ca6f5ac90d80ce", + "state": "sealed", + "blocked_by": [], + "unblocks": 0, + "perfiles": [ + "escritorio-gnome" + ], + "dependientes_total": 0 + }, + "gnome-shell-extension-dash-to-panel": { + "iname": "gnome-shell-extension-dash-to-panel", + "version": "73", + "link": "dynamic", + "compiler": "zig-cc", + "deps": [ + "gettext-tiny", + "glib", + "libffi", + "make", + "pcre2", + "zlib" + ], + "cls": "gui", + "queue": "incoming-gnome", + "foreign": false, + "hash": "b3:620ee7a11e13f0da06358aaa0eaf524145f91d0e8c8a9debd74cc923a41a6aff", + "state": "sealed", + "blocked_by": [], + "unblocks": 0, + "perfiles": [ + "escritorio-gnome" + ], + "dependientes_total": 0 + }, + "gnome-tweaks": { + "iname": "gnome-tweaks", + "version": "46.1", + "link": "dynamic", + "compiler": "zig-cc", + "deps": [ + "appstream", + "cairo-shared", + "curl", + "desktop-file-utils", + "expat", + "fontconfig-shared", + "freetype-shared", + "fribidi", + "gdk-pixbuf", + "gettext-tiny", + "gi-foreign-girs", + "glib", + "glib-introspected", + "gobject-introspection", + "graphene", + "gsettings-desktop-schemas", + "gtk4", + "harfbuzz", + "iso-codes", + "libadwaita", + "libdrm", + "libepoxy", + "libffi", + "libgudev", + "libjpeg-turbo-shared", + "libpng-shared", + "libseccomp", + "libtiff-shared", + "libudev-zero", + "libxml2-shared", + "libxmlb", + "libyaml-shared", + "mesa", + "meson", + "openssl", + "pango", + "pcre2", + "pixman", + "pkgconf", + "py3-gobject", + "python3", + "samurai", + "wayland", + "wayland-protocols", + "xkeyboard-config", + "zlib-shared", + "zstd" + ], + "cls": "gui", + "queue": "incoming-gnome", + "foreign": false, + "hash": "b3:ef9a900ea574f6d0129716b5ae3bc4b34b73450297adae3aeb2f21a3adb4e840", "state": "sealed", "blocked_by": [], "unblocks": 0, @@ -6491,7 +6612,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 31 + "dependientes_total": 32 }, "gobuster": { "iname": "gobuster", @@ -7154,7 +7275,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 6 + "dependientes_total": 7 }, "grcov": { "iname": "grcov", @@ -7330,7 +7451,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 4 + "dependientes_total": 5 }, "gtk3": { "iname": "gtk3", @@ -7429,7 +7550,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 5 + "dependientes_total": 6 }, "gtk4-hello": { "iname": "gtk4-hello", @@ -7710,7 +7831,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 8 + "dependientes_total": 9 }, "harfbuzz-shared": { "iname": "harfbuzz-shared", @@ -8444,7 +8565,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 5 + "dependientes_total": 6 }, "istioctl": { "iname": "istioctl", @@ -8614,9 +8735,10 @@ "unblocks": 0, "perfiles": [ "cli", + "escritorio-gnome", "escritorio-sway" ], - "dependientes_total": 0 + "dependientes_total": 1 }, "jql": { "iname": "jql", @@ -9788,7 +9910,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 1 + "dependientes_total": 2 }, "libarchive": { "iname": "libarchive", @@ -9945,7 +10067,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 149 + "dependientes_total": 150 }, "libei": { "iname": "libei", @@ -10022,7 +10144,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 21 + "dependientes_total": 22 }, "libevdev": { "iname": "libevdev", @@ -10089,7 +10211,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 110 + "dependientes_total": 113 }, "libffi-shared": { "iname": "libffi-shared", @@ -10289,7 +10411,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 5 + "dependientes_total": 6 }, "libgusb": { "iname": "libgusb", @@ -10467,7 +10589,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 20 + "dependientes_total": 21 }, "libksba": { "iname": "libksba", @@ -10644,7 +10766,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 33 + "dependientes_total": 34 }, "libpsl": { "iname": "libpsl", @@ -10747,7 +10869,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 4 + "dependientes_total": 5 }, "libsecret": { "iname": "libsecret", @@ -10930,7 +11052,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 7 + "dependientes_total": 8 }, "libudev-zero": { "iname": "libudev-zero", @@ -10957,7 +11079,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 45 + "dependientes_total": 46 }, "libunibreak": { "iname": "libunibreak", @@ -11190,7 +11312,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 10 + "dependientes_total": 11 }, "libxmlb": { "iname": "libxmlb", @@ -11218,7 +11340,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 7 + "dependientes_total": 8 }, "libyaml": { "iname": "libyaml", @@ -11260,7 +11382,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 2 + "dependientes_total": 3 }, "linux": { "iname": "linux", @@ -11665,7 +11787,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 118 + "dependientes_total": 119 }, "mako": { "iname": "mako", @@ -11987,7 +12109,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 146 + "dependientes_total": 147 }, "mesa-llvmpipe": { "iname": "mesa-llvmpipe", @@ -12083,7 +12205,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 123 + "dependientes_total": 125 }, "micro": { "iname": "micro", @@ -13312,6 +13434,7 @@ "unblocks": 0, "perfiles": [ "cli", + "escritorio-gnome", "escritorio-sway" ], "dependientes_total": 1 @@ -13399,7 +13522,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 28 + "dependientes_total": 29 }, "openssl-threads": { "iname": "openssl-threads", @@ -13666,7 +13789,7 @@ "perfiles": [ "escritorio-gnome" ], - "dependientes_total": 7 + "dependientes_total": 8 }, "pango-shared": { "iname": "pango-shared", @@ -13848,7 +13971,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 82 + "dependientes_total": 85 }, "pcre2-shared": { "iname": "pcre2-shared", @@ -14086,7 +14209,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 45 + "dependientes_total": 46 }, "pkgconf": { "iname": "pkgconf", @@ -14110,7 +14233,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 395 + "dependientes_total": 397 }, "plow": { "iname": "plow", @@ -14560,8 +14683,10 @@ "state": "sealed", "blocked_by": [], "unblocks": 0, - "perfiles": [], - "dependientes_total": 1 + "perfiles": [ + "escritorio-gnome" + ], + "dependientes_total": 2 }, "py3-jinja2": { "iname": "py3-jinja2", @@ -14654,7 +14779,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 314 + "dependientes_total": 316 }, "qrcp": { "iname": "qrcp", @@ -15269,7 +15394,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 266 + "dependientes_total": 268 }, "sassc": { "iname": "sassc", @@ -18043,7 +18168,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 160 + "dependientes_total": 161 }, "wayland-protocols": { "iname": "wayland-protocols", @@ -18071,7 +18196,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 57 + "dependientes_total": 58 }, "websocketd": { "iname": "websocketd", @@ -18552,7 +18677,7 @@ "escritorio-kde", "escritorio-sway" ], - "dependientes_total": 6 + "dependientes_total": 7 }, "xorriso": { "iname": "xorriso", @@ -18991,7 +19116,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 113 + "dependientes_total": 115 }, "zlib-ng": { "iname": "zlib-ng", @@ -19033,7 +19158,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 85 + "dependientes_total": 86 }, "zola": { "iname": "zola", @@ -19092,7 +19217,7 @@ "escritorio-mirada", "escritorio-sway" ], - "dependientes_total": 32 + "dependientes_total": 33 } } } diff --git a/docs/state/drenaje.json b/docs/state/drenaje.json index da2cb9ac..6ba8f2ce 100644 --- a/docs/state/drenaje.json +++ b/docs/state/drenaje.json @@ -31,7 +31,7 @@ }, "escritorio-gnome": { "grafo": "docs/state/build-state-gnome.json", - "nodos": 183, + "nodos": 190, "en_deuda": 0, "ondas": 0, "profundidad": 0, diff --git a/docs/state/targets.toml b/docs/state/targets.toml index 08451521..bf141439 100644 --- a/docs/state/targets.toml +++ b/docs/state/targets.toml @@ -442,7 +442,22 @@ paquetes = [ # con `tar -x` y GNU tar no lee zip, y además el zip es un artefacto que construye EGO a partir # de ese mismo repo. El layout instalado se verificó CONTRA ese zip: idéntico, sin sobras ni # faltantes. + # ⚠ La LISTA de activas no vive en ninguna receta: `enabled-extensions` es un ARRAY y un override + # de GSettings lo escribe entero, así que dos recetas con el suyo no se suman — ganaría la última + # y las otras quedarían instaladas y MUERTAS, sin error. La arma `scripts/gnome/gnome-start-qemu.sh` + # enumerando los uuid presentes en /usr/share/gnome-shell/extensions antes de compilar los + # esquemas. Una receta no puede ser ese sitio: hammer exige `[source]` en toda receta. "gnome-shell-extension-blur-my-shell", + # `dash-to-panel` es la que más cambia el uso diario: junta dash, ventanas y bandeja en una barra. + # `appindicator` devuelve los ICONOS DE BANDEJA que GNOME quitó — sin ella, las apps que usan + # StatusNotifierItem corren y no tienen dónde mostrarse. + "gnome-shell-extension-dash-to-panel", "gnome-shell-extension-appindicator", + # ── Y LA APP QUE GNOME NO INSTALA Y TODO EL MUNDO NECESITA ─────────────────────────────────── + # `gnome-tweaks`: tema, iconos, cursor, tipografías, los botones de minimizar/maximizar que GNOME + # esconde, y el interruptor de las extensiones. Es una app de PYTHON, así que su receta declara + # `python3` y `py3-gobject` como deps de RUNTIME: sin ellas en la imagen se instala y no arranca, + # y ningún build puede delatarlo. + "gnome-tweaks", ] [perfil.escritorio-cosmic] diff --git a/recipes/incoming-gnome/gnome-shell-extension-appindicator.toml b/recipes/incoming-gnome/gnome-shell-extension-appindicator.toml new file mode 100644 index 00000000..572c941a --- /dev/null +++ b/recipes/incoming-gnome/gnome-shell-extension-appindicator.toml @@ -0,0 +1,65 @@ +# appindicator 64 — los ICONOS DE BANDEJA que GNOME quitó del shell. Es la extensión que hace que +# aparezcan en el panel las apps que usan `StatusNotifierItem` / `org.kde.StatusNotifierItem` (y las +# `libappindicator` viejas): clientes de chat, sincronizadores, gestores de portapapeles. Sin ella, +# esas apps corren y no tienen dónde mostrarse. +# +# Tercera extensión del catálogo. El patrón y el porqué de usar el REPO y no el zip de +# extensions.gnome.org están en la cabecera de `gnome-shell-extension-blur-my-shell`. +# El tag `v64` es el que EGO sirve para shell 48, preguntado a su API — ⚠ y acá la pregunta SÍ +# importó: el repo ya tiene `v65`, que es la que se habría tomado por reflejo. +# +# ══ ÉSTA SE CONSTRUYE CON MESON, NO CON UN MAKEFILE ════════════════════════════════════════════ +# Las otras dos son un `pack` y un `make install`; ésta trae `meson.build` con los módulos `gnome` +# e `i18n`, y hace lo mismo que un paquete de distro cuando el prefix NO es local: +# · el árbol va a /share/gnome-shell/extensions// +# · el gschema al directorio GLOBAL /share/glib-2.0/schemas +# · los .mo a /share/locale +# ⚠ `-Dlocal_install=disabled` explícito: la opción viene en `auto`, y en `auto` decide mirando si +# el prefix es /usr/local Y si el uid es 0. Nuestro sandbox corre como root con prefix /usr, así que +# hoy resolvería bien por accidente — pero «funciona por accidente se ve igual que funciona por +# diseño», y si mañana el lab dejara de ser root la instalación se iría a $HOME/.local y el artefacto +# sellaría vacío. +# +# ⚠ `jq` VA EN [deps] AUNQUE LA EXTENSIÓN SEA JAVASCRIPT PURO: `meson.build:22` saca el uuid del +# `metadata.json` con `run_command(jq, '-r', '.uuid', …)` — es una herramienta del sandbox, no una +# librería que se enlace. Sin ella meson corta en el configure. +name = "gnome-shell-extension-appindicator" +version = "64" +# licencia: el `meson.build` declara `license: 'GPL2'` y las cabeceras de los fuentes (extension.js, +# appIndicator.js…) dan la concesión completa: «either version 2 of the License, or (at your option) +# any later version». ⚠ No se dedujo del LICENSE: su apéndice «How to Apply» contiene esa frase +# siempre, así que buscarla ahí da positivo aunque el proyecto sea -only. +license = "GPL-2.0-or-later" + +[source] +repo = "https://github.com/ubuntu/gnome-shell-extension-appindicator" +commit = "c934adc6c97363b8e6bb161ca8d1ac62d1da3d63" # tag v64 (ADR 0006: commit fijo, nunca HEAD) + +[build] +compiler = "zig-cc" +target = "x86_64-linux-musl" +link = "dynamic" + +[build.phases] +configure = "PYTHONPATH=/usr/lib/python3.12/site-packages meson setup output --prefix=/usr --buildtype=release --wrap-mode=nodownload -Dlocal_install=disabled" +compile = "PYTHONPATH=/usr/lib/python3.12/site-packages ninja -C output" +install = ''' +set -e +UUID="appindicatorsupport@rgcjonas.gmail.com" +PYTHONPATH=/usr/lib/python3.12/site-packages DESTDIR=/out meson install -C output --no-rebuild +D="/out/usr/share/gnome-shell/extensions/$UUID" + +# Guardián: se comprueba el RESULTADO, no la intención. Si `local_install` hubiera resuelto a +# «local», esto habría instalado en $HOME/.local y el artefacto sellaría igual, vacío (regla 3 de +# CLAUDE.md — un vacío llega hasta el final diciendo que todo fue bien). +test -s "$D/metadata.json" +test -s "$D/extension.js" +grep -q '"48"' "$D/metadata.json" # falla ruidoso si un bump deja de soportar shell 48 +# El gschema tiene que haber ido al directorio GLOBAL, que es el que compila el lanzador al arrancar. +test -s /out/usr/share/glib-2.0/schemas/org.gnome.shell.extensions.appindicator.gschema.xml +''' + +[deps] +# `jq` es del configure (saca el uuid del metadata.json); `glib` trae glib-compile-schemas para el +# módulo `gnome` de meson y `gettext-tiny` el msgfmt para el módulo `i18n`. +build = ["meson", "samurai", "python3", "pkgconf", "jq", "glib", "pcre2", "libffi", "zlib", "gettext-tiny"] diff --git a/recipes/incoming-gnome/gnome-shell-extension-blur-my-shell.toml b/recipes/incoming-gnome/gnome-shell-extension-blur-my-shell.toml index ae429b33..6657540c 100644 --- a/recipes/incoming-gnome/gnome-shell-extension-blur-my-shell.toml +++ b/recipes/incoming-gnome/gnome-shell-extension-blur-my-shell.toml @@ -81,23 +81,15 @@ for po in po/*.po; do msgfmt -o "$D/locale/$lang/LC_MESSAGES/$UUID.mo" "$po" done -# 4. INSTALADA ≠ ACTIVA. El shell sólo carga las extensiones que estén en la clave -# `org.gnome.shell enabled-extensions`, así que sin esto el artefacto sella, el fichero está en -# la imagen y NO PASA NADA al arrancar — el mismo cuadro de «sellado ≠ instalado» que este repo -# ya se comió con foot, mpv y libnotify, un escalón más abajo. -# Se hace con un override de GSettings, que cambia el DEFAULT sin tocar la config del usuario -# (quien no la quiera la apaga y su dconf gana). El `gnome-start-qemu.sh` corre -# `glib-compile-schemas` sobre este directorio en el primer arranque, así que el override entra. -# -# ⚠ TRAMPA PARA LA SEGUNDA EXTENSIÓN: `enabled-extensions` es un ARRAY y esto lo escribe ENTERO. -# Si mañana otra receta instala su propio override para la misma clave, no se suman: gana el -# fichero que compile último (orden alfabético) y la otra extensión queda instalada y muerta, -# sin error. Cuando llegue la segunda, la lista pasa a un solo sitio que las liste a todas. -mkdir -p /out/usr/share/glib-2.0/schemas -cat > /out/usr/share/glib-2.0/schemas/60_hammer-extensiones.gschema.override </ +# · y en modo «system» SACA de ahí `schemas/` y `locale/` para ponerlos en los directorios +# GLOBALES: /usr/share/glib-2.0/schemas y /usr/share/locale. +# Se usa su install en vez de copiar a mano: es upstream quien decide qué entra y qué no. +# +# ⚠ Que el gschema termine en el directorio GLOBAL no es un detalle: lo compila el mismo +# `glib-compile-schemas` que corre el lanzador al arrancar, junto con los del shell. Por eso esta +# receta NO necesita compilarlo ella (y el Makefile igual lo compila para el `_build`). +# +# ⚠ `VERSION=73` SE PASA A MANO, y no es cosmético. Sin ella el Makefile hace +# `git describe --tags HEAD` para deducirla, y el árbol se materializa con `git archive`, SIN `.git` +# ⇒ la orden falla y `metadata.json` queda con el `"version": 9999` de marcador que trae el repo. +# Es la misma razón por la que la receta de `tzdata` pasa `VERSION=2026b`. +name = "gnome-shell-extension-dash-to-panel" +version = "73" +# licencia: el fichero COPYING del commit pineado es el texto del GPL v2, y el `metadata.json` de +# EGO no declara licencia. ⚠ La concesión está en la CABECERA de los fuentes (src/extension.js y +# compañía): «either version 2 of the License, or (at your option) any later version» ⇒ -or-later. +# No se dedujo del COPYING: su apéndice «How to Apply» contiene esa frase SIEMPRE, así que buscarla +# ahí da positivo aunque el proyecto sea -only (la trampa que ya está documentada en el repo). +license = "GPL-2.0-or-later" + +[source] +repo = "https://github.com/home-sweet-gnome/dash-to-panel" +commit = "b31cbe1f3c9fa997b954b71199563fbedc2f3446" # tag v73 (ADR 0006: commit fijo, nunca HEAD) + +[build] +compiler = "zig-cc" +target = "x86_64-linux-musl" +link = "dynamic" + +[build.phases] +# Nada que compilar en el sentido de C: `make all` sólo compila el gschema y los catálogos .po. +configure = "true" +compile = 'make VERSION=73' +install = ''' +set -e +UUID="dash-to-panel@jderose9.github.com" +make install DESTDIR=/out VERSION=73 +D="/out/usr/share/gnome-shell/extensions/$UUID" + +# Guardián: el `install` de upstream mueve cosas de sitio según DESTDIR, así que se comprueba el +# resultado y no la intención. Un artefacto a medias sella igual y el fallo sale recién al arrancar +# el escritorio (regla 3 de CLAUDE.md). +test -s "$D/metadata.json" +test -s "$D/extension.js" +grep -q '"version": 73' "$D/metadata.json" # falla si el sed de VERSION no corrió (quedaría 9999) +grep -q '"48"' "$D/metadata.json" # falla si un bump deja de soportar shell 48 +# El gschema tiene que haber ido al directorio GLOBAL, que es lo que compila el lanzador. +test -s /out/usr/share/glib-2.0/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml +''' + +[deps] +# `make` para el Makefile, `glib` por glib-compile-schemas y `gettext-tiny` por msgfmt. Ninguna es +# una librería que la extensión enlace: no enlaza nada, es JavaScript. +build = ["make", "glib", "pcre2", "libffi", "zlib", "gettext-tiny"] diff --git a/recipes/incoming-gnome/gnome-tweaks.toml b/recipes/incoming-gnome/gnome-tweaks.toml new file mode 100644 index 00000000..3ef6fd9d --- /dev/null +++ b/recipes/incoming-gnome/gnome-tweaks.toml @@ -0,0 +1,97 @@ +# gnome-tweaks 46.1 — el «tenés que instalarte esto» clásico de GNOME. Es la app que expone lo que +# el shell no deja tocar desde Configuración: tema, iconos, cursor, tipografías, botones de la barra +# de título (minimizar/maximizar, que GNOME esconde), comportamiento del touchpad, aplicaciones al +# inicio y el interruptor de las extensiones. +# +# ⚠ POR QUÉ 46.1 Y NO LA ÚLTIMA. gnome-tweaks NO tiene release 47 ni 48: la lista de +# download.gnome.org salta de 46.1 a 49.rc/49.0. Nuestro shell es el 48, así que la que corresponde +# es la ÚLTIMA anterior — la 49 apunta a la serie 49 de libadwaita/GTK y no hay motivo para +# arriesgar APIs nuevas contra un escritorio 48. Comprobado en el `cache.json` del propio servidor, +# no en una lista de memoria. +# +# ══ NO CUESTA NINGUNA RECETA NUEVA, y eso hubo que medirlo ═════════════════════════════════════ +# Su `meson.build:22-28` declara las versiones mínimas de runtime en un bloque explícito «to make +# packaging more obvious», y las siete se cumplen con lo que ya está sellado: +# glib >= 2.78 ✓ 2.88 gobject-introspection >= 1.78 ✓ 1.84 +# gtk4 >= 4.10 ✓ libadwaita-1 >= 1.4 ✓ 1.7.6 +# pygobject-3.0 >= 3.46 ✓ 3.50 gudev-1.0 >= 238 ✓ 238 +# gsettings-desktop-schemas >= 46 ✓ 48.0 +# +# ⚠ El `pygobject-3.0` de esa lista lo provee `py3-gobject`, que YA ESTABA en el corpus con otro +# nombre —la escribió el frente GNOME para el build de libgweather— y publica `pygobject-3.0.pc` +# (verificado en su artefacto). Sin mirar eso, esta receta parecía arrastrar una cadena de Python +# entera. El nombre no es el hecho, otra vez. +# +# ⚠ Y NO necesita pycairo, que es la parte que `py3-gobject` construye con `-Dpycairo=disabled`: +# ningún fichero de `gtweak/` importa `cairo` (verificado sobre el tarball). +# +# ══ ES UNA APP DE PYTHON: SUS DEPS DE RUNTIME NO SON LAS DE BUILD ══════════════════════════════ +# No se enlaza nada — `gnome-tweaks` es un script que importa `gi.repository`. Si `python3` y +# `py3-gobject` no están EN LA IMAGEN, la app se instala y no arranca, y el build no puede +# delatarlo. Por eso van en `[deps] runtime`, que es exactamente el caso de `xkbcomp` en xwayland. +name = "gnome-tweaks" +version = "46.1" +# licencia: no hace falta interpretar nada — los fuentes llevan etiqueta SPDX explícita. +# `gtweak/tweakmodel.py:2`: «SPDX-License-Identifier: GPL-3.0+», que es la forma vieja de +# `GPL-3.0-or-later`. El tarball no trae COPYING sino un directorio `LICENSES/`. +license = "GPL-3.0-or-later" + +[source] +tarball = "https://download.gnome.org/sources/gnome-tweaks/46/gnome-tweaks-46.1.tar.xz" +sha256 = "2f192a7085fbd6843ecf825716d9da21ec9272029149ea35f3e159e0ac309b80" + +[build] +compiler = "zig-cc" +target = "x86_64-linux-musl" +link = "dynamic" + +[build.phases] +# ⚠ SE SACA EL ÁRABE, y NO es una decisión sobre el idioma: es un BUG del `msgfmt` de +# `gettext-tiny`, el único que hay en el corpus. Revienta con SIGILL —«index 6 out of bounds for +# type 'size_t[6]'», exit 132— al compilar un mensaje con SEIS formas plurales, que es justo lo que +# tiene el árabe. Reproducido FUERA de la receta, con el binario sellado: +# msgfmt -o /tmp/x.mo po/ar.po → panic, exit 132, y deja un .mo de 0 bytes +# No es el idioma: `blur-my-shell` compila su `ar.po` sin problema porque no tiene NINGÚN mensaje +# plural (msgstr[5] = 0 apariciones); el de tweaks tiene exactamente uno (msgstr[5] = 1). +# ⚠ ARREGLARLO DE VERDAD ES OTRA UNIDAD DE TRABAJO: `gettext-tiny` la usan 108 recetas, así que +# tocarla re-hashea el corpus entero. Acá se pierde la traducción al árabe de UNA app y se deja el +# diagnóstico escrito; lo que NO se hace es callarlo. +configure = "sed -i '/^ar$/d' po/LINGUAS && PKG_CONFIG_PATH=/usr/lib/pkgconfig PYTHONPATH=/usr/lib/python3.12/site-packages meson setup output --prefix=/usr --buildtype=release --wrap-mode=nodownload" +compile = "PYTHONPATH=/usr/lib/python3.12/site-packages ninja -C output" +install = ''' +set -e +PYTHONPATH=/usr/lib/python3.12/site-packages DESTDIR=/out meson install -C output --no-rebuild + +# Guardián: `gnome.post_install()` de meson se SALTA sus pasos cuando DESTDIR está seteado (lo dice +# en el log: «Skipping custom install script because DESTDIR is set»), así que lo que hay que +# comprobar es lo que SÍ tiene que quedar en el árbol. El gschema va al directorio GLOBAL, que es el +# que compila el lanzador al arrancar — igual que el de las extensiones. +test -s /out/usr/bin/gnome-tweaks +test -s /out/usr/share/glib-2.0/schemas/org.gnome.tweaks.gschema.xml +test -s /out/usr/share/applications/org.gnome.tweaks.desktop +# El módulo Python tiene que estar donde el intérprete lo busque, no en cualquier lado. +test -d /out/usr/lib/python3.12/site-packages/gtweak +''' + +[deps] +# ⚠ RUNTIME, no build: es una app de Python que importa gi.repository. Sin estas dos en la imagen se +# instala y no arranca, y ningún build lo delata. +runtime = ["python3", "py3-gobject"] +# La clausura ENTERA, que las deps de hammer no son transitivas. Copiada de la que ya usa +# xdg-desktop-portal-gnome, que es el otro consumidor de gtk4+libadwaita de esta cola. +build = ["meson", "samurai", "python3", "pkgconf", "gettext-tiny", "gobject-introspection", + "py3-gobject", "gsettings-desktop-schemas", "gtk4", "libadwaita", "glib", "glib-introspected", + "gi-foreign-girs", "libgudev", "libudev-zero", + "cairo-shared", "pango", "graphene", "libepoxy", "wayland", "wayland-protocols", "libdrm", + "harfbuzz", "fribidi", "libpng-shared", "pixman", "freetype-shared", "expat", "libffi", "pcre2", + "zlib-shared", "gdk-pixbuf", "libjpeg-turbo-shared", "libtiff-shared", "mesa", + "fontconfig-shared", "xkeyboard-config", "iso-codes", "libseccomp", + # ⚠ `appstream` y su cola NO son un capricho: `libadwaita-1.pc` la lleva en `Requires`, así que + # pkg-config la resuelve TRANSITIVAMENTE y sin ella el configure corta con «Package 'appstream', + # required by 'libadwaita-1', not found» — culpando a libadwaita, que está perfectamente + # instalada. Es el patrón `.pc Requires` → `[deps].build` que el corpus ya tiene documentado. + "appstream", "libxmlb", "curl", "openssl", "libxml2-shared", "libyaml-shared", "zstd", + # `desktop-file-utils` por `update-desktop-database`: su `gnome.post_install()` lo pide como + # PROGRAMA y meson corta en el configure si no está (no es una librería que se enlace). La receta + # ya existe y encima está en el perfil desde el 2026-09-09. + "desktop-file-utils"] diff --git a/scripts/gnome/gnome-start-qemu.sh b/scripts/gnome/gnome-start-qemu.sh index bc4de733..a019ec1f 100755 --- a/scripts/gnome/gnome-start-qemu.sh +++ b/scripts/gnome/gnome-start-qemu.sh @@ -104,6 +104,45 @@ chmod 700 "$XDG_RUNTIME_DIR" [ -s /etc/machine-id ] || cat /proc/sys/kernel/random/uuid 2>/dev/null | tr -d - > /etc/machine-id cp -f /etc/machine-id /var/lib/dbus/machine-id 2>/dev/null || true +# ── ACTIVAR LAS EXTENSIONES QUE LA IMAGEN TRAE ──────────────────────────────────────────────── +# Una extensión INSTALADA no hace nada: el shell sólo carga las que estén en +# `org.gnome.shell enabled-extensions`. Sin esto, empaquetarlas sella artefactos que la imagen +# lleva y nadie ejecuta — «sellado ≠ instalado», un escalón más abajo. +# +# ⚠ POR QUÉ LA LISTA SE ARMA ACÁ Y NO EN CADA RECETA. `enabled-extensions` es un ARRAY: un override +# lo escribe ENTERO. Si cada receta trajera el suyo, no se sumarían — ganaría el fichero que +# compile último (orden alfabético) y las demás quedarían instaladas y MUERTAS, sin un solo error. +# La lista tiene que existir en un único sitio, y una receta no puede ser ese sitio: hammer exige +# `[source]` en toda receta (comprobado: «missing field `source`»), así que no hay forma de escribir +# una receta de pura política sin inventarle una fuente. Acá, donde ya se compilan los esquemas, sí. +# +# La política es «lo que la imagen instala, se activa»: el catálogo sólo empaqueta extensiones que +# queremos encendidas. Quien no quiera una la apaga desde su dconf, que gana sobre el default. +EXT_DIR=/usr/share/gnome-shell/extensions +OVR="$GSETTINGS_SCHEMA_DIR/60_hammer-extensiones.gschema.override" +if [ -d "$EXT_DIR" ]; then + uuids="" + for d in "$EXT_DIR"/*/; do + [ -s "$d/metadata.json" ] || continue + u="$(basename "$d")" + uuids="$uuids${uuids:+, }'$u'" + done + if [ -n "$uuids" ]; then + nuevo_ovr="[org.gnome.shell] +enabled-extensions=[$uuids]" + # Si la lista cambió respecto de la compilada, hay que RECOMPILAR: el bloque de abajo sólo + # compila cuando falta `gschemas.compiled`, así que un override nuevo sobre una imagen ya + # arrancada quedaría ignorado en silencio. + if [ ! -f "$OVR" ] || [ "$(cat "$OVR")" != "$nuevo_ovr" ]; then + printf '%s\n' "$nuevo_ovr" > "$OVR" + rm -f "$GSETTINGS_SCHEMA_DIR/gschemas.compiled" + fi + say "extensiones a activar: $uuids" + else + say "no hay extensiones instaladas en $EXT_DIR" + fi +fi + # gschemas.compiled: meson NO lo genera cuando DESTDIR está seteado (lo dice en el log del build: # "Skipping custom install script because DESTDIR is set"). Sin él, GSettings aborta al primer # g_settings_new() y el shell no llega ni a abrir el DRM. Se compila acá, en el primer arranque.