[Sync] replace the flat layout with the unified stow tree
Supersedes the old flat .config/ layout (last published 2026-06-28) with the private repo's structure: one shared base plus per-host overlays. - packages: common/ gui/ lw/ fl/ wm/ plus install.sh and bin/ tooling (dotsync, reconcile-hyde.sh) - new README covering the layout, deploy order and the HyDE dependency - current HyDE waybar rig (layouts/, cava), pi agent extensions, claude/ config, tmux, presenterm, aichat roles - fish: kp (keepassxc-cli + fzf picker, db path from $KP_DB) and bind_M_n_history (alt+1..9 recalls the nth history entry) - drops cruft that should never have been tracked: the duplicate top-level .pi/ copy, btop.log, zellij config.kdl.bak, fish_variables - .pi/agent/auth.json is gitignored; auth.json.example ships instead Host-specific work sessions and the personal backlog stay in the private tree. Endpoint locators in the llamacpp/whisper guides are placeholders ($SERVER, <own-domain>) — the guides themselves stay, since they are the useful part.
This commit is contained in:
Executable
+174
@@ -0,0 +1,174 @@
|
||||
#!/usr/bin/env bash
|
||||
# reconcile-hyde.sh — reconcile a HyDE update with your dots-tracked configs.
|
||||
#
|
||||
# HyDE's updater (`Scripts/install.sh -r`) overwrites every config listed in
|
||||
# Scripts/restore_cfg.psv — including ~/.config/hypr/*. It backs the old ones up to
|
||||
# ~/.config/cfg_backups and REPLACES your stow symlinks with real files (HyDE's new
|
||||
# defaults). This tool, run ON THE GUI MACHINE right after that update, shows per file:
|
||||
# your dots version vs HyDE's new one
|
||||
# lets you keep / take / merge each, then removes the severed real files and re-runs
|
||||
# install.sh so everything is symlinked back to the repo.
|
||||
#
|
||||
# ./bin/reconcile-hyde.sh [host] report only — safe, changes nothing (default)
|
||||
# ./bin/reconcile-hyde.sh -i [host] interactive: decide each conflicting file
|
||||
# ./bin/reconcile-hyde.sh --relink [host] skip decisions: back up severed files,
|
||||
# then re-stow (repo versions win)
|
||||
#
|
||||
# host defaults to `hostname -s`. Commit your repo first so choices are reviewable/revertable.
|
||||
set -uo pipefail
|
||||
|
||||
# Config subtrees where HyDE and your dots overlap. Add/remove as your setup needs.
|
||||
SUBTREES=(.config/hypr .config/waybar)
|
||||
|
||||
# --- args ---
|
||||
MODE=report
|
||||
HOST=""
|
||||
for a in "$@"; do
|
||||
case "$a" in
|
||||
-i|--interactive) MODE=interactive ;;
|
||||
--relink) MODE=relink ;;
|
||||
-h|--help) awk 'NR > 1 && !/^#/ { exit } NR > 1' "$0"; exit 0 ;;
|
||||
-*) echo "unknown option: $a" >&2; exit 2 ;;
|
||||
*) HOST="$a" ;;
|
||||
esac
|
||||
done
|
||||
[ -z "$HOST" ] && HOST="$(hostname -s)"
|
||||
skip_relink=() # files the user chose to skip during interactive reconcile
|
||||
|
||||
DOTS="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/.." && pwd)" # repo root (script in bin/)
|
||||
[ -x "$DOTS/install.sh" ] || { echo "error: $DOTS/install.sh not found — run from inside the dots repo" >&2; exit 1; }
|
||||
|
||||
# repo package search order: host overlay wins, then gui, then common
|
||||
PKGS=("$HOST" gui common)
|
||||
repo_src() { # repo_src <rel-path> -> print the repo file stow would link, or nothing
|
||||
local rel="$1" p
|
||||
for p in "${PKGS[@]}"; do
|
||||
[ -f "$DOTS/$p/$rel" ] && { printf '%s\n' "$DOTS/$p/$rel"; return 0; }
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
echo "host=$HOST dots=$DOTS mode=$MODE"
|
||||
if [ -n "$(git -C "$DOTS" status --porcelain 2>/dev/null)" ]; then
|
||||
echo "note: $DOTS has uncommitted changes — commit first so reconcile choices are reviewable." >&2
|
||||
fi
|
||||
[ -d "$HOME/.config/cfg_backups" ] && echo "HyDE's pre-update backups are in ~/.config/cfg_backups"
|
||||
echo
|
||||
|
||||
# --- classify every live file under the managed subtrees ---
|
||||
linked=0; foreign=0
|
||||
same=(); conflicts=(); new_files=()
|
||||
for st in "${SUBTREES[@]}"; do
|
||||
[ -d "$HOME/$st" ] || continue
|
||||
while IFS= read -r -d '' live; do
|
||||
rel="${live#"$HOME"/}"
|
||||
if [ -L "$live" ]; then # still a symlink
|
||||
tgt="$(readlink -f "$live" 2>/dev/null || true)"
|
||||
case "$tgt" in
|
||||
"$DOTS"/*) linked=$((linked+1)) ;; # intact -> HyDE didn't sever it
|
||||
*) foreign=$((foreign+1)); echo " ? $rel -> symlink outside repo: $tgt" ;;
|
||||
esac
|
||||
continue
|
||||
fi
|
||||
# real file: HyDE overwrote (severed) it, or it is brand new
|
||||
src="$(repo_src "$rel" || true)"
|
||||
if [ -z "$src" ]; then
|
||||
new_files+=("$rel")
|
||||
elif diff -q "$src" "$live" >/dev/null 2>&1; then
|
||||
same+=("$rel") # content == repo; just relink
|
||||
else
|
||||
conflicts+=("$rel") # HyDE's new content differs from yours
|
||||
fi
|
||||
done < <(find "$HOME/$st" \( -type f -o -type l \) -print0)
|
||||
done
|
||||
|
||||
echo "== summary =="
|
||||
echo " intact symlinks (untouched): $linked"
|
||||
echo " severed but identical (relink): ${#same[@]}"
|
||||
echo " severed & CHANGED (need decision): ${#conflicts[@]}"
|
||||
echo " new HyDE files not tracked by dots: ${#new_files[@]}"
|
||||
[ "$foreign" -gt 0 ] && echo " foreign symlinks flagged above: $foreign"
|
||||
echo
|
||||
if [ "$linked" -gt 0 ]; then
|
||||
echo "For intact symlinks, check whether HyDE wrote THROUGH them into the repo:"
|
||||
echo " git -C $DOTS diff -- '*/.config/hypr/*' '*/.config/waybar/*'"
|
||||
echo
|
||||
fi
|
||||
if [ "${#new_files[@]}" -gt 0 ]; then
|
||||
echo "New HyDE files (left as-is; add to a package + re-stow if you want them tracked):"
|
||||
printf ' %s\n' "${new_files[@]}"
|
||||
echo
|
||||
fi
|
||||
if [ "${#conflicts[@]}" -gt 0 ]; then
|
||||
echo "Changed files (your dots version vs HyDE's new default):"
|
||||
for rel in "${conflicts[@]}"; do
|
||||
src="$(repo_src "$rel")"
|
||||
printf ' %-45s %s changed lines\n' "$rel" "$(diff "$src" "$HOME/$rel" | grep -cE '^[<>]')"
|
||||
done
|
||||
echo
|
||||
fi
|
||||
|
||||
# report-only ends here
|
||||
if [ "$MODE" = report ]; then
|
||||
if [ "${#conflicts[@]}" -gt 0 ]; then
|
||||
echo "Re-run with -i to decide each changed file, or --relink to keep your repo versions wholesale."
|
||||
elif [ "${#same[@]}" -gt 0 ]; then
|
||||
echo "No content conflicts. Re-run with --relink to drop the severed files and re-symlink."
|
||||
else
|
||||
echo "Nothing to reconcile."
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- interactive: decide each changed file, writing the choice into the repo copy ---
|
||||
if [ "$MODE" = interactive ] && [ "${#conflicts[@]}" -gt 0 ]; then
|
||||
for rel in "${conflicts[@]}"; do
|
||||
src="$(repo_src "$rel")"; live="$HOME/$rel"
|
||||
echo "──────── $rel ────────"
|
||||
echo " repo (yours): ${src#"$DOTS"/}"
|
||||
diff "$src" "$live" | sed 's/^/ /' | head -60
|
||||
echo " [k]eep yours (default) [t]ake HyDE's [m]erge in \$EDITOR -d [s]kip"
|
||||
read -r -p " choice> " ans </dev/tty || ans=k
|
||||
case "$ans" in
|
||||
t|take) cp "$live" "$src"; echo " -> took HyDE's version into $src" ;;
|
||||
m|merge) "${EDITOR:-nvim}" -d "$src" "$live" </dev/tty >/dev/tty 2>&1; echo " -> merged (saved $src)" ;;
|
||||
s|skip) echo " -> skipped (left severed; not relinked)"; skip_relink+=("$rel") ;;
|
||||
*) echo " -> kept your repo version" ;;
|
||||
esac
|
||||
done
|
||||
echo
|
||||
fi
|
||||
|
||||
# --- relink: back up severed files that the repo owns, remove them, re-stow ---
|
||||
BK="$HOME/.config/hyde-reconcile-backup-$(date +%Y%m%d-%H%M%S)"
|
||||
to_relink=()
|
||||
for st in "${SUBTREES[@]}"; do
|
||||
[ -d "$HOME/$st" ] || continue
|
||||
while IFS= read -r -d '' live; do
|
||||
[ -L "$live" ] && continue # only real (severed) files
|
||||
rel="${live#"$HOME"/}"
|
||||
repo_src "$rel" >/dev/null || continue # only files the repo can provide
|
||||
for s in "${skip_relink[@]}"; do [ "$s" = "$rel" ] && continue 2; done
|
||||
to_relink+=("$rel")
|
||||
done < <(find "$HOME/$st" -type f -print0)
|
||||
done
|
||||
|
||||
if [ "${#to_relink[@]}" -eq 0 ]; then
|
||||
echo "nothing to relink."; exit 0
|
||||
fi
|
||||
echo "will back up + remove ${#to_relink[@]} severed file(s), then re-stow so they link to the repo:"
|
||||
printf ' %s\n' "${to_relink[@]}"
|
||||
read -r -p "proceed? [y/N] " go </dev/tty || go=n
|
||||
case "$go" in y|Y|yes) ;; *) echo "aborted — nothing changed."; exit 0 ;; esac
|
||||
|
||||
for rel in "${to_relink[@]}"; do
|
||||
mkdir -p "$BK/$(dirname "$rel")"
|
||||
cp -a "$HOME/$rel" "$BK/$rel"
|
||||
rm -f "$HOME/$rel"
|
||||
done
|
||||
echo "backed up to $BK; removed severed files. re-stowing…"
|
||||
"$DOTS/install.sh" "$HOST"
|
||||
|
||||
echo
|
||||
echo "done. verify a couple of links resolve into the repo, e.g.:"
|
||||
echo " readlink ~/.config/hypr/keybindings.conf"
|
||||
Reference in New Issue
Block a user