@@ -331,7 +331,28 @@ func cleanPath(ctx context.Context, dir string) error {
331331 }
332332
333333 // Module cache has 0555 directories; make them writable in order to remove content.
334- // Use os.Root to confine chmod operations within `clean` and prevent symlink TOCTOU traversal.
334+ if err := makeTreeWritable (ctx , clean ); err != nil {
335+ return err
336+ }
337+
338+ // Check context again before potentially long RemoveAll
339+ if ctx .Err () != nil {
340+ return ctx .Err ()
341+ }
342+
343+ if err := os .RemoveAll (clean ); err != nil {
344+ return fmt .Errorf ("cleanPath: failed to remove %q: %w" , clean , err )
345+ }
346+
347+ return nil
348+ }
349+
350+ // makeTreeWritable walks `clean` and chmods every directory to 0755 so that
351+ // the subsequent os.RemoveAll can delete read-only entries (e.g. Go module
352+ // cache). The os.Root handle is closed before returning so that the caller
353+ // can remove `clean` on platforms (Windows) that disallow removing a
354+ // directory with an open handle.
355+ func makeTreeWritable (ctx context.Context , clean string ) error {
335356 root , err := os .OpenRoot (clean )
336357 if err != nil {
337358 if errors .Is (err , fs .ErrNotExist ) {
@@ -342,7 +363,6 @@ func cleanPath(ctx context.Context, dir string) error {
342363 defer func () { _ = root .Close () }()
343364
344365 err = fs .WalkDir (root .FS (), "." , func (relPath string , info fs.DirEntry , walkErr error ) error {
345- // Respect context cancellation for long directory trees
346366 select {
347367 case <- ctx .Done ():
348368 return ctx .Err ()
@@ -367,15 +387,5 @@ func cleanPath(ctx context.Context, dir string) error {
367387 }
368388 return fmt .Errorf ("cleanPath: error preparing %q for removal: %w" , clean , err )
369389 }
370-
371- // Check context again before potentially long RemoveAll
372- if ctx .Err () != nil {
373- return ctx .Err ()
374- }
375-
376- if err := os .RemoveAll (clean ); err != nil {
377- return fmt .Errorf ("cleanPath: failed to remove %q: %w" , clean , err )
378- }
379-
380390 return nil
381391}
0 commit comments