./install only ever adds. It copies over /, links dotfiles, installs packages -- and has no way to say "remove that file", "disable that unit", "that symlink points nowhere now". So a machine set up months ago keeps whatever this repository has since decided was wrong, and the only thing that ever fixes it is somebody reading a commit message. With a curl installer in the README, that stopped being hypothetical. A migration is one script that performs one repair, exactly once, on the machines that need it. Named by the commit timestamp that authored it, so glob order is chronological without a sequence number two branches could both pick. Marked in ~/.local/state on success and only on success, so a repair that failed stays pending rather than being recorded as done and hidden forever. Ordered, and stopped at the first failure, because a later repair may assume an earlier one landed. A fresh install marks everything without running it, the way Migrations.qml stamps a pre-versioning settings file at its baseline. The first real one removes the dangling ~/.config/forge symlink left behind when the GNOME session was cut: link-dotfiles could link it but never unlink it. Verified both ways -- a no-op on a machine that never had it, an actual repair on one that did. Root work goes through panama-sudo --reason so the password prompt names the repair, and the contract fails any migration reaching for bare sudo.
45 lines
1.6 KiB
Bash
Executable File
45 lines
1.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Remove the dangling ~/.config/forge symlink left by the GNOME session cut.
|
|
#
|
|
# `forge` was in link-dotfiles' `dirs` array while the GNOME session was still
|
|
# the fallback and Hyprland was being built beside it. Commit 47f29f9 deleted
|
|
# config/dot/forge along with the rest of that hedge, but link-dotfiles has no
|
|
# way to un-link what it once linked: a machine that ran the installer before
|
|
# that commit still has ~/.config/forge pointing into the repository at a path
|
|
# that no longer exists.
|
|
#
|
|
# Nothing reads it, so the cost is only that `ls ~/.config` shows a broken link
|
|
# forever. That is exactly the kind of small permanent wrongness migrations
|
|
# exist to clear.
|
|
#
|
|
# This is the shape every future "a dotfile directory was removed" repair takes:
|
|
# check that the link is dangling AND points into Panama, then remove it. Both
|
|
# halves matter -- a dangling link somebody else made is not ours to delete.
|
|
|
|
set -euo pipefail
|
|
|
|
PANAMA_PATH="${PANAMA_PATH:-$HOME/.local/share/Panama}"
|
|
|
|
link="${XDG_CONFIG_HOME:-$HOME/.config}/forge"
|
|
|
|
# Not a symlink, or not there at all: already correct. Both are the common case
|
|
# on a machine installed after the cut, and neither is a failure.
|
|
[[ -L "$link" ]] || exit 0
|
|
|
|
# Still resolves? Then something else owns this path now and it is not ours to
|
|
# remove.
|
|
[[ -e "$link" ]] && exit 0
|
|
|
|
target="$(readlink "$link")"
|
|
case "$target" in
|
|
"$PANAMA_PATH"/*) ;;
|
|
*)
|
|
echo "Leaving $link alone: it points at $target, which is not Panama's."
|
|
exit 0
|
|
;;
|
|
esac
|
|
|
|
rm -f "$link"
|
|
echo "Removed the dangling $link"
|