Krolyxon
Commit 6efc8ec

Branches

Refs →

aurora6efc8ec

install.sh: split into install/{lib,desktop}.sh

Author
krolyxon
Date
2026-11-08 17:54 +0530
Parent
3ce61b8
Commit
6efc8ecd99f141afe63115290bd4c1780b3d528b

+408 −397

4 files changed

  1. M .stow-local-ignore +1 −0
  2. M install.sh +7 −397
  3. A install/desktop.sh +308 −0
  4. A install/lib.sh +92 −0
M .stow-local-ignore View
@@ -8,3 +8,4 @@ LICENSE
88 CLAUDE\.md
99 glyph-rice
1010 \.stowrc
11+^/install$
M install.sh View
@@ -25,26 +25,12 @@ AUTO_YES=0
2525 CHECK_ONLY=0
2626 BACKUP_DIR=""
2727
28−log() {
29− local level="$1"
30− shift
31−
32− local color reset='\033[0m'
33− case "$level" in
34− INFO) color='\033[0;34m' ;; # Blue
35− WARN) color='\033[0;33m' ;; # Yellow
36− ERROR) color='\033[0;31m' ;; # Red
37− SUCCESS) color='\033[0;32m' ;; # Green
38− *) color='\033[0m' ;;
39− esac
40−
41− printf '%b[%s] [%s]%b %s\n' \
42− "$color" "$(date '+%H:%M:%S')" "$level" "$reset" "$*" >&2
43−}
28+currentDir="$(dirname "$(readlink -f "$0")")"
29+cd "$currentDir" || exit 1
30+PKG_DIR="$currentDir/packages"
4431
45−usage() {
46− sed -n '3,19s/^# \{0,1\}//p' "$0"
47−}
32+# shellcheck source=install/lib.sh
33+source "$currentDir/install/lib.sh"
4834
4935 #######################
5036 ## Arguement Parsing ##
@@ -69,386 +55,10 @@ for arg in "$@"; do
6955 esac
7056 done
7157
72−currentDir="$(dirname "$(readlink -f "$0")")"
73−cd "$currentDir" || exit 1
74−PKG_DIR="$currentDir/packages"
75−
76−
77−###################
78−## Package lists ##
79−###################
80−# packages/*.txt: one package per line, '#' comments.
81−# A trailing '!' (e.g. "blender !") means: listed, but not pre-selected in the picker.
82−
83−# All packages in a list
84−read_list() {
85− sed 's/#.*//' "$PKG_DIR/$1.txt" | awk 'NF { print $1 }'
86−}
87−
88−# Packages of a list that are pre-selected in the picker
89−preselected() {
90− sed 's/#.*//' "$PKG_DIR/$1.txt" | awk 'NF && $2 != "!" { print $1 }'
91−}
92−
93−check_packages() {
94− local listed installed aur
95− listed=$(for f in "$PKG_DIR"/*.txt; do read_list "$(basename "$f" .txt)"; done | sort -u)
96− installed=$(pacman -Qqe | sort -u)
97− aur=$(pacman -Qqm | sort -u)
98−
99− echo "Installed explicitly, but not in any packages/*.txt:"
100− comm -23 <(echo "$installed") <(echo "$listed") | while read -r p; do
101− if grep -qx "$p" <<< "$aur"; then echo " $p (aur)"; else echo " $p"; fi
102− done
103−
104− echo
105− echo "Listed, but not installed:"
106− comm -13 <(pacman -Qq | sort -u) <(echo "$listed") | sed 's/^/ /'
107−}
108−
10958 if ((CHECK_ONLY)); then
11059 check_packages
11160 exit 0
11261 fi
11362
114−
115−#################
116−## GATEKEEPING ##
117−#################
118−
119−## Prevent user from running this script as root
120−if [[ "$EUID" -eq 0 ]]; then
121− log ERROR "This script must NOT be run as root."
122− log INFO "If you need elevated privileges, the script will ask for sudo when required."
123− exit 1
124−fi
125−
126−if [[ ! -f /etc/arch-release ]]; then
127− log ERROR "This is not Arch Linux. These dotfiles and this script are for Arch only."
128− exit 1
129−fi
130−
131−## Does this look like a system that is already set up?
132−## (configs this repo doesn't provide, or another desktop's config)
133−check_fresh_system() {
134− local foreign=() desktops=() entry
135− for entry in "$HOME"/.config/*; do
136− [[ -e "$entry" ]] || continue
137− entry="$(basename "$entry")"
138− [[ -e "$currentDir/.config/$entry" ]] || foreign+=("$entry")
139− done
140− for entry in i3 sway niri river awesome bspwm openbox qtile xfce4 \
141− kdeglobals plasma-org.kde.plasma.desktop-appletsrc gnome-session; do
142− [[ -e "$HOME/.config/$entry" ]] && desktops+=("$entry")
143− done
144−
145− ((${#foreign[@]} <= 10 && ${#desktops[@]} == 0)) && return 0
146−
147− printf '\033[1;31m'
148− echo "=================================================================="
149− echo " This does NOT look like a fresh Arch install."
150− echo
151− ((${#desktops[@]})) && echo " Found another desktop's config: ${desktops[*]}"
152− ((${#foreign[@]} > 10)) && echo " Found ${#foreign[@]} entries in ~/.config that this repo doesn't provide."
153− echo
154− echo " This installer is meant for a freshly installed, unconfigured"
155− echo " system. On a system you already use it WILL change things you"
156− echo " care about: your configs get moved aside, your shell changes, and"
157− echo " lots of packages get installed."
158− echo "=================================================================="
159− printf '\033[0m'
160− local answer
161− read -rp "Type 'I understand' to continue anyway: " answer
162− [[ "$answer" == "I understand" ]] || { log WARN "Aborted."; exit 1; }
163−}
164−check_fresh_system
165−
166−choose_packages() {
167− local list="$1"
168− gum choose --no-limit \
169− --selected "$(preselected "$list" | paste -sd,)" \
170− $(read_list "$list")
171−}
172−
173−prompt_style() {
174− gum style \
175− --border rounded \
176− --padding "0 1" \
177− "$1"
178−}
179−
180−gum_warn(){
181− gum style --bold --foreground 196 "⚠ $1"
182−}
183−
184−gum_to_array() {
185− local -n arr="$1"
186− mapfile -t arr
187− local cleaned=()
188− for item in "${arr[@]}"; do
189− [[ -n "$item" ]] && cleaned+=("$item")
190− done
191− arr=("${cleaned[@]}")
192−}
193−
194−confirm() {
195− local msg="$1"
196− if ((AUTO_YES)); then
197− log INFO "[auto] $msg → yes"
198− return 0
199− fi
200− gum confirm --default=false "$msg"
201−}
202−
203−install_prerequisites() {
204− sudo pacman -S --needed --noconfirm stow gum git zsh
205−}
206−
207−## Installs prerequisites
208−log INFO "Installing prerequisites: "
209−install_prerequisites
210−
211−
212−DISCLAIMER=$(gum style \
213− --border double \
214− --border-foreground 196 \
215− --padding "1 2" \
216− --bold \
217−"⚠️ DISCLAIMER
218−
219−These are MY personal dotfiles, built for MY machine
220−(Lenovo Legion, Intel + NVIDIA hybrid, linux-zen) and the way I work.
221−They are NOT general purpose. They're public as a reference,
222−or for people who want exactly the same setup.
223−
224−Only run this on a FRESHLY INSTALLED, UNCONFIGURED Arch system.
225−
226−This script is provided AS IS, WITHOUT ANY WARRANTY. It will:
227−• Install a lot of packages (including NVIDIA drivers if selected)
228−• Move conflicting files in your \$HOME to ~/.aurora-backup/
229−• Change your login shell to zsh
230−• Optionally write /etc/keyd and enable keyd
231−• Optionally write /etc/pam.d/{login,passwd} (GNOME keyring unlock)
232−• Enable the aurora-shell.service user unit
233−
234−Proceed at your OWN RISK."
235−)
236−
237−confirm "$DISCLAIMER
238−
239−Do you understand the risks and want to continue?" || exit 1
240−
241−
242−#######################
243−## Package selection ##
244−#######################
245−SELECTED_PKGS=()
246−for list in utils dev gpu optional aur; do
247− case "$list" in
248− utils) prompt_style "Important utilities (Most likely go with defaults)" ;;
249− dev) prompt_style "Select Development Tools" ;;
250− gpu) prompt_style "Select GPU drivers" ;;
251− optional) prompt_style "Select Optional Desktop Packages" ;;
252− aur) prompt_style "Select AUR packages" ;;
253− esac
254−
255− if ((AUTO_YES)); then
256− mapfile -t picked < <(preselected "$list")
257− else
258− gum_to_array picked < <(choose_packages "$list")
259− fi
260− SELECTED_PKGS+=("${picked[@]}")
261−done
262−
263−
264−##########################
265−## Configure Everything ##
266−##########################
267−WARNING=$(gum style \
268− --border double \
269− --border-foreground 196 \
270− --padding "1 2" \
271− --bold \
272− "⚠️ Files in your \$HOME that conflict with this repo will be MOVED to
273−~/.aurora-backup/<date>/ and replaced with symlinks from this repo.")
274−
275−if confirm "$WARNING
276−
277−Proceed with system configuration (stow, shell)?"; then
278− ###################
279− ## Stow dotfiles ##
280− ###################
281− log INFO "Detecting conflicts..."
282− mapfile -t conflicts < <(stow -t "$HOME" . --no-folding -nv 2>&1 | \
283− sed -n 's/.*existing target \(.*\) since neither.*/\1/p')
284−
285− if ((${#conflicts[@]} == 0)); then
286− log INFO "No conflicts. Running stow normally..."
287− else
288− log WARN "These paths conflict and will be moved to a backup:"
289− printf ' %s\n' "${conflicts[@]}"
290− if ! confirm "Move these files to ~/.aurora-backup/ ?"; then
291− log WARN "Aborted."
292− exit 1
293− fi
294−
295− # Move conflicts (relative to $HOME) into the backup dir, keeping their paths
296− BACKUP_DIR="$HOME/.aurora-backup/$(date '+%Y%m%d-%H%M%S')"
297− for path in "${conflicts[@]}"; do
298− [[ -n "$path" && "$path" != "/" ]] || continue
299− mkdir -p "$BACKUP_DIR/$(dirname "$path")"
300− mv "$HOME/$path" "$BACKUP_DIR/$path" && log INFO "Backed up $path"
301− done
302− log INFO "Backups are in $BACKUP_DIR"
303− fi
304−
305− stow -t "$HOME" . --no-folding \
306− && log SUCCESS "Dotfiles stowed successfully" \
307− || log ERROR "Stow failed"
308−
309− #################################
310− ## Change default shell to zsh ##
311− #################################
312− log INFO "Changing the default shell to ZSH"
313− if [[ "$SHELL" != "$(command -v zsh)" ]]; then
314− chsh -s "$(command -v zsh)" \
315− && log SUCCESS "Default shell successfully set to zsh" \
316− || log ERROR "Default shell could not be set to zsh"
317− else
318− log INFO "Skipping: zsh is already the default shell"
319− fi
320−else
321− log ERROR "Aborted stow, didn't configure or install anything"
322− exit 1
323−fi
324−
325−
326−mapfile -t DESKTOP_PKGS < <(read_list desktop)
327−ALL_PKGS=(
328− "${DESKTOP_PKGS[@]}"
329− "${SELECTED_PKGS[@]}"
330−)
331−
332−########################
333−## Install Everything ##
334−########################
335−if ((${#ALL_PKGS[@]})); then
336− if confirm "Install all the selected packages?"; then
337− log INFO "Installing selected packages..."
338−
339− ## Installing paru if not installed already
340− if ! command -v paru >/dev/null 2>&1; then
341− log INFO "Installing Paru (AUR package manager)"
342− sudo pacman -S --needed --noconfirm base-devel
343− git clone https://aur.archlinux.org/paru.git
344− (cd paru && makepkg -sri)
345− rm -rf paru
346− fi
347−
348− if paru -Syu --needed "${ALL_PKGS[@]}"; then
349− INSTALL_STATUS="complete"
350− else
351− INSTALL_STATUS="failed"
352− fi
353− else
354− log WARN "Package installation skipped by user"
355− INSTALL_STATUS="partial"
356− fi
357−else
358− log WARN "No packages selected"
359− INSTALL_STATUS="partial"
360−fi
361−
362−
363−
364−################
365−## Setup Keyd ##
366−################
367−if command -v keyd >/dev/null 2>&1; then
368− if confirm "Configure and enable keyd? "; then
369− log INFO "Copying keyd configuration to /etc/keyd/default.conf"
370− sudo cp "$currentDir/system/etc/keyd/default.conf" /etc/keyd/
371− sudo systemctl enable --now keyd.service \
372− && log SUCCESS "Successfully enabled keyd.service" \
373− || log ERROR "Couldn't enable keyd.service"
374− fi
375−fi
376−
377−
378−############################
379−## GNOME keyring on login ##
380−############################
381−# pam_gnome_keyring unlocks the "login" keyring with the login password (tty login and hyprlock,
382−# whose PAM file includes login); passwd keeps the keyring password in sync.
383−if confirm "Unlock GNOME keyring at login (writes /etc/pam.d/login and passwd)?"; then
384− log INFO "Copying PAM files to /etc/pam.d"
385− sudo cp "$currentDir/system/etc/pam.d/login" "$currentDir/system/etc/pam.d/passwd" /etc/pam.d/ \
386− && log SUCCESS "GNOME keyring unlocks at login" \
387− || log ERROR "Couldn't write /etc/pam.d"
388−fi
389−
390−
391−#########################
392−## Enable aurora shell ##
393−#########################
394−# User unit, stowed to ~/.config/systemd/user. Hyprland starts it at login,
395−# enabling it also ties it to graphical-session.target. No --now: no session yet.
396−if [[ -f "$HOME/.config/systemd/user/aurora-shell.service" ]]; then
397− if confirm "Enable aurora-shell.service (the desktop shell)?"; then
398− systemctl --user daemon-reload
399− systemctl --user enable aurora-shell.service \
400− && log SUCCESS "Successfully enabled aurora-shell.service" \
401− || log ERROR "Couldn't enable aurora-shell.service (run 'systemctl --user enable aurora-shell' after logging in)"
402− fi
403−else
404− log WARN "aurora-shell.service is not stowed, skipping"
405−fi
406−
407−
408−####################
409−## Final dialogue ##
410−####################
411−BACKUP_NOTE=""
412−[[ -n "$BACKUP_DIR" ]] && BACKUP_NOTE="
413−
414−Your old conflicting files are in:
415−$BACKUP_DIR"
416−
417−case "$INSTALL_STATUS" in
418− complete)
419− gum style \
420− --border rounded \
421− --border-foreground 42 \
422− --padding "1 2" \
423− --bold \
424− "✔ Installation Complete!
425−
426−All selected packages were installed successfully.
427−You may now reboot the system for all the changes to apply.$BACKUP_NOTE"
428− ;;
429− partial)
430− gum style \
431− --border rounded \
432− --border-foreground 220 \
433− --padding "1 2" \
434− --bold \
435− "⚠ Setup Finished (Partial)
436−
437−Some steps were skipped by user choice.
438−Your system was NOT fully configured.$BACKUP_NOTE"
439− ;;
440− failed)
441− gum style \
442− --border rounded \
443− --border-foreground 196 \
444− --padding "1 2" \
445− --bold \
446− "❌ Installation Failed
447−
448−One or more steps did not complete successfully.
449−Check the logs above.$BACKUP_NOTE"
450− ;;
451− *)
452− gum style --bold "Finished.$BACKUP_NOTE"
453− ;;
454−esac
63+# shellcheck source=install/desktop.sh
64+source "$currentDir/install/desktop.sh"
A install/desktop.sh View
@@ -0,0 +1,308 @@
1+# shellcheck shell=bash
2+# Desktop part: packages, dotfiles (stow), zsh, services. Sourced by install.sh;
3+# runs as the user, asks for sudo when it needs it.
4+
5+#################
6+## GATEKEEPING ##
7+#################
8+
9+## Prevent user from running this script as root
10+if [[ "$EUID" -eq 0 ]]; then
11+ log ERROR "This script must NOT be run as root."
12+ log INFO "If you need elevated privileges, the script will ask for sudo when required."
13+ exit 1
14+fi
15+
16+if [[ ! -f /etc/arch-release ]]; then
17+ log ERROR "This is not Arch Linux. These dotfiles and this script are for Arch only."
18+ exit 1
19+fi
20+
21+## Does this look like a system that is already set up?
22+## (configs this repo doesn't provide, or another desktop's config)
23+check_fresh_system() {
24+ local foreign=() desktops=() entry
25+ for entry in "$HOME"/.config/*; do
26+ [[ -e "$entry" ]] || continue
27+ entry="$(basename "$entry")"
28+ [[ -e "$currentDir/.config/$entry" ]] || foreign+=("$entry")
29+ done
30+ for entry in i3 sway niri river awesome bspwm openbox qtile xfce4 \
31+ kdeglobals plasma-org.kde.plasma.desktop-appletsrc gnome-session; do
32+ [[ -e "$HOME/.config/$entry" ]] && desktops+=("$entry")
33+ done
34+
35+ ((${#foreign[@]} <= 10 && ${#desktops[@]} == 0)) && return 0
36+
37+ printf '\033[1;31m'
38+ echo "=================================================================="
39+ echo " This does NOT look like a fresh Arch install."
40+ echo
41+ ((${#desktops[@]})) && echo " Found another desktop's config: ${desktops[*]}"
42+ ((${#foreign[@]} > 10)) && echo " Found ${#foreign[@]} entries in ~/.config that this repo doesn't provide."
43+ echo
44+ echo " This installer is meant for a freshly installed, unconfigured"
45+ echo " system. On a system you already use it WILL change things you"
46+ echo " care about: your configs get moved aside, your shell changes, and"
47+ echo " lots of packages get installed."
48+ echo "=================================================================="
49+ printf '\033[0m'
50+ local answer
51+ read -rp "Type 'I understand' to continue anyway: " answer
52+ [[ "$answer" == "I understand" ]] || { log WARN "Aborted."; exit 1; }
53+}
54+check_fresh_system
55+
56+
57+install_prerequisites() {
58+ sudo pacman -S --needed --noconfirm stow gum git zsh
59+}
60+
61+## Installs prerequisites
62+log INFO "Installing prerequisites: "
63+install_prerequisites
64+
65+
66+DISCLAIMER=$(gum style \
67+ --border double \
68+ --border-foreground 196 \
69+ --padding "1 2" \
70+ --bold \
71+"⚠️ DISCLAIMER
72+
73+These are MY personal dotfiles, built for MY machine
74+(Lenovo Legion, Intel + NVIDIA hybrid, linux-zen) and the way I work.
75+They are NOT general purpose. They're public as a reference,
76+or for people who want exactly the same setup.
77+
78+Only run this on a FRESHLY INSTALLED, UNCONFIGURED Arch system.
79+
80+This script is provided AS IS, WITHOUT ANY WARRANTY. It will:
81+• Install a lot of packages (including NVIDIA drivers if selected)
82+• Move conflicting files in your \$HOME to ~/.aurora-backup/
83+• Change your login shell to zsh
84+• Optionally write /etc/keyd and enable keyd
85+• Optionally write /etc/pam.d/{login,passwd} (GNOME keyring unlock)
86+• Enable the aurora-shell.service user unit
87+
88+Proceed at your OWN RISK."
89+)
90+
91+confirm "$DISCLAIMER
92+
93+Do you understand the risks and want to continue?" || exit 1
94+
95+
96+#######################
97+## Package selection ##
98+#######################
99+SELECTED_PKGS=()
100+for list in utils dev gpu optional aur; do
101+ case "$list" in
102+ utils) prompt_style "Important utilities (Most likely go with defaults)" ;;
103+ dev) prompt_style "Select Development Tools" ;;
104+ gpu) prompt_style "Select GPU drivers" ;;
105+ optional) prompt_style "Select Optional Desktop Packages" ;;
106+ aur) prompt_style "Select AUR packages" ;;
107+ esac
108+
109+ if ((AUTO_YES)); then
110+ mapfile -t picked < <(preselected "$list")
111+ else
112+ gum_to_array picked < <(choose_packages "$list")
113+ fi
114+ SELECTED_PKGS+=("${picked[@]}")
115+done
116+
117+
118+##########################
119+## Configure Everything ##
120+##########################
121+WARNING=$(gum style \
122+ --border double \
123+ --border-foreground 196 \
124+ --padding "1 2" \
125+ --bold \
126+ "⚠️ Files in your \$HOME that conflict with this repo will be MOVED to
127+~/.aurora-backup/<date>/ and replaced with symlinks from this repo.")
128+
129+if confirm "$WARNING
130+
131+Proceed with system configuration (stow, shell)?"; then
132+ ###################
133+ ## Stow dotfiles ##
134+ ###################
135+ log INFO "Detecting conflicts..."
136+ mapfile -t conflicts < <(stow -t "$HOME" . --no-folding -nv 2>&1 | \
137+ sed -n 's/.*existing target \(.*\) since neither.*/\1/p')
138+
139+ if ((${#conflicts[@]} == 0)); then
140+ log INFO "No conflicts. Running stow normally..."
141+ else
142+ log WARN "These paths conflict and will be moved to a backup:"
143+ printf ' %s\n' "${conflicts[@]}"
144+ if ! confirm "Move these files to ~/.aurora-backup/ ?"; then
145+ log WARN "Aborted."
146+ exit 1
147+ fi
148+
149+ # Move conflicts (relative to $HOME) into the backup dir, keeping their paths
150+ BACKUP_DIR="$HOME/.aurora-backup/$(date '+%Y%m%d-%H%M%S')"
151+ for path in "${conflicts[@]}"; do
152+ [[ -n "$path" && "$path" != "/" ]] || continue
153+ mkdir -p "$BACKUP_DIR/$(dirname "$path")"
154+ mv "$HOME/$path" "$BACKUP_DIR/$path" && log INFO "Backed up $path"
155+ done
156+ log INFO "Backups are in $BACKUP_DIR"
157+ fi
158+
159+ stow -t "$HOME" . --no-folding \
160+ && log SUCCESS "Dotfiles stowed successfully" \
161+ || log ERROR "Stow failed"
162+
163+ #################################
164+ ## Change default shell to zsh ##
165+ #################################
166+ log INFO "Changing the default shell to ZSH"
167+ if [[ "$SHELL" != "$(command -v zsh)" ]]; then
168+ chsh -s "$(command -v zsh)" \
169+ && log SUCCESS "Default shell successfully set to zsh" \
170+ || log ERROR "Default shell could not be set to zsh"
171+ else
172+ log INFO "Skipping: zsh is already the default shell"
173+ fi
174+else
175+ log ERROR "Aborted stow, didn't configure or install anything"
176+ exit 1
177+fi
178+
179+
180+mapfile -t DESKTOP_PKGS < <(read_list desktop)
181+ALL_PKGS=(
182+ "${DESKTOP_PKGS[@]}"
183+ "${SELECTED_PKGS[@]}"
184+)
185+
186+########################
187+## Install Everything ##
188+########################
189+if ((${#ALL_PKGS[@]})); then
190+ if confirm "Install all the selected packages?"; then
191+ log INFO "Installing selected packages..."
192+
193+ ## Installing paru if not installed already
194+ if ! command -v paru >/dev/null 2>&1; then
195+ log INFO "Installing Paru (AUR package manager)"
196+ sudo pacman -S --needed --noconfirm base-devel
197+ git clone https://aur.archlinux.org/paru.git
198+ (cd paru && makepkg -sri)
199+ rm -rf paru
200+ fi
201+
202+ if paru -Syu --needed "${ALL_PKGS[@]}"; then
203+ INSTALL_STATUS="complete"
204+ else
205+ INSTALL_STATUS="failed"
206+ fi
207+ else
208+ log WARN "Package installation skipped by user"
209+ INSTALL_STATUS="partial"
210+ fi
211+else
212+ log WARN "No packages selected"
213+ INSTALL_STATUS="partial"
214+fi
215+
216+
217+
218+################
219+## Setup Keyd ##
220+################
221+if command -v keyd >/dev/null 2>&1; then
222+ if confirm "Configure and enable keyd? "; then
223+ log INFO "Copying keyd configuration to /etc/keyd/default.conf"
224+ sudo cp "$currentDir/system/etc/keyd/default.conf" /etc/keyd/
225+ sudo systemctl enable --now keyd.service \
226+ && log SUCCESS "Successfully enabled keyd.service" \
227+ || log ERROR "Couldn't enable keyd.service"
228+ fi
229+fi
230+
231+
232+############################
233+## GNOME keyring on login ##
234+############################
235+# pam_gnome_keyring unlocks the "login" keyring with the login password (tty login and hyprlock,
236+# whose PAM file includes login); passwd keeps the keyring password in sync.
237+if confirm "Unlock GNOME keyring at login (writes /etc/pam.d/login and passwd)?"; then
238+ log INFO "Copying PAM files to /etc/pam.d"
239+ sudo cp "$currentDir/system/etc/pam.d/login" "$currentDir/system/etc/pam.d/passwd" /etc/pam.d/ \
240+ && log SUCCESS "GNOME keyring unlocks at login" \
241+ || log ERROR "Couldn't write /etc/pam.d"
242+fi
243+
244+
245+#########################
246+## Enable aurora shell ##
247+#########################
248+# User unit, stowed to ~/.config/systemd/user. Hyprland starts it at login,
249+# enabling it also ties it to graphical-session.target. No --now: no session yet.
250+if [[ -f "$HOME/.config/systemd/user/aurora-shell.service" ]]; then
251+ if confirm "Enable aurora-shell.service (the desktop shell)?"; then
252+ systemctl --user daemon-reload
253+ systemctl --user enable aurora-shell.service \
254+ && log SUCCESS "Successfully enabled aurora-shell.service" \
255+ || log ERROR "Couldn't enable aurora-shell.service (run 'systemctl --user enable aurora-shell' after logging in)"
256+ fi
257+else
258+ log WARN "aurora-shell.service is not stowed, skipping"
259+fi
260+
261+
262+####################
263+## Final dialogue ##
264+####################
265+BACKUP_NOTE=""
266+[[ -n "$BACKUP_DIR" ]] && BACKUP_NOTE="
267+
268+Your old conflicting files are in:
269+$BACKUP_DIR"
270+
271+case "$INSTALL_STATUS" in
272+ complete)
273+ gum style \
274+ --border rounded \
275+ --border-foreground 42 \
276+ --padding "1 2" \
277+ --bold \
278+ "✔ Installation Complete!
279+
280+All selected packages were installed successfully.
281+You may now reboot the system for all the changes to apply.$BACKUP_NOTE"
282+ ;;
283+ partial)
284+ gum style \
285+ --border rounded \
286+ --border-foreground 220 \
287+ --padding "1 2" \
288+ --bold \
289+ "⚠ Setup Finished (Partial)
290+
291+Some steps were skipped by user choice.
292+Your system was NOT fully configured.$BACKUP_NOTE"
293+ ;;
294+ failed)
295+ gum style \
296+ --border rounded \
297+ --border-foreground 196 \
298+ --padding "1 2" \
299+ --bold \
300+ "❌ Installation Failed
301+
302+One or more steps did not complete successfully.
303+Check the logs above.$BACKUP_NOTE"
304+ ;;
305+ *)
306+ gum style --bold "Finished.$BACKUP_NOTE"
307+ ;;
308+esac
A install/lib.sh View
@@ -0,0 +1,92 @@
1+# shellcheck shell=bash
2+# Shared helpers, sourced by install.sh.
3+
4+log() {
5+ local level="$1"
6+ shift
7+
8+ local color reset='\033[0m'
9+ case "$level" in
10+ INFO) color='\033[0;34m' ;; # Blue
11+ WARN) color='\033[0;33m' ;; # Yellow
12+ ERROR) color='\033[0;31m' ;; # Red
13+ SUCCESS) color='\033[0;32m' ;; # Green
14+ *) color='\033[0m' ;;
15+ esac
16+
17+ printf '%b[%s] [%s]%b %s\n' \
18+ "$color" "$(date '+%H:%M:%S')" "$level" "$reset" "$*" >&2
19+}
20+
21+usage() {
22+ sed -n '3,19s/^# \{0,1\}//p' "$0"
23+}
24+
25+###################
26+## Package lists ##
27+###################
28+# packages/*.txt: one package per line, '#' comments.
29+# A trailing '!' (e.g. "blender !") means: listed, but not pre-selected in the picker.
30+
31+# All packages in a list
32+read_list() {
33+ sed 's/#.*//' "$PKG_DIR/$1.txt" | awk 'NF { print $1 }'
34+}
35+
36+# Packages of a list that are pre-selected in the picker
37+preselected() {
38+ sed 's/#.*//' "$PKG_DIR/$1.txt" | awk 'NF && $2 != "!" { print $1 }'
39+}
40+
41+check_packages() {
42+ local listed installed aur
43+ listed=$(for f in "$PKG_DIR"/*.txt; do read_list "$(basename "$f" .txt)"; done | sort -u)
44+ installed=$(pacman -Qqe | sort -u)
45+ aur=$(pacman -Qqm | sort -u)
46+
47+ echo "Installed explicitly, but not in any packages/*.txt:"
48+ comm -23 <(echo "$installed") <(echo "$listed") | while read -r p; do
49+ if grep -qx "$p" <<< "$aur"; then echo " $p (aur)"; else echo " $p"; fi
50+ done
51+
52+ echo
53+ echo "Listed, but not installed:"
54+ comm -13 <(pacman -Qq | sort -u) <(echo "$listed") | sed 's/^/ /'
55+}
56+
57+choose_packages() {
58+ local list="$1"
59+ gum choose --no-limit \
60+ --selected "$(preselected "$list" | paste -sd,)" \
61+ $(read_list "$list")
62+}
63+
64+prompt_style() {
65+ gum style \
66+ --border rounded \
67+ --padding "0 1" \
68+ "$1"
69+}
70+
71+gum_warn(){
72+ gum style --bold --foreground 196 "⚠ $1"
73+}
74+
75+gum_to_array() {
76+ local -n arr="$1"
77+ mapfile -t arr
78+ local cleaned=()
79+ for item in "${arr[@]}"; do
80+ [[ -n "$item" ]] && cleaned+=("$item")
81+ done
82+ arr=("${cleaned[@]}")
83+}
84+
85+confirm() {
86+ local msg="$1"
87+ if ((AUTO_YES)); then
88+ log INFO "[auto] $msg → yes"
89+ return 0
90+ fi
91+ gum confirm --default=false "$msg"
92+}