Fix the install pipeline and an idle-lock startup race
The initial package list was quoted into a single bogus dnf argument and every dnf error was discarded, so a fresh install silently skipped most of it. Two package lists were never wired into the pipeline at all, and change-settings ran before install-packages, so the vicinae theme step was permanently skipped. Fixed the ordering, the quoting, and stopped swallowing errors. Separately, hypridle could start with its WAYLAND_DISPLAY condition unmet if it raced the env-publish call, silently never starting -- and it's the only listener for the logind Lock signal. Made the start wait on the environment synchronously. panama-idle also wrote its generated config to a fixed temp path with no locking, so concurrent applies could interleave into a corrupt file; switched to mktemp plus an atomic mv. Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
This commit is contained in:
@@ -23,8 +23,16 @@ hl.on("hyprland.start", function()
|
||||
hl.exec_cmd("dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=Hyprland")
|
||||
hl.exec_cmd("systemctl --user start hyprland-session.target")
|
||||
|
||||
-- Units: polkit prompts, wallpaper, launcher daemon, idle/lock.
|
||||
hl.exec_cmd("systemctl --user start hyprpolkitagent.service hyprpaper.service vicinae.service hypridle.service")
|
||||
-- Units: polkit prompts, wallpaper, launcher daemon, idle/lock. All four
|
||||
-- carry `ConditionEnvironment=WAYLAND_DISPLAY`, and hl.exec_cmd fires
|
||||
-- commands without waiting for them to finish, so the dbus-update call
|
||||
-- above racing this one is not safe to assume complete -- a lost race
|
||||
-- leaves the Condition unmet and the unit silently never starts (exit 0,
|
||||
-- no error). hypridle is the only listener for the logind Lock signal,
|
||||
-- so that failure mode is "lock-session goes to nobody". Re-import
|
||||
-- synchronously in the same shell invocation first so the Condition
|
||||
-- always sees it, regardless of how the dbus-update call above scheduled.
|
||||
hl.exec_cmd("systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP && systemctl --user start hyprpolkitagent.service hyprpaper.service vicinae.service hypridle.service")
|
||||
|
||||
-- The shell: bar, dock, overview, quick settings, notifications, capture.
|
||||
-- No systemd unit ships with quickshell, so it runs as a compositor child.
|
||||
|
||||
@@ -25,6 +25,14 @@ generated="$state_dir/hypridle.conf"
|
||||
dropin_dir="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/hypridle.service.d"
|
||||
dropin="$dropin_dir/panama.conf"
|
||||
|
||||
# Set by generate() to the mktemp path it is currently writing, so concurrent
|
||||
# invocations (e.g. rapid settings changes each spawning `apply`) never share
|
||||
# a tmp file and interleave writes into a corrupt hypridle.conf. Cleared once
|
||||
# the atomic mv below lands, so this is a no-op on a normal exit.
|
||||
generated_tmp=""
|
||||
cleanup() { rm -f "$generated_tmp" 2>/dev/null || true; }
|
||||
trap cleanup EXIT
|
||||
|
||||
read_setting() {
|
||||
local key="$1" fallback="$2"
|
||||
[[ -r "$settings" ]] || { printf '%s' "$fallback"; return; }
|
||||
@@ -53,6 +61,10 @@ generate() {
|
||||
load
|
||||
mkdir -p "$state_dir"
|
||||
|
||||
# Unique per invocation, in the same directory as the destination so the
|
||||
# final mv is an atomic same-filesystem rename rather than a copy.
|
||||
generated_tmp="$(mktemp "$generated.XXXXXX")"
|
||||
|
||||
{
|
||||
printf '# Generated by panama-idle from %s\n' "$settings"
|
||||
printf '# Do not edit: it is rewritten whenever the idle settings change.\n'
|
||||
@@ -91,9 +103,10 @@ generate() {
|
||||
printf ' on-timeout = systemctl suspend\n'
|
||||
printf '}\n'
|
||||
fi
|
||||
} >"$generated.tmp"
|
||||
} >"$generated_tmp"
|
||||
|
||||
mv "$generated.tmp" "$generated"
|
||||
mv "$generated_tmp" "$generated"
|
||||
generated_tmp=""
|
||||
}
|
||||
|
||||
install_dropin() {
|
||||
|
||||
@@ -49,10 +49,16 @@ gsettings set org.gnome.desktop.session idle-delay 0 2>/dev/null || true
|
||||
# still run: a missing optional package should not stop the dotfiles being
|
||||
# linked. The summary at the end is what decides whether the install worked,
|
||||
# because a failure scrolled past twenty minutes ago is a failure nobody saw.
|
||||
#
|
||||
# Explicit order, not glob order: change-settings runs `vicinae theme set`,
|
||||
# which needs both vicinae itself (installed by install-packages) and the
|
||||
# theme files it selects among (symlinked into place by link-dotfiles). New
|
||||
# scripts must be added here explicitly, or they will not run at all.
|
||||
STAGES=(install-packages link-dotfiles change-settings link-vicinae-scripts)
|
||||
failed=()
|
||||
for script in "$PANAMA_PATH"/setup/scripts/*; do
|
||||
for stage in "${STAGES[@]}"; do
|
||||
script="$PANAMA_PATH/setup/scripts/$stage"
|
||||
[[ -x "$script" ]] || continue
|
||||
stage="$(basename "$script")"
|
||||
printf '\n=== %s ===\n' "$stage"
|
||||
if ! "$script"; then
|
||||
failed+=("$stage")
|
||||
|
||||
@@ -32,6 +32,7 @@ mokutil
|
||||
mozilla-openh264
|
||||
nautilus-extensions
|
||||
nautilus-python
|
||||
nextcloud-client
|
||||
openssl-devel
|
||||
opus-devel
|
||||
python3-dnf-plugin-versionlock
|
||||
|
||||
@@ -2,3 +2,5 @@ org.gtk.Gtk3theme.adw-gtk3-dark
|
||||
io.github.Foldex.AdwSteamGtk
|
||||
com.bitwarden.desktop
|
||||
app.bluebubbles.BlueBubbles
|
||||
org.mozilla.thunderbird_esr
|
||||
io.missioncenter.MissionCenter
|
||||
|
||||
@@ -8,6 +8,7 @@ gpu-screen-recorder
|
||||
grim
|
||||
grimblast
|
||||
gtk-update-icon-cache
|
||||
helium-browser-bin
|
||||
hypridle
|
||||
hyprland
|
||||
hyprland-guiutils
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# --- Helper functions ---
|
||||
log() { echo -e "\033[1;34m[INFO]\033[0m $*"; }
|
||||
exists() { command -v "$1" >/dev/null 2>&1; }
|
||||
@@ -10,33 +12,37 @@ LOCAL_BIN_PATH="$HOME/.local/bin"
|
||||
|
||||
echo -e "\n--- Installing Repositories ---"
|
||||
log "Installing RPM Fusion Free and Nonfree Repositories"
|
||||
sudo dnf install -y https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm > /dev/null 2>&1
|
||||
sudo dnf install -y https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm > /dev/null
|
||||
log "Enabling Fedora Cisco OpenH264 Repository"
|
||||
sudo dnf config-manager setopt fedora-cisco-openh264.enabled=1
|
||||
log "Installing RPM Fusion AppStream Metadata"
|
||||
sudo dnf update @core -y > /dev/null 2>&1
|
||||
sudo dnf install -y rpmfusion-\*-appstream-data > /dev/null 2>&1
|
||||
sudo dnf update @core -y > /dev/null
|
||||
sudo dnf install -y rpmfusion-\*-appstream-data > /dev/null
|
||||
log "Installing Terra Repository"
|
||||
sudo dnf install -y --nogpgcheck --repofrompath 'terra,https://repos.fyralabs.com/terra$releasever' terra-release > /dev/null 2>&1
|
||||
sudo dnf install -y --nogpgcheck --repofrompath 'terra,https://repos.fyralabs.com/terra$releasever' terra-release > /dev/null
|
||||
|
||||
echo -e "\n--- Installing relevant packages ---"
|
||||
log "Updating all packages. This may take a while"
|
||||
sudo dnf update -y --refresh > /dev/null 2>&1
|
||||
sudo dnf update -y --refresh > /dev/null
|
||||
|
||||
log "Updating core, multimedia, and sound-and-video groups"
|
||||
# A trailing `&& sync` here previously meant a failing groupupdate was exempt
|
||||
# from set -e (bash does not apply -e to the left side of a && list), so the
|
||||
# failure went unreported. Sync unconditionally on its own line instead.
|
||||
sudo dnf4 groupupdate -y 'core' 'multimedia' 'sound-and-video' \
|
||||
--setop='install_weak_deps=False' \
|
||||
--exclude='PackageKit-gstreamer-plugin' \
|
||||
--allowerasing && sync > /dev/null 2>&1
|
||||
--allowerasing > /dev/null
|
||||
sync
|
||||
log "Swapping ffmpeg-free for ffmpeg"
|
||||
sudo dnf swap -y 'ffmpeg-free' 'ffmpeg' --allowerasing > /dev/null 2>&1
|
||||
sudo dnf swap -y 'ffmpeg-free' 'ffmpeg' --allowerasing > /dev/null
|
||||
log "Swapping mesa-va-drivers for mesa-va-drivers-freeworld"
|
||||
sudo dnf swap -y mesa-va-drivers mesa-va-drivers-freeworld > /dev/null 2>&1
|
||||
sudo dnf swap -y mesa-va-drivers mesa-va-drivers-freeworld > /dev/null
|
||||
log "Upgrading Multimedia group with optional packages"
|
||||
sudo dnf4 group upgrade -y --with-optional Multimedia > /dev/null 2>&1
|
||||
sudo dnf4 group upgrade -y --with-optional Multimedia > /dev/null
|
||||
log "Installing GStreamer plugins (bad, good, base)"
|
||||
sudo dnf install -y gstreamer1-plugins-{bad-\*,good-\*,base} \
|
||||
--exclude=gstreamer1-plugins-bad-free-devel > /dev/null 2>&1
|
||||
--exclude=gstreamer1-plugins-bad-free-devel > /dev/null
|
||||
|
||||
# --- Install all initial packages ---
|
||||
PACKAGES_FILE="$PANAMA_PATH/setup/packages/initial-packages"
|
||||
@@ -45,12 +51,25 @@ if [[ -f "$PACKAGES_FILE" ]]; then
|
||||
log "Installing Initial Packages"
|
||||
echo -e "Includes the following packages:"
|
||||
echo -e "$(<"$PACKAGES_FILE")"
|
||||
sudo dnf install -y "$INITIAL_PACKAGES" > /dev/null 2>&1
|
||||
sudo dnf install -y $INITIAL_PACKAGES > /dev/null
|
||||
log "Initial packages installed!"
|
||||
else
|
||||
log "Package list was not in specified path: $PACKAGES_FILE"
|
||||
fi
|
||||
|
||||
# --- Install Desktop Packages ---
|
||||
DESKTOP_FILE="$PANAMA_PATH/setup/packages/desktop-packages"
|
||||
if [[ -f "$DESKTOP_FILE" ]]; then
|
||||
DESKTOP_PACKAGES=$(tr "\n" " " <"$DESKTOP_FILE")
|
||||
log "Installing Desktop Packages"
|
||||
echo -e "Includes the following packages:"
|
||||
echo -e "$(<"$DESKTOP_FILE")"
|
||||
sudo dnf install -y $DESKTOP_PACKAGES > /dev/null
|
||||
log "Desktop packages installed!"
|
||||
else
|
||||
log "Package list was not in specified path: $DESKTOP_FILE"
|
||||
fi
|
||||
|
||||
# --- Install oh-my-posh if not already installed. ---
|
||||
mkdir -p "$LOCAL_BIN_PATH"
|
||||
if [[ -x "$LOCAL_BIN_PATH/oh-my-posh" ]]; then
|
||||
@@ -67,7 +86,7 @@ if [[ -f "$DEV_FILE" ]]; then
|
||||
log "Installing Development Packages. Mostly for Neovim."
|
||||
echo -e "Includes the following packages:"
|
||||
echo -e "$(<"$DEV_FILE")"
|
||||
sudo dnf install -y $DEV_PACKAGES > /dev/null 2>&1
|
||||
sudo dnf install -y $DEV_PACKAGES > /dev/null
|
||||
log "Development packages installed!"
|
||||
else
|
||||
log "Package list was not in specified path: $DEV_FILE"
|
||||
@@ -78,12 +97,12 @@ fi
|
||||
HYPR_FILE="$PANAMA_PATH/setup/packages/hyprland-packages"
|
||||
if [[ -f "$HYPR_FILE" ]]; then
|
||||
log "Enabling Hyprland COPR"
|
||||
sudo dnf copr enable -y lionheartp/Hyprland > /dev/null 2>&1
|
||||
sudo dnf copr enable -y lionheartp/Hyprland > /dev/null
|
||||
HYPR_PACKAGES=$(tr "\n" " " <"$HYPR_FILE")
|
||||
log "Installing Hyprland desktop packages"
|
||||
echo -e "Includes the following packages:"
|
||||
echo -e "$(<"$HYPR_FILE")"
|
||||
sudo dnf install -y --setopt=install_weak_deps=False $HYPR_PACKAGES > /dev/null 2>&1
|
||||
sudo dnf install -y --setopt=install_weak_deps=False $HYPR_PACKAGES > /dev/null
|
||||
log "Hyprland packages installed!"
|
||||
else
|
||||
log "Package list was not in specified path: $HYPR_FILE"
|
||||
@@ -96,3 +115,18 @@ else
|
||||
log "Installing Bun via curl..."
|
||||
curl -fsSL https://bun.sh/install | bash > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# --- Install Flatpak Packages ---
|
||||
FLATPAK_FILE="$PANAMA_PATH/setup/packages/flatpak-packages"
|
||||
if [[ -f "$FLATPAK_FILE" ]]; then
|
||||
FLATPAK_PACKAGES=$(tr "\n" " " <"$FLATPAK_FILE")
|
||||
log "Adding Flathub remote"
|
||||
sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo > /dev/null
|
||||
log "Installing Flatpak Packages"
|
||||
echo -e "Includes the following packages:"
|
||||
echo -e "$(<"$FLATPAK_FILE")"
|
||||
sudo flatpak install -y flathub $FLATPAK_PACKAGES > /dev/null
|
||||
log "Flatpak packages installed!"
|
||||
else
|
||||
log "Package list was not in specified path: $FLATPAK_FILE"
|
||||
fi
|
||||
|
||||
@@ -63,6 +63,12 @@ for dir in "${dirs[@]}"; do
|
||||
if [ -d "$CONFIG/$dir" ]; then
|
||||
mv "$CONFIG/$dir" "$PANAMA_OLD/$dir"
|
||||
log "Moved existing $dir config to $PANAMA_OLD/$dir"
|
||||
# A regular file at this path (not a directory, not a symlink) is missed by
|
||||
# the guards above, so `ln -s` below would fail with "File exists" -- back
|
||||
# it up the same way.
|
||||
elif [ -f "$CONFIG/$dir" ]; then
|
||||
mv "$CONFIG/$dir" "$PANAMA_OLD/$dir"
|
||||
log "Moved existing $dir file to $PANAMA_OLD/$dir"
|
||||
fi
|
||||
|
||||
# Create symlink
|
||||
|
||||
Reference in New Issue
Block a user