Skip to content

Commit

Permalink
feature: dune show targets and dune show aliases
Browse files Browse the repository at this point in the history
Add a `dune show targets` and `dune show aliases` command for showing
targets and aliases in a directory like `ls`.

fix ocaml#265

Co-authored-by: Rudi Grinberg <me@rgrinberg.com>
Signed-off-by: Ali Caglayan <alizter@gmail.com>
  • Loading branch information
Alizter and rgrinberg committed Jun 17, 2023
1 parent 59b44dc commit ee9768c
Show file tree
Hide file tree
Showing 16 changed files with 312 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ Unreleased
- Respect `-p` / `--only-packages` for `melange.emit` artifacts (#7849,
@anmonteiro)

- Add commands `dune show targets` and `dune show aliases`, which are similar to
`ls`, that display all the available targets and aliases in a given directory
respectively. (#7770, grants #265, @Alizter)

- Fix scanning of Coq installed files (@ejgallego, reported by
@palmskog, #7895 , fixes #7893)

Expand Down
30 changes: 30 additions & 0 deletions bin/describe/aliases_cmd.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
open Import

let fetch_results (build_system : Dune_rules.Main.build_system) root
(_dir : Path.t) =
let open Action_builder.O in
let+ alias_targets =
let+ load_dir =
Action_builder.List.map build_system.contexts ~f:(fun ctx ->
let dir =
Path.Build.append_source
(Dune_engine.Context_name.build_dir (Context.name ctx))
root
|> Path.build
in
Action_builder.of_memo (Load_rules.load_dir ~dir))
in
List.fold_left load_dir ~init:Dune_engine.Alias.Name.Map.empty
~f:(fun acc x ->
match (x : Load_rules.Loaded.t) with
| Build build -> Dune_engine.Alias.Name.Map.superpose acc build.aliases
| _ -> acc)
|> Dune_engine.Alias.Name.Map.keys
in
List.map ~f:Dune_engine.Alias.Name.to_string alias_targets

let term = Ls_like_cmd.term fetch_results

let command =
let doc = "Print aliases in a given directory. Works similalry to ls." in
Cmd.v (Cmd.info "aliases" ~doc ~envs:Common.envs) term
5 changes: 5 additions & 0 deletions bin/describe/aliases_cmd.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
open Import

(** The aliases command lists all the aliases available in the given directory,
defaulting to the current working direcctory. *)
val command : unit Cmd.t
2 changes: 2 additions & 0 deletions bin/describe/describe.ml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ let subcommands =
; Describe_opam_files.command
; Describe_pp.command
; Printenv.command
; Targets_cmd.command
; Aliases_cmd.command
]

let group =
Expand Down
34 changes: 34 additions & 0 deletions bin/describe/ls_like_cmd.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
open Import

let term fetch_results =
let+ common = Common.term
and+ paths = Arg.(value & pos_all string [ "." ] & info [] ~docv:"DIR") in
let config = Common.init common in
let request (build_system : Dune_rules.Main.build_system) =
let header = List.length paths > 1 in
let open Action_builder.O in
let+ paragraphs =
Action_builder.List.map paths ~f:(fun path ->
let dir = Path.of_string path in
let root =
match (dir : Path.t) with
| External e ->
Code_error.raise "target_hint: external path"
[ ("path", Path.External.to_dyn e) ]
| In_source_tree d -> d
| In_build_dir d -> (
match Path.Build.drop_build_context d with
| Some d -> d
| None -> Path.Source.root)
in
let+ targets = fetch_results build_system root dir in
(if header then [ Pp.textf "%s:" (Path.to_string dir) ] else [])
@ [ Pp.concat_map targets ~f:Pp.text ~sep:Pp.newline ]
|> Pp.concat ~sep:Pp.newline)
in
Console.print [ Pp.concat paragraphs ~sep:(Pp.seq Pp.newline Pp.newline) ]
in
Scheduler.go ~common ~config @@ fun () ->
let open Fiber.O in
Build_cmd.run_build_system ~common ~request
>>| fun (_ : (unit, [ `Already_reported ]) result) -> ()
8 changes: 8 additions & 0 deletions bin/describe/ls_like_cmd.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
open Import

val term :
( Dune_rules.Main.build_system
-> Path.Source.t
-> Path.t
-> string list Action_builder.t)
-> unit Term.t
33 changes: 33 additions & 0 deletions bin/describe/targets_cmd.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
open Import

let fetch_results (_ : Dune_rules.Main.build_system) root dir =
let open Action_builder.O in
let+ targets =
let open Memo.O in
Target.all_direct_targets (Some root)
>>| Path.Build.Map.to_list |> Action_builder.of_memo
in
List.map targets
~f:
(if Path.is_in_build_dir dir then fun (path, k) -> (Path.build path, k)
else fun (path, k) ->
match Path.Build.extract_build_context path with
| None -> (Path.build path, k)
| Some (_, path) -> (Path.source path, k))
|> (* Only suggest hints for the basename, otherwise it's slow when there
are lots of files *)
List.filter_map ~f:(fun (path, kind) ->
match Path.equal (Path.parent_exn path) dir with
| false -> None
| true ->
(* directory targets can be distinguied by the trailing path seperator *)
Some
(match kind with
| Target.File -> Path.basename path
| Directory -> Path.basename path ^ Filename.dir_sep))

let term = Ls_like_cmd.term fetch_results

let command =
let doc = "Print targets in a given directory. Works similalry to ls." in
Cmd.v (Cmd.info "targets" ~doc ~envs:Common.envs) term
5 changes: 5 additions & 0 deletions bin/describe/targets_cmd.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
open Import

(** The targets command lists all the targets available in the given directory,
defaulting to the current working direcctory. *)
val command : unit Cmd.t
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(lang dune 3.8)
107 changes: 107 additions & 0 deletions test/blackbox-tests/test-cases/describe/aliases.t/run.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
Testing the "dune show aliases" command. This command shows the aliases in the
current directory. It acts similarly to ls. It will not show aliases that appear
in subdirectories although this could be changed in the future.

In an empty dune project, the following aliases are available.

$ dune show aliases
all
default
fmt

User defined aliases can be added to a dune file. These should be picked up by
the command.

$ cat > dune << EOF
> (alias
> (name foo))
> EOF
$ dune show aliases
all
default
fmt
foo
Aliases in subdirectories should not be picked up.
$ mkdir subdir
$ cat > subdir/dune << EOF
> (alias
> (name bar))
> EOF
$ dune show aliases
all
default
fmt
foo
But checking the subdirectory it should be available.
$ dune show aliases subdir
all
bar
default
fmt
Adding an OCaml library will introduce OCaml specific aliases:
$ cat > dune << EOF
> (library
> (name foo))
> EOF
$ dune show aliases
all
check
default
doc-private
fmt
Adding a cram test will introduce an alias with the name of the test and also
introduce the runtest alias:
bbb
$ rm dune
$ cat > mytest.t
$ dune show aliases
all
default
fmt
mytest
runtest
We can also show aliases in multiple directories at once:
$ dune show aliases . subdir
.:
all
default
fmt
mytest
runtest
subdir:
all
bar
default
fmt
Including those in the _build/ directory:
$ dune build
$ dune show aliases . _build/default
.:
all
default
fmt
mytest
runtest
_build/default:
all
default
fmt
mytest
runtest
Empty file.
Empty file.
2 changes: 2 additions & 0 deletions test/blackbox-tests/test-cases/describe/targets.t/b/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
(library
(name simple2))
10 changes: 10 additions & 0 deletions test/blackbox-tests/test-cases/describe/targets.t/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(library
(name simple))

(rule
(targets
(dir d))
(action
(progn
(run mkdir d)
(run cat > d/foo))))
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
(lang dune 3.8)
(using directory-targets 0.1)
69 changes: 69 additions & 0 deletions test/blackbox-tests/test-cases/describe/targets.t/run.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
Testing the "dune show targets" command in a simple OCaml project with an
additional directory target to see the behaviour there.

We have two libraries with one in a subdirectory. We also have a directory
target d to see how the command will behave.

With no directory provided to the command, it should default to the current
working directory.

$ dune show targets
a.ml
d/
dune
dune-project
simple.a
simple.cma
simple.cmxa
simple.cmxs
simple.ml-gen

Multiple directories can be provided to the command. Also subdirectories may be
used, and only the targets available in that directory will be displayed.

$ dune show targets . b/
.:
a.ml
d/
dune
dune-project
simple.a
simple.cma
simple.cmxa
simple.cmxs
simple.ml-gen

b:
c.ml
dune
simple2.a
simple2.cma
simple2.cmxa
simple2.cmxs
simple2.ml-gen

The command also works with files in the _build directory.

$ dune show targets _build/default/
a.ml
d/
dune
dune-project
simple.a
simple.cma
simple.cmxa
simple.cmxs
simple.ml-gen

$ dune show targets _build/default/b
c.ml
dune
simple2.a
simple2.cma
simple2.cmxa
simple2.cmxs
simple2.ml-gen
We cannot see inside directory targets

$ dune show targets d

0 comments on commit ee9768c

Please sign in to comment.