diff options
author | Heinz N. Gies <heinz@licenser.net> | 2016-02-08 11:15:59 -0500 |
---|---|---|
committer | Heinz N. Gies <heinz@licenser.net> | 2016-02-08 11:15:59 -0500 |
commit | 2f563041cb248ba0cac27b92da5dcc3e7be27f80 (patch) | |
tree | e27ecaf59cfeb0e6406f1f4ce753842ff52855d5 /src/rebar_templater.erl | |
parent | 91c47db27a3c63fc04940c7c72433062dbadf042 (diff) | |
parent | 7fab47dfa05754242790a748bbd303ffe9703e5c (diff) |
Merge master
Diffstat (limited to 'src/rebar_templater.erl')
-rw-r--r-- | src/rebar_templater.erl | 77 |
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, _} -> |