Skip to content

Commit

Permalink
Adds support for globs in dune-action-plugin.
Browse files Browse the repository at this point in the history
Signed-off-by: Jakub Staron <jstaron@janestreet.com>
  • Loading branch information
aalekseyev authored and staronj committed Sep 12, 2019
1 parent 16dbb98 commit d9c370e
Show file tree
Hide file tree
Showing 18 changed files with 162 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/dune/action_exec.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ module Dynamic_dep = struct
function
| File fn -> File (to_dune_path fn)
| Directory dir -> Glob (to_dune_path dir, Glob.universal)
| Glob { path; glob } ->
Glob (to_dune_path path, Glob.of_string_exn Loc.none glob)

let compare x y =
match (x, y) with
Expand Down
4 changes: 2 additions & 2 deletions src/dune/dune
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
(name dune)
(libraries unix stdune fiber incremental_cycles dag memo xdg dune_re
threads.posix opam_file_format dune_lang dune_manager dune_memory
ocaml_config catapult jbuild_support dune_action_plugin)
dune_glob_lexer ocaml_config catapult jbuild_support dune_action_plugin)
(synopsis "Internal Dune library, do not use!")
(preprocess future_syntax))

(ocamllex glob_lexer dune_lexer ocamlobjinfo)
(ocamllex dune_lexer ocamlobjinfo)

(rule
(targets setup.ml)
Expand Down
2 changes: 1 addition & 1 deletion src/dune/glob.ml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let hash t = String.hash t.repr
let to_dyn t = Dyn.Encoder.string t.repr

let of_string repr =
Glob_lexer.parse_string repr
Dune_glob_lexer.parse_string repr
|> Result.map ~f:(fun re -> { re = Re.compile re; repr })

let of_string_exn loc repr =
Expand Down
2 changes: 1 addition & 1 deletion src/dune_action_plugin/dune
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(library
(name dune_action_plugin)
(public_name dune._dune_action_plugin)
(libraries stdune)
(libraries stdune dune_re dune_glob_lexer)
(synopsis
"Monadic interface for defining scripts with dynamic or complex set of depencencies."))
14 changes: 14 additions & 0 deletions src/dune_action_plugin/dune_action_plugin.ml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module Path = Path
module Glob = Glob
open Protocol

module Execution_error = struct
Expand Down Expand Up @@ -123,6 +124,19 @@ let read_directory ~path =
; targets = Stdune.String.Set.empty
}

let read_directory_with_glob ~path ~glob =
let path = Path.to_string path in
let action () =
Fs.read_directory path |> Execution_error.raise_on_fs_error
|> List.filter (Glob.test glob)
in
lift_stage
{ action
; dependencies =
Dependency.Set.singleton (Glob { path; glob = Glob.to_string glob })
; targets = Stdune.String.Set.empty
}

let rec run_by_dune t context =
match t with
| Pure () -> Context.respond context Done
Expand Down
6 changes: 6 additions & 0 deletions src/dune_action_plugin/dune_action_plugin.mli
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
[stage] to discourage people from overusing it. *)

module Path = Path
module Glob = Glob

type 'a t

Expand Down Expand Up @@ -63,6 +64,11 @@ val write_file : path:Path.t -> data:string -> unit t
directory. Computation will result in a directory listing. *)
val read_directory : path:Path.t -> string list t

(** [read_directory_with_glob ~path:directory ~glob] returns a computation
depending on a listing of a [directory] filtered by glob and resulting in
that listing. *)
val read_directory_with_glob : path:Path.t -> glob:Glob.t -> string list t

(** {1:running Running the computation} *)

(** Runs the computation. This function never returns. *)
Expand Down
19 changes: 19 additions & 0 deletions src/dune_action_plugin/glob.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
open Stdune

type t =
{ re : Dune_re.re
; repr : string
}

let test t = Dune_re.execp t.re

let of_string repr =
let result =
Dune_glob_lexer.parse_string repr
|> Result.map ~f:(fun re -> { re = Dune_re.compile re; repr })
in
match result with
| Error (_, msg) -> invalid_arg (Printf.sprintf "invalid glob: :%s" msg)
| Ok t -> t

let to_string (t : t) = t.repr
13 changes: 13 additions & 0 deletions src/dune_action_plugin/glob.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
(** Simple glob support library. *)

