3f83316fa8
Fixed a bash variable expansion bug where $name was being referenced before assignment in a multi-variable local declaration. Changed d assignment to use $1 directly instead of $name to ensure the correct directory path is set. This prevents PKGBUILD lookup failures when processing dependent packages in AUR chains.
322 lines
15 KiB
Bash
Executable File
322 lines
15 KiB
Bash
Executable File
#!/bin/bash
|
|
# ============================================================
|
|
# FWS — Build des paquets AUR (winboat-bin) + PKGBUILD locaux (deps Anaconda)
|
|
# et création du repo pacman local fws-local/.
|
|
#
|
|
# Rejoue-le si tu changes la liste AUR_PACKAGES ou pour
|
|
# rafraîchir le repo local.
|
|
# ============================================================
|
|
set -e
|
|
trap 'rc=$?; echo -e "\033[0;31m[ERR] Échec (setup-aur.sh) ligne $LINENO, code $rc.\033[0m" >&2; exit $rc' ERR
|
|
|
|
# Paquets AUR à construire, DANS L'ORDRE (les deps avant les dépendants ; la
|
|
# boucle plus bas installe chaque paquet après build pour résoudre les chaînes).
|
|
# - libxmlrpc, satyr : deps de libreport (deps officielles uniquement)
|
|
# - libreport : tiré par python-meh ; chaîne AUR→AUR → APRÈS satyr+libxmlrpc
|
|
# - winboat-bin : app FWS
|
|
# - python-* : deps Anaconda présentes dans l'AUR (deps officielles only)
|
|
# python-blivet est packagé en LOCAL (pkgbuilds/, patché sans libselinux).
|
|
# gnome-kiosk (WM de la session GUI) est différé au chantier C.
|
|
AUR_PACKAGES=(libxmlrpc satyr libreport winboat-bin python-langtable python-pid python-iso639 python-xkbregistry python-requests-ftp)
|
|
DISTRO_NAME="${ARCH_WSL_DISTRO:-Arch}"
|
|
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'; CYAN='\033[0;36m'; NC='\033[0m'
|
|
info() { echo -e "${BLUE}==>${NC} $1"; }
|
|
success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[!!]${NC} $1"; }
|
|
error() { echo -e "${RED}[ERR]${NC} $1"; exit 1; }
|
|
step() { echo -e "\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo -e "${CYAN} $1${NC}"
|
|
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; }
|
|
|
|
# ============================================================
|
|
# Bascule Git Bash → WSL si besoin
|
|
# ============================================================
|
|
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || -n "$WINDIR" ]]; then
|
|
info "Git Bash détecté — bascule dans WSL ($DISTRO_NAME)..."
|
|
export MSYS_NO_PATHCONV=1
|
|
export MSYS2_ARG_CONV_EXCL="*"
|
|
|
|
# WSL doit être présent.
|
|
command -v wsl.exe >/dev/null 2>&1 \
|
|
|| error "WSL introuvable — PowerShell admin : 'wsl --install', puis installe une distro Arch et relance."
|
|
|
|
# Choix de la distro Arch : override $ARCH_WSL_DISTRO, sinon nom exact,
|
|
# sinon 1re distro « arch » réellement joignable (énum via `wsl -l -q`,
|
|
# sortie UTF-16LE → on retire NUL/CR ; on garde la sonde « echo ok »).
|
|
pick_arch_distro() {
|
|
wsl.exe -d "$DISTRO_NAME" -u root -- echo ok >/dev/null 2>&1 && return 0
|
|
local d distros=()
|
|
mapfile -t distros < <(wsl.exe -l -q 2>/dev/null | tr -d '\0\r' | sed 's/[[:space:]]*$//;/^$/d')
|
|
for d in "${distros[@]}"; do
|
|
[[ "$d" == "$DISTRO_NAME" ]] || continue
|
|
wsl.exe -d "$d" -u root -- echo ok >/dev/null 2>&1 && { DISTRO_NAME="$d"; return 0; }
|
|
done
|
|
for d in "${distros[@]}"; do
|
|
[[ "$d" =~ [Aa][Rr][Cc][Hh] ]] || continue
|
|
wsl.exe -d "$d" -u root -- echo ok >/dev/null 2>&1 && { DISTRO_NAME="$d"; return 0; }
|
|
done
|
|
return 1
|
|
}
|
|
if ! pick_arch_distro; then
|
|
warn "Distros WSL installées :"
|
|
wsl.exe -l -v 2>/dev/null | tr -d '\0' >&2 || true
|
|
error "Aucune distro WSL Arch joignable. Installe ArchWSL (nom 'Arch') ou 'wsl --install -d archlinux', ou exporte ARCH_WSL_DISTRO=<nom>."
|
|
fi
|
|
info "Distro WSL : $DISTRO_NAME"
|
|
|
|
SCRIPT_DIR_WIN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -W)"
|
|
SCRIPT_PATH_WSL=$(MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- \
|
|
wslpath "$(echo "$SCRIPT_DIR_WIN" | sed 's|/|\\\\|g')/setup-aur.sh" \
|
|
2>/dev/null | tr -d '\r\n')
|
|
[ -n "$SCRIPT_PATH_WSL" ] \
|
|
|| error "Traduction du chemin vers WSL échouée (wslpath). Vérifie ARCH_WSL_DISTRO ($DISTRO_NAME)."
|
|
wsl.exe -d "$DISTRO_NAME" -u root -- test -f "$SCRIPT_PATH_WSL" \
|
|
|| error "Script introuvable dans WSL : $SCRIPT_PATH_WSL"
|
|
|
|
# Relance en root depuis le vrai chemin ($0 → SCRIPT_DIR correct).
|
|
# Fins de ligne garanties LF par .gitattributes (*.sh text eol=lf).
|
|
MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- bash "$SCRIPT_PATH_WSL"
|
|
exit 0
|
|
fi
|
|
|
|
# ============================================================
|
|
# Bascule conteneur : hôte non-Arch (Fedora, Ubuntu, …) →
|
|
# setup dans un conteneur Arch via podman (rootful, --privileged).
|
|
# Voir build.sh pour le détail du design ; même image, même volume de
|
|
# cache pacman, dépôt monté au MÊME chemin absolu (→ local-repo/ revient
|
|
# sur l'hôte). makepkg refuse root mais on est dans le conteneur en root :
|
|
# setup-aur.sh recrée son propre utilisateur fwsbuild, c'est transparent.
|
|
# ============================================================
|
|
host_is_arch() {
|
|
# Fedora empaquette aussi « pacman » → sa seule présence ne suffit pas.
|
|
command -v pacman >/dev/null 2>&1 \
|
|
&& grep -qiE '^ID(_LIKE)?=.*arch' /etc/os-release 2>/dev/null
|
|
}
|
|
|
|
if [ -z "$FWS_IN_CONTAINER" ] && ! host_is_arch; then
|
|
info "Hôte non-Arch détecté — setup dans un conteneur Arch (podman)..."
|
|
command -v podman >/dev/null 2>&1 \
|
|
|| error "podman introuvable. Fedora : 'sudo dnf install -y podman' ; Debian/Ubuntu : 'sudo apt install -y podman'."
|
|
|
|
SUDO=(); [ "$EUID" -eq 0 ] || SUDO=(sudo)
|
|
TTY=(); [ -t 0 ] && TTY=(-it)
|
|
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
IMAGE="docker.io/library/archlinux:latest"
|
|
|
|
# pull explicite : « run » ne re-résout pas « latest » une fois en cache.
|
|
info "Pull de l'image $IMAGE…"
|
|
"${SUDO[@]}" podman pull "$IMAGE"
|
|
|
|
info "Relance dans le conteneur (setup-aur.sh)…"
|
|
"${SUDO[@]}" podman run --rm "${TTY[@]}" --privileged \
|
|
-e FWS_IN_CONTAINER=1 \
|
|
-v "$REPO_DIR":"$REPO_DIR" \
|
|
-v fws-pacman-cache:/var/cache/pacman/pkg \
|
|
-w "$REPO_DIR" \
|
|
"$IMAGE" \
|
|
bash "$REPO_DIR/setup-aur.sh"
|
|
|
|
# podman rootful → local-repo/ appartient à root : on le rend à l'hôte.
|
|
OWNER="$(stat -c '%u:%g' "$REPO_DIR" 2>/dev/null || true)"
|
|
if [ -n "$OWNER" ] && [ -e "$REPO_DIR/local-repo" ]; then
|
|
"${SUDO[@]}" chown -R "$OWNER" "$REPO_DIR/local-repo" 2>/dev/null || true
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
# ============================================================
|
|
# Vérifications
|
|
# ============================================================
|
|
command -v pacman >/dev/null || error "pacman introuvable (lance depuis Arch / WSL)"
|
|
# Élévation root : sudo de préférence, sinon su. $0 cité (chemins à espaces).
|
|
if [ "$EUID" -ne 0 ]; then
|
|
if command -v sudo >/dev/null 2>&1; then
|
|
exec sudo bash "$0" "$@"
|
|
else
|
|
exec su -c "bash \"$0\"" root
|
|
fi
|
|
fi
|
|
success "Arch Linux (root) ✓"
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
LOCAL_REPO="$SCRIPT_DIR/local-repo"
|
|
BUILD_DIR="/tmp/fws-aur-build"
|
|
BUILD_USER="fwsbuild"
|
|
|
|
# ============================================================
|
|
step "0/4 — Préparation pacman (sandbox WSL + keyring)"
|
|
# ============================================================
|
|
# pacman ≥ 7 utilise landlock pour sandboxer les ops fs. Ni le kernel WSL
|
|
# ni (selon le noyau) le conteneur ne le supportent → désactivation explicite.
|
|
if grep -qi 'microsoft\|wsl' /proc/version 2>/dev/null || [ -n "$FWS_IN_CONTAINER" ]; then
|
|
if ! grep -qE '^[[:space:]]*DisableSandbox' /etc/pacman.conf; then
|
|
sed -i '/^\[options\]/a DisableSandbox' /etc/pacman.conf
|
|
warn "WSL/conteneur détecté → DisableSandbox ajouté à /etc/pacman.conf"
|
|
fi
|
|
fi
|
|
|
|
# Keyring : sur une WSL Arch ancienne, archlinux-keyring est périmé et
|
|
# bloque tout install ("unknown trust"). On bypass SigLevel uniquement
|
|
# pour mettre à jour le paquet keyring, puis on rétablit.
|
|
info "Refresh du trousseau pacman…"
|
|
pacman-key --init 2>/dev/null || true
|
|
|
|
if [ -f /etc/pacman.conf ] && ! grep -qE '^[[:space:]]*SigLevel[[:space:]]*=[[:space:]]*Never' /etc/pacman.conf; then
|
|
cp -f /etc/pacman.conf /etc/pacman.conf.fws.bak
|
|
sed -i 's/^SigLevel.*/SigLevel = Never/' /etc/pacman.conf
|
|
pacman -Sy --noconfirm --needed archlinux-keyring \
|
|
|| warn "Maj archlinux-keyring échouée (sigs bypass) — on continue"
|
|
mv -f /etc/pacman.conf.fws.bak /etc/pacman.conf
|
|
fi
|
|
|
|
pacman-key --populate archlinux 2>/dev/null || true
|
|
|
|
# Maj système complète : indispensable pour gérer les "package splits"
|
|
# (ex. gcc-libs → libgcc + libstdc++) sinon makepkg plantera sur
|
|
# "conflicting files" lors de l'install des dépendances.
|
|
info "Mise à jour complète du système (peut être long la première fois)…"
|
|
pacman -Syu --noconfirm \
|
|
|| warn "pacman -Syu a partiellement échoué — on continue"
|
|
|
|
# ============================================================
|
|
step "1/4 — Outils de build"
|
|
# ============================================================
|
|
pacman -Sy --needed --noconfirm base-devel git
|
|
|
|
# ============================================================
|
|
step "2/4 — Préparation utilisateur de build (non-root pour makepkg)"
|
|
# ============================================================
|
|
rm -rf "$BUILD_DIR"
|
|
mkdir -p "$BUILD_DIR"
|
|
|
|
if ! id "$BUILD_USER" &>/dev/null; then
|
|
useradd -m "$BUILD_USER"
|
|
echo "$BUILD_USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/fwsbuild
|
|
chmod 440 /etc/sudoers.d/fwsbuild
|
|
success "Utilisateur $BUILD_USER créé"
|
|
fi
|
|
chown -R "$BUILD_USER:$BUILD_USER" "$BUILD_DIR"
|
|
|
|
# ============================================================
|
|
# Helpers — build INCRÉMENTAL (saute un paquet déjà présent dans local-repo
|
|
# à la même version pkgver-pkgrel). Gros gain quand on n'itère que sur 1 paquet.
|
|
# ============================================================
|
|
mkdir -p "$LOCAL_REPO"
|
|
|
|
# Version « [epoch:]pkgver-pkgrel » lue dans un PKGBUILD (sourcing en sous-shell).
|
|
# Vide si illisible → on (re)construit par sécurité. Nos paquets n'ont pas de
|
|
# pkgver() VCS, donc le pkgver littéral est exact.
|
|
pkgbuild_fullver() {
|
|
( cd "$1" 2>/dev/null && source ./PKGBUILD >/dev/null 2>&1 \
|
|
&& printf '%s%s-%s' "${epoch:+$epoch:}" "$pkgver" "$pkgrel" ) 2>/dev/null || true
|
|
}
|
|
|
|
# Le paquet <name> en version <fullver> est-il déjà dans local-repo ? Le motif
|
|
# « -$ver- » borne la version (évite qu'« anaconda » matche « anaconda-widgets »).
|
|
repo_has() {
|
|
[ -n "$2" ] || return 1
|
|
local f
|
|
for f in "$LOCAL_REPO/$1-$2-"*.pkg.tar.*; do [ -e "$f" ] && return 0; done
|
|
return 1
|
|
}
|
|
|
|
# Publie les .pkg d'un build vers local-repo en purgeant d'abord les anciennes
|
|
# versions de CE paquet (+ son sous-paquet -debug). Le « -[0-9] » empêche
|
|
# « anaconda » d'attraper « anaconda-widgets » / « anaconda-debug ».
|
|
publish_to_repo() {
|
|
local name="$1" d="$2"
|
|
rm -f "$LOCAL_REPO/$name"-[0-9]*.pkg.tar.* \
|
|
"$LOCAL_REPO/$name"-debug-[0-9]*.pkg.tar.* 2>/dev/null || true
|
|
cp -f "$d"/*.pkg.tar.* "$LOCAL_REPO/" || error "Copie de $name vers local-repo échouée"
|
|
}
|
|
|
|
# Construit OU saute <name> (source déjà déposée dans $BUILD_DIR/<name>).
|
|
# Installe TOUJOURS le résultat (depuis local-repo si sauté) pour que les
|
|
# paquets dépendants suivants résolvent leurs deps (chaînes AUR→AUR, anaconda…).
|
|
build_or_skip() {
|
|
# NB : référencer "$1" et PAS "$name" ici — dans un `local a=… b=…` à une
|
|
# seule ligne, bash développe la 2ᵉ valeur AVANT que `name` ne soit affecté,
|
|
# donc "$name" y serait vide → d="/tmp/fws-aur-build/" (PKGBUILD introuvable).
|
|
local name="$1" d="$BUILD_DIR/$1" ver
|
|
[ -f "$d/PKGBUILD" ] || error "PKGBUILD introuvable pour $name ($d)"
|
|
ver="$(pkgbuild_fullver "$d")"
|
|
if repo_has "$name" "$ver"; then
|
|
success "$name $ver déjà construit → saut (install depuis local-repo)"
|
|
pacman -U --noconfirm --needed "$LOCAL_REPO/$name-$ver-"*.pkg.tar.* \
|
|
|| error "Install (repo) de $name échouée"
|
|
return 0
|
|
fi
|
|
info "Build $name ${ver:+($ver) }(peut prendre plusieurs minutes)…"
|
|
chown -R "$BUILD_USER:$BUILD_USER" "$d"
|
|
su - "$BUILD_USER" -c "cd '$d' && makepkg -sf --noconfirm" \
|
|
|| error "Build $name échoué"
|
|
pacman -U --noconfirm "$d/"*.pkg.tar.* || error "Install de $name échouée"
|
|
publish_to_repo "$name" "$d"
|
|
success "$name build + install OK"
|
|
}
|
|
|
|
# ============================================================
|
|
step "3/4 — Build des paquets (saut si déjà à jour dans local-repo)"
|
|
# ============================================================
|
|
# --- Paquets AUR (ordre : deps avant dépendants ; clone shallow puis build/saut) ---
|
|
for pkg in "${AUR_PACKAGES[@]}"; do
|
|
info "Clonage $pkg (AUR)…"
|
|
rm -rf "$BUILD_DIR/$pkg"
|
|
su - "$BUILD_USER" -c "git clone --depth=1 https://aur.archlinux.org/${pkg}.git $BUILD_DIR/$pkg" \
|
|
|| error "Clonage $pkg échoué"
|
|
build_or_skip "$pkg"
|
|
done
|
|
|
|
# --- PKGBUILD locaux FWS (ordre explicite, feuilles d'abord, anaconda dernier) ---
|
|
LOCAL_PKGBUILDS_DIR="$SCRIPT_DIR/pkgbuilds"
|
|
LOCAL_BUILD_ORDER=(
|
|
pykickstart python-productmd python-requests-file python-simpleline
|
|
python-meh python-blivet anaconda-widgets anaconda
|
|
)
|
|
BUILT_LOCAL=()
|
|
|
|
prepare_and_build_local() {
|
|
local name="$1" dir="$LOCAL_PKGBUILDS_DIR/$1"
|
|
[ -f "$dir/PKGBUILD" ] || return 1
|
|
rm -rf "$BUILD_DIR/$name"
|
|
cp -a "$dir" "$BUILD_DIR/$name"
|
|
build_or_skip "$name"
|
|
}
|
|
|
|
if [ -d "$LOCAL_PKGBUILDS_DIR" ]; then
|
|
# 1) Ordre explicite (deps avant dépendants).
|
|
for name in "${LOCAL_BUILD_ORDER[@]}"; do
|
|
if prepare_and_build_local "$name"; then BUILT_LOCAL+=("$name"); fi
|
|
done
|
|
# 2) Repli : tout PKGBUILD présent mais non listé (futur ajout oublié).
|
|
for dir in "$LOCAL_PKGBUILDS_DIR"/*/; do
|
|
[ -f "$dir/PKGBUILD" ] || continue
|
|
name="$(basename "$dir")"
|
|
printf '%s\n' "${BUILT_LOCAL[@]}" | grep -qx "$name" && continue
|
|
prepare_and_build_local "$name" || true
|
|
done
|
|
fi
|
|
|
|
# ============================================================
|
|
step "4/4 — (Re)génération de la base du repo local fws-local"
|
|
# ============================================================
|
|
# local-repo contient déjà TOUS les paquets (construits ce run + sautés des
|
|
# runs précédents). On régénère juste la base de données pacman du dépôt.
|
|
rm -f "$LOCAL_REPO"/fws-local.db* "$LOCAL_REPO"/fws-local.files* 2>/dev/null || true
|
|
repo-add "$LOCAL_REPO/fws-local.db.tar.gz" "$LOCAL_REPO"/*.pkg.tar.* \
|
|
|| error "repo-add a échoué"
|
|
success "Repo local prêt : $LOCAL_REPO"
|
|
|
|
# ============================================================
|
|
# Nettoyage utilisateur de build
|
|
# ============================================================
|
|
userdel -r "$BUILD_USER" 2>/dev/null || true
|
|
rm -f /etc/sudoers.d/fwsbuild
|
|
|
|
echo ""
|
|
echo -e "${GREEN}╔══════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${GREEN}║ Setup terminé. Lance maintenant : ./build.sh ║${NC}"
|
|
echo -e "${GREEN}╚══════════════════════════════════════════════════╝${NC}"
|