test: isolate the two raw git spawns that read the developer's gitconfig - #3863
test: isolate the two raw git spawns that read the developer's gitconfig#3863worktrunk-bot wants to merge 2 commits into
Conversation
test_git_rejects_ansi_escape_in_branch_names spawned a bare
Command::new("bash") whose git inherited the developer's ~/.gitconfig and
locale, against the invariant tests/CLAUDE.md states for every git the
suite runs. The missing LC_ALL/LANG=C pin is what the test's own stderr
assertion rests on — git ships translated messages, so the check for
"not a valid branch name" fails on a non-English machine.
Apply repo.configure_git_cmd to the shell, as the sh child in the same
file already does.
worktrunk-bot
left a comment
There was a problem hiding this comment.
The change itself is right: configure_git_cmd on the shell is the only place the isolation can go, since the git bash spawns inherits it, and the locale pin is genuinely load-bearing — the German catalog renders that msgid as ist kein gültiger Branchname, which matches neither disjunct in the assertion, so the fallback || stderr.contains("invalid") wouldn't have saved it either.
One gap the sweep in the description missed, because it was scoped to shell children rather than to git spawns: tests/helpers/wt-perf/tests/cli.rs spawns a bare Command::new("git") directly. In setup_layers_prune_state_onto_a_canonical_base, the fixture inspection .args(["-C", repo.to_str().unwrap(), "branch", "--format=%(refname:short)"]) runs with an inherited environment and no floor, so it reads the developer's ~/.gitconfig. wt-perf is in default-members, and its own Cargo.toml header says a workspace cargo test builds and runs these in-package CLI tests — so this is inside the guarantee tests/CLAUDE.md states, and it's the same one-line fix (worktrunk::testing::configure_git_cmd is already imported by wt-perf/src/lib.rs, and the crate's own private git_command() helper documents the same rule for the library side).
Practical blast radius there is small — --format=%(refname:short) pins the output and the assertion uses .any(), so host config would have to do something fairly exotic to break it — which is why I'd rather ask than fold it in: happy to push it onto this branch (retitling to cover both), or leave this PR atomic and take it separately.
What I verified
configure_git_cmdappliesscrub_git_path_vars,HERMETIC_TEST_GIT_ENV, andgit_test_env(src/testing/mod.rs); the scrub is a strict improvement here since the test relies on cwd discovery fromrepo.root_path().- Nothing in the applied set perturbs this test: no commit is made (identity/date are inert), no network is touched, and
$'\x1b'is bash ANSI-C quoting, which is locale-independent underLC_ALL=C. - Swept the whole tree for raw
Command::newspawns of a shell or ofgit. Everything else is either isolated already (bare_repository.rs'sapply_wt_envcallsconfigure_git_cmd;wt-perf/src/lib.rsroutes throughgit_command()) or drives something other than git (config_show.rs,completion.rs,shell_wrapper.rs,shell_powershell.rs,nushell_default_config_dir.rs,configure_shell.rs).wt-perf/src/main.rs'srev-parse --git-common-diris binary code run against the developer's real repo, so leaving it uninsulated is correct. test (linux),code-coverage,codecov/patchandcodecov/projectare green onbc9ff50;test (macos)andtest (windows)were still running when I wrote this.
Nit on the description, not the code: the sh child it points at is ~300 lines up, not twelve.
The bare `Command::new("git")` in `setup_layers_prune_state_onto_a_canonical_base`
inherits the developer's environment and reads their `~/.gitconfig`. wt-perf is in
`default-members` and these in-package CLI tests run under a workspace `cargo test`,
so they sit inside the guarantee `tests/CLAUDE.md` states.
|
Folded it in as Took the fold-in over a separate PR because the two hunks aren't independent changes that happen to sit near each other — they're the same invariant (
Also fixed the description's "twelve lines up" — the |
Found during the nightly survey. Two raw
Command::newspawns in the test tree drivegitwith an inherited environment, so they read the developer's~/.gitconfig— breaking the invarianttests/CLAUDE.mdstates absolutely: "Nogitthe suite runs reads the developer's~/.gitconfig, whatever the test drives it through and wherever the fixture lives". Both take the same one-line fix,configure_git_cmdon the spawned command.tests/integration_tests/security.rs—test_git_rejects_ansi_escape_in_branch_namesspawnsbashto rungit branch. Thegitinherits the shell's environment, so the isolation goes on the shell, exactly astest_git_rejects_nul_in_commit_messagesalready does for itsshchild in the same file. This one also drops theLC_ALL/LANG=Cpin that the test's own stderr assertion depends on.tests/helpers/wt-perf/tests/cli.rs—setup_layers_prune_state_onto_a_canonical_baseinspects the built fixture with a baregit branch --format=….wt-perfis indefault-membersand its in-package CLI tests run under a workspacecargo test, so they're inside the same guarantee. The crate's owngit_command()helper documents this rule for the library side but is private to the lib, so the test appliesworktrunk::testing::configure_git_cmddirectly.Why the locale matters, and what I verified
The security test's assertion is
stderr.contains("not a valid branch name") || stderr.contains("invalid"). Git ships translated messages, so on a contributor's machine with a non-English locale that reads a translated rendering and the test fails with "Expected git to complain about invalid branch name". The German catalog renders that msgid asist kein gültiger Branchname, which matches neither disjunct — the|| stderr.contains("invalid")fallback wouldn't have saved it either.Verified on this runner:
'%s' is not a valid branch nameis a live msgid in the shipped German catalog at/usr/share/locale/de/LC_MESSAGES/git.mo(offset 140661), so the string is genuinely subject to translation rather than hardcoded English.git_test_envpinsLC_ALL=CandLANG=C(src/testing/mod.rs), andconfigure_git_cmdapplies both that and theHERMETIC_TEST_GIT_ENVconfig-deny floor.cargo test --test integration security::— all 10 tests pass with the change.cargo test -p wt-perf --test cli— all 10 pass.Not verified end-to-end: the runner only has
C,C.utf8,POSIX, anden_US.utf8generated andlocale-genisn't available unprivileged, so I could not actually drive the test under a translated locale and watch it fail. The failing path is inferred from the catalog evidence above, not observed.The wt-perf site's practical blast radius is small —
--format=%(refname:short)pins the output and the assertion uses.any()— so host config would have to do something fairly exotic to break it. It's fixed because the invariant is stated without exceptions, not because a failure was observed.Swept the rest of the tree for raw
Command::newspawns of a shell or ofgit. Everything else is either isolated already (bare_repository.rs'sapply_wt_envcallsconfigure_git_cmd;wt-perf/src/lib.rsroutes throughgit_command()) or drives something other than git (config_show.rs,completion.rs,shell_wrapper.rs,shell_powershell.rs,nushell_default_config_dir.rs,configure_shell.rs).wt-perf/src/main.rs'srev-parse --git-common-diris binary code run against the developer's real repo, so leaving it uninsulated is correct.No regression test: the changes are to tests' own setup, and the only guard that would catch a recurrence is a source-scanning lint for raw git/shell spawns, which is brittle enough that I'd rather leave the gap noted here than build it. Happy to add one if you'd prefer.