# blur-my-shell 72 — PRIMERA extensión de GNOME Shell del catálogo, y la que fija el patrón. # # ══ POR QUÉ EXISTE ═════════════════════════════════════════════════════════════════════════════ # GNOME manda a propósito una cáscara mínima y el ecosistema la completa con extensiones. Sin # ninguna empaquetada, nuestra imagen de GNOME es esa cáscara: el shell SÍ sabe cargarlas # —`ui/extensionSystem.js` va en el gresource sin opción que lo apague, y su gschema sellado trae # `enabled-extensions`— pero no hay ninguna que cargar. # # ══ LA FUENTE ES EL REPO DEL AUTOR, NO EL ZIP DE extensions.gnome.org ══════════════════════════ # EGO publica un `.zip` por versión con URL inmutable, que parecía la fuente obvia. Dos razones # para no usarlo: # 1. **takana no lo sabe abrir.** El fetch extrae con `tar -x` (fetch.rs:581) y GNU tar no lee # zip — comprobado: «This does not look like a tar archive». Ninguna receta del corpus usa # .zip. Soportarlo sería tocar el fetcher y sumarle una herramienta al host. # 2. **Y aunque lo abriera, no es la fuente.** El zip de EGO es un ARTEFACTO que construye EGO a # partir de este mismo repo. Pinear el zip es pinear el binario de un tercero; pinear el # commit es pinear el código del autor, que es lo que hace el resto del corpus. # El tag `v72` es el que EGO sirve para shell 48: verificado preguntándole # (`extension-info/?uuid=blur-my-shell@aunetx&shell_version=48` → version 72) y confirmado en el # `metadata.json` del propio zip, que declara shell-version ['46','47','48','49','50']. # ⚠ Eso hay que preguntarlo por extensión, no asumirlo: nixpkgs va por GNOME 50 y hay extensiones # que ya sólo declaran el major nuevo. # # ══ SE INSTALA A MANO Y NO CON `gnome-extensions pack` ═════════════════════════════════════════ # El `make build` de upstream llama a `gnome-extensions pack`, que es el CLI `extensions-tool` del # propio gnome-shell — y nuestra receta del shell va con `-Dextensions_tool=false`. Encenderlo # costaría una receta nueva (gnome-autoar) y re-hashear gnome-shell entero. # No hace falta: `pack` sólo arma el zip que después alguien descomprime. Lo que el shell lee es un # DIRECTORIO en /usr/share/gnome-shell/extensions//, así que se copia el árbol directamente. # El layout no se inventó: se leyó del zip de EGO v72, que es la salida de ese mismo `pack` — # `src/*` va a la raíz, `resources/icons`→`icons/`, `resources/ui`→`ui/`, más metadata.json y # LICENSE. # # ⚠ El zip de EGO **no trae `gschemas.compiled`** (verificado): trae el .xml y quien instala # compila. Por eso `glib-compile-schemas` va en el install y `glib` en [deps] — sin eso la # extensión carga y muere al abrir sus preferencias, que es el fallo que no se ve al sellar. name = "gnome-shell-extension-blur-my-shell" version = "72" # licencia: el README del commit pineado lo dice con todas las letras — «This program is distributed # under the terms of the GNU General Public License, version 3 or later». ⚠ La evidencia NO es el # fichero LICENSE: ahí sólo está el texto del GPL, y su apéndice «How to Apply» contiene la frase # «either version 3 … or any later version» SIEMPRE, así que grepearla da positivo aunque el # proyecto sea -only. Y el árbol JS no lleva cabecera de licencia en ningún fichero (verificado). license = "GPL-3.0-or-later" [source] repo = "https://github.com/aunetx/blur-my-shell" commit = "444df605b34529dfab7be77d0f434bf54a6dd4cc" # tag v72 (ADR 0006: commit fijo, nunca HEAD) [build] compiler = "zig-cc" target = "x86_64-linux-musl" link = "dynamic" [build.phases] # No hay nada que compilar: son JS, XML de esquema y catálogos de traducción. configure = "true" compile = "true" install = ''' set -e UUID="blur-my-shell@aunetx" D="/out/usr/share/gnome-shell/extensions/$UUID" mkdir -p "$D" # 1. El árbol, con la MISMA forma que produce `gnome-extensions pack` (leída del zip de EGO v72). cp -r src/. "$D/" cp metadata.json LICENSE "$D/" cp -r resources/icons "$D/icons" cp -r resources/ui "$D/ui" # 2. El esquema: se copia el .xml Y se compila. El shell abre las preferencias con # Gio.SettingsSchemaSource.new_from_directory, que necesita el gschemas.compiled. mkdir -p "$D/schemas" cp schemas/*.gschema.xml "$D/schemas/" glib-compile-schemas "$D/schemas" # 3. Traducciones: un .mo por idioma, nombrado por el UUID (así lo busca el shell). for po in po/*.po; do lang="$(basename "$po" .po)" mkdir -p "$D/locale/$lang/LC_MESSAGES" msgfmt -o "$D/locale/$lang/LC_MESSAGES/$UUID.mo" "$po" done # 4. ⚠ INSTALADA ≠ ACTIVA, y eso NO se resuelve acá. El shell sólo carga lo que esté en # `org.gnome.shell enabled-extensions`, que es un ARRAY: un override de GSettings lo escribe # ENTERO. Si cada receta trajera el suyo no se sumarían — ganaría el que compile último y las # demás quedarían instaladas y MUERTAS, sin un solo error. Por eso la lista se arma en UN sitio, # `scripts/gnome/gnome-start-qemu.sh`, que ya compila los esquemas al arrancar y ahora enumera # los uuid presentes en /usr/share/gnome-shell/extensions. La política es «lo que la imagen # instala, se activa»; quien no quiera una la apaga desde su dconf, que 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.) # 5. Guardián barato: si el árbol quedara vacío o sin metadata, el artefacto sellaría igual y el # fallo aparecería recién al arrancar el escritorio (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" test -s "$D/schemas/gschemas.compiled" grep -q '"48"' "$D/metadata.json" # falla ruidoso si un bump de versión deja de soportar shell 48 ''' [deps] # `glib` por glib-compile-schemas y `gettext-tiny` por msgfmt: las dos son herramientas del # sandbox, no librerías que la extensión enlace (no enlaza nada: es JavaScript). build = ["glib", "pcre2", "libffi", "zlib", "gettext-tiny"]