diff --git a/internal/cli/doctor.go b/internal/cli/doctor.go index 698e9ae..3fe0759 100644 --- a/internal/cli/doctor.go +++ b/internal/cli/doctor.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/openbootdotdev/openboot/internal/brew" + "github.com/openbootdotdev/openboot/internal/system" "github.com/openbootdotdev/openboot/internal/ui" "github.com/spf13/cobra" ) @@ -143,10 +144,10 @@ func checkGit() []checkResult { status: "ok", }) - name, _ := exec.Command("git", "config", "--global", "user.name").Output() - email, _ := exec.Command("git", "config", "--global", "user.email").Output() + name := system.GetGitConfig("user.name") + email := system.GetGitConfig("user.email") - if len(strings.TrimSpace(string(name))) == 0 || len(strings.TrimSpace(string(email))) == 0 { + if name == "" || email == "" { results = append(results, checkResult{ name: "Git identity", status: "warn", diff --git a/internal/diff/compare.go b/internal/diff/compare.go index 57c292f..c7f414c 100644 --- a/internal/diff/compare.go +++ b/internal/diff/compare.go @@ -171,6 +171,12 @@ func diffDotfiles(systemURL, referenceURL string) *DotfilesDiff { dd.RepoChanged = &ValueChange{System: systemURL, Reference: referenceURL} } + // Only check local dotfiles repo state if dotfiles are actually configured + // If both URLs are empty, there's no dotfiles setup to check + if sysNorm == "" && refNorm == "" { + return dd + } + // Check local dotfiles repo for dirty state home, err := os.UserHomeDir() if err != nil { diff --git a/internal/system/system.go b/internal/system/system.go index f22be6e..c945ee9 100644 --- a/internal/system/system.go +++ b/internal/system/system.go @@ -70,11 +70,18 @@ func InstallHomebrew() error { } func GetGitConfig(key string) string { + // Try global first (most common) output, err := RunCommandSilent("git", "config", "--global", key) - if err != nil { - return "" + if err == nil && output != "" { + return output + } + // Fall back to system config only (skip local to avoid repo-specific values) + output, err = RunCommandSilent("git", "config", "--system", key) + if err == nil { + return output } - return output + + return "" } func GetExistingGitConfig() (name, email string) { diff --git a/internal/system/system_test.go b/internal/system/system_test.go index 84ca188..423e640 100644 --- a/internal/system/system_test.go +++ b/internal/system/system_test.go @@ -302,3 +302,28 @@ func TestRunCommandSilent_MultilineOutput(t *testing.T) { assert.Contains(t, output, "line2") assert.Contains(t, output, "line3") } + +// TestGetGitConfig_FallsBackToSystemScope verifies that GetGitConfig falls back +// to --system scope (not local) when --global has no value. This ensures that +// running openboot inside a repo with local git config does not skip the global +// git config wizard. +// Regression test for: git config detection issue +func TestGetGitConfig_FallsBackToSystemScope(t *testing.T) { + tmpDir := t.TempDir() + t.Setenv("HOME", tmpDir) + t.Setenv("XDG_CONFIG_HOME", tmpDir+"/nonexistent") + + // Create a git repo with a local config value + cmd := exec.Command("git", "init", tmpDir) + if err := cmd.Run(); err != nil { + t.Skip("git not installed, skipping") + } + + cmd = exec.Command("git", "-C", tmpDir, "config", "user.localonly", "local-value") + require.NoError(t, cmd.Run()) + + // GetGitConfig should NOT find the local-only value because the fallback + // is --system, not bare git config. + value := GetGitConfig("user.localonly") + assert.Equal(t, "", value, "GetGitConfig should not fall back to local config; only global and system are checked") +}