summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rebar_config.erl39
-rw-r--r--src/rebar_core.erl9
-rw-r--r--src/rebar_deps.erl50
-rw-r--r--src/rebar_subdirs.erl8
4 files changed, 81 insertions, 25 deletions
diff --git a/src/rebar_config.erl b/src/rebar_config.erl
index 6ff31d5..0ca9b41 100644
--- a/src/rebar_config.erl
+++ b/src/rebar_config.erl
@@ -27,8 +27,9 @@
-module(rebar_config).
-export([new/0, new/1,
- get/3, get_list/3,
- delete/2,
+ get/3, get_local/3, get_list/3,
+ get_all/2,
+ set/3,
set_global/2, get_global/2,
is_verbose/0]).
@@ -52,24 +53,35 @@ new(ParentConfig) ->
ConfigFile = filename:join([Dir, "rebar.config"]),
case file:consult(ConfigFile) of
{ok, Terms} ->
- Opts = Terms ++ ParentConfig#config.opts;
+ %% Found a config file with some terms. We need to be able to
+ %% distinguish between local definitions (i.e. from the file
+ %% in the cwd) and inherited definitions. To accomplish this,
+ %% we use a marker in the proplist (since order matters) between
+ %% the new and old defs.
+ Opts = Terms ++ [local] ++ [Opt || Opt <- ParentConfig#config.opts, Opt /= local];
{error, enoent} ->
- Opts = ParentConfig#config.opts;
+ Opts = [local] ++ [Opt || Opt <- ParentConfig#config.opts, Opt /= local];
Other ->
Opts = undefined, % Keep erlc happy
- ?WARN("Failed to load ~s: ~p\n", [ConfigFile, Other]),
- ?FAIL
+ ?ABORT("Failed to load ~s: ~p\n", [ConfigFile, Other])
end,
#config { dir = Dir, opts = Opts }.
+get(Config, Key, Default) ->
+ proplists:get_value(Key, Config#config.opts, Default).
+
get_list(Config, Key, Default) ->
get(Config, Key, Default).
-get(Config, Key, Default) ->
- proplists:get_value(Key, Config#config.opts, Default).
+get_local(Config, Key, Default) ->
+ proplists:get_value(Key, local_opts(Config#config.opts, []), Default).
+
+get_all(Config, Key) ->
+ proplists:get_all_values(Key, Config#config.opts).
-delete(Config, Key) ->
- Config#config { opts = proplists:delete(Key, Config#config.opts) }.
+set(Config, Key, Value) ->
+ Opts = proplists:delete(Key, Config#config.opts),
+ Config#config { opts = [{Key, Value} | Opts] }.
set_global(Key, Value) ->
application:set_env(rebar_global, Key, Value).
@@ -94,3 +106,10 @@ is_verbose() ->
%% ===================================================================
%% Internal functions
%% ===================================================================
+
+local_opts([], Acc) ->
+ lists:reverse(Acc);
+local_opts([local | _Rest], Acc) ->
+ lists:reverse(Acc);
+local_opts([Item | Rest], Acc) ->
+ local_opts(Rest, [Item | Acc]).
diff --git a/src/rebar_core.erl b/src/rebar_core.erl
index eede6fa..9cb1b57 100644
--- a/src/rebar_core.erl
+++ b/src/rebar_core.erl
@@ -166,8 +166,13 @@ process_dir(Dir, ParentConfig, Commands) ->
%% 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),
+
%% Finally, process the current working directory
apply_commands(Commands, Modules, UpdatedConfig, ModuleSetFile),
@@ -243,7 +248,9 @@ update_code_path(Config) ->
restore_code_path(no_change) ->
ok;
restore_code_path({old, Path}) ->
- true = code:set_path(Path),
+ %% Verify that all of the paths still exist -- some dynamically add paths
+ %% can get blown away during clean.
+ true = code:set_path(lists:filter(fun filelib:is_file/1, Path)),
ok.
diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl
index 7e9c232..530dcd7 100644
--- a/src/rebar_deps.erl
+++ b/src/rebar_deps.erl
@@ -28,26 +28,45 @@
-include("rebar.hrl").
--export([preprocess/2]).
+-export([preprocess/2,
+ distclean/2]).
%% ===================================================================
%% Public API
%% ===================================================================
preprocess(Config, _) ->
- %% Get the directory where we will place downloaded deps
- DepsDir = rebar_config:get(Config, deps_dir, "deps"),
+ %% Get the directory where we will place downloaded deps. Take steps
+ %% to ensure that if we're doing a multi-level build, all the deps will
+ %% wind up in a single directory; avoiding potential pain from having
+ %% multiple copies of the same dep scattered throughout the source tree.
+ %%
+ %% The first definition of deps_dir is the one we use; we also fully
+ %% qualify it to ensure everyone sees it properly.
+ case rebar_config:get_all(Config, deps_dir) of
+ [] ->
+ DepsDir = filename:absname("deps");
+ AllDirs ->
+ DepsDir = filename:absname(hd(lists:reverse(AllDirs)))
+ end,
+
+ ?DEBUG("~s: Using deps dir: ~s\n", [rebar_utils:get_cwd(), DepsDir]),
+ Config2 = rebar_config:set(Config, deps_dir, DepsDir),
- %% Process the list of deps from the configuration
- case catch(process_deps(rebar_config:get(Config, deps, []), [], DepsDir)) of
+ %% Process the list of local deps from the configuration
+ case catch(process_deps(rebar_config:get_local(Config, deps, []), [], DepsDir)) of
Dirs when is_list(Dirs) ->
- %% Filter out deps from config so sub-dirs don't wind up trying to d/l deps again
- Config2 = rebar_config:delete(Config, deps),
{ok, Config2, Dirs};
{'EXIT', Reason} ->
?ABORT("Error while processing dependencies: ~p\n", [Reason])
end.
+distclean(Config, _) ->
+ %% Delete all the deps which we downloaded (or would have caused to be
+ %% downloaded).
+ DepsDir = rebar_config:get(Config, deps_dir, rebar_utils:get_cwd()),
+ ?DEBUG("Delete deps: ~p\n", [rebar_config:get(Config, deps, [])]),
+ delete_deps(rebar_config:get_local(Config, deps, []), DepsDir).
%% ===================================================================
%% Internal functions
@@ -62,7 +81,6 @@ process_deps([{App, VsnRegex} | Rest], Acc, Dir) when is_atom(App) ->
require_app(App, VsnRegex),
process_deps(Rest, Acc, Dir);
process_deps([{App, VsnRegex, Source} | Rest], Acc, Dir) ->
- ?DEBUG("Process deps: ~p\n", [Rest]),
case is_app_available(App, VsnRegex) of
true ->
process_deps(Rest, Acc, Dir);
@@ -80,6 +98,22 @@ process_deps([Other | _Rest], _Acc, _Dir) ->
[Other, rebar_utils:get_cwd()]).
+delete_deps([], _DepsDir) ->
+ ok;
+delete_deps([{App, _VsnRegex, _Source} | Rest], DepsDir) ->
+ AppDir = filename:join(DepsDir, App),
+ case filelib:is_dir(AppDir) of
+ true ->
+ ?INFO("Delete dependency dir ~s\n", [AppDir]),
+ rebar_file_utils:rm_rf(AppDir);
+ false ->
+ ok
+ end,
+ delete_deps(Rest, DepsDir);
+delete_deps([_Other | Rest], DepsDir) ->
+ delete_deps(Rest, DepsDir).
+
+
require_app(App, VsnRegex) ->
case is_app_available(App, VsnRegex) of
diff --git a/src/rebar_subdirs.erl b/src/rebar_subdirs.erl
index cb8f79b..81f588d 100644
--- a/src/rebar_subdirs.erl
+++ b/src/rebar_subdirs.erl
@@ -37,10 +37,6 @@
preprocess(Config, _) ->
%% Get the list of subdirs specified in the config (if any).
Cwd = rebar_utils:get_cwd(),
- Subdirs = [filename:join(Cwd, Dir) || Dir <- rebar_config:get(Config, sub_dirs, [])],
-
- %% Filter out the subdirs from the config so that processing in the
- %% subdirs doesn't try to reprocess
- Config2 = rebar_config:delete(Config, sub_dirs),
- {ok, Config2, Subdirs}.
+ Subdirs = [filename:join(Cwd, Dir) || Dir <- rebar_config:get_local(Config, sub_dirs, [])],
+ {ok, Config, Subdirs}.