summaryrefslogtreecommitdiff
path: root/src/rebar_templater.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/rebar_templater.erl')
-rw-r--r--src/rebar_templater.erl242
1 files changed, 121 insertions, 121 deletions
diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl
index 1e015ee..0e1eef1 100644
--- a/src/rebar_templater.erl
+++ b/src/rebar_templater.erl
@@ -43,49 +43,64 @@
%% Public API
%% ===================================================================
-'create-app'(Config, File) ->
+'create-app'(Config, _File) ->
%% Alias for create w/ template=simpleapp
- rebar_config:set_global(template, "simpleapp"),
- create(Config, File).
+ create1(Config, "simpleapp").
-'create-node'(Config, File) ->
+'create-node'(Config, _File) ->
%% Alias for create w/ template=simplenode
- rebar_config:set_global(template, "simplenode"),
- create(Config, File).
+ create1(Config, "simplenode").
-'list-templates'(_Config, _File) ->
- %% Load a list of all the files in the escript -- cache it in the pdict
- %% since we'll potentially need to walk it several times over the course
- %% of a run.
- cache_escript_files(),
+'list-templates'(Config, _File) ->
+ {AvailTemplates, Files} = find_templates(Config),
+ ?DEBUG("Available templates: ~p\n", [AvailTemplates]),
- %% Build a list of available templates
- AvailTemplates = find_disk_templates() ++ find_escript_templates(),
- ?CONSOLE("Available templates:\n", []),
- _ = [begin
- BaseName = filename:basename(F, ".template"),
- {ok, Template} = file:consult(F),
- {_, VarList} = lists:keyfind(variables, 1, Template),
- Vars = lists:foldl(fun({V,_}, Acc) ->
- [atom_to_list(V) | Acc]
- end, [], VarList),
- ?CONSOLE("\t* ~s: ~s (~p) (variables: ~p)\n",
- [BaseName, F, Type, string:join(Vars, ", ")])
- end || {Type, F} <- AvailTemplates],
+ lists:foreach(
+ fun({Type, F}) ->
+ BaseName = filename:basename(F, ".template"),
+ TemplateTerms = consult(load_file(Files, Type, F)),
+ {_, VarList} = lists:keyfind(variables, 1, TemplateTerms),
+ Vars = lists:foldl(fun({V,_}, Acc) ->
+ [atom_to_list(V) | Acc]
+ end, [], VarList),
+ ?CONSOLE(" * ~s: ~s (~p) (variables: ~p)\n",
+ [BaseName, F, Type, string:join(Vars, ", ")])
+ end, AvailTemplates),
ok.
+create(Config, _) ->
+ TemplateId = template_id(Config),
+ create1(Config, TemplateId).
-create(_Config, _) ->
- %% Load a list of all the files in the escript -- cache it in the pdict
- %% since we'll potentially need to walk it several times over the course
- %% of a run.
- cache_escript_files(),
+%%
+%% Given a list of key value pairs, for each string value attempt to
+%% render it using Dict as the context. Storing the result in Dict as Key.
+%%
+resolve_variables([], Dict) ->
+ Dict;
+resolve_variables([{Key, Value0} | Rest], Dict) when is_list(Value0) ->
+ Value = render(list_to_binary(Value0), Dict),
+ resolve_variables(Rest, dict:store(Key, Value, Dict));
+resolve_variables([_Pair | Rest], Dict) ->
+ resolve_variables(Rest, Dict).
- %% Build a list of available templates
- AvailTemplates = find_disk_templates() ++ find_escript_templates(),
- ?DEBUG("Available templates: ~p\n", [AvailTemplates]),
+%%
+%% Render a binary to a string, using mustache and the specified context
+%%
+render(Bin, Context) ->
+ %% Be sure to escape any double-quotes before rendering...
+ ReOpts = [global, {return, list}],
+ Str0 = re:replace(Bin, "\\\\", "\\\\\\", ReOpts),
+ Str1 = re:replace(Str0, "\"", "\\\\\"", ReOpts),
+ mustache:render(Str1, Context).
- TemplateId = template_id(),
+%% ===================================================================
+%% Internal functions
+%% ===================================================================
+
+create1(Config, TemplateId) ->
+ {AvailTemplates, Files} = find_templates(Config),
+ ?DEBUG("Available templates: ~p\n", [AvailTemplates]),
%% Using the specified template id, find the matching template file/type.
%% Note that if you define the same template in both ~/.rebar/templates
@@ -95,7 +110,7 @@ create(_Config, _) ->
%% Load the template definition as is and get the list of variables the
%% template requires.
- TemplateTerms = consult(load_file(Type, Template)),
+ TemplateTerms = consult(load_file(Files, Type, Template)),
case lists:keyfind(variables, 1, TemplateTerms) of
{variables, Vars} ->
case parse_vars(Vars, dict:new()) of
@@ -115,7 +130,7 @@ create(_Config, _) ->
end,
%% Load variables from disk file, if provided
- Context1 = case rebar_config:get_global(template_vars, undefined) of
+ Context1 = case rebar_config:get_global(Config, template_vars, undefined) of
undefined ->
Context0;
File ->
@@ -132,7 +147,7 @@ create(_Config, _) ->
%% For each variable, see if it's defined in global vars -- if it is,
%% prefer that value over the defaults
- Context2 = update_vars(dict:fetch_keys(Context1), Context1),
+ Context2 = update_vars(Config, dict:fetch_keys(Context1), Context1),
?DEBUG("Template ~p context: ~p\n", [TemplateId, dict:to_list(Context1)]),
%% Handle variables that possibly include other variables in their
@@ -144,76 +159,59 @@ create(_Config, _) ->
%% Now, use our context to process the template definition -- this
%% permits us to use variables within the definition for filenames.
- FinalTemplate = consult(render(load_file(Type, Template), Context)),
+ FinalTemplate = consult(render(load_file(Files, Type, Template), Context)),
?DEBUG("Final template def ~p: ~p\n", [TemplateId, FinalTemplate]),
%% Execute the instructions in the finalized template
- Force = rebar_config:get_global(force, "0"),
- execute_template(FinalTemplate, Type, Template, Context, Force, []).
-
-
-%%
-%% Given a list of key value pairs, for each string value attempt to
-%% render it using Dict as the context. Storing the result in Dict as Key.
-%%
-resolve_variables([], Dict) ->
- Dict;
-resolve_variables([{Key, Value0} | Rest], Dict) when is_list(Value0) ->
- Value = render(list_to_binary(Value0), Dict),
- resolve_variables(Rest, dict:store(Key, Value, Dict));
-resolve_variables([_Pair | Rest], Dict) ->
- resolve_variables(Rest, Dict).
-
+ Force = rebar_config:get_global(Config, force, "0"),
+ execute_template(Files, FinalTemplate, Type, Template, Context, Force, []).
-%%
-%% Render a binary to a string, using mustache and the specified context
-%%
-render(Bin, Context) ->
- %% Be sure to escape any double-quotes before rendering...
- ReOpts = [global, {return, list}],
- Str0 = re:replace(Bin, "\\\\", "\\\\\\", ReOpts),
- Str1 = re:replace(Str0, "\"", "\\\\\"", ReOpts),
- mustache:render(Str1, Context).
+find_templates(Config) ->
+ %% Load a list of all the files in the escript -- cache them since
+ %% we'll potentially need to walk it several times over the course of
+ %% a run.
+ Files = cache_escript_files(Config),
+ %% Build a list of available templates
+ AvailTemplates = find_disk_templates(Config)
+ ++ find_escript_templates(Files),
-%% ===================================================================
-%% Internal functions
-%% ===================================================================
+ {AvailTemplates, Files}.
%%
-%% Scan the current escript for available files and cache in pdict.
+%% Scan the current escript for available files
%%
-cache_escript_files() ->
+cache_escript_files(Config) ->
{ok, Files} = rebar_utils:escript_foldl(
fun(Name, _, GetBin, Acc) ->
[{Name, GetBin()} | Acc]
end,
- [], rebar_config:get_global(escript, undefined)),
- erlang:put(escript_files, Files).
+ [], rebar_config:get_xconf(Config, escript)),
+ Files.
-
-template_id() ->
- case rebar_config:get_global(template, undefined) of
+template_id(Config) ->
+ case rebar_config:get_global(Config, template, undefined) of
undefined ->
?ABORT("No template specified.\n", []);
TemplateId ->
TemplateId
end.
-find_escript_templates() ->
- [{escript, Name} || {Name, _Bin} <- erlang:get(escript_files),
- re:run(Name, ?TEMPLATE_RE, [{capture, none}]) == match].
+find_escript_templates(Files) ->
+ [{escript, Name}
+ || {Name, _Bin} <- Files,
+ re:run(Name, ?TEMPLATE_RE, [{capture, none}]) == match].
-find_disk_templates() ->
- OtherTemplates = find_other_templates(),
+find_disk_templates(Config) ->
+ OtherTemplates = find_other_templates(Config),
HomeFiles = rebar_utils:find_files(filename:join([os:getenv("HOME"),
".rebar", "templates"]),
?TEMPLATE_RE),
LocalFiles = rebar_utils:find_files(".", ?TEMPLATE_RE),
[{file, F} || F <- OtherTemplates ++ HomeFiles ++ LocalFiles].
-find_other_templates() ->
- case rebar_config:get_global(template_dir, undefined) of
+find_other_templates(Config) ->
+ case rebar_config:get_global(Config, template_dir, undefined) of
undefined ->
[];
TemplateDir ->
@@ -233,10 +231,10 @@ select_template([{Type, Avail} | Rest], Template) ->
%%
%% Read the contents of a file from the appropriate source
%%
-load_file(escript, Name) ->
- {Name, Bin} = lists:keyfind(Name, 1, erlang:get(escript_files)),
+load_file(Files, escript, Name) ->
+ {Name, Bin} = lists:keyfind(Name, 1, Files),
Bin;
-load_file(file, Name) ->
+load_file(_Files, file, Name) ->
{ok, Bin} = file:read_file(Name),
Bin.
@@ -256,15 +254,15 @@ parse_vars(Other, _Dict) ->
%% Given a list of keys in Dict, see if there is a corresponding value defined
%% in the global config; if there is, update the key in Dict with it
%%
-update_vars([], Dict) ->
+update_vars(_Config, [], Dict) ->
Dict;
-update_vars([Key | Rest], Dict) ->
- Value = rebar_config:get_global(Key, dict:fetch(Key, Dict)),
- update_vars(Rest, dict:store(Key, Value, Dict)).
+update_vars(Config, [Key | Rest], Dict) ->
+ Value = rebar_config:get_global(Config, Key, dict:fetch(Key, Dict)),
+ update_vars(Config, Rest, dict:store(Key, Value, Dict)).
%%
-%% Given a string or binary, parse it into a list of terms, ala file:consult/0
+%% Given a string or binary, parse it into a list of terms, ala file:consult/1
%%
consult(Str) when is_list(Str) ->
consult([], Str, []);
@@ -319,89 +317,91 @@ write_file(Output, Data, Force) ->
%%
%% Execute each instruction in a template definition file.
%%
-execute_template([], _TemplateType, _TemplateName, _Context,
- _Force, ExistingFiles) ->
+execute_template(_Files, [], _TemplateType, _TemplateName,
+ _Context, _Force, ExistingFiles) ->
case ExistingFiles of
[] ->
ok;
_ ->
Msg = lists:flatten([io_lib:format("\t* ~p~n", [F]) ||
F <- lists:reverse(ExistingFiles)]),
- Help =
- "To force overwriting, specify force=1 on the command line.\n",
+ Help = "To force overwriting, specify -f/--force/force=1"
+ " on the command line.\n",
?ERROR("One or more files already exist on disk and "
"were not generated:~n~s~s", [Msg , Help])
end;
-execute_template([{template, Input, Output} | Rest], TemplateType,
+execute_template(Files, [{template, Input, Output} | Rest], TemplateType,
TemplateName, Context, Force, ExistingFiles) ->
InputName = filename:join(filename:dirname(TemplateName), Input),
- case write_file(Output, render(load_file(TemplateType, InputName), Context),
- Force) of
+ File = load_file(Files, TemplateType, InputName),
+ case write_file(Output, render(File, Context), Force) of
ok ->
- execute_template(Rest, TemplateType, TemplateName, Context,
- Force, ExistingFiles);
+ execute_template(Files, Rest, TemplateType, TemplateName,
+ Context, Force, ExistingFiles);
{error, exists} ->
- execute_template(Rest, TemplateType, TemplateName, Context,
- Force, [Output|ExistingFiles])
+ execute_template(Files, Rest, TemplateType, TemplateName,
+ Context, Force, [Output|ExistingFiles])
end;
-execute_template([{file, Input, Output} | Rest], TemplateType, TemplateName,
- Context, Force, ExistingFiles) ->
+execute_template(Files, [{file, Input, Output} | Rest], TemplateType,
+ TemplateName, Context, Force, ExistingFiles) ->
InputName = filename:join(filename:dirname(TemplateName), Input),
- case write_file(Output, load_file(TemplateType, InputName), Force) of
+ File = load_file(Files, TemplateType, InputName),
+ case write_file(Output, File, Force) of
ok ->
- execute_template(Rest, TemplateType, TemplateName,
+ execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles);
{error, exists} ->
- execute_template(Rest, TemplateType, TemplateName,
+ execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, [Output|ExistingFiles])
end;
-execute_template([{dir, Name} | Rest], TemplateType, TemplateName, Context,
- Force, ExistingFiles) ->
+execute_template(Files, [{dir, Name} | Rest], TemplateType,
+ TemplateName, Context, Force, ExistingFiles) ->
case filelib:ensure_dir(filename:join(Name, "dummy")) of
ok ->
- execute_template(Rest, TemplateType, TemplateName,
+ execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles);
{error, Reason} ->
?ABORT("Failed while processing template instruction "
"{dir, ~s}: ~p\n", [Name, Reason])
end;
-execute_template([{copy, Input, Output} | Rest], TemplateType, TemplateName,
- Context, Force, ExistingFiles) ->
+execute_template(Files, [{copy, Input, Output} | Rest], TemplateType,
+ TemplateName, Context, Force, ExistingFiles) ->
InputName = filename:join(filename:dirname(TemplateName), Input),
try rebar_file_utils:cp_r([InputName ++ "/*"], Output) of
ok ->
- execute_template(Rest, TemplateType, TemplateName,
+ execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles)
catch _:_ ->
?ABORT("Failed while processing template instruction "
"{copy, ~s, ~s}~n", [Input, Output])
end;
-execute_template([{chmod, Mod, File} | Rest], TemplateType, TemplateName,
- Context, Force, ExistingFiles) when is_integer(Mod) ->
+execute_template(Files, [{chmod, Mod, File} | Rest], TemplateType,
+ TemplateName, Context, Force, ExistingFiles)
+ when is_integer(Mod) ->
case file:change_mode(File, Mod) of
ok ->
- execute_template(Rest, TemplateType, TemplateName,
+ execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles);
{error, Reason} ->
?ABORT("Failed while processing template instruction "
"{chmod, ~b, ~s}: ~p~n", [Mod, File, Reason])
end;
-execute_template([{symlink, Existing, New} | Rest], TemplateType, TemplateName,
- Context, Force, ExistingFiles) ->
+execute_template(Files, [{symlink, Existing, New} | Rest], TemplateType,
+ TemplateName, Context, Force, ExistingFiles) ->
case file:make_symlink(Existing, New) of
ok ->
- execute_template(Rest, TemplateType, TemplateName,
+ execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles);
{error, Reason} ->
?ABORT("Failed while processing template instruction "
"{symlink, ~s, ~s}: ~p~n", [Existing, New, Reason])
end;
-execute_template([{variables, _} | Rest], TemplateType, TemplateName, Context,
- Force, ExistingFiles) ->
- execute_template(Rest, TemplateType, TemplateName,
+execute_template(Files, [{variables, _} | Rest], TemplateType,
+ TemplateName, Context, Force, ExistingFiles) ->
+ execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles);
-execute_template([Other | Rest], TemplateType, TemplateName, Context,
- Force, ExistingFiles) ->
+execute_template(Files, [Other | Rest], TemplateType, TemplateName,
+ Context, Force, ExistingFiles) ->
?WARN("Skipping unknown template instruction: ~p\n", [Other]),
- execute_template(Rest, TemplateType, TemplateName, Context,
+ execute_template(Files, Rest, TemplateType, TemplateName, Context,
Force, ExistingFiles).