Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
edge case in detecting the global config
  • Loading branch information
MichaelMure committed Oct 10, 2026
commit 1dc496c41b9e266e9e167cba1b2eee254b0b3278
7 changes: 5 additions & 2 deletions env.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ type Env struct {
// GlobalConfig lists the global configuration files, read in order.
// Writes go to the last one that exists, or to the last one if none
// exists: for git's [XDG file, ~/.gitconfig] this picks ~/.gitconfig
// unless only the XDG file exists.
// unless only the XDG file exists. A symbolic link exists if its target
// does.
GlobalConfig []string

// Command holds the values given on the command line (git -c,
Expand Down Expand Up @@ -379,7 +380,9 @@ func (e Env) writeTarget(s Scope) (string, Scope, error) {
return "", 0, ErrNoScope
}
for _, v := range slices.Backward(e.GlobalConfig) {
if _, err := os.Lstat(v); err == nil {
// A link to nothing does not exist, as for git: the write
// goes to the other file, not to the link's target.
if _, err := os.Stat(v); err == nil {
return v, s, nil
}
}
Expand Down
26 changes: 26 additions & 0 deletions env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,32 @@ func TestEnvWritePath(t *testing.T) {
}
}

func TestEnvWritePathDanglingLink(t *testing.T) {
// A ~/.gitconfig that links to nothing does not exist: with an XDG
// file, git writes there; without, through the link (git 2.56).
dir := tempDir(t)
xdg := filepath.Join(dir, "xdg")
home := filepath.Join(dir, "home")
symlink(t, filepath.Join(dir, "dotfiles", "gitconfig"), home)
env := gitconfig.Env{GlobalConfig: []string{xdg, home}}

got, err := env.WritePath(gitconfig.ScopeGlobal)
require.NoError(t, err)
assert.Equal(t, home, got)

writeFile(t, xdg, "")
got, err = env.WritePath(gitconfig.ScopeGlobal)
require.NoError(t, err)
assert.Equal(t, xdg, got)

require.NoError(t, env.UpdateScope(gitconfig.ScopeGlobal, func(f *gitconfig.File) error {
return f.Set("a.k", "v")
}))
_, err = os.Stat(filepath.Join(dir, "dotfiles"))
assert.ErrorIs(t, err, fs.ErrNotExist)
assert.Equal(t, "[a]\n\tk = v\n", readFile(t, xdg))
}

// unsetenv unsets an environment variable for the duration of the test.
func unsetenv(t *testing.T, key string) {
t.Setenv(key, "")
Expand Down