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