Skip to content

Commit 46c5cbd

Browse files
esopergrinberg
authored andcommittedSep 5, 2022
feature: dune describe workspace accepts dirs
allow `dune describe workspace` to accept directories as arguments The provided directories restrict the worskpace description to those directories. Note that the transitive dependencies of the discovered executables and libraries are always printed. If no argument is provided, or if `.` is provided, then the behavior is unchanged. This fixes issue#3893. Signed-off-by: Benoît Montagu <benoit.montagu@inria.fr>
1 parent 54329f1 commit 46c5cbd

File tree

3 files changed

+136
-16
lines changed

3 files changed

+136
-16
lines changed
 

‎CHANGES.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
3.5.0 (unreleased)
22
------------------
33

4+
- Allow dune describe workspace to accept directories as arguments.
5+
The provided directories restrict the worskpace description to those
6+
directories. (#6107, fixes #3893, @esope)
7+
48
- Add a terminal persistence mode that attempts to clear the terminal history.
59
It is enabled by setting terminal persistence to
610
`clear-on-rebuild-and-flush-history` (#6065, @rgrinberg)

‎bin/describe.ml

+75-15
Original file line numberDiff line numberDiff line change
@@ -404,14 +404,38 @@ module Crawl = struct
404404
in
405405
Some (Descr.Item.Library lib_descr)
406406

407+
(** [source_path_is_in_dirs dirs p] tests whether the source path [p] is a
408+
descendant of some of the provided directory [dirs]. If [dirs = None],
409+
then it always succeeds. If [dirs = Some l], then a matching directory is
410+
search in the list [l]. *)
411+
let source_path_is_in_dirs dirs (p : Path.Source.t) =
412+
match dirs with
413+
| None -> true
414+
| Some dirs ->
415+
List.exists ~f:(fun dir -> Path.Source.is_descendant p ~of_:dir) dirs
416+
417+
(** Tests whether a dune file is located in a path that is a descendant of
418+
some directory *)
419+
let dune_file_is_in_dirs dirs (dune_file : Dune_file.t) =
420+
source_path_is_in_dirs dirs dune_file.dir
421+
422+
(** Tests whether a library is located in a path that is a descendant of some
423+
directory *)
424+
let lib_is_in_dirs dirs (lib : Lib.t) =
425+
source_path_is_in_dirs dirs
426+
(Path.drop_build_context_exn @@ Lib_info.best_src_dir @@ Lib.info lib)
427+
407428
(** Builds a workspace description for the provided dune setup and context *)
408-
let workspace options
429+
let workspace options dirs
409430
({ Dune_rules.Main.conf; contexts = _; scontexts } :
410431
Dune_rules.Main.build_system) (context : Context.t) :
411432
Descr.Workspace.t Memo.t =
412433
let sctx = Context_name.Map.find_exn scontexts context.name in
413434
let open Memo.O in
414-
let* dune_files = Dune_load.Dune_files.eval conf.dune_files ~context in
435+
let* dune_files =
436+
Dune_load.Dune_files.eval conf.dune_files ~context
437+
>>| List.filter ~f:(dune_file_is_in_dirs dirs)
438+
in
415439
let* exes, exe_libs =
416440
(* the list of workspace items that describe executables, and the list of
417441
their direct library dependencies *)
@@ -438,7 +462,9 @@ module Crawl = struct
438462
let* scope = Scope.DB.find_by_project ctx project in
439463
Scope.libs scope |> Lib.DB.all)
440464
>>| Lib.Set.union_all
465+
>>| Lib.Set.filter ~f:(lib_is_in_dirs dirs)
441466
in
467+
442468
let+ libs =
443469
(* the executables' libraries, and the project's libraries *)
444470
Lib.Set.union exe_libs project_libs
@@ -610,29 +636,40 @@ end
610636
without hassle. *)
611637
module What = struct
612638
type t =
613-
| Workspace
639+
| Workspace of { dirs : string list option }
614640
| Opam_files
615641
| Pp of string
616642

