feat(sysupdate): Plymouth/ReGreet migration, astal-menu deps, hyprshutdown, usr redeploy

sysupdate.sh's config sync now closes several gaps where a fresh or drifted
machine would silently be missing pieces that config-updater can't reach
(it only copies files, never installs packages or touches /etc):

- _ensure_plymouth_regreet: detects whether the machine is still on
  greetd+tuigreet (or no greeter at all) and offers to run the existing
  migrate-to-greetd.sh tool rather than duplicating its logic.
- _ensure_astal_menu_deps / _ensure_hyprshutdown: detect and offer to install
  the AUR/pacman packages astal-menu and the new power binds need but that
  config-updater never installs on its own.
- _redeploy_usr_configs: hypr/usr/ is intentionally excluded from the
  automated sync to protect per-device customisation (monitors.lua,
  wallpaper.conf), which left feature/bind updates in the dotfiles template
  with no path onto an already-provisioned machine. Adds an explicit,
  file-by-file dialog checklist (device-specific files default off) so those
  updates can be pulled in deliberately instead of hand-copied.
main
Amir Alexander Abdelbaki 2026-07-08 13:35:56 +02:00
parent ed44b84afa
commit d680730d30
1 changed files with 151 additions and 0 deletions

View File

@ -597,6 +597,75 @@ _fix_hypr_usr() {
fi
}
# Offer to redeploy hypr/usr/ (device-specific lua) from the dotfiles template,
# file by file. hypr/usr/ is excluded from the normal config-updater sync to
# preserve per-device customisation (monitors.lua, wallpaper.conf), but feature/
# bind updates in autostart.lua, binds.lua, windowrules.lua etc. still land in
# the dotfiles template and need an explicit, reviewable opt-in to reach a
# machine that already has its own hypr/usr/. Skipped entirely on first-time
# setup — _migrate_hypr_usr already seeds usr/ from the template in that case.
_redeploy_usr_configs() {
local de_dir; de_dir=$(_de_source_dir)
local src_usr="${de_dir:+$de_dir/hypr/usr}"
local usr_dir="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/usr"
[[ -n "${src_usr:-}" && -d "$src_usr" ]] || return 0
[[ -d "$usr_dir" ]] || return 0
ask "Redeploy user-local configs (hypr/usr/)?" || { log "Skipped user-local config redeploy"; return 0; }
local -a files=()
while IFS= read -r -d '' item; do
files+=("$(basename "$item")")
done < <(find "$src_usr" -maxdepth 1 -mindepth 1 -type f ! -name '*.old' -print0 | sort -z)
if [[ ${#files[@]} -eq 0 ]]; then
warn "No template files found in $src_usr"
return 0
fi
local -a selected=()
if command -v dialog &>/dev/null; then
local items=()
for f in "${files[@]}"; do
local tag="on"
[[ "$f" == "monitors.lua" || "$f" == "wallpaper.conf" ]] && tag="off"
local status="new"
[[ -f "$usr_dir/$f" ]] && { diff -q "$usr_dir/$f" "$src_usr/$f" &>/dev/null && status="unchanged" || status="differs"; }
items+=("$f" "($status)" "$tag")
done
local chosen
chosen=$(dialog --stdout --separate-output \
--title " Redeploy hypr/usr/ " \
--checklist " SPACE = toggle | ENTER = confirm | ESC = cancel (monitors.lua / wallpaper.conf default OFF — device-specific) " \
0 70 0 "${items[@]}") || { warn "Cancelled — no user-local configs redeployed."; return 0; }
while IFS= read -r line; do
[[ -n "$line" ]] && selected+=("$line")
done <<< "$chosen"
else
warn "'dialog' not installed — redeploying all except monitors.lua/wallpaper.conf"
for f in "${files[@]}"; do
[[ "$f" == "monitors.lua" || "$f" == "wallpaper.conf" ]] && continue
selected+=("$f")
done
fi
if [[ ${#selected[@]} -eq 0 ]]; then
warn "Nothing selected — no user-local configs redeployed."
return 0
fi
for f in "${selected[@]}"; do
if cp -p "$src_usr/$f" "$usr_dir/$f"; then
ok "redeployed hypr/usr/$f"
else
err "failed hypr/usr/$f"
fi
done
_fix_hypr_usr
}
# Deploy root-owned greeter config (/etc/greetd) that config-updater can't reach.
# Only when greetd is the active greeter on this machine. Uses the sudo credential
# primed once at startup, so it doesn't re-prompt. PAM is intentionally left to the
@ -613,13 +682,95 @@ _deploy_greetd() {
ok "greetd config deployed" || warn "greetd config deploy had errors"
}
# Ensure this machine has finished the Plymouth + greetd/ReGreet boot/login
# migration. Delegates entirely to setup/tools/migrate-to-greetd.sh (idempotent,
# already handles old-DM detection/teardown, PAM/FIDO, wallpaper sync, initramfs
# + GRUB) rather than duplicating that logic here. Skips silently once the
# machine is already on the target stack.
_ensure_plymouth_regreet() {
local migrate_tool="$DOTFILES/setup/tools/migrate-to-greetd.sh"
[[ -x "$migrate_tool" ]] || return 0
local greetd_state; greetd_state=$(systemctl is-enabled greetd.service 2>/dev/null || true)
local using_regreet=false
grep -q 'regreet' /etc/greetd/config.toml 2>/dev/null && using_regreet=true
local plymouth_ok=false
pacman -Qq plymouth &>/dev/null && [[ -d /usr/share/plymouth/themes/m-archy ]] && plymouth_ok=true
if [[ "$greetd_state" == "enabled" && "$using_regreet" == true && "$plymouth_ok" == true ]]; then
ok "Plymouth + greetd/ReGreet already active"
return 0
fi
warn "Not yet on Plymouth + greetd/ReGreet (currently: greetd=${greetd_state}, regreet=${using_regreet}, plymouth=${plymouth_ok})"
if ask "Migrate now? (installs plymouth+regreet+cage, rebuilds initramfs; reboot needed after)"; then
"$migrate_tool" --yes
fi
}
# Ensure the Astal GObject typelibs astal-menu's main.py imports at startup are
# installed. config-updater only copies the astal-menu/ config directory — it
# never installs packages — so a machine that's never run the AUR install is
# missing these even after a full config sync.
_ensure_astal_menu_deps() {
local de_dir; de_dir=$(_de_source_dir)
[[ "${de_dir:-}" == */hyprlua ]] || return 0
[[ -d "$de_dir/astal-menu" ]] || return 0
local -a needed=(libastal-network-git libastal-bluetooth-git libastal-apps-git)
local -a missing=()
for pkg in "${needed[@]}"; do
pacman -Qq "$pkg" &>/dev/null || missing+=("$pkg")
done
if [[ ${#missing[@]} -eq 0 ]]; then
ok "astal-menu AUR deps already installed"
return 0
fi
warn "astal-menu is missing AUR deps: ${missing[*]}"
if ask "Install them now?"; then
if yay -S --noconfirm --needed "${missing[@]}"; then
ok "astal-menu deps installed"
else
warn "Failed to install some astal-menu deps"
fi
fi
}
# Ensure hyprshutdown is installed. hypr/usr/binds.lua's power binds
# (Super+Shift/Ctrl/Ctrl+Shift+O) call it directly; without it those binds
# silently no-op. It's in the official extra repo, not AUR.
_ensure_hyprshutdown() {
local de_dir; de_dir=$(_de_source_dir)
[[ "${de_dir:-}" == */hyprlua ]] || return 0
if pacman -Qq hyprshutdown &>/dev/null; then
ok "hyprshutdown already installed"
return 0
fi
warn "hyprshutdown is missing — the power binds in hypr/usr/binds.lua will no-op without it"
if ask "Install it now?"; then
if sudo pacman -S --noconfirm --needed hyprshutdown; then
ok "hyprshutdown installed"
else
warn "Failed to install hyprshutdown"
fi
fi
}
sync_configs() {
section "Config Sync"
# ── Migration: old flat layout → hypr/usr/ ───────────────────────────────
_migrate_hypr_usr
_fix_hypr_usr
_redeploy_usr_configs
_deploy_greetd
_ensure_plymouth_regreet
_ensure_astal_menu_deps
_ensure_hyprshutdown
# ── Preferred: use the installed update-configs.sh ───────────────────────
local cfg_script