@@ -124,13 +124,48 @@ describe("ProjectCopy", () => {
124124 )
125125 expect ( Array . from ( yield * Fiber . join ( fiber ) ) [ 0 ] ?. data ) . toEqual ( { projectID : input . projectID } )
126126
127- yield * copy . remove ( { projectID : input . projectID , directory : created . directory } )
127+ yield * copy . remove ( { projectID : input . projectID , directory : created . directory , force : false } )
128128
129129 expect ( yield * stored ( input . projectID ) ) . toEqual ( [ { directory : input . sourceDirectory , type : "main" as const } ] )
130130 expect ( yield * Effect . promise ( ( ) => Bun . file ( target ) . exists ( ) ) ) . toBe ( false )
131131 } ) ,
132132 )
133133
134+ it . live ( "requires force to remove a dirty git worktree" , ( ) =>
135+ Effect . gen ( function * ( ) {
136+ const input = yield * setup ( )
137+ const copy = yield * ProjectCopy . Service
138+ const temp = yield * Effect . promise ( ( ) => fs . realpath ( path . dirname ( input . root . path ) ) )
139+ const parent = abs ( path . join ( temp , path . basename ( input . root . path ) + "-copy-dirty" ) )
140+ yield * Effect . addFinalizer ( ( ) =>
141+ Effect . promise ( ( ) => fs . rm ( parent , { recursive : true , force : true } ) ) . pipe ( Effect . ignore ) ,
142+ )
143+ const created = yield * copy . create ( {
144+ projectID : input . projectID ,
145+ strategy : "git_worktree" ,
146+ sourceDirectory : input . sourceDirectory ,
147+ directory : parent ,
148+ name : "copy" ,
149+ } )
150+ yield * Effect . promise ( ( ) => Bun . write ( path . join ( created . directory , "dirty.txt" ) , "dirty" ) )
151+
152+ const error = yield * copy
153+ . remove ( { projectID : input . projectID , directory : created . directory , force : false } )
154+ . pipe ( Effect . flip )
155+
156+ expect ( error ) . toBeInstanceOf ( Git . WorktreeError )
157+ if ( error instanceof Git . WorktreeError ) {
158+ expect ( error . operation ) . toBe ( "remove" )
159+ expect ( error . forceRequired ) . toBe ( true )
160+ }
161+ expect ( yield * stored ( input . projectID ) ) . toContainEqual ( { directory : created . directory , type : "git_worktree" } )
162+ expect ( yield * Effect . promise ( ( ) => Bun . file ( path . join ( created . directory , "dirty.txt" ) ) . exists ( ) ) ) . toBe ( true )
163+
164+ yield * copy . remove ( { projectID : input . projectID , directory : created . directory , force : true } )
165+ expect ( yield * Effect . promise ( ( ) => Bun . file ( created . directory ) . exists ( ) ) ) . toBe ( false )
166+ } ) ,
167+ )
168+
134169 it . live ( "adds a numeric suffix when a copy directory already exists" , ( ) =>
135170 Effect . gen ( function * ( ) {
136171 const input = yield * setup ( )
@@ -160,7 +195,7 @@ describe("ProjectCopy", () => {
160195 true ,
161196 )
162197
163- yield * copy . remove ( { projectID : input . projectID , directory : created . directory } )
198+ yield * copy . remove ( { projectID : input . projectID , directory : created . directory , force : false } )
164199 } ) ,
165200 )
166201
0 commit comments