From 706e845456a691a34b7bd26a1344f37f3d9dad11 Mon Sep 17 00:00:00 2001
From: Luca Bilke <luca@asmara.fritz.box>
Date: Sat, 13 Jan 2024 14:59:15 +0100
Subject: [PATCH] optimizations (mostly for consecutive runs)

---
 bootstrap.sh | 62 +++++++++++++++++++++++++---------------------------
 validate.sh  | 20 +++++++++++++++++
 2 files changed, 50 insertions(+), 32 deletions(-)
 create mode 100755 validate.sh

diff --git a/bootstrap.sh b/bootstrap.sh
index 71ff810..b5d921e 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -21,8 +21,7 @@ error() {
 
 prompt() {
 	message=$1
-	tty=$2
-	printf "%b" "${BLUE}${message}${RESET}" >"$tty"
+	printf "%b" "${BLUE}${message}${RESET}" >"$(tty)"
 	# shellcheck disable=SC3037,SC2046
 	read -r x
 	echo "$x"
@@ -70,36 +69,29 @@ check_root() {
 setup() {
 	tput sc
 	info "Synchronizing XBPS index..."
-    xbps-install -S >/dev/null 2>&1 || error "Failed to synchronize XBPS index! (Try manually running xbps-install -S)"
+	xbps-install -S >/dev/null 2>&1 || error "Failed to synchronize XBPS index! (Try manually running xbps-install -S)"
 	tput rc
 	tput el
 
-	info "Installing ntp..."
-	xbps-install -y ntp >/dev/null 2>&1
-	tput rc
-	tput el
+	if ! xbps-query ntp >/dev/null 2>&1; then
+		info "Installing ntp..."
+		xbps-install -y ntp >/dev/null 2>&1
+		tput rc
+		tput el
 
-	info "Synchronizing time..."
-	ntpdate "pool.ntp.org" >/dev/null 2>&1 || warn "Failed to synchronize time!"
-	tput rc
-	tput el
+		info "Synchronizing time..."
+		ntpdate "pool.ntp.org" >/dev/null 2>&1 || warn "Failed to synchronize time!"
+		tput rc
+		tput el
+	fi
 
 	info "Done!"
 }
 
 install_packages() {
-	failed_packages=""
-	#shellcheck disable=SC2016
-	_loop_wrapper "$1" \
-		'Installing ${x}' \
-		'xbps-install -y "$x" >/dev/null 2>&1 || failed_packages="${failed_packages} ${x}"'
-	if [ -n "$failed_packages" ]; then
-		tput rc
-		tput el
-		warn "Failed to install:${failed_packages}"
-	else
-		info "Done!"
-	fi
+	#shellcheck disable=SC2016,SC2046
+	xbps-install $(xargs -a "$1") 2>&1 | grep -q "not found in repository pool." && error "Invalid package in packages.txt, run validate.sh"
+	info "Done!"
 	command -v git 1>/dev/null 2>&1 || error "git isn't installed even though it should be!"
 	command -v stow 1>/dev/null 2>&1 || error "stow isn't installed even though it should be!"
 }
@@ -116,16 +108,17 @@ create_user() {
 	tput sc
 
 	failed=false
-	while ! echo "$username" | grep -q "[a-z_][a-z0-9_-]*$"; do
+	while ! echo "$username" | grep "^[a-z_][a-z0-9_-]*$" | grep -qv "root"; do
 		$failed && warn "Invalid username, try again!"
-		username=$(prompt "Input Username: " "$(tty)")
+		username=$(prompt "Input Username: ")
 		failed=true
 		tput rc
 		tput el
 	done
 
 	if id -u "$username" >/dev/null 2>&1; then
-		warn "User \"$username\" already exists! Skipping user creation!"
+		warn "User \"$username\" already exists, Skipping user creation!"
+		usermod -aG "$USER_GROUPS" "$username"
 	else
 		info "Creating user \"$username\" with the following groups: \"$USER_GROUPS\"..."
 		useradd -m -G "$USER_GROUPS" "$username"
@@ -134,10 +127,10 @@ create_user() {
 			$failed && warn "Passwords do not match or are empty, try again!"
 			tput rc
 			tput el
-			pass1=$(prompt "Input Password: " "$(tty)")
+			pass1=$(prompt "Input Password: ")
 			tput rc
 			tput el
-			pass2=$(prompt "Repeat Password: " "$(tty)")
+			pass2=$(prompt "Repeat Password: ")
 			tput rc
 			tput el
 			failed=true
@@ -190,8 +183,8 @@ install_dotfiles() {
 }
 
 select_keymap() {
+	[ -L "${user_home}/.local/share/xkb/compiled/default" ] && return
 	map="$(find "${user_home}/.local/share/xkb/compiled" -type f -printf "%f\n" | fzf --header="Select a default keymap:")"
-    rm "${user_home}/.local/share/xkb/compiled/default"
 	ln -s "$map" "${user_home}/.local/share/xkb/compiled/default"
 }
 
@@ -199,7 +192,7 @@ enable_services() {
 	tput sc
 	info "Installing user service service..."
 	target="/etc/sv/runsvdir-${username}"
-	mkdir -p "$(dirname "$target")"
+	mkdir -p "$target"
 	sed "s/<U>/$username/" "${SCRIPT_DIR}/runsvdir-user" >"$target/run"
 	[ ! -L "/var/service/$(basename "$target")" ] &&
 		ln -s "$target" "/var/service/"
@@ -233,8 +226,13 @@ setup
 emphasize "-- Installing Packages --"
 install_packages "${SCRIPT_DIR}/packages.txt"
 
-emphasize "-- Creating User Account --"
-create_user
+username="$SUDO_USER"
+if [ -z "$username" ]; then
+	emphasize "-- Creating User Account --"
+	create_user
+else
+	user_home=$(getent passwd "$username" | cut -d ':' -f 6)
+fi
 
 emphasize "-- Creating Standard Home Directories --"
 create_directories "${SCRIPT_DIR}/directories.txt"
diff --git a/validate.sh b/validate.sh
new file mode 100755
index 0000000..c5e85cf
--- /dev/null
+++ b/validate.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+info() {
+	printf "%b\n" "${1}"
+}
+
+SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
+skip_regex="^(#.*)?$"
+
+total=$(grep -cvP "$skip_regex" "${SCRIPT_DIR}/packages.txt")
+tput sc
+while read -r package; do
+    echo "$package" | grep -qvP "$skip_regex" || continue
+    n=$((n + 1))
+    eval "info \"(${n}/${total}) Validating $package\""
+    xbps-query -R "$package" >/dev/null 2>&1 || failed_packages="${failed_packages} ${package}"
+    tput rc
+    tput el
+done <"${SCRIPT_DIR}/packages.txt"
+
+echo "Failed packages:${failed_packages}"