617-
let default = Workspace
643+
(** By default, describe the whole workspace *)
644+
let default = Workspace { dirs = None }
618645

619646
(* The list of command names, their args, their documentation, and their
620647
parser *)
621648
let parsers_with_docs :
622649
(string * string list * string * t Dune_lang.Decoder.t) list =
623650
let open Dune_lang.Decoder in
624651
[ ( "workspace"
625-
, []
626-
, "prints a description of the workspace's structure"
627-
, return Workspace )
652+
, [ "DIRS" ]
653+
, "prints a description of the workspace's structure. If some \
654+
directories DIRS are provided, then only those directories of the \
655+
workspace are considered."
656+
, let+ dirs = repeat relative_file in
657+
(* [None] means that all directories should be accepted,
658+
whereas [Some l] means that only the directories in the
659+
list [l] should be accepted. The checks on whether the
660+
paths exist and whether they are directories are performed
661+
later in the [describe] function. *)
662+
let dirs = if List.is_empty dirs then None else Some dirs in
663+
Workspace { dirs } )
628664
; ( "opam-files"
629665
, []
630666
, "prints information about the Opam files that have been discovered"
631667
, return Opam_files )
632668
; ( "pp"
633669
, [ "FILE" ]
634670
, "builds a given FILE and prints the preprocessed output"
635-
, filename >>| fun s -> Pp s )
671+
, let+ s = filename in
672+
Pp s )
636673
]
637674

638675
(* The list of documentation strings (one for each command) *)
@@ -666,14 +703,37 @@ module What = struct
666703
in
667704
Dune_lang.Decoder.parse parse Univ_map.empty ast
668705

