11import { execFile } from "node:child_process" ;
22import { randomUUID } from "node:crypto" ;
3- import { mkdtemp , rm } from "node:fs/promises" ;
3+ import { access , mkdtemp , rm } from "node:fs/promises" ;
44import { tmpdir } from "node:os" ;
5- import { dirname , join } from "node:path" ;
5+ import { dirname , join , resolve } from "node:path" ;
66import { promisify } from "node:util" ;
77
88const exec = promisify ( execFile ) ;
@@ -75,21 +75,19 @@ export async function removeWorktree(worktreePath: string): Promise<void> {
7575}
7676
7777export async function getDiff ( worktreePath : string ) : Promise < string > {
78+ const absPath = resolve ( worktreePath ) ;
7879 try {
79- // Include both staged and unstaged changes relative to HEAD
80- // Exclude node_modules symlink (created by createWorktree for tool access)
81- await exec ( "git" , [ "add" , "-A" ] , { cwd : worktreePath } ) ;
82- // Unstage node_modules symlink if it got picked up (created by createWorktree)
83- await exec ( "git" , [ "reset" , "HEAD" , "--" , "node_modules" ] , { cwd : worktreePath } ) . catch (
84- ( ) => { } ,
85- ) ;
86- const { stdout } = await exec ( "git" , [ "diff" , "--cached" , "HEAD" ] , {
87- cwd : worktreePath ,
88- } ) ;
80+ // Verify worktree is still a git repo before running git commands
81+ await access ( join ( absPath , ".git" ) ) ;
82+ await exec ( "git" , [ "rev-parse" , "--git-dir" ] , { cwd : absPath } ) ;
83+
84+ await exec ( "git" , [ "add" , "-A" ] , { cwd : absPath } ) ;
85+ await exec ( "git" , [ "reset" , "HEAD" , "--" , "node_modules" ] , { cwd : absPath } ) . catch ( ( ) => { } ) ;
86+ const { stdout } = await exec ( "git" , [ "diff" , "--cached" , "HEAD" ] , { cwd : absPath } ) ;
8987 return stdout ;
9088 } catch ( err ) {
9189 console . warn (
92- `[thinktank] getDiff failed for worktree ${ worktreePath } : ${ err instanceof Error ? err . message : String ( err ) } ` ,
90+ `[thinktank] getDiff failed for ${ absPath } : ${ err instanceof Error ? err . message : String ( err ) } ` ,
9391 ) ;
9492 return "" ;
9593 }
@@ -98,14 +96,13 @@ export async function getDiff(worktreePath: string): Promise<string> {
9896export async function getDiffStats (
9997 worktreePath : string ,
10098) : Promise < { filesChanged : string [ ] ; linesAdded : number ; linesRemoved : number } > {
99+ const absPath = resolve ( worktreePath ) ;
101100 try {
102- await exec ( "git" , [ "add" , "-A" ] , { cwd : worktreePath } ) ;
103- // Unstage node_modules symlink if it got picked up (created by createWorktree)
104- await exec ( "git" , [ "reset" , "HEAD" , "--" , "node_modules" ] , { cwd : worktreePath } ) . catch (
105- ( ) => { } ,
106- ) ;
101+ await access ( join ( absPath , ".git" ) ) ;
102+ await exec ( "git" , [ "add" , "-A" ] , { cwd : absPath } ) ;
103+ await exec ( "git" , [ "reset" , "HEAD" , "--" , "node_modules" ] , { cwd : absPath } ) . catch ( ( ) => { } ) ;
107104 const { stdout } = await exec ( "git" , [ "diff" , "--cached" , "--stat" , "HEAD" ] , {
108- cwd : worktreePath ,
105+ cwd : absPath ,
109106 } ) ;
110107
111108 const filesChanged : string [ ] = [ ] ;
@@ -126,7 +123,7 @@ export async function getDiffStats(
126123 return { filesChanged, linesAdded, linesRemoved } ;
127124 } catch ( err ) {
128125 console . warn (
129- `[thinktank] getDiffStats failed for worktree ${ worktreePath } : ${ err instanceof Error ? err . message : String ( err ) } ` ,
126+ `[thinktank] getDiffStats failed for ${ absPath } : ${ err instanceof Error ? err . message : String ( err ) } ` ,
130127 ) ;
131128 return { filesChanged : [ ] , linesAdded : 0 , linesRemoved : 0 } ;
132129 }
0 commit comments