#!/bin/bash
# subir-paquetes: publica en el servidor de descargas lo que deja hacer-pkg
# (.deb, .rpm, .tgz, .tar.gz, .summa, cada uno con su .md5) y decide cual es
# la version estable. Pedido del autor, 07/10/2026.
#
# El directorio de descargas (estructura pedida por el autor, 07/10/2026):
#
#   viejos/              lo que habia antes de esta estructura
#   0-README-como-instalar  guia publica de instalacion
#   installsumma.sh      instala summapack, lo que hace falta para instalar
#   bajar-paquetes       cualquier paquete, con bajar-paquetes (autonomo)
#   diccionariodepaquetes  y el diccionario
#   PROYECTO.summa       el .summa de la version estable de cada proyecto
#   PROYECTO/            los paquetes estables del proyecto (.deb, .rpm,
#                        .tgz, .tar.gz): solo eso, para que se vea claro
#   PROYECTO/otros/      todo lo demas: los .md5, lo inestable, las versiones
#                        anteriores, los .summa con version, y mientras
#                        haya algo inestable, PAQ_UNSTABLE... (enlace a la
#                        ultima subida)
#
# PROYECTO es el del .summa: libtabular2-0, libtabular2-dev y tabular van en
# tabular2/. La version estable la dice PROYECTO.summa (VERSION="6.0-38",
# lo agrega --estable). El nombre fijo de lo inestable cambia la version por
# UNSTABLE: calcula_6.0-38_amd64.deb -> calcula_UNSTABLE_amd64.deb,
# calcula-6.0-38.x86_64.rpm -> calcula-UNSTABLE.x86_64.rpm. (Los _last de
# antes quedaron en viejos/; ya no se usan.)
#
#   subir-paquetes [--prueba] [--forzar] ARCHIVO...
#       sube cada archivo con su .md5 a PROYECTO/otros/ y apunta
#       PAQ_UNSTABLE... a el. El proyecto de cada paquete sale del .summa
#       que va entre los archivos (NOMBRE_VERSION.summa, lo deja hacer-pkg)
#       o del .summa del directorio del archivo. Lo que ya esta con el mismo
#       md5 no se vuelve a subir (salvo --forzar); si esta distinto, si.
#   subir-paquetes --estable [--prueba] PROYECTO...
#       lo que hoy es UNSTABLE pasa a estable: los paquetes van a PROYECTO/,
#       los estables anteriores vuelven a PROYECTO/otros/, el .summa se copia
#       arriba como PROYECTO.summa con VERSION="..." y los PAQ_UNSTABLE...
#       desaparecen (hasta que se suba otra version).
#   subir-paquetes --lista [PROYECTO...]
#       lo que hay en el servidor
#   subir-paquetes --reorganizar [--prueba]
#       una vez: pasa a viejos/ todo lo que no sea de esta estructura
#
# El servidor, en el entorno o en ~/.config/simusol/subir (VARIABLE=valor):
#   SUBIR_SERVIDOR   simusol.org ('local': un directorio de esta maquina,
#                    para probar)
#   SUBIR_USUARIO    www-data (en simusol.org no entra por ssh: se usa un
#                    usuario del grupo www-data, ver PAQUETES.md)
#   SUBIR_DIR        /var/www/simusol.org/public_html/downloads
#
# Es parte de summapack (siru/summapack/bin); se instala con el.
# Documentacion: siru/summapack/PAQUETES.md.
set -euo pipefail

# ~/.config/simusol/subir solo completa lo que no venga en el entorno: el
# entorno manda (07/10/2026: al reves, una prueba con SUBIR_SERVIDOR=local
# termino corriendo contra el servidor real)
for _v in SUBIR_SERVIDOR SUBIR_USUARIO SUBIR_DIR; do eval "_entorno_$_v=\${$_v-}"; done
[ -f "$HOME/.config/simusol/subir" ] && . "$HOME/.config/simusol/subir"
for _v in SUBIR_SERVIDOR SUBIR_USUARIO SUBIR_DIR; do eval "[ -z \"\$_entorno_$_v\" ] || $_v=\$_entorno_$_v"; done
SERVIDOR=${SUBIR_SERVIDOR:-simusol.org}
USUARIO=${SUBIR_USUARIO:-www-data}
DIR=${SUBIR_DIR:-/var/www/simusol.org/public_html/downloads}