669-
let describe t options setup super_context =
706+
let describe t options (common : Common.t) setup super_context =
670707
let some = Memo.map ~f:(fun x -> Some x) in
671708
match t with
672709
| Opam_files -> Opam_files.get () |> some
673-
| Workspace ->
710+
| Workspace { dirs } ->
674711
let context = Super_context.context super_context in
675712
let open Memo.O in
676-
Crawl.workspace options setup context
713+
let* dirs =
714+
(* prefix directories with the workspace root, so that the
715+
command also works correctly when it is run from a
716+
subdirectory *)
717+
Memo.Option.map dirs
718+
~f:
719+
(Memo.List.map ~f:(fun dir ->
720+
let p =
721+
Path.Source.(relative root) (Common.prefix_target common dir)
722+
in
723+
let s = Path.source p in
724+
if not @@ Path.exists s then
725+
User_error.raise
726+
[ Pp.textf "No such file or directory: %s"
727+
(Path.to_string s)
728+
];
729+
if not @@ Path.is_directory s then
730+
User_error.raise
731+
[ Pp.textf "File exists, but is not a directory: %s"
732+
(Path.to_string s)
733+
];
734+
Memo.return p))
735+
in
736+
Crawl.workspace options dirs setup context
677737
>>| Sanitize_for_tests.Workspace.sanitize context
678738
>>| Descr.Workspace.to_dyn options
679739
|> some
@@ -799,12 +859,12 @@ let term : unit Term.t =
799859
Import.Main.find_scontext_exn setup ~name:context_name
800860
in
801861
let+ res =
802-
Build_system.run (fun () ->
803-
What.describe what options setup super_context)
862+
Build_system.run_exn (fun () ->
863+
What.describe what options common setup super_context)
804864
in
805865
match res with
806-
| Error `Already_reported | Ok None -> ()
807-
| Ok (Some res) -> (
866+
| None -> ()
867+
| Some res -> (
808868
match format with
809869
| Csexp -> Csexp.to_channel stdout (Sexp.of_dyn res)
810870
| Sexp -> print_as_sexp res))

‎test/blackbox-tests/test-cases/describe.t

+57-1
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,14 @@ Setup
207207
> EOF
208208
$ touch virtual_impl2/virtual.ml
209209

210+
$ mkdir subdir
211+
$ mkdir subdir/subfolder
212+
$ cat >subdir/subfolder/dune <<EOF
213+
> (library
214+
> (name subfolder_lib))
215+
> EOF
216+
$ touch subdir/subfolder/subfolder_lib.ml
217+
210218
Describe various things
211219
-----------------------
212220

@@ -621,6 +629,20 @@ not stable across different setups.
621629
(source_dir /FINDLIB//stdlib-shims)
622630
(modules ())
623631
(include_dirs (/FINDLIB//stdlib-shims))))
632+
(library
633+
((name subfolder_lib)
634+
(uid edb8ce3704b7983446d5ffb4cea0b51e)
635+
(local true)
636+
(requires ())
637+
(source_dir _build/default/subdir/subfolder)
638+
(modules
639+
(((name Subfolder_lib)
640+
(impl (_build/default/subdir/subfolder/subfolder_lib.ml))
641+
(intf ())
642+
(cmt
643+
(_build/default/subdir/subfolder/.subfolder_lib.objs/byte/subfolder_lib.cmt))
644+
(cmti ()))))
645+
(include_dirs (_build/default/subdir/subfolder/.subfolder_lib.objs/byte))))
624646
(library
625647
((name virtual)
626648
(uid f0299ba46dc29b8d4bd2f5d1cf82587c)
@@ -1180,6 +1202,21 @@ not stable across different setups.
11801202
(source_dir /FINDLIB//stdlib-shims)
11811203
(modules ())
11821204
(include_dirs (/FINDLIB//stdlib-shims))))
1205+
(library
1206+
((name subfolder_lib)
1207+
(uid edb8ce3704b7983446d5ffb4cea0b51e)
1208+
(local true)
1209+
(requires ())
1210+
(source_dir _build/default/subdir/subfolder)
1211+
(modules
1212+
(((name Subfolder_lib)
1213+
(impl (_build/default/subdir/subfolder/subfolder_lib.ml))
1214+
(intf ())
1215+
(cmt
1216+
(_build/default/subdir/subfolder/.subfolder_lib.objs/byte/subfolder_lib.cmt))
1217+
(cmti ())
1218+
(module_deps ((for_intf ()) (for_impl ()))))))
1219+
(include_dirs (_build/default/subdir/subfolder/.subfolder_lib.objs/byte))))
11831220
(library
11841221
((name virtual)
11851222
(uid f0299ba46dc29b8d4bd2f5d1cf82587c)
@@ -1247,6 +1284,20 @@ not stable across different setups.
12471284
(for_impl ()))))))
12481285
(include_dirs (_build/default/virtual_impl2/.virtual_impl2.objs/byte)))))
12491286

1287+
$ dune describe workspace --lang 0.1 --sanitize-for-tests virtual
1288+
((library
1289+
((name virtual)
1290+
(uid f0299ba46dc29b8d4bd2f5d1cf82587c)
1291+
(local true)
1292+
(requires ())
1293+
(source_dir _build/default/virtual)
1294+
(modules
1295+
(((name Virtual)
1296+
(impl ())
1297+
(intf (_build/default/virtual/virtual.mli))
1298+
(cmt ())
1299+
(cmti (_build/default/virtual/.virtual.objs/byte/virtual.cmti)))))
1300+
(include_dirs (_build/default/virtual/.virtual.objs/byte)))))
12501301

12511302
Test other formats
12521303
------------------
@@ -1263,7 +1314,12 @@ Test errors
12631314
[1]
12641315

12651316
$ dune describe --lang 0.1 workspace xxx
1266-
Error: Too many argument for workspace
1317+
Error: No such file or directory: xxx
1318+
[1]
1319+
1320+
$ touch yyy
1321+
$ dune describe --lang 0.1 workspace yyy
1322+
Error: File exists, but is not a directory: yyy
12671323
[1]
12681324

12691325
$ dune describe --lang 1.0

0 commit comments

Comments
 (0)
Please sign in to comment.