#!/bin/bash
# Ajoute seulement le depot PHP ScalarX adapte a Debian 9 ou 10 (amd64).
# Aucun apt update, aucune installation et aucun redemarrage de service.
set -Eeuo pipefail
export LC_ALL=C

DEBIAN_FILE=/etc/debian_version
OS_RELEASE_FILE=/etc/os-release
APT_ETC=/etc/apt
HTTPS_METHOD=/usr/lib/apt/methods/https
BACKUP_ROOT=/var/backups/stackx-php-repo
MIRROR=https://mirrors.scalarx.net/stackx-php

die() { printf 'ERREUR : %s\n' "$*" >&2; exit 1; }
require_root() { [[ $EUID -eq 0 ]] || die 'Lancer ce script avec root (ou sudo bash).'; }

usage() {
    cat <<'EOF'
Usage : bash add-stackx-php-repo.sh [--dry-run]

Ajoute /etc/apt/sources.list.d/stackx-php.list pour Debian 9/10 amd64.
--dry-run : affiche ce qui serait fait, sans ecrire de fichier.
Une nouvelle execution ne modifie rien si le depot est deja configure.
Un ancien fichier gere par ce script est sauvegarde avant remplacement.

Le depot est actuellement non signe. trusted=yes est limite a cette source ;
HTTPS est conserve. Aucune dependance n'est installee par le script.
Les mises a jour restent a lancer manuellement avec apt.
EOF
}

main() (
    local dry_run=0 major suite os_id file line source_file entry backup_dir tmp=''
    case "${1:-}" in
        --help|-h) usage; exit 0 ;;
        --dry-run) dry_run=1; shift ;;
    esac
    [[ $# -eq 0 ]] || { usage >&2; exit 2; }

    # Lire les fichiers d'identification, sans executer leur contenu.
    [[ -r $DEBIAN_FILE && -r $OS_RELEASE_FILE ]] || die 'Identification Debian indisponible.'
    major=$(<"$DEBIAN_FILE")
    case "$major" in
        9|9.*) suite=stretch ;;
        10|10.*) suite=buster ;;
        *) die "Version Debian non concernee : $major (seules 9 et 10 sont acceptees)." ;;
    esac
    os_id=''
    while IFS= read -r line || [[ -n $line ]]; do
        case "$line" in ID=*) os_id=${line#ID=} ;; esac
    done < "$OS_RELEASE_FILE"
    [[ $os_id == debian || $os_id == '"debian"' || $os_id == "'debian'" ]] || die 'Ce systeme ne se declare pas comme Debian.'
    command -v dpkg >/dev/null 2>&1 || die 'dpkg est introuvable.'
    [[ $(dpkg --print-architecture) == amd64 ]] || die 'Les paquets de ce depot sont construits pour amd64 uniquement.'
    [[ -x $HTTPS_METHOD ]] || die 'Le transport HTTPS de APT est absent (/usr/lib/apt/methods/https). Aucun paquet ni fichier APT modifie.'
    [[ -d $APT_ETC ]] || die 'Repertoire de configuration APT absent.'
    require_root

    source_file=$APT_ETC/sources.list.d/stackx-php.list
    entry="deb [arch=amd64 trusted=yes] $MIRROR/$suite/repo/ ./"
    [[ ! -L $source_file ]] || die "$source_file est un lien symbolique : remplacement refuse."
    [[ ! -e $source_file || -f $source_file ]] || die "$source_file n'est pas un fichier ordinaire."

    # Ne pas ajouter une seconde definition qui pourrait contredire l'existante.
    shopt -s nullglob
    for file in "$APT_ETC/sources.list" "$APT_ETC/sources.list.d/"*.list "$APT_ETC/sources.list.d/"*.sources; do
        [[ -f $file ]] || continue
        [[ -r $file ]] || die "Impossible de lire $file."
        while IFS= read -r line || [[ -n $line ]]; do
            line=${line%%#*}
            [[ $line =~ [^[:space:]] ]] || continue
            if [[ $file == "$source_file" ]]; then
                [[ $line =~ ^[[:space:]]*deb[[:space:]] && $line == *"$MIRROR/"* ]] ||
                    die "$source_file contient une configuration etrangere au depot ScalarX ; fichier conserve."
            elif [[ $line == *mirrors.scalarx.net/stackx-php* ]]; then
                die "Une definition de ce depot existe deja dans $file. Fichier conserve ; verifier cette definition pour eviter un doublon."
            fi
        done < "$file"
    done

    if [[ -f $source_file ]] && cmp -s "$source_file" <(printf '%s\n' \
        '# Depot PHP ScalarX pour Debian 9/10 - ajoute par add-stackx-php-repo.sh' \
        '# Depot non signe : exception trusted=yes limitee a cette source HTTPS.' "$entry"); then
        printf 'OK : depot %s deja configure. Aucun changement.\n' "$suite"
    elif (( dry_run )); then
        printf 'SIMULATION : ecriture de %s\n%s\n' "$source_file" "$entry"
        [[ ! -f $source_file ]] || printf 'Le fichier existant sera sauvegarde sous %s.\n' "$BACKUP_ROOT"
        exit 0
    else
        for file in cmp mktemp mkdir cp cat mv chmod date rm; do
            command -v "$file" >/dev/null 2>&1 || die "Commande de base manquante : $file."
        done
        mkdir -p -- "$APT_ETC/sources.list.d"
        tmp=$(mktemp "$APT_ETC/sources.list.d/.stackx-php.XXXXXX")
        trap '[[ -z $tmp ]] || rm -f -- "$tmp"' EXIT
        if [[ -f $source_file ]]; then
            backup_dir=$BACKUP_ROOT/$(date -u +%Y%m%dT%H%M%SZ)-$$
            mkdir -p -- "$backup_dir"
            cp -p -- "$source_file" "$backup_dir/stackx-php.list"
            # Conserver proprietaire, groupe et permissions du fichier existant.
            cp -p -- "$source_file" "$tmp"
            printf 'Sauvegarde : %s/stackx-php.list\n' "$backup_dir"
        else
            chmod 0644 "$tmp"
        fi
        printf '%s\n' \
            '# Depot PHP ScalarX pour Debian 9/10 - ajoute par add-stackx-php-repo.sh' \
            '# Depot non signe : exception trusted=yes limitee a cette source HTTPS.' \
            "$entry" > "$tmp"
        mv -fT -- "$tmp" "$source_file"
        tmp=''
        printf 'OK : depot %s ajoute dans %s.\n' "$suite" "$source_file"
    fi

    printf '\nDepot non signe : confiance accordee a cette source uniquement (HTTPS).\n'
    printf 'Aucun paquet installe ou mis a jour, aucun service redemarre.\n'
    printf '\nA lancer ensuite :\n  apt update\n  apt upgrade\n'
    printf '\nPour retirer cette source : rm /etc/apt/sources.list.d/stackx-php.list\n'
)

if [[ ${BASH_SOURCE[0]} == "$0" ]]; then
    main "$@"
fi

