test(git): isolate worktree-shared-directories git config portably (#16582)

`os.devNull` is `\\.\nul` on win32. Git normalizes it to `//./nul` and rejects
it as a config path, so every `git` call in this suite threw in `beforeEach`
and 15 of 19 tests failed on Windows. POSIX resolves the same constant to
/dev/null, which Git accepts, so CI never saw it.

Point GIT_CONFIG_GLOBAL at a real empty file in a private mkdtemp directory,
matching how skill-git-tree-identity and skill-windows-workspace already
isolate, and use GIT_CONFIG_NOSYSTEM instead of GIT_CONFIG_SYSTEM.

Set both on `process.env` rather than only on the suite's `git()` helper.
`resolveWorktreeSharedDirectories` runs its own `git check-ignore` through the
production runner, and `GitRuntimeOptions` carries no env, so the runner
inherits `process.env`. The per-call override never reached the code under
test: a host `core.excludesFile` could make a fixture that is not gitignored
come back as ignored.

Fixes #15409
This commit is contained in:
Neil
2026-08-26 04:36:28 -07:00
committed by GitHub
parent 19e9ec695b
commit 44a3ba59e6
@@ -1,8 +1,8 @@
import { execFileSync } from 'node:child_process'
import { lstatSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
import { devNull, tmpdir } from 'node:os'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
import {
clearConfiguredWorktreeSharedDirectoriesCacheForTests,
getConfiguredWorktreeSharedDirectories,
@@ -16,16 +16,50 @@ import {
import { assertWorktreeCleanForRemoval } from './worktree'
import { getStatus } from './status'
// Why an empty file and not `os.devNull`: that constant is `\\.\nul` on win32, which
// Git normalizes to `//./nul` and rejects — `fatal: unable to access '//./nul': Invalid
// argument`. Every git call in this file then threw. POSIX resolves it to /dev/null,
// which Git accepts, so CI never saw it. An empty file works on every platform and
// matches how skill-git-tree-identity and skill-windows-workspace already isolate.
//
// Why process.env and not just this helper's env: resolveWorktreeSharedDirectories
// runs its own `git check-ignore` through the production runner, which inherits
// process.env. Overriding only the setup helper left the code under test reading the
// host's real config, so a developer with core.excludesFile set saw a fixture that is
// not gitignored come back as ignored.
let gitConfigRoot: string
let previousGitConfigGlobal: string | undefined
let previousGitConfigNosystem: string | undefined
beforeAll(() => {
gitConfigRoot = mkdtempSync(join(tmpdir(), 'orca-shared-dirs-gitconfig-'))
const emptyGlobalGitConfig = join(gitConfigRoot, 'global.gitconfig')
writeFileSync(emptyGlobalGitConfig, '')
previousGitConfigGlobal = process.env.GIT_CONFIG_GLOBAL
previousGitConfigNosystem = process.env.GIT_CONFIG_NOSYSTEM
process.env.GIT_CONFIG_GLOBAL = emptyGlobalGitConfig
process.env.GIT_CONFIG_NOSYSTEM = '1'
})
afterAll(() => {
restoreGitEnv('GIT_CONFIG_GLOBAL', previousGitConfigGlobal)
restoreGitEnv('GIT_CONFIG_NOSYSTEM', previousGitConfigNosystem)
rmSync(gitConfigRoot, { recursive: true, force: true })
})
function restoreGitEnv(
name: 'GIT_CONFIG_GLOBAL' | 'GIT_CONFIG_NOSYSTEM',
value: string | undefined
): void {
if (value === undefined) {
delete process.env[name]
return
}
process.env[name] = value
}
const git = (args: string[], cwd: string): void => {
execFileSync('git', args, {
cwd,
stdio: 'ignore',
env: {
...process.env,
GIT_CONFIG_GLOBAL: devNull,
GIT_CONFIG_SYSTEM: devNull
}
})
execFileSync('git', args, { cwd, stdio: 'ignore' })
}
describe('resolveWorktreeSharedDirectories', () => {