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.erl77
1 files changed, 64 insertions, 13 deletions
diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl
index c7fb2af..2f33bfc 100644
--- a/src/rebar_templater.erl
+++ b/src/rebar_templater.erl
@@ -59,10 +59,14 @@ list_templates(State) ->
%% Expand a single template's value
list_template(Files, {Name, Type, File}, State) ->
- TemplateTerms = consult(load_file(Files, Type, File)),
- {Name, Type, File,
- get_template_description(TemplateTerms),
- get_template_vars(TemplateTerms, State)}.
+ case consult(load_file(Files, Type, File)) of
+ {error, Reason} ->
+ {error, {consult, File, Reason}};
+ TemplateTerms ->
+ {Name, Type, File,
+ get_template_description(TemplateTerms),
+ get_template_vars(TemplateTerms, State)}
+ end.
%% Load up the template description out from a list of attributes read in
%% a .template file.
@@ -155,9 +159,34 @@ drop_var_docs([{K,V}|Rest]) -> [{K,V} | drop_var_docs(Rest)].
create({Template, Type, File}, Files, UserVars, Force, State) ->
TemplateTerms = consult(load_file(Files, Type, File)),
Vars = drop_var_docs(override_vars(UserVars, get_template_vars(TemplateTerms, State))),
+ maybe_warn_about_name(Vars),
TemplateCwd = filename:dirname(File),
execute_template(TemplateTerms, Files, {Template, Type, TemplateCwd}, Vars, Force).
+maybe_warn_about_name(Vars) ->
+ Name = proplists:get_value(name, Vars, "valid"),
+ case validate_atom(Name) of
+ invalid ->
+ ?WARN("The 'name' variable is often associated with Erlang "
+ "module names and/or file names. The value submitted "
+ "(~s) isn't an unquoted Erlang atom. Templates "
+ "generated may contain errors.",
+ [Name]);
+ valid ->
+ ok
+ end.
+
+validate_atom(Str) ->
+ case io_lib:fread("~a", unicode:characters_to_list(Str)) of
+ {ok, [Atom], ""} ->
+ case io_lib:write_atom(Atom) of
+ "'" ++ _ -> invalid; % quoted
+ _ -> valid % unquoted
+ end;
+ _ ->
+ invalid
+ end.
+
%% Run template instructions one at a time.
execute_template([], _, {Template,_,_}, _, _) ->
?DEBUG("Template ~s applied", [Template]),
@@ -235,6 +264,7 @@ replace_var([H|T], Acc, Vars) ->
%% Load a list of all the files in the escript and on disk
find_templates(State) ->
DiskTemplates = find_disk_templates(State),
+ PluginTemplates = find_plugin_templates(State),
{MainTemplates, Files} =
case rebar_state:escript_path(State) of
undefined ->
@@ -245,19 +275,23 @@ find_templates(State) ->
F = cache_escript_files(State),
{find_escript_templates(F), F}
end,
- AvailTemplates = find_available_templates(DiskTemplates,
- MainTemplates),
+ AvailTemplates = find_available_templates([MainTemplates,
+ PluginTemplates,
+ DiskTemplates]),
?DEBUG("Available templates: ~p\n", [AvailTemplates]),
{AvailTemplates, Files}.
-find_available_templates(TemplateList1, TemplateList2) ->
- AvailTemplates = prioritize_templates(
- tag_names(TemplateList1),
- tag_names(TemplateList2)),
-
+find_available_templates(TemplateListList) ->
+ AvailTemplates = prioritize_templates(TemplateListList),
?DEBUG("Available templates: ~p\n", [AvailTemplates]),
AvailTemplates.
+prioritize_templates([TemplateList]) ->
+ tag_names(TemplateList);
+prioritize_templates([TemplateList | TemplateListList]) ->
+ prioritize_templates(tag_names(TemplateList),
+ prioritize_templates(TemplateListList)).
+
%% Scan the current escript for available files
cache_escript_files(State) ->
{ok, Files} = rebar_utils:escript_foldl(
@@ -295,6 +329,14 @@ find_other_templates(State) ->
rebar_utils:find_files(TemplateDir, ?TEMPLATE_RE)
end.
+%% Fetch template indexes that sit on disk in plugins
+find_plugin_templates(State) ->
+ [{plugin, File}
+ || App <- rebar_state:all_plugin_deps(State),
+ Priv <- [rebar_app_info:priv_dir(App)],
+ Priv =/= undefined,
+ File <- rebar_utils:find_files(Priv, ?TEMPLATE_RE)].
+
%% Take an existing list of templates and tag them by name the way
%% the user would enter it from the CLI
tag_names(List) ->
@@ -312,6 +354,10 @@ prioritize_templates([{Name, Type, File} | Rest], Valid) ->
?DEBUG("Skipping template ~p, due to presence of a built-in "
"template with the same name", [Name]),
prioritize_templates(Rest, Valid);
+ {_, plugin, _} ->
+ ?DEBUG("Skipping template ~p, due to presence of a plugin "
+ "template with the same name", [Name]),
+ prioritize_templates(Rest, Valid);
{_, file, _} ->
?DEBUG("Skipping template ~p, due to presence of a custom "
"template at ~s", [Name, File]),
@@ -323,6 +369,9 @@ prioritize_templates([{Name, Type, File} | Rest], Valid) ->
load_file(Files, escript, Name) ->
{Name, Bin} = lists:keyfind(Name, 1, Files),
Bin;
+load_file(_Files, plugin, Name) ->
+ {ok, Bin} = file:read_file(Name),
+ Bin;
load_file(_Files, file, Name) ->
{ok, Bin} = file:read_file(Name),
Bin.
@@ -338,8 +387,10 @@ consult(Cont, Str, Acc) ->
{done, Result, Remaining} ->
case Result of
{ok, Tokens, _} ->
- {ok, Term} = erl_parse:parse_term(Tokens),
- consult([], Remaining, [Term | Acc]);
+ case erl_parse:parse_term(Tokens) of
+ {ok, Term} -> consult([], Remaining, [Term | Acc]);
+ {error, Reason} -> {error, Reason}
+ end;
{eof, _Other} ->
lists:reverse(Acc);
{error, Info, _} ->