From e76770511a6bae6fe9d23e7821db8d32e897f9a8 Mon Sep 17 00:00:00 2001 From: Tim Watson Date: Wed, 26 Jan 2011 01:50:33 +0000 Subject: [PATCH] Add pre and post script support for all commands This change makes it possible to assign pre/post scripts to all rebar commands. This allows users fine grained control over when scripts and/or shell commands should be executed, where such extensions are absolutely needed. Several examples have been added to the rebar.config.sample file. --- inttest/thooks/fish.erl | 5 +++++ inttest/thooks/rebar.config | 7 +++++++ inttest/thooks/thooks_rt.erl | 40 ++++++++++++++++++++++++++++++++++++ rebar.config.sample | 9 ++++++++ src/rebar_core.erl | 18 +++++++++++++++- 5 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 inttest/thooks/fish.erl create mode 100644 inttest/thooks/rebar.config create mode 100644 inttest/thooks/thooks_rt.erl diff --git a/inttest/thooks/fish.erl b/inttest/thooks/fish.erl new file mode 100644 index 0000000..739cb94 --- /dev/null +++ b/inttest/thooks/fish.erl @@ -0,0 +1,5 @@ +-module(fish). + +-compile(export_all). + +fish() -> fish. diff --git a/inttest/thooks/rebar.config b/inttest/thooks/rebar.config new file mode 100644 index 0000000..6514818 --- /dev/null +++ b/inttest/thooks/rebar.config @@ -0,0 +1,7 @@ +%% pre-scripts +{pre_hooks, [{clean, "echo preclean >> preclean.out"}, + {compile, "echo precompile >> precompile.out"}]}. + +%% post-scripts +{post_hooks, [{clean, "echo postclean >> postclean.out"}, + {compile, "echo postcompile >> postcompile.out"}]}. diff --git a/inttest/thooks/thooks_rt.erl b/inttest/thooks/thooks_rt.erl new file mode 100644 index 0000000..52af9f5 --- /dev/null +++ b/inttest/thooks/thooks_rt.erl @@ -0,0 +1,40 @@ +-module(thooks_rt). + +-include_lib("eunit/include/eunit.hrl"). +-compile(export_all). + +files() -> + [ + %% dummy lfe files + {copy, "../../rebar", "rebar"}, + {copy, "rebar.config", "rebar.config"}, + {copy, "fish.erl", "src/fish.erl"}, + {create, "ebin/fish.app", app(fish, [fish])} + ]. + +run(_Dir) -> + ?assertMatch({ok, _}, retest_sh:run("./rebar -v clean compile", [])), + ensure_command_ran_only_once("preclean"), + ensure_command_ran_only_once("precompile"), + ensure_command_ran_only_once("postclean"), + ensure_command_ran_only_once("postcompile"), + ok. + +ensure_command_ran_only_once(Command) -> + File = Command ++ ".out", + ?assert(filelib:is_regular(File)), + %% ensure that this command only ran once (not for each module) + {ok, Content} = file:read_file(File), + ?assertEqual(Command ++ "\n", binary_to_list(Content)). + +%% +%% Generate the contents of a simple .app file +%% +app(Name, Modules) -> + App = {application, Name, + [{description, atom_to_list(Name)}, + {vsn, "1"}, + {modules, Modules}, + {registered, []}, + {applications, [kernel, stdlib]}]}, + io_lib:format("~p.\n", [App]). diff --git a/rebar.config.sample b/rebar.config.sample index 184c16d..9870017 100644 --- a/rebar.config.sample +++ b/rebar.config.sample @@ -138,3 +138,12 @@ %% Subdirectories? {sub_dirs, ["dir1", "dir2"]}. + +%% == Pre/Post Command Hooks == + +{pre_hooks, [{clean, "./prepare_package_files.sh"}, + {compile, "escript generate_headers"}]}. + +{post_hooks, [{clean, "touch file1.out"}, + {eunit, "touch file2.out"}, + {compile, "touch postcompile.out"}]}. diff --git a/src/rebar_core.erl b/src/rebar_core.erl index d92af34..3f8068a 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -223,7 +223,7 @@ execute(Command, Modules, Config, ModuleFile) -> case select_modules(Modules, Command, []) of [] -> ?WARN("'~p' command does not apply to directory ~s\n", - [Command, rebar_utils:get_cwd()]); + [Command, rebar_utils:get_cwd()]); TargetModules -> %% Provide some info on where we are @@ -235,9 +235,11 @@ execute(Command, Modules, Config, ModuleFile) -> erlang:put(operations, erlang:get(operations) + 1), %% Run the available modules + apply_hooks(pre_hooks, Config, Command), case catch(run_modules(TargetModules, Command, Config, ModuleFile)) of ok -> + apply_hooks(post_hooks, Config, Command), ok; {error, failed} -> ?FAIL; @@ -302,6 +304,20 @@ run_modules([Module | Rest], Command, Config, File) -> {Module, Error} end. +apply_hooks(Mode, Config, Command) -> + case rebar_config:get_local(Config, Mode, []) of + [] -> + skip; + Hooks when is_list(Hooks) -> + lists:foreach(fun apply_hook/1, + [{Command, Hook} || Hook <- Hooks]) + end. + +apply_hook({Command, {Command, Hook}}) -> + Msg = lists:flatten(io_lib:format("Command [~p] failed!~n", [Command])), + rebar_utils:sh(Hook, [{abort_on_error, Msg}]); +apply_hook({Command, {HookCmd, _}}) when Command =/= HookCmd -> + skip. acc_modules(Modules, Command, Config, File) -> acc_modules(select_modules(Modules, Command, []),