Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 37 additions & 17 deletions bin/clean.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ let command =
[ `S "DESCRIPTION"
; `P {|Removes files added by dune such as _build, <package>.install, and .merlin|}
; `P
{|If one or more PATH arguments are given, only remove those paths from the build directory.|}
{|If one or more PATH arguments are given, only those paths are removed from the build directory. A PATH may be a path inside the build directory (e.g. _build/default/foo) or a source directory (e.g. foo), in which case the corresponding artifacts are removed from every build context.|}
; `Blocks Common.help_secs
]
in
Expand All @@ -18,30 +18,50 @@ let command =
log file be useless but with some FS this also causes [dune clean] to fail (cf
https://github.com/ocaml/dune/issues/2964). *)
let builder = Common.Builder.disable_log_file builder in
let common, _config = Common.init builder in
let common, config = Common.init builder in
Global_lock.lock_exn ();
match paths with
| [] ->
Dune_engine.Target_promotion.files_in_source_tree_to_delete ()
|> Path.Source.Set.iter ~f:(fun p -> Fpath.unlink_no_err (Path.Source.to_string p));
Path.rm_rf Path.build_dir
| paths ->
let build_path path =
let path = Path.of_string (Common.prefix_target common path) in
match Path.as_in_build_dir path with
| Some path -> path
| None ->
User_error.raise
[ Pp.textf
"%s is not inside the build directory"
(Path.to_string_maybe_quoted path)
]
let remove_build_path path =
Dune_engine.Rule_cache.Workspace_local.remove_target path;
Dune_engine.Rule_cache.Workspace_local.remove_subtree path;
Path.rm_rf (Path.build path)
in
List.iter paths ~f:(fun path ->
let path = build_path path in
let () = Dune_engine.Rule_cache.Workspace_local.remove_target path in
let () = Dune_engine.Rule_cache.Workspace_local.remove_subtree path in
Path.rm_rf (Path.build path))
(* Paths already inside the build directory are removed as is. Source paths
(including the project root) are resolved against every build context,
mirroring how [dune build] accepts source directories. *)
let build_paths, source_paths =
List.partition_map paths ~f:(fun path ->
let path = Path.of_string (Common.prefix_target common path) in
match Path.as_in_build_dir path with
| Some path -> Left path
| None ->
(match Path.as_in_source_tree path with
| Some src -> Right src
| None ->
User_error.raise
[ Pp.textf
"%s is not inside the build directory or the source tree"
(Path.to_string_maybe_quoted path)
]))
in
let source_build_paths =
match source_paths with
| [] -> []
| _ :: _ ->
Scheduler_setup.go_without_rpc_server ~common ~config (fun () ->
Memo.run
(let open Memo.O in
let+ contexts = Context.DB.all () in
List.concat_map source_paths ~f:(fun src ->
List.map contexts ~f:(fun ctx ->
Path.Build.append_source (Context.build_dir ctx) src))))
in
List.iter (build_paths @ source_build_paths) ~f:remove_build_path
in
Cmd.v (Cmd.info "clean" ~doc ~man) term
;;
5 changes: 5 additions & 0 deletions doc/changes/added/15305.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- `dune clean` now accepts source directories (and the project root) in
addition to paths inside the build directory. For example, `dune clean foo`
removes the build artifacts under the source directory `foo` from every build
context, mirroring how `dune build foo` accepts a source directory.
(#15305, fixes #2288, @rgrinberg)
24 changes: 13 additions & 11 deletions test/blackbox-tests/test-cases/clean.t
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ We can clean the entire workspace to re-run everything:
foo
bar

Issue #2288: unlike `dune build`, `dune clean` does not accept source
directories (or package names); it only accepts paths inside the build
directory. So cleaning a source directory, or the project root, is rejected.
Issue #2288: `dune clean` also accepts source directories, not just paths
inside the build directory, mirroring `dune build`. The corresponding artifacts
are removed from every build context.

$ mkdir sub
$ cat >sub/dune <<EOF
Expand All @@ -47,19 +47,21 @@ directory. So cleaning a source directory, or the project root, is rejected.
> (action (bash "touch baz && echo baz")))
> EOF

`dune build` accepts the source directory:

$ dune build sub
baz
$ test -e _build/default/sub/baz && echo built
built

But `dune clean` rejects it:
Cleaning the source directory removes its artifacts, leaving the rest intact:

$ dune clean sub
Error: sub is not inside the build directory
[1]
$ test -e _build/default/sub && echo present || echo removed
removed
$ test -e _build/default/foo && echo present || echo removed
present

The project root is rejected too:
Cleaning the project root cleans the whole build context:

$ dune clean .
Error: . is not inside the build directory
[1]
$ test -e _build/default && echo present || echo removed
removed
Loading