From eab72217378e06711d3b825944a1f5b0d0f29f95 Mon Sep 17 00:00:00 2001 From: AlexSedov Date: Fri, 27 Jul 2018 15:19:11 +0300 Subject: Support wildcards for copy/link to a directory. Additionally, removes a lot of unnecessary conversions to binary in relx_prv_overlay (binary and string in Erlang are two different beasts for filenames), and factors out some common code. --- src/rlx_prv_overlay.erl | 148 +++++++++++++++++++--------------------- test/rlx_extended_bin_SUITE.erl | 5 +- test/rlx_release_SUITE.erl | 2 +- 3 files changed, 71 insertions(+), 84 deletions(-) diff --git a/src/rlx_prv_overlay.erl b/src/rlx_prv_overlay.erl index 645f691..33648d7 100644 --- a/src/rlx_prv_overlay.erl +++ b/src/rlx_prv_overlay.erl @@ -82,9 +82,6 @@ format_error({read_template, FileName, Reason}) -> [FileName, file:format_error(Reason)]); format_error({overlay_failed, Errors}) -> [[format_error(rlx_util:error_reason(Error)), "\n"] || Error <- Errors]; -format_error({dir_render_failed, Dir, Error}) -> - io_lib:format("rendering mkdir path failed ~s with ~p", - [Dir, Error]); format_error({unable_to_make_symlink, AppDir, TargetDir, Reason}) -> io_lib:format("Unable to symlink directory ~s to ~s because \n~s~s", [AppDir, TargetDir, rlx_util:indent(2), @@ -317,14 +314,12 @@ do_individual_overlay(State, _Files, OverlayVars, {chmod, Mode, Path}) -> NewMode = case is_integer(Mode) of true -> Mode; - false -> erlang:list_to_integer(erlang:binary_to_list(render_string (OverlayVars, Mode))) + false -> erlang:binary_to_integer(render_string (OverlayVars, Mode)) end, - Root = rlx_state:output_dir(State), file_render_do(OverlayVars, Path, fun(NewPath) -> - Absolute = absolutize(State, - filename:join(Root,erlang:iolist_to_binary (NewPath))), + Absolute = absolute_path_to(State, NewPath), case file:change_mode(Absolute, NewMode) of {error, Error} -> ?RLX_ERROR({unable_to_chmod, NewMode, NewPath, Error}); @@ -332,20 +327,16 @@ do_individual_overlay(State, _Files, OverlayVars, {chmod, Mode, Path}) -> end end); do_individual_overlay(State, _Files, OverlayVars, {mkdir, Dir}) -> - case rlx_util:render(erlang:iolist_to_binary(Dir), OverlayVars) of - {ok, IoList} -> - Absolute = absolutize(State, - filename:join(rlx_state:output_dir(State), - erlang:iolist_to_binary(IoList))), - case rlx_util:mkdir_p(Absolute) of - {error, Error} -> - ?RLX_ERROR({unable_to_make_dir, Absolute, Error}); - ok -> - ok - end; - {error, Error} -> - ?RLX_ERROR({dir_render_failed, Dir, Error}) - end; + file_render_do(OverlayVars, Dir, + fun(Dir0) -> + Absolute = absolute_path_to(State, Dir0), + case rlx_util:mkdir_p(Absolute) of + {error, Error} -> + ?RLX_ERROR({unable_to_make_dir, Absolute, Error}); + ok -> + ok + end + end); do_individual_overlay(State, _Files, OverlayVars, {copy, From, To}) -> file_render_do(OverlayVars, From, fun(FromFile) -> @@ -372,73 +363,64 @@ do_individual_overlay(State, _Files, OverlayVars, {template, From, To}) -> fun(FromFile) -> file_render_do(OverlayVars, To, fun(ToFile) -> - RelativeRoot = get_relative_root(State), - FromFile0 = absolutize(State, - filename:join(RelativeRoot, - erlang:iolist_to_binary(FromFile))), - FromFile1 = erlang:binary_to_list(FromFile0), write_template(OverlayVars, - FromFile1, - absolutize(State, - filename:join(rlx_state:output_dir(State), - erlang:iolist_to_binary(ToFile)))) + absolute_path_from(State, FromFile), + absolute_path_to(State, ToFile)) end) end). --spec copy_to(rlx_state:t(), file:name(), file:name()) -> ok | relx:error(). -copy_to(State, FromFile0, ToFile0) -> - RelativeRoot = get_relative_root(State), - ToFile1 = absolutize(State, filename:join(rlx_state:output_dir(State), - erlang:iolist_to_binary(ToFile0))), - - FromFile1 = absolutize(State, filename:join(RelativeRoot, - erlang:iolist_to_binary(FromFile0))), - ToFile2 = case is_directory(ToFile0, ToFile1) of - false -> - filelib:ensure_dir(ToFile1), - ToFile1; - true -> - rlx_util:mkdir_p(ToFile1), - erlang:iolist_to_binary(filename:join(ToFile1, - filename:basename(FromFile1))) - end, - case ec_file:copy(FromFile1, ToFile2, [recursive, {file_info, [mode, time]}]) of +-spec wildcard_copy(rlx_state:t(), file:filename_all(), file:filename_all(), + fun((file:filename_all(), file:filename_all()) -> ok | {error, term()}), + ErrorTag :: atom()) -> ok | relx:error(). +wildcard_copy(State, FromFile0, ToFile0, CopyFun, ErrorTag) -> + FromFile1 = absolute_path_from(State, FromFile0), + ToFile1 = absolute_path_to(State, ToFile0), + + Res = case is_directory(ToFile0, ToFile1) of + false -> + filelib:ensure_dir(ToFile1), + CopyFun(FromFile1, ToFile1); + true -> + FromFiles = if + is_list(FromFile1) -> filelib:wildcard(FromFile1); + true -> [FromFile1] + end, + rlx_util:mkdir_p(ToFile1), + lists:foldl(fun + (_, {error, _} = Error) -> Error; + (FromFile, ok) -> + CopyFun(FromFile, filename:join(ToFile1, filename:basename(FromFile))) + end, ok, FromFiles) + end, + + case Res of ok -> ok; {error, Err} -> - ?RLX_ERROR({copy_failed, + ?RLX_ERROR({ErrorTag, FromFile1, ToFile1, Err}) end. + +-spec copy_to(rlx_state:t(), file:name(), file:name()) -> ok | relx:error(). +copy_to(State, FromFile0, ToFile0) -> + wildcard_copy(State, FromFile0, ToFile0, + fun(FromPath, ToPath) -> ec_file:copy(FromPath, ToPath, [recursive, {file_info, [mode, time]}]) end, + copy_failed). + -spec link_to(rlx_state:t(), file:name(), file:name()) -> ok | relx:error(). link_to(State, FromFile0, ToFile0) -> - RelativeRoot = get_relative_root(State), - ToFile1 = absolutize(State, filename:join(rlx_state:output_dir(State), - erlang:iolist_to_binary(ToFile0))), - - FromFile1 = absolutize(State, filename:join(RelativeRoot, - erlang:iolist_to_binary(FromFile0))), - ToFile2 = case is_directory(ToFile0, ToFile1) of - false -> - filelib:ensure_dir(ToFile1), - ToFile1; - true -> - rlx_util:mkdir_p(ToFile1), - erlang:iolist_to_binary(filename:join(ToFile1, - filename:basename(FromFile1))) - end, - case ec_file:is_symlink(ToFile2) of - true -> file:delete(ToFile2); - false -> ec_file:remove(ToFile2, [recursive]) + wildcard_copy(State, FromFile0, ToFile0, + fun make_link/2, + link_failed). + +make_link(FromFile, ToFile) -> + case ec_file:is_symlink(ToFile) of + true -> file:delete(ToFile); + false -> ec_file:remove(ToFile, [recursive]) end, - case file:make_symlink(FromFile1, ToFile2) of - ok -> ok; - {error, Err} -> - ?RLX_ERROR({link_failed, - FromFile1, - ToFile1, Err}) - end. + file:make_symlink(FromFile, ToFile). get_relative_root(State) -> case rlx_state:config_file(State) of @@ -453,6 +435,12 @@ get_relative_root(State) -> end end. +absolute_path_from(State, Path) -> + absolutize(State, filename:join(get_relative_root(State), Path)). + +absolute_path_to(State, Path) -> + absolutize(State, filename:join(rlx_state:output_dir(State), Path)). + -spec is_directory(file:name(), file:name()) -> boolean(). is_directory(ToFile0, ToFile1) -> case re:run(ToFile0, ?DIRECTORY_RE) of @@ -517,16 +505,18 @@ render_string(OverlayVars, Data) -> end. -spec file_render_do(proplists:proplist(), iolist(), - fun((term()) -> {ok, rlx_state:t()} | relx:error())) -> + fun((string() | binary()) -> {ok, rlx_state:t()} | relx:error())) -> {ok, rlx_state:t()} | relx:error(). file_render_do(OverlayVars, File, NextAction) -> + io:format("render ~p~n", [File]), case rlx_util:render(File, OverlayVars) of - {ok, IoList} -> - NextAction(IoList); + {ok, Binary} when is_binary(File) -> + NextAction(Binary); + {ok, Binary} when is_list(File) -> + NextAction(binary_to_list(Binary)); {error, Error} -> ?RLX_ERROR({render_failed, File, Error}) end. absolutize(State, FileName) -> - filename:absname(filename:join(rlx_state:root_dir(State), - erlang:iolist_to_binary(FileName))). + filename:absname(filename:join(rlx_state:root_dir(State), FileName)). diff --git a/test/rlx_extended_bin_SUITE.erl b/test/rlx_extended_bin_SUITE.erl index 86a9d23..d8e74f2 100644 --- a/test/rlx_extended_bin_SUITE.erl +++ b/test/rlx_extended_bin_SUITE.erl @@ -1294,10 +1294,7 @@ custom_start_script_hooks(Config) -> ]} ]}, {mkdir, "scripts"}, - {overlay, [{copy, "./pre_start", "bin/hooks/pre_start"}, - {copy, "./post_start", "bin/hooks/post_start"}, - {copy, "./pre_stop", "bin/hooks/pre_stop"}, - {copy, "./post_stop", "bin/hooks/post_stop"}]} + {overlay, [{copy, "./{pre,post}_{start,stop}", "bin/hooks/"}]} ]), %% write the hook scripts, each of them will write an erlang term to a file diff --git a/test/rlx_release_SUITE.erl b/test/rlx_release_SUITE.erl index affc0ad..eca5f78 100644 --- a/test/rlx_release_SUITE.erl +++ b/test/rlx_release_SUITE.erl @@ -669,7 +669,7 @@ overlay_release(Config) -> {overlay, [{mkdir, "{{target_dir}}/fooo"}, {copy, OverlayVars1, "{{target_dir}}/{{foo_dir}}/vars1.config"}, - {copy, OverlayVars1, + {copy, filename:join([LibDir1, "vars1*.config"]), "{{target_dir}}/{{yahoo}}/"}, {link, OverlayVars4, "{{target_dir}}/{{yahoo}}/vars4.config"}, -- cgit v1.2.3 From d2d3608047d86d093d7fe5bb093ae0d54777e374 Mon Sep 17 00:00:00 2001 From: Alex Es Date: Sat, 28 Jul 2018 09:08:01 +0300 Subject: More careful handling of source root. `from' directory should be excluded from the mask to avoid accidental expansion. --- src/rlx_prv_overlay.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/rlx_prv_overlay.erl b/src/rlx_prv_overlay.erl index 33648d7..59d0d8d 100644 --- a/src/rlx_prv_overlay.erl +++ b/src/rlx_prv_overlay.erl @@ -381,15 +381,16 @@ wildcard_copy(State, FromFile0, ToFile0, CopyFun, ErrorTag) -> filelib:ensure_dir(ToFile1), CopyFun(FromFile1, ToFile1); true -> + Root = absolute_path_from(Root), FromFiles = if - is_list(FromFile1) -> filelib:wildcard(FromFile1); + is_list(FromFile0) -> filelib:wildcard(FromFile0, Root); true -> [FromFile1] end, rlx_util:mkdir_p(ToFile1), lists:foldl(fun (_, {error, _} = Error) -> Error; (FromFile, ok) -> - CopyFun(FromFile, filename:join(ToFile1, filename:basename(FromFile))) + CopyFun(filename:join(Root, FromFile), filename:join(ToFile1, filename:basename(FromFile))) end, ok, FromFiles) end, -- cgit v1.2.3 From 69e196188d09c4dee48f274c7c7e2ee62b72fcdb Mon Sep 17 00:00:00 2001 From: Alex Es Date: Sat, 28 Jul 2018 09:11:23 +0300 Subject: Typo fix. --- src/rlx_prv_overlay.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rlx_prv_overlay.erl b/src/rlx_prv_overlay.erl index 59d0d8d..d4edb15 100644 --- a/src/rlx_prv_overlay.erl +++ b/src/rlx_prv_overlay.erl @@ -381,7 +381,7 @@ wildcard_copy(State, FromFile0, ToFile0, CopyFun, ErrorTag) -> filelib:ensure_dir(ToFile1), CopyFun(FromFile1, ToFile1); true -> - Root = absolute_path_from(Root), + Root = absolute_path_from("."), FromFiles = if is_list(FromFile0) -> filelib:wildcard(FromFile0, Root); true -> [FromFile1] -- cgit v1.2.3 From fcc0fa766606fec55c201ba96cf3d3aa3a0937ca Mon Sep 17 00:00:00 2001 From: Alex Es Date: Sat, 28 Jul 2018 09:23:13 +0300 Subject: I should really have some sleep, and probably not use GitHub Editor. --- src/rlx_prv_overlay.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rlx_prv_overlay.erl b/src/rlx_prv_overlay.erl index d4edb15..92ff69f 100644 --- a/src/rlx_prv_overlay.erl +++ b/src/rlx_prv_overlay.erl @@ -381,7 +381,7 @@ wildcard_copy(State, FromFile0, ToFile0, CopyFun, ErrorTag) -> filelib:ensure_dir(ToFile1), CopyFun(FromFile1, ToFile1); true -> - Root = absolute_path_from("."), + Root = absolute_path_from(State, "."), FromFiles = if is_list(FromFile0) -> filelib:wildcard(FromFile0, Root); true -> [FromFile1] -- cgit v1.2.3