diff options
-rw-r--r-- | rebar.config | 18 | ||||
-rw-r--r-- | src/rebar.hrl | 10 | ||||
-rw-r--r-- | src/rebar3.erl | 9 | ||||
-rw-r--r-- | src/rebar_core.erl | 29 | ||||
-rw-r--r-- | src/rebar_digraph.erl | 12 | ||||
-rw-r--r-- | src/rebar_hooks.erl | 2 | ||||
-rw-r--r-- | src/rebar_prv_common_test.erl | 8 | ||||
-rw-r--r-- | src/rebar_prv_install_deps.erl | 82 | ||||
-rw-r--r-- | src/rebar_prv_lock.erl | 5 | ||||
-rw-r--r-- | src/rebar_prv_release.erl | 10 | ||||
-rw-r--r-- | src/rebar_prv_tar.erl | 10 | ||||
-rw-r--r-- | src/rebar_prv_test_deps.erl | 61 | ||||
-rw-r--r-- | src/rebar_state.erl | 92 | ||||
-rw-r--r-- | src/rebar_utils.erl | 51 |
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. |