diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | priv/templates/gitignore | 1 | ||||
-rw-r--r-- | rebar.config | 2 | ||||
-rw-r--r-- | rebar.lock | 2 | ||||
-rw-r--r-- | src/rebar3.erl | 11 | ||||
-rw-r--r-- | src/rebar_dir.erl | 50 | ||||
-rw-r--r-- | src/rebar_erlc_compiler.erl | 3 | ||||
-rw-r--r-- | src/rebar_fetch.erl | 2 | ||||
-rw-r--r-- | src/rebar_otp_app.erl | 5 | ||||
-rw-r--r-- | src/rebar_plugins.erl | 24 | ||||
-rw-r--r-- | src/rebar_prv_common_test.erl | 13 | ||||
-rw-r--r-- | src/rebar_prv_compile.erl | 4 | ||||
-rw-r--r-- | src/rebar_prv_eunit.erl | 74 | ||||
-rw-r--r-- | src/rebar_prv_install_deps.erl | 3 | ||||
-rw-r--r-- | src/rebar_state.erl | 7 | ||||
-rw-r--r-- | src/rebar_utils.erl | 18 | ||||
-rw-r--r-- | test/rebar_compile_SUITE.erl | 57 | ||||
-rw-r--r-- | test/rebar_dir_SUITE.erl | 99 | ||||
-rw-r--r-- | test/rebar_test_utils.erl | 17 |
20 files changed, 333 insertions, 62 deletions
@@ -1,3 +1,4 @@ +.rebar3 rebar3 _build .depsolver_plt @@ -110,7 +110,7 @@ format_error(Reason) -> Building -------- -Recommended installation of [Erlang/OTP](http://www.erlang.org) is binary packages from [Erlang Solutions](https://www.erlang-solutions.com/downloads/download-erlang-otp). For source it is recommended you use [erln8](http://metadave.github.io/erln8/) or [kerl](https://github.com/yrashk/kerl). +Recommended installation of [Erlang/OTP](http://www.erlang.org) is source built using [erln8](http://metadave.github.io/erln8/) or [kerl](https://github.com/yrashk/kerl). For binary packages use those provided by [Erlang Solutions](https://www.erlang-solutions.com/downloads/download-erlang-otp), but be sure to choose the "Standard" download option or you'll have issues building projects. ### Dependencies diff --git a/priv/templates/gitignore b/priv/templates/gitignore index 40a1d4f..a939dce 100644 --- a/priv/templates/gitignore +++ b/priv/templates/gitignore @@ -16,3 +16,4 @@ _deps _plugins _tdeps logs +_build
\ No newline at end of file diff --git a/rebar.config b/rebar.config index 504a462..b885002 100644 --- a/rebar.config +++ b/rebar.config @@ -10,7 +10,7 @@ {tag, "v1.3.1"}}}, {relx, "", {git, "https://github.com/erlware/relx.git", - {tag, "v2.0.0"}}}, + {branch, "master"}}}, {mustache, ".*", {git, "https://github.com/soranoba/mustache.git", {tag, "v0.3.0"}}}, @@ -1,6 +1,6 @@ [{<<"relx">>, {git,"https://github.com/erlware/relx.git", - {ref,"2e59b1c95575b3c104cc191e954c82baadc43c6c"}}, + {ref,"74fec3455ba6dbb7d9e369137c1b15ab10804993"}}, 0}, {<<"providers">>, {git,"https://github.com/tsloughter/providers.git", diff --git a/src/rebar3.erl b/src/rebar3.erl index 1a02407..523b8b0 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -141,7 +141,16 @@ init_config() -> ?DEBUG("Load global config file ~p", [GlobalConfigFile]), GlobalConfig = rebar_state:new(rebar_config:consult_file(GlobalConfigFile)), - rebar_state:new(GlobalConfig, Config1); + + %% We don't want to worry about global plugin install state effecting later + %% usage. So we throw away the global profile state used for plugin install. + GlobalConfigThrowAway = rebar_state:current_profiles(GlobalConfig, ["global"]), + rebar_plugins:handle_plugins(global, + rebar_state:get(GlobalConfigThrowAway, plugins, []), + GlobalConfigThrowAway), + + GlobalConfig2 = rebar_state:set(GlobalConfig, plugins, []), + rebar_state:new(GlobalConfig2, Config1); false -> rebar_state:new(Config1) end, diff --git a/src/rebar_dir.erl b/src/rebar_dir.erl index a94c72d..9bff2ab 100644 --- a/src/rebar_dir.erl +++ b/src/rebar_dir.erl @@ -20,7 +20,10 @@ template_dir/1, processing_base_dir/1, processing_base_dir/2, - make_relative_path/2]). + make_relative_path/2, + src_dirs/1, src_dirs/2, + extra_src_dirs/1, extra_src_dirs/2, + all_src_dirs/1, all_src_dirs/3]). -include("rebar.hrl"). @@ -30,14 +33,15 @@ base_dir(State) -> -spec profile_dir(rebar_state:t(), [atom()]) -> file:filename_all(). profile_dir(State, Profiles) -> - ProfilesStrings = case [ec_cnv:to_list(P) || P <- Profiles] of - ["default"] -> ["default"]; + {BaseDir, ProfilesStrings} = case [ec_cnv:to_list(P) || P <- Profiles] of + ["global"] -> {?MODULE:global_cache_dir(State), [""]}; + ["default"] -> {rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR), ["default"]}; %% drop `default` from the profile dir if it's implicit and reverse order %% of profiles to match order passed to `as` - ["default"|Rest] -> Rest + ["default"|Rest] -> {rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR), Rest} end, ProfilesDir = string:join(ProfilesStrings, "+"), - filename:join(rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR), ProfilesDir). + filename:join(BaseDir, ProfilesDir). -spec deps_dir(rebar_state:t()) -> file:filename_all(). @@ -81,11 +85,11 @@ global_config_dir(State) -> rebar_state:get(State, global_rebar_dir, filename:join([Home, ".config", "rebar3"])). global_config(State) -> - filename:join(global_config_dir(State), "config"). + filename:join(global_config_dir(State), "rebar.config"). global_config() -> Home = home_dir(), - filename:join([Home, ".config", "rebar3", "config"]). + filename:join([Home, ".config", "rebar3", "rebar.config"]). global_cache_dir(State) -> Home = home_dir(), @@ -120,3 +124,35 @@ do_make_relative_path([H|T1], [H|T2]) -> do_make_relative_path(Source, Target) -> Base = lists:duplicate(max(length(Target) - 1, 0), ".."), filename:join(Base ++ Source). + +-spec src_dirs(rebar_state:t()) -> list(file:filename_all()). +src_dirs(State) -> src_dirs(State, []). + +-spec src_dirs(rebar_state:t(), list(file:filename_all())) -> list(file:filename_all()). +src_dirs(State, Default) -> + ErlOpts = rebar_utils:erl_opts(State), + Vs = proplists:get_all_values(src_dirs, ErlOpts), + case lists:append(Vs) of + [] -> Default; + Dirs -> Dirs + end. + +-spec extra_src_dirs(rebar_state:t()) -> list(file:filename_all()). +extra_src_dirs(State) -> extra_src_dirs(State, []). + +-spec extra_src_dirs(rebar_state:t(), list(file:filename_all())) -> list(file:filename_all()). +extra_src_dirs(State, Default) -> + ErlOpts = rebar_utils:erl_opts(State), + Vs = proplists:get_all_values(extra_src_dirs, ErlOpts), + case lists:append(Vs) of + [] -> Default; + Dirs -> Dirs + end. + +-spec all_src_dirs(rebar_state:t()) -> list(file:filename_all()). +all_src_dirs(State) -> all_src_dirs(State, [], []). + +-spec all_src_dirs(rebar_state:t(), list(file:filename_all()), list(file:filename_all())) -> + list(file:filename_all()). +all_src_dirs(State, SrcDefault, ExtraDefault) -> + src_dirs(State, SrcDefault) ++ extra_src_dirs(State, ExtraDefault). diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index c7a3474..b9072a3 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -143,8 +143,7 @@ doterl_compile(Config, Dir, OutDir, MoreSources, ErlOpts) -> %% Support the src_dirs option allowing multiple directories to %% contain erlang source. This might be used, for example, should %% eunit tests be separated from the core application source. - SrcDirs = [filename:join(Dir, X) || X <- proplists:get_value(src_dirs, ErlOpts, ["src"]) ++ - proplists:get_value(extra_src_dirs, ErlOpts, [])], + SrcDirs = [filename:join(Dir, X) || X <- rebar_dir:all_src_dirs(Config, ["src"], [])], AllErlFiles = gather_src(SrcDirs, []) ++ MoreSources, %% Make sure that ebin/ exists and is on the path diff --git a/src/rebar_fetch.erl b/src/rebar_fetch.erl index 0aca308..64c5380 100644 --- a/src/rebar_fetch.erl +++ b/src/rebar_fetch.erl @@ -72,7 +72,7 @@ format_error({failed_extract, CachePath}) -> format_error({bad_etag, Source}) -> io_lib:format("MD5 Checksum comparison failed for: ~s", [Source]); format_error({fetch_fail, Source}) -> - io_lib:format("Failed to fetch and copy dep: ~s", [Source]); + io_lib:format("Failed to fetch and copy dep: ~p", [Source]); format_error({bad_checksum, File}) -> io_lib:format("Checksum mismatch against tarball in ~s", [File]); format_error({bad_registry_checksum, File}) -> diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl index e5ad1d2..c457999 100644 --- a/src/rebar_otp_app.erl +++ b/src/rebar_otp_app.erl @@ -160,9 +160,8 @@ ebin_modules(State, App, Dir) -> [rebar_utils:beam_to_mod(N) || N <- Filtered]. extra_dirs(State) -> - ErlOpts = rebar_utils:erl_opts(State), - Extras = proplists:get_value(extra_src_dirs, ErlOpts, []), - SrcDirs = proplists:get_value(src_dirs, ErlOpts, ["src"]), + Extras = rebar_dir:extra_src_dirs(State), + SrcDirs = rebar_dir:src_dirs(State, ["src"]), %% remove any dirs that are defined in `src_dirs` from `extra_src_dirs` Extras -- SrcDirs. diff --git a/src/rebar_plugins.erl b/src/rebar_plugins.erl index c16223e..d03ada0 100644 --- a/src/rebar_plugins.erl +++ b/src/rebar_plugins.erl @@ -3,7 +3,7 @@ -module(rebar_plugins). --export([install/1, handle_plugins/2]). +-export([install/1, handle_plugins/2, handle_plugins/3]). -include("rebar.hrl"). @@ -28,16 +28,24 @@ install(State) -> -spec handle_plugins([rebar_prv_install_deps:dep()], rebar_state:t()) -> rebar_state:t(). handle_plugins(Plugins, State) -> + handle_plugins(default, Plugins, State). + +handle_plugins(Profile, Plugins, State) -> + %% Set deps dir to plugins dir so apps are installed there + State1 = rebar_state:set(State, deps_dir, ?DEFAULT_PLUGINS_DIR), + PluginProviders = lists:flatmap(fun(Plugin) -> - handle_plugin(Plugin, State) + handle_plugin(Profile, Plugin, State1) end, Plugins), - rebar_state:create_logic_providers(PluginProviders, State). -handle_plugin(Plugin, State) -> + %% reset deps dir + State2 = rebar_state:set(State1, deps_dir, ?DEFAULT_DEPS_DIR), + + rebar_state:create_logic_providers(PluginProviders, State2). + +handle_plugin(Profile, Plugin, State) -> try - %% Set deps dir to plugins dir so apps are installed there - State1 = rebar_state:set(State, deps_dir, ?DEFAULT_PLUGINS_DIR), - {ok, _, State2} = rebar_prv_install_deps:handle_deps(default, State1, [Plugin]), + {ok, _, State2} = rebar_prv_install_deps:handle_deps(Profile, State, [Plugin]), Apps = rebar_state:all_deps(State2), ToBuild = lists:dropwhile(fun rebar_app_info:valid/1, Apps), @@ -46,7 +54,7 @@ handle_plugin(Plugin, State) -> plugin_providers(Plugin) catch C:T -> - ?DEBUG("~p ~p", [C, T]), + ?DEBUG("~p ~p ~p", [C, T, erlang:get_stacktrace()]), ?WARN("Plugin ~p not available. It will not be used.", [Plugin]), [] end. diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index eb51d8d..af77fa2 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -38,7 +38,7 @@ init(State) -> -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. do(State) -> ?INFO("Running Common Test suites...", []), - code:add_pathsa(rebar_state:code_paths(State, all_deps)), + rebar_utils:update_code(rebar_state:code_paths(State, all_deps)), %% Run ct provider prehooks Providers = rebar_state:providers(State), @@ -49,7 +49,7 @@ do(State) -> {ok, State1} = Result -> %% Run ct provider posthooks rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State1), - rebar_utils:cleanup_code_path(rebar_state:code_paths(State1, default)), + rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)), Result; ?PRV_ERROR(_) = Error -> rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)), @@ -303,7 +303,7 @@ copy(State, Dir) -> compile_dir(State, Dir, OutDir) -> NewState = replace_src_dirs(State, [Dir]), - ok = rebar_erlc_compiler:compile(NewState, rebar_state:dir(State), OutDir), + ok = rebar_erlc_compiler:compile(NewState, rebar_dir:base_dir(State), OutDir), ok = maybe_cover_compile(State, Dir), OutDir. @@ -368,8 +368,11 @@ sub_dirs(Path) -> replace_src_dirs(State, Dirs) -> %% replace any `src_dirs` with the test dirs ErlOpts = rebar_state:get(State, erl_opts, []), - StrippedOpts = lists:keydelete(src_dirs, 1, ErlOpts), - rebar_state:set(State, erl_opts, [{src_dirs, Dirs}|StrippedOpts]). + StrippedOpts = filter_src_dirs(ErlOpts), + rebar_state:set(State, erl_opts, [{extra_src_dirs, Dirs}|StrippedOpts]). + +filter_src_dirs(ErlOpts) -> + lists:filter(fun({src_dirs, _}) -> false; ({extra_src_dirs, _}) -> false; (_) -> true end, ErlOpts). test_dirs(State, Opts) -> BareTest = filename:join([rebar_state:dir(State), "test"]), diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl index 704a9f0..1dff4d8 100644 --- a/src/rebar_prv_compile.erl +++ b/src/rebar_prv_compile.erl @@ -119,9 +119,7 @@ copy_app_dirs(State, OldAppDir, AppDir) -> end, filelib:ensure_dir(filename:join(AppDir, "dummy")), %% link to src_dirs to be adjacent to ebin is needed for R15 use of cover/xref - ErlOpts = rebar_utils:erl_opts(State), - SrcDirs = proplists:get_value(src_dirs, ErlOpts, ["src"]) ++ - proplists:get_value(extra_src_dirs, ErlOpts, []), + SrcDirs = rebar_dir:all_src_dirs(State, ["src"], ["test"]), [symlink_or_copy(OldAppDir, AppDir, Dir) || Dir <- ["priv", "include"] ++ SrcDirs]; false -> ok diff --git a/src/rebar_prv_eunit.erl b/src/rebar_prv_eunit.erl index 8eaa926..3ad593d 100644 --- a/src/rebar_prv_eunit.erl +++ b/src/rebar_prv_eunit.erl @@ -37,7 +37,8 @@ init(State) -> -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. do(State) -> ?INFO("Performing EUnit tests...", []), - code:add_pathsa(rebar_state:code_paths(State, all_deps)), + rebar_utils:update_code(rebar_state:code_paths(State, all_deps)), + %% Run eunit provider prehooks Providers = rebar_state:providers(State), Cwd = rebar_dir:get_cwd(), @@ -49,7 +50,7 @@ do(State) -> {ok, State1} -> %% Run eunit provider posthooks rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State1), - rebar_utils:cleanup_code_path(rebar_state:code_paths(State1, default)), + rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)), {ok, State1}; Error -> rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)), @@ -84,8 +85,7 @@ format_error({error_running_tests, Reason}) -> test_state(State) -> ErlOpts = rebar_state:get(State, eunit_compile_opts, []), TestOpts = safe_define_test_macro(ErlOpts), - TestDir = [{extra_src_dirs, ["test"]}], - first_files(State) ++ [{erl_opts, TestOpts ++ TestDir}]. + first_files(State) ++ [{erl_opts, TestOpts}]. safe_define_test_macro(Opts) -> %% defining a compile macro twice results in an exception so @@ -106,38 +106,56 @@ first_files(State) -> prepare_tests(State) -> {RawOpts, _} = rebar_state:command_parsed_args(State), - ok = maybe_cover_compile(State, RawOpts), - ProjectApps = project_apps(State), - resolve_apps(ProjectApps, RawOpts). - -maybe_cover_compile(State, Opts) -> - State1 = case proplists:get_value(cover, Opts, false) of - true -> rebar_state:set(State, cover_enabled, true); - false -> State - end, - rebar_prv_cover:maybe_cover_compile(State1). + resolve_apps(State, RawOpts). -resolve_apps(ProjectApps, RawOpts) -> +resolve_apps(State, RawOpts) -> case proplists:get_value(app, RawOpts) of - undefined -> resolve_suites(ProjectApps, RawOpts); + undefined -> resolve_suites(State, RawOpts); %% convert app name strings to `rebar_app_info` objects Apps -> AppNames = string:tokens(Apps, [$,]), + ProjectApps = project_apps(State), case filter_apps_by_name(AppNames, ProjectApps) of - {ok, TestApps} -> resolve_suites(TestApps, RawOpts); + {ok, TestApps} -> resolve_suites(State, TestApps, RawOpts); Error -> Error end end. -resolve_suites(Apps, RawOpts) -> +resolve_suites(State, RawOpts) -> resolve_suites(State, project_apps(State), RawOpts). + +resolve_suites(State, Apps, RawOpts) -> case proplists:get_value(suite, RawOpts) of - undefined -> test_set(Apps, all); + undefined -> compile_tests(State, Apps, all, RawOpts); Suites -> SuiteNames = string:tokens(Suites, [$,]), case filter_suites_by_apps(SuiteNames, Apps) of - {ok, S} -> test_set(Apps, S); + {ok, S} -> compile_tests(State, Apps, S, RawOpts); Error -> Error end end. +compile_tests(State, TestApps, Suites, RawOpts) -> + F = fun(AppInfo) -> + AppDir = rebar_app_info:dir(AppInfo), + S = case rebar_app_info:state(AppInfo) of + undefined -> + C = rebar_config:consult(AppDir), + rebar_state:new(State, C, AppDir); + AppState -> + AppState + end, + ok = rebar_erlc_compiler:compile(replace_src_dirs(S), + ec_cnv:to_list(rebar_app_info:out_dir(AppInfo))) + end, + lists:foreach(F, TestApps), + ok = maybe_cover_compile(State, RawOpts), + {ok, test_set(TestApps, Suites)}. + +maybe_cover_compile(State, Opts) -> + State1 = case proplists:get_value(cover, Opts, false) of + true -> rebar_state:set(State, cover_enabled, true); + false -> State + end, + rebar_prv_cover:maybe_cover_compile(State1). + project_apps(State) -> filter_checkouts(rebar_state:project_apps(State)). @@ -204,8 +222,20 @@ app_modules([App|Rest], Acc) -> app_modules(Rest, NewAcc) end. -test_set(Apps, all) -> {ok, set_apps(Apps, [])}; -test_set(_Apps, Suites) -> {ok, set_suites(Suites, [])}. +replace_src_dirs(State) -> + %% replace any `src_dirs` with the test dirs + ErlOpts = rebar_state:get(State, erl_opts, []), + StrippedOpts = filter_src_dirs(ErlOpts), + case rebar_dir:extra_src_dirs(State) of + [] -> rebar_state:set(State, erl_opts, [{src_dirs, ["test"]}|StrippedOpts]); + _ -> rebar_state:set(State, erl_opts, StrippedOpts) + end. + +filter_src_dirs(ErlOpts) -> + lists:filter(fun({src_dirs, _}) -> false; (_) -> true end, ErlOpts). + +test_set(Apps, all) -> set_apps(Apps, []); +test_set(_Apps, Suites) -> set_suites(Suites, []). set_apps([], Acc) -> lists:reverse(Acc); set_apps([App|Rest], Acc) -> diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl index ba49532..2d69aa9 100644 --- a/src/rebar_prv_install_deps.erl +++ b/src/rebar_prv_install_deps.erl @@ -380,7 +380,6 @@ handle_dep(State, DepsDir, AppInfo, Locks, Level) -> %% Dep may have plugins to install. Find and install here. State1 = rebar_plugins:handle_plugins(rebar_state:get(S3, plugins, []), State), - Deps = rebar_state:get(S3, deps, []), %% Upgrade lock level to be the level the dep will have in this dep tree NewLocks = [{DepName, Source, LockLevel+Level} || @@ -432,7 +431,7 @@ maybe_fetch(AppInfo, Profile, Upgrade, Seen, State) -> already_in_default(AppInfo, State) -> Name = ec_cnv:to_list(rebar_app_info:name(AppInfo)), - DefaultAppDir = filename:join([rebar_state:get(State, base_dir), "default", "lib", Name]), + DefaultAppDir = filename:join([rebar_state:get(State, base_dir, []), "default", "lib", Name]), rebar_app_discover:find_app(DefaultAppDir, all). needs_symlinking(State, Profile) -> diff --git a/src/rebar_state.erl b/src/rebar_state.erl index 7a6e60d..55081a5 100644 --- a/src/rebar_state.erl +++ b/src/rebar_state.erl @@ -12,7 +12,7 @@ lock/1, lock/2, - current_profiles/1, + current_profiles/1, current_profiles/2, command_args/1, command_args/2, command_parsed_args/1, command_parsed_args/2, @@ -51,7 +51,7 @@ namespace = undefined :: atom(), command_args = [], - command_parsed_args = [], + command_parsed_args = {[], []}, project_apps = [] :: [rebar_app_info:t()], deps_to_build = [] :: [rebar_app_info:t()], @@ -175,6 +175,9 @@ opts(State, Opts) -> current_profiles(#state_t{current_profiles=Profiles}) -> Profiles. +current_profiles(State, Profiles) -> + State#state_t{current_profiles=Profiles}. + lock(#state_t{lock=Lock}) -> Lock. diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 160d547..ffa29e6 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -47,6 +47,7 @@ deprecated/4, erl_opts/1, indent/1, + update_code/1, cleanup_code_path/1, args_to_tasks/1, expand_env_variable/3, @@ -563,6 +564,23 @@ filter_defines([Opt | Rest], Acc) -> indent(Amount) when erlang:is_integer(Amount) -> [?ONE_LEVEL_INDENT || _ <- lists:seq(1, Amount)]. +%% Replace code paths with new paths for existing apps and +%% purge code of the old modules from those apps. +update_code(Paths) -> + lists:foreach(fun(Path) -> + Name = filename:basename(Path, "/ebin"), + App = list_to_atom(Name), + application:load(App), + case application:get_key(App, modules) of + undefined -> + code:add_patha(Path), + ok; + {ok, Modules} -> + code:replace_path(Name, Path), + [begin code:purge(M), code:delete(M) end || M <- Modules] + end + end, Paths). + cleanup_code_path(OrigPath) -> CurrentPath = code:get_path(), AddedPaths = CurrentPath -- OrigPath, diff --git a/test/rebar_compile_SUITE.erl b/test/rebar_compile_SUITE.erl index bdab075..2dc57c5 100644 --- a/test/rebar_compile_SUITE.erl +++ b/test/rebar_compile_SUITE.erl @@ -19,6 +19,7 @@ delete_beam_if_source_deleted/1, checkout_priority/1, compile_plugins/1, + compile_global_plugins/1, highest_version_of_pkg_dep/1, parse_transform_test/1]). @@ -47,8 +48,8 @@ all() -> build_all_srcdirs, recompile_when_hrl_changes, recompile_when_opts_change, dont_recompile_when_opts_dont_change, dont_recompile_yrl_or_xrl, delete_beam_if_source_deleted, - deps_in_path, checkout_priority, compile_plugins, highest_version_of_pkg_dep, - parse_transform_test]. + deps_in_path, checkout_priority, compile_plugins, compile_global_plugins, + highest_version_of_pkg_dep, parse_transform_test]. build_basic_app(Config) -> AppDir = ?config(apps, Config), @@ -427,6 +428,58 @@ compile_plugins(Config) -> {ok, [{app, Name}, {plugin, PluginName}, {dep, DepName}]} ). +%% Tests that compiling a project installs and compiles the global plugins +compile_global_plugins(Config) -> + AppDir = ?config(apps, Config), + GlobalDir = filename:join(AppDir, "global"), + GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]), + GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]), + + meck:new(rebar_dir, [passthrough]), + meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end), + meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end), + + Name = rebar_test_utils:create_random_name("app1_"), + Vsn = rebar_test_utils:create_random_vsn(), + Vsn2 = rebar_test_utils:create_random_vsn(), + rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + + DepName = rebar_test_utils:create_random_name("dep1_"), + PluginName = rebar_test_utils:create_random_name("plugin1_"), + + mock_git_resource:mock([{deps, [{list_to_atom(PluginName), Vsn}, + {list_to_atom(PluginName), Vsn2}, + {{iolist_to_binary(DepName), iolist_to_binary(Vsn)}, []}]}]), + + + rebar_test_utils:create_config(GlobalConfigDir, + [{plugins, [ + {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn}}} + ]}]), + RConfFile = + rebar_test_utils:create_config(AppDir, + [{deps, [ + {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}} + ]}, + {plugins, [ + {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn2}}} + ]}]), + {ok, RConf} = file:consult(RConfFile), + + %% Runs global plugin install + rebar3:init_config(), + + %% Build with deps. + rebar_test_utils:run_and_check( + Config, RConf, ["compile"], + {ok, [{app, Name}, + {global_plugin, PluginName, Vsn}, + {plugin, PluginName, Vsn2}, + {dep, DepName}]} + ), + + meck:unload(rebar_dir). + highest_version_of_pkg_dep(Config) -> AppDir = ?config(apps, Config), diff --git a/test/rebar_dir_SUITE.erl b/test/rebar_dir_SUITE.erl new file mode 100644 index 0000000..a3c5052 --- /dev/null +++ b/test/rebar_dir_SUITE.erl @@ -0,0 +1,99 @@ +-module(rebar_dir_SUITE). + +-export([all/0, init_per_testcase/2, end_per_testcase/2]). + +-export([default_src_dirs/1, default_extra_src_dirs/1, default_all_src_dirs/1]). +-export([src_dirs/1, extra_src_dirs/1, all_src_dirs/1]). +-export([profile_src_dirs/1, profile_extra_src_dirs/1, profile_all_src_dirs/1]). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("kernel/include/file.hrl"). + + +all() -> [default_src_dirs, default_extra_src_dirs, default_all_src_dirs, + src_dirs, extra_src_dirs, all_src_dirs, + profile_src_dirs, profile_extra_src_dirs, profile_all_src_dirs]. + +init_per_testcase(_, Config) -> + C = rebar_test_utils:init_rebar_state(Config), + AppDir = ?config(apps, C), + + Name = rebar_test_utils:create_random_name("app1_"), + Vsn = rebar_test_utils:create_random_vsn(), + rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + C. + +end_per_testcase(_, _Config) -> ok. + +default_src_dirs(Config) -> + {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return), + + [] = rebar_dir:src_dirs(State), + ["src"] = rebar_dir:src_dirs(State, ["src"]). + +default_extra_src_dirs(Config) -> + {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return), + + [] = rebar_dir:extra_src_dirs(State), + ["src"] = rebar_dir:extra_src_dirs(State, ["src"]). + +default_all_src_dirs(Config) -> + {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return), + + [] = rebar_dir:all_src_dirs(State), + ["src", "test"] = rebar_dir:all_src_dirs(State, ["src"], ["test"]). + +src_dirs(Config) -> + RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar", "baz"]}]}], + {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), + + ["foo", "bar", "baz"] = rebar_dir:src_dirs(State). + +extra_src_dirs(Config) -> + RebarConfig = [{erl_opts, [{extra_src_dirs, ["foo", "bar", "baz"]}]}], + {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), + + ["foo", "bar", "baz"] = rebar_dir:extra_src_dirs(State). + +all_src_dirs(Config) -> + RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}, {extra_src_dirs, ["baz", "qux"]}]}], + {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), + + ["foo", "bar", "baz", "qux"] = rebar_dir:all_src_dirs(State). + +profile_src_dirs(Config) -> + RebarConfig = [ + {erl_opts, [{src_dirs, ["foo", "bar"]}]}, + {profiles, [ + {more, [{erl_opts, [{src_dirs, ["baz", "qux"]}]}]} + ]} + ], + {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "more", "compile"], return), + + R = lists:sort(["foo", "bar", "baz", "qux"]), + R = lists:sort(rebar_dir:src_dirs(State)). + +profile_extra_src_dirs(Config) -> + RebarConfig = [ + {erl_opts, [{extra_src_dirs, ["foo", "bar"]}]}, + {profiles, [ + {more, [{erl_opts, [{extra_src_dirs, ["baz", "qux"]}]}]} + ]} + ], + {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "more", "compile"], return), + + R = lists:sort(["foo", "bar", "baz", "qux"]), + R = lists:sort(rebar_dir:extra_src_dirs(State)). + +profile_all_src_dirs(Config) -> + RebarConfig = [ + {erl_opts, [{src_dirs, ["foo"]}, {extra_src_dirs, ["bar"]}]}, + {profiles, [ + {more, [{erl_opts, [{src_dirs, ["baz"]}, {extra_src_dirs, ["qux"]}]}]} + ]} + ], + {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "more", "compile"], return), + + R = lists:sort(["foo", "bar", "baz", "qux"]), + R = lists:sort(rebar_dir:all_src_dirs(State)). diff --git a/test/rebar_test_utils.erl b/test/rebar_test_utils.erl index 2cdc58b..c4dc663 100644 --- a/test/rebar_test_utils.erl +++ b/test/rebar_test_utils.erl @@ -160,6 +160,7 @@ top_level_deps([{{Name, Vsn, Ref}, _} | Deps]) -> check_results(AppDir, Expected) -> BuildDirs = filelib:wildcard(filename:join([AppDir, "_build", "*", "lib"])), PluginDirs = filelib:wildcard(filename:join([AppDir, "_build", "*", "plugins"])), + GlobalPluginDirs = filelib:wildcard(filename:join([AppDir, "global", "plugins"])), CheckoutsDir = filename:join([AppDir, "_checkouts"]), LockFile = filename:join([AppDir, "rebar.lock"]), Locks = lists:flatten(rebar_config:consult_file(LockFile)), @@ -176,6 +177,8 @@ check_results(AppDir, Expected) -> CheckoutsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Checkouts], Plugins = rebar_app_discover:find_apps(PluginDirs, all), PluginsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Plugins], + GlobalPlugins = rebar_app_discover:find_apps(GlobalPluginDirs, all), + GlobalPluginsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- GlobalPlugins], lists:foreach( fun({app, Name}) -> @@ -224,7 +227,19 @@ check_results(AppDir, Expected) -> ct:pal("Name: ~p, Vsn: ~p", [Name, Vsn]), case lists:keyfind(Name, 1, PluginsNames) of false -> - error({dep_not_found, Name}); + error({plugin_not_found, Name}); + {Name, App} -> + ?assertEqual(iolist_to_binary(Vsn), + iolist_to_binary(rebar_app_info:original_vsn(App))) + end + ; ({global_plugin, Name}) -> + ct:pal("Name: ~p", [Name]), + ?assertNotEqual(false, lists:keyfind(Name, 1, GlobalPluginsNames)) + ; ({global_plugin, Name, Vsn}) -> + ct:pal("Name: ~p, Vsn: ~p", [Name, Vsn]), + case lists:keyfind(Name, 1, GlobalPluginsNames) of + false -> + error({global_plugin_not_found, Name}); {Name, App} -> ?assertEqual(iolist_to_binary(Vsn), iolist_to_binary(rebar_app_info:original_vsn(App))) |