summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rebar.erl13
-rw-r--r--src/rebar_app_utils.erl95
-rw-r--r--src/rebar_appups.erl6
-rw-r--r--src/rebar_config.erl118
-rw-r--r--src/rebar_core.erl243
-rw-r--r--src/rebar_deps.erl231
-rw-r--r--src/rebar_edoc.erl7
-rw-r--r--src/rebar_escripter.erl13
-rw-r--r--src/rebar_eunit.erl54
-rw-r--r--src/rebar_otp_app.erl34
-rw-r--r--src/rebar_port_compiler.erl37
-rw-r--r--src/rebar_rel_utils.erl29
-rw-r--r--src/rebar_reltool.erl21
-rw-r--r--src/rebar_subdirs.erl2
-rw-r--r--src/rebar_upgrade.erl6
-rw-r--r--src/rebar_utils.erl17
16 files changed, 496 insertions, 430 deletions
diff --git a/src/rebar.erl b/src/rebar.erl
index 0b7602b..5812170 100644
--- a/src/rebar.erl
+++ b/src/rebar.erl
@@ -103,9 +103,6 @@ run_aux(Commands) ->
%% Initialize logging system
rebar_log:init(),
- %% Initialize vsn cache
- _VsnCacheTab = ets:new(rebar_vsn_cache,[named_table, public]),
-
%% Convert command strings to atoms
CommandAtoms = [list_to_atom(C) || C <- Commands],
@@ -118,9 +115,6 @@ run_aux(Commands) ->
%% Note the top-level directory for reference
rebar_config:set_global(base_dir, filename:absname(rebar_utils:get_cwd())),
- %% Keep track of how many operations we do, so we can detect bad commands
- erlang:put(operations, 0),
-
%% If $HOME/.rebar/config exists load and use as global config
GlobalConfigFile = filename:join([os:getenv("HOME"), ".rebar", "config"]),
GlobalConfig = case filelib:is_regular(GlobalConfigFile) of
@@ -133,8 +127,13 @@ run_aux(Commands) ->
end,
BaseConfig = rebar_config:base_config(GlobalConfig),
+ %% Keep track of how many operations we do, so we can detect bad commands
+ BaseConfig1 = rebar_config:set_xconf(BaseConfig, operations, 0),
+ %% Initialize vsn cache
+ BaseConfig2 = rebar_config:set_xconf(BaseConfig1, vsn_cache, dict:new()),
+
%% Process each command, resetting any state between each one
- rebar_core:process_commands(CommandAtoms, BaseConfig).
+ rebar_core:process_commands(CommandAtoms, BaseConfig2).
%%
%% print help/usage string
diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl
index dbc2c44..1d2583a 100644
--- a/src/rebar_app_utils.erl
+++ b/src/rebar_app_utils.erl
@@ -29,12 +29,12 @@
-export([is_app_dir/0, is_app_dir/1,
is_app_src/1,
app_src_to_app/1,
- app_name/1,
- app_applications/1,
- app_vsn/1,
- is_skipped_app/1]).
+ app_name/2,
+ app_applications/2,
+ app_vsn/2,
+ is_skipped_app/2]).
--export([load_app_file/1]). % TEMPORARY
+-export([load_app_file/2]). % TEMPORARY
-include("rebar.hrl").
@@ -77,75 +77,80 @@ is_app_src(Filename) ->
app_src_to_app(Filename) ->
filename:join("ebin", filename:basename(Filename, ".app.src") ++ ".app").
-app_name(AppFile) ->
- case load_app_file(AppFile) of
- {ok, AppName, _} ->
- AppName;
+app_name(Config, AppFile) ->
+ case load_app_file(Config, AppFile) of
+ {ok, NewConfig, AppName, _} ->
+ {NewConfig, AppName};
{error, Reason} ->
?ABORT("Failed to extract name from ~s: ~p\n",
[AppFile, Reason])
end.
-app_applications(AppFile) ->
- case load_app_file(AppFile) of
- {ok, _, AppInfo} ->
- get_value(applications, AppInfo, AppFile);
+app_applications(Config, AppFile) ->
+ case load_app_file(Config, AppFile) of
+ {ok, NewConfig, _, AppInfo} ->
+ {NewConfig, get_value(applications, AppInfo, AppFile)};
{error, Reason} ->
?ABORT("Failed to extract applications from ~s: ~p\n",
[AppFile, Reason])
end.
-app_vsn(AppFile) ->
- case load_app_file(AppFile) of
- {ok, _, AppInfo} ->
+app_vsn(Config, AppFile) ->
+ case load_app_file(Config, AppFile) of
+ {ok, Config1, _, AppInfo} ->
AppDir = filename:dirname(filename:dirname(AppFile)),
- rebar_utils:vcs_vsn(get_value(vsn, AppInfo, AppFile), AppDir);
+ rebar_utils:vcs_vsn(Config1, get_value(vsn, AppInfo, AppFile),
+ AppDir);
{error, Reason} ->
?ABORT("Failed to extract vsn from ~s: ~p\n",
[AppFile, Reason])
end.
-is_skipped_app(AppFile) ->
- ThisApp = app_name(AppFile),
+is_skipped_app(Config, AppFile) ->
+ {Config1, ThisApp} = app_name(Config, AppFile),
%% Check for apps global parameter; this is a comma-delimited list
%% of apps on which we want to run commands
- case get_apps() of
- undefined ->
- %% No apps parameter specified, check the skip_apps list..
- case get_skip_apps() of
- undefined ->
- %% No skip_apps list, run everything..
- false;
- SkipApps ->
- TargetApps = [list_to_atom(A) ||
- A <- string:tokens(SkipApps, ",")],
- is_skipped_app(ThisApp, TargetApps)
- end;
- Apps ->
- %% run only selected apps
- TargetApps = [list_to_atom(A) || A <- string:tokens(Apps, ",")],
- is_selected_app(ThisApp, TargetApps)
- end.
+ Skipped =
+ case get_apps() of
+ undefined ->
+ %% No apps parameter specified, check the skip_apps list..
+ case get_skip_apps() of
+ undefined ->
+ %% No skip_apps list, run everything..
+ false;
+ SkipApps ->
+ TargetApps = [list_to_atom(A) ||
+ A <- string:tokens(SkipApps, ",")],
+ is_skipped(ThisApp, TargetApps)
+ end;
+ Apps ->
+ %% run only selected apps
+ TargetApps = [list_to_atom(A) || A <- string:tokens(Apps, ",")],
+ is_selected(ThisApp, TargetApps)
+ end,
+ {Config1, Skipped}.
%% ===================================================================
%% Internal functions
%% ===================================================================
-load_app_file(Filename) ->
+load_app_file(Config, Filename) ->
AppFile = {app_file, Filename},
- case erlang:get(AppFile) of
- undefined ->
+ case rebar_config:get_xconf(Config, {appfile, AppFile}) of
+ error ->
case file:consult(Filename) of
{ok, [{application, AppName, AppData}]} ->
- erlang:put(AppFile, {AppName, AppData}),
- {ok, AppName, AppData};
+ Config1 = rebar_config:set_xconf(Config,
+ {appfile, AppFile},
+ {AppName, AppData}),
+ {ok, Config1, AppName, AppData};
{error, _} = Error ->
Error;
Other ->
{error, {unexpected_terms, Other}}
end;
- {AppName, AppData} ->
- {ok, AppName, AppData}
+ {ok, {AppName, AppData}} ->
+ {ok, Config, AppName, AppData}
end.
get_value(Key, AppInfo, AppFile) ->
@@ -157,7 +162,7 @@ get_value(Key, AppInfo, AppFile) ->
end.
%% apps= for selecting apps
-is_selected_app(ThisApp, TargetApps) ->
+is_selected(ThisApp, TargetApps) ->
case lists:member(ThisApp, TargetApps) of
false ->
{true, ThisApp};
@@ -166,7 +171,7 @@ is_selected_app(ThisApp, TargetApps) ->
end.
%% skip_apps= for filtering apps
-is_skipped_app(ThisApp, TargetApps) ->
+is_skipped(ThisApp, TargetApps) ->
case lists:member(ThisApp, TargetApps) of
false ->
false;
diff --git a/src/rebar_appups.erl b/src/rebar_appups.erl
index 6271e77..88cf8d9 100644
--- a/src/rebar_appups.erl
+++ b/src/rebar_appups.erl
@@ -38,9 +38,9 @@
%% Public API
%% ====================================================================
-'generate-appups'(_Config, ReltoolFile) ->
+'generate-appups'(Config, ReltoolFile) ->
%% Get the old release path
- ReltoolConfig = rebar_rel_utils:load_config(ReltoolFile),
+ {Config1, ReltoolConfig} = rebar_rel_utils:load_config(Config, ReltoolFile),
TargetParentDir = rebar_rel_utils:get_target_parent_dir(ReltoolConfig),
OldVerPath = filename:join([TargetParentDir,
@@ -75,7 +75,7 @@
%% Generate appup files for upgraded apps
generate_appup_files(NewVerPath, OldVerPath, UpgradeApps),
- ok.
+ {ok, Config1}.
%% ===================================================================
%% Internal functions
diff --git a/src/rebar_config.erl b/src/rebar_config.erl
index 7f7d03c..c2d59b2 100644
--- a/src/rebar_config.erl
+++ b/src/rebar_config.erl
@@ -32,13 +32,19 @@
set/3,
set_global/2, get_global/2,
is_verbose/0, get_jobs/0,
- set_env/3, get_env/2]).
+ set_env/3, get_env/2,
+ set_skip_dir/2, is_skip_dir/2, reset_skip_dirs/1,
+ clean_config/2,
+ set_xconf/3, get_xconf/2, erase_xconf/2, reset_xconf/1]).
-include("rebar.hrl").
-record(config, { dir :: file:filename(),
opts = [] :: list(),
- envs = new_env() :: dict() }).
+ envs = new_env() :: dict(),
+ %% cross-directory config
+ skip_dirs = new_skip_dirs() :: dict(),
+ xconf = new_xconf() :: dict() }).
%% Types that can be used from other modules -- alphabetically ordered.
-export_type([config/0]).
@@ -46,13 +52,15 @@
%% data types
-opaque config() :: #config{}.
+-define(DEFAULT_NAME, "rebar.config").
+
%% ===================================================================
%% Public API
%% ===================================================================
-base_config(#config{opts=Opts0}) ->
- ConfName = rebar_config:get_global(config, "rebar.config"),
- new(Opts0, ConfName).
+base_config(GlobalConfig) ->
+ ConfName = rebar_config:get_global(config, ?DEFAULT_NAME),
+ new(GlobalConfig, ConfName).
new() ->
#config{dir = rebar_utils:get_cwd()}.
@@ -65,31 +73,8 @@ new(ConfigFile) when is_list(ConfigFile) ->
Other ->
?ABORT("Failed to load ~s: ~p~n", [ConfigFile, Other])
end;
-new(_ParentConfig=#config{opts=Opts0})->
- new(Opts0, "rebar.config").
-
-new(Opts0, ConfName) ->
- %% Load terms from rebar.config, if it exists
- Dir = rebar_utils:get_cwd(),
- ConfigFile = filename:join([Dir, ConfName]),
- Opts = case consult_file(ConfigFile) of
- {ok, Terms} ->
- %% 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.
- Terms ++ [local] ++
- [Opt || Opt <- Opts0, Opt /= local];
- {error, enoent} ->
- [local] ++
- [Opt || Opt <- Opts0, Opt /= local];
- Other ->
- ?ABORT("Failed to load ~s: ~p\n", [ConfigFile, Other])
- end,
-
- #config{dir = Dir, opts = Opts}.
+new(_ParentConfig=#config{opts=Opts0, skip_dirs=SkipDirs, xconf=Xconf})->
+ new(#config{opts=Opts0, skip_dirs=SkipDirs, xconf=Xconf}, ?DEFAULT_NAME).
get(Config, Key, Default) ->
proplists:get_value(Key, Config#config.opts, Default).
@@ -145,17 +130,74 @@ consult_file(File) ->
end.
set_env(Config, Mod, Env) ->
- OldEnvs = Config#config.envs,
- NewEnvs = dict:store(Mod, Env, OldEnvs),
- Config#config{envs=NewEnvs}.
+ NewEnvs = dict:store(Mod, Env, Config#config.envs),
+ Config#config{envs = NewEnvs}.
get_env(Config, Mod) ->
dict:fetch(Mod, Config#config.envs).
+set_skip_dir(Config, Dir) ->
+ OldSkipDirs = Config#config.skip_dirs,
+ NewSkipDirs = case is_skip_dir(Config, Dir) of
+ false ->
+ ?DEBUG("Adding skip dir: ~s\n", [Dir]),
+ dict:store(Dir, true, OldSkipDirs);
+ true ->
+ OldSkipDirs
+ end,
+ Config#config{skip_dirs = NewSkipDirs}.
+
+is_skip_dir(Config, Dir) ->
+ dict:is_key(Dir, Config#config.skip_dirs).
+
+reset_skip_dirs(Config) ->
+ Config#config{skip_dirs = new_skip_dirs()}.
+
+set_xconf(Config, Key, Value) ->
+ NewXconf = dict:store(Key, Value, Config#config.xconf),
+ Config#config{xconf=NewXconf}.
+
+get_xconf(Config, Key) ->
+ dict:find(Key, Config#config.xconf).
+
+erase_xconf(Config, Key) ->
+ NewXconf = dict:erase(Key, Config#config.xconf),
+ Config#config{xconf = NewXconf}.
+
+reset_xconf(Config) ->
+ Config#config{xconf = new_xconf()}.
+
+clean_config(Old, New) ->
+ New#config{opts=Old#config.opts}.
+
%% ===================================================================
%% Internal functions
%% ===================================================================
+new(ParentConfig, ConfName) ->
+ %% Load terms from rebar.config, if it exists
+ Dir = rebar_utils:get_cwd(),
+ ConfigFile = filename:join([Dir, ConfName]),
+ Opts0 = ParentConfig#config.opts,
+ Opts = case consult_file(ConfigFile) of
+ {ok, Terms} ->
+ %% 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.
+ Terms ++ [local] ++
+ [Opt || Opt <- Opts0, Opt /= local];
+ {error, enoent} ->
+ [local] ++
+ [Opt || Opt <- Opts0, Opt /= local];
+ Other ->
+ ?ABORT("Failed to load ~s: ~p\n", [ConfigFile, Other])
+ end,
+
+ ParentConfig#config{dir = Dir, opts = Opts}.
+
consult_and_eval(File, Script) ->
?DEBUG("Evaluating config script ~p~n", [Script]),
ConfigData = try_consult(File),
@@ -171,7 +213,8 @@ try_consult(File) ->
{ok, Terms} ->
?DEBUG("Consult config file ~p~n", [File]),
Terms;
- {error, enoent} -> [];
+ {error, enoent} ->
+ [];
{error, Reason} ->
?ABORT("Failed to read config file ~s: ~p~n", [File, Reason])
end.
@@ -188,5 +231,8 @@ local_opts([local | _Rest], Acc) ->
local_opts([Item | Rest], Acc) ->
local_opts(Rest, [Item | Acc]).
-new_env() ->
- dict:new().
+new_env() -> dict:new().
+
+new_skip_dirs() -> dict:new().
+
+new_xconf() -> dict:new().
diff --git a/src/rebar_core.erl b/src/rebar_core.erl
index 99d3c38..b175f50 100644
--- a/src/rebar_core.erl
+++ b/src/rebar_core.erl
@@ -26,46 +26,17 @@
%% -------------------------------------------------------------------
-module(rebar_core).
--export([process_commands/2,
- skip_dir/1,
- is_skip_dir/1,
- skip_dirs/0]).
+-export([process_commands/2]).
-include("rebar.hrl").
-
-%% ===================================================================
-%% Public API
-%% ===================================================================
-
-skip_dir(Dir) ->
- SkipDir = {skip_dir, Dir},
- case erlang:get(SkipDir) of
- undefined ->
- ?DEBUG("Adding skip dir: ~s\n", [Dir]),
- erlang:put(SkipDir, true);
- true ->
- ok
- end.
-
-is_skip_dir(Dir) ->
- case erlang:get({skip_dir, Dir}) of
- undefined ->
- false;
- true ->
- true
- end.
-
-skip_dirs() ->
- [Dir || {{skip_dir, Dir}, true} <- erlang:get()].
-
%% ===================================================================
%% Internal functions
%% ===================================================================
-process_commands([], _ParentConfig) ->
+process_commands([], ParentConfig) ->
AbortTrapped = rebar_config:get_global(abort_trapped, false),
- case {erlang:get(operations), AbortTrapped} of
+ case {get_operations(ParentConfig), AbortTrapped} of
{0, _} ->
%% None of the commands had any effect
?ABORT;
@@ -76,47 +47,49 @@ process_commands([], _ParentConfig) ->
ok
end;
process_commands([Command | Rest], ParentConfig) ->
- try
- %% Reset skip dirs
- lists:foreach(fun (D) -> erlang:erase({skip_dir, D}) end, skip_dirs()),
- Operations = erlang:get(operations),
-
- %% Convert the code path so that all the entries are absolute paths.
- %% If not, code:set_path() may choke on invalid relative paths when
- %% trying to restore the code path from inside a subdirectory.
- true = rebar_utils:expand_code_path(),
- _ = process_dir(rebar_utils:get_cwd(), ParentConfig,
- Command, sets:new()),
- case erlang:get(operations) of
- Operations ->
- %% This command didn't do anything
- ?CONSOLE("Command '~p' not understood or not applicable~n",
- [Command]);
- _ ->
- ok
- end,
- %% Wipe out vsn cache to avoid invalid hits when
- %% dependencies are updated
- ets:delete_all_objects(rebar_vsn_cache)
- catch
- throw:rebar_abort ->
- case rebar_config:get_global(keep_going, false) of
- false ->
- ?ABORT;
- true ->
- ?WARN("Continuing on after abort: ~p\n", [Rest]),
- rebar_config:set_global(abort_trapped, true),
+ %% Reset skip dirs
+ ParentConfig1 = rebar_config:reset_skip_dirs(ParentConfig),
+ Operations = rebar_config:get_xconf(ParentConfig1, operations),
+
+ ParentConfig4 =
+ try
+ %% Convert the code path so that all the entries are absolute paths.
+ %% If not, code:set_path() may choke on invalid relative paths when trying
+ %% to restore the code path from inside a subdirectory.
+ true = rebar_utils:expand_code_path(),
+ {ParentConfig2, _DirSet} = process_dir(rebar_utils:get_cwd(),
+ ParentConfig1, Command,
+ sets:new()),
+ case get_operations(ParentConfig2) of
+ Operations ->
+ %% This command didn't do anything
+ ?CONSOLE("Command '~p' not understood or not applicable~n",
+ [Command]);
+ _ ->
ok
- end
- end,
- process_commands(Rest, ParentConfig).
-
+ end,
+ ParentConfig3 = rebar_config:clean_config(ParentConfig1, ParentConfig2),
+ %% Wipe out vsn cache to avoid invalid hits when
+ %% dependencies are updated
+ rebar_config:set_xconf(ParentConfig3, vsn_cache, dict:new())
+ catch
+ throw:rebar_abort ->
+ case rebar_config:get_global(keep_going, false) of
+ false ->
+ ?ABORT;
+ true ->
+ ?WARN("Continuing on after abort: ~p\n", [Rest]),
+ rebar_config:set_global(abort_trapped, true),
+ ParentConfig1
+ end
+ end,
+ process_commands(Rest, ParentConfig4).
process_dir(Dir, ParentConfig, Command, DirSet) ->
case filelib:is_dir(Dir) of
false ->
?WARN("Skipping non-existent sub-dir: ~p\n", [Dir]),
- DirSet;
+ {ParentConfig, DirSet};
true ->
ok = file:set_cwd(Dir),
@@ -157,13 +130,13 @@ maybe_process_dir({_, ModuleSetFile}=ModuleSet, Config, CurrentCodePath,
maybe_process_dir0(AppFile, ModuleSet, Config, CurrentCodePath,
Dir, Command, DirSet) ->
- case rebar_app_utils:is_skipped_app(AppFile) of
- {true, SkippedApp} ->
+ case rebar_app_utils:is_skipped_app(Config, AppFile) of
+ {Config1, {true, SkippedApp}} ->
?DEBUG("Skipping app: ~p~n", [SkippedApp]),
- increment_operations(),
- DirSet;
- false ->
- process_dir0(Dir, Command, DirSet, Config,
+ Config2 = increment_operations(Config1),
+ {Config2, DirSet};
+ {Config1, false} ->
+ process_dir0(Dir, Command, DirSet, Config1,
CurrentCodePath, ModuleSet)
end.
@@ -179,64 +152,63 @@ process_dir0(Dir, Command, DirSet, Config0, CurrentCodePath,
%% Invoke 'preprocess' on the modules -- this yields a list of other
%% directories that should be processed _before_ the current one.
- Predirs = acc_modules(Modules, preprocess, Config0, ModuleSetFile),
+ {Config1, Predirs} = acc_modules(Modules, preprocess, Config0,
+ ModuleSetFile),
SubdirAssoc = remember_cwd_subdir(Dir, Predirs),
%% Get the list of plug-in modules from rebar.config. These
%% modules may participate in preprocess and postprocess.
- {ok, PluginModules} = plugin_modules(Config0, SubdirAssoc),
+ {ok, PluginModules} = plugin_modules(Config1, SubdirAssoc),
- PluginPredirs = acc_modules(PluginModules, preprocess,
- Config0, ModuleSetFile),
+ {Config2, PluginPredirs} = acc_modules(PluginModules, preprocess,
+ Config1, ModuleSetFile),
AllPredirs = Predirs ++ PluginPredirs,
?DEBUG("Predirs: ~p\n", [AllPredirs]),
- DirSet2 = process_each(AllPredirs, Command, Config0,
- ModuleSetFile, DirSet),
+ {Config3, DirSet2} = process_each(AllPredirs, Command, Config2,
+ ModuleSetFile, DirSet),
%% Make sure the CWD is reset properly; processing the dirs may have
%% caused it to change
ok = file:set_cwd(Dir),
%% Check that this directory is not on the skip list
- Config = case is_skip_dir(Dir) of
- true ->
- %% Do not execute the command on the directory, as some
- %% module has requested a skip on it.
- ?INFO("Skipping ~s in ~s\n", [Command, Dir]),
- Config0;
-
- false ->
- %% Check for and get command specific environments
- {Config1, Env} = setup_envs(Config0, Modules),
-
- %% Execute any before_command plugins on this directory
- execute_pre(Command, PluginModules,
- Config1, ModuleSetFile, Env),
-
- %% Execute the current command on this directory
- execute(Command, Modules ++ PluginModules,
- Config1, ModuleSetFile, Env),
-
- %% Execute any after_command plugins on this directory
- execute_post(Command, PluginModules,
- Config1, ModuleSetFile, Env),
-
- Config1
- end,
+ Config7 = case rebar_config:is_skip_dir(Config3, Dir) of
+ true ->
+ %% Do not execute the command on the directory, as some
+ %% module has requested a skip on it.
+ ?INFO("Skipping ~s in ~s\n", [Command, Dir]),
+ Config3;
+
+ false ->
+ %% Check for and get command specific environments
+ {Config4, Env} = setup_envs(Config3, Modules),
+
+ %% Execute any before_command plugins on this directory
+ Config5 = execute_pre(Command, PluginModules,
+ Config4, ModuleSetFile, Env),
+
+ %% Execute the current command on this directory
+ Config6 = execute(Command, Modules ++ PluginModules,
+ Config5, ModuleSetFile, Env),
+
+ %% Execute any after_command plugins on this directory
+ execute_post(Command, PluginModules,
+ Config6, ModuleSetFile, Env)
+ end,
%% Mark the current directory as processed
DirSet3 = sets:add_element(Dir, DirSet2),
%% Invoke 'postprocess' on the modules. This yields a list of other
%% directories that should be processed _after_ the current one.
- Postdirs = acc_modules(Modules ++ PluginModules, postprocess,
- Config, ModuleSetFile),
+ {Config8, Postdirs} = acc_modules(Modules ++ PluginModules, postprocess,
+ Config7, ModuleSetFile),
?DEBUG("Postdirs: ~p\n", [Postdirs]),
- DirSet4 = process_each(Postdirs, Command, Config,
- ModuleSetFile, DirSet3),
+ Res = process_each(Postdirs, Command, Config8,
+ ModuleSetFile, DirSet3),
%% Make sure the CWD is reset properly; processing the dirs may have
%% caused it to change
@@ -246,8 +218,8 @@ process_dir0(Dir, Command, DirSet, Config0, CurrentCodePath,
%% the parent initialized it to
restore_code_path(CurrentCodePath),
- %% Return the updated dirset as our result
- DirSet4.
+ %% Return the updated {config, dirset} as our result
+ Res.
remember_cwd_subdir(Cwd, Subdirs) ->
Store = fun(Dir, Dict) ->
@@ -283,16 +255,17 @@ processing_base_dir(Dir) ->
%% Given a list of directories and a set of previously processed directories,
%% process each one we haven't seen yet
%%
-process_each([], _Command, _Config, _ModuleSetFile, DirSet) ->
- DirSet;
+process_each([], _Command, Config, _ModuleSetFile, DirSet) ->
+ {Config, DirSet};
process_each([Dir | Rest], Command, Config, ModuleSetFile, DirSet) ->
case sets:is_element(Dir, DirSet) of
true ->
?DEBUG("Skipping ~s; already processed!\n", [Dir]),
process_each(Rest, Command, Config, ModuleSetFile, DirSet);
false ->
- DirSet2 = process_dir(Dir, Config, Command, DirSet),
- process_each(Rest, Command, Config, ModuleSetFile, DirSet2)
+ {Config1, DirSet2} = process_dir(Dir, Config, Command, DirSet),
+ Config2 = rebar_config:clean_config(Config, Config1),
+ process_each(Rest, Command, Config2, ModuleSetFile, DirSet2)
end.
@@ -343,22 +316,23 @@ execute(Command, Modules, Config, ModuleFile, Env) ->
false ->
?WARN("'~p' command does not apply to directory ~s\n",
[Command, rebar_utils:get_cwd()])
- end;
+ end,
+ Config;
TargetModules ->
%% Provide some info on where we are
Dir = rebar_utils:get_cwd(),
?CONSOLE("==> ~s (~s)\n", [filename:basename(Dir), Command]),
- increment_operations(),
+ Config1 = increment_operations(Config),
%% Run the available modules
- apply_hooks(pre_hooks, Config, Command, Env),
+ apply_hooks(pre_hooks, Config1, Command, Env),
case catch(run_modules(TargetModules, Command,
- Config, ModuleFile)) of
- ok ->
- apply_hooks(post_hooks, Config, Command, Env),
- ok;
+ Config1, ModuleFile)) of
+ {ok, NewConfig} ->
+ apply_hooks(post_hooks, NewConfig, Command, Env),
+ NewConfig;
{error, failed} ->
?ABORT;
{Module, {error, _} = Other} ->
@@ -373,9 +347,13 @@ execute(Command, Modules, Config, ModuleFile, Env) ->
%% Increment the count of operations, since some module
%% responds to this command
-increment_operations() ->
- erlang:put(operations, erlang:get(operations) + 1).
+increment_operations(Config) ->
+ Operations = get_operations(Config),
+ rebar_config:set_xconf(Config, operations, Operations + 1).
+get_operations(Config) ->
+ {ok, Operations} = rebar_config:get_xconf(Config, operations),
+ Operations.
update_code_path(Config) ->
case rebar_config:get_local(Config, lib_dirs, []) of
@@ -417,12 +395,14 @@ select_modules([Module | Rest], Command, Acc) ->
select_modules(Rest, Command, Acc)
end.
-run_modules([], _Command, _Config, _File) ->
- ok;
+run_modules([], _Command, Config, _File) ->
+ {ok, Config};
run_modules([Module | Rest], Command, Config, File) ->
case Module:Command(Config, File) of
ok ->
run_modules(Rest, Command, Config, File);
+ {ok, NewConfig} ->
+ run_modules(Rest, Command, NewConfig, File);
{error, _} = Error ->
{Module, Error}
end.
@@ -461,11 +441,16 @@ acc_modules(Modules, Command, Config, File) ->
acc_modules(select_modules(Modules, Command, []),
Command, Config, File, []).
-acc_modules([], _Command, _Config, _File, Acc) ->
- Acc;
+acc_modules([], _Command, Config, _File, Acc) ->
+ {Config, Acc};
acc_modules([Module | Rest], Command, Config, File, Acc) ->
- {ok, Dirs} = Module:Command(Config, File),
- acc_modules(Rest, Command, Config, File, Acc ++ Dirs).
+ {Config1, Dirs1} = case Module:Command(Config, File) of
+ {ok, Dirs} ->
+ {Config, Dirs};
+ {ok, NewConfig, Dirs} ->
+ {NewConfig, Dirs}
+ end,
+ acc_modules(Rest, Command, Config1, File, Acc ++ Dirs1).
%%
%% Return a flat list of rebar plugin modules.
diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl
index dc2fe84..1abdce7 100644
--- a/src/rebar_deps.erl
+++ b/src/rebar_deps.erl
@@ -57,37 +57,37 @@ preprocess(Config, _) ->
%% Get the list of deps for the current working directory and identify those
%% deps that are available/present.
Deps = rebar_config:get_local(Config, deps, []),
- {AvailableDeps, MissingDeps} = find_deps(find, Deps),
+ {Config1, {AvailableDeps, MissingDeps}} = find_deps(Config, find, Deps),
?DEBUG("Available deps: ~p\n", [AvailableDeps]),
?DEBUG("Missing deps : ~p\n", [MissingDeps]),
%% Add available deps to code path
- update_deps_code_path(AvailableDeps),
+ Config2 = update_deps_code_path(Config1, AvailableDeps),
%% If skip_deps=true, mark each dep dir as a skip_dir w/ the core so that
%% the current command doesn't run on the dep dir. However, pre/postprocess
%% WILL run (and we want it to) for transitivity purposes.
- case rebar_config:get_global(skip_deps, false) of
- "true" ->
- lists:foreach(fun (#dep{dir = Dir}) ->
- rebar_core:skip_dir(Dir)
- end, AvailableDeps);
- _ ->
- ok
- end,
+ NewConfig = case rebar_config:get_global(skip_deps, false) of
+ "true" ->
+ lists:foldl(
+ fun(#dep{dir = Dir}, C) ->
+ rebar_config:set_skip_dir(C, Dir)
+ end, Config2, AvailableDeps);
+ _ ->
+ Config2
+ end,
%% Return all the available dep directories for process
- {ok, [D#dep.dir || D <- AvailableDeps]}.
-
+ {ok, NewConfig, dep_dirs(AvailableDeps)}.
-postprocess(_Config, _) ->
- case erlang:get(?MODULE) of
- undefined ->
+postprocess(Config, _) ->
+ case rebar_config:get_xconf(Config, ?MODULE) of
+ error ->
{ok, []};
- Dirs ->
- erlang:erase(?MODULE),
- {ok, Dirs}
+ {ok, Dirs} ->
+ NewConfig = rebar_config:erase_xconf(Config, ?MODULE),
+ {ok, NewConfig, Dirs}
end.
compile(Config, AppFile) ->
@@ -114,11 +114,11 @@ setup_env(_Config) ->
'check-deps'(Config, _) ->
%% Get the list of immediate (i.e. non-transitive) deps that are missing
Deps = rebar_config:get_local(Config, deps, []),
- case find_deps(find, Deps) of
- {_, []} ->
+ case find_deps(Config, find, Deps) of
+ {Config1, {_, []}} ->
%% No missing deps
- ok;
- {_, MissingDeps} ->
+ {ok, Config1};
+ {_Config1, {_, MissingDeps}} ->
lists:foreach(fun (#dep{app=App, vsn_regex=Vsn, source=Src}) ->
?CONSOLE("Dependency not available: "
"~p-~s (~p)\n", [App, Vsn, Src])
@@ -129,47 +129,52 @@ setup_env(_Config) ->
'get-deps'(Config, _) ->
%% Determine what deps are available and missing
Deps = rebar_config:get_local(Config, deps, []),
- {_AvailableDeps, MissingDeps} = find_deps(find, Deps),
+ {Config1, {_AvailableDeps, MissingDeps}} = find_deps(Config, find, Deps),
+ MissingDeps1 = [D || D <- MissingDeps, D#dep.source =/= undefined],
%% For each missing dep with a specified source, try to pull it.
- PulledDeps = [use_source(D) || D <- MissingDeps, D#dep.source /= undefined],
+ {Config2, PulledDeps} =
+ lists:foldl(fun(D, {C, PulledDeps0}) ->
+ {C1, D1} = use_source(C, D),
+ {C1, [D1 | PulledDeps0]}
+ end, {Config1, []}, MissingDeps1),
%% Add each pulled dep to our list of dirs for post-processing. This yields
%% the necessary transitivity of the deps
- erlang:put(?MODULE, [D#dep.dir || D <- PulledDeps]),
- ok.
+ {ok, save_dep_dirs(Config2, lists:reverse(PulledDeps))}.
'update-deps'(Config, _) ->
- %% Determine what deps are available and missing
- Deps = rebar_config:get_local(Config, deps, []),
- UpdatedDeps = [update_source(D) || D <- find_deps(read, Deps),
- D#dep.source /= undefined],
+ %% Determine what deps are required
+ RawDeps = rebar_config:get_local(Config, deps, []),
+ {Config1, Deps} = find_deps(Config, read, RawDeps),
+
+ %% Update each dep
+ UpdatedDeps = [update_source(D) || D <- Deps, D#dep.source =/= undefined],
+
%% Add each updated dep to our list of dirs for post-processing. This yields
%% the necessary transitivity of the deps
- erlang:put(?MODULE, [D#dep.dir || D <- UpdatedDeps]),
- ok.
+ {ok, save_dep_dirs(Config1, UpdatedDeps)}.
'delete-deps'(Config, _) ->
%% Delete all the available deps in our deps/ directory, if any
{true, DepsDir} = get_deps_dir(),
Deps = rebar_config:get_local(Config, deps, []),
- {AvailableDeps, _} = find_deps(find, Deps),
+ {Config1, {AvailableDeps, _}} = find_deps(Config, find, Deps),
_ = [delete_dep(D)
|| D <- AvailableDeps,
lists:prefix(DepsDir, D#dep.dir)],
- ok.
+ {ok, Config1}.
'list-deps'(Config, _) ->
Deps = rebar_config:get_local(Config, deps, []),
- case find_deps(find, Deps) of
- {AvailDeps, []} ->
+ case find_deps(Config, find, Deps) of
+ {Config1, {AvailDeps, []}} ->
lists:foreach(fun(Dep) -> print_source(Dep) end, AvailDeps),
- ok;
+ {ok, Config1};
{_, MissingDeps} ->
?ABORT("Missing dependencies: ~p\n", [MissingDeps])
end.
-
%% ===================================================================
%% Internal functions
%% ===================================================================
@@ -191,6 +196,12 @@ get_deps_dir(App) ->
DepsDir = rebar_config:get_global(deps_dir, "deps"),
{true, filename:join([BaseDir, DepsDir, App])}.
+dep_dirs(Deps) ->
+ [D#dep.dir || D <- Deps].
+
+save_dep_dirs(Config, Deps) ->
+ rebar_config:set_xconf(Config, ?MODULE, dep_dirs(Deps)).
+
get_lib_dir(App) ->
%% Find App amongst the reachable lib directories
%% Returns either the found path or a tagged tuple with a boolean
@@ -200,72 +211,77 @@ get_lib_dir(App) ->
Path -> {true, Path}
end.
-update_deps_code_path([]) ->
- ok;
-update_deps_code_path([Dep | Rest]) ->
- case is_app_available(Dep#dep.app, Dep#dep.vsn_regex, Dep#dep.dir) of
- {true, _} ->
- Dir = filename:join(Dep#dep.dir, "ebin"),
- ok = filelib:ensure_dir(filename:join(Dir, "dummy")),
- ?DEBUG("Adding ~s to code path~n", [Dir]),
- true = code:add_patha(Dir);
- {false, _} ->
- true
- end,
- update_deps_code_path(Rest).
-
-
-find_deps(find=Mode, Deps) ->
- find_deps(Mode, Deps, {[], []});
-find_deps(read=Mode, Deps) ->
- find_deps(Mode, Deps, []).
-
-find_deps(find, [], {Avail, Missing}) ->
- {lists:reverse(Avail), lists:reverse(Missing)};
-find_deps(read, [], Deps) ->
- lists:reverse(Deps);
-find_deps(Mode, [App | Rest], Acc) when is_atom(App) ->
- find_deps(Mode, [{App, ".*", undefined} | Rest], Acc);
-find_deps(Mode, [{App, VsnRegex} | Rest], Acc) when is_atom(App) ->
- find_deps(Mode, [{App, VsnRegex, undefined} | Rest], Acc);
-find_deps(Mode, [{App, VsnRegex, Source} | Rest], Acc) ->
+update_deps_code_path(Config, []) ->
+ Config;
+update_deps_code_path(Config, [Dep | Rest]) ->
+ Config2 =
+ case is_app_available(Config, Dep#dep.app,
+ Dep#dep.vsn_regex, Dep#dep.dir) of
+ {Config1, {true, _}} ->
+ Dir = filename:join(Dep#dep.dir, "ebin"),
+ ok = filelib:ensure_dir(filename:join(Dir, "dummy")),
+ ?DEBUG("Adding ~s to code path~n", [Dir]),
+ true = code:add_patha(Dir),
+ Config1;
+ {Config1, {false, _}} ->
+ Config1
+ end,
+ update_deps_code_path(Config2, Rest).
+
+find_deps(Config, find=Mode, Deps) ->
+ find_deps(Config, Mode, Deps, {[], []});
+find_deps(Config, read=Mode, Deps) ->
+ find_deps(Config, Mode, Deps, []).
+
+find_deps(Config, find, [], {Avail, Missing}) ->
+ {Config, {lists:reverse(Avail), lists:reverse(Missing)}};
+find_deps(Config, read, [], Deps) ->
+ {Config, lists:reverse(Deps)};
+find_deps(Config, Mode, [App | Rest], Acc) when is_atom(App) ->
+ find_deps(Config, Mode, [{App, ".*", undefined} | Rest], Acc);
+find_deps(Config, Mode, [{App, VsnRegex} | Rest], Acc) when is_atom(App) ->
+ find_deps(Config, Mode, [{App, VsnRegex, undefined} | Rest], Acc);
+find_deps(Config, Mode, [{App, VsnRegex, Source} | Rest], Acc) ->
Dep = #dep { app = App,
vsn_regex = VsnRegex,
source = Source },
- {Availability, FoundDir} = find_dep(Dep),
- find_deps(Mode, Rest, acc_deps(Mode, Availability, Dep, FoundDir, Acc));
-find_deps(_Mode, [Other | _Rest], _Acc) ->
+ {Config1, {Availability, FoundDir}} = find_dep(Config, Dep),
+ find_deps(Config1, Mode, Rest,
+ acc_deps(Mode, Availability, Dep, FoundDir, Acc));
+find_deps(_Config, _Mode, [Other | _Rest], _Acc) ->
?ABORT("Invalid dependency specification ~p in ~s\n",
[Other, rebar_utils:get_cwd()]).
-find_dep(Dep) ->
+find_dep(Config, Dep) ->
%% Find a dep based on its source,
%% e.g. {git, "https://github.com/mochi/mochiweb.git", "HEAD"}
%% Deps with a source must be found (or fetched) locally.
%% Those without a source may be satisfied from lib dir (get_lib_dir).
- find_dep(Dep, Dep#dep.source).
+ find_dep(Config, Dep, Dep#dep.source).
-find_dep(Dep, undefined) ->
+find_dep(Config, Dep, undefined) ->
%% 'source' is undefined. If Dep is not satisfied locally,
%% go ahead and find it amongst the lib_dir's.
- case find_dep_in_dir(Dep, get_deps_dir(Dep#dep.app)) of
- {avail, _Dir} = Avail -> Avail;
- {missing, _} -> find_dep_in_dir(Dep, get_lib_dir(Dep#dep.app))
+ case find_dep_in_dir(Config, Dep, get_deps_dir(Dep#dep.app)) of
+ {_Config1, {avail, _Dir}} = Avail ->
+ Avail;
+ {Config1, {missing, _}} ->
+ find_dep_in_dir(Config1, Dep, get_lib_dir(Dep#dep.app))
end;
-find_dep(Dep, _Source) ->
+find_dep(Config, Dep, _Source) ->
%% _Source is defined. Regardless of what it is, we must find it
%% locally satisfied or fetch it from the original source
%% into the project's deps
- find_dep_in_dir(Dep, get_deps_dir(Dep#dep.app)).
+ find_dep_in_dir(Config, Dep, get_deps_dir(Dep#dep.app)).
-find_dep_in_dir(_Dep, {false, Dir}) ->
- {missing, Dir};
-find_dep_in_dir(Dep, {true, Dir}) ->
+find_dep_in_dir(Config, _Dep, {false, Dir}) ->
+ {Config, {missing, Dir}};
+find_dep_in_dir(Config, Dep, {true, Dir}) ->
App = Dep#dep.app,
VsnRegex = Dep#dep.vsn_regex,
- case is_app_available(App, VsnRegex, Dir) of
- {true, _AppFile} -> {avail, Dir};
- {false, _} -> {missing, Dir}
+ case is_app_available(Config, App, VsnRegex, Dir) of
+ {Config1, {true, _AppFile}} -> {Config1, {avail, Dir}};
+ {Config1, {false, _}} -> {Config1, {missing, Dir}}
end.
acc_deps(find, avail, Dep, AppDir, {Avail, Missing}) ->
@@ -288,57 +304,59 @@ require_source_engine(Source) ->
true = source_engine_avail(Source),
ok.
-is_app_available(App, VsnRegex, Path) ->
+is_app_available(Config, App, VsnRegex, Path) ->
?DEBUG("is_app_available, looking for App ~p with Path ~p~n", [App, Path]),
case rebar_app_utils:is_app_dir(Path) of
{true, AppFile} ->
- case rebar_app_utils:app_name(AppFile) of
- App ->
- Vsn = rebar_app_utils:app_vsn(AppFile),
+ case rebar_app_utils:app_name(Config, AppFile) of
+ {Config1, App} ->
+ {Config2, Vsn} = rebar_app_utils:app_vsn(Config1, AppFile),
?INFO("Looking for ~s-~s ; found ~s-~s at ~s\n",
[App, VsnRegex, App, Vsn, Path]),
case re:run(Vsn, VsnRegex, [{capture, none}]) of
match ->
- {true, Path};
+ {Config2, {true, Path}};
nomatch ->
?WARN("~s has version ~p; requested regex was ~s\n",
[AppFile, Vsn, VsnRegex]),
- {false, {version_mismatch,
- {AppFile,
- {expected, VsnRegex}, {has, Vsn}}}}
+ {Config2,
+ {false, {version_mismatch,
+ {AppFile,
+ {expected, VsnRegex}, {has, Vsn}}}}}
end;
- OtherApp ->
+ {Config1, OtherApp} ->
?WARN("~s has application id ~p; expected ~p\n",
[AppFile, OtherApp, App]),
- {false, {name_mismatch,
- {AppFile, {expected, App}, {has, OtherApp}}}}
+ {Config1,
+ {false, {name_mismatch,
+ {AppFile, {expected, App}, {has, OtherApp}}}}}
end;
false ->
?WARN("Expected ~s to be an app dir (containing ebin/*.app), "
"but no .app found.\n", [Path]),
- {false, {missing_app_file, Path}}
+ {Config, {false, {missing_app_file, Path}}}
end.
-use_source(Dep) ->
- use_source(Dep, 3).
+use_source(Config, Dep) ->
+ use_source(Config, Dep, 3).
-use_source(Dep, 0) ->
+use_source(_Config, Dep, 0) ->
?ABORT("Failed to acquire source from ~p after 3 tries.\n",
[Dep#dep.source]);
-use_source(Dep, Count) ->
+use_source(Config, Dep, Count) ->
case filelib:is_dir(Dep#dep.dir) of
true ->
%% Already downloaded -- verify the versioning matches the regex
- case is_app_available(Dep#dep.app,
+ case is_app_available(Config, Dep#dep.app,
Dep#dep.vsn_regex, Dep#dep.dir) of
- {true, _} ->
+ {Config1, {true, _}} ->
Dir = filename:join(Dep#dep.dir, "ebin"),
ok = filelib:ensure_dir(filename:join(Dir, "dummy")),
%% Available version matches up -- we're good to go;
%% add the app dir to our code path
true = code:add_patha(Dir),
- Dep;
- {false, Reason} ->
+ {Config1, Dep};
+ {_Config1, {false, Reason}} ->
%% The app that was downloaded doesn't match up (or had
%% errors or something). For the time being, abort.
?ABORT("Dependency dir ~s failed application validation "
@@ -349,7 +367,7 @@ use_source(Dep, Count) ->
require_source_engine(Dep#dep.source),
{true, TargetDir} = get_deps_dir(Dep#dep.app),
download_source(TargetDir, Dep#dep.source),
- use_source(Dep#dep { dir = TargetDir }, Count-1)
+ use_source(Config, Dep#dep { dir = TargetDir }, Count-1)
end.
download_source(AppDir, {hg, Url, Rev}) ->
@@ -433,9 +451,6 @@ update_source(AppDir, {bzr, _Url, Rev}) ->
update_source(AppDir, {rsync, Url}) ->
rebar_utils:sh(?FMT("rsync -az --delete ~s/ ~s",[Url,AppDir]),[]).
-
-
-
%% ===================================================================
%% Source helper functions
%% ===================================================================
diff --git a/src/rebar_edoc.erl b/src/rebar_edoc.erl
index 5d85146..a022913 100644
--- a/src/rebar_edoc.erl
+++ b/src/rebar_edoc.erl
@@ -45,15 +45,14 @@
%% Public API
%% ===================================================================
-%% @doc Generate Erlang program documentation.
--spec doc(Config::rebar_config:config(), File::file:filename()) -> ok.
doc(Config, File) ->
%% Save code path
CodePath = setup_code_path(),
%% Get the edoc_opts and app file info
EDocOpts = rebar_config:get(Config, edoc_opts, []),
- {ok, AppName, _AppData} = rebar_app_utils:load_app_file(File),
+ {ok, Config1, AppName, _AppData} =
+ rebar_app_utils:load_app_file(Config, File),
%% Determine the age of the summary file
EDocInfoName = filename:join(proplists:get_value(dir, EDocOpts, "doc"),
@@ -77,7 +76,7 @@ doc(Config, File) ->
%% Restore code path
true = code:set_path(CodePath),
- ok.
+ {ok, Config1}.
%% ===================================================================
%% Internal functions
diff --git a/src/rebar_escripter.erl b/src/rebar_escripter.erl
index b51a2a5..9ff59f1 100644
--- a/src/rebar_escripter.erl
+++ b/src/rebar_escripter.erl
@@ -36,10 +36,10 @@
%% Public API
%% ===================================================================
-escriptize(Config, AppFile) ->
+escriptize(Config0, AppFile) ->
%% Extract the application name from the archive -- this is the default
%% name of the generated script
- AppName = rebar_app_utils:app_name(AppFile),
+ {Config, AppName} = rebar_app_utils:app_name(Config0, AppFile),
%% Get the output filename for the escript -- this may include dirs
Filename = rebar_config:get_local(Config, escript_name, AppName),
@@ -85,16 +85,17 @@ escriptize(Config, AppFile) ->
%% Finally, update executable perms for our script
{ok, #file_info{mode = Mode}} = file:read_file_info(Filename),
ok = file:change_mode(Filename, Mode bor 8#00111),
- ok.
+ {ok, Config}.
-clean(Config, AppFile) ->
+clean(Config0, AppFile) ->
%% Extract the application name from the archive -- this is the default
%% name of the generated script
- AppName = rebar_app_utils:app_name(AppFile),
+ {Config, AppName} = rebar_app_utils:app_name(Config0, AppFile),
%% Get the output filename for the escript -- this may include dirs
Filename = rebar_config:get_local(Config, escript_name, AppName),
- rebar_file_utils:delete_each([Filename]).
+ rebar_file_utils:delete_each([Filename]),
+ {ok, Config}.
%% ===================================================================
%% Internal functions
diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl
index af14896..385bb49 100644
--- a/src/rebar_eunit.erl
+++ b/src/rebar_eunit.erl
@@ -64,7 +64,7 @@
%% Public API
%% ===================================================================
-eunit(Config, _AppFile) ->
+eunit(Config0, _AppFile) ->
%% Make sure ?EUNIT_DIR/ and ebin/ directory exists (append dummy module)
ok = filelib:ensure_dir(filename:join(eunit_dir(), "dummy")),
ok = filelib:ensure_dir(filename:join(ebin_dir(), "dummy")),
@@ -85,7 +85,7 @@ eunit(Config, _AppFile) ->
%% Copy source files to eunit dir for cover in case they are not directly
%% in src but in a subdirectory of src. Cover only looks in cwd and ../src
%% for source files. Also copy files from src_dirs.
- ErlOpts = rebar_utils:erl_opts(Config),
+ ErlOpts = rebar_utils:erl_opts(Config0),
SrcDirs = rebar_utils:src_dirs(proplists:append_values(src_dirs, ErlOpts)),
SrcErls = lists:foldl(
@@ -119,8 +119,8 @@ eunit(Config, _AppFile) ->
%% Compile erlang code to ?EUNIT_DIR, using a tweaked config
%% with appropriate defines for eunit, and include all the test modules
%% as well.
- rebar_erlc_compiler:doterl_compile(eunit_config(Config),
- ?EUNIT_DIR, TestErls),
+ Config = eunit_config(Config0),
+ rebar_erlc_compiler:doterl_compile(Config, ?EUNIT_DIR, TestErls),
%% Build a list of all the .beams in ?EUNIT_DIR -- use this for
%% cover and eunit testing. Normally you can just tell cover
@@ -166,7 +166,7 @@ eunit(Config, _AppFile) ->
%% Restore code path
true = code:set_path(CodePath),
- ok.
+ {ok, Config}.
clean(_Config, _File) ->
rebar_file_utils:rm_rf(?EUNIT_DIR).
@@ -218,44 +218,48 @@ get_eunit_opts(Config) ->
BaseOpts ++ rebar_config:get_list(Config, eunit_opts, []).
eunit_config(Config) ->
- EqcOpts = eqc_opts(),
- PropErOpts = proper_opts(),
+ {Config1, EqcOpts} = eqc_opts(Config),
+ {Config2, PropErOpts} = proper_opts(Config1),
- ErlOpts = rebar_config:get_list(Config, erl_opts, []),
- EunitOpts = rebar_config:get_list(Config, eunit_compile_opts, []),
+ ErlOpts = rebar_config:get_list(Config2, erl_opts, []),
+ EunitOpts = rebar_config:get_list(Config2, eunit_compile_opts, []),
Opts0 = [{d, 'TEST'}] ++
ErlOpts ++ EunitOpts ++ EqcOpts ++ PropErOpts,
Opts = [O || O <- Opts0, O =/= no_debug_info],
- Config1 = rebar_config:set(Config, erl_opts, Opts),
+ Config3 = rebar_config:set(Config2, erl_opts, Opts),
- FirstErls = rebar_config:get_list(Config1, eunit_first_files, []),
- rebar_config:set(Config1, erl_first_files, FirstErls).
+ FirstErls = rebar_config:get_list(Config3, eunit_first_files, []),
+ rebar_config:set(Config3, erl_first_files, FirstErls).
-eqc_opts() ->
- define_if('EQC', is_lib_avail(is_eqc_avail, eqc,
- "eqc.hrl", "QuickCheck")).
+eqc_opts(Config) ->
+ {NewConfig, IsAvail} = is_lib_avail(Config, is_eqc_avail, eqc,
+ "eqc.hrl", "QuickCheck"),
+ Opts = define_if('EQC', IsAvail),
+ {NewConfig, Opts}.
-proper_opts() ->
- define_if('PROPER', is_lib_avail(is_proper_avail, proper,
- "proper.hrl", "PropEr")).
+proper_opts(Config) ->
+ {NewConfig, IsAvail} = is_lib_avail(Config, is_proper_avail, proper,
+ "proper.hrl", "PropEr"),
+ Opts = define_if('PROPER', IsAvail),
+ {NewConfig, Opts}.
define_if(Def, true) -> [{d, Def}];
define_if(_Def, false) -> [].
-is_lib_avail(DictKey, Mod, Hrl, Name) ->
- case erlang:get(DictKey) of
- undefined ->
+is_lib_avail(Config, DictKey, Mod, Hrl, Name) ->
+ case rebar_config:get_xconf(Config, DictKey) of
+ error ->
IsAvail = case code:lib_dir(Mod, include) of
{error, bad_name} ->
false;
Dir ->
filelib:is_regular(filename:join(Dir, Hrl))
end,
- erlang:put(DictKey, IsAvail),
+ NewConfig = rebar_config:set_xconf(Config, DictKey, IsAvail),
?DEBUG("~s availability: ~p\n", [Name, IsAvail]),
- IsAvail;
- IsAvail ->
- IsAvail
+ {NewConfig, IsAvail};
+ {ok, IsAvail} ->
+ {Config, IsAvail}
end.
perform_cover(Config, BeamFiles, SrcModules) ->
diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl
index 0b2e8be..4304600 100644
--- a/src/rebar_otp_app.erl
+++ b/src/rebar_otp_app.erl
@@ -39,27 +39,27 @@ compile(Config, File) ->
%% If we get an .app.src file, it needs to be pre-processed and
%% written out as a ebin/*.app file. That resulting file will then
%% be validated as usual.
- AppFile = case rebar_app_utils:is_app_src(File) of
- true ->
- preprocess(Config, File);
- false ->
- File
- end,
+ {Config1, AppFile} = case rebar_app_utils:is_app_src(File) of
+ true ->
+ preprocess(Config, File);
+ false ->
+ {Config, File}
+ end,
%% Load the app file and validate it.
- case rebar_app_utils:load_app_file(AppFile) of
- {ok, AppName, AppData} ->
+ case rebar_app_utils:load_app_file(Config1, AppFile) of
+ {ok, Config2, AppName, AppData} ->
validate_name(AppName, AppFile),
%% In general, the list of modules is an important thing to validate
%% for compliance with OTP guidelines and upgrade procedures.
%% However, some people prefer not to validate this list.
- case rebar_config:get_local(Config, validate_app_modules, true) of
+ case rebar_config:get_local(Config1, validate_app_modules, true) of
true ->
- validate_modules(AppName,
- proplists:get_value(modules, AppData));
+ Modules = proplists:get_value(modules, AppData),
+ {validate_modules(AppName, Modules), Config2};
false ->
- ok
+ {ok, Config2}
end;
{error, Reason} ->
?ABORT("Failed to load app file ~s: ~p\n", [AppFile, Reason])
@@ -88,17 +88,17 @@ clean(_Config, File) ->
%% ===================================================================
preprocess(Config, AppSrcFile) ->
- case rebar_app_utils:load_app_file(AppSrcFile) of
- {ok, AppName, AppData} ->
+ case rebar_app_utils:load_app_file(Config, AppSrcFile) of
+ {ok, Config1, AppName, AppData} ->
%% Look for a configuration file with vars we want to
%% substitute. Note that we include the list of modules available in
%% ebin/ and update the app data accordingly.
- AppVars = load_app_vars(Config) ++ [{modules, ebin_modules()}],
+ AppVars = load_app_vars(Config1) ++ [{modules, ebin_modules()}],
A1 = apply_app_vars(AppVars, AppData),
%% AppSrcFile may contain instructions for generating a vsn number
- Vsn = rebar_app_utils:app_vsn(AppSrcFile),
+ {Config2, Vsn} = rebar_app_utils:app_vsn(Config1, AppSrcFile),
A2 = lists:keystore(vsn, 1, A1, {vsn, Vsn}),
%% Build the final spec as a string
@@ -112,7 +112,7 @@ preprocess(Config, AppSrcFile) ->
%% on the code path
true = code:add_path(filename:absname(filename:dirname(AppFile))),
- AppFile;
+ {Config2, AppFile};
{error, Reason} ->
?ABORT("Failed to read ~s for preprocessing: ~p\n",
diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl
index 0ccabc8..8f38cd2 100644
--- a/src/rebar_port_compiler.erl
+++ b/src/rebar_port_compiler.erl
@@ -96,14 +96,14 @@
objects = [] :: [file:filename(), ...] | [],
opts = [] ::list() | []}).
-compile(Config, AppFile) ->
- rebar_utils:deprecated(port_sources, port_specs, Config, "soon"),
- rebar_utils:deprecated(so_name, port_specs, Config, "soon"),
- rebar_utils:deprecated(so_specs, port_specs, Config, "soon"),
+compile(Config0, AppFile) ->
+ rebar_utils:deprecated(port_sources, port_specs, Config0, "soon"),
+ rebar_utils:deprecated(so_name, port_specs, Config0, "soon"),
+ rebar_utils:deprecated(so_specs, port_specs, Config0, "soon"),
%% TODO: remove SpecType and OldSources make get_specs/2
%% return list(#spec{}) when removing deprecated options
- {SpecType, {OldSources, Specs}} = get_specs(Config, AppFile),
+ {Config, {SpecType, {OldSources, Specs}}} = get_specs(Config0, AppFile),
case {SpecType, OldSources, Specs} of
{old, [], _} ->
@@ -149,7 +149,7 @@ compile(Config, AppFile) ->
clean(Config, AppFile) ->
%% TODO: remove SpecType and OldSources make get_specs/2
%% return list(#spec{}) when removing deprecated options
- {SpecType, {OldSources, Specs}} = get_specs(Config, AppFile),
+ {Config1, {SpecType, {OldSources, Specs}}} = get_specs(Config, AppFile),
case {SpecType, OldSources, Specs} of
{old, [], _} ->
@@ -163,7 +163,8 @@ clean(Config, AppFile) ->
rebar_file_utils:delete_each([Target]),
rebar_file_utils:delete_each(Objects)
end, Specs)
- end.
+ end,
+ {ok, Config1}.
setup_env(Config) ->
setup_env(Config, []).
@@ -264,9 +265,10 @@ get_specs(Config, AppFile) ->
case rebar_config:get_local(Config, port_specs, undefined) of
undefined ->
%% TODO: DEPRECATED: remove support for non-port_specs syntax
- {old, old_get_specs(Config, AppFile)};
+ {Config1, Specs} = old_get_specs(Config, AppFile),
+ {Config1, {old, Specs}};
PortSpecs ->
- {new, get_port_specs(Config, PortSpecs)}
+ {Config, {new, get_port_specs(Config, PortSpecs)}}
end.
get_port_specs(Config, PortSpecs) ->
@@ -327,31 +329,32 @@ switch_to_dll_or_exe(Target) ->
old_get_specs(Config, AppFile) ->
OsType = os:type(),
SourceFiles = old_get_sources(Config),
- Specs =
+ {NewConfig, Specs} =
case rebar_config:get_local(Config, so_specs, undefined) of
undefined ->
Objects = port_objects(SourceFiles),
%% New form of so_specs is not provided. See if the old form
%% of {so_name} is available instead
Dir = "priv",
- SoName =
+ {Config2, SoName} =
case rebar_config:get_local(Config, so_name, undefined) of
undefined ->
%% Ok, neither old nor new form is
%% available. Use the app name and
%% generate a sensible default.
- AppName = rebar_app_utils:app_name(AppFile),
+ {Config1, AppName} =
+ rebar_app_utils:app_name(Config, AppFile),
DrvName = ?FMT("~s_drv.so", [AppName]),
- filename:join([Dir, DrvName]);
+ {Config1, filename:join([Dir, DrvName])};
AName ->
%% Old form is available -- use it
- filename:join(Dir, AName)
+ {Config, filename:join(Dir, AName)}
end,
- [old_get_so_spec({SoName, Objects}, OsType)];
+ {Config2, [old_get_so_spec({SoName, Objects}, OsType)]};
SoSpecs ->
- [old_get_so_spec(S, OsType) || S <- SoSpecs]
+ {Config, [old_get_so_spec(S, OsType) || S <- SoSpecs]}
end,
- {SourceFiles, Specs}.
+ {NewConfig, {SourceFiles, Specs}}.
old_get_sources(Config) ->
RawSources = rebar_config:get_local(Config, port_sources,
diff --git a/src/rebar_rel_utils.erl b/src/rebar_rel_utils.erl
index e502743..3c94d97 100644
--- a/src/rebar_rel_utils.erl
+++ b/src/rebar_rel_utils.erl
@@ -35,7 +35,7 @@
get_rel_apps/2,
get_previous_release_path/0,
get_rel_file_path/2,
- load_config/1,
+ load_config/2,
get_sys_tuple/1,
get_target_dir/1,
get_root_dir/1,
@@ -123,10 +123,10 @@ get_previous_release_path() ->
%%
%% Load terms from reltool.config
%%
-load_config(ReltoolFile) ->
+load_config(Config, ReltoolFile) ->
case rebar_config:consult_file(ReltoolFile) of
{ok, Terms} ->
- expand_version(Terms, filename:dirname(ReltoolFile));
+ expand_version(Config, Terms, filename:dirname(ReltoolFile));
Other ->
?ABORT("Failed to load expected config from ~s: ~p\n",
[ReltoolFile, Other])
@@ -217,16 +217,23 @@ make_proplist([H|T], Acc) ->
make_proplist([], Acc) ->
Acc.
-expand_version(ReltoolConfig, Dir) ->
+expand_version(Config, ReltoolConfig, Dir) ->
case lists:keyfind(sys, 1, ReltoolConfig) of
{sys, Sys} ->
- ExpandedSys = {sys, [expand_rel_version(Term, Dir) || Term <- Sys]},
- lists:keyreplace(sys, 1, ReltoolConfig, ExpandedSys);
+ {Config1, Rels} =
+ lists:foldl(
+ fun(Term, {C, R}) ->
+ {C1, Rel} = expand_rel_version(C, Term, Dir),
+ {C1, [Rel|R]}
+ end, {Config, []}, Sys),
+ ExpandedSys = {sys, lists:reverse(Rels)},
+ {Config1, lists:keyreplace(sys, 1, ReltoolConfig, ExpandedSys)};
_ ->
- ReltoolConfig
+ {Config, ReltoolConfig}
end.
-expand_rel_version({rel, Name, Version, Apps}, Dir) ->
- {rel, Name, rebar_utils:vcs_vsn(Version, Dir), Apps};
-expand_rel_version(Other, _Dir) ->
- Other.
+expand_rel_version(Config, {rel, Name, Version, Apps}, Dir) ->
+ {NewConfig, VsnString} = rebar_utils:vcs_vsn(Config, Version, Dir),
+ {NewConfig, {rel, Name, VsnString, Apps}};
+expand_rel_version(Config, Other, _Dir) ->
+ {Config, Other}.
diff --git a/src/rebar_reltool.erl b/src/rebar_reltool.erl
index 06411da..c8e8cb6 100644
--- a/src/rebar_reltool.erl
+++ b/src/rebar_reltool.erl
@@ -37,12 +37,12 @@
%% Public API
%% ===================================================================
-generate(Config, ReltoolFile) ->
+generate(Config0, ReltoolFile) ->
%% Make sure we have decent version of reltool available
check_vsn(),
%% Load the reltool configuration from the file
- ReltoolConfig = rebar_rel_utils:load_config(ReltoolFile),
+ {Config, ReltoolConfig} = rebar_rel_utils:load_config(Config0, ReltoolFile),
Sys = rebar_rel_utils:get_sys_tuple(ReltoolConfig),
@@ -56,7 +56,7 @@ generate(Config, ReltoolFile) ->
%% Finally, run reltool
case catch(run_reltool(Server, Config, ReltoolConfig)) of
ok ->
- ok;
+ {ok, Config};
{error, failed} ->
?ABORT;
Other2 ->
@@ -64,18 +64,17 @@ generate(Config, ReltoolFile) ->
?ABORT
end.
-overlay(_Config, ReltoolFile) ->
+overlay(Config, ReltoolFile) ->
%% Load the reltool configuration from the file
- ReltoolConfig = rebar_rel_utils:load_config(ReltoolFile),
- process_overlay(ReltoolConfig).
+ {Config1, ReltoolConfig} = rebar_rel_utils:load_config(Config, ReltoolFile),
+ {Config1, process_overlay(ReltoolConfig)}.
-clean(_Config, ReltoolFile) ->
- ReltoolConfig = rebar_rel_utils:load_config(ReltoolFile),
+clean(Config, ReltoolFile) ->
+ {Config1, ReltoolConfig} = rebar_rel_utils:load_config(Config, ReltoolFile),
TargetDir = rebar_rel_utils:get_target_dir(ReltoolConfig),
rebar_file_utils:rm_rf(TargetDir),
- rebar_file_utils:delete_each(["reltool.spec"]).
-
-
+ rebar_file_utils:delete_each(["reltool.spec"]),
+ {ok, Config1}.
%% ===================================================================
%% Internal functions
diff --git a/src/rebar_subdirs.erl b/src/rebar_subdirs.erl
index 6c33441..f444a59 100644
--- a/src/rebar_subdirs.erl
+++ b/src/rebar_subdirs.erl
@@ -40,7 +40,7 @@ preprocess(Config, _) ->
Cwd = rebar_utils:get_cwd(),
ListSubdirs = rebar_config:get_local(Config, sub_dirs, []),
Subdirs0 = lists:flatmap(fun filelib:wildcard/1, ListSubdirs),
- case {rebar_core:is_skip_dir(Cwd), Subdirs0} of
+ case {rebar_config:is_skip_dir(Config, Cwd), Subdirs0} of
{true, []} ->
{ok, []};
{true, _} ->
diff --git a/src/rebar_upgrade.erl b/src/rebar_upgrade.erl
index aaa24fd..3f7de03 100644
--- a/src/rebar_upgrade.erl
+++ b/src/rebar_upgrade.erl
@@ -38,9 +38,9 @@
%% Public API
%% ====================================================================
-'generate-upgrade'(_Config, ReltoolFile) ->
+'generate-upgrade'(Config0, ReltoolFile) ->
%% Get the old release path
- ReltoolConfig = rebar_rel_utils:load_config(ReltoolFile),
+ {Config, ReltoolConfig} = rebar_rel_utils:load_config(Config0, ReltoolFile),
TargetParentDir = rebar_rel_utils:get_target_parent_dir(ReltoolConfig),
TargetDir = rebar_rel_utils:get_target_dir(ReltoolConfig),
@@ -72,7 +72,7 @@
%% Restore original path
true = code:set_path(OrigPath),
- ok.
+ {ok, Config}.
%% ===================================================================
%% Internal functions
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index 36348e7..be69acc 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -42,7 +42,7 @@
prop_check/3,
expand_code_path/0,
expand_env_variable/3,
- vcs_vsn/2,
+ vcs_vsn/3,
deprecated/3, deprecated/4,
get_deprecated_global/3, get_deprecated_global/4,
get_deprecated_list/4, get_deprecated_list/5,
@@ -198,14 +198,17 @@ expand_env_variable(InStr, VarName, RawVarValue) ->
re:replace(InStr, RegEx, [VarValue, "\\2"], ReOpts)
end.
-vcs_vsn(Vcs, Dir) ->
+vcs_vsn(Config, Vcs, Dir) ->
Key = {Vcs, Dir},
- try ets:lookup_element(rebar_vsn_cache, Key, 2)
- catch
- error:badarg ->
+ {ok, Cache} = rebar_config:get_xconf(Config, vsn_cache),
+ case dict:find(Key, Cache) of
+ error ->
VsnString = vcs_vsn_1(Vcs, Dir),
- ets:insert(rebar_vsn_cache, {Key, VsnString}),
- VsnString
+ Cache1 = dict:store(Key, VsnString, Cache),
+ Config1 = rebar_config:set_xconf(Config, vsn_cache, Cache1),
+ {Config1, VsnString};
+ {ok, VsnString} ->
+ {Config, VsnString}
end.
get_deprecated_global(OldOpt, NewOpt, When) ->