add config-updater: config-driven update script with manifest

Replaces the hardcoded inline-generated ~/update-hypr-configs.sh with
a proper dotfiles-resident script + config file:

  config-updater/update-configs.sh  — reads updater.conf, applies
    configs, warns about untracked source items and manifest drift
  config-updater/updater.conf       — declares config/flat/ignore
    entries and SOURCE_BASE; hypr-usr is flat (contents → ~/.config/)

hyprland-new.sh step 15 now symlinks both into place instead of
generating a hardcoded script inline. The output is renamed from
~/update-hypr-configs.sh to ~/update-configs.sh.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
The_miro 2026-05-11 09:46:02 +02:00
parent 13a1b6cff4
commit c4b9c5bf92
3 changed files with 169 additions and 10 deletions

View File

@ -0,0 +1,123 @@
#!/usr/bin/env bash
# update-configs — sync dotfiles configs into ~/.config
#
# Config: ~/.config/config-updater/updater.conf
# Manifest: ~/.config/config-updater/manifest
set -euo pipefail
CONF_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/config-updater"
CONF_FILE="${CONF_DIR}/updater.conf"
MANIFEST="${CONF_DIR}/manifest"
TARGET="${XDG_CONFIG_HOME:-$HOME/.config}"
RED='\033[0;31m'; YEL='\033[1;33m'; GRN='\033[0;32m'; DIM='\033[2m'; RST='\033[0m'
err() { printf "${RED}✖ %s${RST}\n" "$*" >&2; }
warn() { printf "${YEL}⚠ %s${RST}\n" "$*"; }
ok() { printf "${GRN}✔ %s${RST}\n" "$*"; }
note() { printf "${DIM} %s${RST}\n" "$*"; }
die() { err "$*"; exit 1; }
[[ -f "$CONF_FILE" ]] || die "Config not found: $CONF_FILE"
# ── parse updater.conf ────────────────────────────────────────────────────────
SOURCE_BASE=""
declare -A ENTRY_TYPE # name → config | flat | ignore
while IFS= read -r line; do
line="${line%%#*}"
line="${line#"${line%%[! ]*}"}"
line="${line%"${line##*[! ]}"}"
[[ -z "$line" ]] && continue
if [[ "$line" =~ ^SOURCE_BASE[[:space:]]*=[[:space:]]*(.+)$ ]]; then
src="${BASH_REMATCH[1]%"${BASH_REMATCH[1]##*[! ]}"}"
SOURCE_BASE="${src/#\~/$HOME}"
continue
fi
read -r type name _rest <<< "$line"
[[ -z "${name:-}" ]] && continue
case "$type" in
config|flat|ignore) ENTRY_TYPE["$name"]="$type" ;;
*) warn "Unknown type '$type' for '$name' — skipping" ;;
esac
done < "$CONF_FILE"
[[ -n "$SOURCE_BASE" ]] || die "SOURCE_BASE not defined in $CONF_FILE"
[[ -d "$SOURCE_BASE" ]] || die "SOURCE_BASE not found: $SOURCE_BASE"
# ── load previous manifest ────────────────────────────────────────────────────
declare -A PREV_MANIFEST
if [[ -f "$MANIFEST" ]]; then
while IFS=: read -r mtype mname; do
[[ -n "${mtype:-}" && -n "${mname:-}" ]] && PREV_MANIFEST["$mname"]="$mtype"
done < "$MANIFEST"
fi
warned=0
# ── warn: manifest entries no longer in updater.conf ─────────────────────────
for mname in "${!PREV_MANIFEST[@]}"; do
[[ -n "${ENTRY_TYPE[$mname]:-}" ]] && continue
warn "'$mname' was previously managed but is no longer in updater.conf"
note "Remove ~/.config/$mname manually if it is no longer needed"
warned=1
done
# ── warn: source items not covered by updater.conf ───────────────────────────
while IFS= read -r -d '' item; do
name="$(basename "$item")"
[[ "$name" == .* ]] && continue
[[ -n "${ENTRY_TYPE[$name]:-}" ]] && continue
warn "Untracked source item: '$name' — add to updater.conf (config / flat / ignore)"
warned=1
done < <(find "$SOURCE_BASE" -maxdepth 1 -mindepth 1 -print0 | sort -z)
(( warned )) && printf '\n'
# ── apply ─────────────────────────────────────────────────────────────────────
errors=0
new_manifest=()
for name in "${!ENTRY_TYPE[@]}"; do
type="${ENTRY_TYPE[$name]}"
[[ "$type" == ignore ]] && continue
src="${SOURCE_BASE}/${name}"
if [[ ! -e "$src" ]]; then
err "Source missing: $src"
(( errors++ )) || true
continue
fi
case "$type" in
config)
rm -rf "${TARGET:?}/${name}"
cp -r "$src" "$TARGET/$name"
ok "config $name"
;;
flat)
[[ -d "$src" ]] || {
err "flat entry '$name' must be a directory: $src"
(( errors++ )) || true
continue
}
cp -r "${src}/." "$TARGET/"
ok "flat $name → (contents into ~/.config/)"
;;
esac
new_manifest+=("${type}:${name}")
done
# ── write manifest ────────────────────────────────────────────────────────────
printf '%s\n' "${new_manifest[@]}" | sort > "$MANIFEST"
printf '\n'
if (( errors > 0 )); then
err "$errors error(s) — manifest may be incomplete"
exit 1
else
ok "Done — manifest updated at $MANIFEST"
fi

