@@ -420,49 +420,78 @@ export namespace Worktree {
420420 }
421421
422422 const directory = await canonical ( input . directory )
423+ const locate = async ( stdout : Uint8Array | undefined ) => {
424+ const lines = outputText ( stdout )
425+ . split ( "\n" )
426+ . map ( ( line ) => line . trim ( ) )
427+ const entries = lines . reduce < { path ?: string ; branch ?: string } [ ] > ( ( acc , line ) => {
428+ if ( ! line ) return acc
429+ if ( line . startsWith ( "worktree " ) ) {
430+ acc . push ( { path : line . slice ( "worktree " . length ) . trim ( ) } )
431+ return acc
432+ }
433+ const current = acc [ acc . length - 1 ]
434+ if ( ! current ) return acc
435+ if ( line . startsWith ( "branch " ) ) {
436+ current . branch = line . slice ( "branch " . length ) . trim ( )
437+ }
438+ return acc
439+ } , [ ] )
440+
441+ return ( async ( ) => {
442+ for ( const item of entries ) {
443+ if ( ! item . path ) continue
444+ const key = await canonical ( item . path )
445+ if ( key === directory ) return item
446+ }
447+ } ) ( )
448+ }
449+
450+ const clean = ( target : string ) =>
451+ fs
452+ . rm ( target , {
453+ recursive : true ,
454+ force : true ,
455+ maxRetries : 5 ,
456+ retryDelay : 100 ,
457+ } )
458+ . catch ( ( error ) => {
459+ const message = error instanceof Error ? error . message : String ( error )
460+ throw new RemoveFailedError ( { message : message || "Failed to remove git worktree directory" } )
461+ } )
462+
423463 const list = await $ `git worktree list --porcelain` . quiet ( ) . nothrow ( ) . cwd ( Instance . worktree )
424464 if ( list . exitCode !== 0 ) {
425465 throw new RemoveFailedError ( { message : errorText ( list ) || "Failed to read git worktrees" } )
426466 }
427467
428- const lines = outputText ( list . stdout )
429- . split ( "\n" )
430- . map ( ( line ) => line . trim ( ) )
431- const entries = lines . reduce < { path ?: string ; branch ?: string } [ ] > ( ( acc , line ) => {
432- if ( ! line ) return acc
433- if ( line . startsWith ( "worktree " ) ) {
434- acc . push ( { path : line . slice ( "worktree " . length ) . trim ( ) } )
435- return acc
436- }
437- const current = acc [ acc . length - 1 ]
438- if ( ! current ) return acc
439- if ( line . startsWith ( "branch " ) ) {
440- current . branch = line . slice ( "branch " . length ) . trim ( )
441- }
442- return acc
443- } , [ ] )
444-
445- const entry = await ( async ( ) => {
446- for ( const item of entries ) {
447- if ( ! item . path ) continue
448- const key = await canonical ( item . path )
449- if ( key === directory ) return item
450- }
451- } ) ( )
468+ const entry = await locate ( list . stdout )
452469
453470 if ( ! entry ?. path ) {
454471 const directoryExists = await exists ( directory )
455472 if ( directoryExists ) {
456- await fs . rm ( directory , { recursive : true , force : true } )
473+ await clean ( directory )
457474 }
458475 return true
459476 }
460477
461478 const removed = await $ `git worktree remove --force ${ entry . path } ` . quiet ( ) . nothrow ( ) . cwd ( Instance . worktree )
462479 if ( removed . exitCode !== 0 ) {
463- throw new RemoveFailedError ( { message : errorText ( removed ) || "Failed to remove git worktree" } )
480+ const next = await $ `git worktree list --porcelain` . quiet ( ) . nothrow ( ) . cwd ( Instance . worktree )
481+ if ( next . exitCode !== 0 ) {
482+ throw new RemoveFailedError ( {
483+ message : errorText ( removed ) || errorText ( next ) || "Failed to remove git worktree" ,
484+ } )
485+ }
486+
487+ const stale = await locate ( next . stdout )
488+ if ( stale ?. path ) {
489+ throw new RemoveFailedError ( { message : errorText ( removed ) || "Failed to remove git worktree" } )
490+ }
464491 }
465492
493+ await clean ( entry . path )
494+
466495 const branch = entry . branch ?. replace ( / ^ r e f s \/ h e a d s \/ / , "" )
467496 if ( branch ) {
468497 const deleted = await $ `git branch -D ${ branch } ` . quiet ( ) . nothrow ( ) . cwd ( Instance . worktree )
0 commit comments