summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoromarkj <omarkj@gmail.com>2014-11-03 13:58:58 -0800
committeromarkj <omarkj@gmail.com>2014-11-03 13:58:58 -0800
commita1d030c9649526422f58e0fb5dae9d33564b395a (patch)
treefeb95f0fec3421ed876e1802584430e18e29f73f /src
parent58f4019fa62a73e335967870f6605182d7386830 (diff)
parenta3ec3a3424dd47e9687d0d2960ef2d3cba6a8f5c (diff)
add help
Diffstat (limited to 'src')
-rw-r--r--src/rebar.app.src8
-rw-r--r--src/rebar3.erl123
-rw-r--r--src/rebar_app_discover.erl40
-rw-r--r--src/rebar_app_info.erl61
-rw-r--r--src/rebar_app_utils.erl68
-rw-r--r--src/rebar_config.erl5
-rw-r--r--src/rebar_core.erl58
-rw-r--r--src/rebar_erlc_compiler.erl43
-rw-r--r--src/rebar_fetch.erl10
-rw-r--r--src/rebar_packages.erl9
-rw-r--r--src/rebar_plugins.erl28
-rw-r--r--src/rebar_provider.erl165
-rw-r--r--src/rebar_prv_app_discovery.erl27
-rw-r--r--src/rebar_prv_clean.erl44
-rw-r--r--src/rebar_prv_common_test.erl119
-rw-r--r--src/rebar_prv_compile.erl50
-rw-r--r--src/rebar_prv_deps.erl27
-rw-r--r--src/rebar_prv_do.erl32
-rw-r--r--src/rebar_prv_erlydtl_compiler.erl (renamed from src/rebar_erlydtl_compiler.erl)43
-rw-r--r--src/rebar_prv_escripter.erl224
-rw-r--r--src/rebar_prv_help.erl50
-rw-r--r--src/rebar_prv_install_deps.erl329
-rw-r--r--src/rebar_prv_lock.erl30
-rw-r--r--src/rebar_prv_new.erl57
-rw-r--r--src/rebar_prv_packages.erl27
-rw-r--r--src/rebar_prv_release.erl40
-rw-r--r--src/rebar_prv_shell.erl27
-rw-r--r--src/rebar_prv_tar.erl38
-rw-r--r--src/rebar_prv_test_deps.erl63
-rw-r--r--src/rebar_prv_update.erl63
-rw-r--r--src/rebar_prv_upgrade.erl55
-rw-r--r--src/rebar_prv_version.erl27
-rw-r--r--src/rebar_state.erl135
-rw-r--r--src/rebar_templater.erl6
-rw-r--r--src/rebar_topo.erl48
-rw-r--r--src/rebar_utils.erl174
36 files changed, 1150 insertions, 1203 deletions
diff --git a/src/rebar.app.src b/src/rebar.app.src
index 3164b73..c41ad92 100644
--- a/src/rebar.app.src
+++ b/src/rebar.app.src
@@ -21,22 +21,24 @@
{log_level, warn},
%% any_dir processing modules
- {providers, [rebar_prv_escripter,
+ {providers, [rebar_prv_clean,
rebar_prv_deps,
rebar_prv_do,
rebar_prv_lock,
rebar_prv_install_deps,
rebar_prv_packages,
- rebar_erlydtl_compiler,
+ rebar_prv_erlydtl_compiler,
rebar_prv_compile,
rebar_prv_app_discovery,
rebar_prv_shell,
rebar_prv_tar,
rebar_prv_new,
rebar_prv_update,
+ rebar_prv_upgrade,
rebar_prv_release,
rebar_prv_version,
rebar_prv_common_test,
- rebar_prv_help]}
+ rebar_prv_help,
+ rebar_prv_test_deps]}
]}
]}.
diff --git a/src/rebar3.erl b/src/rebar3.erl
index dcd78f7..22c08ca 100644
--- a/src/rebar3.erl
+++ b/src/rebar3.erl
@@ -28,15 +28,16 @@
-export([main/1,
run/2,
- option_spec_list/0,
+ global_option_spec_list/0,
+ init_config/0,
+ init_config1/1,
+ set_options/2,
parse_args/1,
version/0,
- log_level/1]).
+ log_level/0]).
-include("rebar.hrl").
--define(DEFAULT_JOBS, 3).
-
%% ====================================================================
%% Public API
%% ====================================================================
@@ -44,14 +45,21 @@
%% escript Entry point
main(Args) ->
case catch(run(Args)) of
- ok ->
+ {ok, _State} ->
ok;
rebar_abort ->
rebar_utils:delayed_halt(1);
+ {error, {Module, Reason}} ->
+ ?ERROR(Module:format_error(Reason, []), []),
+ rebar_utils:delayed_halt(1);
+ {error, Error} ->
+ ?ERROR(Error++"~n", []),
+ rebar_utils:delayed_halt(1);
Error ->
%% Nothing should percolate up from rebar_core;
%% Dump this error to console
- io:format("Uncaught error in rebar_core: ~p\n", [Error]),
+ ?ERROR("Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace~n", []),
+ ?DEBUG("Uncaught error: ~p~n", [Error]),
rebar_utils:delayed_halt(1)
end.
@@ -59,7 +67,7 @@ main(Args) ->
run(BaseState, Command) ->
_ = application:load(rebar),
BaseState1 = rebar_state:set(BaseState, task, Command),
- run_aux(BaseState1, []).
+ run_aux(BaseState1, [Command]).
%% ====================================================================
%% Internal functions
@@ -67,24 +75,21 @@ run(BaseState, Command) ->
run(RawArgs) ->
ok = load_rebar_app(),
- %% Parse out command line arguments -- what's left is a list of commands to
- %% run -- and start running commands
- Args = parse_args(RawArgs),
- BaseConfig = init_config(Args),
- {BaseConfig1, Args1} = set_options(BaseConfig, Args),
- run_aux(BaseConfig1, Args1).
+ BaseConfig = init_config(),
+ {BaseConfig1, _Args1} = set_options(BaseConfig, {[], []}),
+ run_aux(BaseConfig1, RawArgs).
load_rebar_app() ->
%% Pre-load the rebar app so that we get default configuration
ok = application:load(rebar).
-init_config({Options, _NonOptArgs}) ->
+init_config() ->
%% Initialize logging system
- Verbosity = log_level(Options),
+ Verbosity = log_level(),
ok = rebar_log:init(command_line, Verbosity),
- Config = case proplists:get_value(config, Options) of
- undefined ->
+ Config = case os:getenv("REBAR_CONFIG") of
+ false ->
rebar_config:consult_file(?DEFAULT_CONFIG_FILE);
ConfigFile ->
rebar_config:consult_file(ConfigFile)
@@ -103,8 +108,8 @@ init_config({Options, _NonOptArgs}) ->
true ->
?DEBUG("Load global config file ~p~n",
[GlobalConfigFile]),
- rebar_config:consult_file(GlobalConfigFile),
- rebar_state:new(GlobalConfigFile, Config1);
+ GlobalConfig = rebar_state:new(rebar_config:consult_file(GlobalConfigFile)),
+ rebar_state:new(GlobalConfig, Config1);
false ->
rebar_state:new(Config1)
end,
@@ -123,7 +128,7 @@ init_config1(BaseConfig) ->
BaseConfig
end.
-run_aux(State, Args) ->
+run_aux(State, RawArgs) ->
%% Make sure crypto is running
case crypto:start() of
ok -> ok;
@@ -136,28 +141,33 @@ run_aux(State, Args) ->
State1 = init_config1(State),
+ code:add_pathsa([filename:join(rebar_utils:get_cwd(), "plugins")]),
%% Process each command, resetting any state between each one
State2 = rebar_state:set(State1, base_dir, filename:absname(rebar_state:dir(State1))),
{ok, Providers} = application:get_env(rebar, providers),
- State3 = rebar_state:create_logic_providers(Providers, State2),
- Task = rebar_state:get(State3, task, "help"),
- rebar_core:process_command(rebar_state:command_args(State3, Args), list_to_atom(Task)),
- ok.
+
+ {ok, PluginProviders, State3} = rebar_plugins:install(State2),
+ rebar_core:update_code_path(State3),
+
+ State4 = rebar_state:create_logic_providers(Providers++PluginProviders, State3),
+ {Task, Args} = parse_args(RawArgs),
+
+ rebar_core:process_command(rebar_state:command_args(State4, Args), list_to_atom(Task)).
%%
%% Parse command line arguments using getopt and also filtering out any
%% key=value pairs. What's left is the list of commands to run
%%
-parse_args(RawArgs) ->
- %% Parse getopt options
- OptSpecList = option_spec_list(),
- case getopt:parse(OptSpecList, RawArgs) of
- {ok, Args} ->
- Args;
- {error, {Reason, Data}} ->
- ?ERROR("~s ~p~n~n", [Reason, Data]),
- rebar_utils:delayed_halt(1)
- end.
+parse_args([]) ->
+ parse_args(["help"]);
+parse_args([H | Rest]) when H =:= "-h"
+ ; H =:= "--help" ->
+ parse_args(["help" | Rest]);
+parse_args([H | Rest]) when H =:= "-v"
+ ; H =:= "--version" ->
+ parse_args(["version" | Rest]);
+parse_args([RawTask | RawRest]) ->
+ {RawTask, RawRest}.
set_options(State, {Options, NonOptArgs}) ->
GlobalDefines = proplists:get_all_values(defines, Options),
@@ -166,32 +176,26 @@ set_options(State, {Options, NonOptArgs}) ->
%% Set global variables based on getopt options
State2 = set_global_flag(State1, Options, force),
- State3 = case proplists:get_value(jobs, Options, ?DEFAULT_JOBS) of
- ?DEFAULT_JOBS ->
- State2;
- Jobs ->
- rebar_state:set(State2, jobs, Jobs)
- end,
Task = proplists:get_value(task, Options, "help"),
- {rebar_state:set(State3, task, Task), NonOptArgs}.
+ {rebar_state:set(State2, task, Task), NonOptArgs}.
%%
%% get log level based on getopt option
%%
-log_level(Options) ->
- case proplists:get_bool(quiet, Options) of
- true ->
- rebar_log:error_level();
+log_level() ->
+ case os:getenv("QUIET") of
false ->
DefaultLevel = rebar_log:default_level(),
- case proplists:get_all_values(verbose, Options) of
- [] ->
+ case os:getenv("DEBUG") of
+ false ->
DefaultLevel;
- Verbosities ->
- DefaultLevel + lists:last(Verbosities)
- end
+ _ ->
+ DefaultLevel + 3
+ end;
+ _ ->
+ rebar_log:error_level()
end.
%%
@@ -218,17 +222,12 @@ set_global_flag(State, Options, Flag) ->
%%
%% options accepted via getopt
%%
-option_spec_list() ->
- Jobs = ?DEFAULT_JOBS,
- JobsHelp = io_lib:format(
- "Number of concurrent workers a command may use. Default: ~B",
- [Jobs]),
+global_option_spec_list() ->
[
- %% {Name, ShortOpt, LongOpt, ArgSpec, HelpMsg}
- {help, $h, "help", undefined, "Print this help."},
- {verbose, $v, "verbose", integer, "Verbosity level (-v, -vv)."},
- {version, $V, "version", undefined, "Show version information."},
- {jobs, $j, "jobs", integer, JobsHelp},
- {config, $C, "config", string, "Rebar config file to use."},
- {task, undefined, undefined, string, "Task to run."}
+ %% {Name, ShortOpt, LongOpt, ArgSpec, HelpMsg}
+ {help, $h, "help", undefined, "Print this help."},
+ %{verbose, $v, "verbose", integer, "Verbosity level (-v, -vv)."},
+ {version, $V, "version", undefined, "Show version information."},
+ %{config, $C, "config", string, "Rebar config file to use."},
+ {task, undefined, undefined, string, "Task to run."}
].
diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl
index c90a8df..ae4916e 100644
--- a/src/rebar_app_discover.erl
+++ b/src/rebar_app_discover.erl
@@ -13,7 +13,8 @@ do(State, LibDirs) ->
Apps = find_apps(Dirs, all),
ProjectDeps = rebar_state:deps_names(State),
lists:foldl(fun(AppInfo, StateAcc) ->
- rebar_state:project_apps(StateAcc, rebar_app_info:deps(AppInfo, ProjectDeps))
+ ProjectDeps1 = lists:delete(rebar_app_info:name(AppInfo), ProjectDeps),
+ rebar_state:project_apps(StateAcc, rebar_app_info:deps(AppInfo, ProjectDeps1))
end, State, Apps).
-spec all_app_dirs(list(file:name())) -> list(file:name()).
@@ -47,14 +48,17 @@ app_dirs(LibDir) ->
find_unbuilt_apps(LibDirs) ->
find_apps(LibDirs, invalid).
+-spec find_apps([file:filename_all()]) -> [rebar_app_info:t()].
find_apps(LibDirs) ->
find_apps(LibDirs, valid).
+-spec find_apps([file:filename_all()], valid | invalid | all) -> [rebar_app_info:t()].
find_apps(LibDirs, Validate) ->
rebar_utils:filtermap(fun(AppDir) ->
find_app(AppDir, Validate)
end, all_app_dirs(LibDirs)).
+-spec find_app(file:filename_all(), valid | invalid | all) -> {true, rebar_app_info:t()} | false.
find_app(AppDir, Validate) ->
AppFile = filelib:wildcard(filename:join([AppDir, "ebin", "*.app"])),
AppSrcFile = filelib:wildcard(filename:join([AppDir, "src", "*.app.src"])),
@@ -104,12 +108,17 @@ find_app(AppDir, Validate) ->
app_dir(AppFile) ->
filename:join(rebar_utils:droplast(filename:split(filename:dirname(AppFile)))).
+-spec create_app_info(file:name(), file:name()) -> rebar_app_info:t() | error.
create_app_info(AppDir, AppFile) ->
case file:consult(AppFile) of
{ok, [{application, AppName, AppDetails}]} ->
AppVsn = proplists:get_value(vsn, AppDetails),
+ %AppDeps = proplists:get_value(applications, AppDetails, []),
+ C = rebar_config:consult(AppDir),
+ S = rebar_state:new(rebar_state:new(), C, AppDir),
+ AppDeps = rebar_state:deps_names(S),
AbsCwd = filename:absname(rebar_utils:get_cwd()),
- {ok, AppInfo} = rebar_app_info:new(AppName, AppVsn, AppDir),
+ {ok, AppInfo} = rebar_app_info:new(AppName, AppVsn, AppDir, AppDeps),
RebarConfig = filename:join(AppDir, "rebar.config"),
AppState = case filelib:is_file(RebarConfig) of
true ->
@@ -121,22 +130,28 @@ create_app_info(AppDir, AppFile) ->
AppState1 = rebar_state:set(AppState, base_dir, AbsCwd),
AppInfo1 = rebar_app_info:config(
rebar_app_info:app_details(AppInfo, AppDetails), AppState1),
- rebar_app_info:dir(AppInfo1, AppDir)
+ rebar_app_info:dir(AppInfo1, AppDir);
+ _ ->
+ error
end.
-spec validate_application_info(rebar_app_info:t()) -> boolean().
validate_application_info(AppInfo) ->
EbinDir = rebar_app_info:ebin_dir(AppInfo),
- AppFile = rebar_app_info:app_file(AppInfo),
- AppDetail = rebar_app_info:app_details(AppInfo),
- case get_modules_list(AppFile, AppDetail) of
- {ok, List} ->
- has_all_beams(EbinDir, List);
- _Error ->
- false
+ case rebar_app_info:app_file(AppInfo) of
+ undefined ->
+ false;
+ AppFile ->
+ AppDetail = rebar_app_info:app_details(AppInfo),
+ case get_modules_list(AppFile, AppDetail) of
+ {ok, List} ->
+ has_all_beams(EbinDir, List);
+ _Error ->
+ false
+ end
end.
--spec get_modules_list(file:name(), proplists:proplist()) ->
+-spec get_modules_list(file:filename_all(), proplists:proplist()) ->
{ok, list()} |
{warning, Reason::term()} |
{error, Reason::term()}.
@@ -148,8 +163,7 @@ get_modules_list(AppFile, AppDetail) ->
{ok, ModulesList}
end.
--spec has_all_beams(file:name(), list()) ->
- ok | {error, Reason::term()}.
+-spec has_all_beams(file:filename_all(), list()) -> boolean().
has_all_beams(EbinDir, [Module | ModuleList]) ->
BeamFile = filename:join([EbinDir,
ec_cnv:to_list(Module) ++ ".beam"]),
diff --git a/src/rebar_app_info.erl b/src/rebar_app_info.erl
index 008bfd2..7a33811 100644
--- a/src/rebar_app_info.erl
+++ b/src/rebar_app_info.erl
@@ -1,7 +1,6 @@
-module(rebar_app_info).
--export([new/0,
- new/1,
+-export([new/1,
new/2,
new/3,
new/4,
@@ -21,6 +20,8 @@
ebin_dir/1,
deps/1,
deps/2,
+ dep_level/1,
+ dep_level/2,
dir/1,
dir/2,
source/1,
@@ -31,43 +32,40 @@
-export_type([t/0]).
-record(app_info_t, {name :: binary(),
- app_file_src :: file:name() | undefined,
- app_file :: file:name(),
- config :: rebar_config:config() | undefined,
- original_vsn :: string(),
+ app_file_src :: file:filename_all() | undefined,
+ app_file :: file:filename_all() | undefined,
+ config :: rebar_state:t() | undefined,
+ original_vsn :: binary() | string() | undefined,
app_details=[] :: list(),
deps=[] :: list(),
+ dep_level :: integer(),
dir :: file:name(),
- source :: string() | undefined,
+ source :: string() | tuple() | undefined,
valid :: boolean()}).
%%============================================================================
%% types
%%============================================================================
--opaque t() :: record(app_info_t).
+-type t() :: record(app_info_t).
%%============================================================================
%% API
%% ============================================================================
%% @doc Build a new, empty, app info value. This is not of a lot of use and you
%% probably wont be doing this much.
--spec new() -> {ok, t()}.
-new() ->
- {ok, #app_info_t{}}.
-
-spec new(atom() | binary() | string()) ->
{ok, t()}.
new(AppName) ->
{ok, #app_info_t{name=ec_cnv:to_binary(AppName)}}.
--spec new(atom() | binary() | string(), string()) ->
+-spec new(atom() | binary() | string(), binary() | string()) ->
{ok, t()}.
new(AppName, Vsn) ->
{ok, #app_info_t{name=ec_cnv:to_binary(AppName),
original_vsn=Vsn}}.
%% @doc build a complete version of the app info with all fields set.
--spec new(atom() | binary() | string(), string(), file:name()) ->
+-spec new(atom() | binary() | string(), binary() | string(), file:name()) ->
{ok, t()}.
new(AppName, Vsn, Dir) ->
{ok, #app_info_t{name=ec_cnv:to_binary(AppName),
@@ -75,7 +73,7 @@ new(AppName, Vsn, Dir) ->
dir=Dir}}.
%% @doc build a complete version of the app info with all fields set.
--spec new(atom() | binary() | string(), string(), file:name(), list()) ->
+-spec new(atom() | binary() | string(), binary() | string(), file:name(), list()) ->
{ok, t()}.
new(AppName, Vsn, Dir, Deps) ->
{ok, #app_info_t{name=ec_cnv:to_binary(AppName),
@@ -84,17 +82,16 @@ new(AppName, Vsn, Dir, Deps) ->
deps=Deps}}.
%% @doc discover a complete version of the app info with all fields set.
--spec discover(file:name()) ->
- {ok, t()}.
+-spec discover(file:filename_all()) -> {ok, t()} | not_found.
discover(Dir) ->
case rebar_app_discover:find_app(Dir, all) of
{true, AppInfo} ->
{ok, AppInfo};
- _ ->
+ false ->
not_found
end.
--spec name(t()) -> atom().
+-spec name(t()) -> binary().
name(#app_info_t{name=Name}) ->
Name.
@@ -102,15 +99,15 @@ name(#app_info_t{name=Name}) ->
name(AppInfo=#app_info_t{}, AppName) ->
AppInfo#app_info_t{name=ec_cnv:to_binary(AppName)}.
--spec config(t()) -> rebar_config:confg().
+-spec config(t()) -> rebar_state:t().
config(#app_info_t{config=Config}) ->
Config.
--spec config(t(), rebar_config:confg()) -> t().
+-spec config(t(), rebar_state:t()) -> t().
config(AppInfo=#app_info_t{}, Config) ->
AppInfo#app_info_t{config=Config}.
--spec app_file_src(t()) -> file:name().
+-spec app_file_src(t()) -> file:filename_all() | undefined.
app_file_src(#app_info_t{app_file_src=undefined, dir=Dir, name=Name}) ->
AppFileSrc = filename:join([ec_cnv:to_list(Dir), "src", ec_cnv:to_list(Name)++".app.src"]),
case filelib:is_file(AppFileSrc) of
@@ -122,11 +119,11 @@ app_file_src(#app_info_t{app_file_src=undefined, dir=Dir, name=Name}) ->
app_file_src(#app_info_t{app_file_src=AppFileSrc}) ->
ec_cnv:to_list(AppFileSrc).
--spec app_file_src(t(), file:name()) -> t().
+-spec app_file_src(t(), file:filename_all()) -> t().
app_file_src(AppInfo=#app_info_t{}, AppFileSrc) ->
AppInfo#app_info_t{app_file_src=ec_cnv:to_list(AppFileSrc)}.
--spec app_file(t()) -> file:name().
+-spec app_file(t()) -> file:filename_all() | undefined.
app_file(#app_info_t{app_file=undefined, dir=Dir, name=Name}) ->
AppFile = filename:join([ec_cnv:to_list(Dir), "ebin", ec_cnv:to_list(Name)++".app"]),
case filelib:is_file(AppFile) of
@@ -138,9 +135,9 @@ app_file(#app_info_t{app_file=undefined, dir=Dir, name=Name}) ->
app_file(#app_info_t{app_file=AppFile}) ->
AppFile.
--spec app_file(t(), file:name()) -> t().
+-spec app_file(t(), file:filename_all()) -> t().
app_file(AppInfo=#app_info_t{}, AppFile) ->
- AppInfo#app_info_t{app_file=ec_cnv:to_list(AppFile)}.
+ AppInfo#app_info_t{app_file=AppFile}.
-spec app_details(t()) -> list().
app_details(#app_info_t{app_details=AppDetails}) ->
@@ -154,7 +151,7 @@ app_details(AppInfo=#app_info_t{}, AppDetails) ->
original_vsn(#app_info_t{original_vsn=Vsn}) ->
Vsn.
--spec original_vsn(t(), string()) -> string().
+-spec original_vsn(t(), string()) -> t().
original_vsn(AppInfo=#app_info_t{}, Vsn) ->
AppInfo#app_info_t{original_vsn=Vsn}.
@@ -166,6 +163,12 @@ deps(#app_info_t{deps=Deps}) ->
deps(AppInfo=#app_info_t{}, Deps) ->
AppInfo#app_info_t{deps=Deps}.
+dep_level(AppInfo=#app_info_t{}, Level) ->
+ AppInfo#app_info_t{dep_level=Level}.
+
+dep_level(#app_info_t{dep_level=Level}) ->
+ Level.
+
-spec dir(t()) -> file:name().
dir(#app_info_t{dir=Dir}) ->
Dir.
@@ -178,11 +181,11 @@ dir(AppInfo=#app_info_t{}, Dir) ->
ebin_dir(#app_info_t{dir=Dir}) ->
filename:join(Dir, "ebin").
--spec source(t(), string()) -> t().
+-spec source(t(), string() | tuple()) -> t().
source(AppInfo=#app_info_t{}, Source) ->
AppInfo#app_info_t{source=Source}.
--spec source(t()) -> string().
+-spec source(t()) -> string() | tuple().
source(#app_info_t{source=Source}) ->
Source.
diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl
index 1c53743..8fc3df8 100644
--- a/src/rebar_app_utils.erl
+++ b/src/rebar_app_utils.erl
@@ -26,13 +26,14 @@
%% -------------------------------------------------------------------
-module(rebar_app_utils).
--export([is_app_dir/0, is_app_dir/1,
+-export([find/2,
+ find/3,
+ is_app_dir/0, is_app_dir/1,
is_app_src/1,
app_src_to_app/1,
app_name/2,
app_applications/2,
- app_vsn/2,
- is_skipped_app/2]).
+ app_vsn/2]).
-export([load_app_file/2]). % TEMPORARY
@@ -42,9 +43,22 @@
%% Public API
%% ===================================================================
+-spec find(binary(), [rebar_app_info:t()]) -> {ok, rebar_app_info:t()} | error.
+find(Name, Apps) ->
+ ec_lists:find(fun(App) -> rebar_app_info:name(App) =:= Name end, Apps).
+
+-spec find(binary(), binary(), [rebar_app_info:t()]) -> {ok, rebar_app_info:t()} | error.
+find(Name, Vsn, Apps) ->
+ ec_lists:find(fun(App) ->
+ rebar_app_info:name(App) =:= Name
+ andalso rebar_app_info:original_vsn(App) =:= Vsn
+ end, Apps).
+
+-spec is_app_dir() -> {true, file:name()} | false.
is_app_dir() ->
is_app_dir(rebar_utils:get_cwd()).
+-spec is_app_dir(file:name()) -> {true, file:name()} | false.
is_app_dir(Dir) ->
SrcDir = filename:join([Dir, "src"]),
AppSrc = filename:join([SrcDir, "*.app.src"]),
@@ -109,30 +123,6 @@ app_vsn(Config, AppFile) ->
[AppFile, Reason])
end.
-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
- Skipped =
- case get_apps(Config) of
- undefined ->
- %% No apps parameter specified, check the skip_apps list..
- case get_skip_apps(Config) 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
%% ===================================================================
@@ -176,27 +166,3 @@ get_value(Key, AppInfo, AppFile) ->
Value ->
Value
end.
-
-%% apps= for selecting apps
-is_selected(ThisApp, TargetApps) ->
- case lists:member(ThisApp, TargetApps) of
- false ->
- {true, ThisApp};
- true ->
- false
- end.
-
-%% skip_apps= for filtering apps
-is_skipped(ThisApp, TargetApps) ->
- case lists:member(ThisApp, TargetApps) of
- false ->
- false;
- true ->
- {true, ThisApp}
- end.
-
-get_apps(Config) ->
- rebar_config:get_global(Config, apps, undefined).
-
-get_skip_apps(Config) ->
- rebar_config:get_global(Config, skip_apps, undefined).
diff --git a/src/rebar_config.erl b/src/rebar_config.erl
index a45bef9..7ef2488 100644
--- a/src/rebar_config.erl
+++ b/src/rebar_config.erl
@@ -35,11 +35,11 @@
%% Public API
%% ===================================================================
--spec consult(file:name()) -> {ok, any()}.
+-spec consult(file:name()) -> [any()].
consult(Dir) ->
consult_file(filename:join(Dir, ?DEFAULT_CONFIG_FILE)).
--spec consult_file(file:name()) -> {ok, any()}.
+-spec consult_file(file:name()) -> [any()].
consult_file(File) when is_binary(File) ->
consult_file(binary_to_list(File));
consult_file(File) ->
@@ -73,7 +73,6 @@ remove_script_ext(F) ->
try_consult(File) ->
case file:consult(File) of
{ok, Terms} ->
- ?DEBUG("Consult config file ~p~n", [File]),
Terms;
{error, enoent} ->
[];
diff --git a/src/rebar_core.erl b/src/rebar_core.erl
index cb021e3..16d8f07 100644
--- a/src/rebar_core.erl
+++ b/src/rebar_core.erl
@@ -26,33 +26,61 @@
%% -------------------------------------------------------------------
-module(rebar_core).
--export([process_command/2]).
+-export([process_command/2
+ ,update_code_path/1]).
-include("rebar.hrl").
+-spec process_command(rebar_state:t(), atom()) -> {ok, rebar_state:t()} | {error, string()}.
process_command(State, Command) ->
+ %% ? rebar_prv_install_deps:setup_env(State),
+ Providers = rebar_state:providers(State),
+ TargetProviders = providers:get_target_providers(Command, Providers),
+ case providers:get_provider(Command, Providers) of
+ not_found ->
+ {error, io_lib:format("Command ~p not found", [Command])};
+ CommandProvider ->
+ Opts = providers:opts(CommandProvider)++rebar3:global_option_spec_list(),
+ case Command of
+ do ->
+ do(TargetProviders, State);
+ _ ->
+ case getopt:parse(Opts, rebar_state:command_args(State)) of
+ {ok, Args} ->
+ State2 = rebar_state:command_parsed_args(State, Args),
+ do(TargetProviders, State2);
+ {error, {invalid_option, Option}} ->
+ {error, io_lib:format("Invalid option ~s on task ~p", [Option, Command])}
+ end
+ end
+ end.
+
+-spec do([atom()], rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
+do([], State) ->
+ {ok, State};
+do([ProviderName | Rest], State) ->
+ Provider = providers:get_provider(ProviderName
+ ,rebar_state:providers(State)),
+ case providers:do(Provider, State) of
+ {ok, State1} ->
+ do(Rest, State1);
+ {error, Error} ->
+ {error, Error}
+ end.
+
+update_code_path(State) ->
true = rebar_utils:expand_code_path(),
LibDirs = rebar_state:get(State, lib_dirs, ?DEFAULT_LIB_DIRS),
- DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIRS),
- _UpdatedCodePaths = update_code_path([DepsDir | LibDirs]),
- rebar_prv_install_deps:setup_env(State),
-
- TargetProviders = rebar_provider:get_target_providers(Command, State),
+ DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR),
+ PluginsDir = rebar_state:get(State, plugins_dir, ?DEFAULT_PLUGINS_DIR),
+ _UpdatedCodePaths = update_code_path_([DepsDir, PluginsDir | LibDirs]).
- lists:foldl(fun(TargetProvider, Conf) ->
- Provider = rebar_provider:get_provider(TargetProvider
- ,rebar_state:providers(Conf)),
- {ok, Conf1} = rebar_provider:do(Provider, Conf),
- Conf1
- end, State, TargetProviders).
%% ===================================================================
%% Internal functions
%% ===================================================================
-update_code_path([]) ->
- no_change;
-update_code_path(Paths) ->
+update_code_path_(Paths) ->
LibPaths = expand_lib_dirs(Paths, rebar_utils:get_cwd(), []),
ok = code:add_pathsa(LibPaths),
%% track just the paths we added, so we can remove them without
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index 6a16977..33983e4 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -96,30 +96,30 @@ compile(Config, Dir) ->
rebar_base_compiler:run(Config,
check_files(rebar_state:get(
Config, xrl_first_files, [])),
- "src", ".xrl", "src", ".erl",
+ filename:join(Dir, "src"), ".xrl", filename:join(Dir, "src"), ".erl",
fun compile_xrl/3),
rebar_base_compiler:run(Config,
check_files(rebar_state:get(
Config, yrl_first_files, [])),
- "src", ".yrl", "src", ".erl",
+ filename:join(Dir, "src"), ".yrl", filename:join(Dir, "src"), ".erl",
fun compile_yrl/3),
rebar_base_compiler:run(Config,
check_files(rebar_state:get(
Config, mib_first_files, [])),
- "mibs", ".mib", "priv/mibs", ".bin",
+ filename:join(Dir, "mibs"), ".mib", filename:join([Dir, "priv", "mibs"]), ".bin",
fun compile_mib/3),
doterl_compile(Config, Dir).
-spec clean(rebar_state:t(), file:filename()) -> 'ok'.
-clean(Config, _AppFile) ->
- MibFiles = rebar_utils:find_files("mibs", ?RE_PREFIX".*\\.mib\$"),
+clean(Config, AppDir) ->
+ MibFiles = rebar_utils:find_files(filename:join(AppDir, "mibs"), ?RE_PREFIX".*\\.mib\$"),
MIBs = [filename:rootname(filename:basename(MIB)) || MIB <- MibFiles],
rebar_file_utils:delete_each(
- [filename:join(["include",MIB++".hrl"]) || MIB <- MIBs]),
+ [filename:join([AppDir, "include",MIB++".hrl"]) || MIB <- MIBs]),
lists:foreach(fun(F) -> ok = rebar_file_utils:rm_rf(F) end,
- ["ebin/*.beam", "priv/mibs/*.bin"]),
+ [filename:join(AppDir, "ebin/*.beam"), filename:join(AppDir, "priv/mibs/*.bin")]),
- YrlFiles = rebar_utils:find_files("src", ?RE_PREFIX".*\\.[x|y]rl\$"),
+ YrlFiles = rebar_utils:find_files(filename:join(AppDir, "src"), ?RE_PREFIX".*\\.[x|y]rl\$"),
rebar_file_utils:delete_each(
[ binary_to_list(iolist_to_binary(re:replace(F, "\\.[x|y]rl$", ".erl")))
|| F <- YrlFiles ]),
@@ -131,9 +131,9 @@ clean(Config, _AppFile) ->
%% directory structure in ebin with .beam files within. As such, we want
%% to scan whatever is left in the ebin/ directory for sub-dirs which
%% satisfy our criteria.
- BeamFiles = rebar_utils:find_files("ebin", ?RE_PREFIX".*\\.beam\$"),
+ BeamFiles = rebar_utils:find_files(filename:join(AppDir, "ebin"), ?RE_PREFIX".*\\.beam\$"),
rebar_file_utils:delete_each(BeamFiles),
- lists:foreach(fun(Dir) -> delete_dir(Dir, dirs(Dir)) end, dirs("ebin")),
+ lists:foreach(fun(Dir) -> delete_dir(Dir, dirs(Dir)) end, dirs(filename:join(AppDir, "ebin"))),
ok.
%% ===================================================================
@@ -241,14 +241,14 @@ test_compile_config_and_opts(Config, ErlOpts, Cmd) ->
%% *_first_files is questionable as the file would need to exist
%% in all project directories for it to work.
OptsAtom = list_to_atom(Cmd ++ "_compile_opts"),
- TestOpts = rebar_state:get_list(Config3, OptsAtom, []),
+ TestOpts = rebar_state:get(Config3, OptsAtom, []),
Opts0 = [{d, 'TEST'}] ++
ErlOpts ++ TestOpts ++ TriqOpts ++ PropErOpts ++ EqcOpts,
Opts = [O || O <- Opts0, O =/= no_debug_info],
Config4 = rebar_state:set(Config3, erl_opts, Opts),
FirstFilesAtom = list_to_atom(Cmd ++ "_first_files"),
- FirstErls = rebar_state:get_list(Config4, FirstFilesAtom, []),
+ FirstErls = rebar_state:get(Config4, FirstFilesAtom, []),
Config5 = rebar_state:set(Config4, erl_first_files, FirstErls),
{Config5, Opts}.
@@ -274,7 +274,7 @@ define_if(Def, true) -> [{d, Def}];
define_if(_Def, false) -> [].
is_lib_avail(Config, DictKey, Mod, Hrl, Name) ->
- case rebar_state:get_xconf(Config, DictKey, undefined) of
+ case rebar_state:get(Config, DictKey, undefined) of
undefined ->
IsAvail = case code:lib_dir(Mod, include) of
{error, bad_name} ->
@@ -282,17 +282,17 @@ is_lib_avail(Config, DictKey, Mod, Hrl, Name) ->
Dir ->
filelib:is_regular(filename:join(Dir, Hrl))
end,
- NewConfig = rebar_state:set_xconf(Config, DictKey, IsAvail),
+ NewConfig = rebar_state:set(Config, DictKey, IsAvail),
?DEBUG("~s availability: ~p\n", [Name, IsAvail]),
{NewConfig, IsAvail};
IsAvail ->
{Config, IsAvail}
end.
--spec doterl_compile(rebar_state:t(), file:filename()) -> 'ok'.
-doterl_compile(Config, Dir) ->
- ErlOpts = rebar_utils:erl_opts(Config),
- doterl_compile(Config, Dir, [], ErlOpts).
+-spec doterl_compile(rebar_state:t(), file:filename()) -> ok.
+doterl_compile(State, Dir) ->
+ ErlOpts = rebar_utils:erl_opts(State),
+ doterl_compile(State, Dir, [], ErlOpts).
doterl_compile(Config, Dir, MoreSources, ErlOpts) ->
OutDir = filename:join(Dir, "ebin"),
@@ -634,16 +634,19 @@ compile_yrl(Source, Target, Config) ->
-spec compile_xrl_yrl(rebar_state:t(), file:filename(),
file:filename(), list(), module()) -> 'ok'.
compile_xrl_yrl(Config, Source, Target, Opts, Mod) ->
+ Dir = rebar_state:dir(Config),
+ Opts1 = [{includefile, filename:join(Dir, I)} || {includefile, I} <- Opts,
+ filename:pathtype(I) =:= relative],
case needs_compile(Source, Target, []) of
true ->
- case Mod:file(Source, Opts ++ [{return, true}]) of
+ case Mod:file(Source, Opts1 ++ [{return, true}]) of
{ok, _} ->
ok;
{ok, _Mod, Ws} ->
rebar_base_compiler:ok_tuple(Config, Source, Ws);
{error, Es, Ws} ->
rebar_base_compiler:error_tuple(Config, Source,
- Es, Ws, Opts)
+ Es, Ws, Opts1)
end;
false ->
skipped
diff --git a/src/rebar_fetch.erl b/src/rebar_fetch.erl
index 6b31f6c..0a90848 100644
--- a/src/rebar_fetch.erl
+++ b/src/rebar_fetch.erl
@@ -49,14 +49,16 @@ lock_source(_AppDir, Source) ->
download_source(AppDir, Source) ->
TmpDir = ec_file:insecure_mkdtemp(),
AppDir1 = ec_cnv:to_list(AppDir),
+ ec_file:mkdir_p(AppDir1),
case download_source_tmp(TmpDir, Source) of
{ok, _} ->
- ec_file:mkdir_p(AppDir1),
ok = ec_file:copy(TmpDir, filename:absname(AppDir1), [recursive]);
{tarball, File} ->
- ok = erl_tar:extract(File, [{cwd,
- (filename:dirname(filename:absname(AppDir1)))}
- ,compressed])
+ ok = erl_tar:extract(File, [{cwd, TmpDir}
+ ,compressed]),
+ BaseName = filename:basename(AppDir1),
+ [FromDir] = filelib:wildcard(filename:join(TmpDir, BaseName++"-*")),
+ ec_file:copy(FromDir, AppDir1, [recursive])
end.
download_source_tmp(TmpDir, {p4, Url}) ->
diff --git a/src/rebar_packages.erl b/src/rebar_packages.erl
index 103d3a3..cd979fa 100644
--- a/src/rebar_packages.erl
+++ b/src/rebar_packages.erl
@@ -4,7 +4,7 @@
-include("rebar.hrl").
--spec get_packages(rebar_state:t()) -> {list(), rlx_depsolver:t()}.
+-spec get_packages(rebar_state:t()) -> {rebar_dict(), rlx_depsolver:t()}.
get_packages(State) ->
RebarDir = rebar_state:get(State, global_rebar_dir, filename:join(os:getenv("HOME"), ".rebar")),
PackagesFile = filename:join(RebarDir, "packages"),
@@ -12,12 +12,13 @@ get_packages(State) ->
true ->
try
{ok, Binary} = file:read_file(PackagesFile),
- binary_to_term(Binary)
+ {Dict, Graph} = binary_to_term(Binary),
+ {Dict, Graph}
catch
_:_ ->
?ERROR("Bad packages index, try to fix with `rebar update`~n", []),
- {[], rlx_depsolver:new()}
+ {dict:new(), rlx_depsolver:new_graph()}
end;
false ->
- {[], rlx_depsolver:new()}
+ {dict:new(), rlx_depsolver:new_graph()}
end.
diff --git a/src/rebar_plugins.erl b/src/rebar_plugins.erl
index 0fdbc6d..b180ede 100644
--- a/src/rebar_plugins.erl
+++ b/src/rebar_plugins.erl
@@ -3,10 +3,36 @@
-module(rebar_plugins).
--export([]).
+-export([install/1]).
-include("rebar.hrl").
%% ===================================================================
%% Public API
%% ===================================================================
+
+install(State) ->
+ State1 = rebar_state:set(State, deps_dir, ?DEFAULT_PLUGINS_DIR),
+
+ Plugins = rebar_state:get(State1, plugins, []),
+ {ok, State2} = rebar_prv_install_deps:handle_deps(State1, Plugins),
+
+ Apps = rebar_state:get(State2, all_deps, []),
+ ToBuild = lists:dropwhile(fun rebar_app_info:valid/1, Apps),
+ lists:foreach(fun(AppInfo) ->
+ C = rebar_config:consult(rebar_app_info:dir(AppInfo)),
+ S = rebar_state:new(rebar_state:new(), C, rebar_app_info:dir(AppInfo)),
+ rebar_prv_compile:build(S, AppInfo)
+ end, ToBuild),
+
+ PluginProviders = plugin_providers(Plugins),
+ {ok, PluginProviders, rebar_state:set(State2, deps_dir, ?DEFAULT_DEPS_DIR)}.
+
+plugin_providers(Plugins) ->
+ lists:map(fun({Plugin, _, _}) when is_atom(Plugin) ->
+ Plugin;
+ ({Plugin, _}) when is_atom(Plugin) ->
+ Plugin;
+ (Plugin) when is_atom(Plugin) ->
+ Plugin
+ end, Plugins).
diff --git a/src/rebar_provider.erl b/src/rebar_provider.erl
deleted file mode 100644
index e5d7520..0000000
--- a/src/rebar_provider.erl
+++ /dev/null
@@ -1,165 +0,0 @@
--module(rebar_provider).
-
-%% API
--export([new/2,
- do/2,
- impl/1,
- get_provider/2,
- get_target_providers/2,
- help/1,
- format/1]).
-
--export_type([t/0]).
-
--include("rebar.hrl").
-
-%%%===================================================================
-%%% Types
-%%%===================================================================
-
--opaque t() :: record(provider).
-
--type provider_name() :: atom().
-
--ifdef(have_callback_support).
-
--callback init(rebar_state:t()) -> {ok, rebar_state:t()} | relx:error().
--callback do(rebar_state:t()) -> {ok, rebar_state:t()} | relx:error().
-
--else.
-
-%% In the case where R14 or lower is being used to compile the system
-%% we need to export a behaviour info
--export([behaviour_info/1]).
--spec behaviour_info(atom()) -> [{atom(), arity()}] | undefined.
-behaviour_info(callbacks) ->
- [{init, 1},
- {do, 1}];
-behaviour_info(_) ->
- undefined.
-
--endif.
-
-%%%===================================================================
-%%% API
-%%%===================================================================
-
-%% @doc create a new provider object from the specified module. The
-%% module should implement the provider behaviour.
-%%
-%% @param ModuleName The module name.
-%% @param State0 The current state of the system
--spec new(module(), rebar_state:t()) ->
- {ok, rebar_state:t()}.
-new(ModuleName, State0) when is_atom(ModuleName) ->
- case code:which(ModuleName) of
- non_existing ->
- ?ERROR("Module ~p does not exist.", [ModuleName]);
- _ ->
- ModuleName:init(State0)
- end.
-
-%% @doc Manipulate the state of the system, that new state
-%%
-%% @param Provider the provider object
-%% @param State the current state of the system
--spec do(Provider::t(), rebar_state:t()) ->
- {ok, rebar_state:t()}.
-do(Provider, State) ->
- {PreHooks, PostHooks} = rebar_state:hooks(State, Provider#provider.name),
- {ok, State1} = run_hook_plugins(PreHooks, State),
- {ok, State2} = (Provider#provider.provider_impl):do(State1),
- run_hook_plugins(PostHooks, State2).
-
-run_hook_plugins(Hooks, State) ->
- State1 = lists:foldl(fun(Hook, StateAcc) ->
- {ok, StateAcc1} = rebar_provider:do(Hook, StateAcc),
- StateAcc1
- end, State, Hooks),
- {ok, State1}.
-
-%%% @doc get the name of the module that implements the provider
-%%% @param Provider the provider object
--spec impl(Provider::t()) -> module().
-impl(Provider) ->
- Provider#provider.name.
-
-help(State) ->
- Providers = rebar_state:providers(State),
- Help = lists:sort([{ec_cnv:to_list(P#provider.name), P#provider.short_desc} || P <- Providers,
- P#provider.bare =/= true]),
- Longest = lists:max([length(X) || {X, _} <- Help]),
-
- lists:foreach(fun({Name, ShortDesc}) ->
- Length = length(Name),
- Spacing = lists:duplicate(Longest - Length + 8, " "),
- io:format("~s~s~s~n", [Name, Spacing, ShortDesc])
- end, Help).
-
-
-%% @doc print the provider module name
-%%
-%% @param T - The provider
-%% @return An iolist describing the provider
--spec format(t()) -> iolist().
-format(#provider{name=Name}) ->
- atom_to_list(Name).
-
-get_target_providers(Target, State) ->
- Providers = rebar_state:providers(State),
- TargetProviders = lists:filter(fun(#provider{name=T}) when T =:= Target->
- true;
- (#provider{name=T}) ->
- false
- end, Providers),
- process_deps(TargetProviders, Providers).
-
--spec get_provider(provider_name(), [t()]) -> t().
-get_provider(ProviderName, [Provider = #provider{name = ProviderName} | _]) ->
- Provider;
-get_provider(ProviderName, [_ | Rest]) ->
- get_provider(ProviderName, Rest);
-get_provider(_ProviderName, _) ->
- [].
-
-process_deps([], _Providers) ->
- [];
-process_deps(TargetProviders, Providers) ->
- DepChain = lists:flatmap(fun(Provider) ->
- {DC, _, _} = process_deps(Provider, Providers, []),
- DC
- end, TargetProviders),
- ['NONE' | Rest] =
- reorder_providers(lists:flatten([{'NONE', P#provider.name} || P <- TargetProviders] ++ DepChain)),
- Rest.
-
-process_deps(Provider, Providers, Seen) ->
- case lists:member(Provider, Seen) of
- true ->
- {[], Providers, Seen};
- false ->
- Deps = Provider#provider.deps,
- DepList = lists:map(fun(Dep) ->
- {Dep, Provider#provider.name}
- end, Deps),
- {NewDeps, _, NewSeen} =
- lists:foldl(fun(Arg, Acc) ->
- process_dep(Arg, Acc)
- end,
- {[], Providers, Seen}, Deps),
- {[DepList | NewDeps], Providers, NewSeen}
- end.
-
-process_dep(ProviderName, {Deps, Providers, Seen}) ->
- Provider = get_provider(ProviderName, Providers),
- {NewDeps, _, NewSeen} = process_deps(Provider, Providers, [ProviderName | Seen]),
- {[Deps | NewDeps], Providers, NewSeen}.
-
-%% @doc Reorder the providers according to thier dependency set.
-reorder_providers(OProviderList) ->
- case rebar_topo:sort(OProviderList) of
- {ok, ProviderList} ->
- ProviderList;
- {cycle, _} ->
- ?ERROR("There was a cycle in the provider list. Unable to complete build!", [])
- end.
diff --git a/src/rebar_prv_app_discovery.erl b/src/rebar_prv_app_discovery.erl
index 897a38d..e2dcf23 100644
--- a/src/rebar_prv_app_discovery.erl
+++ b/src/rebar_prv_app_discovery.erl
@@ -3,10 +3,11 @@
-module(rebar_prv_app_discovery).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
@@ -19,18 +20,22 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = true,
- deps = ?DEPS,
- example = "",
- short_desc = "",
- desc = "",
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, true},
+ {deps, ?DEPS},
+ {example, ""},
+ {short_desc, ""},
+ {desc, ""},
+ {opts, []}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()}.
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
LibDirs = rebar_state:get(State, lib_dirs, ?DEFAULT_LIB_DIRS),
State1 = rebar_app_discover:do(State, LibDirs),
{ok, State1}.
+
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
diff --git a/src/rebar_prv_clean.erl b/src/rebar_prv_clean.erl
new file mode 100644
index 0000000..72b85dc
--- /dev/null
+++ b/src/rebar_prv_clean.erl
@@ -0,0 +1,44 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+
+-module(rebar_prv_clean).
+
+-behaviour(provider).
+
+-export([init/1,
+ do/1,
+ format_error/2]).
+
+-include("rebar.hrl").
+
+-define(PROVIDER, clean).
+-define(DEPS, [app_discovery]).
+
+%% ===================================================================
+%% Public API
+%% ===================================================================
+
+-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
+init(State) ->
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar clean"},
+ {short_desc, "Remove compiled beam files from apps."},
+ {desc, ""},
+ {opts, []}])),
+ {ok, State1}.
+
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
+do(State) ->
+ ProjectApps = rebar_state:project_apps(State),
+ lists:foreach(fun(AppInfo) ->
+ ?INFO("Cleaning out ~s...~n", [rebar_app_info:name(AppInfo)]),
+ rebar_erlc_compiler:clean(State, ec_cnv:to_list(rebar_app_info:dir(AppInfo)))
+ end, ProjectApps),
+ {ok, State}.
+
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl
index b880d77..37d1920 100644
--- a/src/rebar_prv_common_test.erl
+++ b/src/rebar_prv_common_test.erl
@@ -6,6 +6,7 @@
-behaviour(rebar_provider).
-export([init/1,
+ format_error/2,
do/1]).
-include("rebar.hrl").
@@ -19,15 +20,15 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State,
- #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar ct",
- short_desc = "Run Common Tests",
- desc = "",
- opts = []}),
+ Provider = providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {deps, ?DEPS},
+ {bare, false},
+ {example, "rebar ct"},
+ {short_desc, "Run Common Tests"},
+ {desc, ""},
+ {opts, ct_opts(State)}]),
+ State1 = rebar_state:add_provider(State, Provider),
{ok, State1}.
-spec do(rebar_state:t()) -> {ok, rebar_state:t()}.
@@ -36,6 +37,106 @@ do(State) ->
ct:run_test(Opts),
{ok, State}.
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
+
+ct_opts(State) ->
+ DefaultTestDir = filename:join([rebar_state:dir(State), "test"]),
+ DefaultLogsDir = filename:join([rebar_state:dir(State), "logs"]),
+ [{dir, undefined, "dir", {string, DefaultTestDir}, help(dir)}, %% dir
+ {suite, undefined, "suite", string, help(suite)}, %% comma-seperated list
+ {group, undefined, "group", string, help(group)}, %% comma-seperated list
+ {testcase, undefined, "case", string, help(testcase)}, %% comma-seperated list
+ {spec, undefined, "spec", string, help(spec)}, %% comma-seperated list
+ {join_specs, undefined, "join_specs", boolean, help(join_specs)}, %% Boolean
+ {label, undefined, "label", string, help(label)}, %% String
+ {config, undefined, "config", string, help(config)}, %% comma-seperated list
+ {userconfig, undefined, "userconfig", string, help(userconfig)}, %% [{CallbackMod, CfgStrings}] | {CallbackMod, CfgStrings}
+ {allow_user_terms, undefined, "allow_user_terms", boolean, help(allow_user_terms)}, %% Bool
+ {logdir, undefined, "logdir", {string, DefaultLogsDir}, help(logdir)}, %% string
+ {logopts, undefined, "logopts", string, help(logopts)}, %% enum, no_nl | no_src
+ {verbosity, undefined, "verbosity", string, help(verbosity)}, %% Integer OR [{Category, VLevel}]
+ {silent_connections, undefined, "silent_connections", string,
+ help(silent_connections)}, % all OR %% comma-seperated list
+ {stylesheet, undefined, "stylesheet", string, help(stylesheet)}, %% file
+ {cover, undefined, "cover", string, help(cover)}, %% file
+ {cover_stop, undefined, "cover_stop", boolean, help(cover_stop)}, %% Boolean
+ {event_handler, undefined, "event_handler", string, help(event_handler)}, %% EH | [EH] WHERE EH atom() | {atom(), InitArgs} | {[atom()], InitArgs}
+ {include, undefined, "include", string, help(include)},
+ {abort_if_missing_suites, undefined, "abort_if_missing_suites", {boolean, true},
+ help(abort_if_missing_suites)}, %% boolean
+ {multiply_timetraps, undefined, "multiply_timetraps", integer,
+ help(multiply_timetraps)}, %% integer
+ {scale_timetraps, undefined, "scale_timetraps", boolean, help(scale_timetraps)}, %% Boolean
+ {create_priv_dir, undefined, "create_priv_dir", string, help(create_priv_dir)}, %% enum: auto_per_run | auto_per_tc | manual_per_tc
+ {repeat, undefined, "repeat", integer, help(repeat)}, %% integer
+ {duration, undefined, "duration", string, help(duration)}, % format: HHMMSS
+ {until, undefined, "until", string, help(until)}, %% format: YYMoMoDD[HHMMSS]
+ {force_stop, undefined, "force_stop", string, help(force_stop)}, % enum: skip_rest, bool
+ {basic_html, undefined, "basic_html", boolean, help(basic_html)}, %% Booloean
+ {ct_hooks, undefined, "ct_hooks", string, help(ct_hooks)} %% List: [CTHModule | {CTHModule, CTHInitArgs}] where CTHModule is atom CthInitArgs is term
+ ].
+
+help(dir) ->
+ "Test folder (default: test/)";
+help(suite) ->
+ "List of test suites to run";
+help(group) ->
+ "List of test groups to run";
+help(testcase) ->
+ "List of test cases to run";
+help(spec) ->
+ "List of test specs to run";
+help(join_specs) ->
+ ""; %% ??
+help(label) ->
+ "Test label";
+help(config) ->
+ "List of config files";
+help(allow_user_terms) ->
+ ""; %% ??
+help(logdir) ->
+ "Log folder";
+help(logopts) ->
+ ""; %% ??
+help(verbosity) ->
+ "Verbosity";
+help(silent_connections) ->
+ ""; %% ??
+help(stylesheet) ->
+ "Stylesheet to use for test results";
+help(cover) ->
+ "Cover file to use";
+help(cover_stop) ->
+ ""; %% ??
+help(event_handler) ->
+ "Event handlers to attach to the runner";
+help(include) ->
+ "Include folder";
+help(abort_if_missing_suites) ->
+ "Abort if suites are missing";
+help(multiply_timetraps) ->
+ ""; %% ??
+help(scale_timetraps) ->
+ ""; %% ??
+help(create_priv_dir) ->
+ ""; %% ??
+help(repeat) ->
+ "How often to repeat tests";
+help(duration) ->
+ "Max runtime (format: HHMMSS)";
+help(until) ->
+ "Run until (format: HHMMSS)";
+help(force_stop) ->
+ "Force stop after time";
+help(basic_html) ->
+ "Show basic HTML";
+help(ct_hooks) ->
+ "";
+help(userconfig) ->
+ "".
+
build_options(State) ->
Arguments = rebar_state:command_args(State),
Opts = parse_args(Arguments, []),
diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl
index d89a4b0..30611cd 100644
--- a/src/rebar_prv_compile.erl
+++ b/src/rebar_prv_compile.erl
@@ -1,9 +1,10 @@
-module(rebar_prv_compile).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
do/1,
+ format_error/2,
build/2]).
-include("rebar.hrl").
@@ -11,34 +12,48 @@
-define(PROVIDER, compile).
-define(DEPS, [lock]).
+-define(DEFAULT_JOBS, 3).
+
%% ===================================================================
%% Public API
%% ===================================================================
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar compile",
- short_desc = "Compile apps .app.src and .erl files.",
- desc = "",
- opts = []}),
+ JobsHelp = io_lib:format(
+ "Number of concurrent workers the compiler may use. Default: ~B",
+ [?DEFAULT_JOBS]),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar compile"},
+ {short_desc, "Compile apps .app.src and .erl files."},
+ {desc, ""},
+ {opts, [
+ {jobs, $j, "jobs", integer, JobsHelp}
+ ]}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()} | relx:error().
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
- ProjectApps = rebar_state:project_apps(State),
- Deps = rebar_state:get(State, deps_to_build, []),
+ {ok, State1} = handle_args(State),
+
+ ProjectApps = rebar_state:project_apps(State1),
+ Deps = rebar_state:get(State1, deps_to_build, []),
lists:foreach(fun(AppInfo) ->
- C = rebar_config:consult(rebar_app_info:dir(AppInfo)),
- S = rebar_state:new(rebar_state:new(), C, rebar_app_info:dir(AppInfo)),
+ AppDir = rebar_app_info:dir(AppInfo),
+ C = rebar_config:consult(AppDir),
+ S = rebar_state:new(State1, C, AppDir),
build(S, AppInfo)
end, Deps++ProjectApps),
- {ok, State}.
+ {ok, State1}.
+
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
build(State, AppInfo) ->
?INFO("Compiling ~s~n", [rebar_app_info:name(AppInfo)]),
@@ -49,3 +64,8 @@ build(State, AppInfo) ->
%% ===================================================================
%% Internal functions
%% ===================================================================
+
+handle_args(State) ->
+ {Args, _} = rebar_state:command_parsed_args(State),
+ Jobs = proplists:get_value(jobs, Args, ?DEFAULT_JOBS),
+ {ok, rebar_state:set(State, jobs, Jobs)}.
diff --git a/src/rebar_prv_deps.erl b/src/rebar_prv_deps.erl
index 111f32f..80122ac 100644
--- a/src/rebar_prv_deps.erl
+++ b/src/rebar_prv_deps.erl
@@ -1,9 +1,10 @@
-module(rebar_prv_deps).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
@@ -12,20 +13,24 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = true,
- deps = ?DEPS,
- example = "rebar deps",
- short_desc = "List dependencies",
- desc = info("List dependencies"),
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, true},
+ {deps, ?DEPS},
+ {example, "rebar deps"},
+ {short_desc, "List dependencies"},
+ {desc, info("List dependencies")},
+ {opts, []}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()}.
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
{ok, State}.
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
+
info(Description) ->
io_lib:format("~s.~n"
"~n"
diff --git a/src/rebar_prv_do.erl b/src/rebar_prv_do.erl
index a2ac648..e66fdbd 100644
--- a/src/rebar_prv_do.erl
+++ b/src/rebar_prv_do.erl
@@ -3,10 +3,11 @@
-module(rebar_prv_do).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
@@ -19,27 +20,30 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar3 do <task1>, <task2>, ...",
- short_desc = "Higher order provider for running multiple tasks in a sequence.",
- desc = "",
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar3 do <task1>, <task2>, ..."},
+ {short_desc, "Higher order provider for running multiple tasks in a sequence."},
+ {desc, ""},
+ {opts, []}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()} | relx:error().
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
Tasks = args_to_tasks(rebar_state:command_args(State)),
- State1 = lists:foldl(fun(TaskArgs, StateAcc) ->
+ lists:foldl(fun(TaskArgs, {ok, StateAcc}) ->
[TaskStr | Args] = string:tokens(TaskArgs, " "),
Task = list_to_atom(TaskStr),
StateAcc1 = rebar_state:set(StateAcc, task, Task),
StateAcc2 = rebar_state:command_args(StateAcc1, Args),
rebar_core:process_command(StateAcc2, Task)
- end, State, Tasks),
- {ok, State1}.
+ end, {ok, State}, Tasks).
+
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
args_to_tasks(Args) ->
[string:strip(T) || T <- string:tokens(string:join(Args, " "), ",")].
diff --git a/src/rebar_erlydtl_compiler.erl b/src/rebar_prv_erlydtl_compiler.erl
index 88ee20f..8d80cdd 100644
--- a/src/rebar_erlydtl_compiler.erl
+++ b/src/rebar_prv_erlydtl_compiler.erl
@@ -92,12 +92,13 @@
%% {doc_root, "templates"}, {module_ext, ""}, {source_ext, ".html"}
%% ]
%% ]}.
--module(rebar_erlydtl_compiler).
+-module(rebar_prv_erlydtl_compiler).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
%% for internal use only
-export([info/2]).
@@ -113,22 +114,23 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar erlydtl compile",
- short_desc = "Compile erlydtl templates.",
- desc = "",
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar erlydtl compile"},
+ {short_desc, "Compile erlydtl templates."},
+ {desc, ""},
+ {opts, []}])),
{ok, State1}.
do(Config) ->
MultiDtlOpts = erlydtl_opts(Config),
OrigPath = code:get_path(),
- true = code:add_path(rebar_utils:ebin_dir()),
+ %true = code:add_path(rebar_utils:ebin_dir()),
Result = lists:foldl(fun(DtlOpts, _) ->
+ file:make_dir(option(out_dir, DtlOpts)),
rebar_base_compiler:run(Config, [],
option(doc_root, DtlOpts),
option(source_ext, DtlOpts),
@@ -144,6 +146,10 @@ do(Config) ->
true = code:set_path(OrigPath),
{Result, Config}.
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
+
%% ===================================================================
%% Internal functions
%% ===================================================================
@@ -230,24 +236,15 @@ do_compile(Config, Source, Target, DtlOpts) ->
Opts = lists:ukeymerge(1, DtlOpts, Sorted),
?INFO("Compiling \"~s\" -> \"~s\" with options:~n ~s~n",
[Source, Target, io_lib:format("~p", [Opts])]),
- case erlydtl:compile(Source,
- module_name(Target),
+ case erlydtl:compile_file(ec_cnv:to_list(Source),
+ list_to_atom(module_name(Target)),
Opts) of
- ok ->
- ok;
{ok, _Mod} ->
ok;
{ok, _Mod, Ws} ->
rebar_base_compiler:ok_tuple(Config, Source, Ws);
- {ok, _Mod, _Bin, Ws} ->
- rebar_base_compiler:ok_tuple(Config, Source, Ws);
error ->
rebar_base_compiler:error_tuple(Config, Source, [], [], Opts);
- {error, {_File, _Msgs} = Error} ->
- rebar_base_compiler:error_tuple(Config, Source, [Error], [], Opts);
- {error, Msg} ->
- Es = [{Source, [{erlydtl_parser, Msg}]}],
- rebar_base_compiler:error_tuple(Config, Source, Es, [], Opts);
{error, Es, Ws} ->
rebar_base_compiler:error_tuple(Config, Source, Es, Ws, Opts)
end.
diff --git a/src/rebar_prv_escripter.erl b/src/rebar_prv_escripter.erl
deleted file mode 100644
index 418ac6c..0000000
--- a/src/rebar_prv_escripter.erl
+++ /dev/null
@@ -1,224 +0,0 @@
-%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
-%% ex: ts=4 sw=4 et
-%% -------------------------------------------------------------------
-%%
-%% rebar: Erlang Build Tools
-%%
-%% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com)
-%%
-%% Permission is hereby granted, free of charge, to any person obtaining a copy
-%% of this software and associated documentation files (the "Software"), to deal
-%% in the Software without restriction, including without limitation the rights
-%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-%% copies of the Software, and to permit persons to whom the Software is
-%% furnished to do so, subject to the following conditions:
-%%
-%% The above copyright notice and this permission notice shall be included in
-%% all copies or substantial portions of the Software.
-%%
-%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-%% THE SOFTWARE.
-%% -------------------------------------------------------------------
--module(rebar_prv_escripter).
-
--behaviour(rebar_provider).
-
--export([init/1,
- do/1]).
-
--export([escriptize/2,
- clean/2]).
-
-%% for internal use only
--export([info/2]).
-
--include("rebar.hrl").
--include_lib("kernel/include/file.hrl").
-
--define(PROVIDER, escriptize).
--define(DEPS, [app_builder]).
-
-%% ===================================================================
-%% Public API
-%% ===================================================================
-
--spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
-init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar escriptize",
- short_desc = "Build escript from project.",
- desc = "",
- opts = []}),
- {ok, State1}.
-
--spec do(rebar_state:t()) -> {ok, rebar_state:t()} | relx:error().
-do(Config) ->
- AppName = rebar_state:get_local(Config, escript_top_level_app, undefined),
- App = rebar_state:get_app(Config, AppName),
- {ok, Config1} = escriptize(Config, rebar_app_info:app_file(App)),
- {ok, Config1}.
-
-escriptize(Config0, AppFile) ->
- %% Extract the application name from the archive -- this is the default
- %% name of the generated script
- {Config, AppName} = rebar_app_utils:app_name(Config0, AppFile),
- AppNameStr = atom_to_list(AppName),
-
- %% Get the output filename for the escript -- this may include dirs
- Filename = rebar_state:get_local(Config, escript_name, AppName),
- ok = filelib:ensure_dir(Filename),
-
- %% Look for a list of other applications (dependencies) to include
- %% in the output file. We then use the .app files for each of these
- %% to pull in all the .beam files.
- InclBeams = get_app_beams(
- rebar_state:get_local(Config, escript_incl_apps, []), []),
-
- %% Look for a list of extra files to include in the output file.
- %% For internal rebar-private use only. Do not use outside rebar.
- InclExtra = get_extra(Config),
-
- %% Construct the archive of everything in ebin/ dir -- put it on the
- %% top-level of the zip file so that code loading works properly.
- EbinPrefix = filename:join(AppNameStr, "ebin"),
- EbinFiles = usort(load_files(EbinPrefix, "*", "ebin")),
- ExtraFiles = usort(InclBeams ++ InclExtra),
- Files = EbinFiles ++ ExtraFiles,
-
- case zip:create("mem", Files, [memory]) of
- {ok, {"mem", ZipBin}} ->
- %% Archive was successfully created. Prefix that binary with our
- %% header and write to our escript file
- Shebang = rebar_state:get(Config, escript_shebang,
- "#!/usr/bin/env escript\n"),
- Comment = rebar_state:get(Config, escript_comment, "%%\n"),
- DefaultEmuArgs = ?FMT("%%! -pa ~s/~s/ebin\n",
- [AppNameStr, AppNameStr]),
- EmuArgs = rebar_state:get(Config, escript_emu_args,
- DefaultEmuArgs),
- Script = iolist_to_binary([Shebang, Comment, EmuArgs, ZipBin]),
- case file:write_file(Filename, Script) of
- ok ->
- ok;
- {error, WriteError} ->
- ?ERROR("Failed to write ~p script: ~p\n",
- [AppName, WriteError]),
- ?FAIL
- end;
- {error, ZipError} ->
- ?ERROR("Failed to construct ~p escript: ~p\n",
- [AppName, ZipError]),
- ?FAIL
- end,
-
- %% 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, Config}.
-
-clean(Config0, AppFile) ->
- %% Extract the application name from the archive -- this is the default
- %% name of the generated script
- {Config, AppName} = rebar_app_utils:app_name(Config0, AppFile),
-
- %% Get the output filename for the escript -- this may include dirs
- Filename = rebar_state:get_local(Config, escript_name, AppName),
- rebar_file_utils:delete_each([Filename]),
- {ok, Config}.
-
-%% ===================================================================
-%% Internal functions
-%% ===================================================================
-
-info(help, escriptize) ->
- info_help("Generate escript archive");
-info(help, clean) ->
- info_help("Delete generated escript archive").
-
-info_help(Description) ->
- ?CONSOLE(
- "~s.~n"
- "~n"
- "Valid rebar.config options:~n"
- " ~p~n"
- " ~p~n"
- " ~p~n"
- " ~p~n"
- " ~p~n",
- [
- Description,
- {escript_name, "application"},
- {escript_incl_apps, []},
- {escript_shebang, "#!/usr/bin/env escript\n"},
- {escript_comment, "%%\n"},
- {escript_emu_args, "%%! -pa application/application/ebin\n"}
- ]).
-
-get_app_beams([], Acc) ->
- Acc;
-get_app_beams([App | Rest], Acc) ->
- case code:lib_dir(App, ebin) of
- {error, bad_name} ->
- ?ABORT("Failed to get ebin/ directory for "
- "~p escript_incl_apps.", [App]);
- Path ->
- Prefix = filename:join(atom_to_list(App), "ebin"),
- Acc2 = load_files(Prefix, "*", Path),
- get_app_beams(Rest, Acc2 ++ Acc)
- end.
-
-get_extra(Config) ->
- Extra = rebar_state:get_local(Config, escript_incl_extra, []),
- lists:foldl(fun({Wildcard, Dir}, Files) ->
- load_files(Wildcard, Dir) ++ Files
- end, [], Extra).
-
-load_files(Wildcard, Dir) ->
- load_files("", Wildcard, Dir).
-
-load_files(Prefix, Wildcard, Dir) ->
- [read_file(Prefix, Filename, Dir)
- || Filename <- filelib:wildcard(Wildcard, Dir)].
-
-read_file(Prefix, Filename, Dir) ->
- Filename1 = case Prefix of
- "" ->
- Filename;
- _ ->
- filename:join([Prefix, Filename])
- end,
- [dir_entries(filename:dirname(Filename1)),
- {Filename1, file_contents(filename:join(Dir, Filename))}].
-
-file_contents(Filename) ->
- {ok, Bin} = file:read_file(Filename),
- Bin.
-
-%% Given a filename, return zip archive dir entries for each sub-dir.
-%% Required to work around issues fixed in OTP-10071.
-dir_entries(File) ->
- Dirs = dirs(File),
- [{Dir ++ "/", <<>>} || Dir <- Dirs].
-
-%% Given "foo/bar/baz", return ["foo", "foo/bar", "foo/bar/baz"].
-dirs(Dir) ->
- dirs1(filename:split(Dir), "", []).
-
-dirs1([], _, Acc) ->
- lists:reverse(Acc);
-dirs1([H|T], "", []) ->
- dirs1(T, H, [H]);
-dirs1([H|T], Last, Acc) ->
- Dir = filename:join(Last, H),
- dirs1(T, Dir, [Dir|Acc]).
-
-usort(List) ->
- lists:ukeysort(1, lists:flatten(List)).
diff --git a/src/rebar_prv_help.erl b/src/rebar_prv_help.erl
index a9949e7..8300378 100644
--- a/src/rebar_prv_help.erl
+++ b/src/rebar_prv_help.erl
@@ -3,10 +3,11 @@
-module(rebar_prv_help).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
@@ -19,30 +20,49 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar help <task>",
- short_desc = "Display a list of tasks or help for a given task or subtask.",
- desc = "",
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar help <task>"},
+ {short_desc, "Display a list of tasks or help for a given task or subtask."},
+ {desc, "Display a list of tasks or help for a given task or subtask."},
+ {opts, [
+ {help_task, undefined, undefined, string, "Task to print help for."}
+ ]}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()} | relx:error().
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
- help(State),
- {ok, State}.
+ {Args, _} = rebar_state:command_parsed_args(State),
+ case proplists:get_value(help_task, Args, undefined) of
+ undefined ->
+ help(State),
+ {ok, State};
+ Name ->
+ Providers = rebar_state:providers(State),
+ case providers:get_provider(list_to_atom(Name), Providers) of
+ not_found ->
+ {error, io_lib:format("Unknown task ~s", [Name])};
+ Provider ->
+ providers:help(Provider),
+ {ok, State}
+ end
+ end.
+
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
%%
%% print help/usage string
%%
help(State) ->
?CONSOLE("Rebar is a tool for working with Erlang projects.~n~n", []),
- OptSpecList = rebar3:option_spec_list(),
+ OptSpecList = rebar3:global_option_spec_list(),
getopt:usage(OptSpecList, "rebar", "", []),
?CONSOLE("~nSeveral tasks are available:~n", []),
- rebar_provider:help(State),
+ providers:help(rebar_state:providers(State)),
?CONSOLE("~nRun 'rebar help <TASK>' for details.~n~n", []).
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index d20f2b5..522420d 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -26,14 +26,16 @@
%% -------------------------------------------------------------------
-module(rebar_prv_install_deps).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
--export([setup_env/1]).
+-export([handle_deps/2,
+ handle_deps/3]).
%% for internal use only
-export([get_deps_dir/1]).
@@ -43,9 +45,9 @@
-define(DEPS, [app_discovery]).
-type src_dep() :: {atom(), string(), {atom(), string(), string()}}.
--type binary_dep() :: {atom(), binary()} | atom().
+-type pkg_dep() :: {atom(), binary()} | atom().
--type dep() :: src_dep() | binary_dep().
+-type dep() :: src_dep() | pkg_dep().
%% ===================================================================
%% Public API
@@ -53,174 +55,237 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = true,
- deps = ?DEPS,
- example = undefined,
- short_desc = "Install dependencies",
- desc = info("Install dependencies"),
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, true},
+ {deps, ?DEPS},
+ {example, undefined},
+ {short_desc, "Install dependencies"},
+ {desc, info("Install dependencies")},
+ {opts, []}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()}.
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
- case rebar_state:get(State, locks, []) of
- [] ->
- handle_deps(State, ordsets:from_list(rebar_state:get(State, deps, [])));
- Locks ->
- handle_deps(State, ordsets:from_list(Locks))
+ ProjectApps = rebar_state:project_apps(State),
+ {ok, State1} = case rebar_state:get(State, locks, []) of
+ [] ->
+ handle_deps(State, rebar_state:get(State, deps, []));
+ Locks ->
+ handle_deps(State, Locks)
+ end,
+
+ Source = ProjectApps ++ rebar_state:src_apps(State1),
+ case rebar_topo:sort_apps(Source) of
+ {ok, Sort} ->
+ {ok, rebar_state:set(State1, deps_to_build, lists:dropwhile(fun rebar_app_info:valid/1, Sort -- ProjectApps))};
+ {error, Error} ->
+ {error, Error}
end.
-%% set REBAR_DEPS_DIR and ERL_LIBS environment variables
-setup_env(State) ->
- DepsDir = get_deps_dir(State),
- %% include rebar's DepsDir in ERL_LIBS
- Separator = case os:type() of
- {win32, nt} ->
- ";";
- _ ->
- ":"
- end,
- ERL_LIBS = case os:getenv("ERL_LIBS") of
- false ->
- {"ERL_LIBS", DepsDir};
- PrevValue ->
- {"ERL_LIBS", DepsDir ++ Separator ++ PrevValue}
- end,
- [{"REBAR_DEPS_DIR", DepsDir}, ERL_LIBS].
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
-spec get_deps_dir(rebar_state:t()) -> file:filename_all().
get_deps_dir(State) ->
BaseDir = rebar_state:get(State, base_dir, ""),
- get_deps_dir(BaseDir, "deps").
+ DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR),
+ get_deps_dir(BaseDir, DepsDir).
--spec get_deps_dir(file:filename_all(), rebar_state:t()) -> file:filename_all().
+-spec get_deps_dir(file:filename_all(), file:filename_all()) -> file:filename_all().
get_deps_dir(DepsDir, App) ->
filename:join(DepsDir, App).
-%% ===================================================================
-%% Internal functions
-%% ===================================================================
-
-spec handle_deps(rebar_state:t(), [dep()]) -> {ok, rebar_state:t()}.
-handle_deps(State, []) ->
- {ok, State};
handle_deps(State, Deps) ->
+ handle_deps(State, Deps, false).
+
+-spec handle_deps(rebar_state:t(), [dep()], boolean() | {true, binary(), integer()})
+ -> {ok, rebar_state:t()}.
+handle_deps(State, [], _) ->
+ {ok, State};
+handle_deps(State, Deps, Update) ->
%% Read in package index and dep graph
{Packages, Graph} = rebar_packages:get_packages(State),
- ProjectApps = rebar_state:project_apps(State),
- %% Split source deps form binary deps, needed to keep backwards compatibility
+ %% Split source deps from pkg deps, needed to keep backwards compatibility
DepsDir = get_deps_dir(State),
- {SrcDeps, BinaryDeps} = parse_deps(DepsDir, Deps),
- State1 = rebar_state:src_deps(rebar_state:binary_deps(State, BinaryDeps),
+ {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps),
+ State1 = rebar_state:src_deps(rebar_state:pkg_deps(State, PkgDeps),
SrcDeps),
%% Fetch transitive src deps
- State2 = update_src_deps(State1),
- Solved = case rebar_state:binary_deps(State2) of
- [] -> %% No binary deps
- [];
- BinaryDeps1 ->
- %% Find binary deps needed
- {ok, S} = rlx_depsolver:solve(Graph, BinaryDeps1),
- %% Create app_info record for each binary dep
- lists:map(fun({Name, Vsn}) ->
- AppInfo = package_to_app(DepsDir
- ,Packages
- ,Name
- ,Vsn),
- ok = maybe_fetch(AppInfo),
- AppInfo
- end, S)
+ State2 = update_src_deps(0, State1, Update),
+ Solved = case rebar_state:pkg_deps(State2) of
+ [] -> %% No pkg deps
+ [];
+ PkgDeps1 ->
+ %% Find pkg deps needed
+ {ok, S} = rlx_depsolver:solve(Graph, PkgDeps1),
+ %% Create app_info record for each pkg dep
+ [AppInfo || Pkg <- S,
+ AppInfo <- package_to_app(DepsDir
+ ,Packages
+ ,Pkg),
+ maybe_fetch(AppInfo, Update)]
end,
- Source = ProjectApps ++ ordsets:to_list(rebar_state:src_deps(State2)),
- AllDeps = ordsets:union([ordsets:to_list(rebar_state:src_deps(State2))
- ,ordsets:from_list(Solved)]),
-
+ AllDeps = lists:ukeymerge(2
+ ,lists:ukeysort(2, rebar_state:src_apps(State2))
+ ,lists:ukeysort(2, Solved)),
%% Sort all apps to build order
State3 = rebar_state:set(State2, all_deps, AllDeps),
- {ok, Sort} = rebar_topo:sort_apps(ordsets:to_list(Source)),
- {ok, rebar_state:set(State3, deps_to_build, lists:dropwhile(fun is_valid/1, Sort -- ProjectApps))}.
+ {ok, State3}.
+
+%% ===================================================================
+%% Internal functions
+%% ===================================================================
--spec is_valid(rebar_app_info:t()) -> boolean().
-is_valid(App) ->
- rebar_app_info:valid(App).
+package_to_app(DepsDir, Packages, Pkg={_, Vsn}) ->
+ Name = ec_cnv:to_binary(rlx_depsolver:dep_pkg(Pkg)),
+ FmtVsn = iolist_to_binary(rlx_depsolver:format_version(Vsn)),
+ case dict:find({Name, FmtVsn}, Packages) of
+ error ->
+ [];
+ {ok, P} ->
+ PkgDeps = proplists:get_value(<<"deps">>, P, []),
+ Link = proplists:get_value(<<"link">>, P, ""),
+ {ok, AppInfo} = rebar_app_info:new(Name, FmtVsn),
+ AppInfo1 = rebar_app_info:deps(AppInfo, PkgDeps),
+ AppInfo2 = rebar_app_info:dir(AppInfo1, get_deps_dir(DepsDir, Name)),
+ [rebar_app_info:source(AppInfo2, Link)]
+ end.
--spec package_to_app(file:name(), rlx_depsolver:t(), binary(), binary()) -> rebar_app_info:t().
-package_to_app(DepsDir, Packages, Name, Vsn) ->
- FmtVsn = ec_cnv:to_binary(rlx_depsolver:format_version(Vsn)),
+-spec update_src_deps(integer(), rebar_state:t(), boolean()) -> rebar_state:t().
+update_src_deps(Level, State, Update) ->
+ SrcDeps = rebar_state:src_deps(State),
+ case lists:foldl(fun(AppInfo, {SrcDepsAcc, PkgDepsAcc, StateAcc}) ->
+ case Update of
+ {true, UpdateName, UpdateLevel} ->
+ handle_update(AppInfo
+ ,UpdateName
+ ,UpdateLevel
+ ,SrcDepsAcc
+ ,PkgDepsAcc
+ ,Level
+ ,StateAcc);
+ _ ->
+ maybe_fetch(AppInfo, false),
+ handle_dep(AppInfo
+ ,SrcDepsAcc
+ ,PkgDepsAcc
+ ,Level
+ ,StateAcc)
+ end
+ end, {[], rebar_state:pkg_deps(State), State}, SrcDeps) of
+ {[], NewPkgDeps, State1} ->
+ rebar_state:pkg_deps(State1, NewPkgDeps);
+ {NewSrcDeps, NewPkgDeps, State1} ->
+ State2 = rebar_state:pkg_deps(State1, NewPkgDeps),
+ State3 = rebar_state:src_deps(State2, NewSrcDeps),
+ update_src_deps(Level+1, State3, Update)
+ end.
- {ok, P} = dict:find({Name, FmtVsn}, Packages),
- PkgDeps = proplists:get_value(<<"deps">>, P),
- Link = proplists:get_value(<<"link">>, P),
+handle_update(AppInfo, UpdateName, UpdateLevel, SrcDeps, PkgDeps, Level, State) ->
+ Name = rebar_app_info:name(AppInfo),
+ Locks = rebar_state:get(State, locks, []),
+ {_, _, _, DepLevel} = lists:keyfind(Name, 1, Locks),
+ case UpdateLevel < DepLevel
+ orelse Name =:= UpdateName of
+ true ->
+ case maybe_fetch(AppInfo, true) of
+ true ->
+ handle_dep(AppInfo
+ ,SrcDeps
+ ,PkgDeps
+ ,Level
+ ,State);
- {ok, AppInfo} = rebar_app_info:new(Name, FmtVsn),
- AppInfo1 = rebar_app_info:deps(AppInfo, PkgDeps),
- AppInfo2 =
- rebar_app_info:dir(AppInfo1, get_deps_dir(DepsDir, <<Name/binary, "-", FmtVsn/binary>>)),
- rebar_app_info:source(AppInfo2, Link).
+ false ->
+ {SrcDeps, PkgDeps, State}
+ end;
+ false ->
+ {SrcDeps, PkgDeps, State}
+ end.
--spec update_src_deps(rebar_state:t()) -> rebat_state:t().
-update_src_deps(State) ->
- SrcDeps = rebar_state:src_deps(State),
+handle_dep(AppInfo, SrcDeps, PkgDeps, Level, State) ->
DepsDir = get_deps_dir(State),
- case lists:foldl(fun(AppInfo, {SrcDepsAcc, BinaryDepsAcc}) ->
- ok = maybe_fetch(AppInfo),
- {AppInfo1, NewSrcDeps, NewBinaryDeps} = handle_dep(DepsDir, AppInfo),
- {ordsets:union(ordsets:add_element(AppInfo1, SrcDepsAcc), NewSrcDeps)
- ,NewBinaryDeps++BinaryDepsAcc}
- end, {ordsets:new(), rebar_state:binary_deps(State)}, SrcDeps) of
- {NewSrcDeps, NewBinaryDeps} when length(SrcDeps) =:= length(NewSrcDeps) ->
- rebar_state:src_deps(rebar_state:binary_deps(State, NewBinaryDeps), NewSrcDeps);
- {NewSrcDeps, NewBinaryDeps} ->
- State1 = rebar_state:src_deps(rebar_state:binary_deps(State, NewBinaryDeps), NewSrcDeps),
- update_src_deps(State1)
- end.
+ {AppInfo1, NewSrcDeps, NewPkgDeps} =
+ handle_dep(DepsDir, AppInfo),
+ AppInfo2 = rebar_app_info:dep_level(AppInfo1, Level),
+ {NewSrcDeps ++ SrcDeps
+ ,NewPkgDeps++PkgDeps
+ ,rebar_state:src_apps(State, AppInfo2)}.
--spec handle_dep(binary(), rebar_state:t()) -> {[rebar_app_info:t()], [binary_dep()]}.
+-spec handle_dep(file:filename_all(), rebar_app_info:t()) ->
+ {rebar_app_info:t(), [rebar_app_info:t()], [pkg_dep()]}.
handle_dep(DepsDir, AppInfo) ->
C = rebar_config:consult(rebar_app_info:dir(AppInfo)),
S = rebar_state:new(rebar_state:new(), C, rebar_app_info:dir(AppInfo)),
Deps = rebar_state:get(S, deps, []),
AppInfo1 = rebar_app_info:deps(AppInfo, rebar_state:deps_names(S)),
- {SrcDeps, BinaryDeps} = parse_deps(DepsDir, Deps),
- {AppInfo1, SrcDeps, BinaryDeps}.
+ {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps),
+ {AppInfo1, SrcDeps, PkgDeps}.
--spec maybe_fetch(rebar_app_info:t()) -> ok.
-maybe_fetch(AppInfo) ->
- AppDir = rebar_app_info:dir(AppInfo),
- case filelib:is_dir(AppDir) of
- false ->
- ?INFO("Fetching ~s~n", [rebar_app_info:name(AppInfo)]),
- Source = rebar_app_info:source(AppInfo),
- rebar_fetch:download_source(AppDir, Source);
- true ->
- ok
+-spec maybe_fetch(rebar_app_info:t(), boolean() | {true, binary(), integer()}) -> boolean().
+maybe_fetch(AppInfo, Update) ->
+ AppDir = ec_cnv:to_list(rebar_app_info:dir(AppInfo)),
+ Apps = rebar_app_discover:find_apps(["_checkouts"], all),
+ case rebar_app_utils:find(rebar_app_info:name(AppInfo), Apps) of
+ {ok, _} ->
+ %% Don't fetch dep if it exists in the _checkouts dir
+ false;
+ error ->
+ Exists = case rebar_app_utils:is_app_dir(filename:absname(AppDir)++"-*") of
+ {true, _} ->
+ true;
+ _ ->
+ case rebar_app_utils:is_app_dir(filename:absname(AppDir)) of
+ {true, _} ->
+ true;
+ _ ->
+ false
+ end
+ end,
+
+ case not Exists orelse Update of
+ true ->
+ ?INFO("Fetching ~s~n", [rebar_app_info:name(AppInfo)]),
+ Source = rebar_app_info:source(AppInfo),
+ rebar_fetch:download_source(AppDir, Source),
+ true;
+ _ ->
+ false
+ end
end.
--spec parse_deps(binary(), [dep()]) -> {ordsets:ordset(rebar_app_info:t()), [binary_dep()]}.
+-spec parse_deps(binary(), [dep()]) -> {[rebar_app_info:t()], [pkg_dep()]}.
parse_deps(DepsDir, Deps) ->
- lists:foldl(fun({Name, Vsn}, {SrcDepsAcc, BinaryDepsAcc}) ->
+ lists:foldl(fun({Name, Vsn}, {SrcDepsAcc, PkgDepsAcc}) ->
{SrcDepsAcc, [parse_goal(ec_cnv:to_binary(Name)
- ,ec_cnv:to_binary(Vsn)) | BinaryDepsAcc]};
- (Name, {SrcDepsAcc, BinaryDepsAcc}) when is_atom(Name) ->
- {SrcDepsAcc, [ec_cnv:to_binary(Name) | BinaryDepsAcc]};
- ({Name, Vsn, Source}, {SrcDepsAcc, BinaryDepsAcc}) when is_tuple (Source) ->
- Dir = ec_cnv:to_list(get_deps_dir(DepsDir, Name)),
- {ok, Dep} = case rebar_app_info:discover(Dir) of
- {ok, App} ->
- {ok, App};
- not_found ->
- rebar_app_info:new(Name, Vsn, Dir)
- end,
- Dep1 = rebar_app_info:source(Dep, Source),
- {ordsets:add_element(Dep1, SrcDepsAcc), BinaryDepsAcc}
- end, {ordsets:new(), []}, Deps).
-
--spec parse_goal(binary(), binary()) -> binary_dep().
+ ,ec_cnv:to_binary(Vsn)) | PkgDepsAcc]};
+ (Name, {SrcDepsAcc, PkgDepsAcc}) when is_atom(Name) ->
+ {SrcDepsAcc, [ec_cnv:to_binary(Name) | PkgDepsAcc]};
+ ({Name, Vsn, Source}, {SrcDepsAcc, PkgDepsAcc}) when is_tuple (Source) ->
+ Dep = new_dep(DepsDir, Name, Vsn, Source),
+ {[Dep | SrcDepsAcc], PkgDepsAcc};
+ ({Name, Vsn, Source, _Level}, {SrcDepsAcc, PkgDepsAcc}) when is_tuple (Source) ->
+ Dep = new_dep(DepsDir, Name, Vsn, Source),
+ {[Dep | SrcDepsAcc], PkgDepsAcc}
+ end, {[], []}, Deps).
+
+new_dep(DepsDir, Name, Vsn, Source) ->
+ Dir = ec_cnv:to_list(get_deps_dir(DepsDir, Name)),
+ {ok, Dep} = case rebar_app_info:discover(Dir) of
+ {ok, App} ->
+ {ok, App};
+ not_found ->
+ rebar_app_info:new(Name, Vsn, Dir)
+ end,
+ rebar_app_info:source(Dep, Source).
+
+-spec parse_goal(binary(), binary()) -> pkg_dep().
parse_goal(Name, Constraint) ->
case re:run(Constraint, "([^\\d]*)(\\d.*)", [{capture, [1,2], binary}]) of
{match, [<<>>, Vsn]} ->
@@ -236,9 +301,7 @@ info(Description) ->
"~n"
"Valid rebar.config options:~n"
" ~p~n"
- " ~p~n"
- "Valid command line options:~n"
- " deps_dir=\"deps\" (override default or rebar.config deps_dir)~n",
+ " ~p~n",
[
Description,
{deps_dir, "deps"},
diff --git a/src/rebar_prv_lock.erl b/src/rebar_prv_lock.erl
index b4a7d8d..32c5f1a 100644
--- a/src/rebar_prv_lock.erl
+++ b/src/rebar_prv_lock.erl
@@ -1,9 +1,10 @@
-module(rebar_prv_lock).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
@@ -16,17 +17,17 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = true,
- deps = ?DEPS,
- example = "",
- short_desc = "Locks dependencies.",
- desc = info("Locks dependencies"),
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, true},
+ {deps, ?DEPS},
+ {example, ""},
+ {short_desc, "Locks dependencies."},
+ {desc, info("Locks dependencies")},
+ {opts, []}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()}.
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
case rebar_state:get(State, locks, []) of
[] ->
@@ -40,7 +41,8 @@ do(State) ->
Source when is_tuple(Source) ->
{rebar_app_info:name(Dep)
,rebar_app_info:original_vsn(Dep)
- ,rebar_fetch:lock_source(Dir, Source)};
+ ,rebar_fetch:lock_source(Dir, Source)
+ ,rebar_app_info:dep_level(Dep)};
_Source ->
{rebar_app_info:name(Dep)
,rebar_app_info:original_vsn(Dep)}
@@ -53,5 +55,9 @@ do(State) ->
{ok, State}
end.
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
+
info(_) ->
"".
diff --git a/src/rebar_prv_new.erl b/src/rebar_prv_new.erl
index ed3c1b4..2555b4d 100644
--- a/src/rebar_prv_new.erl
+++ b/src/rebar_prv_new.erl
@@ -1,9 +1,10 @@
-module(rebar_prv_new).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
@@ -16,17 +17,17 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar new <template>",
- short_desc = "Create new project from templates.",
- desc = info(create),
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar new <template>"},
+ {short_desc, "Create new project from templates."},
+ {desc, info()},
+ {opts, []}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()}.
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
case rebar_state:command_args(State) of
[TemplateName] ->
@@ -41,33 +42,17 @@ do(State) ->
{ok, State}
end.
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
+
%% ===================================================================
%% Internal functions
%% ===================================================================
-info(create) ->
- io_lib:format(
- "Create skel based on template and vars.~n"
- "~n"
- "Valid command line options:~n"
- " template= [var=foo,...]~n", []);
-info(create_app) ->
- io_lib:format(
- "Create simple app skel.~n"
- "~n"
- "Valid command line options:~n"
- " [appid=myapp]~n", []);
-info(create_lib) ->
- io_lib:format(
- "Create simple lib skel.~n"
- "~n"
- "Valid command line options:~n"
- " [libid=mylib]~n", []);
-info(create_node) ->
+info() ->
io_lib:format(
- "Create simple node skel.~n"
- "~n"
- "Valid command line options:~n"
- " [nodeid=mynode]~n", []);
-info(list_templates) ->
- io_lib:format("List available templates.~n", []).
+ "Create rebar project based on template and vars.~n"
+ "~n"
+ "Valid command line options:~n"
+ " template= [var=foo,...]~n", []).
diff --git a/src/rebar_prv_packages.erl b/src/rebar_prv_packages.erl
index 79c1cd2..be51833 100644
--- a/src/rebar_prv_packages.erl
+++ b/src/rebar_prv_packages.erl
@@ -1,9 +1,10 @@
-module(rebar_prv_packages).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
@@ -12,22 +13,26 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar pkgs",
- short_desc = "List available packages.",
- desc = info("List available packages"),
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar pkgs"},
+ {short_desc, "List available packages."},
+ {desc, info("List available packages")},
+ {opts, []}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()}.
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
{Packages, _Graph} = rebar_packages:get_packages(State),
print_packages(Packages),
{ok, State}.
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
+
print_packages(Packages) ->
Keys = lists:keysort(1, dict:fetch_keys(Packages)),
Pkgs = merge(Keys),
diff --git a/src/rebar_prv_release.erl b/src/rebar_prv_release.erl
index 4203c3a..572f909 100644
--- a/src/rebar_prv_release.erl
+++ b/src/rebar_prv_release.erl
@@ -3,10 +3,11 @@
-module(rebar_prv_release).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
@@ -19,17 +20,28 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar release",
- short_desc = "Build release of project.",
- desc = "",
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar release"},
+ {short_desc, "Build release of project."},
+ {desc, ""},
+ {opts, relx:opt_spec_list()}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()} | relx:error().
-do(Config) ->
- relx:main("release"),
- {ok, Config}.
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
+do(State) ->
+ Options = rebar_state:command_args(State),
+ AllOptions = string:join(["release" | Options], " "),
+ case rebar_state:get(State, relx, []) of
+ [] ->
+ relx:main(AllOptions);
+ Config ->
+ relx:main([{config, Config}], AllOptions)
+ end,
+ {ok, State}.
+
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl
index 80f6bcf..24e357b 100644
--- a/src/rebar_prv_shell.erl
+++ b/src/rebar_prv_shell.erl
@@ -28,10 +28,11 @@
-module(rebar_prv_shell).
-author("Kresten Krab Thorup <krab@trifork.com>").
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
@@ -44,21 +45,25 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar shell",
- short_desc = "Run shell with project apps and deps in path.",
- desc = info(),
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar shell"},
+ {short_desc, "Run shell with project apps and deps in path."},
+ {desc, info()},
+ {opts, []}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()} | relx:error().
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(Config) ->
shell(),
{ok, Config}.
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
+
%% NOTE:
%% this is an attempt to replicate `erl -pa ./ebin -pa deps/*/ebin`. it is
%% mostly successful but does stop and then restart the user io system to get
diff --git a/src/rebar_prv_tar.erl b/src/rebar_prv_tar.erl
index 7f5ab4f..04a1b33 100644
--- a/src/rebar_prv_tar.erl
+++ b/src/rebar_prv_tar.erl
@@ -3,10 +3,11 @@
-module(rebar_prv_tar).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
@@ -19,17 +20,26 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar tar",
- short_desc = "Tar archive of release built of project.",
- desc = "",
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar tar"},
+ {short_desc, "Tar archive of release built of project."},
+ {desc, ""},
+ {opts, []}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()} | relx:error().
-do(Config) ->
- relx:main("release tar"),
- {ok, Config}.
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
+do(State) ->
+ case rebar_state:get(State, relx, []) of
+ [] ->
+ relx:main(["release tar"]);
+ Config ->
+ relx:main([{config, Config}], ["release tar"])
+ end,
+ {ok, State}.
+
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
diff --git a/src/rebar_prv_test_deps.erl b/src/rebar_prv_test_deps.erl
new file mode 100644
index 0000000..081b210
--- /dev/null
+++ b/src/rebar_prv_test_deps.erl
@@ -0,0 +1,63 @@
+-module(rebar_prv_test_deps).
+
+-behaviour(provider).
+
+-export([init/1,
+ do/1,
+ format_error/2]).
+
+-include("rebar.hrl").
+
+-define(PROVIDER, test_deps).
+-define(DEPS, [install_deps]).
+
+%% ===================================================================
+%% Public API
+%% ===================================================================
+
+-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
+init(State) ->
+ Providers = rebar_state:providers(State),
+ CompileProvider = providers:get_provider(compile, Providers),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, true},
+ {deps, ?DEPS},
+ {hooks, {[], [CompileProvider]}},
+ {example, undefined},
+ {short_desc, "Install dependencies needed only for testing."},
+ {desc, ""},
+ {opts, []}])),
+ {ok, State1}.
+
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
+do(State) ->
+ ProjectApps = rebar_state:project_apps(State),
+ TestDeps = rebar_state:get(State, test_deps, []),
+ Names = [ec_cnv:to_binary(element(1, Dep)) || Dep <- TestDeps],
+ ProjectApps1 = [rebar_app_info:deps(A, Names) || A <- ProjectApps],
+
+ {ok, State1} = rebar_prv_install_deps:handle_deps(State, TestDeps),
+ AllDeps = rebar_state:get(State1, all_deps, []),
+
+ case rebar_topo:sort_apps(ProjectApps1++AllDeps) of
+ {ok, Sort} ->
+ _ToBuild = lists:dropwhile(fun rebar_app_info:valid/1, Sort),
+ %% lists:foreach(fun(AppInfo) ->
+ %% AppDir = rebar_app_info:dir(AppInfo),
+ %% C = rebar_config:consult(AppDir),
+ %% S = rebar_state:new(State1, C, AppDir),
+ %% rebar_prv_compile:build(S, AppInfo)
+ %% end, ToBuild),
+ {ok, State1};
+ {error, Error} ->
+ {error, Error}
+ end.
+
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
+
+%% ===================================================================
+%% Internal functions
+%% ===================================================================
diff --git a/src/rebar_prv_update.erl b/src/rebar_prv_update.erl
index e19041a..0d388c8 100644
--- a/src/rebar_prv_update.erl
+++ b/src/rebar_prv_update.erl
@@ -3,10 +3,11 @@
-module(rebar_prv_update).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
@@ -19,41 +20,35 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar update cowboy",
- short_desc = "Update package index or individual dependency.",
- desc = "",
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar update"},
+ {short_desc, "Update package index."},
+ {desc, ""},
+ {opts, []}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()} | relx:error().
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
- case rebar_state:command_args(State) of
- [Name] ->
- ?ERROR("NOT IMPLEMENTED: Updating ~s~n", [Name]),
- {ok, State};
- [] ->
- ?INFO("Updating package index...~n", []),
- Url = url(State),
- %{ok, [Home]} = init:get_argument(home),
- ec_file:mkdir_p(filename:join([os:getenv("HOME"), ".rebar"])),
- PackagesFile = filename:join([os:getenv("HOME"), ".rebar", "packages"]),
- {ok, RequestId} = httpc:request(get, {Url, []}, [], [{stream, PackagesFile}, {sync, false}]),
- wait(RequestId, State)
- end.
-
-wait(RequestId, State) ->
- receive
- {http, {RequestId, saved_to_file}} ->
- {ok, State}
- after
- 500 ->
- io:format("."),
- wait(RequestId, State)
- end.
+ ?INFO("Updating package index...~n", []),
+ try
+ Url = url(State),
+ %{ok, [Home]} = init:get_argument(home),
+ ec_file:mkdir_p(filename:join([os:getenv("HOME"), ".rebar"])),
+ PackagesFile = filename:join([os:getenv("HOME"), ".rebar", "packages"]),
+ {ok, _RequestId} = httpc:request(get, {Url, []}, [], [{stream, PackagesFile}
+ ,{sync, true}])
+ catch
+ _:_ ->
+ {error, io_lib:format("Failed to write package index.~n", [])}
+ end,
+ {ok, State}.
+
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
url(State) ->
SystemArch = erlang:system_info(system_architecture),
diff --git a/src/rebar_prv_upgrade.erl b/src/rebar_prv_upgrade.erl
new file mode 100644
index 0000000..1668e1c
--- /dev/null
+++ b/src/rebar_prv_upgrade.erl
@@ -0,0 +1,55 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+
+-module(rebar_prv_upgrade).
+
+-behaviour(provider).
+
+-export([init/1,
+ do/1,
+ format_error/2]).
+
+-include("rebar.hrl").
+
+-define(PROVIDER, upgrade).
+-define(DEPS, [lock]).
+
+%% ===================================================================
+%% Public API
+%% ===================================================================
+
+-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
+init(State) ->
+ State1 =
+ rebar_state:add_provider(State,
+ providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar upgrade cowboy"},
+ {short_desc, "Upgrade dependency."},
+ {desc, ""},
+ {opts, [
+ {package, undefined, undefined, string, "Package to upgrade."}
+ ]}])),
+ {ok, State1}.
+
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
+do(State) ->
+ {Args, _} = rebar_state:command_parsed_args(State),
+ Name = proplists:get_value(package, Args),
+ ?INFO("Updating ~s~n", [Name]),
+ Locks = rebar_state:get(State, locks, []),
+ case lists:keyfind(ec_cnv:to_binary(Name), 1, Locks) of
+ {_, _, _, Level} ->
+ Deps = rebar_state:get(State, deps),
+ Dep = lists:keyfind(list_to_atom(Name), 1, Deps),
+ rebar_prv_install_deps:handle_deps(State, [Dep], {true, ec_cnv:to_binary(Name), Level}),
+ {ok, State};
+ _ ->
+ {error, io_lib:format("No such dependency ~s~n", [Name])}
+ end.
+
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
diff --git a/src/rebar_prv_version.erl b/src/rebar_prv_version.erl
index 9197438..1e907d1 100644
--- a/src/rebar_prv_version.erl
+++ b/src/rebar_prv_version.erl
@@ -3,10 +3,11 @@
-module(rebar_prv_version).
--behaviour(rebar_provider).
+-behaviour(provider).
-export([init/1,
- do/1]).
+ do/1,
+ format_error/2]).
-include("rebar.hrl").
@@ -19,18 +20,22 @@
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
- State1 = rebar_state:add_provider(State, #provider{name = ?PROVIDER,
- provider_impl = ?MODULE,
- bare = false,
- deps = ?DEPS,
- example = "rebar version",
- short_desc = "Print version for rebar and current Erlang.",
- desc = "",
- opts = []}),
+ State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
+ {module, ?MODULE},
+ {bare, false},
+ {deps, ?DEPS},
+ {example, "rebar version"},
+ {short_desc, "Print version for rebar and current Erlang."},
+ {desc, ""},
+ {opts, []}])),
{ok, State1}.
--spec do(rebar_state:t()) -> {ok, rebar_state:t()} | relx:error().
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
rebar3:version(),
{ok, State}.
+
+-spec format_error(any(), rebar_state:t()) -> {iolist(), rebar_state:t()}.
+format_error(Reason, State) ->
+ {io_lib:format("~p", [Reason]), State}.
diff --git a/src/rebar_state.erl b/src/rebar_state.erl
index 706c528..f39251d 100644
--- a/src/rebar_state.erl
+++ b/src/rebar_state.erl
@@ -3,49 +3,39 @@
-export([new/0, new/1, new/2, new/3,
get/2, get/3, set/3,
command_args/1, command_args/2,
+ command_parsed_args/1, command_parsed_args/2,
dir/1, dir/2,
- set_skip_dir/2, is_skip_dir/2, reset_skip_dirs/1,
create_logic_providers/2,
project_apps/1, project_apps/2,
deps_names/1,
- binary_deps/1, binary_deps/2,
+ pkg_deps/1, pkg_deps/2,
src_deps/1, src_deps/2,
+ src_apps/1, src_apps/2,
prepend_hook/3, append_hook/3, hooks/2,
providers/1, providers/2, add_provider/2]).
-include("rebar.hrl").
--ifdef(namespaced_types).
-%% dict:dict() exists starting from Erlang 17.
--type rebar_dict() :: dict:dict(term(), term()).
--else.
-%% dict() has been obsoleted in Erlang 17 and deprecated in 18.
--type rebar_dict() :: dict().
--endif.
+-record(state_t, {dir :: file:name(),
+ opts = [],
--record(state_t, {dir :: file:filename(),
- opts = [] :: list(),
- local_opts = [] :: list(),
- config = new_globals() :: rebar_dict(),
+ command_args = [],
+ command_parsed_args = [],
- envs = new_env() :: rebar_dict(),
- command_args = [] :: list(),
+ src_deps = [],
+ src_apps = [],
+ pkg_deps = [] :: [rlx_depsolver:constraint()],
+ project_apps = [],
- src_deps = ordsets:new() :: ordsets:ordset(rebar_app_info:t()),
- binary_deps = [],
- project_apps = ordsets:new() :: ordsets:ordset(rebar_app_info:t()),
-
- providers = [],
- hooks = [],
- skip_dirs = new_skip_dirs() :: rebar_dict() }).
+ providers = []}).
-export_type([t/0]).
--opaque t() :: #state_t{}.
+-type t() :: record(state_t).
-spec new() -> t().
new() ->
@@ -64,9 +54,9 @@ new(ParentState=#state_t{}, Config) ->
-spec new(t(), list(), file:name()) -> t().
new(ParentState, Config, Dir) ->
- _Opts = ParentState#state_t.opts,
+ Opts = ParentState#state_t.opts,
LocalOpts = case rebar_config:consult_file(?LOCK_FILE) of
- {ok, [D]} ->
+ [D] ->
[{locks, D} | Config];
_ ->
Config
@@ -74,7 +64,7 @@ new(ParentState, Config, Dir) ->
ProviderModules = [],
create_logic_providers(ProviderModules, ParentState#state_t{dir=Dir
- ,opts=LocalOpts}).
+ ,opts=lists:umerge(LocalOpts, Opts)}).
get(State, Key) ->
proplists:get_value(Key, State#state_t.opts).
@@ -82,33 +72,23 @@ get(State, Key) ->
get(State, Key, Default) ->
proplists:get_value(Key, State#state_t.opts, Default).
+-spec set(t(), any(), any()) -> t().
set(State, Key, Value) ->
Opts = proplists:delete(Key, State#state_t.opts),
State#state_t { opts = [{Key, Value} | Opts] }.
-set_skip_dir(State, Dir) ->
- OldSkipDirs = State#state_t.skip_dirs,
- NewSkipDirs = case is_skip_dir(State, Dir) of
- false ->
- ?DEBUG("Adding skip dir: ~s\n", [Dir]),
- dict:store(Dir, true, OldSkipDirs);
- true ->
- OldSkipDirs
- end,
- State#state_t{skip_dirs = NewSkipDirs}.
-
-is_skip_dir(State, Dir) ->
- dict:is_key(Dir, State#state_t.skip_dirs).
-
-reset_skip_dirs(State) ->
- State#state_t{skip_dirs = new_skip_dirs()}.
-
command_args(#state_t{command_args=CmdArgs}) ->
CmdArgs.
command_args(State, CmdArgs) ->
State#state_t{command_args=CmdArgs}.
+command_parsed_args(#state_t{command_parsed_args=CmdArgs}) ->
+ CmdArgs.
+
+command_parsed_args(State, CmdArgs) ->
+ State#state_t{command_parsed_args=CmdArgs}.
+
dir(#state_t{dir=Dir}) ->
Dir.
@@ -123,13 +103,14 @@ deps_names(State) ->
ec_cnv:to_binary(Dep)
end, Deps).
-binary_deps(#state_t{binary_deps=BinaryDeps}) ->
- BinaryDeps.
+-spec pkg_deps(t()) -> [rlx_depsolver:constraint()].
+pkg_deps(#state_t{pkg_deps=PkgDeps}) ->
+ PkgDeps.
-binary_deps(State=#state_t{binary_deps=BinaryDeps}, NewBinaryDeps) when is_list(BinaryDeps) ->
- State#state_t{binary_deps=NewBinaryDeps};
-binary_deps(State=#state_t{binary_deps=BinaryDeps}, BinaryDep) ->
- State#state_t{binary_deps=[BinaryDep | BinaryDeps]}.
+pkg_deps(State=#state_t{pkg_deps=PkgDeps}, NewPkgDeps) when is_list(PkgDeps) ->
+ State#state_t{pkg_deps=NewPkgDeps};
+pkg_deps(State=#state_t{pkg_deps=PkgDeps}, PkgDep) ->
+ State#state_t{pkg_deps=[PkgDep | PkgDeps]}.
src_deps(#state_t{src_deps=SrcDeps}) ->
SrcDeps.
@@ -137,7 +118,19 @@ src_deps(#state_t{src_deps=SrcDeps}) ->
src_deps(State=#state_t{src_deps=SrcDeps}, NewSrcDeps) when is_list(SrcDeps) ->
State#state_t{src_deps=NewSrcDeps};
src_deps(State=#state_t{src_deps=SrcDeps}, SrcDep) ->
- State#state_t{src_deps=[SrcDep | SrcDeps]}.
+ Name = rebar_app_info:name(SrcDep),
+ NewSrcDeps = lists:keystore(Name, 2, SrcDeps, SrcDep),
+ State#state_t{src_deps=NewSrcDeps}.
+
+src_apps(#state_t{src_apps=SrcApps}) ->
+ SrcApps.
+
+src_apps(State=#state_t{src_apps=_SrcApps}, NewSrcApps) when is_list(NewSrcApps) ->
+ State#state_t{src_apps=NewSrcApps};
+src_apps(State=#state_t{src_apps=SrcApps}, NewSrcApp) ->
+ Name = rebar_app_info:name(NewSrcApp),
+ NewSrcApps = lists:keystore(Name, 2, SrcApps, NewSrcApp),
+ State#state_t{src_apps=NewSrcApps}.
project_apps(#state_t{project_apps=Apps}) ->
Apps.
@@ -153,32 +146,44 @@ providers(#state_t{providers=Providers}) ->
providers(State, NewProviders) ->
State#state_t{providers=NewProviders}.
+-spec add_provider(t(), providers:t()) -> t().
add_provider(State=#state_t{providers=Providers}, Provider) ->
State#state_t{providers=[Provider | Providers]}.
create_logic_providers(ProviderModules, State0) ->
lists:foldl(fun(ProviderMod, Acc) ->
- {ok, State1} = rebar_provider:new(ProviderMod, Acc),
- State1
+ case providers:new(ProviderMod, Acc) of
+ {error, Reason} ->
+ ?ERROR(Reason++"~n", []),
+ Acc;
+ {ok, State1} ->
+ State1
+ end
end, State0, ProviderModules).
-prepend_hook(State=#state_t{hooks=Hooks}, Target, Hook) ->
- {PreHooks, PostHooks} = proplists:get_value(Target, Hooks, {[], []}),
- State#state_t{hooks=[{Target, {[Hook | PreHooks], PostHooks}} | proplists:delete(Target, Hooks)]}.
+prepend_hook(State=#state_t{providers=Providers}, Target, Hook) ->
+ State#state_t{providers=add_hook(pre, Providers, Target, Hook)}.
-append_hook(State=#state_t{hooks=Hooks}, Target, Hook) ->
- {PreHooks, PostHooks} = proplists:get_value(Target, Hooks, {[], []}),
- State#state_t{hooks=[{Target, {PreHooks, [Hook | PostHooks]}} | proplists:delete(Target, Hooks)]}.
+append_hook(State=#state_t{providers=Providers}, Target, Hook) ->
+ State#state_t{providers=add_hook(post, Providers, Target, Hook)}.
-hooks(#state_t{hooks=Hooks}, Target) ->
- proplists:get_value(Target, Hooks, {[], []}).
+-spec hooks(t(), atom()) -> {[providers:t()], [providers:t()]}.
+hooks(_State=#state_t{providers=Providers}, Target) ->
+ Provider = providers:get_provider(Target, Providers),
+ providers:hooks(Provider).
%% ===================================================================
%% Internal functions
%% ===================================================================
-new_globals() -> dict:new().
-
-new_env() -> dict:new().
-
-new_skip_dirs() -> dict:new().
+add_hook(Which, Providers, Target, Hook) ->
+ Provider = providers:get_provider(Target, Providers),
+ Hooks = providers:hooks(Provider),
+ NewHooks = add_hook(Which, Hooks, Hook),
+ NewProvider = providers:hooks(Provider, NewHooks),
+ [NewProvider | lists:delete(Provider, Providers)].
+
+add_hook(pre, {PreHooks, PostHooks}, Hook) ->
+ {[Hook | PreHooks], PostHooks};
+add_hook(post, {PreHooks, PostHooks}, Hook) ->
+ {PreHooks, [Hook | PostHooks]}.
diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl
index a795b66..b30c517 100644
--- a/src/rebar_templater.erl
+++ b/src/rebar_templater.erl
@@ -47,6 +47,8 @@ new(app, DirName, State) ->
create1(State, DirName, "otp_app");
new(lib, DirName, State) ->
create1(State, DirName, "otp_lib");
+new(plugin, DirName, State) ->
+ create1(State, DirName, "plugin");
new(rel, DirName, State) ->
create1(State, DirName, "otp_rel").
@@ -78,7 +80,7 @@ create(State) ->
resolve_variables([], Dict) ->
Dict;
resolve_variables([{Key, Value0} | Rest], Dict) when is_list(Value0) ->
- Value = render(list_to_binary(Value0), Dict),
+ Value = render(Value0, Dict),
resolve_variables(Rest, dict:store(Key, Value, Dict));
resolve_variables([{Key, {list, Dicts}} | Rest], Dict) when is_list(Dicts) ->
%% just un-tag it so erlydtl can use it
@@ -376,7 +378,7 @@ execute_template(Files, [{'case', Variable, Values, Instructions} | Rest], Templ
ExistingFiles);
execute_template(Files, [{template, Input, Output} | Rest], TemplateType,
TemplateName, Context, Force, ExistingFiles) ->
- InputName = filename:join(filename:dirname(TemplateName), Input),
+ _InputName = filename:join(filename:dirname(TemplateName), Input),
%File = load_file(Files, TemplateType, InputName),
OutputTemplateName = make_template_name("rebar_output_template", Output),
{ok, OutputTemplateName1} = erlydtl:compile_template(Output, OutputTemplateName, ?ERLYDTL_COMPILE_OPTS),
diff --git a/src/rebar_topo.erl b/src/rebar_topo.erl
index 87ee234..de3351a 100644
--- a/src/rebar_topo.erl
+++ b/src/rebar_topo.erl
@@ -54,20 +54,18 @@
%% applications. This implies that you have already done the
%% constraint solve before you pass the list of apps here to be
%% sorted.
--spec sort_apps([rebar_app_info:t()]) ->
- {ok, [rebar_app_info:t()]} |
- relx:error().
+-spec sort_apps([rebar_app_info:t()]) -> {ok, [rebar_app_info:t()]} | {error, any()}.
sort_apps(Apps) ->
Pairs = apps_to_pairs(Apps),
case sort(Pairs) of
{ok, Names} ->
{ok, names_to_apps(Names, Apps)};
E ->
- E
+ {error, E}
end.
%% @doc Do a topological sort on the list of pairs.
--spec sort([pair()]) -> {ok, [atom()]} | relx:error().
+-spec sort([pair()]) -> {ok, [atom()]} | {error, any()}.
sort(Pairs) ->
iterate(Pairs, [], all(Pairs)).
@@ -78,9 +76,9 @@ format_error({cycle, Pairs}) ->
"before we can continue:\n",
case Pairs of
[{P1, P2}] ->
- [rebar_util:indent(2), erlang:atom_to_list(P2), "->", erlang:atom_to_list(P1)];
+ [rebar_utils:indent(2), erlang:atom_to_list(P2), "->", erlang:atom_to_list(P1)];
[{P1, P2} | Rest] ->
- [rebar_util:indent(2), erlang:atom_to_list(P2), "->", erlang:atom_to_list(P1),
+ [rebar_utils:indent(2), erlang:atom_to_list(P2), "->", erlang:atom_to_list(P1),
[["-> ", erlang:atom_to_list(PP2), " -> ", erlang:atom_to_list(PP1)] || {PP1, PP2} <- Rest]];
[] ->
[]
@@ -91,12 +89,12 @@ format_error({cycle, Pairs}) ->
%%====================================================================
-spec names_to_apps([atom()], [rebar_app_info:t()]) -> [rebar_app_info:t()].
names_to_apps(Names, Apps) ->
- [element(2, App) || App <- [find_app_by_name(Name, Apps) || Name <- Names], App =/= error].
+ [element(2, App) || App <- [find_app_by_name(Name, Apps) || Name <- Names], App =/= error].
-spec find_app_by_name(atom(), [rebar_app_info:t()]) -> {ok, rebar_app_info:t()} | error.
find_app_by_name(Name, Apps) ->
ec_lists:find(fun(App) ->
- rebar_app_info:name(App) =:= Name
+ ec_cnv:to_atom(rebar_app_info:name(App)) =:= ec_cnv:to_atom(Name)
end, Apps).
-spec apps_to_pairs([rebar_app_info:t()]) -> [pair()].
@@ -105,20 +103,20 @@ apps_to_pairs(Apps) ->
-spec app_to_pairs(rebar_app_info:t()) -> [pair()].
app_to_pairs(App) ->
- [{DepApp, rebar_app_info:name(App)} ||
+ [{ec_cnv:to_atom(DepApp), ec_cnv:to_atom(rebar_app_info:name(App))} ||
DepApp <-
rebar_app_info:deps(App)].
%% @doc Iterate over the system. @private
-spec iterate([pair()], [name()], [name()]) ->
- {ok, [name()]} | relx:error().
+ {ok, [name()]} | {error, iolist()}.
iterate([], L, All) ->
{ok, remove_duplicates(L ++ subtract(All, L))};
iterate(Pairs, L, All) ->
case subtract(lhs(Pairs), rhs(Pairs)) of
[] ->
- ?ERROR(format_error({cycle, Pairs}), []);
+ {error, format_error({cycle, Pairs})};
Lhs ->
iterate(remove_pairs(Lhs, Pairs), L ++ Lhs, All)
end.
@@ -188,29 +186,27 @@ topo_2_test() ->
topo_pairs_cycle_test() ->
Pairs = [{app2, app1}, {app1, app2}, {stdlib, app1}],
- ?assertMatch({error, {_, {cycle, [{app2, app1}, {app1, app2}]}}},
- sort(Pairs)).
+ ?assertMatch({error, _}, sort(Pairs)).
topo_apps_cycle_test() ->
- {ok, App1} = rebar_app_info:new(app1, "0.1", "/no-dir", [app2], [stdlib]),
- {ok, App2} = rebar_app_info:new(app2, "0.1", "/no-dir", [app1], []),
+ {ok, App1} = rebar_app_info:new(app1, "0.1", "/no-dir", [app2]),
+ {ok, App2} = rebar_app_info:new(app2, "0.1", "/no-dir", [app1]),
Apps = [App1, App2],
- ?assertMatch({error, {_, {cycle, [{app2,app1},{app1,app2}]}}},
- sort_apps(Apps)).
+ ?assertMatch({error, _}, sort_apps(Apps)).
topo_apps_good_test() ->
Apps = [App ||
{ok, App} <-
- [rebar_app_info:new(app1, "0.1", "/no-dir", [app2, zapp1], [stdlib, kernel]),
- rebar_app_info:new(app2, "0.1", "/no-dir", [app3], []),
- rebar_app_info:new(app3, "0.1", "/no-dir", [kernel], []),
- rebar_app_info:new(zapp1, "0.1", "/no-dir", [app2,app3,zapp2], []),
- rebar_app_info:new(stdlib, "0.1", "/no-dir", [], []),
- rebar_app_info:new(kernel, "0.1", "/no-dir", [], []),
- rebar_app_info:new(zapp2, "0.1", "/no-dir", [], [])]],
+ [rebar_app_info:new(app1, "0.1", "/no-dir", [app2, zapp1]),
+ rebar_app_info:new(app2, "0.1", "/no-dir", [app3]),
+ rebar_app_info:new(app3, "0.1", "/no-dir", [kernel]),
+ rebar_app_info:new(zapp1, "0.1", "/no-dir", [app2,app3,zapp2]),
+ rebar_app_info:new(stdlib, "0.1", "/no-dir", []),
+ rebar_app_info:new(kernel, "0.1", "/no-dir", []),
+ rebar_app_info:new(zapp2, "0.1", "/no-dir", [])]],
{ok, Sorted} = sort_apps(Apps),
?assertMatch([stdlib, kernel, zapp2,
app3, app2, zapp1, app1],
- [rebar_app_info:name(App) || App <- Sorted]).
+ [ec_cnv:to_atom(rebar_app_info:name(App)) || App <- Sorted]).
-endif.
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index b83c03e..87387be 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -30,42 +30,27 @@
filtermap/2,
get_cwd/0,
is_arch/1,
- get_arch/0,
- wordsize/0,
sh/2,
sh_send/3,
+ abort/0,
+ abort/2,
+ escript_foldl/3,
find_files/2,
find_files/3,
- now_str/0,
ensure_dir/1,
beam_to_mod/1,
beams/1,
- erl_to_mod/1,
- abort/0,
- abort/2,
- escript_foldl/3,
find_executable/1,
- prop_check/3,
expand_code_path/0,
- expand_env_variable/3,
vcs_vsn/3,
deprecated/3,
deprecated/4,
- get_deprecated_global/4,
- get_deprecated_global/5,
- get_experimental_global/3,
- get_experimental_local/3,
- get_deprecated_list/4,
- get_deprecated_list/5,
- get_deprecated_local/4,
- get_deprecated_local/5,
delayed_halt/1,
erl_opts/1,
src_dirs/1,
ebin_dir/0,
processing_base_dir/1,
processing_base_dir/2,
- patch_env/2,
indent/1]).
%% for internal use only
@@ -177,11 +162,6 @@ find_files(Dir, Regex, Recursive) ->
filelib:fold_files(Dir, Regex, Recursive,
fun(F, Acc) -> [F | Acc] end, []).
-now_str() ->
- {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:local_time(),
- lists:flatten(io_lib:format("~4b/~2..0b/~2..0b ~2..0b:~2..0b:~2..0b",
- [Year, Month, Day, Hour, Minute, Second])).
-
%% TODO: filelib:ensure_dir/1 corrected in R13B04. Remove when we drop
%% support for OTP releases older than R13B04.
ensure_dir(Path) ->
@@ -194,27 +174,6 @@ ensure_dir(Path) ->
Error
end.
--spec abort() -> no_return().
-abort() ->
- throw(rebar_abort).
-
--spec abort(string(), [term()]) -> no_return().
-abort(String, Args) ->
- ?ERROR(String, Args),
- abort().
-
-%% TODO: Rename emulate_escript_foldl to escript_foldl and remove
-%% this function when the time is right. escript:foldl/3 was an
-%% undocumented exported fun and has been removed in R14.
-escript_foldl(Fun, Acc, File) ->
- {module, zip} = code:ensure_loaded(zip),
- case erlang:function_exported(zip, foldl, 3) of
- true ->
- emulate_escript_foldl(Fun, Acc, File);
- false ->
- escript:foldl(Fun, Acc, File)
- end.
-
find_executable(Name) ->
case os:find_executable(Name) of
false -> false;
@@ -222,10 +181,6 @@ find_executable(Name) ->
"\"" ++ filename:nativename(Path) ++ "\""
end.
-%% Helper function for checking values and aborting when needed
-prop_check(true, _, _) -> true;
-prop_check(false, Msg, Args) -> ?ABORT(Msg, Args).
-
%% Convert all the entries in the code path to absolute paths.
expand_code_path() ->
CodePath = lists:foldl(fun(Path, Acc) ->
@@ -233,25 +188,6 @@ expand_code_path() ->
end, [], code:get_path()),
code:set_path(lists:reverse(CodePath)).
-%%
-%% Given env. variable FOO we want to expand all references to
-%% it in InStr. References can have two forms: $FOO and ${FOO}
-%% The end of form $FOO is delimited with whitespace or eol
-%%
-expand_env_variable(InStr, VarName, RawVarValue) ->
- case string:chr(InStr, $$) of
- 0 ->
- %% No variables to expand
- InStr;
- _ ->
- ReOpts = [global, unicode, {return, list}],
- VarValue = re:replace(RawVarValue, "\\\\", "\\\\\\\\", ReOpts),
- %% Use a regex to match/replace:
- %% Given variable "FOO": match $FOO\s | $FOOeol | ${FOO}
- RegEx = io_lib:format("\\\$(~s(\\s|$)|{~s})", [VarName, VarName]),
- re:replace(InStr, RegEx, [VarValue, "\\2"], ReOpts)
- end.
-
vcs_vsn(Config, Vsn, Dir) ->
Key = {Vsn, Dir},
Cache = rebar_state:get(Config, vsn_cache, dict:new()),
@@ -265,33 +201,6 @@ vcs_vsn(Config, Vsn, Dir) ->
{Config, VsnString}
end.
-get_deprecated_global(Config, OldOpt, NewOpt, When) ->
- get_deprecated_global(Config, OldOpt, NewOpt, undefined, When).
-
-get_deprecated_global(Config, OldOpt, NewOpt, Default, When) ->
- get_deprecated_3(fun rebar_state:get/3,
- Config, OldOpt, NewOpt, Default, When).
-
-get_experimental_global(Config, Opt, Default) ->
- get_experimental_3(fun rebar_state:get/3, Config, Opt, Default).
-
-get_experimental_local(Config, Opt, Default) ->
- get_experimental_3(fun rebar_state:get/3, Config, Opt, Default).
-
-get_deprecated_list(Config, OldOpt, NewOpt, When) ->
- get_deprecated_list(Config, OldOpt, NewOpt, undefined, When).
-
-get_deprecated_list(Config, OldOpt, NewOpt, Default, When) ->
- get_deprecated_3(fun rebar_state:get_list/3,
- Config, OldOpt, NewOpt, Default, When).
-
-get_deprecated_local(Config, OldOpt, NewOpt, When) ->
- get_deprecated_local(Config, OldOpt, NewOpt, undefined, When).
-
-get_deprecated_local(Config, OldOpt, NewOpt, Default, When) ->
- get_deprecated_3(fun rebar_state:get/3,
- Config, OldOpt, NewOpt, Default, When).
-
deprecated(Old, New, Opts, When) when is_list(Opts) ->
case lists:member(Old, Opts) of
true ->
@@ -337,7 +246,7 @@ delayed_halt(Code) ->
end.
%% @doc Return list of erl_opts
--spec erl_opts(rebar_state:config()) -> list().
+-spec erl_opts(rebar_state:t()) -> list().
erl_opts(Config) ->
RawErlOpts = filter_defines(rebar_state:get(Config, erl_opts, []), []),
Defines = [{d, list_to_atom(D)} ||
@@ -367,25 +276,6 @@ processing_base_dir(State, Dir) ->
AbsDir = filename:absname(Dir),
AbsDir =:= rebar_state:get(State, base_dir).
-%% @doc Returns the list of environment variables including 'REBAR' which
-%% points to the rebar executable used to execute the currently running
-%% command. The environment is not modified if rebar was invoked
-%% programmatically.
--spec patch_env(rebar_state:config(), [{string(), string()}])
- -> [{string(), string()}].
-patch_env(Config, []) ->
- %% If we reached an empty list, the env did not contain the REBAR variable.
- case rebar_state:get(Config, escript, "") of
- "" -> % rebar was invoked programmatically
- [];
- Path ->
- [{"REBAR", Path}]
- end;
-patch_env(_Config, [{"REBAR", _} | _]=All) ->
- All;
-patch_env(Config, [E | Rest]) ->
- [E | patch_env(Config, Rest)].
-
%% ====================================================================
%% Internal functions
%% ====================================================================
@@ -426,30 +316,6 @@ otp_release1(Rel) ->
binary:bin_to_list(Vsn, {0, Size - 1})
end.
-get_deprecated_3(Get, Config, OldOpt, NewOpt, Default, When) ->
- case Get(Config, NewOpt, Default) of
- Default ->
- case Get(Config, OldOpt, Default) of
- Default ->
- Default;
- Old ->
- deprecated(OldOpt, NewOpt, When),
- Old
- end;
- New ->
- New
- end.
-
-get_experimental_3(Get, Config, Opt, Default) ->
- Val = Get(Config, Opt, Default),
- case Val of
- Default ->
- Default;
- Val ->
- ?CONSOLE("NOTICE: Using experimental option '~p'~n", [Opt]),
- Val
- end.
-
%% We do the shell variable substitution ourselves on Windows and hope that the
%% command doesn't use any other shell magic.
patch_on_windows(Cmd, Env) ->
@@ -466,6 +332,25 @@ patch_on_windows(Cmd, Env) ->
Cmd
end.
+%%
+%% Given env. variable FOO we want to expand all references to
+%% it in InStr. References can have two forms: $FOO and ${FOO}
+%% The end of form $FOO is delimited with whitespace or eol
+%%
+expand_env_variable(InStr, VarName, RawVarValue) ->
+ case string:chr(InStr, $$) of
+ 0 ->
+ %% No variables to expand
+ InStr;
+ _ ->
+ ReOpts = [global, unicode, {return, list}],
+ VarValue = re:replace(RawVarValue, "\\\\", "\\\\\\\\", ReOpts),
+ %% Use a regex to match/replace:
+ %% Given variable "FOO": match $FOO\s | $FOOeol | ${FOO}
+ RegEx = io_lib:format("\\\$(~s(\\s|$)|{~s})", [VarName, VarName]),
+ re:replace(InStr, RegEx, [VarValue, "\\2"], ReOpts)
+ end.
+
expand_sh_flag(return_on_error) ->
{error_handler,
fun(_Command, Err) ->
@@ -521,14 +406,19 @@ sh_loop(Port, Fun, Acc) ->
beam_to_mod(Filename) ->
list_to_atom(filename:basename(Filename, ".beam")).
-erl_to_mod(Filename) ->
- list_to_atom(filename:rootname(filename:basename(Filename))).
-
beams(Dir) ->
filelib:fold_files(Dir, ".*\.beam\$", true,
fun(F, Acc) -> [F | Acc] end, []).
-emulate_escript_foldl(Fun, Acc, File) ->
+-spec abort() -> no_return().
+abort() ->
+ throw(rebar_abort).
+-spec abort(string(), [term()]) -> no_return().
+abort(String, Args) ->
+ ?ERROR(String, Args),
+ abort().
+
+escript_foldl(Fun, Acc, File) ->
case escript:extract(File, [compile_source]) of
{ok, [_Shebang, _Comment, _EmuArgs, Body]} ->
case Body of