File tree Expand file tree Collapse file tree 3 files changed +39
-14
lines changed Expand file tree Collapse file tree 3 files changed +39
-14
lines changed Original file line number Diff line number Diff line change @@ -165,18 +165,30 @@ let rmdir t =
165
165
let bt = Printexc. get_raw_backtrace () in
166
166
Exn. reraise_with_context ex bt " removing directory %a" pp t
167
167
168
- let rec rmtree (t : Fs.dir_ty t ) =
169
- with_open_dir t (fun t ->
170
- read_dir t |> List. iter (fun name ->
171
- let item = t / name in
172
- match kind ~follow: false item with
173
- | `Directory -> rmtree item
174
- | _ -> unlink item
175
- )
168
+ let catch_missing ~missing_ok fn x =
169
+ if missing_ok then
170
+ try fn x
171
+ with Exn. Io (Fs. E Not_found _ , _ ) -> ()
172
+ else fn x
173
+
174
+ let rec rmtree ~missing_ok t =
175
+ match kind ~follow: false t with
176
+ | `Directory ->
177
+ Switch. run (fun sw ->
178
+ match
179
+ let t = open_dir ~sw t in
180
+ t, read_dir t
181
+ with
182
+ | t , items -> List. iter (fun x -> rmtree ~missing_ok (t / x)) items
183
+ | exception Exn. Io (Fs. E Not_found _ , _ ) when missing_ok -> ()
176
184
);
177
- rmdir t
185
+ catch_missing ~missing_ok rmdir t
186
+ | `Not_found when missing_ok -> ()
187
+ | _ ->
188
+ catch_missing ~missing_ok unlink t
178
189
179
- let rmtree = (rmtree : Fs.dir_ty t -> unit :> [> Fs.dir_ty] t -> unit )
190
+ let rmtree ?(missing_ok =false ) t =
191
+ rmtree ~missing_ok (t :> Fs.dir_ty t )
180
192
181
193
let rename t1 t2 =
182
194
let (dir2, new_path) = t2 in
Original file line number Diff line number Diff line change @@ -192,8 +192,13 @@ val rmdir : _ t -> unit
192
192
193
193
Note: this usually requires the directory to be empty. *)
194
194
195
- val rmtree : _ t -> unit
196
- (* * [rmtree t] removes directory [t] and its contents, recursively. *)
195
+ val rmtree : ?missing_ok : bool -> _ t -> unit
196
+ (* * [rmtree t] removes [t] (and its contents, recursively, if it's a directory).
197
+
198
+ @param missing_ok If [false] (the default), raise an {!Fs.Not_found} IO error if [t] doesn't exist.
199
+ If [true], ignore missing items.
200
+ This applies recursively, allowing two processes
201
+ to attempt to remove a tree at the same time. *)
197
202
198
203
val rename : _ t -> _ t -> unit
199
204
(* * [rename old_t new_t] atomically unlinks [old_t] and links it as [new_t].
Original file line number Diff line number Diff line change @@ -61,8 +61,8 @@ let try_rmdir path =
61
61
| () -> traceln "rmdir %a -> ok" Path.pp path
62
62
| exception ex -> traceln "@[<h>%a@]" Eio.Exn.pp ex
63
63
64
- let try_rmtree path =
65
- match Path.rmtree path with
64
+ let try_rmtree ?missing_ok path =
65
+ match Path.rmtree ?missing_ok path with
66
66
| () -> traceln "rmtree %a -> ok" Path.pp path
67
67
| exception ex -> traceln "@[<h>%a@]" Eio.Exn.pp ex
68
68
@@ -413,9 +413,17 @@ Removing something that doesn't exist or is out of scope:
413
413
try_write_file ~create:(`Exclusive 0o600) (foo / "bar/file1") "data";
414
414
try_rmtree foo;
415
415
assert (Path.kind ~follow:false foo = `Not_found);
416
+ traceln "A second rmtree is OK with missing_ok:";
417
+ try_rmtree ~missing_ok:true foo;
418
+ traceln "But not without:";
419
+ try_rmtree ~missing_ok:false foo;
416
420
+mkdirs <cwd:foo/bar/baz> -> ok
417
421
+write <cwd:foo/bar/file1> -> ok
418
422
+rmtree <cwd:foo> -> ok
423
+ +A second rmtree is OK with missing_ok:
424
+ +rmtree <cwd:foo> -> ok
425
+ +But not without:
426
+ +Eio.Io Fs Not_found _, removing file <cwd:foo>
419
427
- : unit = ()
420
428
```
421
429
You can’t perform that action at this time.
0 commit comments