Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Global sandboxing setting #2213

Merged
merged 53 commits into from
Jul 29, 2019
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
55f2aaa
add sandbox_config types
aalekseyev May 28, 2019
c8c15d5
add sandboxing_preference to config file
aalekseyev May 28, 2019
541e81d
propagate config to the actual logic
aalekseyev May 28, 2019
e65d010
Annotate all the call sites that clearly rely on no-sandboxing.
aalekseyev May 28, 2019
535aea5
cli
aalekseyev May 29, 2019
3b02538
discovered another breakage with ocaml platform
aalekseyev May 29, 2019
66625d7
this bit seems unnecessary
aalekseyev Jul 23, 2019
081e4b2
changelog entry
aalekseyev May 29, 2019
61882e3
explore an idea: why not treat sandbox requirement as one of the depe…
aalekseyev Jul 19, 2019
0543de2
the parsing layer
aalekseyev Jul 22, 2019
d242a16
require dune 1.11 and update the changelog
aalekseyev Jul 22, 2019
f83d45c
test
aalekseyev Jul 22, 2019
52de199
fix bug
aalekseyev Jul 22, 2019
dd0f137
fix test
aalekseyev Jul 22, 2019
3b5f834
add to the test
aalekseyev Jul 22, 2019
bcff36f
test preserve_file_kind
aalekseyev Jul 22, 2019
67d0494
it's not clear what the solution is
aalekseyev Jul 22, 2019
6b0cd6e
fix alias stamp file dir sandboxing
aalekseyev Jul 23, 2019
5e6ba9c
sandbox aliases, fix some sandboxed actions
aalekseyev Jul 23, 2019
cbf17ea
introduce Sandbox_mode.Dict.t
aalekseyev Jul 23, 2019
76a8858
improve error message, and make code easier to follow
aalekseyev Jul 23, 2019
206b6df
remove no_sandboxing that will become unnecessary soon
aalekseyev Jul 23, 2019
77bf41e
too late for 1.11
aalekseyev Jul 23, 2019
85b4035
do not sandbox actions that have nothing to sandbox
aalekseyev Jul 23, 2019
5a67d1f
Merge remote-tracking branch 'origin/master' into global-sandboxing-s…
aalekseyev Jul 23, 2019
db7959a
swap changelog entries
aalekseyev Jul 23, 2019
b0c0251
Merge remote-tracking branch 'origin/master' into global-sandboxing-s…
aalekseyev Jul 24, 2019
b020446
fix tests
aalekseyev Jul 24, 2019
2f3a821
remove stale comment, remove seemingly unnecessary no_sandboxing anno…
aalekseyev Jul 24, 2019
daab63a
make promotion work with sandboxing
aalekseyev Jul 24, 2019
7ff667c
odoc seems fine now
aalekseyev Jul 24, 2019
1568d00
make copy_and_add_line_directive work well with sandboxing
aalekseyev Jul 24, 2019
3675518
add doc
aalekseyev Jul 24, 2019
7e43558
merge
aalekseyev Jul 24, 2019
16ea040
doc
jeremiedimino Jul 25, 2019
1d1da0c
Add missing .ml dependencies for expect tests
jeremiedimino Jul 25, 2019
2007786
Fix dependencies of inline tests
jeremiedimino Jul 25, 2019
8375ed2
better error if targets are missing when you move them from sandbox
aalekseyev Jul 25, 2019
af07f49
Merge branch 'global-sandboxing-setting' of github.com:aalekseyev/dun…
aalekseyev Jul 25, 2019
0c4a65e
Fix deps of ppx.exe
jeremiedimino Jul 25, 2019
e022e8a
Merge branch 'global-sandboxing-setting' of github.com:aalekseyev/dun…
aalekseyev Jul 25, 2019
b280639
doc
jeremiedimino Jul 25, 2019
32d280b
move archive_files handling to [Lib.Lib_and_module.link_flags]
aalekseyev Jul 25, 2019
56df7fa
fix another missing dependency
aalekseyev Jul 25, 2019
6b11a16
Merge branch 'global-sandboxing-setting' of github.com:aalekseyev/dun…
aalekseyev Jul 25, 2019
ca1d6cf
add DUNE_SANDBOX env var
aalekseyev Jul 25, 2019
0a9fd35
Remove unused ignore
jeremiedimino Jul 25, 2019
d8b2571
improve exception
aalekseyev Jul 25, 2019
149c59a
Merge branch 'global-sandboxing-setting' of github.com:aalekseyev/dun…
aalekseyev Jul 25, 2019
552f5b9
Merge remote-tracking branch 'origin/master' into global-sandboxing-s…
aalekseyev Jul 25, 2019
194ef81
merge
aalekseyev Jul 29, 2019
12ea213
credit jdimino
aalekseyev Jul 29, 2019
2740d9d
Merge remote-tracking branch 'origin/master' into global-sandboxing-s…
aalekseyev Jul 29, 2019
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
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
- Stop symlinking object files to main directory for stanzas defined `jbuild`
files (#2440, @rgrinerg)

- Add a new config option `sandboxing_preference`, the cli argument `--sandbox`,
and the dep spec `sandbox` in dune language. These let the user control the level of
sandboxing done by dune per rule and globally. The rule specification takes precedence.
The global configuration merely specifies the default.
(#2213, @aalekseyev)

1.11.0 (23/07/2019)
-------------------

Expand Down
27 changes: 27 additions & 0 deletions bin/common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,31 @@ let term =
& info ["j"] ~docs ~docv:"JOBS"
~doc:{|Run no more than $(i,JOBS) commands simultaneously.|}
)
and+ sandboxing_preference =
let arg =
Arg.conv
((fun s ->
Result.map_error (Dune.Sandbox_mode.of_string s)
~f:(fun s -> `Msg s)),
(fun pp x ->
Format.pp_print_string pp (Dune.Sandbox_mode.to_string x)))
in
Arg.(value
& opt (some arg) None
& info ["sandbox"]
~env:(
Arg.env_var
~doc:"Sandboxing mode to use by default. (see --sandbox)"
"DUNE_SANDBOX")
~doc:(
Printf.sprintf
"Sandboxing mode to use by default. Some actions require \
a certain sandboxing mode, so they will ignore this \
setting. The allowed values are: %s."
(String.concat ~sep: ", " (
List.map Dune.Sandbox_mode.all
~f:Dune.Sandbox_mode.to_string))
))
and+ debug_dep_path =
Arg.(value
& flag
Expand Down Expand Up @@ -462,6 +487,8 @@ let term =
Config.merge config
{ display
; concurrency
; sandboxing_preference =
Option.map sandboxing_preference ~f:(fun x -> [x])
}
in
let config =
Expand Down
1 change: 1 addition & 0 deletions bin/import.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ module Main = struct
let open Fiber.O in
scan_workspace ~log common
>>= init_build_system
~sandboxing_preference:(common.config.sandboxing_preference)
?external_lib_deps_mode
?only_packages:common.only_packages
end
Expand Down
1 change: 1 addition & 0 deletions bin/subst.ml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ let term =
let config : Config.t =
{ display = Quiet
; concurrency = Fixed 1
; sandboxing_preference = []
}
in
Path.set_root (Path.External.cwd ());
Expand Down
10 changes: 7 additions & 3 deletions doc/dune-files.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1413,8 +1413,7 @@ introduced in 4.08, allowing the user to define custom let operators.
Dependency specification
------------------------

Dependencies in ``dune`` files can be specified using one of the following
syntax:
Dependencies in ``dune`` files can be specified using one of the following:

- ``(:name <dependencies>)`` will bind the the list of dependencies to the
``name`` variable. This variable will be available as ``%{name}`` in actions.
Expand All @@ -1429,7 +1428,6 @@ syntax:
:ref:`glob <glob>` for details

.. _source_tree:

- ``(source_tree <dir>)``: depend on all source files in the subtree with root
``<dir>``

Expand All @@ -1445,6 +1443,12 @@ syntax:
- ``(env_var <var>)``: depend on the value of the environment variable ``<var>``.
If this variable becomes set, becomes unset, or changes value, the target
will be rebuilt.
- ``(sandbox <config>)``: require a particular sandboxing configuration.
Config can be one (or many) of:
- ``always``: the action requires a clean environment.
- ``none``: the action must run in the build directory.
- ``preserve_file_kind``: the action needs the files it reads to look
like normal files (so dune won't use symlinks for sandboxing)

In all these cases, the argument supports `Variables expansion`_.

Expand Down
2 changes: 1 addition & 1 deletion dune-project
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(lang dune 1.11)
(lang dune 1.12)
(name dune)

(implicit_transitive_deps false)
Expand Down
64 changes: 58 additions & 6 deletions src/action.ml
Original file line number Diff line number Diff line change
Expand Up @@ -173,33 +173,85 @@ let chdirs =
in
fun t -> loop Path.Set.empty t

let symlink_managed_paths sandboxed deps ~eval_pred =
let prepare_managed_paths ~link ~sandboxed deps ~eval_pred =
let steps =
Path.Set.fold (Dep.Set.paths deps ~eval_pred) ~init:[]
~f:(fun path acc ->
match Path.as_in_build_dir path with
| None ->
(* This can actually raise if we try to sandbox the "copy from
source dir" rules. There is no reason to do that though. *)
assert (not (Path.is_in_source_tree path));
acc
| Some p -> Symlink (path, sandboxed p) :: acc)
| Some p -> link path (sandboxed p) :: acc)
in
Progn steps

let link_function ~(mode : Sandbox_mode.some) : path -> target -> t =
match mode with
| Symlink ->
if Sys.win32 then
Code_error.raise
"Don't have symlinks on win32, but [Symlink] sandboxing \
mode was selected. To use emulation via copy, the [Copy] sandboxing \
mode should be selected." []
else
(fun a b -> Symlink (a, b))
| Copy ->
(fun a b -> Copy (a, b))

let maybe_sandbox_path f p =
match Path.as_in_build_dir p with
| None -> p
| Some p -> Path.build (f p)

let sandbox t ~sandboxed ~deps ~targets ~eval_pred : t =
let sandbox t ~sandboxed ~mode ~deps ~eval_pred : t =
let link = link_function ~mode in
Progn
[ symlink_managed_paths sandboxed deps ~eval_pred
[ prepare_managed_paths ~sandboxed ~link deps ~eval_pred
; map t
~dir:Path.root
~f_string:(fun ~dir:_ x -> x)
~f_path:(fun ~dir:_ p -> maybe_sandbox_path sandboxed p)
~f_target:(fun ~dir:_ -> sandboxed)
~f_program:(fun ~dir:_ ->
Result.map ~f:(maybe_sandbox_path sandboxed))
; Progn (List.filter_map targets ~f:(fun path ->
Some (Rename (sandboxed path, path))))
]

type is_useful_to_sandbox =
| Clearly_not
| Maybe

let is_useful_to_sandbox =
let rec loop t =
match t with
| Chdir (_, t) ->
loop t
| Setenv (_, _, t) ->
loop t
| Redirect (_, _, t) ->
loop t
| Ignore (_, t) ->
loop t
| Progn l -> List.exists l ~f:loop
| Echo _ -> false
| Cat _ -> false
| Copy _ -> false
| Symlink _ -> false
| Copy_and_add_line_directive _ -> false
| Write_file _ -> false
| Rename _ -> false
| Remove_tree _ -> false
| Diff _ -> false
| Mkdir _ -> false
| Digest_files _ -> false
| Merge_files_into _ -> false
| Run _ -> true
| System _ -> true
| Bash _ -> true
in
fun t -> match loop t with
| true ->
Maybe
| false ->
Clearly_not
12 changes: 10 additions & 2 deletions src/action.mli
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,19 @@ module Unresolved : sig
val resolve : t -> f:(Loc.t option -> string -> Path.t) -> action
end with type action := t

(** Return a sandboxed version of an action *)
(** Return a sandboxed version of an action.
It takes care of preparing deps in the sandbox, but it does not copy the
targets back out. It's the responsibility of the caller to do that. *)
val sandbox
: t
-> sandboxed:(Path.Build.t -> Path.Build.t)
-> mode:Sandbox_mode.some
-> deps:Dep.Set.t
-> targets:Path.Build.t list
-> eval_pred:Dep.eval_pred
-> t

type is_useful_to_sandbox =
| Clearly_not
| Maybe

val is_useful_to_sandbox : t -> is_useful_to_sandbox
12 changes: 7 additions & 5 deletions src/action_exec.ml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ let rec exec t ~ectx ~dir ~env ~stdout_to ~stderr_to =
Io.with_file_in src ~f:(fun ic ->
Path.build dst
|> Io.with_file_out ~f:(fun oc ->
let fn = Path.drop_optional_build_context src in
let fn = Path.drop_optional_build_context_maybe_sandboxed src in
output_string oc
(Utils.line_directive
~filename:(Path.to_string fn)
Expand Down Expand Up @@ -142,15 +142,17 @@ let rec exec t ~ectx ~dir ~env ~stdout_to ~stderr_to =
Fiber.return ()
else begin
let is_copied_from_source_tree file =
match Path.drop_build_context file with
match Path.extract_build_context_dir_maybe_sandboxed file with
| None -> false
| Some file -> Path.exists (Path.source file)
| Some (_, file) -> Path.exists (Path.source file)
in
if is_copied_from_source_tree file1 &&
not (is_copied_from_source_tree file2) then begin
Promotion.File.register
{ src = Path.as_in_build_dir_exn file2
; dst = Option.value_exn (Path.drop_build_context file1)
{ src = snd (Path.Build.split_sandbox_root (
Path.as_in_build_dir_exn file2))
; dst = snd (Option.value_exn (
Path.extract_build_context_dir_maybe_sandboxed file1))
}
end;
if mode = Binary then
Expand Down
11 changes: 7 additions & 4 deletions src/alias.ml
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,18 @@ let suffix = "-" ^ String.make 32 '0'
let name t = t.name
let dir t = t.dir

let fully_qualified_name t = Path.Build.relative t.dir t.name

(* Where we store stamp files for aliases *)
let alias_dir = Path.Build.(relative root ".aliases")

let stamp_file t =
let stamp_file_dir t =
let local = Path.Build.local t.dir in
Path.Build.append_local alias_dir local

let fully_qualified_name t = Path.Build.relative t.dir t.name

let stamp_file t =
Path.Build.relative
(Path.Build.append_local alias_dir local)
(stamp_file_dir t)
(t.name ^ suffix)

let find_dir_specified_on_command_line ~dir ~file_tree =
Expand Down
1 change: 1 addition & 0 deletions src/alias.mli
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ val make : string -> dir:Path.Build.t -> t
*)
val name : t -> string
val dir : t -> Path.Build.t
val stamp_file_dir : t -> Path.Build.t

val to_dyn : t -> Dyn.t

Expand Down
Loading