summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rebar_base_compiler.erl3
-rw-r--r--src/rebar_core.erl138
-rw-r--r--src/rebar_deps.erl4
-rw-r--r--src/rebar_erlc_compiler.erl3
4 files changed, 127 insertions, 21 deletions
diff --git a/src/rebar_base_compiler.erl b/src/rebar_base_compiler.erl
index 8ca0a7b..a83ffe5 100644
--- a/src/rebar_base_compiler.erl
+++ b/src/rebar_base_compiler.erl
@@ -179,7 +179,8 @@ compile_worker(QueuePid, Config, CompileFn) ->
QueuePid ! {skipped, Source},
compile_worker(QueuePid, Config, CompileFn);
Error ->
- QueuePid ! {fail, Error},
+ QueuePid ! {fail, [{error, Error},
+ {source, Source}]},
ok
end;
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) ->
diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl
index 46d7657..7d07ff4 100644
--- a/src/rebar_deps.erl
+++ b/src/rebar_deps.erl
@@ -254,11 +254,11 @@ use_source(AppDir, App, VsnRegex, Source, Count) ->
download_source(AppDir, {hg, Url, Rev}) ->
ok = filelib:ensure_dir(AppDir),
- rebar_utils:sh(?FMT("hg clone -U ~s", [Url]), [], filename:dirname(AppDir)),
+ rebar_utils:sh(?FMT("hg clone -U ~s ~s", [Url, filename:basename(AppDir)]), [], filename:dirname(AppDir)),
rebar_utils:sh(?FMT("hg update ~s", [Rev]), [], AppDir);
download_source(AppDir, {git, Url, Rev}) ->
ok = filelib:ensure_dir(AppDir),
- rebar_utils:sh(?FMT("git clone -n ~s", [Url]), [], filename:dirname(AppDir)),
+ rebar_utils:sh(?FMT("git clone -n ~s ~s", [Url, filename:basename(AppDir)]), [], filename:dirname(AppDir)),
rebar_utils:sh(?FMT("git checkout ~s", [Rev]), [], AppDir);
download_source(AppDir, {bzr, Url, Rev}) ->
ok = filelib:ensure_dir(AppDir),
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index 8cdaf75..ea17b30 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -116,7 +116,8 @@ doterl_compile(Config, OutDir, MoreSources) ->
[{F, compile_priority(F)} || F <- RestErls ])],
- %% Make sure that ebin/ is on the path
+ %% Make sure that ebin/ exists and is on the path
+ ok = filelib:ensure_dir(filename:join("ebin", "dummy.beam")),
CurrPath = code:get_path(),
code:add_path("ebin"),
rebar_base_compiler:run(Config, FirstErls, SortedRestErls,