Do not use process dict in rebar_templater

This commit is contained in:
Tuncer Ayaz 2012-05-26 19:33:33 +02:00
parent 4fe3306d99
commit d9e6cc3d90

View file

@ -54,18 +54,13 @@
create(Config, File). create(Config, File).
'list-templates'(_Config, _File) -> 'list-templates'(_Config, _File) ->
%% Load a list of all the files in the escript -- cache it in the pdict {AvailTemplates, Files} = find_templates(),
%% since we'll potentially need to walk it several times over the course ?DEBUG("Available templates: ~p\n", [AvailTemplates]),
%% of a run.
cache_escript_files(),
%% Build a list of available templates
AvailTemplates = find_disk_templates() ++ find_escript_templates(),
?CONSOLE("Available templates:\n", []),
lists:foreach( lists:foreach(
fun({Type, F}) -> fun({Type, F}) ->
BaseName = filename:basename(F, ".template"), BaseName = filename:basename(F, ".template"),
TemplateTerms = consult(load_file(Type, F)), TemplateTerms = consult(load_file(Files, Type, F)),
{_, VarList} = lists:keyfind(variables, 1, TemplateTerms), {_, VarList} = lists:keyfind(variables, 1, TemplateTerms),
Vars = lists:foldl(fun({V,_}, Acc) -> Vars = lists:foldl(fun({V,_}, Acc) ->
[atom_to_list(V) | Acc] [atom_to_list(V) | Acc]
@ -77,13 +72,7 @@
create(_Config, _) -> create(_Config, _) ->
%% Load a list of all the files in the escript -- cache it in the pdict {AvailTemplates, Files} = find_templates(),
%% since we'll potentially need to walk it several times over the course
%% of a run.
cache_escript_files(),
%% Build a list of available templates
AvailTemplates = find_disk_templates() ++ find_escript_templates(),
?DEBUG("Available templates: ~p\n", [AvailTemplates]), ?DEBUG("Available templates: ~p\n", [AvailTemplates]),
TemplateId = template_id(), TemplateId = template_id(),
@ -96,7 +85,7 @@ create(_Config, _) ->
%% Load the template definition as is and get the list of variables the %% Load the template definition as is and get the list of variables the
%% template requires. %% template requires.
TemplateTerms = consult(load_file(Type, Template)), TemplateTerms = consult(load_file(Files, Type, Template)),
case lists:keyfind(variables, 1, TemplateTerms) of case lists:keyfind(variables, 1, TemplateTerms) of
{variables, Vars} -> {variables, Vars} ->
case parse_vars(Vars, dict:new()) of case parse_vars(Vars, dict:new()) of
@ -145,12 +134,12 @@ create(_Config, _) ->
%% Now, use our context to process the template definition -- this %% Now, use our context to process the template definition -- this
%% permits us to use variables within the definition for filenames. %% 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]), ?DEBUG("Final template def ~p: ~p\n", [TemplateId, FinalTemplate]),
%% Execute the instructions in the finalized template %% Execute the instructions in the finalized template
Force = rebar_config:get_global(force, "0"), Force = rebar_config:get_global(force, "0"),
execute_template(FinalTemplate, Type, Template, Context, Force, []). execute_template(Files, FinalTemplate, Type, Template, Context, Force, []).
%% %%
@ -181,8 +170,19 @@ render(Bin, Context) ->
%% Internal functions %% Internal functions
%% =================================================================== %% ===================================================================
find_templates() ->
%% 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(),
%% Build a list of available templates
AvailTemplates = find_disk_templates() ++ find_escript_templates(Files),
{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() ->
{ok, Files} = rebar_utils:escript_foldl( {ok, Files} = rebar_utils:escript_foldl(
@ -190,8 +190,7 @@ cache_escript_files() ->
[{Name, GetBin()} | Acc] [{Name, GetBin()} | Acc]
end, end,
[], rebar_config:get_global(escript, undefined)), [], rebar_config:get_global(escript, undefined)),
erlang:put(escript_files, Files). Files.
template_id() -> template_id() ->
case rebar_config:get_global(template, undefined) of case rebar_config:get_global(template, undefined) of
@ -201,9 +200,10 @@ template_id() ->
TemplateId TemplateId
end. end.
find_escript_templates() -> find_escript_templates(Files) ->
[{escript, Name} || {Name, _Bin} <- erlang:get(escript_files), [{escript, Name}
re:run(Name, ?TEMPLATE_RE, [{capture, none}]) == match]. || {Name, _Bin} <- Files,
re:run(Name, ?TEMPLATE_RE, [{capture, none}]) == match].
find_disk_templates() -> find_disk_templates() ->
OtherTemplates = find_other_templates(), OtherTemplates = find_other_templates(),
@ -234,10 +234,10 @@ select_template([{Type, Avail} | Rest], Template) ->
%% %%
%% Read the contents of a file from the appropriate source %% Read the contents of a file from the appropriate source
%% %%
load_file(escript, Name) -> load_file(Files, escript, Name) ->
{Name, Bin} = lists:keyfind(Name, 1, erlang:get(escript_files)), {Name, Bin} = lists:keyfind(Name, 1, Files),
Bin; Bin;
load_file(file, Name) -> load_file(_Files, file, Name) ->
{ok, Bin} = file:read_file(Name), {ok, Bin} = file:read_file(Name),
Bin. Bin.
@ -320,8 +320,8 @@ write_file(Output, Data, Force) ->
%% %%
%% Execute each instruction in a template definition file. %% Execute each instruction in a template definition file.
%% %%
execute_template([], _TemplateType, _TemplateName, _Context, execute_template(_Files, [], _TemplateType, _TemplateName,
_Force, ExistingFiles) -> _Context, _Force, ExistingFiles) ->
case ExistingFiles of case ExistingFiles of
[] -> [] ->
ok; ok;
@ -333,76 +333,78 @@ execute_template([], _TemplateType, _TemplateName, _Context,
?ERROR("One or more files already exist on disk and " ?ERROR("One or more files already exist on disk and "
"were not generated:~n~s~s", [Msg , Help]) "were not generated:~n~s~s", [Msg , Help])
end; end;
execute_template([{template, Input, Output} | Rest], TemplateType, execute_template(Files, [{template, Input, Output} | Rest], TemplateType,
TemplateName, Context, Force, ExistingFiles) -> TemplateName, Context, Force, ExistingFiles) ->
InputName = filename:join(filename:dirname(TemplateName), Input), InputName = filename:join(filename:dirname(TemplateName), Input),
case write_file(Output, render(load_file(TemplateType, InputName), Context), File = load_file(Files, TemplateType, InputName),
Force) of case write_file(Output, render(File, Context), Force) of
ok -> ok ->
execute_template(Rest, TemplateType, TemplateName, Context, execute_template(Files, Rest, TemplateType, TemplateName,
Force, ExistingFiles);
{error, exists} ->
execute_template(Rest, TemplateType, TemplateName, Context,
Force, [Output|ExistingFiles])
end;
execute_template([{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
ok ->
execute_template(Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles); Context, Force, ExistingFiles);
{error, exists} -> {error, exists} ->
execute_template(Rest, TemplateType, TemplateName, execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, [Output|ExistingFiles]) Context, Force, [Output|ExistingFiles])
end; end;
execute_template([{dir, Name} | Rest], TemplateType, TemplateName, Context, execute_template(Files, [{file, Input, Output} | Rest], TemplateType,
Force, ExistingFiles) -> TemplateName, Context, Force, ExistingFiles) ->
InputName = filename:join(filename:dirname(TemplateName), Input),
File = load_file(Files, TemplateType, InputName),
case write_file(Output, File, Force) of
ok ->
execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles);
{error, exists} ->
execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, [Output|ExistingFiles])
end;
execute_template(Files, [{dir, Name} | Rest], TemplateType,
TemplateName, Context, Force, ExistingFiles) ->
case filelib:ensure_dir(filename:join(Name, "dummy")) of case filelib:ensure_dir(filename:join(Name, "dummy")) of
ok -> ok ->
execute_template(Rest, TemplateType, TemplateName, execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles); Context, Force, ExistingFiles);
{error, Reason} -> {error, Reason} ->
?ABORT("Failed while processing template instruction " ?ABORT("Failed while processing template instruction "
"{dir, ~s}: ~p\n", [Name, Reason]) "{dir, ~s}: ~p\n", [Name, Reason])
end; end;
execute_template([{copy, Input, Output} | Rest], TemplateType, TemplateName, execute_template(Files, [{copy, Input, Output} | Rest], TemplateType,
Context, Force, ExistingFiles) -> TemplateName, Context, Force, ExistingFiles) ->
InputName = filename:join(filename:dirname(TemplateName), Input), InputName = filename:join(filename:dirname(TemplateName), Input),
try rebar_file_utils:cp_r([InputName ++ "/*"], Output) of try rebar_file_utils:cp_r([InputName ++ "/*"], Output) of
ok -> ok ->
execute_template(Rest, TemplateType, TemplateName, execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles) Context, Force, ExistingFiles)
catch _:_ -> catch _:_ ->
?ABORT("Failed while processing template instruction " ?ABORT("Failed while processing template instruction "
"{copy, ~s, ~s}~n", [Input, Output]) "{copy, ~s, ~s}~n", [Input, Output])
end; end;
execute_template([{chmod, Mod, File} | Rest], TemplateType, TemplateName, execute_template(Files, [{chmod, Mod, File} | Rest], TemplateType,
Context, Force, ExistingFiles) when is_integer(Mod) -> TemplateName, Context, Force, ExistingFiles)
when is_integer(Mod) ->
case file:change_mode(File, Mod) of case file:change_mode(File, Mod) of
ok -> ok ->
execute_template(Rest, TemplateType, TemplateName, execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles); Context, Force, ExistingFiles);
{error, Reason} -> {error, Reason} ->
?ABORT("Failed while processing template instruction " ?ABORT("Failed while processing template instruction "
"{chmod, ~b, ~s}: ~p~n", [Mod, File, Reason]) "{chmod, ~b, ~s}: ~p~n", [Mod, File, Reason])
end; end;
execute_template([{symlink, Existing, New} | Rest], TemplateType, TemplateName, execute_template(Files, [{symlink, Existing, New} | Rest], TemplateType,
Context, Force, ExistingFiles) -> TemplateName, Context, Force, ExistingFiles) ->
case file:make_symlink(Existing, New) of case file:make_symlink(Existing, New) of
ok -> ok ->
execute_template(Rest, TemplateType, TemplateName, execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles); Context, Force, ExistingFiles);
{error, Reason} -> {error, Reason} ->
?ABORT("Failed while processing template instruction " ?ABORT("Failed while processing template instruction "
"{symlink, ~s, ~s}: ~p~n", [Existing, New, Reason]) "{symlink, ~s, ~s}: ~p~n", [Existing, New, Reason])
end; end;
execute_template([{variables, _} | Rest], TemplateType, TemplateName, Context, execute_template(Files, [{variables, _} | Rest], TemplateType,
Force, ExistingFiles) -> TemplateName, Context, Force, ExistingFiles) ->
execute_template(Rest, TemplateType, TemplateName, execute_template(Files, Rest, TemplateType, TemplateName,
Context, Force, ExistingFiles); Context, Force, ExistingFiles);
execute_template([Other | Rest], TemplateType, TemplateName, Context, execute_template(Files, [Other | Rest], TemplateType, TemplateName,
Force, ExistingFiles) -> Context, Force, ExistingFiles) ->
?WARN("Skipping unknown template instruction: ~p\n", [Other]), ?WARN("Skipping unknown template instruction: ~p\n", [Other]),
execute_template(Rest, TemplateType, TemplateName, Context, execute_template(Files, Rest, TemplateType, TemplateName, Context,
Force, ExistingFiles). Force, ExistingFiles).