diff options
Diffstat (limited to 'src/rebar_core.erl')
-rw-r--r-- | src/rebar_core.erl | 138 |
1 files changed, 121 insertions, 17 deletions
diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 39565ac..15fb74c 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -72,7 +72,9 @@ run(RawArgs) -> ?DEBUG("Rebar location: ~p\n", [rebar_config:get_global(escript, undefined)]), %% Load rebar.config, if it exists - process_dir(rebar_utils:get_cwd(), rebar_config:new(), CommandAtoms). + [process_dir(rebar_utils:get_cwd(), rebar_config:new(), [Command]) + || Command <- CommandAtoms], + ok. %% =================================================================== @@ -178,8 +180,8 @@ clean Clean compile Compile sources create template= [var=foo,...] Create skel based on template and vars -create-app Create simple app skel -create-node Create simple node skel +create-app [appid=myapp] Create simple app skel +create-node [nodeid=mynode] Create simple node skel check-deps Display to be fetched dependencies get-deps Fetch dependencies @@ -274,22 +276,10 @@ process_dir(Dir, ParentConfig, Commands) -> %% that are processed in addition to modules associated with this directory %% type. These any_dir modules are processed FIRST. {ok, AnyDirModules} = application:get_env(rebar, any_dir_modules), - Modules = AnyDirModules ++ DirModules, - - %% Give the modules a chance to tweak config and indicate if there - %% are any other dirs that might need processing first. - {UpdatedConfig, Dirs} = acc_modules(select_modules(Modules, preprocess, []), - preprocess, Config, ModuleSetFile, []), - ?DEBUG("~s subdirs: ~p\n", [Dir, Dirs]), - [process_dir(D, UpdatedConfig, Commands) || D <- Dirs], - %% Make sure the CWD is reset properly; processing subdirs may have caused it - %% to change - ok = file:set_cwd(Dir), + Modules = AnyDirModules ++ DirModules, - %% Finally, process the current working directory - ?DEBUG("Commands: ~p Modules: ~p\n", [Commands, Modules]), - apply_commands(Commands, Modules, UpdatedConfig, ModuleSetFile), + ok = process_subdirs(Dir, Modules, Config, ModuleSetFile, Commands), %% Once we're all done processing, reset the code path to whatever %% the parent initialized it to @@ -297,6 +287,76 @@ process_dir(Dir, ParentConfig, Commands) -> ok end. + +%% +%% Run the preprocessors and execute commands on all newly +%% found Dirs until no new Dirs are found by the preprocessors. +%% +process_subdirs(Dir, Modules, Config, ModuleSetFile, Commands) -> + process_subdirs(Dir, Modules, Config, ModuleSetFile, Commands, sets:new()). + +process_subdirs(Dir, Modules, Config, ModuleSetFile, Commands, ProcessedDirs) -> + %% Give the modules a chance to tweak config and indicate if there + %% are any other dirs that might need processing first. + {UpdatedConfig, Dirs} = acc_modules(select_modules(Modules, preprocess, []), + preprocess, Config, ModuleSetFile, []), + ?DEBUG("~s subdirs: ~p\n", [Dir, Dirs]), + + %% Add ebin to path if this app has any plugins configured locally. + prep_plugin_modules(UpdatedConfig), + + %% Process subdirs that haven't already been processed. + F = fun (D, S) -> + case filelib:is_dir(D) andalso (not sets:is_element(D, S)) of + true -> + process_dir(D, UpdatedConfig, Commands), + sets:add_element(D, S); + false -> + S + end + end, + NewProcessedDirs = lists:foldl(F, sets:add_element(parent, ProcessedDirs), Dirs), + + %% http://bitbucket.org/basho/rebar/issue/5 + %% If the compiler ran, run the preprocess again because a new ebin dir + %% may have been produced. + {UpdatedConfig1, _} = case (Dirs =/= [] andalso + lists:member(compile, Commands)) of + true -> + acc_modules( + select_modules(Modules, preprocess, []), + preprocess, UpdatedConfig, ModuleSetFile, []); + false -> + {UpdatedConfig, Dirs} + end, + + %% Make sure the CWD is reset properly; processing subdirs may have caused it + %% to change + ok = file:set_cwd(Dir), + + %% Run the parent commands exactly once as well + case sets:is_element(parent, ProcessedDirs) of + true -> + ok; + false -> + %% Get the list of plug-in modules from rebar.config. These modules are + %% processed LAST and do not participate in preprocess. + {ok, PluginModules} = plugin_modules(UpdatedConfig1), + + %% Finally, process the current working directory + ?DEBUG("Commands: ~p Modules: ~p Plugins: ~p\n", [Commands, Modules, PluginModules]), + apply_commands(Commands, Modules ++ PluginModules, UpdatedConfig1, ModuleSetFile) + end, + + %% Repeat the process if there are new SeenDirs + case NewProcessedDirs =:= ProcessedDirs of + true -> + ok; + false -> + process_subdirs(Dir, Modules, UpdatedConfig1, ModuleSetFile, Commands, + NewProcessedDirs) + end. + %% %% Given a list of module sets from rebar.app and a directory, find %% the appropriate subset of modules for this directory @@ -312,6 +372,50 @@ choose_module_set([{Fn, Modules} | Rest], Dir) -> end. %% +%% Add ebin to path if there are any local plugin modules for this app. +%% +prep_plugin_modules(Config) -> + case rebar_config:get_local(Config, rebar_plugins, []) of + [_H | _T] -> + code:add_path(filename:join([rebar_utils:get_cwd(), "ebin"])); + _ -> + ok + end. + +%% +%% Return a flat list of rebar plugin modules. +%% +plugin_modules(Config) -> + Modules = lists:flatten(rebar_config:get_all(Config, rebar_plugins)), + plugin_modules(Config, ulist(Modules)). + +ulist(L) -> + ulist(L, sets:new(), []). + +ulist([], _S, Acc) -> + lists:reverse(Acc); +ulist([H | T], S, Acc) -> + case sets:is_element(H, S) of + true -> + ulist(T, S, Acc); + false -> + ulist(T, sets:add_element(H, S), [H | Acc]) + end. + +plugin_modules(_Config, []) -> + {ok, []}; +plugin_modules(_Config, Modules) -> + FoundModules = [M || M <- Modules, code:which(M) =/= non_existing], + case (Modules =:= FoundModules) of + true -> + ok; + false -> + ?DEBUG("Missing plugins: ~p\n", [Modules -- FoundModules]), + ok + end, + {ok, FoundModules}. + +%% %% Return .app file if the current directory is an OTP app %% app_dir(Dir) -> |