🔒 Repository is read-only – file editing is disabled.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
#!/bin/bash
# =============================================================================
# build-repo.sh – budowa pakietów do repo PAG na PC (w chrootcie PaganOS)
# -----------------------------------------------------------------------------
# DLACZEGO NA PC, A NIE NA VPS:
# VPS buduje przez builder-chroot.sh w chrootcie DEBIANA (suite trixie), więc
# pakiety linkują się z Debianowymi bibliotekami. To właśnie stąd brały się
# rozjazdy ABI w repo: `libgsf` z odwołaniem do xmlNanoHTTPClose (w PaganLinux
# nie ma – libxml2 2.16 tego nie eksportuje) i `libavcodec` z
# rsvg_handle_render_document (nasze librsvg to 2.40.21, Debian ma 2.46+).
# Budowa w rootfsie PaganOS daje pakiety spójne z dystrybucją – a PC jest
# szybszy, więc i tak wygrywa.
#
# Użycie (wymaga roota):
# sudo ./build-repo.sh --prepare # utwórz rootfs buildera i zbuduj domyślne pakiety
# sudo ./build-repo.sh kernel nvidia-kernel # zbuduj wybrane pakiety
# sudo ./build-repo.sh --rootfs /mnt/pagan-build --out ./repo-out kernel
# sudo ./build-repo.sh --sign --gpg-key ABCD1234 kernel
# sudo ./build-repo.sh --upload user@vps:/var/www/repo.paganlinux.eu/stable kernel
#
# Kolejność ma znaczenie przy NVIDIA: `kernel` musi pójść pierwszy (skrypt sam
# instaluje go w rootfsie buildera, bo z niego korzysta `nvidia-kernel`).
#
# Czego ten skrypt NIE robi: nie publikuje repo.json (to robi `pagsync --gen-repo`
# na VPS – patrz instrukcja wypisywana na końcu).
# =============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOTFS="/mnt/pagan-build" # rootfs buildera (chroot)
PAGAN_SRC_ROOT="${PAGAN_ROOT:-/mnt/pagan}" # źródłowy rootfs (obraz) do skopiowania
OUT_DIR="$SCRIPT_DIR/repo-out"
SRC_CACHE="/var/cache/pagbuild/sources"
DO_PREPARE=0
DO_SIGN=0
GPG_KEY=""
UPLOAD=""
PKGS=()
# Domyślnie: rolling kernel + gotowe moduły NVIDIA (to, czego brakuje w repo).
DEFAULT_PKGS=(kernel nvidia-kernel)
usage() { sed -n '3,/^set -euo pipefail$/p' "$0" | grep -v '^set -euo pipefail$'; exit "${1:-0}"; }
while [[ $# -gt 0 ]]; do
case "$1" in
--rootfs) ROOTFS="$2"; shift 2 ;;
--out) OUT_DIR="$2"; shift 2 ;;
--pagansrc) PAGAN_SRC_ROOT="$2"; shift 2 ;;
--prepare) DO_PREPARE=1; shift ;;
--sign) DO_SIGN=1; shift ;;
--gpg-key) GPG_KEY="$2"; shift 2 ;;
--upload) UPLOAD="$2"; shift 2 ;;
-h|--help) usage 0 ;;
-*) echo "Nieznana opcja: $1" >&2; usage 2 ;;
*) PKGS+=("$1"); shift ;;
esac
done
[[ $EUID -eq 0 ]] || { echo "❌ Wymagane uprawnienia root (chroot)." >&2; exit 1; }
[[ -x "$SCRIPT_DIR/pagbuild" ]] || { echo "❌ Brak wykonywalnego $SCRIPT_DIR/pagbuild" >&2; exit 1; }
[[ ${#PKGS[@]} -gt 0 ]] || PKGS=("${DEFAULT_PKGS[@]}")
info() { printf '\033[1;36m▸ %s\033[0m\n' "$*"; }
ok() { printf '\033[1;32m✓ %s\033[0m\n' "$*"; }
warn() { printf '\033[1;33m! %s\033[0m\n' "$*"; }
die() { printf '\033[1;31m✗ %s\033[0m\n' "$*" >&2; exit 1; }
ABI_FAILED=()
# ── Montowanie systemowych katalogów w chrootcie (dla `pag install`) ──
_mounted=0
_mount_chroot() {
local r="$1"
for d in dev proc sys; do
mountpoint -q "$r/$d" 2>/dev/null || mount --bind "/$d" "$r/$d" 2>/dev/null || true
done
_mounted=1
}
_umount_chroot() {
[[ $_mounted -eq 1 ]] || return 0
local r="$1"
for d in sys proc dev; do
mountpoint -q "$r/$d" 2>/dev/null && umount -l "$r/$d" 2>/dev/null || true
done
_mounted=0
}
# ── (1) Przygotowanie rootfsu buildera ───────────────────────────────────────
# Kopiujemy GOTOWY rootfs PaganOS (ma już gcc/make/bison/flex/perl) zamiast
# stawiać od zera rootfs.sh (godziny). Wyłączamy sources/ – to 10+ GB, a pagbuild
# sam ściąga źródła do /var/cache/pagbuild/work wewnątrz chroota.
if [[ $DO_PREPARE -eq 1 && ! -d "$ROOTFS" ]]; then
[[ -d "$PAGAN_SRC_ROOT/usr/bin" ]] || die "Brak $PAGAN_SRC_ROOT – podaj --pagansrc"
info "Tworzę rootfs buildera: $ROOTFS (z $PAGAN_SRC_ROOT, bez sources/)"
df -h "$(dirname "$ROOTFS")" | tail -1
command -v rsync >/dev/null || die "Brak rsync (potrzebny do kopii rootfsu)"
mkdir -p "$ROOTFS"
rsync -aHAX --info=progress2 \
--exclude='/sources/' --exclude='/tmp/' --exclude='/var/cache/pagbuild/' \
--exclude='/proc/' --exclude='/sys/' --exclude='/dev/' --exclude='/run/' \
"$PAGAN_SRC_ROOT/" "$ROOTFS/" || die "Kopiowanie rootfsu nieudane"
ok "Rootfs buildera gotowy: $ROOTFS"
fi
[[ -d "$ROOTFS/usr/bin" ]] || die "Brak rootfsu buildera ($ROOTFS). Użyj --prepare."
# ── (2) Narzędzia budowy, których brakuje w obrazie ────────────────────────
# binutils: ISO ma tylko binutils-pass1 w /tools – w /usr/bin NIE MA `ld`, więc
# nic się nie zlinkuje (dotyczy też DKMS na docelowym systemie).
# libelf: jądro robi `pkg-config --exists libelf` (objtool dla
# CONFIG_UNWINDER_ORC=y). Obraz ma libelf.so, ale BEZ libelf.pc → w chrootcie
# budowa jądra pada na „Cannot generate ORC metadata … please install
# libelf-dev”. W buildzie ISO to przechodziło, bo objtool buduje się
# narzędziami HOSTA (a host ma libelf), nie rootfsu.
# bc/bison/flex: wymagane przez Kbuild; w obrazie są, ale gdy kiedyś znikną…
_pag_install_in_rootfs() {
local r="$1"; shift
[[ $# -gt 0 ]] || return 0
cp -L /etc/resolv.conf "$r/etc/resolv.conf" 2>/dev/null || true
_mount_chroot "$r"
trap '_umount_chroot "$ROOTFS"' EXIT
chroot "$r" /usr/bin/env PAG_YES=1 /usr/bin/pag install -y "$@" \
|| warn " nie udało się doinstalować: $*"
_umount_chroot "$r"
trap - EXIT
}
for _spec in "binutils:/usr/bin/ld" \
"libelf:/usr/lib/pkgconfig/libelf.pc" \
"bc:/usr/bin/bc" "bison:/usr/bin/bison" "flex:/usr/bin/flex" \
"meson:/usr/bin/meson" "ninja:/usr/bin/ninja" \
"cmake:/usr/bin/cmake" "pkgconf:/usr/bin/pkgconf" \
"autoconf:/usr/bin/autoconf" "automake:/usr/bin/automake" \
"libtool:/usr/bin/libtool" "m4:/usr/bin/m4"; do
_dep="${_spec%%:*}"; _sent="${_spec#*:}"
if [[ ! -e "$ROOTFS$_sent" ]]; then
info "Doinstalowuję $_dep w rootfsie buildera (brak $_sent)"
_pag_install_in_rootfs "$ROOTFS" "$_dep"
fi
done
[[ -x "$ROOTFS/usr/bin/ld" ]] || warn "Nadal brak $ROOTFS/usr/bin/ld – linker zostanie wzięty z hosta? (nie zadziała w chrootcie)"
# meson OSOBNO i z twardą kontrolą: obraz ISO go nie zawiera (nie jest potrzebny
# w systemie uruchomieniowym), a KAŻDA receptura mesonowa (mesa, libglvnd, libva,
# xf86-video-amdgpu…) padnie na "meson: command not found" (exit 127). Pre-flight
# w pagbuild pomija meson jako „zawsze obecny w builderze”, więc bez tego wpisu
# brak meson nie jest w ogóle raportowany przed buildem.
if [[ ! -x "$ROOTFS/usr/bin/meson" ]]; then
warn "Brak meson w rootfsie buildera – receptury mesonowe padną na 'meson: command not found'"
fi
# cmake w tym rootfsie bywa zbudowany pod systemowy rhash (NEEDED librhash.so.1),
# a sam pakiet rhash nie jest wciągany jako zależność – po podmianie cmake przez
# `pag install` (np. jako zależności glslang/llvm) KAŻDY build cmake'owy pada na
# „cmake: error while loading shared libraries: librhash.so.1”. Wykrywamy to
# działaniem, a nie obecnością pliku (cmake JEST, tylko zepsuty).
if [[ -x "$ROOTFS/usr/bin/cmake" ]]; then
if ! grep -qa 'librhash\.so' "$ROOTFS/usr/bin/cmake" 2>/dev/null; then
: # cmake bez librhash – OK (self-contained)
elif [[ ! -e "$ROOTFS/usr/lib/librhash.so.1" && ! -e "$ROOTFS/usr/lib64/librhash.so.1" ]]; then
info "cmake wymaga librhash.so.1, którego nie ma – doinstalowuję rhash"
_pag_install_in_rootfs "$ROOTFS" rhash
fi
fi
# ── (3) Cache źródeł: nie ściągaj ponownie 160 MB kernela ───────────────────
# pagbuild trzyma źródła w /var/cache/pagbuild/sources (nazwa = basename URL-a,
# chyba że to „tagowa” nazwa typu 610.57.04.tar.gz – wtedy z hashem; kernel ma
# nazwę linux-<ver>.tar.xz, więc trafia do cache pod tą samą nazwą).
# Wersję bierzemy z receptury, żeby nie rozjechała się z tym, co budujemy.
mkdir -p "$SRC_CACHE" "$OUT_DIR"
_kernel_ver="$(python3 -c "import yaml,sys;print(yaml.safe_load(open(sys.argv[1]))['pkgver'])" \
"$SCRIPT_DIR/recipes/utils/kernel/PAGBUILD.yaml" 2>/dev/null || echo 7.2.5)"
for f in "$PAGAN_SRC_ROOT"/sources/linux-"$_kernel_ver".tar.xz; do
[[ -f "$f" ]] || continue
b="$(basename "$f")"
[[ -f "$SRC_CACHE/$b" ]] || { cp -f "$f" "$SRC_CACHE/$b" && ok "Cache źródeł: $b (z $PAGAN_SRC_ROOT/sources)"; }
done
# ── (4) Budowa ──
# Kolejność ma znaczenie: nvidia-kernel buduje się POD ŹRÓDŁA z pakietu kernel
# (/usr/src/kernel), więc po zbudowaniu kernela instalujemy go w rootfsie
# buildera – inaczej Kbuild nie znajdzie drzewa jądra.
#
# Przed każdą recepturą doinstalowujemy jej `makedepends` w rootfsie buildera
# (jedno `pag install` na recepturę). Bez tego ciężkie buildy (mesa z
# -Dvalgrind=enabled, gvfs z libsecret…) padają na konfiguracji, mimo że pakiet
# JEST w repo.
_install_recipe_deps() {
local recipe="$1" deps
deps="$(python3 - "$recipe" <<'PY'
import sys, yaml
d = yaml.safe_load(open(sys.argv[1])) or {}
md = d.get("makedepends") or []
if isinstance(md, str):
md = [md]
# pomijamy wpisy wirtualne (pkgconfig(x), libfoo.so) – to nie nazwy pakietów
print(" ".join(x for x in md if x and not any(c in x for c in "()")))
PY
)"
[[ -n "$deps" ]] || return 0
info " makedepends: $deps"
_pag_install_in_rootfs "$ROOTFS" $deps
}
# ── Auto-zapis configu jądra po udanym buildzie ──────────────────────────────
# Receptura w fazie build robi `make olddefconfig`, więc w pakiecie leży config
# dopasowany do bieżącego Kconfig (boot/config-<release>). Zapisujemy go z
# powrotem do receptury (+ świeży SHA wpisu `config`). Na PC nie ma pagsync,
# dlatego robimy to tutaj; zmiany w recipes/ trzeba zacommitować.
_save_kernel_config() {
local recipe="$1" pag="$2"
[[ -f "$recipe" && -f "$pag" ]] || return 0
python3 - "$recipe" "$pag" <<'PY'
import io, os, sys, tarfile, hashlib
import yaml
recipe, pag = sys.argv[1:3]
cfg = os.path.join(os.path.dirname(os.path.abspath(recipe)), "config")
if not os.path.isfile(cfg):
raise SystemExit
def extract(p):
with tarfile.open(p, "r:xz") as tf:
fh = tf.extractfile("data.tar.xz")
if fh is None:
return None, None
data = fh.read()
with tarfile.open(fileobj=io.BytesIO(data), mode="r:xz") as df:
for ti in df.getmembers():
nm = ti.name[2:] if ti.name.startswith("./") else ti.name
parts = nm.split("/")
if len(parts) == 2 and parts[0] == "boot" and parts[1].startswith("config-"):
fh = df.extractfile(ti)
return (fh.read().decode("utf-8", "replace"), parts[1][len("config-"):]) if fh else (None, None)
return None, None
content, rel = extract(pag)
if not content:
print(" \u23ed save-kernel-config: brak boot/config-* w " + os.path.basename(pag))
raise SystemExit
if not content.endswith("\n"):
content += "\n"
old = open(cfg, encoding="utf-8").read()
if content == old:
print(" \u2705 config kernela aktualny (" + rel + ")")
raise SystemExit
open(cfg, "w", encoding="utf-8").write(content)
sha = hashlib.sha256(open(cfg, "rb").read()).hexdigest()
txt = open(recipe, encoding="utf-8").read()
d = yaml.safe_load(txt) or {}
srcs = d.get("source") or []
if isinstance(srcs, str):
srcs = [srcs]
if "config" in srcs:
idx = srcs.index("config")
lines = txt.split("\n"); start = None
for i, l in enumerate(lines):
if l.startswith("sha256sums:"):
start = i; break
if start is not None:
n = -1
for j in range(start + 1, len(lines)):
l = lines[j]
if l.startswith("- "):
n += 1
if n == idx:
lines[j] = "- " + sha; break
elif l and not l.startswith((" ", "\t")):
break
open(recipe, "w", encoding="utf-8").write("\n".join(lines))
print(" \U0001f4be config kernela zaktualizowany (" + rel + ", sha " + sha[:12] + "…) – zacommituj recipes/")
PY
}
# ── Instalacja zbudowanego pakietu w rootfsie buildera ──────────────────────
# PO CO: łańcuchy zależności w JEDNEJ komendzie (libva → intel-media-driver,
# mesa → xf86-video-*). Bez tego drugi pakiet nie widzi nagłówków/.pc pierwszego
# i pada już na konfiguracji („Package 'libva' not found”), mimo że receptura ma
# go w makedepends – pagbuild instaluje makedepends TYLKO z repo, a świeżo
# zbudowanego pakietu w repo jeszcze nie ma.
# Podmieniamy pliki WŁASNYM pakietem zbudowanym w tym samym rootfsie, więc
# builder pozostaje spójny z targetem (żadnego Debiana tu nie mieszamy).
# Wyłączenie: PAGAN_BUILDER_NO_INSTALL=1
_install_in_builder() {
local pag_file="$1" pkgname="$2" in_chroot_dir _s
[[ "${PAGAN_BUILDER_NO_INSTALL:-0}" == "1" ]] && return 0
[[ -f "$pag_file" ]] || return 0
info " → instaluję $pkgname w rootfsie buildera (widoczność dla kolejnych buildów)"
in_chroot_dir="$ROOTFS/var/cache/pagbuild/out"
mkdir -p "$in_chroot_dir"
cp -f "$pag_file" "$in_chroot_dir/"
# pag weryfikuje lokalny plik FAIL-CLOSED – podpis (jeśli jest) musi trafić do chroot razem z pakietem.
for _s in "$pag_file".asc "$pag_file".sig; do
[[ -f "$_s" ]] && cp -f "$_s" "$in_chroot_dir/"
done
_mount_chroot "$ROOTFS"
trap '_umount_chroot "$ROOTFS"' EXIT
# PAG_INSECURE=1: pakiety budowane TU (na PC) nie są podpisane – nie ma tu
# klucza repo (celowo trzyma go VPS). `pag` jest FAIL-CLOSED dla lokalnych
# plików, więc bez tego instalacja w builderze kończyła się „Brak podpisu dla
# pakietu”. To NASZE, świeżo zbudowane pakiety w NASZYM rootfsie budowy, więc
# pominięcie weryfikacji jest tu bezpieczne i celowe; na systemie docelowym
# podpisy nadal obowiązują (tam instalacja idzie z podpisanego repo).
chroot "$ROOTFS" /usr/bin/env PAG_YES=1 PAG_INSECURE=1 /usr/bin/pag install -y \
"/var/cache/pagbuild/out/$(basename "$pag_file")" \
|| warn " instalacja $pkgname w builderze nieudana – kolejne buildy mogą go nie widzieć"
_umount_chroot "$ROOTFS"
trap - EXIT
}
_built_kernel_pag=""
for pkg in "${PKGS[@]}"; do
info "Budowanie: $pkg"
# UWAGA: NIE pisz tego jako `_recipe="$SCRIPT_DIR/recipes"/*/"$pkg"/PAGBUILD.yaml`!
# Bash NIE rozwija globów w zwykłym przypisaniu (tylko w `arr=( ... )`), więc
# zmienna zostawała LITERALNYM wzorcem z gwiazdką, `[[ -f $_recipe ]]` był
# zawsze fałszywy i makedepends NIGDY nie trafiały do rootfsu buildera – buildy
# padały (meson/cmake/pkg-config nie widziały zależności), a komunikat mówił
# „brak receptury” mimo że receptura leżała na dysku. `find` jest odporne.
_recipe="$(find "$SCRIPT_DIR/recipes" -type f -path "*/$pkg/PAGBUILD.yaml" -print -quit 2>/dev/null || true)"
if [[ -n "$_recipe" && -f "$_recipe" ]]; then
info " receptura: ${_recipe#"$SCRIPT_DIR/"}"
_install_recipe_deps "$_recipe"
else
warn " brak receptury dla '$pkg' w recipes/*/ – pagbuild i tak spróbuje"
_recipe="" # nie przekazuj śmieciowego wzorca do _save_kernel_config
fi
args=( "$pkg" --rootfs "$ROOTFS" --out "$OUT_DIR" )
[[ $DO_SIGN -eq 1 ]] && args+=( --sign )
[[ -n "$GPG_KEY" ]] && args+=( --gpg-key "$GPG_KEY" )
if ! "$SCRIPT_DIR/pagbuild" "${args[@]}"; then
warn "Budowa $pkg NIEUDANA – pomijam"
continue
fi
pag_file="$(ls -1t "$OUT_DIR/$pkg"-*.pag 2>/dev/null | head -n1 || true)"
if [[ -z "$pag_file" ]]; then
warn "$pkg: pagbuild zwrócił 0, ale nie ma $OUT_DIR/$pkg-*.pag"
continue
fi
ok "$pkg → $pag_file ($(du -h "$pag_file" | cut -f1))"
printf ' sha256: %s\n' "$(sha256sum "$pag_file" | cut -d' ' -f1)"
# Auto-zapis configu jądra (olddefconfig) z powrotem do receptury.
case "$pkg" in kernel*) _save_kernel_config "$_recipe" "$pag_file" ;; esac
# ── Bramka ABI ──────────────────────────────────────────────────────────
# Pakiet NIE MOŻE odwoływać się do symboli, których nie ma w docelowym
# PaganLinux. To wyłapuje pakiety zbudowane w chrootcie Debiana na VPS
# (tak wyszły zepsute libgsf z xmlNanoHTTPClose i libavcodec z
# rsvg_handle_render_document). Indeks symboli jest cache'owany.
#
# TRYB ROZJAZDU (--build-rootfs), a NIE „celu”: pytamy wyłącznie o symbole,
# które SĄ w środowisku budowy, a których NIE MA w docelowym systemie – dokładnie
# to znaczy „zbudowano pod inne biblioteki”. Tryb „celu” (bez --build-rootfs)
# raportuje KAŻDĄ zależność spoza obrazu i kończy się kodem 0 (bez --strict),
# więc jako bramka był bezużyteczny: zawsze mówił „ABI zgodne”, mimo że dla
# pakietów repo zależności spoza ISO są normalne (dociąga je `pag`).
# UWAGA do nazwy cache: „-v2” celowo. Cache v1 (/var/cache/pagbuild/target-symbols.txt)
# powstał przy skanie z -maxdepth, więc NIE zawiera symboli modułów z głębszych
# katalogów (np. /usr/lib/xorg/modules/libglamoregl.so → glamor_init) i dawał
# fałszywe „rozjazdy ABI” dla sterowników Xorg. Nowa wersja skanuje całe drzewo.
if [[ -x "$SCRIPT_DIR/check-pag-abi.sh" ]]; then
if PAGAN_ABI_INDEX="${PAGAN_ABI_INDEX:-/var/cache/pagbuild/target-symbols-v2.txt}" \
"$SCRIPT_DIR/check-pag-abi.sh" --rootfs "$PAGAN_SRC_ROOT" \
--build-rootfs "$ROOTFS" --quiet "$pag_file" >/dev/null 2>&1; then
ok " $pkg: brak rozjazdu ABI względem $PAGAN_SRC_ROOT"
else
warn " $pkg: ROZJAZD ABI z $PAGAN_SRC_ROOT – NIE publikuj tego pakietu!"
warn " szczegóły: ./check-pag-abi.sh --rootfs $PAGAN_SRC_ROOT --build-rootfs $ROOTFS $pag_file"
ABI_FAILED+=("$pkg")
fi
fi
# Każdy zbudowany pakiet ląduje w rootfsie buildera, żeby KOLEJNE buildy z tej
# samej komendy widziały jego nagłówki/.pc (np. libva → intel-media-driver).
_install_in_builder "$pag_file" "$pkg"
# Kernel dodatkowo: gwarancja /usr/src/kernel (SYSSRC dla nvidia-kernel/dkms),
# nawet gdy `pag install` odmówi (podpis / konflikt symlinku w /usr/lib/modules).
if [[ "$pkg" == "kernel" ]]; then
_built_kernel_pag="$pag_file"
in_chroot_dir="$ROOTFS/var/cache/pagbuild/out"
mkdir -p "$in_chroot_dir"
# Gwarancja obecności źródeł jądra (SYSSRC dla nvidia-kernel/dkms).
# Bezpośrednie rozpakowanie omija bramkę podpisu pag oraz konflikt
# symlinku w /usr/lib/modules (który nas tu nie interesuje) – bierzemy
# tylko /usr/src i /boot.
if [[ ! -d "$ROOTFS/usr/src/kernel" ]]; then
if tar -xJf "$pag_file" -C "$in_chroot_dir" data.tar.xz 2>/dev/null; then
tar -xJf "$in_chroot_dir/data.tar.xz" -C "$ROOTFS" ./usr/src ./boot 2>/dev/null \
|| warn " niepełne rozpakowanie źródeł jądra"
rm -f "$in_chroot_dir/data.tar.xz"
fi
fi
[[ -d "$ROOTFS/usr/src/kernel" ]] \
|| warn " brak $ROOTFS/usr/src/kernel – nvidia-kernel może się nie zbudować"
fi
done
echo
info "Zbudowane pakiety w: $OUT_DIR"
ls -1sh "$OUT_DIR"/*.pag 2>/dev/null || warn "Brak .pag w $OUT_DIR"
# Bramka ABI: czy któryś pakiet odwołuje się do symboli, których nie ma w obrazie?
if [[ ${#ABI_FAILED[@]} -gt 0 ]]; then
echo
warn "UWAGA: ${#ABI_FAILED[@]} pakiet(ów) z niezgodnym ABI: ${ABI_FAILED[*]}"
warn "Takie pakiety padają na starcie z „undefined symbol”. NIE wgrywaj ich do repo –"
warn "przebuduj natywnie na PC (ten skrypt) albo popraw zależności w recepturze."
_abi_rc=1
else
_abi_rc=0
fi
echo
cat <<EOF
────────────────────────────────────────────────────────────────────────────
PUBLIKACJA (na VPS, tam gdzie stoi repo i pagsync):
1) wgraj pakiety (z tego PC):
rsync -av --progress "$OUT_DIR"/*.pag* ${UPLOAD:-user@vps:/var/www/repo.paganlinux.eu/stable/}
2) na VPS odśwież repo.json (i ewentualnie podpisy):
sudo pagsync --gen-repo --sign # sama regeneracja indeksu
# albo pełny przebieg (skan receptur + kolejka):
sudo pagsync --once --sign
Podpisane paczki muszą leżeć obok .pag jako <nazwa>.pag.asc – jeśli budujesz
z --sign, rsync powyżej zabierze je razem z pakietami.
────────────────────────────────────────────────────────────────────────────
EOF
# Kod wyjścia: 1, gdy którykolwiek pakiet ma niezgodne ABI (łatwe do wykrycia
# w automatyzacji: `./build-repo.sh ... || echo "NIE PUBLIKUJ"`).
exit "$_abi_rc"