From 3fbdd754c16b02e4f299b1ce1fadcad15b691b19 Mon Sep 17 00:00:00 2001 From: Sir Blob Date: Sun, 20 Sep 2026 23:13:32 +0000 Subject: [PATCH] Find systemd units on disk and report the packages the desktop needs --- docs/install.md | 28 ++++++++++++++++++++------ docs/packages.md | 8 ++++++++ install.sh | 1 + install/helpers/lib.sh | 17 +++++++++++++++- install/steps/login.sh | 27 ++++++++++++++++++++------ install/steps/packages.sh | 41 ++++++++++++++++++++++++++++++++++++++- 6 files changed, 108 insertions(+), 14 deletions(-) diff --git a/docs/install.md b/docs/install.md index cdc595f..dbca8eb 100644 --- a/docs/install.md +++ b/docs/install.md @@ -30,7 +30,10 @@ with `--check`. than assuming step 1 ran. 3. **Packages** come from `packages/blob.packages` and `packages/blob-aur.packages`. A machine with no AUR helper gets `yay-bin` - built once with `makepkg`. See [packages.md](packages.md). + built once with `makepkg`. A failed batch refreshes the databases and retries, + then falls back to one package at a time, so a single name that no longer + resolves cannot cost you the other hundred and the config, service and login + steps below. See [packages.md](packages.md). 4. **Config** is copied into `~/.config`: `hypr/`, the themed app configs, `blob/shell.json`, the uwsm environment, and the icon font. `session/profile.sh` also goes to `/etc/profile.d/blob.sh`, which sources @@ -63,7 +66,17 @@ with `--check`. avahi, docker, power-profiles-daemon, and oomd. `NetworkManager-wait-online.service` is masked so a slow DHCP lease cannot hold up the login screen. -9. **The login screen** is SDDM. Three pieces have to be in place: +9. **The login screen** is SDDM. It has to be installed first: if + `sddm.service` is not there, the installer says whether the package is + missing or whether systemd has simply not re-read its units yet, and carries + on without enabling anything. A unit counts as present when `systemctl cat` + finds it or when its file is under `/etc/systemd/system`, + `/run/systemd/system`, `/usr/local/lib/systemd/system` or + `/usr/lib/systemd/system` - `systemctl` goes through the service manager, so + it reports a perfectly good unit as missing inside a chroot or right after + pacman wrote it. + + Three pieces have to be in place: | File | Why | | --- | --- | @@ -97,10 +110,13 @@ with `--check`. `--autologin` writes `zzz-blob-autologin.conf`, the only file that sorts after `zz-blob.conf`. -10. **Launch.** When the installer was run from a console and nothing graphical - is running, it starts `sddm.service` so the desktop appears without a reboot. - `--no-launch` prints the command instead. `--autologin` writes - `/etc/sddm.conf.d/zzz-blob-autologin.conf` for the current user. +10. **Launch.** `sddm`, `hyprland`, `quickshell` and `uwsm` are checked one last + time and any that are missing are named, because that is the whole difference + between a desktop and a console. Then, when the installer was run from a + console and nothing graphical is running, it starts `sddm.service` so the + desktop appears without a reboot. `--no-launch` prints the command instead. + `--autologin` writes `/etc/sddm.conf.d/zzz-blob-autologin.conf` for the + current user. ## Flags diff --git a/docs/packages.md b/docs/packages.md index c1a21d4..0ff20f5 100644 --- a/docs/packages.md +++ b/docs/packages.md @@ -81,6 +81,14 @@ packages pulled in under a different name no longer come back on every run. AUR packages are built one at a time, so a build that fails is reported at the end instead of stopping the install. +Repo packages go in one `pacman` call. If that call fails the databases are +refreshed with `pacman -Sy` and it is tried again, because a stale database is +what turns an installed-and-present package into `target not found`. If it still +fails the packages are installed one at a time, so one unresolvable name does not +block the other hundred - which is how a missing `sddm` used to turn into a +machine with no login screen. `install.sh` ends by naming any of `sddm`, +`hyprland`, `quickshell` and `uwsm` that are still not installed. + `./install.sh --check` lists what it would install without installing anything, and `--skip-packages` does the directories and config only. diff --git a/install.sh b/install.sh index a2b5e6f..b089e19 100755 --- a/install.sh +++ b/install.sh @@ -82,6 +82,7 @@ install_session_entry install_autologin enable_display_manager report_login_conflicts +report_desktop_essentials say "" if [[ $check == true ]]; then diff --git a/install/helpers/lib.sh b/install/helpers/lib.sh index 4a6d9df..f43d760 100644 --- a/install/helpers/lib.sh +++ b/install/helpers/lib.sh @@ -8,8 +8,23 @@ note_change() { changes=$((changes + 1)) } +unit_search_dirs=( + /etc/systemd/system + /run/systemd/system + /usr/local/lib/systemd/system + /usr/lib/systemd/system +) + system_unit_exists() { - systemctl cat -- "$1" &>/dev/null + local unit="$1" dir + + systemctl cat -- "$unit" &>/dev/null && return 0 + + for dir in "${unit_search_dirs[@]}"; do + [[ -e $dir/$unit ]] && return 0 + done + + return 1 } user_manager_available() { diff --git a/install/steps/login.sh b/install/steps/login.sh index 513a305..f44a0a4 100644 --- a/install/steps/login.sh +++ b/install/steps/login.sh @@ -85,7 +85,13 @@ report_login_conflicts() { # its default target is multi-user.target, which never pulls in graphical.target. enable_display_manager() { if ! system_unit_exists sddm.service; then - say "WARN sddm.service not found; the desktop cannot start at boot" + if package_installed sddm; then + say "WARN sddm is installed but sddm.service is not visible to systemd" + say " run 'sudo systemctl daemon-reload', then ./install.sh again" + else + say "WARN sddm is not installed; the desktop cannot start at boot" + say " install it with 'sudo pacman -S sddm', then ./install.sh again" + fi return 0 fi @@ -114,13 +120,19 @@ enable_display_manager() { fi if [[ $enable_needed == true ]]; then - as_root systemctl enable sddm.service - say "enable sddm.service" + if as_root systemctl enable sddm.service; then + say "enable sddm.service" + else + say "WARN could not enable sddm.service" + fi fi if [[ $target_needed == true ]]; then - as_root systemctl set-default graphical.target - say "set default target to graphical.target" + if as_root systemctl set-default graphical.target; then + say "set default target to graphical.target" + else + say "WARN could not set the default target to graphical.target" + fi fi } @@ -137,6 +149,7 @@ launch_desktop() { fi if ! system_unit_exists sddm.service; then + say "No login screen to start: sddm is not installed." return 0 fi @@ -151,5 +164,7 @@ launch_desktop() { fi say "Starting the login screen. Pick the Blob session to log in." - as_root systemctl start sddm.service + as_root systemctl start sddm.service || { + say "WARN sddm.service did not start; see 'systemctl status sddm'" + } } diff --git a/install/steps/packages.sh b/install/steps/packages.sh index 40a288b..d745405 100644 --- a/install/steps/packages.sh +++ b/install/steps/packages.sh @@ -58,7 +58,7 @@ install_packages() { if (( ${#repo_missing[@]} )); then say "install ${#repo_missing[@]} repo package(s)" - as_root pacman -S --needed --noconfirm "${repo_missing[@]}" + install_repo_packages "${repo_missing[@]}" fi if (( ${#aur_missing[@]} )); then @@ -71,6 +71,45 @@ install_packages() { fi } +install_repo_packages() { + local package + local -a failed=() + + as_root pacman -S --needed --noconfirm "$@" && return 0 + + say "WARN the batch install failed; refreshing the package databases" + as_root pacman -Sy --noconfirm || true + as_root pacman -S --needed --noconfirm "$@" && return 0 + + say "WARN still failing; retrying one package at a time" + for package in "$@"; do + as_root pacman -S --needed --noconfirm "$package" || failed+=("$package") + done + + (( ${#failed[@]} == 0 )) && return 0 + + say "WARN ${#failed[@]} repo package(s) failed to install: ${failed[*]}" +} + +desktop_essentials=(sddm hyprland quickshell uwsm) + +report_desktop_essentials() { + local package + local -a missing=() + + for package in "${desktop_essentials[@]}"; do + package_installed "$package" || missing+=("$package") + done + + if (( ${#missing[@]} == 0 )); then + say "ok desktop essentials" + return 0 + fi + + say "WARN the desktop cannot start without: ${missing[*]}" + say " install them with 'sudo pacman -S ${missing[*]}', then ./install.sh again" +} + install_aur_packages() { local package local -a failed=()