aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.github/copilot-instructions.md2
-rw-r--r--justfile35
2 files changed, 36 insertions, 1 deletions
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index a72ec26..a91bc99 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -21,7 +21,7 @@ The repo root is a chezmoi source directory. Files targeting `$HOME` use chezmoi
- `bootstrap.sh` at the repo root is a POSIX shell script that takes a fresh minimal Arch install (only `base`) to a fully deployed state. It installs prerequisites, enables `%wheel` sudoers, bootstraps `paru-bin` from the AUR, clones the repo, runs `just init`, and optionally invokes `create-efi`. Designed to be curlable: `curl -fsSL .../bootstrap.sh | sh`.
- `.chezmoiignore` excludes non-home files (`etc/`, `meta/`, `systemd-units/`, `firefox/`, docs) from deployment to `$HOME`.
- `.githooks/` contains git hooks (notably `post-commit` which runs `chezmoi apply`). Activated by `just init`.
-- `justfile` provides recipes: `init` (first-time setup), `sync` (apply + fix), `apply`, `readd`, `fix`, `status`, `pkg-drift`, `dotfile-drift`, `undeclared`, `diff`, `merge`, `groups`, `install`, `install-all`, `add`, `remove`, `services`, `services-enable`, `services-drift`, `etc`, `etc-diff`, `etc-upstream-diff`, `etc-add`, `etc-readd`, `etc-rm`, `etc-reset`, `etc-untrack`. Run `just` or `just --list` to see them.
+- `justfile` provides recipes: `init` (first-time setup), `sync` (apply + fix), `apply`, `readd`, `fix`, `status`, `pkg-drift`, `dotfile-drift`, `undeclared`, `diff`, `merge`, `groups`, `install`, `install-all`, `add`, `remove`, `services`, `services-enable`, `services-drift`, `etc`, `etc-diff`, `etc-upstream-diff`, `etc-add`, `etc-readd`, `etc-rm`, `etc-reset`, `etc-untrack`, `etc-restore`. Run `just` or `just --list` to see them.
## Window manager
diff --git a/justfile b/justfile
index bbf2eec..f8205ff 100644
--- a/justfile
+++ b/justfile
@@ -448,6 +448,41 @@ etc-untrack +paths:
just etc-reset {{ paths }}
just etc-rm {{ paths }}
+# Restore live /etc/<path> to pristine pacman contents (bypasses the repo)
+etc-restore +paths:
+ #!/usr/bin/env bash
+ set -eo pipefail
+ for raw in {{ paths }}; do
+ case "$raw" in
+ *..*|*/./*|./*|../*) echo "error: unsafe path: $raw" >&2; exit 1 ;;
+ esac
+ p=${raw#/}; p=${p#etc/}
+ live=/etc/$p
+ [ -e "$live" ] || { echo "error: $live does not exist" >&2; exit 1; }
+ pkg=$(pacman -Qoq "$live" 2>/dev/null) \
+ || { echo "error: $live has no owning package; nothing to restore to" >&2; exit 1; }
+ ver=$(pacman -Q "$pkg" | awk '{print $2}')
+ arch=$(pacman -Qi "$pkg" | awk -F': *' '/^Architecture/{print $2; exit}')
+ cache=""
+ for ext in zst xz; do
+ c="/var/cache/pacman/pkg/${pkg}-${ver}-${arch}.pkg.tar.${ext}"
+ [ -f "$c" ] && { cache="$c"; break; }
+ done
+ if [ -z "$cache" ]; then
+ echo " fetching $pkg from mirror..." >&2
+ doas pacman -Sw --noconfirm "$pkg" >/dev/null || true
+ for ext in zst xz; do
+ c="/var/cache/pacman/pkg/${pkg}-${ver}-${arch}.pkg.tar.${ext}"
+ [ -f "$c" ] && { cache="$c"; break; }
+ done
+ fi
+ [ -n "$cache" ] || { echo "error: no cache for ${pkg}-${ver}; mirror may have moved past installed version" >&2; exit 1; }
+ bsdtar -tf "$cache" "${live#/}" >/dev/null 2>&1 \
+ || { echo "error: $live not present in $pkg archive" >&2; exit 1; }
+ bsdtar -xOf "$cache" "${live#/}" | doas tee "$live" >/dev/null
+ echo "restored (from $pkg): $live"
+ done
+
# ═══════════════════════════════════════════════════════════════════
# Package management
# ═══════════════════════════════════════════════════════════════════