mirror of
https://github.com/correl/rebar.git
synced 2024-11-14 19:19:30 +00:00
Remove shared state
This commit is contained in:
parent
1948eb4a47
commit
e185e86bff
16 changed files with 489 additions and 423 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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().
|
||||
|
|
|
@ -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),
|
||||
%% Reset skip dirs
|
||||
ParentConfig1 = rebar_config:reset_skip_dirs(ParentConfig),
|
||||
Operations = rebar_config:get_xconf(ParentConfig1, 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),
|
||||
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;
|
||||
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
|
||||
{Config1, Env} = setup_envs(Config0, Modules),
|
||||
false ->
|
||||
%% Check for and get command specific environments
|
||||
{Config4, Env} = setup_envs(Config3, Modules),
|
||||
|
||||
%% Execute any before_command plugins on this directory
|
||||
execute_pre(Command, PluginModules,
|
||||
Config1, ModuleSetFile, Env),
|
||||
%% Execute any before_command plugins on this directory
|
||||
Config5 = execute_pre(Command, PluginModules,
|
||||
Config4, ModuleSetFile, Env),
|
||||
|
||||
%% Execute the current command on this directory
|
||||
execute(Command, Modules ++ PluginModules,
|
||||
Config1, 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,
|
||||
Config1, ModuleSetFile, Env),
|
||||
|
||||
Config1
|
||||
end,
|
||||
%% 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.
|
||||
|
|
|
@ -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).
|
||||
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(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) ->
|
||||
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
|
||||
%% ===================================================================
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) ->
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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}.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, _} ->
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) ->
|
||||
|
|
Loading…
Reference in a new issue