From 41db5fc767fbe5a5453b2fa0583de8c3b2cf4021 Mon Sep 17 00:00:00 2001 From: Tom van der Lee Date: Thu, 17 Sep 2026 11:49:58 +0200 Subject: Add automatic dotfiles clone + stow modules/home/dotfiles.nix clones ~/dotfiles on activation (only if not already present) and stows every top-level package directory into $HOME, independently per package so one conflict doesn't block the rest. Removes home-manager's own git config management in favor of letting the stowed ~/dotfiles/git/.gitconfig own it, and adds homeConfigurations."tom@darwin" so the feature is usable on this Mac. users/tom.nix now points home.dotfiles.repoUrl at the real repo. --- .../changes/add-dotfiles-stow-bootstrap/tasks.md | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 openspec/changes/add-dotfiles-stow-bootstrap/tasks.md (limited to 'openspec/changes/add-dotfiles-stow-bootstrap/tasks.md') diff --git a/openspec/changes/add-dotfiles-stow-bootstrap/tasks.md b/openspec/changes/add-dotfiles-stow-bootstrap/tasks.md new file mode 100644 index 0000000..228a5fa --- /dev/null +++ b/openspec/changes/add-dotfiles-stow-bootstrap/tasks.md @@ -0,0 +1,39 @@ +## 1. Dotfiles module + +- [x] 1.1 Create `modules/home/dotfiles.nix` defining `options.home.dotfiles.repoUrl` (string, default `""`) — verify by reading the option definition against the template in design.md +- [x] 1.2 Implement `config = lib.mkIf (cfg.repoUrl != "") { ... }` wrapping the feature so it's fully inert when unset — verify the `mkIf` condition guards both `home.packages` and `home.activation.dotfiles` +- [x] 1.3 Add `home.packages = [ pkgs.git pkgs.stow ];` inside the `mkIf` block — verify both packages are listed +- [x] 1.4 Implement `home.activation.dotfiles` using `lib.hm.dag.entryAfter [ "writeBoundary" ]`: clone `cfg.repoUrl` to `~/dotfiles` with `--recurse-submodules` only if `~/dotfiles/.git` doesn't already exist, using `$DRY_RUN_CMD` on the clone — verify the existence check precedes the clone and no unconditional clone/rm exists +- [x] 1.5 In the same activation script, loop over non-hidden top-level directories under `~/dotfiles` and run `stow -d ~/dotfiles -t ` per directory (via `$DRY_RUN_CMD`), with `|| echo "Warning: ..." >&2` so one failure doesn't abort the loop — verify the loop skips hidden entries (`case "$pkg_name" in .*) continue ;; esac`) and each `stow` call is independently fault-tolerant +- [x] 1.6 Add `modules/home/dotfiles.nix` to `modules/home/default.nix`'s imports — verify by grep confirming the import is present + +## 2. Remove home-manager git config management + +- [x] 2.1 Delete `modules/home/git.nix` — verify the file no longer exists +- [x] 2.2 Remove `./git.nix` from `modules/home/default.nix`'s imports — verify by grep confirming no reference to `git.nix` remains in that file +- [x] 2.3 Remove the `programs.git = { userName = ...; userEmail = ...; };` block from `users/tom.nix` — verify by reading the file and confirming no `programs.git` reference remains + +## 3. Keep git available independent of the dotfiles feature + +- [x] 3.1 Add `pkgs.git` to `modules/home/cli-tools.nix`'s package list — verify by reading the updated package list + +## 4. Darwin home-manager output + +- [x] 4.1 Add `homeConfigurations."tom@darwin" = lib.mkHome { username = "tom"; system = "aarch64-darwin"; };` to `flake.nix`, alongside the existing `tom@linux` entry — verify by grep confirming both entries exist + +## 5. Open task: repo URL + +- [x] 5.1 In `users/tom.nix`, add `home.dotfiles.repoUrl = "";` with a comment marking it as an intentional placeholder for the user to fill in later — verify the value is an empty string, not a guessed or invented URL, and the comment is present (left blank as specified; the user has since supplied the real URL directly — `home.dotfiles.repoUrl = "https://git.tomvanderlee.com/dotfiles"` — so this open item is now resolved, not just scaffolded) + +## 6. Documentation + +- [x] 6.1 Update `README.md` to document the dotfiles feature (what it does, that it's opt-in via `home.dotfiles.repoUrl`) and note the open task of filling in the real URL — verify by reading the updated section for consistency with the actual module behavior (also fixed two now-stale mentions: the layout line still listing "git" as a managed module, and the non-NixOS section only mentioning `tom@linux`) + +## 7. Validation + +- [ ] 7.1 Run `nix flake check` and confirm the new module and `tom@darwin` output evaluate without error (blocked — Nix is not installed on this machine; run this once Nix is available, e.g. via a real install or CI — this is the real acceptance gate, not the individual checkboxes above) +- [x] 7.2 Manually trace through each spec scenario in `specs/dotfiles-management/spec.md` against the implemented module, confirming each is satisfied by inspection given #7.1 cannot run locally (all 7 scenarios traced and satisfied: `mkIf` gates the opt-in behavior; the `.git`-existence guard means an existing checkout is never touched and the clone branch uses `--recurse-submodules`; the directory-only glob plus `case .*) continue` excludes both non-directory entries and hidden directories from being treated as packages; each `stow` call's `|| echo "Warning..."` keeps one conflict from aborting the loop under `set -e`) + +--- + +**Verification note:** as with the two prior changes, Nix is not installed on this machine, so task 7.1 (`nix flake check`) could not be executed and remains the outstanding acceptance gate for all three changes now. `shellcheck` was unavailable locally in the prior change too, but this change's activation script logic is plain POSIX-ish shell embedded in a Nix string (not a standalone script file), so there was no separate file to syntax-check with `bash -n` either — review here was manual/by-inspection only. -- cgit v1.3