Some checks failed
Check / eval (push) Failing after 3m11s
With settings.autoCommit on, only menu/theme mutations were committed (theme-sync pathspec-limits to theme-state.json by design), so hand edits to system.nix/home.nix and lock bumps stayed forever-dirty. New internal nomarchy-autocommit (nomarchy-lifecycle): live-reads the same flag, commits everything dirty as "nomarchy: auto-commit before <pull|rebuild|home switch>" with the swept file list in the body, fallback identity, never fatal (|| true at call sites). Called at the top of all three lifecycle commands; before the ff-only pull it also un-dirties the tree. Exposed via passthru.autocommit + package export; guarded by checks.lifecycle-autocommit (sandbox repos: sweep, no-op on clean/off/non-repo). Sync sweep: README, RECOVERY, ROADMAP, rofi toggle, control-center prompt, theme-sync docstring, JOURNAL. Verified: V1+ — flake check --no-build green; the new check builds; end-to-end run of the built nomarchy-rebuild (stubbed sudo/rebuild) against a copy of a real dirty ~/.nomarchy: 4 files → one commit, clean tree. No VM boot — no session-visible surface. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
217 lines
8.4 KiB
Nix
217 lines
8.4 KiB
Nix
# Day-to-day lifecycle CLIs for a Nomarchy machine flake (~/.nomarchy).
|
|
# Installed on both NixOS (systemPackages) and Home Manager so a home
|
|
# switch can refresh them without waiting for a full system rebuild —
|
|
# otherwise a broken nomarchy-pull can never update itself.
|
|
{ lib, writeShellScriptBin, nvd, jq, symlinkJoin, nomarchy-what-changed }:
|
|
|
|
let
|
|
# Shared preamble: refuse root, resolve flake path.
|
|
preamble = name: ''
|
|
set -euo pipefail
|
|
if [ "$(id -u)" -eq 0 ]; then
|
|
echo "${name}: run as your normal user" >&2
|
|
exit 1
|
|
fi
|
|
flake="''${NOMARCHY_PATH:-$HOME/.nomarchy}"
|
|
'';
|
|
|
|
# Opt-in sweep (settings.autoCommit — the same flag theme-sync honours):
|
|
# commit EVERYTHING dirty in the machine flake before a pull/rebuild/
|
|
# home switch, so hand edits to system.nix/home.nix and lock bumps land
|
|
# in history at the moment they become live — `git log` mirrors the
|
|
# generation list. Complements nomarchy-theme-sync's auto_commit, which
|
|
# is pathspec-limited to theme-state.json on menu writes precisely so
|
|
# half-finished hand edits never ride a settings-named commit; here the
|
|
# sweep is the point, and the commit body lists what was swept. Never
|
|
# fatal — callers `|| true` so a git hiccup can't block a rebuild. Not
|
|
# in the symlinkJoin paths (internal; callers use the store path) but
|
|
# exposed as passthru.autocommit for checks.lifecycle-autocommit.
|
|
nomarchy-autocommit = writeShellScriptBin "nomarchy-autocommit" ''
|
|
${preamble "nomarchy-autocommit"}
|
|
label="''${1:-rebuild}"
|
|
[ -d "$flake/.git" ] || exit 0
|
|
command -v git >/dev/null 2>&1 || exit 0
|
|
flag=$(${jq}/bin/jq -r '.settings.autoCommit // false' \
|
|
"$flake/theme-state.json" 2>/dev/null || true)
|
|
[ "$flag" = "true" ] || exit 0
|
|
dirty=$(git -C "$flake" status --porcelain || true)
|
|
[ -n "$dirty" ] || exit 0
|
|
g=(git -C "$flake")
|
|
if [ -z "$("''${g[@]}" config user.email 2>/dev/null || true)" ]; then
|
|
g+=(-c user.name=Nomarchy -c user.email=nomarchy@localhost)
|
|
fi
|
|
"''${g[@]}" add -A
|
|
if "''${g[@]}" commit --quiet -m "nomarchy: auto-commit before $label" \
|
|
-m "$dirty"; then
|
|
echo "nomarchy-autocommit: committed pending flake changes before $label:"
|
|
echo "$dirty" | sed 's/^/ /'
|
|
else
|
|
echo "nomarchy-autocommit: commit failed — continuing without it" >&2
|
|
fi
|
|
'';
|
|
|
|
nomarchy-pull = writeShellScriptBin "nomarchy-pull" ''
|
|
${preamble "nomarchy-pull"}
|
|
if [ ! -e "$flake/flake.nix" ]; then
|
|
echo "nomarchy-pull: no flake.nix at $flake" >&2
|
|
echo " Set NOMARCHY_PATH or put your machine flake in ~/.nomarchy." >&2
|
|
exit 1
|
|
fi
|
|
# With settings.autoCommit on, sweep pending hand edits into a commit
|
|
# first — also keeps the ff-only pull below safe on a dirty tree.
|
|
${nomarchy-autocommit}/bin/nomarchy-autocommit pull || true
|
|
# Optional: pull *your* machine config only if this checkout tracks a
|
|
# remote. Distro updates come from the nomarchy flake *input* below —
|
|
# many installs have no upstream on ~/.nomarchy (local auto-commits).
|
|
if [ -d "$flake/.git" ] \
|
|
&& git -C "$flake" rev-parse --abbrev-ref '@{u}' >/dev/null 2>&1; then
|
|
echo "nomarchy-pull: git pull --ff-only (machine flake tracks upstream)"
|
|
git -C "$flake" pull --ff-only
|
|
elif [ -d "$flake/.git" ]; then
|
|
echo "nomarchy-pull: machine flake has no upstream branch — skipping git pull"
|
|
echo " (normal for a local-only ~/.nomarchy; distro updates use flake inputs)"
|
|
fi
|
|
echo "nomarchy-pull: nix flake update in $flake"
|
|
nix flake update --flake "$flake"
|
|
nom=$(nix flake metadata "$flake" --json 2>/dev/null \
|
|
| ${jq}/bin/jq -r '
|
|
.locks.nodes.nomarchy.locked
|
|
| if . == null then empty
|
|
elif .rev then "nomarchy @ \(.rev[0:12])"
|
|
else empty end
|
|
' 2>/dev/null || true)
|
|
[ -n "''${nom:-}" ] && echo "nomarchy-pull: $nom"
|
|
echo "nomarchy-pull: done — next: nomarchy-rebuild then nomarchy-home"
|
|
'';
|
|
|
|
nomarchy-rebuild = writeShellScriptBin "nomarchy-rebuild" ''
|
|
${preamble "nomarchy-rebuild"}
|
|
if [ ! -e "$flake/flake.nix" ]; then
|
|
echo "nomarchy-rebuild: no flake.nix at $flake" >&2
|
|
exit 1
|
|
fi
|
|
# With settings.autoCommit on, sweep pending hand edits (system.nix,
|
|
# lock bumps, …) into a commit so `git log` mirrors the generations.
|
|
${nomarchy-autocommit}/bin/nomarchy-autocommit rebuild || true
|
|
before=$(readlink -f /run/current-system)
|
|
log=$(mktemp)
|
|
trap 'rm -f "$log"' EXIT
|
|
set +e
|
|
if command -v nixos-rebuild-snap >/dev/null 2>&1; then
|
|
sudo env NOMARCHY_PATH="$flake" nixos-rebuild-snap "$@" 2>&1 | tee "$log"
|
|
else
|
|
sudo nixos-rebuild switch --flake "$flake#default" "$@" 2>&1 | tee "$log"
|
|
fi
|
|
rc=''${PIPESTATUS[0]}
|
|
set -e
|
|
if [ "$rc" -ne 0 ]; then
|
|
echo
|
|
echo "nomarchy-rebuild: FAILED (exit $rc). Last lines:"
|
|
tail -n 40 "$log" || true
|
|
echo
|
|
echo "Diagnose: nomarchy-doctor"
|
|
echo "Recovery: docs/RECOVERY.md (boot menu generations / snapper)"
|
|
exit "$rc"
|
|
fi
|
|
after=$(readlink -f /run/current-system)
|
|
if [ "$before" = "$after" ]; then
|
|
echo "nomarchy-rebuild: no changes — the system is identical."
|
|
else
|
|
echo "nomarchy-rebuild: what changed:"
|
|
${nvd}/bin/nvd diff "$before" "$after" || true
|
|
# One-line toast for the session (full report already on the terminal).
|
|
if command -v notify-send >/dev/null 2>&1 \
|
|
&& command -v nomarchy-what-changed >/dev/null 2>&1; then
|
|
body=$(nomarchy-what-changed --summary --diff "$before" "$after" 2>/dev/null \
|
|
| sed 's/^Diff: //' || true)
|
|
[ -n "''${body:-}" ] && notify-send -a Nomarchy "System rebuild" "$body" || true
|
|
fi
|
|
fi
|
|
'';
|
|
|
|
nomarchy-home = writeShellScriptBin "nomarchy-home" ''
|
|
${preamble "nomarchy-home"}
|
|
if [ ! -e "$flake/flake.nix" ]; then
|
|
echo "nomarchy-home: no flake.nix at $flake" >&2
|
|
exit 1
|
|
fi
|
|
# With settings.autoCommit on, sweep pending hand edits (home.nix, …)
|
|
# into a commit so `git log` mirrors the generations.
|
|
${nomarchy-autocommit}/bin/nomarchy-autocommit "home switch" || true
|
|
# Snapshot the active HM generation before the switch so we can nvd it.
|
|
hm_before=""
|
|
for d in \
|
|
"''${XDG_STATE_HOME:-$HOME/.local/state}/nix/profiles" \
|
|
"/nix/var/nix/profiles/per-user/$(id -un)"; do
|
|
if [ -L "$d/home-manager" ]; then
|
|
hm_before=$(readlink -f "$d/home-manager" 2>/dev/null || true)
|
|
break
|
|
fi
|
|
done
|
|
log=$(mktemp)
|
|
trap 'rm -f "$log"' EXIT
|
|
set +e
|
|
home-manager switch --flake "$flake" "$@" 2>&1 | tee "$log"
|
|
rc=''${PIPESTATUS[0]}
|
|
set -e
|
|
if [ "$rc" -ne 0 ]; then
|
|
echo
|
|
echo "nomarchy-home: FAILED (exit $rc). Last lines:"
|
|
tail -n 40 "$log" || true
|
|
echo
|
|
echo "Diagnose: nomarchy-doctor"
|
|
echo "Recovery: home-manager generations (or docs/RECOVERY.md)"
|
|
exit "$rc"
|
|
fi
|
|
hm_after=""
|
|
for d in \
|
|
"''${XDG_STATE_HOME:-$HOME/.local/state}/nix/profiles" \
|
|
"/nix/var/nix/profiles/per-user/$(id -un)"; do
|
|
if [ -L "$d/home-manager" ]; then
|
|
hm_after=$(readlink -f "$d/home-manager" 2>/dev/null || true)
|
|
break
|
|
fi
|
|
done
|
|
if [ -n "$hm_before" ] && [ -n "$hm_after" ] && [ "$hm_before" != "$hm_after" ]; then
|
|
echo "nomarchy-home: what changed:"
|
|
${nvd}/bin/nvd diff "$hm_before" "$hm_after" || true
|
|
if command -v notify-send >/dev/null 2>&1 \
|
|
&& command -v nomarchy-what-changed >/dev/null 2>&1; then
|
|
body=$(nomarchy-what-changed --summary --diff "$hm_before" "$hm_after" 2>/dev/null \
|
|
| sed 's/^Diff: //' || true)
|
|
[ -n "''${body:-}" ] && notify-send -a Nomarchy "Desktop updated" "$body" || true
|
|
fi
|
|
else
|
|
echo "nomarchy-home: desktop applied."
|
|
fi
|
|
'';
|
|
|
|
# Legacy aliases
|
|
sys-update = writeShellScriptBin "sys-update" ''
|
|
nomarchy-pull && nomarchy-rebuild "$@"
|
|
'';
|
|
sys-rebuild = writeShellScriptBin "sys-rebuild" ''
|
|
exec nomarchy-rebuild "$@"
|
|
'';
|
|
home-update = writeShellScriptBin "home-update" ''
|
|
exec nomarchy-home "$@"
|
|
'';
|
|
in
|
|
symlinkJoin {
|
|
name = "nomarchy-lifecycle";
|
|
paths = [
|
|
nomarchy-pull
|
|
nomarchy-rebuild
|
|
nomarchy-home
|
|
sys-update
|
|
sys-rebuild
|
|
home-update
|
|
nomarchy-what-changed
|
|
];
|
|
passthru.autocommit = nomarchy-autocommit;
|
|
meta = {
|
|
description = "Nomarchy machine-flake lifecycle: pull, rebuild, home";
|
|
mainProgram = "nomarchy-pull";
|
|
};
|
|
}
|