Skip to content
Draft
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
124 changes: 81 additions & 43 deletions bin/describe/aliases_targets.ml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
open Import

let ls_term (fetch_results : Path.Build.t -> string list Action_builder.t) =
let ls_term_gen extra_args fetch_results =
let+ builder = Common.Builder.term
(* CR-someday Alizter: document this option *)
and+ paths = Arg.(value & pos_all string [ "." ] & info [] ~docv:"DIR" ~doc:None)
and+ context =
Common.context_arg
~doc:(Some "The context to look in. Defaults to the default context.")
in
and+ extra = extra_args in
let common, config = Common.init builder in
let request (_ : Dune_rules.Main.build_system) =
let header = List.length paths > 1 in
Expand Down Expand Up @@ -54,28 +54,46 @@ let ls_term (fetch_results : Path.Build.t -> string list Action_builder.t) =
Action_builder.of_memo
@@
let open Memo.O in
Source_tree.find_dir src_dir
(* First check if it's a directory target *)
Load_rules.load_dir ~dir:(Path.build build_dir)
>>= function
| Some _ -> Memo.return ()
| None ->
(* The directory didn't exist. We therefore check if it was a
directory target and error for the user accordingly. *)
let+ is_dir_target =
Load_rules.is_under_directory_target (Path.build build_dir)
in
if is_dir_target
then
User_error.raise
[ Pp.textf
"Directory %s is a directory target. This command does not support \
the inspection of directory targets."
(Path.to_string dir)
]
else
User_error.raise
[ Pp.textf "Directory %s does not exist." (Path.to_string dir) ]
| Load_rules.Loaded.Build_under_directory_target _ ->
User_error.raise
[ Pp.textf
"Directory %s is a directory target. This command does not support the \
inspection of directory targets."
(Path.to_string dir)
]
| External _ | Build _ | Source _ ->
(* Check if directory exists in source tree or is a valid build-only directory *)
Source_tree.find_dir src_dir
>>= (function
| Some _ -> Memo.return () (* Exists in source tree *)
| None ->
(* Not in source tree, check if it's a valid build-only subdirectory *)
(match Path.Build.parent build_dir with
| None ->
(* Build context root always exists *)
Memo.return ()
| Some parent_dir ->
Load_rules.load_dir ~dir:(Path.build parent_dir)
>>| (function
| Load_rules.Loaded.Build { allowed_subdirs; _ } ->
let subdir_set =
Dune_engine.Dir_set.descend
allowed_subdirs
(Path.Build.basename build_dir)
in
if Dune_engine.Dir_set.here subdir_set
then ()
else
User_error.raise
[ Pp.textf "Directory %s does not exist." (Path.to_string dir) ]
| _ ->
User_error.raise
[ Pp.textf "Directory %s does not exist." (Path.to_string dir) ])))
in
let+ targets = fetch_results build_dir in
let+ targets = fetch_results extra build_dir in
(* If we are printing multiple directories, we print the directory
name as a header. *)
(if header then [ Pp.textf "%s:" (Path.to_string dir) ] else [])
Expand All @@ -92,7 +110,7 @@ let ls_term (fetch_results : Path.Build.t -> string list Action_builder.t) =
;;

module Aliases_cmd = struct
let fetch_results (dir : Path.Build.t) =
let fetch_results () (dir : Path.Build.t) =
let open Action_builder.O in
let+ alias_targets =
let+ load_dir =
Expand All @@ -105,7 +123,7 @@ module Aliases_cmd = struct
List.map ~f:Dune_engine.Alias.Name.to_string alias_targets
;;

let term = ls_term fetch_results
let term = ls_term_gen (Term.const ()) fetch_results

let command =
let doc = "Print aliases in a given directory. Works similarly to ls." in
Expand All @@ -114,28 +132,48 @@ module Aliases_cmd = struct
end

module Targets_cmd = struct
let fetch_results (dir : Path.Build.t) =
let fetch_results all (dir : Path.Build.t) =
let open Action_builder.O in
let+ targets =
let open Memo.O in
Target.all_direct_targets (Some (Path.Build.drop_build_context_exn dir))
>>| Path.Build.Map.to_list
|> Action_builder.of_memo
in
List.filter_map targets ~f:(fun (path, kind) ->
match Path.Build.equal (Path.Build.parent_exn path) dir with
| false -> None
| true ->
(* directory targets can be distinguied by the trailing path separator
*)
Some
(match kind with
| Target.File -> Path.Build.basename path |> Filename.to_string
| Directory ->
(Path.Build.basename path |> Filename.to_string) ^ Filename.dir_sep))
let+ load_dir = Action_builder.of_memo (Load_rules.load_dir ~dir:(Path.build dir)) in
match load_dir with
| Load_rules.Loaded.Build { rules_here; allowed_subdirs; _ } ->
let file_targets =
Path.Build.Map.keys rules_here.by_file_targets
|> List.filter_map ~f:(fun path ->
if Path.Build.equal (Path.Build.parent_exn path) dir
then Some (Path.Build.basename path |> Filename.to_string)
else None)
in
let dir_targets =
Path.Build.Map.keys rules_here.by_directory_targets
|> List.filter_map ~f:(fun path ->
if Path.Build.equal (Path.Build.parent_exn path) dir
then Some ((Path.Build.basename path |> Filename.to_string) ^ Filename.dir_sep)
else None)
in
let subdirs =
match Dune_engine.Dir_set.toplevel_subdirs allowed_subdirs with
| Infinite -> []
| Finite set ->
Filename.Set.to_list set
|> Filename.L.to_string
|> List.filter ~f:(fun name -> all || String.length name = 0 || name.[0] <> '.')
|> List.map ~f:(fun name -> name ^ Filename.dir_sep)
in
List.sort ~compare:String.compare (file_targets @ dir_targets @ subdirs)
| _ -> []
;;

let extra_args =
Arg.(
value
& flag
& info
[ "a"; "all" ]
~doc:(Some "Show hidden directories (those starting with '.')."))
;;

let term = ls_term fetch_results
let term = ls_term_gen extra_args fetch_results

let command =
let doc = "Print targets in a given directory. Works similarly to ls." in
Expand Down
3 changes: 3 additions & 0 deletions doc/changes/changed/14665.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- `dune show targets` now includes subdirectories that contain build targets,
and accepts an `-a`/`--all` flag to also include hidden directories (those
starting with `.`). (#14665, fixes #13783, @Alizter)
2 changes: 2 additions & 0 deletions doc/changes/fixed/14664.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- `dune show targets` now accepts build-only directories such as
`_build/default/.simple.objs`. (#14664, fixes #13782, @Alizter)
6 changes: 5 additions & 1 deletion doc/reference/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ documentation for each command is available through ``dune COMMAND --help``.

.. describe:: dune describe targets

Print targets in a given directory. Works similarly to ls.
Print targets in a given directory. Works similarly to ls. The directory
may be a path in the source tree, or a build-only directory under
``_build/`` (such as ``_build/default/.lib.objs``). Subdirectories
containing build targets are listed alongside the targets themselves;
pass ``-a``/``--all`` to also include hidden directories.

.. describe:: dune describe workspace

Expand Down
35 changes: 30 additions & 5 deletions test/blackbox-tests/test-cases/describe/targets.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ With no directory provided to the command, it should default to the current
working directory.

$ dune show targets
_doc/
_doc_new/
a.ml
b/
d/
dune
dune-project
Expand All @@ -23,7 +26,10 @@ used, and only the targets available in that directory will be displayed.

$ dune show targets . b/
.:
_doc/
_doc_new/
a.ml
b/
d/
dune
dune-project
Expand All @@ -45,7 +51,10 @@ used, and only the targets available in that directory will be displayed.
The command also works with files in the _build directory.

$ dune show targets _build/default/
_doc/
_doc_new/
a.ml
b/
d/
dune
dune-project
Expand All @@ -70,15 +79,31 @@ We cannot see inside directory targets
Error: Directory d is a directory target. This command does not support the
inspection of directory targets.

We cannot show targets in build-only directories that don't exist in the source
tree, like .simple.objs:
Build-only directories that don't exist in the source tree, like .simple.objs
(Dune's internal object directory for the `simple` library), can now be
queried:

$ dune show targets .simple.objs
Error: Directory .simple.objs does not exist.
byte/
cctx.ocaml-index
jsoo/
native/

CR-soon Alizter: This should work
$ dune show targets _build/default/.simple.objs
Error: Directory _build/default/.simple.objs does not exist.
byte/
cctx.ocaml-index
jsoo/
native/

With --all, hidden directories are also shown:

$ dune show targets --all .simple.objs
.bin/
.utop/
byte/
cctx.ocaml-index
jsoo/
native/

And we error on non-existent directories

Expand Down
Loading