11import { afterEach , beforeEach , expect , test } from "bun:test" ;
2- import { chmod , mkdir , readFile , rm , writeFile } from "node:fs/promises" ;
2+ import { mkdir , readFile , rm , writeFile } from "node:fs/promises" ;
33import { realpathSync } from "node:fs" ;
4- import { delimiter , join } from "node:path" ;
4+ import { join } from "node:path" ;
55import { tmpdir } from "node:os" ;
66import { execFileSync } from "node:child_process" ;
77
@@ -27,10 +27,6 @@ afterEach(async () => {
2727 await rm ( root , { recursive : true , force : true } ) ;
2828} ) ;
2929
30- function shQuote ( value : string ) : string {
31- return `'${ value . replaceAll ( "'" , "'\\''" ) } '` ;
32- }
33-
3430async function commitReadme ( dir : string ) : Promise < void > {
3531 await writeFile ( join ( dir , "README" ) , "x" ) ;
3632 execFileSync ( "git" , [ "add" , "README" ] , { cwd : dir , stdio : "ignore" } ) ;
@@ -59,41 +55,26 @@ test("projectRootFor spawns git rev-parse once for the same cwd", async () => {
5955 initTemporaryGitRepo ( root ) ;
6056 await commitReadme ( root ) ;
6157
62- const countFile = join ( root , "rev-parse-spawns" ) ;
63- await writeFile ( countFile , "0\n" ) ;
64- const realGit = execFileSync ( "/usr/bin/which" , [ "git" ] , {
65- encoding : "utf8" ,
66- } ) . trim ( ) ;
67- const bin = join ( root , "git-bin" ) ;
68- await mkdir ( bin ) ;
69- const wrapper = join ( bin , "git" ) ;
70- const resolved = realpathSync ( root ) ;
71- await writeFile (
72- wrapper ,
73- `#!/bin/sh
74- if [ "$1" = "rev-parse" ] && [ "$(pwd)" = ${ shQuote ( resolved ) } ]; then
75- n=$(cat ${ shQuote ( countFile ) } )
76- echo $((n + 1)) > ${ shQuote ( countFile ) }
77- fi
78- exec ${ shQuote ( realGit ) } "$@"
79- ` ,
80- ) ;
81- await chmod ( wrapper , 0o755 ) ;
82-
83- const previousPath = process . env . PATH ;
84- process . env . PATH = `${ bin } ${ delimiter } ${ previousPath ?? "" } ` ;
58+ const traceFile = join ( root , "git-trace2-events" ) ;
59+ const previousTrace = process . env . GIT_TRACE2_EVENT ;
60+ process . env . GIT_TRACE2_EVENT = traceFile ;
8561 try {
8662 const first = projectRootFor ( root ) ;
8763 const second = projectRootFor ( root ) ;
8864 expect ( second ) . toBe ( first ) ;
8965 expect ( first ) . toBe ( realpathSync ( root ) ) ;
90- const spawns = Number ( ( await readFile ( countFile , "utf8" ) ) . trim ( ) ) ;
66+ const spawns = ( await readFile ( traceFile , "utf8" ) )
67+ . split ( "\n" )
68+ . filter (
69+ ( line ) =>
70+ line . includes ( '"event":"start"' ) && line . includes ( "rev-parse" ) ,
71+ ) . length ;
9172 expect ( spawns ) . toBe ( 1 ) ;
9273 } finally {
93- if ( previousPath === undefined ) {
94- delete process . env . PATH ;
74+ if ( previousTrace === undefined ) {
75+ delete process . env . GIT_TRACE2_EVENT ;
9576 } else {
96- process . env . PATH = previousPath ;
77+ process . env . GIT_TRACE2_EVENT = previousTrace ;
9778 }
9879 }
9980} ) ;
@@ -116,18 +97,19 @@ test("projectRootFor retries a nested dir after git was unavailable", async () =
11697 const nested = join ( root , "nested" ) ;
11798 await mkdir ( nested ) ;
11899 const parent = realpathSync ( root ) ;
119- const emptyBin = join ( root , "empty-bin" ) ;
120- await mkdir ( emptyBin ) ;
100+ // Bun resolves execFileSync("git") from the startup PATH, so emptying PATH
101+ // does not hide git. A missing GIT_DIR is forwarded and makes rev-parse fail.
102+ const missingGitDir = join ( root , "missing-git-dir" ) ;
121103
122- const previousPath = process . env . PATH ;
123- process . env . PATH = emptyBin ;
104+ const previousGitDir = process . env . GIT_DIR ;
105+ process . env . GIT_DIR = missingGitDir ;
124106 try {
125107 expect ( projectRootFor ( nested ) ) . toBe ( realpathSync ( nested ) ) ;
126108 } finally {
127- if ( previousPath === undefined ) {
128- delete process . env . PATH ;
109+ if ( previousGitDir === undefined ) {
110+ delete process . env . GIT_DIR ;
129111 } else {
130- process . env . PATH = previousPath ;
112+ process . env . GIT_DIR = previousGitDir ;
131113 }
132114 }
133115 expect ( projectRootFor ( nested ) ) . toBe ( parent ) ;
0 commit comments