@@ -2875,6 +2875,116 @@ it.layer(layerTest)("GitVcsDriver core integration", (it) => {
28752875 } ) ,
28762876 ) ;
28772877
2878+ it . effect . each ( [
2879+ "object format" ,
2880+ "configuration" ,
2881+ "initialization" ,
2882+ "read target" ,
2883+ "resolve" ,
2884+ "promote ref" ,
2885+ "read promoted target" ,
2886+ "shared budget" ,
2887+ ] as const ) ( "bounds the complete status fetch when %s stalls" , ( stage ) =>
2888+ Effect . gen ( function * ( ) {
2889+ const cwd = yield * makeTmpDir ( ) ;
2890+ const remote = yield * makeTmpDir ( "git-vcs-driver-remote-" ) ;
2891+ const updater = yield * makeTmpDir ( "git-vcs-driver-updater-" ) ;
2892+ const { initialBranch } = yield * initRepoWithCommit ( cwd ) ;
2893+ const originalCommit = yield * git ( cwd , [ "rev-parse" , "HEAD" ] ) ;
2894+ yield * git ( remote , [ "init" , "--bare" ] ) ;
2895+ yield * git ( cwd , [ "remote" , "add" , "origin" , remote ] ) ;
2896+ yield * git ( cwd , [ "push" , "-u" , "origin" , initialBranch ] ) ;
2897+ yield * git ( updater , [ "clone" , "--branch" , initialBranch , remote , "." ] ) ;
2898+ yield * git ( updater , [ "config" , "user.email" , "[email protected] " ] ) ; 2899+ yield * git ( updater , [ "config" , "user.name" , "Test" ] ) ;
2900+ yield * writeTextFile ( updater , "remote.txt" , "remote update\n" ) ;
2901+ yield * git ( updater , [ "add" , "remote.txt" ] ) ;
2902+ yield * git ( updater , [ "commit" , "-m" , "remote update" ] ) ;
2903+ yield * git ( updater , [ "push" ] ) ;
2904+
2905+ const delegate = yield * ChildProcessSpawner . ChildProcessSpawner ;
2906+ const blocked = yield * Deferred . make < void > ( ) ;
2907+ const release = yield * Deferred . make < void > ( ) ;
2908+ const interrupted = yield * Deferred . make < void > ( ) ;
2909+ const preparationBlocked = yield * Deferred . make < void > ( ) ;
2910+ const releasePreparation = yield * Deferred . make < void > ( ) ;
2911+ let targetReads = 0 ;
2912+ let attempts = 0 ;
2913+ const spawner = ChildProcessSpawner . make ( ( command ) =>
2914+ Effect . gen ( function * ( ) {
2915+ if ( ChildProcess . isStandardCommand ( command ) ) {
2916+ const args = command . args ;
2917+ if ( stage === "shared budget" && args . includes ( "extensions.objectFormat" ) ) {
2918+ yield * Deferred . succeed ( preparationBlocked , undefined ) ;
2919+ yield * Deferred . await ( releasePreparation ) ;
2920+ }
2921+ const readsTarget =
2922+ args . includes ( "rev-parse" ) &&
2923+ args . at ( - 1 ) === `refs/remotes/origin/${ initialBranch } ` ;
2924+ if ( readsTarget ) targetReads += 1 ;
2925+ if ( stage === "read promoted target" && args . includes ( "update-ref" ) ) {
2926+ return ChildProcessSpawner . makeHandle ( {
2927+ ...makeSuccessfulHandle ( "" ) ,
2928+ exitCode : Effect . succeed ( ChildProcessSpawner . ExitCode ( 1 ) ) ,
2929+ } ) ;
2930+ }
2931+ const shouldBlock =
2932+ ( stage === "object format" && args . includes ( "extensions.objectFormat" ) ) ||
2933+ ( stage === "configuration" && args . includes ( "--show-scope" ) ) ||
2934+ ( stage === "initialization" && args [ 0 ] === "init" && args . includes ( "--bare" ) ) ||
2935+ ( stage === "read target" && readsTarget && targetReads === 1 ) ||
2936+ ( ( stage === "resolve" || stage === "shared budget" ) &&
2937+ args . includes ( "rev-parse" ) &&
2938+ command . options . env ?. GIT_OBJECT_DIRECTORY !== undefined ) ||
2939+ ( stage === "promote ref" && args . includes ( "update-ref" ) ) ||
2940+ ( stage === "read promoted target" && readsTarget && targetReads === 2 ) ;
2941+ if ( shouldBlock ) {
2942+ attempts += 1 ;
2943+ yield * Deferred . succeed ( blocked , undefined ) ;
2944+ yield * Deferred . await ( release ) . pipe (
2945+ Effect . onInterrupt ( ( ) => Deferred . succeed ( interrupted , undefined ) ) ,
2946+ ) ;
2947+ }
2948+ }
2949+ return yield * delegate . spawn ( command ) ;
2950+ } ) ,
2951+ ) ;
2952+ const driver = yield * makeGitVcsDriverCore ( ) . pipe (
2953+ Effect . provideService ( ChildProcessSpawner . ChildProcessSpawner , spawner ) ,
2954+ Effect . provide ( layerServerConfig ) ,
2955+ ) ;
2956+ const refresh = yield * driver
2957+ . statusDetailsRemote ( cwd )
2958+ . pipe ( Effect . forkChild ( { startImmediately : true } ) ) ;
2959+ if ( stage === "shared budget" ) {
2960+ yield * Deferred . await ( preparationBlocked ) ;
2961+ yield * TestClock . adjust ( "3 seconds" ) ;
2962+ yield * Deferred . succeed ( releasePreparation , undefined ) ;
2963+ }
2964+ yield * Deferred . await ( blocked ) ;
2965+ yield * TestClock . adjust ( stage === "shared budget" ? "2 seconds" : "5 seconds" ) ;
2966+ const interruptedWithinDeadline = yield * Deferred . isDone ( interrupted ) ;
2967+ // Always release the injected stall so the pre-fix regression fails without leaking fibers.
2968+ yield * Deferred . succeed ( release , undefined ) ;
2969+ const status = yield * Fiber . join ( refresh ) ;
2970+ assert . isTrue ( interruptedWithinDeadline ) ;
2971+ assert . equal ( status . behindCount , 0 ) ;
2972+ assert . equal (
2973+ yield * git ( cwd , [ "rev-parse" , `refs/remotes/origin/${ initialBranch } ` ] ) ,
2974+ originalCommit ,
2975+ ) ;
2976+ assert . equal ( ( yield * driver . statusDetailsRemote ( cwd ) ) . behindCount , 0 ) ;
2977+ assert . equal ( attempts , 1 ) ;
2978+ const fs = yield * FileSystem . FileSystem ;
2979+ const path = yield * Path . Path ;
2980+ const isolatedRoot = path . join ( cwd , ".git" , "objects" , "t3-status-fetch" ) ;
2981+ if ( yield * fs . exists ( isolatedRoot ) ) {
2982+ assert . deepStrictEqual ( yield * fs . readDirectory ( isolatedRoot ) , [ ] ) ;
2983+ }
2984+ yield * git ( cwd , [ "fsck" , "--full" , "--no-dangling" ] ) ;
2985+ } ) ,
2986+ ) ;
2987+
28782988 it . effect ( "refreshes status without a second upload-pack process" , ( ) =>
28792989 Effect . gen ( function * ( ) {
28802990 const cwd = yield * makeTmpDir ( ) ;
0 commit comments