prueba=0; forzar=0; modo=subir; args=()
while [ $# -gt 0 ]; do
    case "$1" in
        --prueba)      prueba=1 ;;
        --forzar)      forzar=1 ;;
        --estable)     modo=estable ;;
        --lista)       modo=lista ;;
        --reorganizar) modo=reorganizar ;;
        -h|--help)     sed -n '2,45s/^# \{0,1\}//p' "$0"; exit 0 ;;
        -*)            echo "subir-paquetes: no conozco $1" >&2; exit 2 ;;
        *)             args+=("$1") ;;
    esac
    shift
done

# un script en el servidor (o aca, con SUBIR_SERVIDOR=local), con PRUEBA
# para que solo muestre lo que haria; los argumentos van despues de --
remoto() {
    local script=$1; shift
    if [ "$SERVIDOR" = local ]; then
        PRUEBA=$prueba bash -s -- "$DIR" "$@" <<< "$script"
    else
        ssh "$USUARIO@$SERVIDOR" "PRUEBA=$prueba bash -s -- '$DIR' $(printf "'%s' " "$@")" <<< "$script"
    fi
}
copiar() {   # copiar DESTINO_RELATIVO ARCHIVOS...
    local dest=$1; shift
    if [ $prueba = 1 ]; then echo "  [prueba] copiar $* -> $SERVIDOR:$DIR/$dest/"; return 0; fi
    if [ "$SERVIDOR" = local ]; then cp "$@" "$DIR/$dest/"; else scp -q "$@" "$USUARIO@$SERVIDOR:$DIR/$dest/"; fi
}

# lo comun de los scripts remotos
COMUN='set -eu
D=$1; shift
hacer() { if [ "$PRUEBA" = 1 ]; then echo "  [prueba] $*"; else "$@"; fi; }
cd "$D"
'

# el nombre fijo de un archivo: la version por $2 (UNSTABLE), conservando la
# marca de la distribucion (tabular-2.0-14.fedora.x86_64.rpm ->
# tabular-UNSTABLE.fedora.x86_64.rpm; tabular_2.0-14+arch_amd64.tgz ->
# tabular_UNSTABLE+arch_amd64.tgz), para que no se pisen los de Ubuntu
# con los compilados en otra distribucion (siru/summapack/distros)
fijo() {
    local f="$1" v="$2"
    case "$f" in
        *.rpm)  echo "$f" | sed -E "s/^(.+)-[^-]+-[0-9]+(\.[a-z][a-z0-9]*)?\.([^.]+)\.rpm$/\1-$v\2.\3.rpm/" ;;
        *_*_*)  echo "$f" | sed -E "s/^([^_]+)_[^_+]+(\+[^_]+)?_(.+)$/\1_${v}\2_\3/" ;;
        *_*)    echo "$f" | sed -E "s/^([^_]+)_[^_]+\.(tar\.gz|summa|tgz)$/\1_${v}.\2/" ;;
        *)      echo "$f" ;;
    esac
}
# el paquete de un archivo
paquete() {
    case "$1" in
        *.rpm) echo "$1" | sed -E 's/^(.+)-[^-]+-[^-]+\.[^.]+\.rpm$/\1/' ;;
        *)     echo "${1%%_*}" ;;
    esac
}
# los paquetes de un .summa (sin ejecutarlo)
paquetes_de() { sed -n 's/^PACKAGES="\(.*\)"$/\1/p' "$1"; }

case $modo in
reorganizar)
    remoto "$COMUN"'
hacer mkdir -p viejos
n=0
for f in * .[!.]*; do
    [ -e "$f" ] || [ -L "$f" ] || continue
    case "$f" in viejos|0-README-como-instalar|installsumma.sh|bajar-paquetes|diccionariodepaquetes|fuentesexternas) continue ;; *.summa) [ -f "${f%.summa}/otros/.estructura" ] && continue ;; esac
    [ -d "$f" ] && [ -f "$f/otros/.estructura" ] && continue
    hacer mv -- "$f" viejos/
    n=$((n + 1))
