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 {
@@ -139,10 +139,14 @@ export class GitHandoffTracker {
139139 upstreamMergeRef : tracking . upstreamMergeRef ,
140140 remoteUrl : tracking . remoteUrl ,
141141 } ,
142+ artifactDirectory : tempDir ,
142143 headPack,
143144 indexFile,
144145 totalBytes : ( headPack ?. rawBytes ?? 0 ) + indexFile . rawBytes ,
145146 } ;
147+ } catch ( error ) {
148+ await rm ( tempDir , { recursive : true , force : true } ) . catch ( ( ) => { } ) ;
149+ throw error ;
146150 } finally {
147151 await deleteCheckpoint ( git , checkpoint . checkpointId ) . catch ( ( ) => { } ) ;
148152 }
@@ -590,8 +594,27 @@ export class GitHandoffTracker {
590594 return exitCode === 0 ;
591595 }
592596
593- private async createTempDir ( checkpointId : string ) : Promise < string > {
594- return mkdtemp ( joinTempPrefix ( checkpointId ) ) ;
597+ private async createTempDir (
598+ git : GitClient ,
599+ checkpointId : string ,
600+ ) : Promise < string > {
601+ // Git stages packs in the object store, so the destination must share its filesystem.
602+ const gitCommonDir = await this . resolveGitCommonDir ( git ) ;
603+ return mkdtemp (
604+ path . join ( gitCommonDir , `posthog-code-handoff-${ checkpointId } -` ) ,
605+ ) ;
606+ }
607+
608+ private async resolveGitCommonDir ( git : GitClient ) : Promise < string > {
609+ const raw = await git . raw ( [
610+ "rev-parse" ,
611+ "--path-format=absolute" ,
612+ "--git-common-dir" ,
613+ ] ) ;
614+ const resolved = raw . trim ( ) || ".git" ;
615+ return path . isAbsolute ( resolved )
616+ ? resolved
617+ : path . resolve ( this . repositoryPath , resolved ) ;
595618 }
596619
597620 private async getGitPath ( git : GitClient , gitPath : string ) : Promise < string > {
@@ -715,10 +738,6 @@ export class GitHandoffTracker {
715738 }
716739}
717740
718- function joinTempPrefix ( checkpointId : string ) : string {
719- return path . join ( tmpdir ( ) , `posthog-code-handoff-${ checkpointId } -` ) ;
720- }
721-
722741export async function readHandoffLocalGitState (
723742 repositoryPath : string ,
724743) : Promise < HandoffLocalGitState > {
0 commit comments