Feature: #91 — Windows support audit
Fixed in #682 (commit 9ad98fa1). Filed for the record, because the finding outlives the fix
and the failure mode is not one you would predict from reading the call site.
What happened
The first CI run that included windows-11-arm failed both of its legs. Four tests, one cause:
git [init --quiet --initial-branch=main]: exit status 128
fatal: unable to access 'NUL': Invalid argument
TestRepo_Add_ClonesURL_DefaultHome
TestRepo_Add_ClonesURL_PositionalDestination
TestWritDeployScenario_Harness
TestWritDeployScenario_Deploy
Two test helpers isolated git from the developer's configuration like this:
cmd.Env = append(os.Environ(), "GIT_CONFIG_GLOBAL="+os.DevNull, "GIT_CONFIG_SYSTEM="+os.DevNull)
os.DevNull is "NUL" on Windows. The git build on the windows-11-arm runner image refuses to
open it as a config path. The identical command succeeds on windows-latest, so this is a
property of that image's git, not of the architecture — and it is why the defect stayed invisible
until windows/arm64 joined the matrix.
The distinction worth remembering
os.DevNull is correct as a write target on Windows. devlore-test uses it that way in ~20
places for discard destinations, and cmd/devlore-test/devloretest/commands.go already says so:
"The discard destination needs no sentinel: os.DevNull already names the platform's own." Those
uses are fine and were deliberately left alone.
The failure is narrower: git opening the null device as a config file to read. At the call
site the two uses look identical, which is what makes this worth writing down.
The fix
An empty regular file. It is what the helpers actually wanted — a config git can open and find
nothing in — and it carries none of the device semantics that vary by platform and by git build.
func isolatedGitEnv(t *testing.T) []string {
t.Helper()
empty := filepath.Join(t.TempDir(), "gitconfig")
if err := os.WriteFile(empty, nil, 0o600); err != nil {
t.Fatalf("write empty git config: %v", err)
}
return append(os.Environ(), "GIT_CONFIG_GLOBAL="+empty, "GIT_CONFIG_SYSTEM="+empty)
}
Rejected alternatives:
- A nonexistent path works today, but depends on how each git version treats an unreadable
config rather than on documented behavior.
git -c key=value overrides individual keys without preventing the global config from being
read at all — whack-a-mole against core.hooksPath and anything else a developer has set.
- Setting
HOME covers global config but not GIT_CONFIG_SYSTEM.
Audit
Both affected sites are fixed; there is no third. Across the module:
GIT_CONFIG_GLOBAL/GIT_CONFIG_SYSTEM are set in exactly those two helpers.
- The one production consumer,
pkg/gitignore/tracker.go:261, reads GIT_CONFIG_GLOBAL and
continues past a path it cannot open — so a user whose environment carries
GIT_CONFIG_GLOBAL=NUL degrades quietly rather than failing.
Why it is worth a record
The guidance — never hand git a device path as a config file; hand it an empty file — lives only
in the doc comments of the two helpers. Someone reaching for os.DevNull in a different package,
for a different tool, will not be reading those.
Related: #681 (added the windows/arm64 leg that surfaced this), #671 (running the execution matrix
on real machines — this is that class of discovery), #599 (Windows/ARM64 scenario work).
Feature: #91 — Windows support audit
Fixed in #682 (commit
9ad98fa1). Filed for the record, because the finding outlives the fixand the failure mode is not one you would predict from reading the call site.
What happened
The first CI run that included
windows-11-armfailed both of its legs. Four tests, one cause:TestRepo_Add_ClonesURL_DefaultHomeTestRepo_Add_ClonesURL_PositionalDestinationTestWritDeployScenario_HarnessTestWritDeployScenario_DeployTwo test helpers isolated git from the developer's configuration like this:
os.DevNullis"NUL"on Windows. The git build on thewindows-11-armrunner image refuses toopen it as a config path. The identical command succeeds on
windows-latest, so this is aproperty of that image's git, not of the architecture — and it is why the defect stayed invisible
until windows/arm64 joined the matrix.
The distinction worth remembering
os.DevNullis correct as a write target on Windows.devlore-testuses it that way in ~20places for discard destinations, and
cmd/devlore-test/devloretest/commands.goalready says so:"The discard destination needs no sentinel: os.DevNull already names the platform's own." Those
uses are fine and were deliberately left alone.
The failure is narrower: git opening the null device as a config file to read. At the call
site the two uses look identical, which is what makes this worth writing down.
The fix
An empty regular file. It is what the helpers actually wanted — a config git can open and find
nothing in — and it carries none of the device semantics that vary by platform and by git build.
Rejected alternatives:
config rather than on documented behavior.
git -c key=valueoverrides individual keys without preventing the global config from beingread at all — whack-a-mole against
core.hooksPathand anything else a developer has set.HOMEcovers global config but notGIT_CONFIG_SYSTEM.Audit
Both affected sites are fixed; there is no third. Across the module:
GIT_CONFIG_GLOBAL/GIT_CONFIG_SYSTEMare set in exactly those two helpers.pkg/gitignore/tracker.go:261, readsGIT_CONFIG_GLOBALandcontinues past a path it cannot open — so a user whose environment carriesGIT_CONFIG_GLOBAL=NULdegrades quietly rather than failing.Why it is worth a record
The guidance — never hand git a device path as a config file; hand it an empty file — lives only
in the doc comments of the two helpers. Someone reaching for
os.DevNullin a different package,for a different tool, will not be reading those.
Related: #681 (added the windows/arm64 leg that surfaced this), #671 (running the execution matrix
on real machines — this is that class of discovery), #599 (Windows/ARM64 scenario work).