View File

@ -0,0 +1,42 @@
# Config updater — defines which dotfiles configs are deployed to ~/.config
#
# SOURCE_BASE base directory containing all configs in the dotfiles
#
# config <name> copy SOURCE_BASE/<name> to ~/.config/<name>
# flat <name> copy contents of SOURCE_BASE/<name> directly into ~/.config/
# (for installation-specific files that live at the ~/.config root)
# ignore <name> present in source but intentionally not managed here
SOURCE_BASE = ~/Dotfiles/desktopenvs/hyprland
# ── deployed as ~/.config/<name> ─────────────────────────────────────────────
config alacritty
config btop
config dunst
config gtk-3.0
config hypr
config kitty
config mimeapps.list
config nwg-dock-hyprland
config nwg-drawer
config nwg-panel
config scripts
config ulauncher
config vicinae
config walker
config wofi
config xfce4
# ── flat: directory contents copied directly into ~/.config/ ──────────────────
flat hypr-usr # installation-specific: binds, monitors, autostart, etc.
# ── intentionally not managed here ───────────────────────────────────────────
ignore config-updater # the updater itself
ignore CRT # referenced from dotfiles path directly in binds.conf
ignore eww # eww bar variant selected and installed separately
ignore eww-nobattery
ignore eww-touch
ignore greetd-tuigreet # deployed to /etc/greetd/ at install time
ignore spicetify # managed separately (spicetify handles its own config)
ignore Vencord # managed separately
ignore waybar # present but inactive; eww bar is used instead

View File

@ -122,16 +122,10 @@ fi
sudo systemctl enable udiskie.service
sudo systemctl start udiskie.service
# 15. Generate config-update helper
cat << 'EOF' > ~/update-hypr-configs.sh
#!/bin/bash
CONFIGS=(kitty mimeapps.list walker ulauncher vicinae hypr xfce4 wofi dunst alacritty nwg-dock-hyprland nwg-drawer nwg-panel scripts btop gtk-3.0)
for cfg in "${CONFIGS[@]}"; do
cp -r ~/Dotfiles/desktopenvs/hyprland/"$cfg" ~/.config/
done
echo "Configs updated."
EOF
chmod +x ~/update-hypr-configs.sh
# 15. Install config updater
mkdir -p ~/.config/config-updater
ln -sf ~/Dotfiles/desktopenvs/hyprland/config-updater/updater.conf ~/.config/config-updater/updater.conf
ln -sf ~/Dotfiles/desktopenvs/hyprland/config-updater/update-configs.sh ~/update-configs.sh
# 16. WallRizz (run manually after login — requires a running desktop session)
# curl -sL "$(curl -s https://api.github.com/repos/5hubham5ingh/WallRizz/releases/latest \