浏览代码

Allow to forcibly overwrite files with templates

pull/3/head
Fred Hebert 10 年前
父节点
当前提交
4ed1c4ef58
共有 2 个文件被更改,包括 44 次插入33 次删除
  1. +20
    -9
      src/rebar_prv_new.erl
  2. +24
    -24
      src/rebar_templater.erl

+ 20
- 9
src/rebar_prv_new.erl 查看文件

@ -17,14 +17,17 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) -> init(State) ->
State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
{module, ?MODULE},
{bare, false},
{deps, ?DEPS},
{example, "rebar new <template>"},
{short_desc, "Create new project from templates."},
{desc, info()},
{opts, []}])),
Provider = providers:create([
{name, ?PROVIDER},
{module, ?MODULE},
{bare, false},
{deps, ?DEPS},
{example, "rebar new <template>"},
{short_desc, "Create new project from templates."},
{desc, info()},
{opts, [{force, $f, "force", undefined, "overwrite existing files"}]}
]),
State1 = rebar_state:add_provider(State, Provider),
{ok, State1}. {ok, State1}.
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
@ -37,7 +40,8 @@ do(State) ->
end, end,
{ok, State}; {ok, State};
[TemplateName | Opts] -> [TemplateName | Opts] ->
ok = rebar_templater:new(TemplateName, parse_opts(Opts), State),
Force = is_forced(State),
ok = rebar_templater:new(TemplateName, parse_opts(Opts), Force, State),
{ok, State}; {ok, State};
[] -> [] ->
show_short_templates(rebar_templater:list_templates(State)), show_short_templates(rebar_templater:list_templates(State)),
@ -59,6 +63,13 @@ info() ->
"Valid command line options:~n" "Valid command line options:~n"
" template= [var=foo,...]~n", []). " template= [var=foo,...]~n", []).
is_forced(State) ->
{Args, _} = rebar_state:command_parsed_args(State),
case proplists:get_value(force, Args) of
undefined -> false;
_ -> true
end.
parse_opts([]) -> []; parse_opts([]) -> [];
parse_opts([Opt|Opts]) -> [parse_opt(Opt, "") | parse_opts(Opts)]. parse_opts([Opt|Opts]) -> [parse_opt(Opt, "") | parse_opts(Opts)].

+ 24
- 24
src/rebar_templater.erl 查看文件

