summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rebar.config18
-rw-r--r--src/rebar.hrl10
-rw-r--r--src/rebar3.erl9
-rw-r--r--src/rebar_core.erl29
-rw-r--r--src/rebar_digraph.erl12
-rw-r--r--src/rebar_hooks.erl2
-rw-r--r--src/rebar_prv_common_test.erl8
-rw-r--r--src/rebar_prv_install_deps.erl82
-rw-r--r--src/rebar_prv_lock.erl5
-rw-r--r--src/rebar_prv_release.erl10
-rw-r--r--src/rebar_prv_tar.erl10
-rw-r--r--src/rebar_prv_test_deps.erl61
-rw-r--r--src/rebar_state.erl92
-rw-r--r--src/rebar_utils.erl51
14 files changed, 226 insertions, 173 deletions
diff --git a/rebar.config b/rebar.config
index 7bc15ca..2c51f73 100644
--- a/rebar.config
+++ b/rebar.config
@@ -10,12 +10,16 @@
{escript_top_level_app, rebar}.
{escript_name, rebar3}.
-{erl_opts,
- [{platform_define, "R14", no_callback_support},
- {platform_define, "^[0-9]+", namespaced_types},
- {platform_define, "^R1[4|5]", deprecated_crypto},
- debug_info,
- warnings_as_errors]}.
+{profiles, [{dev, [
+ {erl_opts,
+ [{platform_define, "R14", no_callback_support},
+ {platform_define, "^[0-9]+", namespaced_types},
+ {platform_define, "^R1[4|5]", deprecated_crypto},
+ debug_info,
+ warnings_as_errors]}
+ ]}
+ ]
+}.
%% Types dict:dict() and digraph:digraph() have been introduced in Erlang 17.
%% At the same time, their counterparts dict() and digraph() are to be
@@ -32,7 +36,7 @@
{branch, "master"}}},
{providers, "",
{git, "https://github.com/tsloughter/providers.git",
- {branch, "format_error1"}}},
+ {branch, "master"}}},
{erlydtl, ".*",
{git, "https://github.com/erlydtl/erlydtl.git",
{tag, "0.9.4"}}},
diff --git a/src/rebar.hrl b/src/rebar.hrl
index 794d738..260e188 100644
--- a/src/rebar.hrl
+++ b/src/rebar.hrl
@@ -13,11 +13,13 @@
-define(FMT(Str, Args), lists:flatten(io_lib:format(Str, Args))).
--define(DEFAULT_BASE_DIR, "").
+-define(DEFAULT_BASE_DIR, "_build").
+-define(DEFAULT_PROFILE_DIR, "default").
-define(DEFAULT_LIB_DIRS, ["_checkouts", "apps", "lib", "."]).
--define(DEFAULT_DEPS_DIR, "_deps").
--define(DEFAULT_PLUGINS_DIR, "_plugins").
--define(DEFAULT_TEST_DEPS_DIR, "_tdeps").
+-define(DEFAULT_DEPS_DIR, "lib").
+-define(DEFAULT_PLUGINS_DIR, "plugins").
+-define(DEFAULT_TEST_DEPS_DIR, "test/lib").
+-define(DEFAULT_RELEASE_DIR, "rel").
-define(DEFAULT_CONFIG_FILE, "rebar.config").
-define(LOCK_FILE, "rebar.lock").
-define(CONFIG_DIR, ".rebar3").
diff --git a/src/rebar3.erl b/src/rebar3.erl
index 40f80d3..5ea62e6 100644
--- a/src/rebar3.erl
+++ b/src/rebar3.erl
@@ -107,12 +107,9 @@ run_aux(State, RawArgs) ->
inets:start(),
%% Process each command, resetting any state between each one
- State2 = case rebar_state:get(State, base_dir, undefined) of
- undefined ->
- rebar_state:set(State, base_dir, filename:absname(rebar_state:dir(State)));
- Dir ->
- rebar_state:set(State, base_dir, filename:absname(Dir))
- end,
+ BaseDir = rebar_utils:base_dir(State),
+ State2 = rebar_state:set(State, base_dir,
+ filename:join(filename:absname(rebar_state:dir(State)), BaseDir)),
{ok, Providers} = application:get_env(rebar, providers),
diff --git a/src/rebar_core.erl b/src/rebar_core.erl
index b2af936..7dacc50 100644
--- a/src/rebar_core.erl
+++ b/src/rebar_core.erl
@@ -40,15 +40,18 @@ process_command(State, Command) ->
not_found ->
{error, io_lib:format("Command ~p not found", [Command])};
CommandProvider ->
+ Profile = providers:profile(CommandProvider),
+ State1 = rebar_state:current_profile(State, Profile),
+ State2 = rebar_state:apply_profile(State1, Profile),
Opts = providers:opts(CommandProvider)++rebar3:global_option_spec_list(),
case Command of
do ->
- do(TargetProviders, State);
+ do(TargetProviders, State2);
_ ->
- case getopt:parse(Opts, rebar_state:command_args(State)) of
+ case getopt:parse(Opts, rebar_state:command_args(State2)) of
{ok, Args} ->
- State2 = rebar_state:command_parsed_args(State, Args),
- do(TargetProviders, State2);
+ State3 = rebar_state:command_parsed_args(State2, Args),
+ do(TargetProviders, State3);
{error, {invalid_option, Option}} ->
{error, io_lib:format("Invalid option ~s on task ~p", [Option, Command])}
end
@@ -58,22 +61,22 @@ process_command(State, Command) ->
-spec do([atom()], rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do([], State) ->
{ok, State};
-do([ProviderName | Rest], State) ->
+do([{ProviderName, Profile} | Rest], State) ->
+ State1 = rebar_state:current_profile(State, Profile),
Provider = providers:get_provider(ProviderName
- ,rebar_state:providers(State)),
- case providers:do(Provider, State) of
- {ok, State1} ->
- do(Rest, State1);
+ ,rebar_state:providers(State1)),
+ case providers:do(Provider, State1) of
+ {ok, State2} ->
+ do(Rest, State2);
{error, Error} ->
{error, Error}
end.
update_code_path(State) ->
true = rebar_utils:expand_code_path(),
- BaseDir = rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR),
- LibDirs = rebar_state:get(State, lib_dirs, ?DEFAULT_LIB_DIRS),
- DepsDir = filename:join(BaseDir, rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR)),
- PluginsDir = filename:join(BaseDir, rebar_state:get(State, plugins_dir, ?DEFAULT_PLUGINS_DIR)),
+ LibDirs = rebar_utils:lib_dirs(State),
+ DepsDir = rebar_utils:deps_dir(State),
+ PluginsDir = rebar_utils:plugins_dir(State),
_UpdatedCodePaths = update_code_path_([DepsDir, PluginsDir | LibDirs]).
diff --git a/src/rebar_digraph.erl b/src/rebar_digraph.erl
index 27bbdd2..bb031cb 100644
--- a/src/rebar_digraph.erl
+++ b/src/rebar_digraph.erl
@@ -32,9 +32,15 @@ add(Graph, {PkgName, Deps}) ->
end,
lists:foreach(fun(DepName) ->
- V3 = case digraph:vertex(Graph, DepName) of
+ case DepName of
+ {Name, _Vsn} ->
+ Name;
+ Name ->
+ Name
+ end,
+ V3 = case digraph:vertex(Graph, Name) of
false ->
- digraph:add_vertex(Graph, DepName);
+ digraph:add_vertex(Graph, Name);
{V2, []} ->
V2
end,
@@ -94,5 +100,5 @@ names_to_apps(Names, Apps) ->
-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) ->
- ec_cnv:to_atom(rebar_app_info:name(App)) =:= ec_cnv:to_atom(Name)
+ binary_to_atom(rebar_app_info:name(App), utf8) =:= binary_to_atom(Name, utf8)
end, Apps).
diff --git a/src/rebar_hooks.erl b/src/rebar_hooks.erl
index 3e6d533..e64b7eb 100644
--- a/src/rebar_hooks.erl
+++ b/src/rebar_hooks.erl
@@ -4,7 +4,7 @@
run_compile_hooks(Dir, Type, Command, State) ->
Hooks = rebar_state:get(State, Type, []),
- Env = [{"REBAR_DEPS_DIR", rebar_prv_install_deps:get_deps_dir(State)}],
+ Env = [{"REBAR_DEPS_DIR", rebar_utils:deps_dir(State)}],
lists:foreach(fun({_, C, _}=Hook) when C =:= Command ->
apply_hook(Dir, Env, Hook);
({C, _}=Hook) when C =:= Command ->
diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl
index 59f5565..d14144f 100644
--- a/src/rebar_prv_common_test.erl
+++ b/src/rebar_prv_common_test.erl
@@ -12,7 +12,7 @@
-include("rebar.hrl").
-define(PROVIDER, ct).
--define(DEPS, [test_deps, compile]).
+-define(DEPS, [{install_deps, default}, compile]).
%% ===================================================================
%% Public API
@@ -27,7 +27,8 @@ init(State) ->
{example, "rebar ct"},
{short_desc, "Run Common Tests"},
{desc, ""},
- {opts, ct_opts(State)}]),
+ {opts, ct_opts(State)},
+ {profile, test}]),
State1 = rebar_state:add_provider(State, Provider),
{ok, State1}.
@@ -36,8 +37,7 @@ do(State) ->
{Opts, _} = rebar_state:command_parsed_args(State),
Opts1 = transform_opts(Opts),
ok = create_dirs(Opts1),
- expand_test_deps(filename:absname(rebar_state:get(State, test_deps_dir,
- ?DEFAULT_TEST_DEPS_DIR))),
+ expand_test_deps(filename:join(rebar_utils:profile_dir(State), ?DEFAULT_DEPS_DIR)),
case ct:run_test(Opts1) of
{_, 0, _} -> {ok, State};
{_, FailedCount, _} -> {error, {?MODULE, {failures_running_tests,
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index 9822b32..7fdddac 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -37,10 +37,6 @@
-export([handle_deps/2,
handle_deps/3]).
-%% for internal use only
--export([get_deps_dir/1]).
--export([get_deps_dir/2]).
-
-define(PROVIDER, install_deps).
-define(DEPS, [app_discovery]).
@@ -67,11 +63,12 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
+ Profile = rebar_state:current_profile(State),
ProjectApps = rebar_state:project_apps(State),
try
{ok, State1} = case rebar_state:get(State, locks, []) of
[] ->
- handle_deps(State, rebar_state:get(State, deps, []));
+ handle_deps(State, rebar_state:get(State, {deps, Profile}, []));
Locks ->
handle_deps(State, Locks)
end,
@@ -94,16 +91,6 @@ do(State) ->
format_error(Reason) ->
io_lib:format("~p", [Reason]).
--spec get_deps_dir(rebar_state:t()) -> file:filename_all().
-get_deps_dir(State) ->
- BaseDir = rebar_state:get(State, base_dir, ""),
- DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR),
- get_deps_dir(BaseDir, DepsDir).
-
--spec get_deps_dir(file:filename_all(), file:filename_all()) -> file:filename_all().
-get_deps_dir(DepsDir, App) ->
- filename:join(DepsDir, App).
-
-spec handle_deps(rebar_state:t(), [dep()]) -> {ok, rebar_state:t()}.
handle_deps(State, Deps) ->
handle_deps(State, Deps, false).
@@ -117,8 +104,8 @@ handle_deps(State, Deps, Update) ->
{Packages, Graph} = rebar_packages:get_packages(State),
%% Split source deps from pkg deps, needed to keep backwards compatibility
- DepsDir = get_deps_dir(State),
- {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps),
+ DepsDir = rebar_utils:deps_dir(State),
+ {SrcDeps, PkgDeps} = parse_deps(State, DepsDir, Deps),
State1 = rebar_state:src_deps(rebar_state:pkg_deps(State, PkgDeps),
SrcDeps),
@@ -144,7 +131,7 @@ handle_deps(State, Deps, Update) ->
AppInfo <- package_to_app(DepsDir
,Packages
,Pkg),
- maybe_fetch(AppInfo, Update, sets:new())]
+ maybe_fetch(State2, AppInfo, Update, sets:new())]
end,
AllDeps = lists:ukeymerge(2
@@ -152,7 +139,8 @@ handle_deps(State, Deps, Update) ->
,lists:ukeysort(2, Solved)),
%% Sort all apps to build order
State3 = rebar_state:set(State2, all_deps, AllDeps),
- {ok, State3}.
+ State4 = rebar_state:set(State3, {all_deps, rebar_state:current_profile(State)}, AllDeps),
+ {ok, State4}.
%% ===================================================================
%% Internal functions
@@ -167,7 +155,7 @@ package_to_app(DepsDir, Packages, {Name, Vsn}) ->
Link = proplists:get_value(<<"link">>, P, ""),
{ok, AppInfo} = rebar_app_info:new(Name, Vsn),
AppInfo1 = rebar_app_info:deps(AppInfo, PkgDeps),
- AppInfo2 = rebar_app_info:dir(AppInfo1, get_deps_dir(DepsDir, Name)),
+ AppInfo2 = rebar_app_info:dir(AppInfo1, rebar_utils:deps_dir(DepsDir, Name)),
[rebar_app_info:source(AppInfo2, {pkg, Name, Vsn, Link})]
end.
@@ -188,7 +176,7 @@ update_src_deps(Level, State, Update, Seen) ->
,Level
,StateAcc);
_ ->
- maybe_fetch(AppInfo, false, SeenAcc),
+ maybe_fetch(StateAcc, AppInfo, false, SeenAcc),
handle_dep(AppInfo
,SrcDepsAcc
,PkgDepsAcc
@@ -213,7 +201,7 @@ handle_update(AppInfo, UpdateName, UpdateLevel, SrcDeps, PkgDeps, Level, State)
case UpdateLevel < DepLevel
orelse Name =:= UpdateName of
true ->
- case maybe_fetch(AppInfo, true, []) of
+ case maybe_fetch(State, AppInfo, true, []) of
true ->
handle_dep(AppInfo
,SrcDeps
@@ -229,29 +217,38 @@ handle_update(AppInfo, UpdateName, UpdateLevel, SrcDeps, PkgDeps, Level, State)
end.
handle_dep(AppInfo, SrcDeps, PkgDeps, Level, State) ->
- DepsDir = get_deps_dir(State),
+ DepsDir = rebar_utils:deps_dir(State),
{AppInfo1, NewSrcDeps, NewPkgDeps} =
- handle_dep(DepsDir, AppInfo),
+ handle_dep(State, DepsDir, AppInfo),
AppInfo2 = rebar_app_info:dep_level(AppInfo1, Level),
{NewSrcDeps ++ SrcDeps
,NewPkgDeps++PkgDeps
,rebar_state:src_apps(State, AppInfo2)}.
--spec handle_dep(file:filename_all(), rebar_app_info:t()) ->
+-spec handle_dep(rebar_state:t(), file:filename_all(), rebar_app_info:t()) ->
{rebar_app_info:t(), [rebar_app_info:t()], [pkg_dep()]}.
-handle_dep(DepsDir, AppInfo) ->
+handle_dep(State, DepsDir, AppInfo) ->
+ Profile = rebar_state:current_profile(State),
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, PkgDeps} = parse_deps(DepsDir, Deps),
+ S1 = rebar_state:apply_profile(S, Profile),
+ Deps = case Profile of
+ default ->
+ rebar_state:get(S1, {deps, Profile}, []);
+ _ ->
+ rebar_state:get(S1, {deps, default}, []) ++
+ rebar_state:get(S1, {deps, Profile}, [])
+ end,
+ AppInfo1 = rebar_app_info:deps(AppInfo, rebar_state:deps_names(Deps)),
+ {SrcDeps, PkgDeps} = parse_deps(State, DepsDir, Deps),
{AppInfo1, SrcDeps, PkgDeps}.
--spec maybe_fetch(rebar_app_info:t(), boolean() | {true, binary(), integer()},
+-spec maybe_fetch(rebar_state:t(), rebar_app_info:t(), boolean() | {true, binary(), integer()},
sets:set(binary())) -> boolean().
-maybe_fetch(AppInfo, Update, Seen) ->
+maybe_fetch(State, AppInfo, Update, Seen) ->
AppDir = ec_cnv:to_list(rebar_app_info:dir(AppInfo)),
- Apps = rebar_app_discover:find_apps(["_checkouts"], all),
+ DefaultProfileDeps = rebar_utils:default_profile_deps(State),
+ Apps = rebar_app_discover:find_apps(["_checkouts", DefaultProfileDeps], 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
@@ -301,28 +298,31 @@ maybe_fetch(AppInfo, Update, Seen) ->
end
end.
--spec parse_deps(binary(), [dep()]) -> {[rebar_app_info:t()], [pkg_dep()]}.
-parse_deps(DepsDir, Deps) ->
+-spec parse_deps(rebar_state:t(), binary(), [dep()]) -> {[rebar_app_info:t()], [pkg_dep()]}.
+parse_deps(State, DepsDir, Deps) ->
lists:foldl(fun({Name, Vsn}, {SrcDepsAcc, PkgDepsAcc}) ->
{SrcDepsAcc, [parse_goal(ec_cnv:to_binary(Name)
,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 = new_dep(State, 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 = new_dep(State, 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} ->
+new_dep(State, DepsDir, Name, Vsn, Source) ->
+ Dirs = [ec_cnv:to_list(filename:join(rebar_utils:default_profile_deps(State), Name)),
+ ec_cnv:to_list(filename:join(DepsDir, Name))],
+ {ok, Dep} = case ec_lists:search(fun(Dir) ->
+ rebar_app_info:discover(Dir)
+ end, Dirs) of
+ {ok, App, _} ->
{ok, App};
not_found ->
- rebar_app_info:new(Name, Vsn, Dir)
+ rebar_app_info:new(Name, Vsn, ec_cnv:to_list(filename:join(DepsDir, Name)))
end,
rebar_app_info:source(Dep, Source).
diff --git a/src/rebar_prv_lock.erl b/src/rebar_prv_lock.erl
index 4ada1ef..1de8083 100644
--- a/src/rebar_prv_lock.erl
+++ b/src/rebar_prv_lock.erl
@@ -31,13 +31,14 @@ init(State) ->
do(State) ->
case rebar_state:get(State, locks, []) of
[] ->
- AllDeps = rebar_state:get(State, all_deps, []),
+ AllDeps = rebar_state:get(State, {all_deps, default}, []),
Locks = lists:map(fun(Dep) ->
Dir = rebar_app_info:dir(Dep),
+ Source = rebar_app_info:source(Dep),
%% If source is tuple it is a source dep
%% e.g. {git, "git://github.com/ninenines/cowboy.git", "master"}
- case rebar_app_info:source(Dep) of
+ case Source of
Source when is_tuple(Source) ->
{rebar_app_info:name(Dep)
,rebar_app_info:original_vsn(Dep)
diff --git a/src/rebar_prv_release.erl b/src/rebar_prv_release.erl
index cbbb473..7ec8ead 100644
--- a/src/rebar_prv_release.erl
+++ b/src/rebar_prv_release.erl
@@ -12,7 +12,7 @@
-include("rebar.hrl").
-define(PROVIDER, release).
--define(DEPS, [compile]).
+-define(DEPS, [{compile, default}, compile]).
%% ===================================================================
%% Public API
@@ -33,16 +33,16 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
Options = rebar_state:command_args(State),
- DepsDir = rebar_prv_install_deps:get_deps_dir(State),
- OutputDir = filename:join(rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR), "_rel"),
+ DepsDir = [rebar_utils:default_deps_dir(State)], % rebar_utils:deps_dir(State)],
+ OutputDir = filename:join(rebar_utils:profile_dir(State), ?DEFAULT_RELEASE_DIR),
AllOptions = string:join(["release" | Options], " "),
try
case rebar_state:get(State, relx, []) of
[] ->
- relx:main([{lib_dirs, [DepsDir]}
+ relx:main([{lib_dirs, DepsDir}
,{output_dir, OutputDir}], AllOptions);
Config ->
- relx:main([{lib_dirs, [DepsDir]}
+ relx:main([{lib_dirs, DepsDir}
,{config, Config}
,{output_dir, OutputDir}], AllOptions)
end,
diff --git a/src/rebar_prv_tar.erl b/src/rebar_prv_tar.erl
index a340ba9..34a9153 100644
--- a/src/rebar_prv_tar.erl
+++ b/src/rebar_prv_tar.erl
@@ -32,14 +32,18 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
+ OutputDir = filename:join(rebar_utils:profile_dir(State), ?DEFAULT_RELEASE_DIR),
Options = rebar_state:command_args(State),
- DepsDir = rebar_prv_install_deps:get_deps_dir(State),
+ DepsDir = rebar_utils:deps_dir(State),
AllOptions = string:join(["release", "tar" | Options], " "),
case rebar_state:get(State, relx, []) of
[] ->
- relx:main([{lib_dirs, [DepsDir]}], AllOptions);
+ relx:main([{lib_dirs, [DepsDir]
+ ,{output_dir, OutputDir}}], AllOptions);
Config ->
- relx:main([{lib_dirs, [DepsDir]}, {config, Config}], AllOptions)
+ relx:main([{lib_dirs, [DepsDir]}
+ ,{config, Config}
+ ,{output_dir, OutputDir}], AllOptions)
end,
{ok, State}.
diff --git a/src/rebar_prv_test_deps.erl b/src/rebar_prv_test_deps.erl
deleted file mode 100644
index b7341d0..0000000
--- a/src/rebar_prv_test_deps.erl
+++ /dev/null
@@ -1,61 +0,0 @@
--module(rebar_prv_test_deps).
-
--behaviour(provider).
-
--export([init/1,
- do/1,
- format_error/1]).
-
--include("rebar.hrl").
-
--define(PROVIDER, test_deps).
--define(DEPS, []).
-
-%% ===================================================================
-%% 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, true},
- {deps, ?DEPS},
- {hooks, {[], []}},
- {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],
-
- %% Set deps_dir to a different dir for test deps so they don't collide
- TestDepsDir = rebar_state:get(State, test_deps_dir, ?DEFAULT_TEST_DEPS_DIR),
- DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR),
- State1 = rebar_state:set(State, deps_dir, TestDepsDir),
- {ok, State2} = rebar_prv_install_deps:handle_deps(State1, TestDeps),
- AllDeps = rebar_state:get(State2, all_deps, []),
- State3 = rebar_state:set(State2, deps_dir, DepsDir),
-
- case rebar_digraph:compile_order(ProjectApps1++AllDeps) of
- {ok, Sort} ->
- ToBuild = lists:dropwhile(fun rebar_app_info:valid/1, Sort -- ProjectApps1),
- State4 = rebar_state:set(State3, deps_to_build, ToBuild),
- {ok, State4};
- {error, Error} ->
- {error, Error}
- end.
-
--spec format_error(any()) -> iolist().
-format_error(Reason) ->
- io_lib:format("~p", [Reason]).
-
-%% ===================================================================
-%% Internal functions
-%% ===================================================================
diff --git a/src/rebar_state.erl b/src/rebar_state.erl
index 840b428..7b0ac6a 100644
--- a/src/rebar_state.erl
+++ b/src/rebar_state.erl
@@ -2,9 +2,15 @@
-export([new/0, new/1, new/2, new/3,
get/2, get/3, set/3,
+
+ current_profile/1,
+ current_profile/2,
+
command_args/1, command_args/2,
command_parsed_args/1, command_parsed_args/2,
+ apply_profile/2,
+
dir/1, dir/2,
create_logic_providers/2,
@@ -20,18 +26,20 @@
-include("rebar.hrl").
--record(state_t, {dir :: file:name(),
- opts = [],
+-record(state_t, {dir :: file:name(),
+ opts = dict:new() :: rebar_dict(),
- command_args = [],
+ current_profile = default :: atom(),
+
+ command_args = [],
command_parsed_args = [],
- src_deps = [],
- src_apps = [],
- pkg_deps = [] :: [rebar_packages:package()],
- project_apps = [],
+ src_deps = [],
+ src_apps = [],
+ pkg_deps = [] :: [rebar_packages:package()],
+ project_apps = [],
- providers = []}).
+ providers = []}).
-export_type([t/0]).
@@ -44,7 +52,7 @@ new() ->
-spec new(list()) -> t().
new(Config) when is_list(Config) ->
#state_t { dir = rebar_utils:get_cwd(),
- opts = Config }.
+ opts = dict:from_list(Config) }.
-spec new(t(), list()) -> t().
new(ParentState=#state_t{}, Config) ->
@@ -57,25 +65,39 @@ new(ParentState, Config, Dir) ->
Opts = ParentState#state_t.opts,
LocalOpts = case rebar_config:consult_file(?LOCK_FILE) of
[D] ->
- [{locks, D} | Config];
+ dict:from_list([{locks, D} | Config]);
_ ->
- Config
+ dict:from_list(Config)
end,
ProviderModules = [],
- create_logic_providers(ProviderModules, ParentState#state_t{dir=Dir
- ,opts=lists:umerge(LocalOpts, Opts)}).
+ create_logic_providers(ProviderModules
+ ,ParentState#state_t{dir=Dir
+ ,opts=dict:merge(fun(_Key, Value1, _Value2) ->
+ Value1
+ end, LocalOpts, Opts)}).
get(State, Key) ->
- proplists:get_value(Key, State#state_t.opts).
+ {ok, Value} = dict:find(Key, State#state_t.opts),
+ Value.
get(State, Key, Default) ->
- proplists:get_value(Key, State#state_t.opts, Default).
+ case dict:find(Key, State#state_t.opts) of
+ {ok, Value} ->
+ Value;
+ error ->
+ Default
+ end.
-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(State=#state_t{opts=Opts}, Key, Value) ->
+ State#state_t{ opts = dict:store(Key, Value, Opts) }.
+
+current_profile(#state_t{current_profile=Profile}) ->
+ Profile.
+
+current_profile(State, Profile) ->
+ State#state_t{current_profile=Profile}.
command_args(#state_t{command_args=CmdArgs}) ->
CmdArgs.
@@ -89,19 +111,45 @@ command_parsed_args(#state_t{command_parsed_args=CmdArgs}) ->
command_parsed_args(State, CmdArgs) ->
State#state_t{command_parsed_args=CmdArgs}.
+apply_profile(State=#state_t{opts=Opts}, Profile) ->
+ ConfigProfiles = rebar_state:get(State, profiles, []),
+ Deps = rebar_state:get(State, deps, []),
+ Opts1 = dict:store({deps, default}, Deps, dict:erase(deps, Opts)),
+ ProfileOpts = dict:from_list(proplists:get_value(Profile, ConfigProfiles, [])),
+ State#state_t{opts=merge_opts(Profile, ProfileOpts, Opts1)}.
+
+merge_opts(Profile, Opts1, Opts2) ->
+ dict:fold(fun(deps, Value, OptsAcc) ->
+ dict:store({deps, Profile}, Value, OptsAcc);
+ (Key, Value, OptsAcc) ->
+ case dict:fetch(Key, 1, Opts2) of
+ {_, OldValue} when is_list(OldValue) ->
+ case io_lib:printable_list(Value) of
+ true ->
+ dict:store(Key, OptsAcc, {Key, Value});
+ false ->
+ dict:store(Key, OptsAcc, {Key, lists:keymerge(1, lists:keysort(1, OldValue), lists:keysort(1, Value))})
+ end;
+ error ->
+ dict:store(Key, Value, OptsAcc)
+ end
+ end, Opts2, Opts1).
+
dir(#state_t{dir=Dir}) ->
Dir.
dir(State=#state_t{}, Dir) ->
State#state_t{dir=filename:absname(Dir)}.
-deps_names(State) ->
- Deps = rebar_state:get(State, deps, []),
+deps_names(Deps) when is_list(Deps) ->
lists:map(fun(Dep) when is_tuple(Dep) ->
ec_cnv:to_binary(element(1, Dep));
(Dep) when is_atom(Dep) ->
ec_cnv:to_binary(Dep)
- end, Deps).
+ end, Deps);
+deps_names(State) ->
+ Deps = rebar_state:get(State, deps, []),
+ deps_names(Deps).
-spec pkg_deps(t()) -> [rebar_packages:package()].
pkg_deps(#state_t{pkg_deps=PkgDeps}) ->
@@ -138,7 +186,7 @@ project_apps(#state_t{project_apps=Apps}) ->
project_apps(State=#state_t{}, NewApps) when is_list(NewApps) ->
State#state_t{project_apps=NewApps};
project_apps(State=#state_t{project_apps=Apps}, App) ->
- State#state_t{project_apps=[App | Apps]}.
+ State#state_t{project_apps=lists:keystore(rebar_app_info:name(App), 2, Apps, App)}.
providers(#state_t{providers=Providers}) ->
Providers.
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index 9a0e1d9..d28d761 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -26,7 +26,17 @@
%% -------------------------------------------------------------------
-module(rebar_utils).
--export([home_dir/0,
+-export([base_dir/1,
+ deps_dir/1,
+ deps_dir/2,
+ plugins_dir/1,
+ lib_dirs/1,
+ profile_dir/1,
+ default_deps_dir/1,
+ default_profile_dir/1,
+ default_profile_deps/1,
+ home_dir/0,
+
droplast/1,
filtermap/2,
get_cwd/0,
@@ -68,6 +78,45 @@
%% Public API
%% ====================================================================
+-spec base_dir(rebar_state:t()) -> file:filename_all().
+base_dir(State) ->
+ rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR).
+
+-spec deps_dir(rebar_state:t()) -> file:filename_all().
+deps_dir(State) ->
+ DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR),
+ filename:join(profile_dir(State), DepsDir).
+
+-spec deps_dir(file:filename_all(), file:filename_all()) -> file:filename_all().
+deps_dir(DepsDir, App) ->
+ filename:join(DepsDir, App).
+
+-spec default_deps_dir(rebar_state:t()) -> file:filename_all().
+default_deps_dir(State) ->
+ DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR),
+ filename:join([base_dir(State), "default", DepsDir]).
+
+-spec plugins_dir(rebar_state:t()) -> file:filename_all().
+plugins_dir(State) ->
+ filename:join(base_dir(State), rebar_state:get(State, plugins_dir, ?DEFAULT_PLUGINS_DIR)).
+
+-spec lib_dirs(rebar_state:t()) -> file:filename_all().
+lib_dirs(State) ->
+ rebar_state:get(State, lib_dirs, ?DEFAULT_LIB_DIRS).
+
+-spec default_profile_dir(rebar_state:t()) -> file:filename_all().
+default_profile_dir(State) ->
+ filename:join(base_dir(State), "default").
+
+-spec profile_dir(rebar_state:t()) -> file:filename_all().
+profile_dir(State) ->
+ Profile = rebar_state:current_profile(State),
+ filename:join(base_dir(State), atom_to_list(Profile)).
+
+-spec default_profile_deps(rebar_state:t()) -> file:filename_all().
+default_profile_deps(State) ->
+ filename:join(default_profile_dir(State), ?DEFAULT_DEPS_DIR).
+
home_dir() ->
{ok, [[Home]]} = init:get_argument(home),
Home.