Files
debianito-post-install/modules/repos.sh
T
stornic56 a91b0caa25 critical-fixes, swap module & gaming overhaul
- Fixed script crashes from `whiptail` Cancel/Esc under `set -e`. Added `_menu()`, `_checklist()` and `_inputbox()` wrappers with `|| true` to prevent premature exits.
- Resolved startup failures by using defaults instead of relying on unset variables with `set -u`.
- Hardened sudoers management — `_validate_sudoers()` writes to temp file, validates with `visudo -cf`, only copies if successful.
- Replaced `eval` in `_run_cmd` with safer `bash -c` execution.

Swap Management Module (`modules/swap.sh`)
- New standalone module with 9 internal functions and `manage_swap()` entry point.
- Btrfs CoW detection — applies `chattr +C` before swapfile creation to prevent mkswap rejection on Btrfs.
- Dynamic swappiness configuration — reads current system value instead of hardcoding 60, pre-fills inputbox with existing setting.
- Uses `/run/lock/debianito-swap.lock` for early init compatibility (added as option 9 in main menu).

Repository & Branch Migration (`modules/repos/migrate.sh`)
- Handles branch migration from stable (11/12) to Testing or SID with 5-screen UX flow.
- Persistent backup system — creates timestamped tar.gz backups of `/etc/apt/sources.list*`, auto-restores on apt update failure.
- SID guardrails — installs `apt-listbugs` and `apt-listchanges` before upgrade to warn about critical bugs in unstable packages.
- Dynamic menu options based on Debian version (SID shows only 1-2-3 Exit, non-SID includes backports + branch migration).
- New `_components_enabled()` helper detects current contrib/non-free state.

Gaming Module Overhaul
- Unified gaming checklist — merged i386 toggle into single prompt with lazy evaluation instead of separate pre-check.
- Lazy 32-bit architecture enablement — only enables i386 when needed (steam/lutris/i386 selected) and installs graphics drivers if `need_32bit=true`.
- New `_install_nvidia_32bit()` helper with proper driver detection, version pinning, and legacy/tesla variant handling.

Heroic & OpenRGB Downloads
- Heroic — fetches latest release from GitHub API using `jq` to extract amd64.deb URL, validates with `dpkg-deb --info`.
- OpenRGB — downloads from Codeberg Gitea API with SHA256 verification when available, fallback to `dpkg-deb` validation.
- Dynamic codename detection — now detects Bookworm vs Trixie at runtime instead of hardcoded static values for .deb download URLs.

|Other Improvements
- Renumbered main menu: 8=ZRAM, 9=Swap Management, 10=Extras, 11=Boot Rescue, 12=Exit.
- Improved `detect_storage()` — excludes loop/CD-ROM devices via `lsblk -e 7,11`, explicitly skips zram, detects USB/SD via `/sys/block/$name/removable`.
- Standardized SCROLL_HINT across all files with centralized readonly variable.
2026-07-10 01:42:57 -05:00

