[Sync] adopt unified stow layout from the private repo

Mirrors the private dots tree at 900bdda: one shared base plus per-host
overlays, replacing the old flat .config/ layout (last synced 2026-06-28).

- packages: common/ gui/ wm/ lw/ fl/ + install.sh and bin/ tooling (dotsync,
  reconcile-hyde.sh)
- new README (layout, deploy order, HyDE dependency), plus ToDo.md and
  HYDE-UPDATE.md
- current HyDE waybar rig (layouts/, cava), pi agent extensions, claude/
  config, tmux, presenterm, aichat roles
- drops stale duplicates and generated cruft that should never have been
  tracked: the second top-level .pi/ copy, btop.log, zellij config.kdl.bak,
  fish_variables, nvim codecompanion.lua
- .pi/agent/auth.json is gitignored now; auth.json.example ships instead
- fl/ and wm/ hypr themes/ stay untracked (HyDE-generated per machine, per
  the root .gitignore)
This commit is contained in:
coja
2026-08-12 22:50:18 +02:00
parent f62cb40499
commit a700e23e0a
318 changed files with 12564 additions and 10772 deletions
+174
View File
@@ -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"