tawasuyu

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 1569Shell 203Rust 109Markdown 993728 Definiciones

⎇ 4190c7b43e5bd323a9b166340cfa16cd324ca2e4 scripts/licencias-desambiguar.sh Shell · 100 líneas · 6.6 KB Historia crudo

licencias: resolver -only vs -or-later CON LA CITA — y tres «pruebas» que no probaban nada 2c2ee951d · sergio ·

1#!/usr/bin/env bash
2# licencias-desambiguar.sh — resuelve `-only` vs `-or-later` en los SPDX obsoletos, CON LA CITA.
3#
4# ── EL PROBLEMA QUE CIERRA ─────────────────────────────────────────────────────────────────────
5# La API de licencias de GitHub devuelve identificadores obsoletos (`GPL-2.0`, `GPL-3.0`, `LGPL-2.1`,
6# `AGPL-3.0`). SPDX los declaró obsoletos **porque son ambiguos**: no dicen si el proyecto concede
7# «sólo esta versión» o «ésta o cualquier posterior». La diferencia no es cosmética — decide con qué
8# se puede combinar el paquete y bajo qué términos puede redistribuirlo quien lo reciba.
9#
10# ── POR QUÉ NO SE PUEDE MIRAR EL COPYING (la trampa) ───────────────────────────────────────────
11# El fichero COPYING de la GPL es **idéntico** en los dos casos: es el texto de la licencia, no la
12# concesión. Y encima su apéndice «cómo aplicar la licencia a tus programas» contiene literalmente la
13# frase «or (at your option) any later version» ⇒ buscarla en el COPYING da SIEMPRE positivo y
14# parecería evidencia siendo texto de plantilla. Es la misma trampa que la regla del `.a` no-PIC,
15# donde `grep R_X86_64_32` contaba reubicaciones de `.debug_*` y mentía.
16#
17# La concesión vive en las **cabeceras de los fuentes** y en el README. Por eso acá se busca la frase
18# en TODO el repo y se **descartan explícitamente** COPYING/LICENSE/LICENCE: si sólo aparece ahí, no
19# hay evidencia y el paquete se deja para el humano.
20#
21# ── SE GUARDA LA CITA, NO SÓLO EL VEREDICTO ────────────────────────────────────────────────────
22# Cada línea de salida lleva el fichero y la frase exacta que decidió. Una licencia es una afirmación
23# legal: quien la revise tiene que poder ver POR QUÉ dice lo que dice sin repetir el trabajo. Un
24# veredicto sin su prueba obliga a confiar; con la prueba, se audita en diez segundos.
25#
26# Ejemplo real (htop): yo lo habría puesto `-only` de memoria. `htop.c` dice «Released under the GNU
27# GPLv2+» y el README «version 2 (GPL-2.0) or, at your option, any later version» ⇒ es `-or-later`.
28# La memoria se equivoca; la cita no.
29#
30# Uso:  scripts/licencias-desambiguar.sh     (escribe docs/licencias-desambiguadas.tsv)
31set -uo pipefail
32ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
33SALIDA="${SALIDA:-docs/licencias-desambiguadas.tsv}"
34command -v gh >/dev/null && gh auth status >/dev/null 2>&1 || { echo "!!  'gh' ausente o sin auth"; exit 1; }
35TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT
36
37# Las ambiguas con fuente en GitHub. (La búsqueda de código de GitHub sólo funciona sobre GitHub;
38# el resto se queda para el humano, y eso se dice al final en vez de disimularlo.)
39./scripts/licencias.sh --revisar 2>/dev/null | while IFS=$'\t' read -r n lic; do
40  [ -z "${n:-}" ] && continue
41  f=$(ls "recipes/$n.toml" 2>/dev/null | head -1)
42  [ -z "$f" ] && f=$(ls recipes/incoming-*/"$n.toml" 2>/dev/null | head -1)
43  [ -z "$f" ] && continue
44  u=$(grep -m1 -E '^[[:space:]]*(tarball|repo)[[:space:]]*=' "$f" 2>/dev/null)
45  case "$u" in *github.com*) ;; *) continue ;; esac
46  slug=$(printf '%s\n' "$u" | sed -E 's#.*github\.com[:/]+([^/"]+)/([^/"]+).*#\1/\2#; s/\.git$//')
47  case "$slug" in */*) printf '%s\t%s\t%s\n' "$n" "$lic" "$slug" ;; esac
48done | sort -u > "$TMP/obj.tsv"
49echo "==> ambiguas con fuente en GitHub: $(wc -l < "$TMP/obj.tsv")"
50
51# En SERIE: la búsqueda de código de GitHub va a 10 consultas por minuto. Paralelizar sólo consigue
52# que devuelva 403 y que la mitad se pierda en silencio, que es peor que tardar.
53: > "$TMP/ok.tsv"; : > "$TMP/no.tsv"
54while IFS=$'\t' read -r n lic slug; do
55  paths=$(gh api -X GET search/code -f q="repo:$slug \"any later version\"" \
56            --jq '[.items[].path] | join(" ")' 2>/dev/null)
57  # Tres clases de fichero que PARECEN evidencia y no lo son. Las tres aparecieron en la primera
58  # corrida, y sólo se vieron porque guardamos la cita:
59  #   · ficheros de licencia  → la frase es plantilla del propio COPYING (ver cabecera);
60  #   · FIXTURES DE TEST      → `caligula` "probaba" ser GPL-3.0-or-later por una frase dentro de
61  #                             `checks/headless/expected.iso`, una imagen de prueba;
62  #   · CÓDIGO VENDORIZADO    → `libnl` citaba `include/linux-private/linux/seg6.h`, una cabecera del
63  #                             KERNEL incrustada. La licencia del kernel no es la de libnl.
64  util=""
65  for p in $paths; do
66    bn=$(basename "$p" | tr '[:upper:]' '[:lower:]')
67    case "$bn" in copying*|license*|licence*|copyright) continue ;; esac
68    case "$p" in
69      *test*|*Test*|*fixture*|*checks/*|*testdata/*|*.iso|*.bin|*.img) continue ;;
70      *vendor/*|*third_party/*|*3rdparty/*|*linux-private/*|*/deps/*|*external/*) continue ;;
71    esac
72    util="$p"; break
73  done
74  if [ -z "$util" ]; then printf '%s\t%s\t%s\n' "$n" "$lic" "$slug" >> "$TMP/no.tsv"; sleep 6; continue; fi
75  cita=$(gh api "repos/$slug/contents/$util" --jq .content 2>/dev/null | base64 -d 2>/dev/null \
76           | grep -m1 -i "any later version" | tr -s ' \t' ' ' | sed 's/^ *//' | cut -c1-120)
77  # ── LA CITA TIENE QUE HABLAR DE LA MISMA VERSIÓN QUE LA LICENCIA DECLARADA ───────────────────
78  # `lm-sensors` estaba declarado GPL-2.0 y su cita decía «version 2.1 of the License», que es la
79  # LGPL: la frase era real pero NO sostenía lo que se le atribuía. Una evidencia que habla de otra
80  # licencia no es evidencia de ésta.
81  ver=$(printf '%s' "$lic" | sed -E 's/^A?L?GPL-([0-9.]+).*/\1/')
82  case "$cita" in
83    *"$ver"*) ;;
84    *) printf '%s\t%s\t%s\n' "$n" "$lic" "$slug" >> "$TMP/no.tsv"; sleep 6; continue ;;
85  esac
86  nuevo=$(printf '%s' "$lic" | sed -E 's/^(A?L?GPL-[0-9.]+)$/\1-or-later/')
87  printf '%s\t%s\t%s :: %s\n' "$n" "$nuevo" "$util" "${cita:-(sin cita legible)}" >> "$TMP/ok.tsv"
88  sleep 6
89done < "$TMP/obj.tsv"
90
91N=$(wc -l < "$TMP/ok.tsv"); M=$(wc -l < "$TMP/no.tsv")
92{
93  echo "# licencias-desambiguadas.tsv — GENERADO por scripts/licencias-desambiguar.sh."
94  echo "# Resuelve -only vs -or-later buscando la concesión FUERA del COPYING (donde la frase es"
95  echo "# plantilla y daría siempre positivo). Tercera columna: fichero :: cita que lo decidió."
96  echo "# Resueltas $N · sin evidencia (quedan para el humano) $M"
97  sort "$TMP/ok.tsv"
98} > "$SALIDA"
99echo "==> resueltas $N · sin evidencia $M → $SALIDA"
100[ "$M" -gt 0 ] && { echo "==> sin evidencia:"; cut -f1 "$TMP/no.tsv" | tr '\n' ' '; echo; }