Skip to content

Commit

Permalink
add describe opam-files (ocaml#3577)
Browse files Browse the repository at this point in the history
Signed-off-by: Jeremie Dimino <jeremie@dimino.org>
  • Loading branch information
jeremiedimino authored Jun 25, 2020
1 parent 9f93ceb commit c38df3d
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 25 deletions.
39 changes: 37 additions & 2 deletions bin/describe.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
open Stdune
open Import

(* This command is not yet versioned, but some people are using it in
non-released tools. If you change the format of the output, please contact:
- rotor people for "describe workspace"
- duniverse people for "describe opam-files" *)

let doc = "Describe the workspace."

let man =
Expand Down Expand Up @@ -98,6 +105,31 @@ module Crawl = struct
Dyn.List (Lib.Set.to_list libs |> List.filter_map ~f:(library sctx))
end

module Opam_files = struct
let get () =
let project = Dune.File_tree.root () |> Dune.File_tree.Dir.project in
let packages =
Dune_project.packages project |> Dune.Package.Name.Map.values
in
Dyn.List
(List.map packages ~f:(fun pkg ->
let opam_file = Path.source (Dune.Package.opam_file pkg) in
let contents =
if not (Dune_project.generate_opam_files project) then
Io.read_file opam_file
else
let template_file = Dune.Opam_create.template_file opam_file in
let template =
if Path.exists template_file then
Some (template_file, Io.read_file template_file)
else
None
in
Dune.Opam_create.generate project pkg ~template
in
Dyn.Tuple [ String (Path.to_string opam_file); String contents ]))
end

(* What to describe. To determine what to describe, we convert the positional
arguments of the command line to a list of atoms and we parse it using the
regular [Dune_lang.Decoder].
Expand All @@ -106,13 +138,15 @@ end
machinery. This also allow to easily extend this to arbitrary complex phrases
without hassle. *)
module What = struct
type t = Workspace
type t =
| Workspace
| Opam_files

let default = Workspace

let parse =
let open Dune_lang.Decoder in
sum [ ("workspace", return Workspace) ]
sum [ ("workspace", return Workspace); ("opam-files", return Opam_files) ]

let parse ~lang args =
match args with
Expand All @@ -128,6 +162,7 @@ module What = struct
let describe t setup context =
match t with
| Workspace -> Crawl.workspace setup context
| Opam_files -> Opam_files.get ()
end

module Format = struct
Expand Down
54 changes: 32 additions & 22 deletions src/dune/opam_create.ml
Original file line number Diff line number Diff line change
Expand Up @@ -160,36 +160,46 @@ let opam_fields project (package : Package.t) =
else
Opam_file.Create.normalise_field_order fields

let template_file = Path.extend_basename ~suffix:".template"

let opam_template ~opam_path =
let opam_template_path =
opam_path |> Path.Build.extend_basename ~suffix:".template" |> Path.build
in
let open Build.O in
let opam_template_path = template_file opam_path in
Build.if_file_exists opam_template_path
~then_:(Build.contents opam_template_path)
~else_:(Build.return "")
~then_:
(let+ contents = Build.contents opam_template_path in
Some (opam_template_path, contents))
~else_:(Build.return None)

let generate project pkg ~template =
let opam_fname = Package.opam_file pkg in
let filter_fields =
match template with
| None -> Fun.id
| Some (fname, contents) ->
let vars_in_template =
Lexbuf.from_string ~fname:(Path.to_string fname) contents
|> Opam_file.parse |> Opam_file.existing_variables
in
List.filter ~f:(fun (v, _) -> not (String.Set.mem vars_in_template v))
in
let generated_fields =
opam_fields project pkg |> filter_fields
|> Opam_file.Create.of_bindings ~file:(Path.source opam_fname)
in
sprintf "# This file is generated by dune, edit dune-project instead\n%s\n%s"
(OpamPrinter.opamfile generated_fields)
( match template with
| None -> ""
| Some (_, s) -> s )

let add_rule sctx ~project ~pkg =
let open Build.O in
let build_dir = Super_context.build_dir sctx in
let opam_path = Path.Build.append_source build_dir (Package.opam_file pkg) in
let opam_rule =
(let+ template = opam_template ~opam_path in
let opam_path = Path.build opam_path in
let opamfile =
Opam_file.parse
(Lexbuf.from_string ~fname:(Path.to_string opam_path) template)
in
let existing_vars_template = Opam_file.existing_variables opamfile in
let generated_fields =
opam_fields project pkg
|> List.filter ~f:(fun (v, _) ->
not (String.Set.mem existing_vars_template v))
|> Opam_file.Create.of_bindings ~file:opam_path
in
sprintf
"# This file is generated by dune, edit dune-project instead\n%s\n%s"
(OpamPrinter.opamfile generated_fields)
template)
(let+ template = opam_template ~opam_path:(Path.build opam_path) in
generate project pkg ~template)
|> Build.write_file_dyn opam_path
in
let dir = Path.Build.append_source build_dir pkg.path in
Expand Down
10 changes: 10 additions & 0 deletions src/dune/opam_create.mli
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
(** Generate opam files from dune-project metadata *)

open Stdune

(** Given an opam filename, returns the filename of the template file *)
val template_file : Path.t -> Path.t

(** Generate the contents of an opam file. [template] is the filename and
contents of the template file. *)
val generate :
Dune_project.t -> Package.t -> template:(Path.t * string) option -> string

val add_rules : Super_context.t -> dir:Path.Build.t -> unit
32 changes: 31 additions & 1 deletion test/blackbox-tests/test-cases/describe/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ Setup

$ cat >dune-project <<EOF
> (lang dune 2.3)
> (package (name foo))
> (package
> (name foo)
> (synopsis "foo bar baz"))
> (generate_opam_files)
> EOF

$ cat >dune <<EOF
Expand Down Expand Up @@ -81,3 +84,30 @@ Test errors
Usage: dune describe [OPTION]... [STRING]...
Try `dune describe --help' or `dune --help' for more information.
[1]

opam file listing
-----------------

$ dune describe --lang 0.1 opam-files | sed 's/\\n/\n/g'
((foo.opam
"# This file is generated by dune, edit dune-project instead
opam-version: \"2.0\"
synopsis: \"foo bar baz\"
depends: [
\"dune\" {>= \"2.3\"}
]
build: [
[\"dune\" \"subst\"] {pinned}
[
\"dune\"
\"build\"
\"-p\"
name
\"-j\"
jobs
\"@install\"
\"@runtest\" {with-test}
\"@doc\" {with-doc}
]
]
"))

0 comments on commit c38df3d

Please sign in to comment.