8000 fix: make copying sandbox files writeable by rgrinberg · Pull Request #8920 · ocaml/dune · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

fix: make copying sandbox files writeable #8920

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

Merged
merged 1 commit into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions doc/changes/8920.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Dependencies in the copying sandbox are now writeable (#8920, @rgrinberg)
79 changes: 57 additions & 22 deletions src/dune_engine/sandbox.ml
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,60 @@ type t =
let dir t = t.dir
let map_path t p = Path.Build.append t.dir p

let rec copy_recursively (src_kind : Unix.file_kind) ~src ~dst =
match src_kind with
| S_REG -> Io.copy_file ~src ~dst ()
| S_DIR ->
(match Path.Untracked.readdir_unsorted_with_kinds src with
| Error e -> Unix_error.Detailed.raise e
| Ok contents ->
Path.mkdir_p dst;
List.iter contents ~f:(fun (name, kind) ->
copy_recursively kind ~src:(Path.relative src name) ~dst:(Path.relative dst name)))
| _ ->
User_error.raise
~hints:
[ Pp.text "re-run dune to delete the stale artifact, or manually delete this file"
module Item = struct
type t =
| File
| Directory of { perms : int }
| Other of Unix.file_kind

let of_path path =
let { Unix.st_kind; st_perm; _ } = Path.Untracked.stat_exn path in
match st_kind with
| S_DIR -> Directory { perms = st_perm }
| S_REG -> File
| kind -> Other kind
;;

let of_kind path (kind : Unix.file_kind) =
match kind with
| S_DIR -> Directory { perms = (Path.Untracked.stat_exn path).st_perm }
| S_REG -> File
| _ -> Other kind
;;
end

let copy_recursively =
let chmod_file = Path.Permissions.add Path.Permissions.write in
let chmod_dir p =
Path.Permissions.add Path.Permissions.execute p
|> Path.Permissions.add Path.Permissions.write
in
let rec loop item ~src ~dst =
match (item : Item.t) with
| File -> Io.copy_file ~chmod:chmod_file ~src ~dst ()
| Directory { perms } ->
(match Path.Untracked.readdir_unsorted_with_kinds src with
| Error e -> Unix_error.Detailed.raise e
| Ok contents ->
let perms = chmod_dir perms in
Path.mkdir_p ~perms dst;
List.iter contents ~f:(fun (name, kind) ->
let src = Path.relative src name in
let item = Item.of_kind src kind in
loop item ~src ~dst:(Path.relative dst name)))
| Other kind ->
User_error.raise
~hints:
[ Pp.text
"Re-run Dune to delete the stale artifact, or manually delete this file"
]
[ Pp.textf
"Failed to copy file %s of kind %S while creating a copy sandbox"
(Path.to_string_maybe_quoted src)
(File_kind.to_string_hum kind)
]
[ Pp.textf
"Failed to copy file %s of kind %s while creating a copy sandbox"
(Path.to_string_maybe_quoted src)
(File_kind.to_string_hum src_kind)
]
in
loop
;;

let create_dirs t ~deps ~rule_dir =
Expand Down Expand Up @@ -90,15 +124,16 @@ let link_function ~(mode : Sandbox_mode.some) =
| false -> fun src dst -> Io.portable_symlink ~src ~dst)
| Copy ->
fun src dst ->
let { Unix.st_kind; _ } = Path.Untracked.stat_exn src in
copy_recursively st_kind ~src ~dst
let what = Item.of_path src in
copy_recursively what ~src ~dst
| Hardlink ->
(match Sys.win32 with
| true -> win32_error mode
| false -> fun src dst -> Io.portable_hardlink ~src ~dst)
| Patch_back_source_tree ->
(* We need to let the action modify its dependencies, so we copy
dependencies and make them writable. *)
(* CR-someday: this doesn't work with directory targets *)
let chmod = Path.Permissions.add Path.Permissions.write in
fun src dst -> Io.copy_file ~src ~dst ~chmod ())
;;
Expand Down Expand Up @@ -318,7 +353,7 @@ let move_targets_to_build_dir t ~loc ~should_be_skipped ~(targets : Targets.Vali
User_error.raise
~hints:hint_delete_dir
[ Pp.textf
"Target %s of kind %s already exists in the build directory"
"Target %s of kind %S already exists in the build directory"
(Path.Build.to_string_maybe_quoted target)
(File_kind.to_string_hum st_kind)
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ mode:
permissions of output/
755
permissions of output/y
444
644
permissions of output/x
444
644
permissions of output/subdir
755
754
permissions of output/subdir/z
444
644


$ ( cd _build/default && ../../print-permissions.sh )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ A faulty test escapes the sandbox by creating its target outside the sandbox
1 | (rule
2 | (target (dir foo))
3 | (action (system "mkdir $TESTCASE_ROOT/_build/default/foo && mkdir foo")))
Error: Target _build/default/foo of kind directory already exists in the
Error: Target _build/default/foo of kind "directory" already exists in the
build directory
Hint: delete this file manually or check the permissions of the parent
directory of this file
0