From 3f7535f5d0f7d961e04992ff20f327b07d10308d Mon Sep 17 00:00:00 2001 From: stornic56 <71296607+stornic56@users.noreply.github.com> Date: Fri, 16 Oct 2026 12:56:57 -0500 Subject: [PATCH] GNOME: use ptyxis instead of gnome-terminal on trixie+ gnome-core declares the OR-dependency "gnome-terminal (>= 3.56) or gnome-console (>= 46) or ptyxis (>= 47)" (packages.debian.org /trixie/gnome-core, verified 2026-10-16) and apt resolves an unset OR-dep with the FIRST alternative, so the desktop pull would install gnome-terminal by default. Listing the terminal package explicitly in the same apt transaction steers the resolver to ptyxis (48.5-1~deb13u1, GTK4) on trixie. - _gnome_terminal_pkg(): trixie -> ptyxis, anything else or empty -> gnome-terminal (ptyxis does not exist in bookworm). - _install_gnome_full/_install_gnome_core list the resolved package in the pre-apply summary and in the apt command. - No purge or apt-mark: an already-installed gnome-terminal is left alone and both can coexist. - 4 new BATS tests capture the apt command via the existing sudo/_run_cmd mocks: ptyxis on trixie (Full and Core), gnome-terminal fallback on bookworm and on empty codename. Co-authored-by: Claude Opus 4.8 --- modules/desktops/desktop_gnome.sh | 37 ++++++++++++++--- tests/desktops.bats | 68 ++++++++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 7 deletions(-) diff --git a/modules/desktops/desktop_gnome.sh b/modules/desktops/desktop_gnome.sh index c7a2f59..d2b76c7 100644 --- a/modules/desktops/desktop_gnome.sh +++ b/modules/desktops/desktop_gnome.sh @@ -4,6 +4,23 @@ # Debian ships GNOME 48 (13), 43 (12) and 3.38 (11). # License GPL v3 +# Pick the terminal emulator for this release. gnome-core +# declares the OR-dependency "gnome-terminal (>= 3.56) or +# gnome-console (>= 46) or ptyxis (>= 47)" (packages.debian.org +# /trixie/gnome-core, verified 2026-10-16) and apt resolves an +# unset OR-dep with the FIRST alternative, so gnome-core alone +# would pull gnome-terminal. Listing ptyxis in the same apt +# transaction satisfies the OR-dep with ptyxis instead. ptyxis +# (GTK4) exists in trixie (48.5-1~deb13u1) but NOT in bookworm +# (packages.debian.org/bookworm/ptyxis → no such package), hence +# the trixie-only gate. An already-installed gnome-terminal is +# left alone: both can coexist; no purge is ever attempted. +_gnome_terminal_pkg() { + case "${DEBIAN_CODENAME:-}" in + trixie) printf '%s\n' "ptyxis" ;; + *) printf '%s\n' "gnome-terminal" ;; + esac +} gnome_menu() { while true; do local -a gn_items=() @@ -26,8 +43,12 @@ gnome_menu() { _install_gnome_full() { # Pre-apply summary: confirm the selection before any - # debconf or apt transaction starts. - _confirm_install_list "GNOME Full Desktop" gnome gdm3 || return + # debconf or apt transaction starts. The terminal package + # is resolved once (ptyxis on trixie, gnome-terminal + # elsewhere) so the summary lists what apt will install. + local terminal_pkg + terminal_pkg=$(_gnome_terminal_pkg) + _confirm_install_list "GNOME Full Desktop" gnome gdm3 "$terminal_pkg" || return echo -e "${GREEN}Installing GNOME (Full Desktop)...${NC}" @@ -41,7 +62,7 @@ _install_gnome_full() { fi echo "${target_dm} shared/default-x-display-manager select ${target_dm}" | sudo debconf-set-selections _ensure_apt_updated - _run_cmd "GNOME Full" "sudo apt install -y gnome gdm3" \ + _run_cmd "GNOME Full" "sudo apt install -y gnome gdm3 $terminal_pkg" \ "Installing GNOME (Full Meta Package) + GDM3..." if [ "$target_dm" = "gdm3" ]; then sudo systemctl enable gdm3 @@ -55,8 +76,12 @@ _install_gnome_full() { _install_gnome_core() { # Pre-apply summary: confirm the selection before any - # debconf or apt transaction starts. - _confirm_install_list "GNOME Core" gnome-core gdm3 || return + # debconf or apt transaction starts. The terminal package + # is resolved once (ptyxis on trixie, gnome-terminal + # elsewhere) so the summary lists what apt will install. + local terminal_pkg + terminal_pkg=$(_gnome_terminal_pkg) + _confirm_install_list "GNOME Core" gnome-core gdm3 "$terminal_pkg" || return echo -e "${GREEN}Installing GNOME Core (Minimal)...${NC}" @@ -70,7 +95,7 @@ _install_gnome_core() { fi echo "${target_dm} shared/default-x-display-manager select ${target_dm}" | sudo debconf-set-selections _ensure_apt_updated - _run_cmd "GNOME Core" "sudo apt install -y gnome-core gdm3" \ + _run_cmd "GNOME Core" "sudo apt install -y gnome-core gdm3 $terminal_pkg" \ "Installing GNOME Core (Minimal) + GDM3..." if [ "$target_dm" = "gdm3" ]; then sudo systemctl enable gdm3 diff --git a/tests/desktops.bats b/tests/desktops.bats index 3afadc8..f92479c 100644 --- a/tests/desktops.bats +++ b/tests/desktops.bats @@ -34,9 +34,13 @@ setup() { # Re-declare it globally for the _load_module tests. declare -gA _LOADED_MODULES=() + # Only function definitions at the top level: safe to source. # Only function definitions at the top level: safe to source. source "${TEST_PROJECT_ROOT}/modules/desktop_display.sh" - + # The GNOME installers are pure function definitions too; + # desktop_display.sh (their DM/pipewire collaborators) is + # already sourced above. + source "${TEST_PROJECT_ROOT}/modules/desktops/desktop_gnome.sh" # Fixture redirect for /etc/X11/default-display-manager: # the file exists but is empty, so `-s` fails and the # systemctl fallback is exercised deterministically. @@ -188,3 +192,65 @@ _load_module_with_deps_marked() { run _load_module no_such_module [ "$status" -eq 1 ] } + +# ── terminal selection: ptyxis on trixie ────────────── +# gnome-core declares the OR-dep "gnome-terminal or +# gnome-console or ptyxis"; apt resolves an unset OR-dep +# with the first alternative, so listing the terminal +# explicitly in the same apt transaction is what steers +# the resolver. These tests assert the exact package +# that lands in the apt command. +# +# _gnome_capture_apt_cmd runs one installer with every +# external effect stubbed: _run_cmd is replaced so the +# apt command is captured instead of executed, and the +# PATH sudo mock stays in dry-run mode so debconf and +# systemctl invocations are logged, not executed. +_gnome_capture_apt_cmd() { + local installer="$1" + GNOME_APT_CMD="" + _confirm_install_list() { return 0; } + _ensure_apt_updated() { :; } + _run_cmd() { GNOME_APT_CMD="$2"; } + "$installer" + printf '%s\n' "$GNOME_APT_CMD" +} + +@test "GNOME Full installs ptyxis on trixie" { + export DEBIAN_CODENAME="trixie" + export MOCK_SUDO_DRY_RUN=1 + run _gnome_capture_apt_cmd _install_gnome_full + [ "$status" -eq 0 ] + [[ "$output" == *"apt install -y gnome gdm3 ptyxis"* ]] + [[ "$output" != *gnome-terminal* ]] +} + +@test "GNOME Core installs ptyxis on trixie" { + export DEBIAN_CODENAME="trixie" + export MOCK_SUDO_DRY_RUN=1 + run _gnome_capture_apt_cmd _install_gnome_core + [ "$status" -eq 0 ] + [[ "$output" == *"apt install -y gnome-core gdm3 ptyxis"* ]] + [[ "$output" != *gnome-terminal* ]] +} + +@test "GNOME Full falls back to gnome-terminal off trixie" { + export DEBIAN_CODENAME="bookworm" + export MOCK_SUDO_DRY_RUN=1 + run _gnome_capture_apt_cmd _install_gnome_full + [ "$status" -eq 0 ] + [[ "$output" == *"apt install -y gnome gdm3 gnome-terminal"* ]] + [[ "$output" != *ptyxis* ]] +} + +@test "GNOME falls back to gnome-terminal when the codename is empty" { + # /etc/os-release missing or without VERSION_CODENAME + # leaves DEBIAN_CODENAME unset: the safe default is the + # historical behaviour. + export DEBIAN_CODENAME="" + export MOCK_SUDO_DRY_RUN=1 + run _gnome_capture_apt_cmd _install_gnome_full + [ "$status" -eq 0 ] + [[ "$output" == *"apt install -y gnome gdm3 gnome-terminal"* ]] + [[ "$output" != *ptyxis* ]] +}