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 =
165165 let bt = Printexc. get_raw_backtrace () in
166166 Exn. reraise_with_context ex bt " removing directory %a" pp t
167167
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 -> ()
176184 );
177- rmdir t
185+ catch_missing ~missing_ok rmdir t
186+ | `Not_found when missing_ok -> ()
187+ | _ ->
188+ catch_missing ~missing_ok unlink t
178189
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 )
180192
181193let rename t1 t2 =
182194 let (dir2, new_path) = t2 in
Original file line number Diff line number Diff line change @@ -192,8 +192,13 @@ val rmdir : _ t -> unit
192192
193193 Note: this usually requires the directory to be empty. *)
194194
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. *)
197202
198203val rename : _ t -> _ t -> unit
199204(* * [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 =
6161 | () -> traceln "rmdir %a -> ok" Path.pp path
6262 | exception ex -> traceln "@[<h>%a@]" Eio.Exn.pp ex
6363
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
6666 | () -> traceln "rmtree %a -> ok" Path.pp path
6767 | exception ex -> traceln "@[<h>%a@]" Eio.Exn.pp ex
6868
@@ -413,9 +413,17 @@ Removing something that doesn't exist or is out of scope:
413413 try_write_file ~create:(`Exclusive 0o600) (foo / "bar/file1") "data";
414414 try_rmtree foo;
415415 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;
416420+mkdirs <cwd:foo/bar/baz> -> ok
417421+write <cwd:foo/bar/file1> -> ok
418422+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>
419427- : unit = ()
420428```
421429
You can’t perform that action at this time.
0 commit comments