diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/rebar_config.erl | 39 | ||||
-rw-r--r-- | src/rebar_core.erl | 9 | ||||
-rw-r--r-- | src/rebar_deps.erl | 50 | ||||
-rw-r--r-- | src/rebar_subdirs.erl | 8 |
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}. |