11import { spawn } from "node:child_process" ;
22import { copyFile , mkdtemp , readFile , rm , stat } from "node:fs/promises" ;
3- import { tmpdir } from "node:os" ;
43import path from "node:path" ;
54import type {
65 GitHandoffCheckpoint ,
@@ -26,6 +25,7 @@ export interface GitHandoffArtifactFile {
2625
2726export interface GitHandoffCaptureResult {
2827 checkpoint : GitHandoffCheckpoint ;
28+ artifactDirectory : string ;
2929 headPack ?: GitHandoffArtifactFile ;
3030 indexFile : GitHandoffArtifactFile ;
3131 totalBytes : number ;
@@ -92,7 +92,7 @@ export class GitHandoffTracker {
9292
9393 const checkpoint = result . data ;
9494 const git = createGitClient ( this . repositoryPath ) ;
95- const tempDir = await this . createTempDir ( checkpoint . checkpointId ) ;
95+ const tempDir = await this . createTempDir ( git , checkpoint . checkpointId ) ;
9696 const checkpointRef = `${ CHECKPOINT_REF_PREFIX } ${ checkpoint . checkpointId } ` ;
9797
9898 try {
@@ -137,10 +137,14 @@ export class GitHandoffTracker {
137137 upstreamMergeRef : tracking . upstreamMergeRef ,
138138 remoteUrl : tracking . remoteUrl ,
139139 } ,
140+ artifactDirectory : tempDir ,
140141 headPack,
141142 indexFile,
142143 totalBytes : ( headPack ?. rawBytes ?? 0 ) + indexFile . rawBytes ,
143144 } ;
145+ } catch ( error ) {
146+ await rm ( tempDir , { recursive : true , force : true } ) . catch ( ( ) => { } ) ;
147+ throw error ;
144148 } finally {
145149 await deleteCheckpoint ( git , checkpoint . checkpointId ) . catch ( ( ) => { } ) ;
146150 }
@@ -544,8 +548,27 @@ export class GitHandoffTracker {
544548 return exitCode === 0 ;
545549 }
546550
547- private async createTempDir ( checkpointId : string ) : Promise < string > {
548- return mkdtemp ( joinTempPrefix ( checkpointId ) ) ;
551+ private async createTempDir (
552+ git : GitClient ,
553+ checkpointId : string ,
554+ ) : Promise < string > {
555+ // Git stages packs in the object store, so the destination must share its filesystem.
556+ const gitCommonDir = await this . resolveGitCommonDir ( git ) ;
557+ return mkdtemp (
558+ path . join ( gitCommonDir , `posthog-code-handoff-${ checkpointId } -` ) ,
559+ ) ;
560+ }
561+
562+ private async resolveGitCommonDir ( git : GitClient ) : Promise < string > {
563+ const raw = await git . raw ( [
564+ "rev-parse" ,
565+ "--path-format=absolute" ,
566+ "--git-common-dir" ,
567+ ] ) ;
568+ const resolved = raw . trim ( ) || ".git" ;
569+ return path . isAbsolute ( resolved )
570+ ? resolved
571+ : path . resolve ( this . repositoryPath , resolved ) ;
549572 }
550573
551574 private async getGitPath ( git : GitClient , gitPath : string ) : Promise < string > {
@@ -669,10 +692,6 @@ export class GitHandoffTracker {
669692 }
670693}
671694
672- function joinTempPrefix ( checkpointId : string ) : string {
673- return path . join ( tmpdir ( ) , `posthog-code-handoff-${ checkpointId } -` ) ;
674- }
675-
676695export async function readHandoffLocalGitState (
677696 repositoryPath : string ,
678697) : Promise < HandoffLocalGitState > {
0 commit comments