@ -26,7 +26,7 @@
%% ------------------------------------------------------------------- %% -------------------------------------------------------------------
-module(rebar_templater). -module(rebar_templater).
-export([new/3,
-export([new/4,
list_templates/1]). list_templates/1]).
%% API for other utilities that need templating functionality %% API for other utilities that need templating functionality
@ -43,12 +43,12 @@
%% =================================================================== %% ===================================================================
%% Apply a template %% Apply a template
new(Template, Vars, State) ->
new(Template, Vars, Force, State) ->
{AvailTemplates, Files} = find_templates(State), {AvailTemplates, Files} = find_templates(State),
?DEBUG("Looking for ~p~n", [Template]), ?DEBUG("Looking for ~p~n", [Template]),
case lists:keyfind(Template, 1, AvailTemplates) of case lists:keyfind(Template, 1, AvailTemplates) of
false -> {not_found, Template}; false -> {not_found, Template};
TemplateTup -> create(TemplateTup, Files, Vars)
TemplateTup -> create(TemplateTup, Files, Vars, Force)
end. end.
%% Give a list of templates with their expanded content %% Give a list of templates with their expanded content
@ -157,24 +157,24 @@ drop_var_docs([{K,V}|Rest]) -> [{K,V} | drop_var_docs(Rest)].
%% Load the template index, resolve all variables, and then execute %% Load the template index, resolve all variables, and then execute
%% the template. %% the template.
create({Template, Type, File}, Files, UserVars) ->
create({Template, Type, File}, Files, UserVars, Force) ->
TemplateTerms = consult(load_file(Files, Type, File)), TemplateTerms = consult(load_file(Files, Type, File)),
Vars = drop_var_docs(override_vars(UserVars, get_template_vars(TemplateTerms))), Vars = drop_var_docs(override_vars(UserVars, get_template_vars(TemplateTerms))),
TemplateCwd = filename:dirname(File), TemplateCwd = filename:dirname(File),
execute_template(TemplateTerms, Files, {Template, Type, TemplateCwd}, Vars).
execute_template(TemplateTerms, Files, {Template, Type, TemplateCwd}, Vars, Force).
%% Run template instructions one at a time. %% Run template instructions one at a time.
execute_template([], _, {Template,_,_}, _) ->
execute_template([], _, {Template,_,_}, _, _) ->
?DEBUG("Template ~s applied~n", [Template]), ?DEBUG("Template ~s applied~n", [Template]),
ok; ok;
%% We can't execute the description %% We can't execute the description
execute_template([{description, _} | Terms], Files, Template, Vars) ->
execute_template(Terms, Files, Template, Vars);
execute_template([{description, _} | Terms], Files, Template, Vars, Force) ->
execute_template(Terms, Files, Template, Vars, Force);
%% We can't execute variables %% We can't execute variables
execute_template([{variables, _} | Terms], Files, Template, Vars) ->
execute_template(Terms, Files, Template, Vars);
execute_template([{variables, _} | Terms], Files, Template, Vars, Force) ->
execute_template(Terms, Files, Template, Vars, Force);
%% Create a directory %% Create a directory
execute_template([{dir, Path} | Terms], Files, Template, Vars) ->
execute_template([{dir, Path} | Terms], Files, Template, Vars, Force) ->
?DEBUG("Creating directory ~p~n", [Path]), ?DEBUG("Creating directory ~p~n", [Path]),
case ec_file:mkdir_p(expand_path(Path, Vars)) of case ec_file:mkdir_p(expand_path(Path, Vars)) of
ok -> ok ->
@ -183,45 +183,45 @@ execute_template([{dir, Path} | Terms], Files, Template, Vars) ->
?ABORT("Failed while processing template instruction " ?ABORT("Failed while processing template instruction "
"{dir, ~p}: ~p~n", [Path, Reason]) "{dir, ~p}: ~p~n", [Path, Reason])
end, end,
execute_template(Terms, Files, Template, Vars);
execute_template(Terms, Files, Template, Vars, Force);
%% Change permissions on a file %% Change permissions on a file
execute_template([{chmod, File, Perm} | Terms], Files, Template, Vars) ->
execute_template([{chmod, File, Perm} | Terms], Files, Template, Vars, Force) ->
Path = expand_path(File, Vars), Path = expand_path(File, Vars),
case file:change_mode(Path, Perm) of case file:change_mode(Path, Perm) of
ok -> ok ->
execute_template(Terms, Files, Template, Vars);
execute_template(Terms, Files, Template, Vars, Force);
{error, Reason} -> {error, Reason} ->
?ABORT("Failed while processing template instruction " ?ABORT("Failed while processing template instruction "
"{chmod, ~.8#, ~p}: ~p~n", [Perm, File, Reason]) "{chmod, ~.8#, ~p}: ~p~n", [Perm, File, Reason])
end; end;
%% Create a raw untemplated file %% Create a raw untemplated file
execute_template([{file, From, To} | Terms], Files, {Template, Type, Cwd}, Vars) ->
execute_template([{file, From, To} | Terms], Files, {Template, Type, Cwd}, Vars, Force) ->
?DEBUG("Creating file ~p~n", [To]), ?DEBUG("Creating file ~p~n", [To]),
Data = load_file(Files, Type, filename:join(Cwd, From)), Data = load_file(Files, Type, filename:join(Cwd, From)),
Out = expand_path(To,Vars), Out = expand_path(To,Vars),
case write_file(Out, Data, false) of
case write_file(Out, Data, Force) of
ok -> ok; ok -> ok;
{error, exists} -> ?INFO("File ~p already exists.~n", [Out]) {error, exists} -> ?INFO("File ~p already exists.~n", [Out])
end, end,
execute_template(Terms, Files, {Template, Type, Cwd}, Vars);
execute_template(Terms, Files, {Template, Type, Cwd}, Vars, Force);
%% Operate on a django template %% Operate on a django template
execute_template([{template, From, To} | Terms], Files, {Template, Type, Cwd}, Vars) ->
execute_template([{template, From, To} | Terms], Files, {Template, Type, Cwd}, Vars, Force) ->
?DEBUG("Executing template file ~p~n", [From]), ?DEBUG("Executing template file ~p~n", [From]),
Out = expand_path(To, Vars), Out = expand_path(To, Vars),
Tpl = load_file(Files, Type, filename:join(Cwd, From)), Tpl = load_file(Files, Type, filename:join(Cwd, From)),
TplName = make_template_name("rebar_template", Out), TplName = make_template_name("rebar_template", Out),
{ok, Mod} = erlydtl:compile_template(Tpl, TplName, ?ERLYDTL_COMPILE_OPTS), {ok, Mod} = erlydtl:compile_template(Tpl, TplName, ?ERLYDTL_COMPILE_OPTS),
{ok, Output} = Mod:render(Vars), {ok, Output} = Mod:render(Vars),
case write_file(Out, Output, false) of
case write_file(Out, Output, Force) of
ok -> ok; ok -> ok;
{error, exists} -> ?INFO("File ~p already exists~n", [Out]) {error, exists} -> ?INFO("File ~p already exists~n", [Out])
end, end,
execute_template(Terms, Files, {Template, Type, Cwd}, Vars);
execute_template(Terms, Files, {Template, Type, Cwd}, Vars, Force);
%% Unknown %% Unknown
execute_template([Instruction|Terms], Files, Tpl={Template,_,_}, Vars) ->
execute_template([Instruction|Terms], Files, Tpl={Template,_,_}, Vars, Force) ->
?WARN("Unknown template instruction ~p in template ~s", ?WARN("Unknown template instruction ~p in template ~s",
[Instruction, Template]), [Instruction, Template]),
execute_template(Terms, Files, Tpl, Vars).
execute_template(Terms, Files, Tpl, Vars, Force).
%% Workaround to allow variable substitution in path names without going %% Workaround to allow variable substitution in path names without going
%% through the ErlyDTL compilation step. Parse the string and replace %% through the ErlyDTL compilation step. Parse the string and replace
@ -346,11 +346,11 @@ write_file(Output, Data, Force) ->
%% perform the function if we're allowed, %% perform the function if we're allowed,
%% otherwise just process the next template %% otherwise just process the next template
case Force =:= "1" orelse FileExists =:= false of
case Force orelse FileExists =:= false of
true -> true ->
ok = filelib:ensure_dir(Output), ok = filelib:ensure_dir(Output),
case {Force, FileExists} of case {Force, FileExists} of
{"1", true} ->
{true, true} ->
?INFO("Writing ~s (forcibly overwriting)", ?INFO("Writing ~s (forcibly overwriting)",
[Output]); [Output]);
_ -> _ ->

正在加载...
取消
保存