#!/bin/bash
# subir-paquetes: publica en el servidor de descargas lo que deja hacer-deb
# (.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
#   installsumma.sh      instala summapack, lo que hace falta para instalar
#                        cualquier paquete (bajar-paquetes e instalar-tgz,
#                        que usa, en summapack/)
#   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 los nombres
#                        fijos (enlaces): PAQ_last... a la estable y
#                        PAQ_UNSTABLE... a la ultima subida
#
# PROYECTO es el del .summa: libtabular2-0, libtabular2-dev y tabular van en
# tabular2/. Los nombres fijos cambian la version por last o UNSTABLE:
# calcula_6.0-38_amd64.deb -> calcula_last_amd64.deb,
# calcula-6.0-38.x86_64.rpm -> calcula-last.x86_64.rpm.
#
#   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-deb)
#       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/, PAQ_last... apunta
#       a los nuevos y el .summa se copia arriba como PROYECTO.summa.
#   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 o last)
fijo() {
    local f="$1" v="$2"
    case "$f" in
        *.rpm)  echo "$f" | sed -E "s/^(.+)-([^-]+-[^-]+)\.([^.]+)\.rpm$/\1-$v.\3.rpm/" ;;
        *_*_*)  echo "$f" | sed -E "s/^([^_]+)_[^_]+_(.+)$/\1_${v}_\2/" ;;
        *_*)    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|installsumma.sh) 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-deb
            # (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
        [ -f "$f.md5" ] || (cd "$(dirname "$f")" && md5sum "$(basename "$f")" > "$(basename "$f").md5")
        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
            alla=$(remoto "$COMUN"'for f in "$1/$2" "$1/otros/$2"; do [ -f "$f" ] && { md5sum < "$f" | cut -d" " -f1; break; }; done; true' "$p" "$b")
            if [ -n "$alla" ]; then
                if [ "$alla" = "$(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#../}
    l=$(echo "$u" | sed "s/UNSTABLE/last/")
    case "$real" in
    *.summa)
        # el .summa queda en otros/ y se copia arriba
        hacer ln -sfn "$real" "$l"; hacer ln -sfn "$real.md5" "$l.md5"
        hacer cp "$real" "../../$p.summa"
        echo "$p.summa <- $real" ;;
    *)
        # el estable anterior de este mismo nombre fijo vuelve a otros/
        if [ -L "$l" ]; then
            viejo=$(readlink "$l"); viejo=${viejo#../}
            if [ "$viejo" != "$real" ] && [ -e "../$viejo" ]; then
                hacer mv "../$viejo" .
                echo "  a otros/: $viejo"
            fi
        fi
        if [ -e "$real" ] && [ ! -L "$real" ]; then hacer mv "$real" ..; fi
        hacer ln -sfn "../$real" "$l"; hacer ln -sfn "$real.md5" "$l.md5"
        hacer ln -sfn "../$real" "$u"
        echo "$p/$real" ;;
    esac
done
[ $hay = 1 ] || { echo "no hay nada UNSTABLE en $p/otros" >&2; exit 1; }
' "$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
