Skip to content

feat: directory-based profile assignment via includeIf#17

Merged
aanogueira merged 28 commits intomainfrom
andre.nogueira/dir-based-profiles
May 5, 2026
Merged

feat: directory-based profile assignment via includeIf#17
aanogueira merged 28 commits intomainfrom
andre.nogueira/dir-based-profiles

Conversation

@aanogueira
Copy link
Copy Markdown
Contributor

@aanogueira aanogueira commented May 5, 2026

Summary

Adds directory-based profile assignment using git's native includeIf "gitdir:..." mechanism, so the right git identity applies automatically based on where you are in the filesystem — no need to remember to switch.

  • New git-context dir add/remove/list subcommands
  • Per-profile gitconfig files at ~/.config/git-context/profiles/<name>.gitconfig
  • ~/.gitconfig becomes a thin manifest: [include] for the default + [includeIf] per assigned directory
  • Every mutating command (switch, add, remove, dir add/remove) regenerates the manifest from config.yaml (single source of truth)
  • current now also reports the effective profile in $PWD, surfacing when an includeIf is overriding the default

Spec: docs/superpowers/specs/2026-05-04-directory-based-profile-assignment-design.md
Plan: docs/superpowers/plans/2026-05-04-directory-based-profile-assignment.md

Test Plan

  • Unit tests across internal/config, internal/git, cmd (175 passing)
  • End-to-end integration test (cmd/integration_test.go) drives full lifecycle through real git config --show-origin user.email resolution inside vs outside an assigned repo
  • Smoke: git-context init && git-context add work && git-context switch work && git-context dir add ~/projects/personal personal && git-context current (manual)
  • Verify backup behavior: first switch after upgrade preserves the original ~/.gitconfig to ~/.gitconfig.bak; subsequent switches don't clobber it (header-marker guard in `BackupConfig`)
  • Verify removing the last assigned directory cleans up the manifest (removeManagedManifest helper deletes only files we own)

aanogueira and others added 27 commits May 4, 2026 14:13
Captures the includeIf-based approach: per-profile gitconfig files
materialized to ~/.config/git-context/profiles/, with ~/.gitconfig
becoming a thin manifest of [include] + [includeIf gitdir:...] blocks
that git-context regenerates on every mutating command.

Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
17 TDD-structured tasks covering config schema changes, atomic file
writers, the new `dir` subcommand, and updates to existing commands.
End-to-end test verifies git resolves the right user.email inside and
outside assigned directories.

Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
…ure path

Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
Signed-off-by: Andre Nogueira <andre.nogueira@mollie.com>
The previous determineCurrent() probed git config --global user.name
to recover Current on each LoadConfig. After the manifest refactor in
Task 9, --global doesn't follow [include] directives, so Current would
always read as empty and any subsequent Regenerate would drop the
default profile from the manifest. Persisting Current in config.yaml
removes the side channel and makes the manifest faithfully reflect
the configured default.

Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 5, 2026

Git config rejects backslashes in unquoted 'path =' values, causing
WriteRootConfig output to fail on Windows CI. Pipe defaultProfilePath,
gitdir keys, and includeIf paths through a small toGitPath helper that
unconditionally replaces backslashes with forward slashes — filepath.ToSlash
is insufficient because it only swaps the OS-specific separator and is a
no-op on POSIX, which would leave the regression test (using literal
Windows-shaped paths) failing on macOS/Linux.

Signed-off-by: Andre Nogueira <aanogueira@protonmail.com>
@aanogueira aanogueira merged commit 4f99292 into main May 5, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants