diff options
author | Tristan Sloughter <tristan.sloughter@gmail.com> | 2014-12-02 15:55:51 -0600 |
---|---|---|
committer | Tristan Sloughter <tristan.sloughter@gmail.com> | 2014-12-02 15:55:51 -0600 |
commit | 3b2d9ba8c81a41ae5cd554a3f50283e713e191c8 (patch) | |
tree | f5309346fc164fe3556e96db679b32bf5eca5a56 /src | |
parent | 8d655d3c502295394ab30d9fc3fd11679629885d (diff) | |
parent | 3af351cec28521caaa15308b1a4a992380723794 (diff) |
Merge pull request #31 from tsloughter/profiles
Profiles
Diffstat (limited to 'src')
33 files changed, 514 insertions, 447 deletions
diff --git a/src/rebar.app.src b/src/rebar.app.src index 0341f79..5ef2c2f 100644 --- a/src/rebar.app.src +++ b/src/rebar.app.src @@ -41,7 +41,6 @@ rebar_prv_release, rebar_prv_version, rebar_prv_common_test, - rebar_prv_help, - rebar_prv_test_deps]} + rebar_prv_help]} ]} ]}. 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..24d9ad3 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -74,7 +74,7 @@ main(Args) -> run(BaseState, Command) -> _ = application:load(rebar), BaseState1 = rebar_state:set(BaseState, task, Command), - run_aux(BaseState1, [Command]). + run_aux(BaseState1, [], [Command]). %% ==================================================================== %% Internal functions @@ -82,7 +82,7 @@ run(BaseState, Command) -> run(RawArgs) -> _ = application:load(rebar), - BaseConfig = init_config(), + {GlobalPluginProviders, BaseConfig} = init_config(), case erlang:system_info(version) of "6.1" -> @@ -93,9 +93,9 @@ run(RawArgs) -> end, {BaseConfig1, _Args1} = set_options(BaseConfig, {[], []}), - run_aux(BaseConfig1, RawArgs). + run_aux(BaseConfig1, GlobalPluginProviders, RawArgs). -run_aux(State, RawArgs) -> +run_aux(State, GlobalPluginProviders, RawArgs) -> %% Make sure crypto is running case crypto:start() of ok -> ok; @@ -106,23 +106,28 @@ run_aux(State, RawArgs) -> application:start(ssl), 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)) + State2 = case os:getenv("REBAR_DEFAULT_PROFILE") of + false -> + rebar_state:current_profile(State, default); + Profile -> + State1 = rebar_state:current_profile(State, list_to_atom(Profile)), + rebar_state:default(State1, rebar_state:opts(State1)) end, - {ok, Providers} = application:get_env(rebar, providers), + %% Process each command, resetting any state between each one + BaseDir = rebar_dir:base_dir(State2), + State3 = rebar_state:set(State2, base_dir, + filename:join(filename:absname(rebar_state:dir(State2)), BaseDir)), - {ok, PluginProviders, State3} = rebar_plugins:install(State2), - rebar_core:update_code_path(State3), + {ok, Providers} = application:get_env(rebar, providers), + {ok, PluginProviders, State4} = rebar_plugins:install(State3), + rebar_core:update_code_path(State4), - State4 = rebar_state:create_logic_providers(Providers++PluginProviders, State3), + AllProviders = Providers++PluginProviders++GlobalPluginProviders, + State5 = rebar_state:create_logic_providers(AllProviders, State4), {Task, Args} = parse_args(RawArgs), - rebar_core:process_command(rebar_state:command_args(State4, Args), list_to_atom(Task)). + rebar_core:process_command(rebar_state:command_args(State5, Args), list_to_atom(Task)). init_config() -> %% Initialize logging system @@ -144,15 +149,17 @@ init_config() -> end, %% If $HOME/.rebar3/config exists load and use as global config - Home = rebar_utils:home_dir(), + Home = rebar_dir:home_dir(), GlobalConfigFile = filename:join([Home, ?CONFIG_DIR, "config"]), State = case filelib:is_regular(GlobalConfigFile) of true -> ?DEBUG("Load global config file ~p", [GlobalConfigFile]), - GlobalConfig = rebar_state:new(rebar_config:consult_file(GlobalConfigFile)), - rebar_state:new(GlobalConfig, Config1); + GlobalConfig = rebar_state:new(global, rebar_config:consult_file(GlobalConfigFile)), + {ok, PluginProviders, GlobalConfig1} = rebar_plugins:install(GlobalConfig), + rebar_state:new(GlobalConfig1, Config1); false -> + PluginProviders = [], rebar_state:new(Config1) end, @@ -168,7 +175,7 @@ init_config() -> %% TODO: Do we need this still? I think it may still be used. %% Initialize vsn cache - rebar_state:set(State1, vsn_cache, dict:new()). + {PluginProviders, rebar_state:set(State1, vsn_cache, dict:new())}. %% %% Parse command line arguments using getopt and also filtering out any diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl index ea49075..e2bf05e 100644 --- a/src/rebar_app_discover.erl +++ b/src/rebar_app_discover.erl @@ -124,7 +124,7 @@ create_app_info(AppDir, AppFile) -> 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()), + AbsCwd = filename:absname(rebar_dir:get_cwd()), {ok, AppInfo} = rebar_app_info:new(AppName, AppVsn, AppDir, AppDeps), RebarConfig = filename:join(AppDir, "rebar.config"), AppState = case filelib:is_file(RebarConfig) of diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl index 8fc3df8..dac3f0f 100644 --- a/src/rebar_app_utils.erl +++ b/src/rebar_app_utils.erl @@ -56,7 +56,7 @@ find(Name, Vsn, Apps) -> -spec is_app_dir() -> {true, file:name()} | false. is_app_dir() -> - is_app_dir(rebar_utils:get_cwd()). + is_app_dir(rebar_dir:get_cwd()). -spec is_app_dir(file:name()) -> {true, file:name()} | false. is_app_dir(Dir) -> diff --git a/src/rebar_base_compiler.erl b/src/rebar_base_compiler.erl index b42189b..ee023e7 100644 --- a/src/rebar_base_compiler.erl +++ b/src/rebar_base_compiler.erl @@ -258,10 +258,5 @@ format_error(AbsSource, Extra, {Mod, Desc}) -> ErrorDesc = Mod:format_error(Desc), ?FMT("~s: ~s~s~n", [AbsSource, Extra, ErrorDesc]). -maybe_absname(Config, Filename) -> - case rebar_utils:processing_base_dir(Config) of - true -> - Filename; - false -> - filename:absname(Filename) - end. +maybe_absname(_Config, Filename) -> + Filename. diff --git a/src/rebar_core.erl b/src/rebar_core.erl index b2af936..21d008a 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -40,40 +40,42 @@ 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), Opts = providers:opts(CommandProvider)++rebar3:global_option_spec_list(), case Command of do -> - do(TargetProviders, State); + do(TargetProviders, State1); _ -> - case getopt:parse(Opts, rebar_state:command_args(State)) of + case getopt:parse(Opts, rebar_state:command_args(State1)) of {ok, Args} -> - State2 = rebar_state:command_parsed_args(State, Args), - do(TargetProviders, State2); + State3 = rebar_state:command_parsed_args(State1, Args), + do(TargetProviders, State3); {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()}. +-spec do([{atom(), 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_dir:lib_dirs(State), + DepsDir = rebar_dir:deps_dir(State), + PluginsDir = rebar_dir:plugins_dir(State), _UpdatedCodePaths = update_code_path_([DepsDir, PluginsDir | LibDirs]). @@ -82,7 +84,7 @@ update_code_path(State) -> %% =================================================================== update_code_path_(Paths) -> - LibPaths = expand_lib_dirs(Paths, rebar_utils:get_cwd(), []), + LibPaths = expand_lib_dirs(Paths, rebar_dir:get_cwd(), []), ok = code:add_pathsa(LibPaths), %% track just the paths we added, so we can remove them without %% removing other paths added by this dep diff --git a/src/rebar_cover_utils.erl b/src/rebar_cover_utils.erl index 7de9d48..0439b8a 100644 --- a/src/rebar_cover_utils.erl +++ b/src/rebar_cover_utils.erl @@ -78,7 +78,7 @@ init(true, BeamFiles, TargetDir) -> group_leader(F, CoverPid), - ?INFO("Cover compiling ~s\n", [rebar_utils:get_cwd()]), + ?INFO("Cover compiling ~s\n", [rebar_dir:get_cwd()]), Compiled = [{Beam, cover:compile_beam(Beam)} || Beam <- BeamFiles], case [Module || {_, {ok, Module}} <- Compiled] of @@ -121,7 +121,7 @@ analyze(Config, FilteredModules, SrcModules, TargetDir) -> [html]) end, Coverage), - Index = filename:join([rebar_utils:get_cwd(), TargetDir, "index.html"]), + Index = filename:join([rebar_dir:get_cwd(), TargetDir, "index.html"]), ?CONSOLE("Cover analysis: ~s\n", [Index]), %% Export coverage data, if configured 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_dir.erl b/src/rebar_dir.erl new file mode 100644 index 0000000..a6f18ed --- /dev/null +++ b/src/rebar_dir.erl @@ -0,0 +1,104 @@ +-module(rebar_dir). + +-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, + global_config_dir/1, + get_cwd/0, + ensure_dir/1, + src_dirs/1, + ebin_dir/0, + processing_base_dir/1, + processing_base_dir/2]). + +-include("rebar.hrl"). + +-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"). + +profile_dir(State) -> + case rebar_state:current_profile(State) of + global -> + global_config_dir(State); + Profile -> + filename:join(base_dir(State), atom_to_list(Profile)) + end. + +-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. + +global_config_dir(State) -> + Home = home_dir(), + rebar_state:get(State, global_rebar_dir, filename:join(Home, ?CONFIG_DIR)). + +get_cwd() -> + {ok, Dir} = file:get_cwd(), + Dir. + +%% TODO: filelib:ensure_dir/1 corrected in R13B04. Remove when we drop +%% support for OTP releases older than R13B04. +ensure_dir(Path) -> + case filelib:ensure_dir(Path) of + ok -> + ok; + {error,eexist} -> + ok; + Error -> + Error + end. + +-spec src_dirs([string()]) -> [file:filename(), ...]. +src_dirs([]) -> + ["src"]; +src_dirs(SrcDirs) -> + SrcDirs. + +ebin_dir() -> + filename:join(get_cwd(), "ebin"). + +processing_base_dir(State) -> + Cwd = get_cwd(), + processing_base_dir(State, Cwd). + +processing_base_dir(State, Dir) -> + AbsDir = filename:absname(Dir), + AbsDir =:= rebar_state:get(State, base_dir). diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 71ee780..99082f8 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -142,7 +142,7 @@ test_compile(Config, Cmd, OutDir) -> %% Copy source files to eunit dir for cover in case they are not directly %% in src but in a subdirectory of src. Cover only looks in cwd and ../src %% for source files. Also copy files from src_dirs. - SrcDirs = rebar_utils:src_dirs(proplists:append_values(src_dirs, ErlOpts1)), + SrcDirs = rebar_dir:src_dirs(proplists:append_values(src_dirs, ErlOpts1)), SrcErls = lists:foldl( fun(Dir, Acc) -> Files = rebar_utils:find_files( @@ -295,7 +295,7 @@ doterl_compile(Config, Dir, MoreSources, ErlOpts) -> %% eunit tests be separated from the core application source. SrcDirs = lists:map(fun(X) -> filename:join(Dir, X) - end, rebar_utils:src_dirs(proplists:append_values(src_dirs, ErlOpts))), + end, rebar_dir:src_dirs(proplists:append_values(src_dirs, ErlOpts))), AllErlFiles = gather_src(SrcDirs, []) ++ MoreSources, %% NOTE: If and when erl_first_files is not inherited anymore %% (rebar_state:get instead of rebar_state:get_list), consider @@ -410,7 +410,7 @@ check_erlcinfo(Config, _) -> [erlcinfo_file(Config)]). erlcinfo_file(_Config) -> - filename:join([rebar_utils:get_cwd(), ?CONFIG_DIR, ?ERLCINFO_FILE]). + filename:join([rebar_dir:get_cwd(), ?CONFIG_DIR, ?ERLCINFO_FILE]). init_erlcinfo(Config, Erls) -> G = restore_erlcinfo(Config), @@ -589,8 +589,8 @@ internal_erl_compile(Config, Dir, Source, OutDir, ErlOpts, G) -> -spec compile_mib(file:filename(), file:filename(), rebar_state:t()) -> 'ok'. compile_mib(Source, Target, Config) -> - ok = rebar_utils:ensure_dir(Target), - ok = rebar_utils:ensure_dir(filename:join("include", "dummy.hrl")), + ok = rebar_dir:ensure_dir(Target), + ok = rebar_dir:ensure_dir(filename:join("include", "dummy.hrl")), Opts = [{outdir, "priv/mibs"}, {i, ["priv/mibs"]}] ++ rebar_state:get(Config, mib_opts, []), case snmpc:compile(Source, Opts) of diff --git a/src/rebar_fetch.erl b/src/rebar_fetch.erl index e763c2c..2df892c 100644 --- a/src/rebar_fetch.erl +++ b/src/rebar_fetch.erl @@ -19,52 +19,45 @@ -spec lock_source(file:filename_all(), rebar_resource:resource()) -> rebar_resource:resource() | {error, string()}. lock_source(AppDir, Source) -> - case get_resource_type(Source) of - {error, _}=Error -> - Error; - Module -> - Module:lock(AppDir, Source) - end. + Module = get_resource_type(Source), + Module:lock(AppDir, Source). -spec download_source(file:filename_all(), rebar_resource:resource()) -> true | {error, any()}. download_source(AppDir, Source) -> - case get_resource_type(Source) of - {error, _}=Error -> - Error; - Module -> - TmpDir = ec_file:insecure_mkdtemp(), - AppDir1 = ec_cnv:to_list(AppDir), - ec_file:mkdir_p(AppDir1), - case Module:download(TmpDir, Source) of - {ok, _} -> - code:del_path(filename:absname(filename:join(AppDir1, "ebin"))), - ec_file:remove(filename:absname(AppDir1), [recursive]), - ok = ec_file:copy(TmpDir, filename:absname(AppDir1), [recursive]), - true; - {tarball, File} -> - ok = erl_tar:extract(File, [{cwd, TmpDir} - ,compressed]), - BaseName = filename:basename(AppDir1), - [FromDir] = filelib:wildcard(filename:join(TmpDir, BaseName++"-*")), - code:del_path(filename:absname(filename:join(AppDir1, "ebin"))), - ec_file:remove(filename:absname(AppDir1), [recursive]), - ok = ec_file:copy(FromDir, filename:absname(AppDir1), [recursive]), - true - end + try + Module = get_resource_type(Source), + TmpDir = ec_file:insecure_mkdtemp(), + AppDir1 = ec_cnv:to_list(AppDir), + ec_file:mkdir_p(AppDir1), + case Module:download(TmpDir, Source) of + {ok, _} -> + code:del_path(filename:absname(filename:join(AppDir1, "ebin"))), + ec_file:remove(filename:absname(AppDir1), [recursive]), + ok = ec_file:copy(TmpDir, filename:absname(AppDir1), [recursive]), + true; + {tarball, File} -> + ok = erl_tar:extract(File, [{cwd, TmpDir} + ,compressed]), + BaseName = filename:basename(AppDir1), + [FromDir] = filelib:wildcard(filename:join(TmpDir, BaseName++"-*")), + code:del_path(filename:absname(filename:join(AppDir1, "ebin"))), + ec_file:remove(filename:absname(AppDir1), [recursive]), + ok = ec_file:copy(FromDir, filename:absname(AppDir1), [recursive]), + true + end + catch + _:E -> + {error, E} end. -spec needs_update(file:filename_all(), rebar_resource:resource()) -> boolean() | {error, string()}. needs_update(AppDir, Source) -> - case get_resource_type(Source) of - {error, _}=Error -> - Error; - Module -> - try - Module:needs_update(AppDir, Source) - catch - _:_ -> - true - end + Module = get_resource_type(Source), + try + Module:needs_update(AppDir, Source) + catch + _:_ -> + true end. get_resource_type({Type, Location}) -> diff --git a/src/rebar_git_resource.erl b/src/rebar_git_resource.erl index bcd2374..4edaa48 100644 --- a/src/rebar_git_resource.erl +++ b/src/rebar_git_resource.erl @@ -126,12 +126,7 @@ collect_default_refcount() -> build_vsn_string(Vsn, RawRef, RawCount) -> %% Cleanup the tag and the Ref information. Basically leading 'v's and %% whitespace needs to go away. - RefTag = case RawRef of - undefined -> - ""; - RawRef -> - [".ref", re:replace(RawRef, "\\s", "", [global])] - end, + RefTag = [".ref", re:replace(RawRef, "\\s", "", [global])], Count = erlang:iolist_to_binary(re:replace(RawCount, "\\s", "", [global])), %% Create the valid [semver](http://semver.org) version from the tag diff --git a/src/rebar_hooks.erl b/src/rebar_hooks.erl index 3e6d533..fbc207e 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_dir: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_packages.erl b/src/rebar_packages.erl index a0d1a9d..2164b79 100644 --- a/src/rebar_packages.erl +++ b/src/rebar_packages.erl @@ -12,8 +12,7 @@ -spec get_packages(rebar_state:t()) -> {rebar_dict(), rebar_digraph()}. get_packages(State) -> - Home = rebar_utils:home_dir(), - RebarDir = rebar_state:get(State, global_rebar_dir, filename:join(Home, ?CONFIG_DIR)), + RebarDir = rebar_dir:global_config_dir(State), PackagesFile = filename:join(RebarDir, "packages"), case ec_file:exists(PackagesFile) of true -> diff --git a/src/rebar_plugins.erl b/src/rebar_plugins.erl index b7d81e2..000ccdc 100644 --- a/src/rebar_plugins.erl +++ b/src/rebar_plugins.erl @@ -13,20 +13,23 @@ install(State) -> %% Set deps_dir to a different dir for plugin so they don't collide - DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR), + OldDepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR), State1 = rebar_state:set(State, deps_dir, ?DEFAULT_PLUGINS_DIR), - expand_plugins(?DEFAULT_PLUGINS_DIR), + DepsDir = rebar_dir:deps_dir(State1), + expand_plugins(DepsDir), Plugins = rebar_state:get(State1, plugins, []), PluginProviders = rebar_utils:filtermap(fun(Plugin) -> handle_plugin(Plugin, State1) end, Plugins), - {ok, PluginProviders, rebar_state:set(State1, deps_dir, DepsDir)}. + State2 = rebar_state:set(State1, deps_dir, OldDepsDir), + {ok, PluginProviders, State2}. +-spec handle_plugin(rebar_prv_install_deps:dep(), rebar_state:t()) -> {true, any()} | false. handle_plugin(Plugin, State) -> try - {ok, State1} = rebar_prv_install_deps:handle_deps(State, [Plugin]), - Apps = rebar_state:get(State1, all_deps, []), + {ok, _, State1} = rebar_prv_install_deps:handle_deps(State, [Plugin]), + Apps = rebar_state:all_deps(State1), ToBuild = lists:dropwhile(fun rebar_app_info:valid/1, Apps), lists:foreach(fun(AppInfo) -> AppDir = rebar_app_info:dir(AppInfo), diff --git a/src/rebar_prv_clean.erl b/src/rebar_prv_clean.erl index 2a5abf7..6d14cdb 100644 --- a/src/rebar_prv_clean.erl +++ b/src/rebar_prv_clean.erl @@ -48,7 +48,7 @@ do(State) -> EmptyState = rebar_state:new(), clean_apps(EmptyState, DepApps), - Cwd = rebar_utils:get_cwd(), + Cwd = rebar_dir:get_cwd(), rebar_hooks:run_compile_hooks(Cwd, pre_hooks, clean, State), clean_apps(State, ProjectApps), rebar_hooks:run_compile_hooks(Cwd, post_hooks, clean, State), diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 59f5565..3d64517 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_dir: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_compile.erl b/src/rebar_prv_compile.erl index 893fd76..221876b 100644 --- a/src/rebar_prv_compile.erl +++ b/src/rebar_prv_compile.erl @@ -42,8 +42,8 @@ do(State) -> Jobs = rebar_state:get(State1, jobs), ProjectApps = rebar_state:project_apps(State1), - Deps = rebar_state:get(State1, deps_to_build, []), - Cwd = rebar_utils:get_cwd(), + Deps = rebar_state:deps_to_build(State1), + Cwd = rebar_dir:get_cwd(), rebar_hooks:run_compile_hooks(Cwd, pre_hooks, compile, State1), %% Need to allow global config vars used on deps diff --git a/src/rebar_prv_dialyzer.erl b/src/rebar_prv_dialyzer.erl index 6bff26b..8ef5b50 100644 --- a/src/rebar_prv_dialyzer.erl +++ b/src/rebar_prv_dialyzer.erl @@ -286,7 +286,7 @@ build_proj_plt(State, Plt, Files) -> end. get_base_plt_location(State) -> - Home = rebar_utils:home_dir(), + Home = rebar_dir:home_dir(), GlobalConfigDir = filename:join(Home, ?CONFIG_DIR), BaseDir = rebar_state:get(State, dialyzer_base_plt_dir, GlobalConfigDir), BasePlt = rebar_state:get(State, dialyzer_base_plt, default_plt()), diff --git a/src/rebar_prv_eunit.erl b/src/rebar_prv_eunit.erl index 8f05f02..c14a15d 100644 --- a/src/rebar_prv_eunit.erl +++ b/src/rebar_prv_eunit.erl @@ -101,9 +101,9 @@ run_eunit(Config, CodePath, SrcErls) -> ensure_dirs() -> %% Make sure ?EUNIT_DIR/ and ebin/ directory exists (append dummy module) ok = filelib:ensure_dir(filename:join(eunit_dir(), "dummy")), - ok = filelib:ensure_dir(filename:join(rebar_utils:ebin_dir(), "dummy")). + ok = filelib:ensure_dir(filename:join(rebar_dir:ebin_dir(), "dummy")). eunit_dir() -> - filename:join(rebar_utils:get_cwd(), ?EUNIT_DIR). + filename:join(rebar_dir:get_cwd(), ?EUNIT_DIR). setup_code_path() -> %% Setup code path prior to compilation so that parse_transforms %% and the like work properly. Also, be sure to add ebin_dir() @@ -111,7 +111,7 @@ setup_code_path() -> %% through hoops to access the .app file CodePath = code:get_path(), true = code:add_patha(eunit_dir()), - true = code:add_pathz(rebar_utils:ebin_dir()), + true = code:add_pathz(rebar_dir:ebin_dir()), CodePath. %% %% == get matching tests == @@ -354,7 +354,7 @@ perform_eunit(Config, Tests) -> EunitOpts = get_eunit_opts(Config), %% Move down into ?EUNIT_DIR while we run tests so any generated files %% are created there (versus in the source dir) - Cwd = rebar_utils:get_cwd(), + Cwd = rebar_dir:get_cwd(), ok = file:set_cwd(?EUNIT_DIR), EunitResult = (catch eunit:test(Tests, EunitOpts)), %% Return to original working dir diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl index 9822b32..5fcc4d6 100644 --- a/src/rebar_prv_install_deps.erl +++ b/src/rebar_prv_install_deps.erl @@ -37,9 +37,7 @@ -export([handle_deps/2, handle_deps/3]). -%% for internal use only --export([get_deps_dir/1]). --export([get_deps_dir/2]). +-export_type([dep/0]). -define(PROVIDER, install_deps). -define(DEPS, [app_discovery]). @@ -67,20 +65,22 @@ 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, [])); - Locks -> - handle_deps(State, Locks) - end, - - Source = ProjectApps ++ rebar_state:src_apps(State1), + {ok, SrcApps, State1} = case rebar_state:get(State, locks, []) of + [] -> + handle_deps(State, rebar_state:get(State, {deps, Profile}, [])); + Locks -> + handle_deps(State, Locks) + end, + + Source = ProjectApps ++ SrcApps, case rebar_digraph:compile_order(Source) of {ok, Sort} -> - {ok, rebar_state:set(State1, deps_to_build, - lists:dropwhile(fun rebar_app_info:valid/1, Sort -- ProjectApps))}; + {ok, rebar_state:deps_to_build(State1, + lists:dropwhile(fun rebar_app_info:valid/1 + , Sort -- ProjectApps))}; {error, Error} -> {error, Error} end @@ -94,90 +94,101 @@ 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()}. +-spec handle_deps(rebar_state:t(), list()) -> + {ok, [rebar_app_info:t()], rebar_state:t()} | {error, string()}. handle_deps(State, Deps) -> handle_deps(State, Deps, false). --spec handle_deps(rebar_state:t(), [dep()], boolean() | {true, binary(), integer()}) - -> {ok, rebar_state:t()} | {error, string()}. +-spec handle_deps(rebar_state:t(), list(), boolean() | {true, binary(), integer()}) + -> {ok, [rebar_app_info:t()], rebar_state:t()} | {error, string()}. handle_deps(State, [], _) -> - {ok, State}; + {ok, [], State}; handle_deps(State, Deps, Update) -> %% Read in package index and dep graph {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), - State1 = rebar_state:src_deps(rebar_state:pkg_deps(State, PkgDeps), - SrcDeps), + DepsDir = rebar_dir:deps_dir(State), + {SrcDeps, PkgDeps} = parse_deps(State, DepsDir, Deps), %% Fetch transitive src deps - {State2, _Seen} = update_src_deps(0, State1, Update, sets:new()), - - Solved = case rebar_state:pkg_deps(State2) of - [] -> %% No pkg deps - []; - PkgDeps1 -> - %% Find pkg deps needed - S = case rebar_digraph:cull_deps(Graph, PkgDeps1) of - {ok, []} -> - throw({rebar_digraph, no_solution}); - {ok, Solution} -> - Solution; - [] -> - throw({rebar_digraph, no_solution}) - end, - - %% Create app_info record for each pkg dep - [AppInfo || Pkg <- S, - AppInfo <- package_to_app(DepsDir - ,Packages - ,Pkg), - maybe_fetch(AppInfo, Update, sets:new())] - end, + {State1, SrcApps, PkgDeps1, Seen} = + update_src_deps(0, SrcDeps, PkgDeps, [], State, Update, sets:new()), + + {Solved, State2} = case PkgDeps1 of + [] -> %% No pkg deps + {[], State1}; + PkgDeps2 -> + %% Find pkg deps needed + S = case rebar_digraph:cull_deps(Graph, PkgDeps2) of + {ok, []} -> + throw({rebar_digraph, no_solution}); + {ok, Solution} -> + Solution + end, + + update_pkg_deps(S, Packages, Update, Seen, State1) + end, AllDeps = lists:ukeymerge(2 - ,lists:ukeysort(2, rebar_state:src_apps(State2)) + ,lists:ukeysort(2, SrcApps) ,lists:ukeysort(2, Solved)), %% Sort all apps to build order - State3 = rebar_state:set(State2, all_deps, AllDeps), - {ok, State3}. + State3 = rebar_state:all_deps(State2, AllDeps), + + {ok, SrcApps, State3}. %% =================================================================== %% Internal functions %% =================================================================== +update_pkg_deps(Pkgs, Packages, Update, Seen, State) -> + %% Create app_info record for each pkg dep + DepsDir = rebar_dir:deps_dir(State), + {Solved, _, State1} + = lists:foldl(fun(Pkg, {Acc, SeenAcc, StateAcc}) -> + AppInfo = package_to_app(DepsDir + ,Packages + ,Pkg), + {SeenAcc1, StateAcc1} = maybe_lock(AppInfo, SeenAcc, StateAcc), + case maybe_fetch(StateAcc1, AppInfo, Update, SeenAcc) of + true -> + {[AppInfo | Acc], SeenAcc1, StateAcc1}; + false -> + {Acc, SeenAcc1, StateAcc1} + end + end, {[], Seen, State}, Pkgs), + {Solved, State1}. + +maybe_lock(AppInfo, Seen, State) -> + Name = rebar_app_info:name(AppInfo), + case sets:is_element(Name, Seen) of + false -> + {sets:add_element(Name, Seen), + rebar_state:lock(State, AppInfo)}; + true -> + {sets:add_element(Name, Seen), State} + end. + package_to_app(DepsDir, Packages, {Name, Vsn}) -> case dict:find({Name, Vsn}, Packages) of error -> - []; + {error, missing_package}; {ok, P} -> PkgDeps = proplists:get_value(<<"deps">>, P, []), 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)), - [rebar_app_info:source(AppInfo2, {pkg, Name, Vsn, Link})] + AppInfo2 = rebar_app_info:dir(AppInfo1, rebar_dir:deps_dir(DepsDir, Name)), + rebar_app_info:source(AppInfo2, {pkg, Name, Vsn, Link}) end. --spec update_src_deps(integer(), rebar_state:t(), boolean(), sets:set(binary())) -> - {rebar_state:t(), [binary()]}. -update_src_deps(Level, State, Update, Seen) -> - SrcDeps = rebar_state:src_deps(State), - case lists:foldl(fun(AppInfo, {SrcDepsAcc, PkgDepsAcc, StateAcc, SeenAcc}) -> - SeenAcc1 = sets:add_element(rebar_app_info:name(AppInfo), SeenAcc), - {SrcDepsAcc1, PkgDepsAcc1, StateAcc1} = +-spec update_src_deps(non_neg_integer(), list(), list(), list(), rebar_state:t(), boolean(), sets:set(binary())) -> {rebar_state:t(), list(), list(), sets:set(binary())}. +update_src_deps(Level, SrcDeps, PkgDeps, SrcApps, State, Update, Seen) -> + case lists:foldl(fun(AppInfo, {SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc, SeenAcc}) -> + %% If not seen, add to list of locks to write out + {SeenAcc1, StateAcc1} = maybe_lock(AppInfo, SeenAcc, StateAcc), + {SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2} = case Update of {true, UpdateName, UpdateLevel} -> handle_update(AppInfo @@ -185,73 +196,84 @@ update_src_deps(Level, State, Update, Seen) -> ,UpdateLevel ,SrcDepsAcc ,PkgDepsAcc + ,SrcAppsAcc ,Level - ,StateAcc); + ,StateAcc1); _ -> - maybe_fetch(AppInfo, false, SeenAcc), + maybe_fetch(StateAcc, AppInfo, false, SeenAcc), handle_dep(AppInfo ,SrcDepsAcc ,PkgDepsAcc + ,SrcAppsAcc ,Level - ,StateAcc) + ,StateAcc1) end, - {SrcDepsAcc1, PkgDepsAcc1, StateAcc1, SeenAcc1} - end, {[], rebar_state:pkg_deps(State), State, Seen}, SrcDeps) of - {[], NewPkgDeps, State1, Seen1} -> - {rebar_state:pkg_deps(State1, NewPkgDeps), Seen1}; - {NewSrcDeps, NewPkgDeps, State1, Seen1} -> - State2 = rebar_state:pkg_deps(State1, NewPkgDeps), - State3 = rebar_state:src_deps(State2, NewSrcDeps), - update_src_deps(Level+1, State3, Update, Seen1) + {SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, SeenAcc1} + end, {[], PkgDeps, SrcApps, State, Seen}, SrcDeps) of + {[], NewPkgDeps, NewSrcApps, State1, Seen1} -> + {State1, NewSrcApps, NewPkgDeps, Seen1}; + {NewSrcDeps, NewPkgDeps, NewSrcApps, State1, Seen1} -> + update_src_deps(Level+1, NewSrcDeps, NewPkgDeps, NewSrcApps, State1, Update, Seen1) end. -handle_update(AppInfo, UpdateName, UpdateLevel, SrcDeps, PkgDeps, Level, State) -> +handle_update(AppInfo, UpdateName, UpdateLevel, SrcDeps, PkgDeps, SrcApps, 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 + case maybe_fetch(State, AppInfo, true, []) of true -> handle_dep(AppInfo ,SrcDeps ,PkgDeps + ,SrcApps ,Level ,State); false -> - {SrcDeps, PkgDeps, State} + {SrcDeps, PkgDeps, SrcApps, State} end; false -> - {SrcDeps, PkgDeps, State} + {SrcDeps, PkgDeps, SrcApps, State} end. -handle_dep(AppInfo, SrcDeps, PkgDeps, Level, State) -> - DepsDir = get_deps_dir(State), +handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps, Level, State) -> + DepsDir = rebar_dir: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)}. + ,[AppInfo2 | SrcApps] + ,State}. --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_dir: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 +323,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(), list()) -> {[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_dir: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..aba5080 100644 --- a/src/rebar_prv_lock.erl +++ b/src/rebar_prv_lock.erl @@ -31,22 +31,17 @@ init(State) -> do(State) -> case rebar_state:get(State, locks, []) of [] -> - AllDeps = rebar_state:get(State, all_deps, []), + AllDeps = rebar_state:lock(State), 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 - Source when is_tuple(Source) -> - {rebar_app_info:name(Dep) - ,rebar_app_info:original_vsn(Dep) - ,rebar_fetch:lock_source(Dir, Source) - ,rebar_app_info:dep_level(Dep)}; - _Source -> - {rebar_app_info:name(Dep) - ,rebar_app_info:original_vsn(Dep)} - end + {rebar_app_info:name(Dep) + ,rebar_app_info:original_vsn(Dep) + ,rebar_fetch:lock_source(Dir, Source) + ,rebar_app_info:dep_level(Dep)} end, AllDeps), Dir = rebar_state:dir(State), file:write_file(filename:join(Dir, "rebar.lock"), io_lib:format("~p.~n", [Locks])), diff --git a/src/rebar_prv_release.erl b/src/rebar_prv_release.erl index cbbb473..d9cc40f 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_dir:default_deps_dir(State)], % rebar_dir:deps_dir(State)], + OutputDir = filename:join(rebar_dir: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_shell.erl b/src/rebar_prv_shell.erl index 9709807..76a416d 100644 --- a/src/rebar_prv_shell.erl +++ b/src/rebar_prv_shell.erl @@ -72,7 +72,6 @@ format_error(Reason) -> %% immediately kill the script. ctrl-g, however, works fine shell() -> - true = code:add_pathz(rebar_utils:ebin_dir()), %% scan all processes for any with references to the old user and save them to %% update later NeedsUpdate = [Pid || Pid <- erlang:processes(), diff --git a/src/rebar_prv_tar.erl b/src/rebar_prv_tar.erl index a340ba9..ae1942b 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_dir:profile_dir(State), ?DEFAULT_RELEASE_DIR), Options = rebar_state:command_args(State), - DepsDir = rebar_prv_install_deps:get_deps_dir(State), + DepsDir = rebar_dir: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_prv_update.erl b/src/rebar_prv_update.erl index 16987be..524a684 100644 --- a/src/rebar_prv_update.erl +++ b/src/rebar_prv_update.erl @@ -37,7 +37,7 @@ do(State) -> Url = url(State), TmpDir = ec_file:insecure_mkdtemp(), TmpFile = filename:join(TmpDir, "packages"), - Home = rebar_utils:home_dir(), + Home = rebar_dir:home_dir(), PackagesFile = filename:join([Home, ?CONFIG_DIR, "packages"]), filelib:ensure_dir(PackagesFile), {ok, _RequestId} = httpc:request(get, {Url, [{"Accept", "application/erlang"}]}, diff --git a/src/rebar_prv_upgrade.erl b/src/rebar_prv_upgrade.erl index 8b18f5e..c0a56c3 100644 --- a/src/rebar_prv_upgrade.erl +++ b/src/rebar_prv_upgrade.erl @@ -42,9 +42,13 @@ do(State) -> case lists:keyfind(Name, 1, Locks) of {_, _, _, Level} -> Deps = rebar_state:get(State, deps), - Dep = lists:keyfind(binary_to_atom(Name, utf8), 1, Deps), - rebar_prv_install_deps:handle_deps(State, [Dep], {true, Name, Level}), - {ok, State}; + case lists:keyfind(binary_to_atom(Name, utf8), 1, Deps) of + false -> + {error, io_lib:format("No such dependency ~s~n", [Name])}; + Dep -> + rebar_prv_install_deps:handle_deps(State, [Dep], {true, Name, Level}), + {ok, State} + end; _ -> {error, io_lib:format("No such dependency ~s~n", [Name])} end. diff --git a/src/rebar_resource.erl b/src/rebar_resource.erl index ee7d2d3..2bc28e2 100644 --- a/src/rebar_resource.erl +++ b/src/rebar_resource.erl @@ -36,7 +36,7 @@ behaviour_info(_) -> -callback download(file:filename_all(), tuple()) -> {tarball, file:filename_all()} | {ok, any()} | {error, any()}. -callback needs_update(file:filename_all(), tuple()) -> - {tarball, file:filename_all()} | {ok, any()} | {error, any()}. + boolean(). -callback make_vsn(file:filename_all()) -> {plain, string()} | {error, string()}. diff --git a/src/rebar_state.erl b/src/rebar_state.erl index 840b428..77004a7 100644 --- a/src/rebar_state.erl +++ b/src/rebar_state.erl @@ -2,36 +2,49 @@ -export([new/0, new/1, new/2, new/3, get/2, get/3, set/3, + + opts/1, + default/1, default/2, + + lock/1, lock/2, + + 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, project_apps/1, project_apps/2, + deps_to_build/1, deps_to_build/2, + all_deps/1, all_deps/2, deps_names/1, - 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"). --record(state_t, {dir :: file:name(), - opts = [], +-record(state_t, {dir :: file:name(), + opts = dict:new() :: rebar_dict(), + default = dict:new() :: rebar_dict(), - command_args = [], + lock = [], + current_profile = default :: atom(), + + command_args = [], command_parsed_args = [], - src_deps = [], - src_apps = [], - pkg_deps = [] :: [rebar_packages:package()], - project_apps = [], + project_apps = [] :: [rebar_app_into:t()], + deps_to_build = [] :: [rebar_app_into:t()], + all_deps = [] :: [rebar_app_into:t()], - providers = []}). + providers = []}). -export_type([t/0]). @@ -39,17 +52,26 @@ -spec new() -> t(). new() -> - #state_t{dir = rebar_utils:get_cwd()}. + #state_t{dir = rebar_dir:get_cwd()}. -spec new(list()) -> t(). new(Config) when is_list(Config) -> - #state_t { dir = rebar_utils:get_cwd(), - opts = Config }. - --spec new(t(), list()) -> t(). + Opts = dict:from_list(Config), + #state_t { dir = rebar_dir:get_cwd(), + default = Opts, + opts = Opts }. + +-spec new(t() | atom(), list()) -> t(). +new(Profile, Config) when is_atom(Profile) + , is_list(Config) -> + Opts = dict:from_list(Config), + #state_t { dir = rebar_dir:get_cwd(), + current_profile = Profile, + default = Opts, + opts = Opts }; new(ParentState=#state_t{}, Config) -> %% Load terms from rebar.config, if it exists - Dir = rebar_utils:get_cwd(), + Dir = rebar_dir:get_cwd(), new(ParentState, Config, Dir). -spec new(t(), list(), file:name()) -> t(). @@ -57,25 +79,55 @@ 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, - + NewOpts = dict:merge(fun(_Key, Value1, _Value2) -> + Value1 + end, LocalOpts, Opts), 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=NewOpts + ,default=NewOpts}). 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) }. + +default(#state_t{default=Opts}) -> + Opts. + +default(State, Opts) -> + State#state_t{default=Opts}. + +opts(#state_t{opts=Opts}) -> + Opts. + +current_profile(#state_t{current_profile=Profile}) -> + Profile. + +current_profile(State, Profile) -> + apply_profile(State#state_t{current_profile=Profile}, Profile). + +lock(#state_t{lock=Lock}) -> + Lock. + +lock(State=#state_t{lock=Lock}, App) -> + State#state_t{lock=[App | Lock]}. command_args(#state_t{command_args=CmdArgs}) -> CmdArgs. @@ -89,48 +141,46 @@ command_parsed_args(#state_t{command_parsed_args=CmdArgs}) -> command_parsed_args(State, CmdArgs) -> State#state_t{command_parsed_args=CmdArgs}. +%% Only apply profiles to the default profile +apply_profile(State=#state_t{default=Opts}, Profile) -> + ConfigProfiles = rebar_state:get(State, profiles, []), + Deps = rebar_state:get(State, deps, []), + Opts1 = dict:store({deps, default}, 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, Opts2) of + OldValue when is_list(OldValue) -> + case io_lib:printable_list(Value) of + true -> + dict:store(Key, Value, OptsAcc); + false -> + dict:store(Key, lists:keymerge(1, lists:keysort(1, OldValue), lists:keysort(1, Value)), OptsAcc) + end; + _ -> + 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). - --spec pkg_deps(t()) -> [rebar_packages:package()]. -pkg_deps(#state_t{pkg_deps=PkgDeps}) -> - PkgDeps. - -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. - -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) -> - 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}. + end, Deps); +deps_names(State) -> + Deps = rebar_state:get(State, deps, []), + deps_names(Deps). project_apps(#state_t{project_apps=Apps}) -> Apps. @@ -138,7 +188,21 @@ 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)}. + +deps_to_build(#state_t{deps_to_build=Apps}) -> + Apps. + +deps_to_build(State=#state_t{}, NewApps) when is_list(NewApps) -> + State#state_t{deps_to_build=NewApps}; +deps_to_build(State=#state_t{deps_to_build=Apps}, App) -> + State#state_t{deps_to_build=lists:keystore(rebar_app_info:name(App), 2, Apps, App)}. + +all_deps(#state_t{all_deps=Apps}) -> + Apps. + +all_deps(State=#state_t{}, NewApps) -> + State#state_t{all_deps=NewApps}. providers(#state_t{providers=Providers}) -> Providers. diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl index f4cf3d2..7fe9241 100644 --- a/src/rebar_templater.erl +++ b/src/rebar_templater.erl @@ -143,7 +143,7 @@ default_variables() -> %% Load variable definitions from the 'Globals' file in the home template %% directory global_variables() -> - Home = rebar_utils:home_dir(), + Home = rebar_dir:home_dir(), GlobalFile = filename:join([Home, ?CONFIG_DIR, "templates", "globals"]), case file:consult(GlobalFile) of {error, enoent} -> []; @@ -270,7 +270,7 @@ find_escript_templates(Files) -> %% Fetch template indexes that sit on disk in the user's HOME find_disk_templates(State) -> OtherTemplates = find_other_templates(State), - Home = rebar_utils:home_dir(), + Home = rebar_dir:home_dir(), HomeFiles = rebar_utils:find_files(filename:join([Home, ?CONFIG_DIR, "templates"]), ?TEMPLATE_RE), [{file, F} || F <- OtherTemplates ++ HomeFiles]. diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 9a0e1d9..21629a4 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -26,10 +26,8 @@ %% ------------------------------------------------------------------- -module(rebar_utils). --export([home_dir/0, - droplast/1, +-export([droplast/1, filtermap/2, - get_cwd/0, is_arch/1, sh/2, sh_send/3, @@ -38,7 +36,6 @@ escript_foldl/3, find_files/2, find_files/3, - ensure_dir/1, beam_to_mod/1, beam_to_mod/2, erl_to_mod/1, @@ -50,10 +47,6 @@ deprecated/4, delayed_halt/1, erl_opts/1, - src_dirs/1, - ebin_dir/0, - processing_base_dir/1, - processing_base_dir/2, indent/1, cleanup_code_path/1]). @@ -68,17 +61,9 @@ %% Public API %% ==================================================================== -home_dir() -> - {ok, [[Home]]} = init:get_argument(home), - Home. - droplast(L) -> lists:reverse(tl(lists:reverse(L))). -get_cwd() -> - {ok, Dir} = file:get_cwd(), - Dir. - filtermap(F, [Hd|Tail]) -> case F(Hd) of true -> @@ -114,7 +99,7 @@ wordsize() -> sh_send(Command0, String, Options0) -> ?INFO("sh_send info:\n\tcwd: ~p\n\tcmd: ~s < ~s\n", - [get_cwd(), Command0, String]), + [rebar_dir:get_cwd(), Command0, String]), ?DEBUG("\topts: ~p\n", [Options0]), DefaultOptions = [use_stdout, abort_on_error], @@ -140,7 +125,7 @@ sh_send(Command0, String, Options0) -> %% Val = string() | false %% sh(Command0, Options0) -> - ?DEBUG("sh info:\n\tcwd: ~p\n\tcmd: ~s\n", [get_cwd(), Command0]), + ?DEBUG("sh info:\n\tcwd: ~p\n\tcmd: ~s\n", [rebar_dir:get_cwd(), Command0]), ?DEBUG("\topts: ~p\n", [Options0]), DefaultOptions = [{use_stdout, false}, debug_and_abort_on_error], @@ -170,18 +155,6 @@ find_files(Dir, Regex, Recursive) -> filelib:fold_files(Dir, Regex, Recursive, fun(F, Acc) -> [F | Acc] end, []). -%% TODO: filelib:ensure_dir/1 corrected in R13B04. Remove when we drop -%% support for OTP releases older than R13B04. -ensure_dir(Path) -> - case filelib:ensure_dir(Path) of - ok -> - ok; - {error,eexist} -> - ok; - Error -> - Error - end. - find_executable(Name) -> case os:find_executable(Name) of false -> false; @@ -267,23 +240,6 @@ erl_opts(Config) -> [debug_info|Opts] end. --spec src_dirs([string()]) -> [file:filename(), ...]. -src_dirs([]) -> - ["src"]; -src_dirs(SrcDirs) -> - SrcDirs. - -ebin_dir() -> - filename:join(get_cwd(), "ebin"). - -processing_base_dir(State) -> - Cwd = rebar_utils:get_cwd(), - processing_base_dir(State, Cwd). - -processing_base_dir(State, Dir) -> - AbsDir = filename:absname(Dir), - AbsDir =:= rebar_state:get(State, base_dir). - %% ==================================================================== %% Internal functions %% ==================================================================== @@ -471,31 +427,7 @@ vcs_vsn_1(Vcs, Dir) -> unknown -> ?ABORT("vcs_vsn: Unknown vsn format: ~p\n", [Vcs]); {error, Reason} -> - ?ABORT("vcs_vsn: ~s\n", [Reason]); - Cmd -> - %% If there is a valid VCS directory in the application directory, - %% use that version info - Extension = lists:concat([".", Vcs]), - case filelib:is_dir(filename:join(Dir, Extension)) of - true -> - ?DEBUG("vcs_vsn: Primary vcs used for ~s\n", [Dir]), - vcs_vsn_invoke(Cmd, Dir); - false -> - %% No VCS directory found for the app. Depending on source - %% tree structure, there may be one higher up, but that can - %% yield unexpected results when used with deps. So, we - %% fallback to searching for a priv/vsn.Vcs file. - VsnFile = filename:join([Dir, "priv", "vsn" ++ Extension]), - case file:read_file(VsnFile) of - {ok, VsnBin} -> - ?DEBUG("vcs_vsn: Read ~s from priv/vsn.~p\n", - [VsnBin, Vcs]), - string:strip(binary_to_list(VsnBin), right, $\n); - {error, enoent} -> - ?DEBUG("vcs_vsn: Fallback to vcs for ~s\n", [Dir]), - vcs_vsn_invoke(Cmd, Dir) - end - end + ?ABORT("vcs_vsn: ~s\n", [Reason]) end. %% Temp work around for repos like relx that use "semver" |