From 88d1f29257869b0de9369881236477163804125a Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Tue, 28 Apr 2015 22:36:44 -0500 Subject: use mustache instead of erlydtl for overlays --- src/rlx_prv_archive.erl | 3 +- src/rlx_prv_assembler.erl | 26 +++--- src/rlx_prv_overlay.erl | 208 +++++++++++++++++----------------------------- src/rlx_util.erl | 62 +++++++++++++- 4 files changed, 154 insertions(+), 145 deletions(-) (limited to 'src') diff --git a/src/rlx_prv_archive.erl b/src/rlx_prv_archive.erl index 3ed34f8..59fbdc2 100644 --- a/src/rlx_prv_archive.erl +++ b/src/rlx_prv_archive.erl @@ -144,8 +144,7 @@ overlay_files(_, undefined, _) -> overlay_files(OverlayVars, Overlay, OutputDir) -> [begin To = to(O), - ToTemplateName = rlx_prv_overlay:make_template_name("rlx_template_to_template", To), - File = rlx_prv_overlay:render_string(OverlayVars, To, ToTemplateName), + File = rlx_prv_overlay:render_string(OverlayVars, To), {ec_cnv:to_list(File), ec_cnv:to_list(filename:join(OutputDir, File))} end || O <- Overlay, filter(O)]. diff --git a/src/rlx_prv_assembler.erl b/src/rlx_prv_assembler.erl index 60cef76..5fa1817 100644 --- a/src/rlx_prv_assembler.erl +++ b/src/rlx_prv_assembler.erl @@ -545,20 +545,20 @@ ensure_not_exist(RelConfPath) -> end. erl_script(ErtsVsn) -> - render(erl_script_dtl, [{erts_vsn, ErtsVsn}]). + render(erl_script, [{erts_vsn, ErtsVsn}]). bin_file_contents(OsFamily, RelName, RelVsn, ErtsVsn, ErlOpts) -> Template = case OsFamily of - unix -> bin_dtl; - win32 -> bin_windows_dtl + unix -> bin; + win32 -> bin_windows end, render(Template, [{rel_name, RelName}, {rel_vsn, RelVsn}, {erts_vsn, ErtsVsn}, {erl_opts, ErlOpts}]). extended_bin_file_contents(OsFamily, RelName, RelVsn, ErtsVsn, ErlOpts) -> Template = case OsFamily of - unix -> extended_bin_dtl; - win32 -> extended_bin_windows_dtl + unix -> extended_bin; + win32 -> extended_bin_windows end, render(Template, [{rel_name, RelName}, {rel_vsn, RelVsn}, {erts_vsn, ErtsVsn}, {erl_opts, ErlOpts}]). @@ -566,23 +566,25 @@ extended_bin_file_contents(OsFamily, RelName, RelVsn, ErtsVsn, ErlOpts) -> erl_ini(OutputDir, ErtsVsn) -> ErtsDirName = string:concat("erts-", ErtsVsn), BinDir = filename:join([OutputDir, ErtsDirName, bin]), - render(erl_ini_dtl, [{bin_dir, BinDir}, {output_dir, OutputDir}]). + render(erl_ini, [{bin_dir, BinDir}, {output_dir, OutputDir}]). install_upgrade_escript_contents() -> - render(install_upgrade_escript_dtl). + render(install_upgrade_escript). nodetool_contents() -> - render(nodetool_dtl). + render(nodetool). sys_config_file() -> - render(sys_config_dtl). + render(sys_config). vm_args_file(RelName) -> - render(vm_args_dtl, [{rel_name, RelName}]). + render(vm_args, [{rel_name, RelName}]). render(Template) -> render(Template, []). render(Template, Data) -> - {ok, Rendered} = Template:render(Data), - Rendered. + Files = rlx_util:template_files(), + Tpl = rlx_util:load_file(Files, escript, atom_to_list(Template)), + {ok, Content} = rlx_util:render(Tpl, Data), + Content. diff --git a/src/rlx_prv_overlay.erl b/src/rlx_prv_overlay.erl index d9c409c..6c27b5c 100644 --- a/src/rlx_prv_overlay.erl +++ b/src/rlx_prv_overlay.erl @@ -29,13 +29,10 @@ format_error/1]). -export([generate_overlay_vars/2, - make_template_name/2, - render_string/3]). + render_string/2]). -define(DIRECTORY_RE, ".*(\/|\\\\)$"). --define(ERLYDTL_COMPILE_OPTS, [report_warnings, return_errors, {auto_escape, false}, {out_dir, false}]). - -include("relx.hrl"). -define(PROVIDER, overlay). @@ -64,7 +61,8 @@ do(State) -> {error, Reason} -> {error, Reason}; OverlayVars -> - do_overlay(State, OverlayVars) + Files = rlx_util:template_files(), + do_overlay(State, Files, OverlayVars) end; false -> ?RLX_ERROR({unresolved_release, RelName, RelVsn}) @@ -79,6 +77,9 @@ format_error({ec_file_error, AppDir, TargetDir, E}) -> format_error({unable_to_read_varsfile, FileName, Reason}) -> io_lib:format("Unable to read vars file (~s) for overlay due to: ~p", [FileName, Reason]); +format_error({read_template, FileName, Reason}) -> + io_lib:format("Unable to read template file (~s) for overlay due to: ~s", + [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}) -> @@ -183,8 +184,16 @@ merge_overlay_vars(State, FileNames) -> lists:foldl(fun(FileName, Acc) -> RelativePath = filename:join(RelativeRoot, erlang:iolist_to_binary(FileName)), case file:consult(RelativePath) of + %% {ok, [Terms]} -> + %% lists:ukeymerge(1, lists:ukeysort(1, Terms), Acc); + %% % the location of the included overlay files will be relative + %% %% to the current one being read + %% %% OverlayRelativeRoot = filename:dirname(FileName), + %% %% NewTerms = check_overlay_inclusion(State, OverlayRelativeRoot, Terms), + + %% %% lists:ukeymerge(1, lists:ukeysort(1, NewTerms), Acc); {ok, Terms} -> - % the location of the included overlay files will be relative + %% the location of the included overlay files will be relative %% to the current one being read OverlayRelativeRoot = filename:dirname(FileName), NewTerms = check_overlay_inclusion(State, OverlayRelativeRoot, Terms), @@ -237,26 +246,7 @@ generate_release_vars(Release) -> {release_erts_version, rlx_release:erts(Release)}, {release_name, rlx_release:name(Release)}, {rel_vsn, rlx_release:vsn(Release)}, - {release_version, rlx_release:vsn(Release)}, - {release_applications, lists:map(fun(App) -> - rlx_app_info:name(App) - end, rlx_release:application_details(Release))}, - {release, [generate_app_vars(App)|| App <- rlx_release:application_details(Release)]}, - {release_goals, [if - erlang:is_list(Constraint) -> - Constraint; - true -> - rlx_depsolver:format_constraint(Constraint) - end || Constraint <- rlx_release:goals(Release)]}]. - --spec generate_app_vars(rlx_app_info:t()) -> AppInfo::tuple(). -generate_app_vars(App) -> - {rlx_app_info:name(App), - [{version, rlx_app_info:original_vsn(App)}, - {dir, rlx_app_info:dir(App)}, - {active_dependencies, rlx_app_info:active_deps(App)}, - {library_dependencies, rlx_app_info:library_deps(App)}, - {link, rlx_app_info:link(App)}]}. + {release_version, rlx_release:vsn(Release)}]. -spec generate_state_vars(rlx_state:t()) -> proplists:proplist(). generate_state_vars(State) -> @@ -288,16 +278,16 @@ generate_state_vars(State) -> erlang:atom_to_list(Name1) ++ "-" ++ Vsn1 end}]. --spec do_overlay(rlx_state:t(), proplists:proplist()) -> +-spec do_overlay(rlx_state:t(), list(), proplists:proplist()) -> {ok, rlx_state:t()} | relx:error(). -do_overlay(State, OverlayVars) -> +do_overlay(State, Files, OverlayVars) -> case rlx_state:get(State, overlay, undefined) of undefined -> {ok, State}; Overlays -> handle_errors(State, lists:map(fun(Overlay) -> - do_individual_overlay(State, OverlayVars, + do_individual_overlay(State, Files, OverlayVars, Overlay) end, Overlays)) end. @@ -313,61 +303,49 @@ handle_errors(State, Result) -> {ok, State} end. --spec do_individual_overlay(rlx_state:t(), proplists:proplist(), +-spec do_individual_overlay(rlx_state:t(), list(), proplists:proplist(), OverlayDirective::term()) -> {ok, rlx_state:t()} | relx:error(). -do_individual_overlay(State, OverlayVars, {mkdir, Dir}) -> - ModuleName = make_template_name("rlx_mkdir_template", Dir), - case erlydtl:compile(erlang:iolist_to_binary(Dir), ModuleName, ?ERLYDTL_COMPILE_OPTS) of - {ok, ModuleName} -> - case render(ModuleName, 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; +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({dir_render_failed, Dir, Error}) + ?RLX_ERROR({unable_to_make_dir, Absolute, Error}); + ok -> + ok end; - {error, Reason, _Warnings} -> - ?RLX_ERROR({unable_to_compile_template, Dir, Reason}) + {error, Error} -> + ?RLX_ERROR({dir_render_failed, Dir, Error}) end; -do_individual_overlay(State, OverlayVars, {copy, From, To}) -> - FromTemplateName = make_template_name("rlx_copy_from_template", From), - ToTemplateName = make_template_name("rlx_copy_to_template", To), - file_render_do(OverlayVars, From, FromTemplateName, +do_individual_overlay(State, _Files, OverlayVars, {copy, From, To}) -> + file_render_do(OverlayVars, From, fun(FromFile) -> - file_render_do(OverlayVars, To, ToTemplateName, + file_render_do(OverlayVars, To, fun(ToFile) -> copy_to(State, FromFile, ToFile) end) end); -do_individual_overlay(State, OverlayVars, {link, From, To}) -> +do_individual_overlay(State, Files, OverlayVars, {link, From, To}) -> case rlx_state:dev_mode(State) of false -> - do_individual_overlay(State, OverlayVars, {copy, From, To}); + do_individual_overlay(State, Files, OverlayVars, {copy, From, To}); true -> - FromTemplateName = make_template_name("rlx_copy_from_template", From), - ToTemplateName = make_template_name("rlx_copy_to_template", To), - file_render_do(OverlayVars, From, FromTemplateName, + file_render_do(OverlayVars, From, fun(FromFile) -> - file_render_do(OverlayVars, To, ToTemplateName, + file_render_do(OverlayVars, To, fun(ToFile) -> link_to(State, FromFile, ToFile) end) end) end; -do_individual_overlay(State, OverlayVars, {template, From, To}) -> - FromTemplateName = make_template_name("rlx_template_from_template", From), - ToTemplateName = make_template_name("rlx_template_to_template", To), - file_render_do(OverlayVars, From, FromTemplateName, +do_individual_overlay(State, _Files, OverlayVars, {template, From, To}) -> + file_render_do(OverlayVars, From, fun(FromFile) -> - file_render_do(OverlayVars, To, ToTemplateName, + file_render_do(OverlayVars, To, fun(ToFile) -> RelativeRoot = get_relative_root(State), FromFile0 = absolutize(State, @@ -465,85 +443,55 @@ is_directory(ToFile0, ToFile1) -> -spec render_template(proplists:proplist(), iolist()) -> ok | relx:error(). render_template(OverlayVars, Data) -> - TemplateName = make_template_name("rlx_template_renderer", Data), - case erlydtl:compile(Data, TemplateName, ?ERLYDTL_COMPILE_OPTS) of - Good when Good =:= ok; Good =:= {ok, TemplateName} -> - case render(TemplateName, OverlayVars) of - {ok, IoData} -> - {ok, IoData}; - {error, Reason} -> - ?RLX_ERROR({unable_to_render_template, Data, Reason}) - end; - {error, Reason, _Warnings} -> - ?RLX_ERROR({unable_to_compile_template, Data, Reason}) + case rlx_util:render(Data, OverlayVars) of + {ok, IoData} -> + {ok, IoData}; + {error, Reason} -> + ?RLX_ERROR({unable_to_render_template, Data, Reason}) end. write_template(OverlayVars, FromFile, ToFile) -> - case render_template(OverlayVars, FromFile) of - {ok, IoData} -> - case filelib:ensure_dir(ToFile) of - ok -> - case file:write_file(ToFile, IoData) of + case file:read_file(FromFile) of + {ok, File} -> + case render_template(OverlayVars, File) of + {ok, IoData} -> + case filelib:ensure_dir(ToFile) of ok -> - {ok, FileInfo} = file:read_file_info(FromFile), - ok = file:write_file_info(ToFile, FileInfo), - ok; + case file:write_file(ToFile, IoData) of + ok -> + {ok, FileInfo} = file:read_file_info(FromFile), + ok = file:write_file_info(ToFile, FileInfo), + ok; + {error, Reason} -> + ?RLX_ERROR({unable_to_write, ToFile, Reason}) + end; {error, Reason} -> - ?RLX_ERROR({unable_to_write, ToFile, Reason}) + ?RLX_ERROR({unable_to_enclosing_dir, ToFile, Reason}) end; - {error, Reason} -> - ?RLX_ERROR({unable_to_enclosing_dir, ToFile, Reason}) + Error -> + Error end; - Error -> - Error + {error, Error} -> + ?RLX_ERROR({read_template, Error}) end. -render_string(OverlayVars, Data, TemplateName) -> - case erlydtl:compile(erlang:iolist_to_binary(Data), TemplateName, ?ERLYDTL_COMPILE_OPTS) of - {ok, TemplateName} -> - case render(TemplateName, OverlayVars) of - {ok, IoList} -> - erlang:iolist_to_binary(IoList); - {error, Error} -> - ?RLX_ERROR({render_failed, Data, Error}) - end; - {error, Reason, _Warnings} -> - ?RLX_ERROR({unable_to_compile_template, Data, Reason}) +render_string(OverlayVars, Data) -> + case rlx_util:render(Data, OverlayVars) of + {ok, IoList} -> + erlang:iolist_to_binary(IoList); + {error, Error} -> + ?RLX_ERROR({render_failed, Data, Error}) end. --spec file_render_do(proplists:proplist(), iolist(), module(), +-spec file_render_do(proplists:proplist(), iolist(), fun((term()) -> {ok, rlx_state:t()} | relx:error())) -> {ok, rlx_state:t()} | relx:error(). -file_render_do(OverlayVars, Data, TemplateName, NextAction) -> - case erlydtl:compile(erlang:iolist_to_binary(Data), TemplateName, ?ERLYDTL_COMPILE_OPTS) of - {ok, TemplateName} -> - case render(TemplateName, OverlayVars) of - {ok, IoList} -> - NextAction(IoList); - {error, Error} -> - ?RLX_ERROR({render_failed, Data, Error}) - end; - {error, Reason, _Warnings} -> - ?RLX_ERROR({unable_to_compile_template, Data, Reason}) - end. - --spec make_template_name(string(), term()) -> module(). -make_template_name(Base, Value) -> - %% Seed so we get different values each time - random:seed(os:timestamp()), - Hash = erlang:phash2(Value), - Ran = random:uniform(10000000), - erlang:list_to_atom(Base ++ "_" ++ - erlang:integer_to_list(Hash) ++ - "_" ++ erlang:integer_to_list(Ran)). - --spec render(module(), proplists:proplist()) -> {ok, iolist()} | {error, Reason::term()}. -render(ModuleName, OverlayVars) -> - try - ModuleName:render(OverlayVars) - catch - _:Reason -> - {error, Reason} +file_render_do(OverlayVars, File, NextAction) -> + case rlx_util:render(File, OverlayVars) of + {ok, IoList} -> + NextAction(IoList); + {error, Error} -> + ?RLX_ERROR({render_failed, File, Error}) end. absolutize(State, FileName) -> diff --git a/src/rlx_util.erl b/src/rlx_util.erl index 9c4dcc2..4639ffa 100644 --- a/src/rlx_util.erl +++ b/src/rlx_util.erl @@ -32,7 +32,12 @@ error_reason/1, indent/1, optional_to_string/1, - wildcard_paths/1]). + wildcard_paths/1, + render/1, + render/2, + load_file/3, + template_files/0, + escript_foldl/3]). -define(ONE_LEVEL_INDENT, " "). %%============================================================================ @@ -147,6 +152,61 @@ wildcard(Path) when is_list(Path) -> Paths -> Paths end. +render(Template) -> + render(Template, []). + +render(Template, Data) -> + {ok, mustache:render(ec_cnv:to_binary(Template), Data)}. + +load_file(Files, escript, Name) -> + {Name, Bin} = lists:keyfind(Name, 1, Files), + Bin; +load_file(_Files, file, Name) -> + {ok, Bin} = file:read_file(Name), + Bin. + +template_files() -> + find_priv_templates() ++ escript_files(). + +find_priv_templates() -> + Files = filelib:wildcard(filename:join([code:priv_dir(relx), "templates", "*"])), + lists:map(fun(File) -> + {ok, Bin} = file:read_file(File), + {filename:basename(File), Bin} + end, Files). + +%% Scan the current escript for available files +escript_files() -> + try + {ok, Files} = escript_foldl( + fun(Name, _, GetBin, Acc) -> + [{filename:basename(Name), GetBin()} | Acc] + end, [], filename:absname(escript:script_name())), + Files + catch + _:_ -> + [] + end. + +escript_foldl(Fun, Acc, File) -> + case escript:extract(File, [compile_source]) of + {ok, [_Shebang, _Comment, _EmuArgs, Body]} -> + case Body of + {source, BeamCode} -> + GetInfo = fun() -> file:read_file_info(File) end, + GetBin = fun() -> BeamCode end, + {ok, Fun(".", GetInfo, GetBin, Acc)}; + {beam, BeamCode} -> + GetInfo = fun() -> file:read_file_info(File) end, + GetBin = fun() -> BeamCode end, + {ok, Fun(".", GetInfo, GetBin, Acc)}; + {archive, ArchiveBin} -> + zip:foldl(Fun, Acc, {File, ArchiveBin}) + end; + {error, _} = Error -> + Error + end. + %%%=================================================================== %%% Test Functions %%%=================================================================== -- cgit v1.2.3