pkgsync: aborta sin commitear si falla el parcheo, notifica fallos

cmd_push() seguía adelante y commiteaba lo que hubiera en disco aunque
patch_array_file no encontrara los arrays -- así fue como el fichero
acabó vacío en origin/main. Ahora aborta sin tocar git si cualquiera
de los 3 parcheos falla.

Añade notify_fail() (notify-send con urgencia critical) en los puntos
de fallo real de push/pull: parcheo fallido, git push/pull/clone
fallidos. Como push corre en ExecStop durante el apagado (sesión/D-Bus
cayéndose, notify-send no garantizado), también deja un marcador en
disco que el siguiente pull revisa al arrancar con la sesión completa,
para no depender de que la notificación del apagado llegara a verse.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Josevi
2026-09-17 18:49:26 +02:00
co-authored by Claude Sonnet 5
parent 598e8b52c8
commit 64bb53eadf
+54 -7
View File
@@ -23,6 +23,12 @@ METAPAC_CONFIG_DIR="$HOME/.config/metapac"
METAPAC_GROUP="$METAPAC_CONFIG_DIR/groups/arch-setup.toml" METAPAC_GROUP="$METAPAC_CONFIG_DIR/groups/arch-setup.toml"
OVERRIDES_FILE="$METAPAC_CONFIG_DIR/groups/overrides.local.toml" OVERRIDES_FILE="$METAPAC_CONFIG_DIR/groups/overrides.local.toml"
# Marca que un push falló. pull la revisa al arrancar (con la sesión gráfica
# ya arriba) para avisar aunque el notify-send del propio push, disparado
# durante el apagado con la sesión cayéndose, no llegara a mostrarse. Se
# borra en el primer push que vuelve a tener éxito.
FAIL_MARKER="$HOME/.local/share/pkgsync.failed"
# flatpak sin --user/--system instala en "system" con la config actual de # flatpak sin --user/--system instala en "system" con la config actual de
# install_flatpaks() en packages-common.sh. Si tu máquina usa --user, cambia # install_flatpaks() en packages-common.sh. Si tu máquina usa --user, cambia
# esto (o verifica con: flatpak list --columns=installation,application). # esto (o verifica con: flatpak list --columns=installation,application).
@@ -219,6 +225,18 @@ notify() {
command -v notify-send &>/dev/null && timeout 5 notify-send --app-name=pkgsync "$1" "$2" command -v notify-send &>/dev/null && timeout 5 notify-send --app-name=pkgsync "$1" "$2"
} }
# Como notify(), pero urgencia "critical" (se queda en pantalla hasta que se
# cierra a mano) y además deja constancia en $FAIL_MARKER: push corre en
# ExecStop durante el apagado, con la sesión/D-Bus ya cayéndose, así que su
# notify-send puede no llegar a mostrarse -- el marcador es la red de
# seguridad que garantiza el aviso en el siguiente pull, ya con la sesión
# gráfica completa.
notify_fail() {
echo "!! $1: $2" >&2
printf '%s -- %s: %s\n' "$(date -Iseconds)" "$1" "$2" >"$FAIL_MARKER"
command -v notify-send &>/dev/null && timeout 5 notify-send --app-name=pkgsync --urgency=critical "$1" "$2"
}
# --- subcomandos -------------------------------------------------------------- # --- subcomandos --------------------------------------------------------------
cmd_bootstrap() { cmd_bootstrap() {
echo ">> pkgsync bootstrap" echo ">> pkgsync bootstrap"
@@ -282,7 +300,7 @@ cmd_push() {
echo "=== push $(date -Iseconds) ===" echo "=== push $(date -Iseconds) ==="
if [[ ! -d "$REPO_DIR/.git" ]]; then if [[ ! -d "$REPO_DIR/.git" ]]; then
echo "!! no existe $REPO_DIR, corre 'pkgsync bootstrap' primero" notify_fail "pkgsync: push falló" "no existe el clon $REPO_DIR, corre 'pkgsync bootstrap'"
return 0 return 0
fi fi
@@ -314,25 +332,40 @@ cmd_push() {
add_flatpak="$(comm -23 "$work/inst_flatpak" "$work/decl_flatpak" | comm -23 - "$work/overrides")" add_flatpak="$(comm -23 "$work/inst_flatpak" "$work/decl_flatpak" | comm -23 - "$work/overrides")"
local pc="$REPO_DIR/shared/packages-common.sh" local pc="$REPO_DIR/shared/packages-common.sh"
patch_array_file "$pc" PACMAN_COMMON "$remove_pacman" "$add_pacman" local patch_failed=0
patch_array_file "$pc" AUR_COMMON "$remove_aur" "$add_aur" patch_array_file "$pc" PACMAN_COMMON "$remove_pacman" "$add_pacman" || patch_failed=1
patch_array_file "$pc" FLATPAK_COMMON "$remove_flatpak" "$add_flatpak" patch_array_file "$pc" AUR_COMMON "$remove_aur" "$add_aur" || patch_failed=1
patch_array_file "$pc" FLATPAK_COMMON "$remove_flatpak" "$add_flatpak" || patch_failed=1
rm -rf "$work" rm -rf "$work"
# No commitear nunca un parcheo a medias/fallido -- así fue como el fichero
# acabó vacío en origin/main una vez (2026-08-27): el parcheo falló pero el
# script siguió y commiteó igualmente lo que hubiera en disco. El fichero
# de trabajo no se toca cuando patch_array_file falla (solo escribe si
# encuentra el array), así que abortar aquí es seguro: el próximo intento
# vuelve a partir del mismo estado.
if (( patch_failed )); then
notify_fail "pkgsync: push falló" "no se pudo parchear packages-common.sh (arrays no encontrados), reviso sin commitear -- $LOG"
return 1
fi
write_group_file write_group_file
cd "$REPO_DIR" || return 0 cd "$REPO_DIR" || return 0
git add shared/packages-common.sh git add shared/packages-common.sh
if git diff --cached --quiet; then if git diff --cached --quiet; then
echo "sin cambios de paquetes que subir" echo "sin cambios de paquetes que subir"
rm -f "$FAIL_MARKER"
return 0 return 0
fi fi
git commit -m "pkgsync: actualiza inventario de paquetes $(date '+%Y-%m-%d %H:%M')" git commit -m "pkgsync: actualiza inventario de paquetes $(date '+%Y-%m-%d %H:%M')"
if timeout 20 git push origin main; then if timeout 20 git push origin main; then
echo "push OK" echo "push OK"
rm -f "$FAIL_MARKER"
else else
echo "push falló (¿sin red?), el commit queda en local para el próximo intento" notify_fail "pkgsync: push falló" "commit local OK pero 'git push' falló (¿sin red?); el commit queda en local para el próximo intento"
fi fi
} }
@@ -341,17 +374,31 @@ cmd_pull() {
exec >>"$LOG" 2>&1 exec >>"$LOG" 2>&1
echo "=== pull $(date -Iseconds) ===" echo "=== pull $(date -Iseconds) ==="
# Red de seguridad: si un push anterior falló (típicamente en ExecStop
# durante el apagado, con la sesión/D-Bus ya cayéndose y su propio
# notify-send sin garantía de mostrarse), avisar aquí sí o sí -- pull corre
# al arrancar sesión, con el escritorio ya completo.
if [[ -f "$FAIL_MARKER" ]]; then
notify_fail "pkgsync: hay un fallo pendiente de revisar" "$(cat "$FAIL_MARKER")"
fi
if ! timeout 15 git ls-remote --exit-code "$REPO_URL" &>/dev/null; then if ! timeout 15 git ls-remote --exit-code "$REPO_URL" &>/dev/null; then
echo "sin conexión con el remoto, me quedo con el estado local" echo "sin conexión con el remoto, me quedo con el estado local"
elif [[ ! -d "$REPO_DIR/.git" ]]; then elif [[ ! -d "$REPO_DIR/.git" ]]; then
echo "clonando arch-setup en $REPO_DIR..." echo "clonando arch-setup en $REPO_DIR..."
mkdir -p "$(dirname "$REPO_DIR")" mkdir -p "$(dirname "$REPO_DIR")"
timeout 30 git clone "$REPO_URL" "$REPO_DIR" && echo "clon inicial OK" || echo "clone falló" if timeout 30 git clone "$REPO_URL" "$REPO_DIR"; then
echo "clon inicial OK"
else
notify_fail "pkgsync: pull falló" "no se pudo clonar $REPO_URL, revisa $LOG"
fi
else else
if timeout 30 git -C "$REPO_DIR" pull --ff-only origin main; then if timeout 30 git -C "$REPO_DIR" pull --ff-only origin main; then
echo "git pull OK" echo "git pull OK"
else else
echo "git pull falló (conflicto local o sin red); sigo con el estado que haya" # ls-remote de arriba ya confirmó que hay red -- esto es un conflicto
# real (fast-forward imposible), no un simple "sin conexión".
notify_fail "pkgsync: pull falló" "'git pull --ff-only' falló (conflicto local, revisa $REPO_DIR a mano); sigo con el estado que haya"
fi fi
fi fi