Browse Source

wip: profiles

pull/31/head
Tristan Sloughter 10 years ago
parent
commit
14cb6803e0
14 changed files with 226 additions and 173 deletions
  1. +11
    -7
      rebar.config
  2. +6
    -4
      src/rebar.hrl
  3. +3
    -6
      src/rebar3.erl
  4. +16
    -13
      src/rebar_core.erl
  5. +9
    -3
      src/rebar_digraph.erl
  6. +1
    -1
      src/rebar_hooks.erl
  7. +4
    -4
      src/rebar_prv_common_test.erl
  8. +41
    -41
      src/rebar_prv_install_deps.erl
  9. +3
    -2
      src/rebar_prv_lock.erl
  10. +5
    -5
      src/rebar_prv_release.erl
  11. +7
    -3
      src/rebar_prv_tar.erl
  12. +0
    -61
      src/rebar_prv_test_deps.erl
  13. +70
    -22
      src/rebar_state.erl
  14. +50
    -1
      src/rebar_utils.erl

+ 11
- 7
rebar.config View File

@ -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"}}},

+ 6
- 4
src/rebar.hrl View File

@ -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").

+ 3
- 6
src/rebar3.erl View File

@ -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),

+ 16
- 13
src/rebar_core.erl View File

@ -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]).

+ 9
- 3
src/rebar_digraph.erl View File

@ -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).

+ 1
- 1
src/rebar_hooks.erl View File

@ -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 ->

+ 4
- 4
src/rebar_prv_common_test.erl View File

@ -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,

+ 41
- 41
src/rebar_prv_install_deps.erl View File

@ -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).

+ 3
- 2
src/rebar_prv_lock.erl View File

@ -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)

+ 5
- 5
src/rebar_prv_release.erl View File

@ -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,

+ 7
- 3
src/rebar_prv_tar.erl View File

@ -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}.

+ 0
- 61
src/rebar_prv_test_deps.erl View File

@ -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
%% ===================================================================

+ 70
- 22
src/rebar_state.erl View File

@ -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.

+ 50
- 1
src/rebar_utils.erl View File

@ -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.

Loading…
Cancel
Save