type t

(** Tests if string matches the glob. *)
val test : t -> string -> bool

(** Returns textual representation of a glob. *)
val to_string : t -> string

(** Converts string to glob. Throws [Invalid_argument] exception if string is
not a valid glob. *)
val of_string : string -> t
14 changes: 14 additions & 0 deletions src/dune_action_plugin/protocol.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,21 @@ module Dependency = struct
type t =
| File of string
| Directory of string
| Glob of
{ path : string
; glob : string
}

let sexp_of_t : _ -> Sexp.t = function
| File path -> List [ Atom "file"; Atom path ]
| Directory path -> List [ Atom "directory"; Atom path ]
| Glob { path; glob } -> List [ Atom "glob"; Atom path; Atom glob ]

let t_of_sexp : Sexp.t -> _ = function
| List [ Atom "file"; Atom path ] -> Some (File path)
| List [ Atom "directory"; Atom path ] -> Some (Directory path)
| List [ Atom "glob"; Atom path; Atom glob ] ->
Some (Glob { path; glob })
| _ -> None

let compare x y =
Expand All @@ -35,6 +42,13 @@ module Dependency = struct
| File _, _ -> Lt
| _, File _ -> Gt
| Directory x, Directory y -> String.compare x y
| Directory _, _ -> Lt
| _, Directory _ -> Gt
| ( Glob { path = path1; glob = glob1 }
, Glob { path = path2; glob = glob2 } ) -> (
match String.compare path1 path2 with
| Eq -> String.compare glob1 glob2
| not_eq -> not_eq )

let to_dyn _ = Dyn.opaque
end
Expand Down
4 changes: 4 additions & 0 deletions src/dune_action_plugin/protocol.mli
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ module Dependency : sig
type t =
| File of string
| Directory of string
| Glob of
{ path : string
; glob : string
}

include Sexpable with type t := t

Expand Down
8 changes: 8 additions & 0 deletions src/dune_glob_lexer/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
(library
(name dune_glob_lexer)
(public_name dune._dune_glob_lexer)
(flags (:standard -w -50))
(synopsis "Internal Dune library, do not use!")
(libraries stdune dune_re))

(ocamllex dune_glob_lexer)
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(executables
(names foo)
(libraries dune_action_plugin))
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
open Dune_action_plugin

let action =
let open Dune_action_plugin.O in
let glob = Glob.of_string "some_file*" in
let+ listing =
read_directory_with_glob ~path:(Path.of_string "some_dir") ~glob
in
String.concat "\n" listing |> print_endline

let () = run action
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
(data_only_dirs test)

(alias
(name run_dynamic)
(deps
(package dune)
(source_tree test/)
(glob_files bin/*.exe))
(action
(chdir
test
(progn
(run %{bin:cram} -test run.t)
(diff? run.t run.t.corrected)))))

(alias
(name runtest)
(deps
(alias run_dynamic)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
$ echo "(lang dune 2.0)" > dune-project

$ cat > dune << EOF
> (alias
> (name runtest)
> (action (dynamic-run ./foo.exe)))
> EOF

$ mkdir some_dir

$ cat > some_dir/dune << EOF
> (rule
> (target some_file)
> (action
> (progn
> (echo "Building some_file!\n")
> (with-stdout-to %{target} (echo "")))))
> \
> (rule
> (target another_file)
> (action
> (progn
> (echo "SHOULD NOT BE PRINTED!")
> (with-stdout-to %{target} (echo "")))))
> \
> (rule
> (target some_file_but_different)
> (action
> (progn
> (echo "Building some_file_but_different!\n")
> (with-stdout-to %{target} (echo "")))))
> EOF

$ cp ../bin/foo.exe ./

$ dune runtest --display short
foo alias runtest
Building some_file!
Building some_file_but_different!
foo alias runtest
some_file
some_file_but_different
5 changes: 3 additions & 2 deletions vendor/re/src/dune
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(library
(name dune_re)
(flags (:standard -w -50))
(name dune_re)
(public_name dune._dune_re)
(flags (:standard -w -50))
(synopsis "Internal Dune library, do not use!"))

(rule (with-stdout-to dune_re.ml (echo "include Re")))

0 comments on commit d9c370e

Please sign in to comment.