File tree Expand file tree Collapse file tree 3 files changed +43
-3
lines changed Expand file tree Collapse file tree 3 files changed +43
-3
lines changed Original file line number Diff line number Diff line change @@ -72,7 +72,9 @@ let open_out ~sw ?(append=false) ~create t =
7272let open_dir ~sw t =
7373 let (Resource. T (dir, ops), path) = t in
7474 let module X = (val (Resource. get ops Fs.Pi. Dir )) in
75- try X. open_dir dir ~sw path, " "
75+ try
76+ let sub = X. open_dir dir ~sw path, " " in
77+ (sub : [`Close | `Dir] t :> [< `Close | `Dir] t )
7678 with Exn. Io _ as ex ->
7779 let bt = Printexc. get_raw_backtrace () in
7880 Exn. reraise_with_context ex bt " opening directory %a" pp t
@@ -163,6 +165,19 @@ let rmdir t =
163165 let bt = Printexc. get_raw_backtrace () in
164166 Exn. reraise_with_context ex bt " removing directory %a" pp t
165167
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+ )
176+ );
177+ rmdir t
178+
179+ let rmtree = (rmtree : Fs.dir_ty t -> unit :> [> Fs.dir_ty] t -> unit )
180+
166181let rename t1 t2 =
167182 let (dir2, new_path) = t2 in
168183 let (Resource. T (dir, ops), old_path) = t1 in
Original file line number Diff line number Diff line change @@ -139,12 +139,12 @@ val mkdirs : ?exists_ok:bool -> perm:File.Unix_perm.t -> _ t -> unit
139139
140140 @param exist_ok If [false] (the default) then we raise {! Fs.Already_exists} if [t] is already a directory. *)
141141
142- val open_dir : sw :Switch .t -> _ t -> [`Close | dir_ty ] t
142+ val open_dir : sw :Switch .t -> _ t -> [< `Close | dir_ty ] t
143143(* * [open_dir ~sw t] opens [t].
144144
145145 This can be passed to functions to grant access only to the subtree [t]. *)
146146
147- val with_open_dir : _ t -> ([`Close | dir_ty ] t -> 'a ) -> 'a
147+ val with_open_dir : _ t -> ([< `Close | dir_ty ] t -> 'a ) -> 'a
148148(* * [with_open_dir] is like [open_dir], but calls [fn dir] with the new directory and closes
149149 it automatically when [fn] returns (if it hasn't already been closed by then). *)
150150
@@ -192,6 +192,9 @@ 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. *)
197+
195198val rename : _ t -> _ t -> unit
196199(* * [rename old_t new_t] atomically unlinks [old_t] and links it as [new_t].
197200
Original file line number Diff line number Diff line change @@ -61,6 +61,11 @@ 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
66+ | () -> traceln "rmtree %a -> ok" Path.pp path
67+ | exception ex -> traceln "@[<h>%a@]" Eio.Exn.pp ex
68+
6469let chdir path =
6570 traceln "chdir %S" path;
6671 Unix.chdir path
@@ -397,6 +402,23 @@ Removing something that doesn't exist or is out of scope:
397402- : unit = ()
398403```
399404
405+ # Recursive removal
406+
407+ ``` ocaml
408+ # run @@ fun env ->
409+ Switch.run @@ fun sw ->
410+ let cwd = Eio.Stdenv.cwd env in
411+ let foo = cwd / "foo" in
412+ try_mkdirs (foo / "bar"/ "baz");
413+ try_write_file ~create:(`Exclusive 0o600) (foo / "bar/file1") "data";
414+ try_rmtree foo;
415+ assert (Path.kind ~follow:false foo = `Not_found);
416+ +mkdirs <cwd:foo/bar/baz> -> ok
417+ +write <cwd:foo/bar/file1> -> ok
418+ +rmtree <cwd:foo> -> ok
419+ - : unit = ()
420+ ```
421+
400422# Limiting to a subdirectory
401423
402424Create a sandbox, write a file with it, then read it from outside:
You can’t perform that action at this time.
0 commit comments