aboutsummaryrefslogtreecommitdiffstats
path: root/src/rcl_prv_overlay.erl
diff options
context:
space:
mode:
authorTristan Sloughter <[email protected]>2013-01-05 11:09:18 -0800
committerTristan Sloughter <[email protected]>2013-01-05 11:09:18 -0800
commit1a43e62a5ee0ceafb2082a41e632489b48e7f567 (patch)
tree106c5822d41a2410830b4049993e1a9792e70900 /src/rcl_prv_overlay.erl
parented855acb2246aaa05d2fab628e1e09d1082b06a8 (diff)
parentf1632c3282d719cd5cbb46299f4f0557653ba50f (diff)
downloadrelx-1a43e62a5ee0ceafb2082a41e632489b48e7f567.tar.gz
relx-1a43e62a5ee0ceafb2082a41e632489b48e7f567.tar.bz2
relx-1a43e62a5ee0ceafb2082a41e632489b48e7f567.zip
Merge pull request #20 from ericbmerritt/next
overlay directory support
Diffstat (limited to 'src/rcl_prv_overlay.erl')
-rw-r--r--src/rcl_prv_overlay.erl202
1 files changed, 148 insertions, 54 deletions
diff --git a/src/rcl_prv_overlay.erl b/src/rcl_prv_overlay.erl
index af914ee..94b5f3d 100644
--- a/src/rcl_prv_overlay.erl
+++ b/src/rcl_prv_overlay.erl
@@ -28,6 +28,8 @@
do/1,
format_error/1]).
+-define(DIRECTORY_RE, ".*(\/|\\\\)$").
+
-include_lib("relcool/include/relcool.hrl").
%%============================================================================
@@ -110,13 +112,55 @@ get_overlay_vars_from_file(State, OverlayVars) ->
-spec read_overlay_vars(rcl_state:t(), proplists:proplist(), file:name()) ->
{ok, rcl_state:t()} | relcool:error().
read_overlay_vars(State, OverlayVars, FileName) ->
- case file:consult(FileName) of
+ RelativeRoot = get_relative_root(State),
+ RelativePath = filename:join(RelativeRoot, erlang:iolist_to_binary(FileName)),
+ case file:consult(RelativePath) of
{ok, Terms} ->
- do_overlay(State, OverlayVars ++ Terms);
+ case render_overlay_vars(OverlayVars, Terms, []) of
+ {ok, NewTerms} ->
+ do_overlay(State, NewTerms ++ OverlayVars);
+ Error ->
+ Error
+ end;
{error, Reason} ->
?RCL_ERROR({unable_to_read_varsfile, FileName, Reason})
end.
+-spec render_overlay_vars(proplists:proplist(), proplists:proplist(),
+ proplists:proplist()) ->
+ {ok, proplists:proplist()} | relcool:error().
+render_overlay_vars(OverlayVars, [{Key, Value} | Rest], Acc)
+ when erlang:is_list(Value) ->
+ case io_lib:printable_list(Value) of
+ true ->
+ case render_template(Acc ++ OverlayVars, erlang:iolist_to_binary(Value)) of
+ {ok, Data} ->
+ %% Adding to the end sucks, but ordering needs to be retained
+ render_overlay_vars(OverlayVars, Rest, Acc ++ [{Key, Data}]);
+ Error ->
+ Error
+ end;
+ false ->
+ case render_overlay_vars(Acc ++ OverlayVars, Value, []) of
+ {ok, NewValue} ->
+ render_overlay_vars(OverlayVars, Rest, Acc ++ [{Key, NewValue}]);
+ Error ->
+ Error
+ end
+ end;
+render_overlay_vars(OverlayVars, [{Key, Value} | Rest], Acc)
+ when erlang:is_binary(Value) ->
+ case render_template(Acc ++ OverlayVars, erlang:iolist_to_binary(Value)) of
+ {ok, Data} ->
+ render_overlay_vars(OverlayVars, Rest, Acc ++ [{Key, erlang:iolist_to_binary(Data)}]);
+ Error ->
+ Error
+ end;
+render_overlay_vars(OverlayVars, [KeyValue | Rest], Acc) ->
+ render_overlay_vars(OverlayVars, Rest, Acc ++ [KeyValue]);
+render_overlay_vars(_OverlayVars, [], Acc) ->
+ {ok, Acc}.
+
-spec generate_release_vars(rcl_release:t()) -> proplists:proplist().
generate_release_vars(Release) ->
[{erts_vsn, rcl_release:erts(Release)},
@@ -154,7 +198,7 @@ generate_state_vars(State) ->
{goals, [rcl_depsolver:format_constraint(Constraint) ||
Constraint <- rcl_state:goals(State)]},
{lib_dirs, rcl_state:lib_dirs(State)},
- {config_files, rcl_state:config_files(State)},
+ {config_file, rcl_state:config_file(State)},
{providers, rcl_state:providers(State)},
{sys_config, rcl_state:sys_config(State)},
{root_dir, rcl_state:root_dir(State)},
@@ -181,13 +225,10 @@ do_overlay(State, OverlayVars) ->
{ok, State};
Overlays ->
handle_errors(State,
- ec_plists:map(fun(Overlay) ->
- io:format("--->Doing ~p~n", [Overlay]),
- Res = do_individual_overlay(State, OverlayVars,
- Overlay),
- io:format("-->Done ~p~n", [Overlay]),
- Res
- end, Overlays))
+ lists:map(fun(Overlay) ->
+ do_individual_overlay(State, OverlayVars,
+ Overlay)
+ end, Overlays))
end.
-spec handle_errors(rcl_state:t(), [ok | relcool:error()]) ->
@@ -206,16 +247,13 @@ handle_errors(State, Result) ->
{ok, rcl_state:t()} | relcool:error().
do_individual_overlay(State, OverlayVars, {mkdir, Dir}) ->
ModuleName = make_template_name("rcl_mkdir_template", Dir),
- io:format("compiling to ~p ~n", [ModuleName]),
case erlydtl:compile(erlang:iolist_to_binary(Dir), ModuleName) of
{ok, ModuleName} ->
- io:format("compiled ~n"),
case render(ModuleName, OverlayVars) of
{ok, IoList} ->
- io:format("rendered ~n"),
- Absolute = filename:absname(filename:join(rcl_state:root_dir(State),
- erlang:iolist_to_binary(IoList))),
- io:format("got ~p ~n", [Absolute]),
+ Absolute = absolutize(State,
+ filename:join(rcl_state:output_dir(State),
+ erlang:iolist_to_binary(IoList))),
case rcl_util:mkdir_p(Absolute) of
{error, Error} ->
?RCL_ERROR({unable_to_make_dir, Absolute, Error});
@@ -231,72 +269,124 @@ do_individual_overlay(State, OverlayVars, {mkdir, Dir}) ->
do_individual_overlay(State, OverlayVars, {copy, From, To}) ->
FromTemplateName = make_template_name("rcl_copy_from_template", From),
ToTemplateName = make_template_name("rcl_copy_to_template", To),
- file_render_do(State, OverlayVars, From, FromTemplateName,
+ file_render_do(OverlayVars, From, FromTemplateName,
fun(FromFile) ->
- file_render_do(State, OverlayVars, To, ToTemplateName,
+ file_render_do(OverlayVars, To, ToTemplateName,
fun(ToFile) ->
- filelib:ensure_dir(ToFile),
- case ec_file:copy(FromFile, ToFile) of
- ok ->
- ok;
- {error, Err} ->
- ?RCL_ERROR({copy_failed,
- FromFile,
- ToFile, Err})
- end
+ copy_to(State, FromFile, ToFile)
end)
end);
do_individual_overlay(State, OverlayVars, {template, From, To}) ->
FromTemplateName = make_template_name("rcl_template_from_template", From),
ToTemplateName = make_template_name("rcl_template_to_template", To),
- file_render_do(State, OverlayVars, From, FromTemplateName,
+ file_render_do(OverlayVars, From, FromTemplateName,
fun(FromFile) ->
- file_render_do(State, OverlayVars, To, ToTemplateName,
+ file_render_do(OverlayVars, To, ToTemplateName,
fun(ToFile) ->
- render_template(OverlayVars,
- erlang:binary_to_list(FromFile),
- 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(rcl_state:output_dir(State),
+ erlang:iolist_to_binary(ToFile))))
end)
end).
--spec render_template(proplists:proplist(), iolist(), file:name()) ->
+-spec copy_to(rcl_state:t(), file:name(), file:name()) -> ok | relcool:error().
+copy_to(State, FromFile0, ToFile0) ->
+ RelativeRoot = get_relative_root(State),
+ ToFile1 = absolutize(State, filename:join(rcl_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 ->
+ rcl_util:mkdir_p(ToFile1),
+ erlang:iolist_to_binary(filename:join(ToFile1,
+ filename:basename(FromFile1)))
+ end,
+ case ec_file:copy(FromFile1, ToFile2) of
+ ok ->
+ {ok, FileInfo} = file:read_file_info(FromFile1),
+ ok = file:write_file_info(ToFile2, FileInfo),
+ ok;
+ {error, Err} ->
+ ?RCL_ERROR({copy_failed,
+ FromFile1,
+ ToFile1, Err})
+ end.
+
+get_relative_root(State) ->
+ case rcl_state:config_file(State) of
+ [] ->
+ rcl_state:root_dir(State);
+ Config ->
+ filename:dirname(Config)
+ end.
+
+-spec is_directory(file:name(), file:name()) -> boolean().
+is_directory(ToFile0, ToFile1) ->
+ case re:run(ToFile0, ?DIRECTORY_RE) of
+ nomatch ->
+ filelib:is_dir(ToFile1);
+ _ ->
+ true
+ end.
+
+
+-spec render_template(proplists:proplist(), iolist()) ->
ok | relcool:error().
-render_template(OverlayVars, FromFile, ToFile) ->
- TemplateName = make_template_name("rcl_template_renderer", FromFile),
- case erlydtl:compile(FromFile, TemplateName) of
- Good when Good =:= ok; ok =:= {ok, TemplateName} ->
+render_template(OverlayVars, Data) ->
+ TemplateName = make_template_name("rcl_template_renderer", Data),
+ case erlydtl:compile(Data, TemplateName) of
+ Good when Good =:= ok; Good =:= {ok, TemplateName} ->
case render(TemplateName, OverlayVars) of
{ok, IoData} ->
- io:format("Rendering ~p~n", [IoData]),
- case filelib:ensure_dir(ToFile) of
+ {ok, IoData};
+ {error, Reason} ->
+ ?RCL_ERROR({unable_to_render_template, Data, Reason})
+ end;
+ {error, Reason} ->
+ ?RCL_ERROR({unable_to_compile_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
ok ->
- case file:write_file(ToFile, IoData) of
- ok ->
- ok;
- {error, Reason} ->
- ?RCL_ERROR({unable_to_write, ToFile, Reason})
- end;
+ {ok, FileInfo} = file:read_file_info(FromFile),
+ ok = file:write_file_info(ToFile, FileInfo),
+ ok;
{error, Reason} ->
- ?RCL_ERROR({unable_to_enclosing_dir, ToFile, Reason})
+ ?RCL_ERROR({unable_to_write, ToFile, Reason})
end;
{error, Reason} ->
- ?RCL_ERROR({unable_to_render_template, FromFile, Reason})
+ ?RCL_ERROR({unable_to_enclosing_dir, ToFile, Reason})
end;
- {error, Reason} ->
- ?RCL_ERROR({unable_to_compile_template, FromFile, Reason})
+ Error ->
+ Error
end.
--spec file_render_do(rcl_state:t(), proplists:proplist(), iolist(), module(),
+-spec file_render_do(proplists:proplist(), iolist(), module(),
fun((term()) -> {ok, rcl_state:t()} | relcool:error())) ->
{ok, rcl_state:t()} | relcool:error().
-file_render_do(State, OverlayVars, Data, TemplateName, NextAction) ->
+file_render_do(OverlayVars, Data, TemplateName, NextAction) ->
case erlydtl:compile(erlang:iolist_to_binary(Data), TemplateName) of
{ok, TemplateName} ->
case render(TemplateName, OverlayVars) of
{ok, IoList} ->
- Absolute = filename:absname(filename:join(rcl_state:root_dir(State),
- erlang:iolist_to_binary(IoList))),
- NextAction(Absolute);
+ NextAction(IoList);
{error, Error} ->
?RCL_ERROR({render_failed, Data, Error})
end;
@@ -322,3 +412,7 @@ render(ModuleName, OverlayVars) ->
_:Reason ->
{error, Reason}
end.
+
+absolutize(State, FileName) ->
+ filename:absname(filename:join(rcl_state:root_dir(State),
+ erlang:iolist_to_binary(FileName))).