Skip to content

Commit 0807d03

Browse files
authored
fix(install): show detected distro in sudo apt Accept prompt (#7324)
* fix(install): show detected distro in sudo apt Accept prompt Make the package-install elevation prompt name the detected distro and state that packages come from official apt repos, so users know we are not installing a tarball outside their package manager (#6207). * fix(install): avoid case/;; inside $() for bash 3.2 macOS CI uses bash 3.2, which misparses case arms inside command substitution and fails install.sh at the apt distro helper. Use a plain subshell so the Accept? prompt still works everywhere.
1 parent f5a0c22 commit 0807d03

2 files changed

Lines changed: 128 additions & 1 deletion

File tree

install.sh

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,36 @@ _is_pkg_installed() {
625625
esac
626626
}
627627

628+
# ── Helper: human-readable apt distro label for the sudo package prompt (#6207) ──
629+
# Reads /etc/os-release so the Accept? prompt can say which distro we detected and
630+
# that packages come from that distro's official apt repos (not a tarball).
631+
_apt_distro_description() {
632+
# Plain ( ... ) subshell — not $() — so case/;; stays bash-3.2-safe on macOS.
633+
# Bash 3.2 misparses case arms inside command substitution and errors on `;;`.
634+
(
635+
if [ ! -r /etc/os-release ]; then
636+
printf 'a debian-like system'
637+
exit 0
638+
fi
639+
# shellcheck disable=SC1091
640+
. /etc/os-release 2>/dev/null || true
641+
if [ -n "${NAME:-}" ] && [ -n "${VERSION_ID:-}" ]; then
642+
_ad_label="$NAME $VERSION_ID"
643+
elif [ -n "${PRETTY_NAME:-}" ]; then
644+
_ad_label="$PRETTY_NAME"
645+
elif [ -n "${NAME:-}" ]; then
646+
_ad_label="$NAME"
647+
else
648+
printf 'a debian-like system'
649+
exit 0
650+
fi
651+
case " ${ID:-} ${ID_LIKE:-} " in
652+
*" debian "*|*" ubuntu "*) _ad_label="${_ad_label} (debian-like)" ;;
653+
esac
654+
printf '%s' "$_ad_label"
655+
)
656+
}
657+
628658
# ── Helper: install packages via apt, escalating to sudo only if needed ──
629659
# Usage: _smart_apt_install pkg1 pkg2 pkg3 ...
630660
_smart_apt_install() {
@@ -655,11 +685,14 @@ _smart_apt_install() {
655685

656686
# Step 3: Escalate -- need elevated permissions for remaining packages
657687
if command -v sudo >/dev/null 2>&1; then
688+
_ad_desc="$(_apt_distro_description)"
658689
echo ""
659690
echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
660691
echo " WARNING: We require sudo elevated permissions to install:"
661692
echo " $_STILL_MISSING"
662-
echo " If you accept, we'll run sudo now, and it'll prompt your password."
693+
echo " Detected ${_ad_desc}."
694+
echo " If you accept, we'll run sudo apt-get to install these packages"
695+
echo " from your distro's official repositories (not a third-party tarball)."
663696
echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
664697
echo ""
665698
printf " Accept? [Y/n] "

tests/sh/test_apt_distro_prompt.sh

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: AGPL-3.0-only
3+
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
4+
# Unit tests for install.sh's _apt_distro_description helper (#6207).
5+
# The sudo Accept? prompt should name the detected distro and say packages come
6+
# from official apt repos. Hermetic: extract the helper and rewrite
7+
# /etc/os-release to per-test fixtures (same pattern as test_strixhalo_wsl_reroute.sh).
8+
set -e
9+
10+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
11+
INSTALL_SH="$SCRIPT_DIR/../../install.sh"
12+
PASS=0
13+
FAIL=0
14+
15+
_TMP_ROOT=$(mktemp -d)
16+
trap 'rm -rf "$_TMP_ROOT"' EXIT
17+
18+
assert_eq() {
19+
_label="$1"; _expected="$2"; _actual="$3"
20+
if [ "$_actual" = "$_expected" ]; then
21+
echo " PASS: $_label"; PASS=$((PASS + 1))
22+
else
23+
echo " FAIL: $_label (expected '$_expected', got '$_actual')"; FAIL=$((FAIL + 1))
24+
fi
25+
}
26+
27+
assert_contains() {
28+
_label="$1"; _hay="$2"; _needle="$3"
29+
case "$_hay" in
30+
*"$_needle"*) echo " PASS: $_label"; PASS=$((PASS + 1)) ;;
31+
*) echo " FAIL: $_label (missing '$_needle' in: $_hay)"; FAIL=$((FAIL + 1)) ;;
32+
esac
33+
}
34+
35+
# Extract helper with /etc/os-release rewritten to $1.
36+
build_func() {
37+
_fix="$1"
38+
_f=$(mktemp -p "$_TMP_ROOT")
39+
sed -n '/^_apt_distro_description()/,/^}/p' "$INSTALL_SH" \
40+
| sed -e "s#/etc/os-release#$_fix/os-release#g" \
41+
> "$_f"
42+
echo "$_f"
43+
}
44+
45+
run_desc() {
46+
_os="$1"
47+
_d=$(mktemp -d -p "$_TMP_ROOT")
48+
printf '%s\n' "$_os" > "$_d/os-release"
49+
_f=$(build_func "$_d")
50+
# shellcheck disable=SC1090
51+
. "$_f"
52+
_apt_distro_description
53+
}
54+
55+
echo "=== _apt_distro_description ==="
56+
57+
assert_eq "ubuntu name+version debian-like" \
58+
"Ubuntu 24.04 (debian-like)" \
59+
"$(run_desc "$(printf 'NAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nID=ubuntu\nID_LIKE=debian\n')")"
60+
61+
assert_eq "debian name+version debian-like" \
62+
"Debian GNU/Linux 12 (debian-like)" \
63+
"$(run_desc "$(printf 'NAME=\"Debian GNU/Linux\"\nVERSION_ID=\"12\"\nID=debian\n')")"
64+
65+
assert_eq "pretty_name fallback when name/version missing" \
66+
"Linux Mint 22 (debian-like)" \
67+
"$(run_desc "$(printf 'PRETTY_NAME=\"Linux Mint 22\"\nID=linuxmint\nID_LIKE=\"ubuntu debian\"\n')")"
68+
69+
# NAME alone (no VERSION_ID) — still prefer NAME over PRETTY_NAME.
70+
assert_eq "name only" \
71+
"Pop!_OS (debian-like)" \
72+
"$(run_desc "$(printf 'NAME=\"Pop!_OS\"\nID=pop\nID_LIKE=\"ubuntu debian\"\n')")"
73+
74+
assert_eq "missing os-release file" \
75+
"a debian-like system" \
76+
"$(
77+
_d=$(mktemp -d -p "$_TMP_ROOT")
78+
_f=$(build_func "$_d")
79+
# shellcheck disable=SC1090
80+
. "$_f"
81+
_apt_distro_description
82+
)"
83+
84+
echo "=== _smart_apt_install prompt contract ==="
85+
_smart=$(sed -n '/^_smart_apt_install()/,/^}/p' "$INSTALL_SH")
86+
assert_contains "calls distro helper" "$_smart" '_apt_distro_description'
87+
assert_contains "names detected distro" "$_smart" 'Detected ${_ad_desc}'
88+
assert_contains "mentions apt-get" "$_smart" 'sudo apt-get'
89+
assert_contains "mentions official repos" "$_smart" "official repositories"
90+
assert_contains "rejects tarball worry" "$_smart" "not a third-party tarball"
91+
92+
echo ""
93+
echo "Results: $PASS passed, $FAIL failed"
94+
[ "$FAIL" -eq 0 ]

0 commit comments

Comments
 (0)