done
echo "a viejos/: $n"
'
    ;;
subir)
    [ ${#args[@]} -gt 0 ] || { echo "uso: subir-paquetes [--prueba] [--forzar] ARCHIVO..." >&2; exit 2; }
    # de que proyecto es cada paquete: los .summa de la lista, y los del
    # directorio de cada archivo
    declare -A proyecto=()
    for f in "${args[@]}"; do
        case "$f" in *_*.summa)
            p=$(basename "$f"); p=${p%%_*}; proyecto[$p]=$p
            for q in $(paquetes_de "$f"); do proyecto[$q]=$p; done ;;
        esac
    done
    for f in "${args[@]}"; do
        for s in "$(dirname "$f")"/*.summa; do
            [ -f "$s" ] || continue
            # el del proyecto (tabular2.summa) o el que deja hacer-pkg
            # (tabular2_2.0-14.summa)
            p=$(basename "$s" .summa); p=${p%%_*}
            for q in $(paquetes_de "$s"); do [ -n "${proyecto[$q]:-}" ] || proyecto[$q]=$p; done
        done
    done
    for f in "${args[@]}"; do
        [ -f "$f" ] || { echo "no esta $f" >&2; exit 1; }
        case "$f" in *.md5) continue ;; esac
        # el .md5 se rehace si falta o no coincide con el archivo (uno viejo de
        # una compilacion anterior con la misma version: bajar-paquetes
        # descartaria el paquete)
        if [ ! -f "$f.md5" ] || [ "$(md5sum < "$f" | cut -d' ' -f1)" != "$(cut -d' ' -f1 < "$f.md5")" ]; then
            [ -f "$f.md5" ] && echo "  $f.md5 no coincide con el archivo: se rehace"
            (cd "$(dirname "$f")" && md5sum "$(basename "$f")" > "$(basename "$f").md5")
        fi
        b=$(basename "$f")
        u=$(fijo "$b" UNSTABLE)
        [ "$u" != "$b" ] || { echo "no se a que version corresponde $b: no lo subo" >&2; exit 1; }
        q=$(paquete "$b")
        case "$b" in *.tar.gz|*.summa) p=$q ;; *) p=${proyecto[$q]:-} ;; esac
        [ -n "$p" ] || { echo "no se de que proyecto es $b: poner su .summa (NOMBRE_VERSION.summa) entre los archivos" >&2; exit 1; }
        # si ya esta igual (mismo md5), no se sube; si esta distinto (una
        # subida cortada), se vuelve a subir
        if [ $forzar = 0 ] && [ $prueba = 0 ]; then
            # md5 del archivo alla y lo que dice su .md5 alla (uno viejo hace
            # que bajar-paquetes lo descarte): los dos tienen que coincidir
            alla=$(remoto "$COMUN"'for f in "$1/$2" "$1/otros/$2"; do [ -f "$f" ] && { echo "$(md5sum < "$f" | cut -d" " -f1)$(cut -d" " -f1 "$1/otros/$2.md5" 2>/dev/null)"; break; }; done; true' "$p" "$b")
            if [ -n "$alla" ]; then
                if [ "$alla" = "$(cut -d' ' -f1 < "$f.md5")$(cut -d' ' -f1 < "$f.md5")" ]; then
                    echo "ya esta $p/$b"
                    continue
                fi
                echo "$p/$b esta en el servidor pero distinto (subida cortada?): se vuelve a subir"
            fi
        fi
        remoto "$COMUN"'hacer mkdir -p "$1/otros"; [ "$PRUEBA" = 1 ] || touch "$1/otros/.estructura"' "$p"
        copiar "$p/otros" "$f" "$f.md5"
        remoto "$COMUN"'cd "$1/otros"; hacer ln -sfn "$2" "$3"; hacer ln -sfn "$2.md5" "$3.md5"' "$p" "$b" "$u"
        echo "$p/otros/$b  ($u)"
    done
    ;;
estable)
    [ ${#args[@]} -gt 0 ] || { echo "uso: subir-paquetes --estable PROYECTO..." >&2; exit 2; }
    for p in "${args[@]}"; do
        remoto "$COMUN"'
p=$1
[ -d "$p/otros" ] || { echo "no hay $p/otros en el servidor" >&2; exit 1; }
cd "$p/otros"
hay=0
for u in *_UNSTABLE* *-UNSTABLE*; do
    [ -L "$u" ] || continue
    case "$u" in *.md5) continue ;; esac
    hay=1
    a=$(readlink "$u"); real=${a#../}
    case "$real" in
    *.summa)
        # el .summa queda en otros/ y se copia arriba con la version
        # completa (6.0-38), que es como bajar-paquetes sabe cual es la
        # estable
        v=${real#"$p"_}; v=${v%.summa}
        if [ "$PRUEBA" = 1 ]; then
            echo "  [prueba] $real -> ../../$p.summa (con VERSION=\"$v\")"
        else
            # el .summa ya lleva VERSION (desde 07/10/2026); los de antes no
            if grep -q "^VERSION=\"$v\"\$" "$real"; then cp "$real" "../../$p.summa"
            else { cat "$real"; printf "\n# la version estable en el servidor (la agrega subir-paquetes --estable)\nVERSION=\"%s\"\n" "$v"; } > "../../$p.summa"; fi
        fi
        hacer rm -f "$u" "$u.md5"
        echo "$p.summa <- $real" ;;
    *)
        # el estable anterior del mismo paquete, tipo y distribucion vuelve
        # a otros/: el que tiene el mismo nombre fijo con otra version
        clave() {
            case "$1" in
                *.rpm) echo "$1" | sed -E "s/^(.+)-[^-]+-[0-9]+(\.[a-z][a-z0-9]*)?\.([^.]+)\.rpm$/\1-V\2.\3.rpm/" ;;
                *_*_*) echo "$1" | sed -E "s/^([^_]+)_[^_+]+(\+[^_]+)?_(.+)$/\1_V\2_\3/" ;;
                *)     echo "$1" | sed -E "s/^([^_]+)_[^_]+\.(tar\.gz|tgz)$/\1_V.\2/" ;;
            esac
        }
        k=$(clave "$real")
        for viejo in ../*; do
            [ -f "$viejo" ] || continue
            b=$(basename "$viejo")
            [ "$b" != "$real" ] && [ "$(clave "$b")" = "$k" ] || continue
            hacer mv "$viejo" .
            echo "  a otros/: $b"
        done
        if [ -e "$real" ] && [ ! -L "$real" ]; then hacer mv "$real" ..; fi
        # ya no hay nada inestable de este paquete: el UNSTABLE desaparece
        # hasta que se suba otra version
        hacer rm -f "$u" "$u.md5"
        echo "$p/$real" ;;
    esac
done
# los nombres _last de antes ya no se usan
for l in *_last* *-last*; do if [ -L "$l" ]; then hacer rm -f "$l"; fi; done
# nada pendiente (ya estable: se volvio a correr): se avisa y se sigue
[ $hay = 1 ] || echo "  $p: nada UNSTABLE en otros/ (ya estaba estable)"
' "$p"
    done
    ;;
lista)
    remoto "$COMUN"'
for p in "${@:-*}"; do
    for d in $p; do
        [ -d "$d/otros" ] || continue
        echo "$d/"
        ls -1 "$d" | grep -v "^otros$" | sed "s/^/  /"
        echo "  otros/: $(ls -1 "$d/otros" | grep -vc "\.md5$") archivos y enlaces, $(ls -1 "$d/otros" | grep -c "\.md5$") md5"
        ls -l "$d/otros" | awk "/_UNSTABLE|-UNSTABLE/ && !/md5/ {print \"    \" \$(NF-2), \$(NF-1), \$NF}"
    done
done
' "${args[@]+"${args[@]}"}"
    ;;
esac