496 lines
17 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
source "${MODULES_DIR}/repos/migrate.sh" 2>/dev/null || true
# State for backup/restore
REPO_BACKUP_DIR=""
backup_current_repos() {
REPO_BACKUP_DIR=$(mktemp -d)
for f in /etc/apt/sources.list /etc/apt/sources.list.d/debian.sources \
/etc/apt/sources.list.d/debian-backports.list /etc/apt/sources.list.d/debian-backports.sources; do
if [ -f "$f" ]; then
mkdir -p "$REPO_BACKUP_DIR/$(dirname "${f#/etc/apt/}")"
cp "$f" "$REPO_BACKUP_DIR/$(dirname "${f#/etc/apt/}")/$(basename "$f")"
fi
done
}
restore_previous_repos() {
if [ -z "$REPO_BACKUP_DIR" ] || [ ! -d "$REPO_BACKUP_DIR" ]; then
return
fi
echo -e "${RED}Restoring previous repository configuration...${NC}"
local found=false
for f in /etc/apt/sources.list /etc/apt/sources.list.d/debian.sources \
/etc/apt/sources.list.d/debian-backports.list /etc/apt/sources.list.d/debian-backports.sources; do
local rel="${f#/etc/apt/}"
local backup_file="$REPO_BACKUP_DIR/$rel"
if [ -f "$backup_file" ]; then
sudo cp "$backup_file" "$f"
found=true
elif [ -f "$f" ]; then
sudo rm -f "$f"
found=true
fi
done
if $found; then
sudo rm -f /etc/apt/sources.list.disabled
fi
rm -rf "$REPO_BACKUP_DIR"
REPO_BACKUP_DIR=""
}
cleanup_repo_backup() {
if [ -n "$REPO_BACKUP_DIR" ] && [ -d "$REPO_BACKUP_DIR" ]; then
rm -rf "$REPO_BACKUP_DIR"
REPO_BACKUP_DIR=""
fi
}
# ---------------------------------------------------------------------------
# Cleanup helpers for embedded backports
# ---------------------------------------------------------------------------
_clean_embedded_backports_classic() {
local codename="$1"
local file="/etc/apt/sources.list"
[ ! -f "$file" ] && return
grep -qE "^[^#]*${codename}-backports\b" "$file" 2>/dev/null || return
if _confirm "Clean Classic Sources" "Remove backports line from ${file}?"; then
sudo sed -i "/${codename}-backports/d" "$file"
echo "Removed backports from ${file}"
fi
}
_clean_embedded_backports_deb822() {
local codename="$1"
local file="/etc/apt/sources.list.d/debian.sources"
[ ! -f "$file" ] && return
# Only proceed if the Suites line contains the backports token
grep -qE "^Suites:.*${codename}-backports\b" "$file" 2>/dev/null || return
if _confirm "Clean deb822 Sources" "Remove backports suite from ${file}?"; then
# Remove only the backports token, leaving other suites intact
sudo sed -i "s/[[:space:]]*${codename}-backports[[:space:]]*/ /g" "$file"
# Clean up whitespace on Suites lines
sudo sed -i '/^Suites:[[:space:]]*$/d' "$file" 2>/dev/null || true
echo "Removed backports suite from ${file}"
fi
}
# ---------------------------------------------------------------------------
# Write functions idempotent, with _confirm dialogs
# ---------------------------------------------------------------------------
_write_deb822() {
local codename="$1" action="$2" bp_enabled="$3" bp_location="$4"
local components="${5:-main contrib non-free non-free-firmware}"
local main_file="/etc/apt/sources.list.d/debian.sources"
local main_content=""
main_content+="Types: deb\n"
main_content+="URIs: https://deb.debian.org/debian\n"
main_content+="Suites: ${codename} ${codename}-updates\n"
main_content+="Components: ${components}\n"
main_content+="\n"
main_content+="Types: deb\n"
main_content+="URIs: https://security.debian.org/debian-security\n"
main_content+="Suites: ${codename}-security\n"
main_content+="Components: ${components}\n"
if content_differs "$main_file" "$main_content"; then
if _confirm "Deb822 Sources" "Write main deb822 configuration to ${main_file}?"; then
sudo mkdir -p /etc/apt/sources.list.d
echo -e "$main_content" | sudo tee "$main_file" > /dev/null
echo "Wrote ${main_file}"
else
echo "Main repository configuration skipped."
return 1
fi
fi
# Backports: always in separate file
if [ "$bp_enabled" = true ]; then
_write_deb822_backports "$codename"
else
_remove_deb822_backports "$codename"
fi
# On migration from classic, disable the old file
if [ "$action" = "migrate" ] && [ "$bp_location" = "embedded-classic" -o "$bp_location" = "standalone-classic" ]; then
if [ -f /etc/apt/sources.list ]; then
if _confirm "Disable Classic" "Migrating to deb822. Disable /etc/apt/sources.list?"; then
sudo mv /etc/apt/sources.list /etc/apt/sources.list.disabled
echo "Classic sources.list disabled (renamed to sources.list.disabled)"
fi
fi
fi
# Clean embedded backports from old classic file if they existed there
if [ "$bp_location" = "embedded-classic" ]; then
_clean_embedded_backports_classic "$codename"
fi
}
_write_deb822_backports() {
local codename="$1"
local bp_file="/etc/apt/sources.list.d/debian-backports.sources"
local bp_content=""
bp_content+="Types: deb\n"
bp_content+="URIs: https://deb.debian.org/debian\n"
bp_content+="Suites: ${codename}-backports\n"
bp_content+="Components: main contrib non-free non-free-firmware\n"
if content_differs "$bp_file" "$bp_content"; then
if _confirm "Deb822 Backports" "Write backports to ${bp_file}?"; then
sudo mkdir -p /etc/apt/sources.list.d
echo -e "$bp_content" | sudo tee "$bp_file" > /dev/null
echo "Wrote ${bp_file}"
fi
fi
# If backports were formerly embedded in debian.sources, clean them
grep -qE "^Suites:.*${codename}-backports\b" /etc/apt/sources.list.d/debian.sources 2>/dev/null && \
_clean_embedded_backports_deb822 "$codename"
}
_remove_deb822_backports() {
local codename="$1"
local bp_file="/etc/apt/sources.list.d/debian-backports.sources"
if [ -f "$bp_file" ]; then
if _confirm "Remove Backports" "Remove ${bp_file}?"; then
sudo rm -f "$bp_file"
echo "Removed ${bp_file}"
fi
fi
# Also clean any embedded backports in main debian.sources
grep -qE "^Suites:.*${codename}-backports\b" /etc/apt/sources.list.d/debian.sources 2>/dev/null && \
_clean_embedded_backports_deb822 "$codename"
# Clean embedded backports from classic file too (safety net)
_clean_embedded_backports_classic "$codename"
}
_write_classic() {
local codename="$1" action="$2" bp_enabled="$3" bp_location="$4"
local components="${5:-main contrib non-free non-free-firmware}"
local main_file="/etc/apt/sources.list"
local main_content=""
main_content+="# Official repository\n"
main_content+="deb https://deb.debian.org/debian ${codename} ${components}\n"
main_content+="# deb-src https://deb.debian.org/debian ${codename} ${components}\n"
main_content+="\n"
main_content+="# Updates\n"
main_content+="deb https://deb.debian.org/debian ${codename}-updates ${components}\n"
main_content+="# deb-src https://deb.debian.org/debian ${codename}-updates ${components}\n"
main_content+="\n"
main_content+="# Security\n"
main_content+="deb https://security.debian.org/debian-security ${codename}-security ${components}\n"
main_content+="# deb-src https://security.debian.org/debian-security ${codename}-security ${components}\n"
if content_differs "$main_file" "$main_content"; then
if _confirm "Classic Sources" "Write main classic configuration to ${main_file}?"; then
echo -e "$main_content" | sudo tee "$main_file" > /dev/null
echo "Wrote ${main_file}"
else
echo "Main repository configuration skipped."
return 1
fi
fi
# Backports: always in separate file
if [ "$bp_enabled" = true ]; then
_write_classic_backports "$codename"
else
_remove_classic_backports "$codename"
fi
# On migration from deb822, disable the old file
if [ "$action" = "migrate" ]; then
if [ -f /etc/apt/sources.list.d/debian.sources ]; then
if _confirm "Disable Deb822" "Migrating to classic format. Disable /etc/apt/sources.list.d/debian.sources?"; then
sudo mv /etc/apt/sources.list.d/debian.sources /etc/apt/sources.list.d/debian.sources.disabled
echo "Deb822 sources disabled (renamed to debian.sources.disabled)"
fi
fi
fi
# Clean embedded backports from old deb822 file if they existed there
if [ "$bp_location" = "embedded-deb822" ]; then
_clean_embedded_backports_deb822 "$codename"
fi
}
_write_classic_backports() {
local codename="$1"
local bp_file="/etc/apt/sources.list.d/debian-backports.list"
local bp_content=""
bp_content+="# Backports\n"
bp_content+="deb https://deb.debian.org/debian ${codename}-backports main contrib non-free non-free-firmware\n"
if content_differs "$bp_file" "$bp_content"; then
if _confirm "Classic Backports" "Write backports to ${bp_file}?"; then
sudo mkdir -p /etc/apt/sources.list.d
echo -e "$bp_content" | sudo tee "$bp_file" > /dev/null
echo "Wrote ${bp_file}"
fi
fi
# If backports were formerly embedded in sources.list, clean them
grep -qE "^[^#]*${codename}-backports\b" /etc/apt/sources.list 2>/dev/null && \
_clean_embedded_backports_classic "$codename"
}
_remove_classic_backports() {
local codename="$1"
local bp_file="/etc/apt/sources.list.d/debian-backports.list"
if [ -f "$bp_file" ]; then
if _confirm "Remove Backports" "Remove ${bp_file}?"; then
sudo rm -f "$bp_file"
echo "Removed ${bp_file}"
fi
fi
# Also clean any embedded backports in main sources.list
grep -qE "^[^#]*${codename}-backports\b" /etc/apt/sources.list 2>/dev/null && \
_clean_embedded_backports_classic "$codename"
# Clean embedded backports from deb822 file too (safety net)
_clean_embedded_backports_deb822 "$codename"
}
# ---------------------------------------------------------------------------
# Main entry point
# ---------------------------------------------------------------------------
configure_repos() {
echo -e "${YELLOW}Repository configuration...${NC}"
if [ -z "$DEBIAN_CODENAME" ]; then
echo -e "${RED}Error: Could not detect Debian codename. Aborting.${NC}"
return 1
fi
# ── Repositories submenu ──
while true; do
local repo_choice
if [ "$DEBIAN_CODENAME" = "sid" ]; then
repo_choice=$(_menu "Repositories" \
"Select an option:" $TUI_ALTO $TUI_ANCHO 6 \
"1" "Enable Contrib & Non-Free Components" \
"2" "Migrate traditional sources.list to DEB822 format" \
"3" "Back to main menu")
else
repo_choice=$(_menu "Repositories" \
"Select an option:" $TUI_ALTO $TUI_ANCHO 6 \
"1" "Enable Contrib & Non-Free Components" \
"2" "Migrate traditional sources.list to DEB822 format" \
"3" "Setup/Update Backports repositories" \
"4" "[ADVANCED] Upgrade system branch (Testing / SID)" \
"5" "Back to main menu")
fi
[ -z "$repo_choice" ] && break
clear
case "$repo_choice" in
1) _repos_enable_components ;;
2) _repos_migrate_format ;;
3)
if [ "$DEBIAN_CODENAME" = "sid" ]; then
break
else
_repos_setup_backports
fi
;;
4) _branch_migration || true ;;
5) break ;;
esac
done
}
# ---------------------------------------------------------------------------
# Submenu helpers
# ---------------------------------------------------------------------------
_components_enabled() {
if [ -f /etc/apt/sources.list.d/debian.sources ]; then
grep -qE "^Components:.*\b(contrib|non-free)\b" /etc/apt/sources.list.d/debian.sources 2>/dev/null && return 0
fi
if [ -f /etc/apt/sources.list ]; then
grep -qE "^[^#]*\b(contrib|non-free)\b" /etc/apt/sources.list 2>/dev/null && return 0
fi
return 1
}
_repos_offer_upgrade() {
local upgradable
upgradable=$(apt list --upgradable 2>/dev/null | grep -c /)
if [ "$upgradable" -gt 0 ]; then
if _confirm "Upgrade System" "$upgradable packages can be upgraded. Upgrade now?"; then
sudo apt-mark hold tzdata 2>/dev/null || true
_run_cmd "Upgrade" "sudo apt upgrade -y" "Upgrading system..."
sudo apt-mark unhold tzdata 2>/dev/null || true
sudo apt autoremove -y
sudo apt autoclean
echo -e "${GREEN}System upgraded.${NC}"
else
echo "Skipping upgrade."
fi
fi
}
_repos_enable_components() {
local current_format bp_enabled bp_location components
current_format=$(detect_repo_format)
if _components_enabled; then
if ! _confirm "Disable Components" \
"Contrib and non-free are already enabled. Disable them?"; then
echo "No changes made."
_pause
return
fi
components="main"
else
if ! _confirm "Enable Components" \
"Enable contrib and non-free components?\n\n\
Needed for proprietary drivers, firmware, and other popular\n\
software (like gaming platforms and proprietary tools)." 12 60; then
echo "No changes made."
_pause
return
fi
components="main contrib non-free non-free-firmware"
fi
bp_enabled=false
bp_location="none"
if detect_backports_status "$DEBIAN_CODENAME"; then
bp_enabled=true
bp_location=$(detect_backports_location "$DEBIAN_CODENAME")
fi
backup_current_repos
if [ "$current_format" = "deb822" ] || [ "$current_format" = "none" ]; then
_write_deb822 "$DEBIAN_CODENAME" "write" "$bp_enabled" "$bp_location" "$components"
else
_write_classic "$DEBIAN_CODENAME" "write" "$bp_enabled" "$bp_location" "$components"
fi
echo "Updating package lists..."
if sudo apt update; then
REPOS_CONFIGURED=true
cleanup_repo_backup
echo -e "${GREEN}Repository components configured.${NC}"
_repos_offer_upgrade
else
restore_previous_repos
echo -e "${RED}apt update failed. Previous configuration restored.${NC}"
fi
_pause
}
_repos_migrate_format() {
local current_format bp_enabled bp_location
current_format=$(detect_repo_format)
if [ "$current_format" != "classic" ]; then
echo "Repositories are already in DEB822 format."
_pause
return
fi
if [ "$DEBIAN_CODENAME" != "trixie" ]; then
echo "Format migration is only relevant for Debian 13 (Trixie)."
_pause
return
fi
# Preserve existing backports state across format migration
bp_enabled=false
bp_location="none"
if detect_backports_status "$DEBIAN_CODENAME"; then
bp_enabled=true
bp_location=$(detect_backports_location "$DEBIAN_CODENAME")
fi
backup_current_repos
_write_deb822 "$DEBIAN_CODENAME" "migrate" "$bp_enabled" "$bp_location"
echo "Updating package lists..."
if sudo apt update; then
REPOS_CONFIGURED=true
cleanup_repo_backup
echo -e "${GREEN}Repository format migrated to DEB822.${NC}"
else
restore_previous_repos
echo -e "${RED}apt update failed. Backup restored.${NC}"
fi
_pause
}
_repos_setup_backports() {
local current_format bp_status bp_location
current_format=$(detect_repo_format)
if detect_backports_status "$DEBIAN_CODENAME"; then
bp_status="enabled"
else
bp_status="disabled"
fi
bp_location=$(detect_backports_location "$DEBIAN_CODENAME")
echo "Backports are currently $bp_status."
local enable_backports=false
if _confirm "Backports" "Do you want to enable the official Debian Backports repository?\n\n\
Backports provides newer, selectively updated packages from the next\n\
Debian testing branch, recompiled to run stably on your current system.\n\n\
Answer NO to disable or remove backports if they are currently enabled." 16 70; then
enable_backports=true
fi
# Nothing to do — already in desired state
if { $enable_backports && [ "$bp_status" = "enabled" ]; } || \
{ ! $enable_backports && [ "$bp_status" = "disabled" ]; }; then
echo "Backports are already configured as requested."
_pause
return
fi
backup_current_repos
if $enable_backports; then
if [ "$current_format" = "deb822" ]; then
_write_deb822_backports "$DEBIAN_CODENAME"
else
_write_classic_backports "$DEBIAN_CODENAME"
fi
else
if [ "$current_format" = "deb822" ]; then
_remove_deb822_backports "$DEBIAN_CODENAME"
else
_remove_classic_backports "$DEBIAN_CODENAME"
fi
fi
echo "Updating package lists..."
if sudo apt update; then
cleanup_repo_backup
echo -e "${GREEN}Backports configured.${NC}"
else
restore_previous_repos
echo -e "${RED}apt update failed. Backup restored.${NC}"
fi
_pause
}