@@ -62,8 +62,25 @@ func (filer *Httpfs) Remove(name string) error {
6262 return filer .fs .Remove (name )
6363}
6464
65+ // RemoveAller is an optional interface that filesystems can implement
66+ // to provide optimized recursive directory removal.
67+ type RemoveAller interface {
68+ RemoveAll (path string ) error
69+ }
70+
6571// RemoveAll removes a directory after removing all children of that directory.
66- func (filer * Httpfs ) RemoveAll (path string ) (err error ) {
72+ // If the underlying filesystem implements RemoveAller, it delegates to that.
73+ // Returns nil for non-existent paths (matching os.RemoveAll behavior).
74+ func (filer * Httpfs ) RemoveAll (path string ) error {
75+ // Check if the underlying filesystem implements RemoveAll
76+ if ra , ok := filer .fs .(RemoveAller ); ok {
77+ err := ra .RemoveAll (path )
78+ if os .IsNotExist (err ) {
79+ return nil
80+ }
81+ return err
82+ }
83+
6784 info , err := filer .Stat (path )
6885 if err != nil {
6986 if os .IsNotExist (err ) {
@@ -72,34 +89,46 @@ func (filer *Httpfs) RemoveAll(path string) (err error) {
7289 return err
7390 }
7491
75- // if it's not a directory remove it and return
92+ // If it's not a directory, just remove it
7693 if ! info .IsDir () {
7794 return filer .Remove (path )
7895 }
7996
80- f , err := filer .OpenFile (path , os .O_RDWR , 0700 )
97+ // Open directory read-only to list entries
98+ f , err := filer .OpenFile (path , os .O_RDONLY , 0 )
8199 if err != nil {
82100 if os .IsNotExist (err ) {
83101 return nil
84102 }
85103 return err
86104 }
87105
88- // get and loop through each directory entry calling remove all recursively
89106 infos , err := f .Readdir (0 )
107+ f .Close ()
90108 if err != nil {
91109 return err
92110 }
93- f .Close ()
94111
95112 for _ , info := range infos {
96- err = filer .RemoveAll (filepath .Join (path , info .Name ()))
97- if err != nil {
113+ name := info .Name ()
114+ // Skip . and .. to avoid infinite recursion
115+ if name == "." || name == ".." {
116+ continue
117+ }
118+ if err := filer .RemoveAll (filepath .Join (path , name )); err != nil {
98119 return err
99120 }
100121 }
101122
102- return filer .Remove (path )
123+ err = filer .Remove (path )
124+ // Some filesystems (e.g., memfs) return "directory not empty" even when
125+ // only . and .. remain. Check if the directory was actually removed.
126+ if err != nil {
127+ if _ , statErr := filer .Stat (path ); os .IsNotExist (statErr ) {
128+ return nil
129+ }
130+ }
131+ return err
103132}
104133
105134// Stat returns the FileInfo structure describing file. If there is an error, it will be of type *PathError.
0 commit comments