diff options
-rwxr-xr-x | bootstrap | 24 | ||||
-rw-r--r-- | rebar.config | 11 | ||||
-rw-r--r-- | rebar.lock | 8 | ||||
-rw-r--r-- | src/rebar3.erl | 4 | ||||
-rw-r--r-- | src/rebar_app_discover.erl | 121 | ||||
-rw-r--r-- | src/rebar_app_info.erl | 13 | ||||
-rw-r--r-- | src/rebar_config.erl | 10 | ||||
-rw-r--r-- | src/rebar_packages.erl | 4 | ||||
-rw-r--r-- | src/rebar_prv_clean.erl | 3 | ||||
-rw-r--r-- | src/rebar_prv_common_test.erl | 27 | ||||
-rw-r--r-- | src/rebar_prv_escriptize.erl | 23 | ||||
-rw-r--r-- | src/rebar_prv_eunit.erl | 17 | ||||
-rw-r--r-- | src/rebar_prv_path.erl | 4 | ||||
-rw-r--r-- | src/rebar_prv_plugins.erl | 11 | ||||
-rw-r--r-- | src/rebar_prv_upgrade.erl | 2 | ||||
-rw-r--r-- | src/rebar_templater.erl | 11 | ||||
-rw-r--r-- | src/rebar_utils.erl | 2 | ||||
-rw-r--r-- | test/rebar_compile_SUITE.erl | 46 | ||||
-rw-r--r-- | test/rebar_ct_SUITE.erl | 41 | ||||
-rw-r--r-- | test/rebar_eunit_SUITE.erl | 5 | ||||
-rw-r--r-- | test/rebar_src_dirs_SUITE.erl | 98 | ||||
-rw-r--r-- | test/rebar_test_utils.erl | 4 |
22 files changed, 357 insertions, 132 deletions
@@ -52,21 +52,7 @@ main(_) -> rebar3:run(["escriptize"]), %% Done with compile, can turn back on error logger - error_logger:tty(true), - - %% Finally, update executable perms for our script on *nix, - %% or write out script files on win32. - ec_file:copy("_build/default/bin/rebar3", "./rebar3"), - case os:type() of - {unix,_} -> - [] = os:cmd("chmod u+x rebar3"), - ok; - {win32,_} -> - write_windows_scripts(), - ok; - _ -> - ok - end. + error_logger:tty(true). default_registry_file() -> {ok, [[Home]]} = init:get_argument(home), @@ -305,14 +291,6 @@ reset_env() -> application:unload(rebar), application:load(rebar). -write_windows_scripts() -> - CmdScript= - "@echo off\r\n" - "setlocal\r\n" - "set rebarscript=%~f0\r\n" - "escript.exe \"%rebarscript:.cmd=%\" %*\r\n", - ok = file:write_file("rebar3.cmd", CmdScript). - get_deps() -> case file:consult("rebar.lock") of {ok, [[]]} -> diff --git a/rebar.config b/rebar.config index 1d853c4..36ef8c7 100644 --- a/rebar.config +++ b/rebar.config @@ -7,14 +7,19 @@ {providers, "1.6.0"}, {getopt, "0.8.2"}, {bbmustache, "1.3.0"}, - {relx, "3.22.2"}, + {relx, "3.22.3"}, {cf, "0.2.2"}, - {cth_readable, "1.2.3"}, + {cth_readable, "1.2.4"}, {eunit_formatters, "0.3.1"}]}. {post_hooks, [{"(linux|darwin|solaris|freebsd|netbsd|openbsd)", escriptize, - "cp $REBAR_BUILD_DIR/bin/rebar3 ./rebar3 && chmod u+x rebar3"}]}. + "cp \"$REBAR_BUILD_DIR/bin/rebar3\" ./rebar3"}, + {"win32", + escriptize, + "robocopy \"%REBAR_BUILD_DIR%/bin/\" ./ rebar3* " + "/njs /njh /nfl /ndl & exit /b 0"} % silence things + ]}. {escript_name, rebar3}. {escript_emu_args, "%%! +sbtu +A0\n"}. @@ -2,23 +2,23 @@ [{<<"bbmustache">>,{pkg,<<"bbmustache">>,<<"1.3.0">>},0}, {<<"certifi">>,{pkg,<<"certifi">>,<<"0.4.0">>},0}, {<<"cf">>,{pkg,<<"cf">>,<<"0.2.2">>},0}, - {<<"cth_readable">>,{pkg,<<"cth_readable">>,<<"1.2.3">>},0}, + {<<"cth_readable">>,{pkg,<<"cth_readable">>,<<"1.2.4">>},0}, {<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"1.0.0">>},0}, {<<"eunit_formatters">>,{pkg,<<"eunit_formatters">>,<<"0.3.1">>},0}, {<<"getopt">>,{pkg,<<"getopt">>,<<"0.8.2">>},0}, {<<"providers">>,{pkg,<<"providers">>,<<"1.6.0">>},0}, - {<<"relx">>,{pkg,<<"relx">>,<<"3.22.2">>},0}, + {<<"relx">>,{pkg,<<"relx">>,<<"3.22.3">>},0}, {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.1">>},0}]}. [ {pkg_hash,[ {<<"bbmustache">>, <<"2010ADAE78830992A4C69680115ECD7D475DD03A72C076BBADDCCBF2D4B32035">>}, {<<"certifi">>, <<"A7966EFB868B179023618D29A407548F70C52466BF1849B9E8EBD0E34B7EA11F">>}, {<<"cf">>, <<"7F2913FFF90ABCABD0F489896CFEB0B0674F6C8DF6C10B17A83175448029896C">>}, - {<<"cth_readable">>, <<"293120673DFF82F0768612C5282E35C40CACC1B6F94FE99077438FD3749D0E27">>}, + {<<"cth_readable">>, <<"F89D353BA7D6C9D7F8141AF5CE4CB7E796F214B75766960DF480AB2B339C43CE">>}, {<<"erlware_commons">>, <<"087467DE5833C0BB5B3CCDD387F9E9C1FB816A75B7A709629BF24B5ED3246C51">>}, {<<"eunit_formatters">>, <<"7A6FC351EB5B873E2356B8852EB751E20C13A72FBCA03393CF682B8483509573">>}, {<<"getopt">>, <<"B17556DB683000BA50370B16C0619DF1337E7AF7ECBF7D64FBF8D1D6BCE3109B">>}, {<<"providers">>, <<"DB0E2F9043AE60C0155205FCD238D68516331D0E5146155E33D1E79DC452964A">>}, - {<<"relx">>, <<"AEE2EF6E9AC6D21D6661133B7A0BE6E81424DE9CDCA0012FC008BC677297C469">>}, + {<<"relx">>, <<"36CB10F463E3834CE7BAF685F18D80D6B415BA9B227649E1140D091077A55246">>}, {<<"ssl_verify_fun">>, <<"28A4D65B7F59893BC2C7DE786DEC1E1555BD742D336043FE644AE956C3497FBE">>}]} ]. diff --git a/src/rebar3.erl b/src/rebar3.erl index 56bf3e8..1e1d0b0 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -176,7 +176,7 @@ init_config() -> Verbosity = log_level(), ok = rebar_log:init(command_line, Verbosity), - Config = rebar_config:consult(), + Config = rebar_config:consult_root(), Config1 = rebar_config:merge_locks(Config, rebar_config:consult_lock_file(?LOCK_FILE)), %% If $HOME/.config/rebar3/rebar.config exists load and use as global config @@ -344,7 +344,7 @@ start_and_load_apps(Caller) -> ensure_running(asn1, Caller), ensure_running(public_key, Caller), ensure_running(ssl, Caller), - inets:start(), + ensure_running(inets, Caller), inets:start(httpc, [{profile, rebar}]). %% @doc Make sure a required app is running, or display an error message diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl index fd55960..db74cd3 100644 --- a/src/rebar_app_discover.erl +++ b/src/rebar_app_discover.erl @@ -7,8 +7,10 @@ find_unbuilt_apps/1, find_apps/1, find_apps/2, + find_apps/3, find_app/2, - find_app/3]). + find_app/3, + find_app/4]). -include("rebar.hrl"). -include_lib("providers/include/providers.hrl"). @@ -20,7 +22,9 @@ do(State, LibDirs) -> BaseDir = rebar_state:dir(State), Dirs = [filename:join(BaseDir, LibDir) || LibDir <- LibDirs], - Apps = find_apps(Dirs, all), + RebarOpts = rebar_state:opts(State), + SrcDirs = rebar_dir:src_dirs(RebarOpts, ["src"]), + Apps = find_apps(Dirs, SrcDirs, all), ProjectDeps = rebar_state:deps_names(State), DepsDir = rebar_dir:deps_dir(State), CurrentProfiles = rebar_state:current_profiles(State), @@ -179,32 +183,44 @@ reset_hooks(Opts) -> rebar_opts:set(OptsAcc, Key, []) end, Opts, [post_hooks, pre_hooks, provider_hooks, artifacts]). -%% @doc find the directories for all apps --spec all_app_dirs([file:name()]) -> [file:name()]. +%% @private find the directories for all apps, while detecting their source dirs +%% Returns the app dir with the respective src_dirs for them, in that order, +%% for every app found. +-spec all_app_dirs([file:name()]) -> [{file:name(), [file:name()]}]. all_app_dirs(LibDirs) -> lists:flatmap(fun(LibDir) -> - app_dirs(LibDir) + SrcDirs = find_config_src(LibDir, ["src"]), + app_dirs(LibDir, SrcDirs) end, LibDirs). -%% @doc find the directories based on the library directories --spec app_dirs([file:name()]) -> [file:name()]. -app_dirs(LibDir) -> - Path1 = filename:join([LibDir, - "src", - "*.app.src"]), - - Path2 = filename:join([LibDir, - "src", - "*.app.src.script"]), - - Path3 = filename:join([LibDir, - "ebin", - "*.app"]), +%% @private find the directories for all apps based on their source dirs +%% Returns the app dir with the respective src_dirs for them, in that order, +%% for every app found. +-spec all_app_dirs([file:name()], [file:name()]) -> [{file:name(), [file:name()]}]. +all_app_dirs(LibDirs, SrcDirs) -> + lists:flatmap(fun(LibDir) -> app_dirs(LibDir, SrcDirs) end, LibDirs). + +%% @private find the directories based on the library directories. +%% Returns the app dir with the respective src_dirs for them, in that order, +%% for every app found. +%% +%% The function returns the src directories since they might have been +%% detected in a top-level loop and we want to skip further detection +%% starting now. +-spec app_dirs([file:name()], [file:name()]) -> [{file:name(), [file:name()]}]. +app_dirs(LibDir, SrcDirs) -> + Paths = lists:append([ + [filename:join([LibDir, SrcDir, "*.app.src"]), + filename:join([LibDir, SrcDir, "*.app.src.script"])] + || SrcDir <- SrcDirs + ]), + EbinPath = filename:join([LibDir, "ebin", "*.app"]), lists:usort(lists:foldl(fun(Path, Acc) -> - Files = filelib:wildcard(ec_cnv:to_list(Path)), - [app_dir(File) || File <- Files] ++ Acc - end, [], [Path1, Path2, Path3])). + Files = filelib:wildcard(ec_cnv:to_list(Path)), + [{app_dir(File), SrcDirs} + || File <- Files] ++ Acc + end, [], [EbinPath | Paths])). %% @doc find all apps that haven't been built in a list of directories -spec find_unbuilt_apps([file:filename_all()]) -> [rebar_app_info:t()]. @@ -222,16 +238,32 @@ find_apps(LibDirs) -> %% app info records. -spec find_apps([file:filename_all()], valid | invalid | all) -> [rebar_app_info:t()]. find_apps(LibDirs, Validate) -> - rebar_utils:filtermap(fun(AppDir) -> - find_app(AppDir, Validate) - end, all_app_dirs(LibDirs)). + rebar_utils:filtermap( + fun({AppDir, AppSrcDirs}) -> + find_app(rebar_app_info:new(), AppDir, AppSrcDirs, Validate) + end, + all_app_dirs(LibDirs) + ). + +%% @doc for each directory passed, with the configured source directories, +%% find all apps according to the validity rule passed in. +%% Returns all the related app info records. +-spec find_apps([file:filename_all()], [file:filename_all()], valid | invalid | all) -> [rebar_app_info:t()]. +find_apps(LibDirs, SrcDirs, Validate) -> + rebar_utils:filtermap( + fun({AppDir, AppSrcDirs}) -> + find_app(rebar_app_info:new(), AppDir, AppSrcDirs, Validate) + end, + all_app_dirs(LibDirs, SrcDirs) + ). %% @doc check that a given app in a directory is there, and whether it's %% valid or not based on the second argument. Returns the related %% app info record. -spec find_app(file:filename_all(), valid | invalid | all) -> {true, rebar_app_info:t()} | false. find_app(AppDir, Validate) -> - find_app(rebar_app_info:new(), AppDir, Validate). + SrcDirs = find_config_src(AppDir, ["src"]), + find_app(rebar_app_info:new(), AppDir, SrcDirs, Validate). %% @doc check that a given app in a directory is there, and whether it's %% valid or not based on the second argument. Returns the related @@ -239,9 +271,29 @@ find_app(AppDir, Validate) -> -spec find_app(rebar_app_info:t(), file:filename_all(), valid | invalid | all) -> {true, rebar_app_info:t()} | false. find_app(AppInfo, AppDir, Validate) -> + %% if no src dir is passed, figure it out from the app info, with a default + %% of src/ + AppOpts = rebar_app_info:opts(AppInfo), + SrcDirs = rebar_dir:src_dirs(AppOpts, ["src"]), + find_app(AppInfo, AppDir, SrcDirs, Validate). + +%% @doc check that a given app in a directory is there, and whether it's +%% valid or not based on the second argument. The third argument includes +%% the directories where source files can be located. Returns the related +%% app info record. +-spec find_app(rebar_app_info:t(), file:filename_all(), + [file:filename_all()], valid | invalid | all) -> + {true, rebar_app_info:t()} | false. +find_app(AppInfo, AppDir, SrcDirs, Validate) -> AppFile = filelib:wildcard(filename:join([AppDir, "ebin", "*.app"])), - AppSrcFile = filelib:wildcard(filename:join([AppDir, "src", "*.app.src"])), - AppSrcScriptFile = filelib:wildcard(filename:join([AppDir, "src", "*.app.src.script"])), + AppSrcFile = lists:append( + [filelib:wildcard(filename:join([AppDir, SrcDir, "*.app.src"])) + || SrcDir <- SrcDirs] + ), + AppSrcScriptFile = lists:append( + [filelib:wildcard(filename:join([AppDir, SrcDir, "*.app.src.script"])) + || SrcDir <- SrcDirs] + ), try_handle_app_file(AppInfo, AppFile, AppDir, AppSrcFile, AppSrcScriptFile, Validate). %% @doc find the directory that an appfile has @@ -358,3 +410,16 @@ enable(State, AppInfo) -> -spec to_atom(binary()) -> atom(). to_atom(Bin) -> list_to_atom(binary_to_list(Bin)). + +%% @private when looking for unknown apps, it's possible they have a +%% rebar.config file specifying non-standard src_dirs. Check for a +%% possible config file and extract src_dirs from it. +find_config_src(AppDir, Default) -> + case rebar_config:consult(AppDir) of + [] -> + Default; + Terms -> + %% TODO: handle profiles I guess, but we don't have that info + proplists:get_value(src_dirs, Terms, Default) + end. + diff --git a/src/rebar_app_info.erl b/src/rebar_app_info.erl index fdaadb8..62ec6dd 100644 --- a/src/rebar_app_info.erl +++ b/src/rebar_app_info.erl @@ -248,13 +248,12 @@ set(AppInfo=#app_info_t{opts=Opts}, Key, Value) -> %% @doc finds the .app.src file for an app, if any. -spec app_file_src(t()) -> file:filename_all() | undefined. -app_file_src(#app_info_t{app_file_src=undefined, dir=Dir, name=Name}) -> - AppFileSrc = filename:join([ec_cnv:to_list(Dir), "src", ec_cnv:to_list(Name)++".app.src"]), - case filelib:is_file(AppFileSrc) of - true -> - AppFileSrc; - false -> - undefined +app_file_src(#app_info_t{app_file_src=undefined, dir=Dir, name=Name, opts=Opts}) -> + CandidatePaths = [filename:join([ec_cnv:to_list(Dir), Src, ec_cnv:to_list(Name)++".app.src"]) + || Src <- rebar_opts:get(Opts, src_dirs, ["src"])], + case lists:dropwhile(fun(Path) -> not filelib:is_file(Path) end, CandidatePaths) of + [] -> undefined; + [AppFileSrc|_] -> AppFileSrc end; app_file_src(#app_info_t{app_file_src=AppFileSrc}) -> ec_cnv:to_list(AppFileSrc). diff --git a/src/rebar_config.erl b/src/rebar_config.erl index 97e27ab..82ff0d9 100644 --- a/src/rebar_config.erl +++ b/src/rebar_config.erl @@ -26,7 +26,7 @@ %% ------------------------------------------------------------------- -module(rebar_config). --export([consult/0 +-export([consult_root/0 ,consult/1 ,consult_app_file/1 ,consult_file/1 @@ -46,15 +46,15 @@ %% Public API %% =================================================================== -%% @doc reads the default config file. --spec consult() -> [any()]. -consult() -> +%% @doc reads the default config file at the top of a full project +-spec consult_root() -> [any()]. +consult_root() -> consult_file(config_file()). %% @doc reads the default config file in a given directory. -spec consult(file:name()) -> [any()]. consult(Dir) -> - consult_file(filename:join(Dir, config_file())). + consult_file(filename:join(Dir, ?DEFAULT_CONFIG_FILE)). %% @doc reads a given app file, including the `.script' variations, %% if any can be found. diff --git a/src/rebar_packages.erl b/src/rebar_packages.erl index 4cce5a8..5b6ab5c 100644 --- a/src/rebar_packages.erl +++ b/src/rebar_packages.erl @@ -207,10 +207,10 @@ handle_single_vsn(Pkg, PkgVsn, Dep, Vsn, Constraint) -> false -> case {Pkg, PkgVsn} of {undefined, undefined} -> - ?WARN("Only existing version of ~s is ~s which does not match constraint ~~> ~s. " + ?DEBUG("Only existing version of ~s is ~s which does not match constraint ~~> ~s. " "Using anyway, but it is not guaranteed to work.", [Dep, Vsn, Constraint]); _ -> - ?WARN("[~s:~s] Only existing version of ~s is ~s which does not match constraint ~~> ~s. " + ?DEBUG("[~s:~s] Only existing version of ~s is ~s which does not match constraint ~~> ~s. " "Using anyway, but it is not guaranteed to work.", [Pkg, PkgVsn, Dep, Vsn, Constraint]) end, {ok, Vsn} diff --git a/src/rebar_prv_clean.erl b/src/rebar_prv_clean.erl index 8f31fdd..d185f75 100644 --- a/src/rebar_prv_clean.erl +++ b/src/rebar_prv_clean.erl @@ -44,7 +44,8 @@ do(State) -> case All of true -> DepsDir = rebar_dir:deps_dir(State1), - AllApps = rebar_app_discover:find_apps([filename:join(DepsDir, "*")], all), + DepsDirs = filelib:wildcard(filename:join(DepsDir, "*")), + AllApps = rebar_app_discover:find_apps(DepsDirs, all), clean_apps(State1, Providers, AllApps); false -> ProjectApps = rebar_state:project_apps(State1), diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 2ac8fc7..7a060f8 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -431,18 +431,21 @@ test_dirs(State, Apps, Opts) -> set_compile_dirs(State, Apps, join(Suites, Dir)); {_Suites, _Dirs} -> {error, "Only a single directory may be specified when specifying suites"} end; - Specs0 -> - case get_dirs_from_specs(Specs0) of - {ok,{Specs,SuiteDirs}} -> - {State1,Apps1} = set_compile_dirs1(State, Apps, - {dir, SuiteDirs}), - {State2,Apps2} = set_compile_dirs1(State1, Apps1, - {spec, Specs}), - [maybe_copy_spec(State2,Apps2,S) || S <- Specs], - {ok, rebar_state:project_apps(State2, Apps2)}; - Error -> - Error - end + Spec when is_integer(hd(Spec)) -> + spec_test_dirs(State, Apps, [Spec]); + Specs -> + spec_test_dirs(State, Apps, Specs) + end. + +spec_test_dirs(State, Apps, Specs0) -> + case get_dirs_from_specs(Specs0) of + {ok,{Specs,SuiteDirs}} -> + {State1,Apps1} = set_compile_dirs1(State, Apps, {dir, SuiteDirs}), + {State2,Apps2} = set_compile_dirs1(State1, Apps1, {spec, Specs}), + [maybe_copy_spec(State2,Apps2,S) || S <- Specs], + {ok, rebar_state:project_apps(State2, Apps2)}; + Error -> + Error end. join(Suite, Dir) when is_integer(hd(Suite)) -> diff --git a/src/rebar_prv_escriptize.erl b/src/rebar_prv_escriptize.erl index 7ee20c2..56b0d8a 100644 --- a/src/rebar_prv_escriptize.erl +++ b/src/rebar_prv_escriptize.erl @@ -130,9 +130,15 @@ escriptize(State0, App) -> throw(?PRV_ERROR({escript_creation_failed, AppName, EscriptError})) end, - %% Finally, update executable perms for our script - {ok, #file_info{mode = Mode}} = file:read_file_info(Filename), - ok = file:change_mode(Filename, Mode bor 8#00111), + %% Finally, update executable perms for our script on *nix or write out + %% script files on win32 + case os:type() of + {unix, _} -> + {ok, #file_info{mode = Mode}} = file:read_file_info(Filename), + ok = file:change_mode(Filename, Mode bor 8#00111); + {win32, _} -> + write_windows_script(Filename) + end, {ok, State}. -spec format_error(any()) -> iolist(). @@ -258,3 +264,14 @@ def(Rm, State, Key, Default) -> rm_newline(String) -> [C || C <- String, C =/= $\n]. + +write_windows_script(Target) -> + CmdPath = if is_binary(Target) -> <<Target/binary, ".cmd">>; + is_list(Target) -> Target ++ ".cmd" + end, + CmdScript= + "@echo off\r\n" + "setlocal\r\n" + "set rebarscript=%~f0\r\n" + "escript.exe \"%rebarscript:.cmd=%\" %*\r\n", + ok = file:write_file(CmdPath, CmdScript). diff --git a/src/rebar_prv_eunit.erl b/src/rebar_prv_eunit.erl index 7d44137..65addc3 100644 --- a/src/rebar_prv_eunit.erl +++ b/src/rebar_prv_eunit.erl @@ -83,13 +83,16 @@ run_tests(State, Tests) -> EUnitOpts = resolve_eunit_opts(State), ?DEBUG("eunit_tests ~p", [T]), ?DEBUG("eunit_opts ~p", [EUnitOpts]), - Result = eunit:test(T, EUnitOpts), - ok = maybe_write_coverdata(State), - case handle_results(Result) of - {error, Reason} -> - ?PRV_ERROR(Reason); - ok -> - {ok, State} + try eunit:test(T, EUnitOpts) of + Result -> + ok = maybe_write_coverdata(State), + case handle_results(Result) of + {error, Reason} -> + ?PRV_ERROR(Reason); + ok -> + {ok, State} + end + catch error:badarg -> ?PRV_ERROR({error, badarg}) end. -spec format_error(any()) -> iolist(). diff --git a/src/rebar_prv_path.erl b/src/rebar_prv_path.erl index 4259eec..d8e14a4 100644 --- a/src/rebar_prv_path.erl +++ b/src/rebar_prv_path.erl @@ -27,7 +27,7 @@ init(State) -> {example, "rebar3 path"}, {short_desc, "Print paths to build dirs in current profile."}, {desc, "Print paths to build dirs in current profile."}, - {opts, eunit_opts(State)}])), + {opts, path_opts(State)}])), {ok, State1}. @@ -107,7 +107,7 @@ normalize(AppName) when is_list(AppName) -> AppName; normalize(AppName) when is_atom(AppName) -> atom_to_list(AppName); normalize(AppName) when is_binary(AppName) -> binary_to_list(AppName). -eunit_opts(_State) -> +path_opts(_State) -> [{app, undefined, "app", string, help(app)}, {base, undefined, "base", boolean, help(base)}, {bin, undefined, "bin", boolean, help(bin)}, diff --git a/src/rebar_prv_plugins.erl b/src/rebar_prv_plugins.erl index 7e6b88e..c76dae1 100644 --- a/src/rebar_prv_plugins.erl +++ b/src/rebar_prv_plugins.erl @@ -34,14 +34,17 @@ do(State) -> GlobalConfigFile = rebar_dir:global_config(), GlobalConfig = rebar_state:new(rebar_config:consult_file(GlobalConfigFile)), GlobalPlugins = rebar_state:get(GlobalConfig, plugins, []), + GlobalSrcDirs = rebar_state:get(GlobalConfig, src_dirs, ["src"]), GlobalPluginsDir = filename:join([rebar_dir:global_cache_dir(rebar_state:opts(State)), "plugins", "*"]), - GlobalApps = rebar_app_discover:find_apps([GlobalPluginsDir], all), + GlobalApps = rebar_app_discover:find_apps([GlobalPluginsDir], GlobalSrcDirs, all), display_plugins("Global plugins", GlobalApps, GlobalPlugins), + RebarOpts = rebar_state:opts(State), + SrcDirs = rebar_dir:src_dirs(RebarOpts, ["src"]), Plugins = rebar_state:get(State, plugins, []), - PluginsDir = filename:join(rebar_dir:plugins_dir(State), "*"), - CheckoutsDir = filename:join(rebar_dir:checkouts_dir(State), "*"), - Apps = rebar_app_discover:find_apps([CheckoutsDir, PluginsDir], all), + PluginsDirs = filelib:wildcard(filename:join(rebar_dir:plugins_dir(State), "*")), + CheckoutsDirs = filelib:wildcard(filename:join(rebar_dir:checkouts_dir(State), "*")), + Apps = rebar_app_discover:find_apps(CheckoutsDirs++PluginsDirs, SrcDirs, all), display_plugins("Local plugins", Apps, Plugins), {ok, State}. diff --git a/src/rebar_prv_upgrade.erl b/src/rebar_prv_upgrade.erl index 18c307b..34631ff 100644 --- a/src/rebar_prv_upgrade.erl +++ b/src/rebar_prv_upgrade.erl @@ -32,7 +32,7 @@ init(State) -> {deps, ?DEPS}, {example, "rebar3 upgrade [cowboy[,ranch]]"}, {short_desc, "Upgrade dependencies."}, - {desc, "Upgrade project dependecies. Mentioning no application " + {desc, "Upgrade project dependencies. Mentioning no application " "will upgrade all dependencies. To upgrade specific dependencies, " "their names can be listed in the command."}, {opts, [ diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl index 9b33ec5..1c28788 100644 --- a/src/rebar_templater.erl +++ b/src/rebar_templater.erl @@ -334,8 +334,19 @@ find_plugin_templates(State) -> || App <- rebar_state:all_plugin_deps(State), Priv <- [rebar_app_info:priv_dir(App)], Priv =/= undefined, + File <- rebar_utils:find_files(Priv, ?TEMPLATE_RE)] + ++ %% and add global plugins too + [{plugin, File} + || PSource <- rebar_state:get(State, {plugins, global}, []), + Plugin <- [plugin_provider(PSource)], + is_atom(Plugin), + Priv <- [code:priv_dir(Plugin)], + Priv =/= undefined, File <- rebar_utils:find_files(Priv, ?TEMPLATE_RE)]. +plugin_provider(P) when is_atom(P) -> P; +plugin_provider(T) when is_tuple(T) -> element(1, T). + %% Take an existing list of templates and tag them by name the way %% the user would enter it from the CLI tag_names(List) -> diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index c357e94..c684e2d 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -857,7 +857,7 @@ url_append_path(Url, ExtraPath) -> escape_chars(Str) when is_atom(Str) -> escape_chars(atom_to_list(Str)); escape_chars(Str) -> - re:replace(Str, "([ ()?`!$&;])", "\\\\&", [global, {return, list}]). + re:replace(Str, "([ ()?`!$&;\"\'])", "\\\\&", [global, {return, list}]). %% "escape inside these" escape_double_quotes(Str) -> diff --git a/test/rebar_compile_SUITE.erl b/test/rebar_compile_SUITE.erl index 9f01496..5a18745 100644 --- a/test/rebar_compile_SUITE.erl +++ b/test/rebar_compile_SUITE.erl @@ -78,21 +78,10 @@ all() -> recompile_when_parse_transform_as_opt_changes, recompile_when_parse_transform_inline_changes, regex_filter_skip, regex_filter_regression, - %% recompile behaviour when `ERL_COMPILER_OPTIONS` differs prior to 19.x - recursive, no_recursive] ++ recompile_when_env_changes_test(). - -recompile_when_env_changes_test() -> - _ = code:ensure_loaded(os), - UnSetEnv = erlang:function_exported(os, unsetenv, 1), - _ = code:ensure_loaded(compile), - EnvOpts = erlang:function_exported(compile, env_compiler_options, 0), - case {UnSetEnv, EnvOpts} of - {true, true} -> - [dont_recompile_when_erl_compiler_options_env_does_not_change, - recompile_when_erl_compiler_options_env_changes]; - {true, false} -> [always_recompile_when_erl_compiler_options_set]; - {false, _} -> [] - end. + recursive, no_recursive, + always_recompile_when_erl_compiler_options_set, + dont_recompile_when_erl_compiler_options_env_does_not_change, + recompile_when_erl_compiler_options_env_changes]. groups() -> [{basic_app, [], [build_basic_app, paths_basic_app, clean_basic_app]}, @@ -266,7 +255,31 @@ init_per_suite(Config) -> end_per_suite(_Config) -> ok. -init_per_testcase(_, Config) -> +init_per_testcase(Test, Config) when + Test == dont_recompile_when_erl_compiler_options_env_does_not_change + orelse + Test == recompile_when_erl_compiler_options_env_changes -> + _ = code:ensure_loaded(os), + UnSetEnv = erlang:function_exported(os, unsetenv, 1), + _ = code:ensure_loaded(compile), + EnvOpts = erlang:function_exported(compile, env_compiler_options, 0), + case {UnSetEnv, EnvOpts} of + {true, true} -> maybe_init_config(Config); + _ -> {skip, "compile:env_compiler_options/0 unavailable"} + end; +init_per_testcase(always_recompile_when_erl_compiler_options_set, Config) -> + _ = code:ensure_loaded(os), + UnSetEnv = erlang:function_exported(os, unsetenv, 1), + _ = code:ensure_loaded(compile), + EnvOpts = erlang:function_exported(compile, env_compiler_options, 0), + case {UnSetEnv, EnvOpts} of + {true, true} -> {skip, "compile:env_compiler_options/0 available"}; + {true, false} -> maybe_init_config(Config); + _ -> {skip, "os:unsetenv/1 unavailable"} + end; +init_per_testcase(_, Config) -> maybe_init_config(Config). + +maybe_init_config(Config) -> case ?config(apps, Config) of undefined -> rebar_test_utils:init_rebar_state(Config); _ -> Config @@ -276,7 +289,6 @@ end_per_testcase(_, _Config) -> catch meck:unload(). - %% test cases build_basic_app(Config) -> diff --git a/test/rebar_ct_SUITE.erl b/test/rebar_ct_SUITE.erl index 06dc76e..586e7b5 100644 --- a/test/rebar_ct_SUITE.erl +++ b/test/rebar_ct_SUITE.erl @@ -55,7 +55,8 @@ testspec/1, testspec_at_root/1, testspec_parse_error/1, - cmd_vs_cfg_opts/1]). + cmd_vs_cfg_opts/1, + single_testspec_in_ct_opts/1]). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). @@ -75,7 +76,8 @@ all() -> [{group, basic_app}, testspec, testspec_at_root, testspec_parse_error, - cmd_vs_cfg_opts]. + cmd_vs_cfg_opts, + single_testspec_in_ct_opts]. groups() -> [{basic_app, [], [basic_app_default_dirs, basic_app_default_beams, @@ -1548,6 +1550,41 @@ cmd_vs_cfg_opts(Config) -> ok. +single_testspec_in_ct_opts(Config) -> + C = rebar_test_utils:init_rebar_state(Config, "ct_testspec_"), + + AppDir = ?config(apps, C), + + Name = rebar_test_utils:create_random_name("ct_testspec_"), + Vsn = rebar_test_utils:create_random_vsn(), + rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + Spec = filename:join([AppDir, "test", "some.spec"]), + ok = filelib:ensure_dir(Spec), + ok = file:write_file(Spec, "{suites,\".\",all}.\n"), + + {ok,Wd} = file:get_cwd(), + ok = file:set_cwd(AppDir), + + RebarConfig = [{ct_opts, [{spec,"test/some.spec"}]}], + + {ok, State} = rebar_test_utils:run_and_check(C, RebarConfig, ["as", "test", "lock"], return), + + Providers = rebar_state:providers(State), + Namespace = rebar_state:namespace(State), + CommandProvider = providers:get_provider(ct, Providers, Namespace), + GetOptSpec = providers:opts(CommandProvider), + + %% Testspec in "test" directory + {ok, GetOptResult1} = getopt:parse(GetOptSpec, []), + State1 = rebar_state:command_parsed_args(State, GetOptResult1), + Tests1 = rebar_prv_common_test:prepare_tests(State1), + {ok, T1} = Tests1, + "test/some.spec" = proplists:get_value(spec,T1), + {ok, _NewState} = rebar_prv_common_test:compile(State1, Tests1), + + ok = file:set_cwd(Wd), + ok. + %% helper for generating test data test_suite(Name) -> io_lib:format("-module(~ts_SUITE).\n" diff --git a/test/rebar_eunit_SUITE.erl b/test/rebar_eunit_SUITE.erl index 6fb325b..4805b3d 100644 --- a/test/rebar_eunit_SUITE.erl +++ b/test/rebar_eunit_SUITE.erl @@ -1,7 +1,8 @@ -module(rebar_eunit_SUITE). -export([all/0, groups/0]). --export([init_per_suite/1, init_per_group/2, end_per_group/2]). +-export([init_per_suite/1, end_per_suite/1]). +-export([init_per_group/2, end_per_group/2]). -export([basic_app_compiles/1, basic_app_files/1]). -export([basic_app_exports/1, basic_app_testset/1]). -export([basic_app_eunit_macro/1]). @@ -60,6 +61,8 @@ init_per_suite(Config) -> {ok, _} = zip:extract(filename:join([PrivDir, "multi_app.zip"]), [{cwd, PrivDir}]), Config. +end_per_suite(Config) -> Config. + init_per_group(basic_app, Config) -> GroupState = rebar_test_utils:init_rebar_state(Config, "basic_app_"), diff --git a/test/rebar_src_dirs_SUITE.erl b/test/rebar_src_dirs_SUITE.erl index f854a94..bc22160 100644 --- a/test/rebar_src_dirs_SUITE.erl +++ b/test/rebar_src_dirs_SUITE.erl @@ -11,12 +11,16 @@ src_dirs_in_erl_opts/1, extra_src_dirs_in_erl_opts/1, src_dirs_at_root_and_in_erl_opts/1, + dupe_src_dirs_at_root_and_in_erl_opts/1, extra_src_dirs_at_root_and_in_erl_opts/1, build_basic_app/1, build_multi_apps/1, - src_dir_takes_precedence_over_extra/1]). + src_dir_takes_precedence_over_extra/1, + src_dir_checkout_dep/1, + app_src_info/1]). -include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). suite() -> []. @@ -35,8 +39,11 @@ end_per_testcase(_, _Config) -> ok. all() -> [src_dirs_at_root, extra_src_dirs_at_root, src_dirs_in_erl_opts, extra_src_dirs_in_erl_opts, - src_dirs_at_root_and_in_erl_opts, extra_src_dirs_at_root_and_in_erl_opts, - build_basic_app, build_multi_apps, src_dir_takes_precedence_over_extra]. + src_dirs_at_root_and_in_erl_opts, + dupe_src_dirs_at_root_and_in_erl_opts, + extra_src_dirs_at_root_and_in_erl_opts, + build_basic_app, build_multi_apps, src_dir_takes_precedence_over_extra, + src_dir_checkout_dep, app_src_info]. src_dirs_at_root(Config) -> AppDir = ?config(apps, Config), @@ -93,15 +100,47 @@ extra_src_dirs_in_erl_opts(Config) -> src_dirs_at_root_and_in_erl_opts(Config) -> AppDir = ?config(apps, Config), - Name = rebar_test_utils:create_random_name("app1_"), + Name = rebar_test_utils:create_random_name("src_dirs_root_erlopts_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}]}, {src_dirs, ["baz", "qux"]}], + %% move the .app.src file to one of the subdirs, out of src/ + filelib:ensure_dir(filename:join([AppDir, "qux", "fake"])), + rebar_file_utils:mv(filename:join([AppDir, "src", Name ++ ".app.src"]), + filename:join([AppDir, "qux", Name ++ ".app.src"])), + {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), - ["bar", "baz", "foo", "qux"] = rebar_dir:src_dirs(rebar_state:opts(State), []). + ["bar", "baz", "foo", "qux"] = rebar_dir:src_dirs(rebar_state:opts(State), []), + rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], + {ok, [{app, Name}]}), + ok. + +dupe_src_dirs_at_root_and_in_erl_opts(Config) -> + AppDir = ?config(apps, Config), + + Name = rebar_test_utils:create_random_name("dupe_src_dirs_root_erlopts_"), + Vsn = rebar_test_utils:create_random_vsn(), + rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + + RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}]}, {src_dirs, ["baz", "qux"]}], + + %% move the .app.src file to one of the subdirs, out of src/ + filelib:ensure_dir(filename:join([AppDir, "qux", "fake"])), + filelib:ensure_dir(filename:join([AppDir, "foo", "fake"])), + Src1 = filename:join([AppDir, "qux", Name ++ ".app.src"]), + Src2 = filename:join([AppDir, "foo", Name ++ ".app.src"]), + rebar_file_utils:mv(filename:join([AppDir, "src", Name ++ ".app.src"]), + Src1), + %% Then copy it over to create a conflict with dupes + file:copy(Src1, Src2), + + {error, {rebar_prv_app_discovery, {multiple_app_files, [Src2, Src1]}}} = + rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), + + ok. extra_src_dirs_at_root_and_in_erl_opts(Config) -> AppDir = ?config(apps, Config), @@ -236,3 +275,52 @@ src_dir_takes_precedence_over_extra(Config) -> [{application, _, KVs}] = App, Mods = proplists:get_value(modules, KVs), true = lists:member(extra, Mods). + +src_dir_checkout_dep(Config) -> + AppDir = ?config(apps, Config), + AppName = rebar_test_utils:create_random_name("src_dir_checkout_app"), + DepName = rebar_test_utils:create_random_name("src_dir_checkout_dep"), + AtomDep = list_to_atom(DepName), + + Vsn = rebar_test_utils:create_random_vsn(), + rebar_test_utils:create_app(AppDir, AppName, Vsn, [kernel, stdlib]), + RebarConfig = [{deps, [AtomDep]}], + + DepDir = filename:join([?config(checkouts, Config), DepName]), + ct:pal("checkouts dir: ~p", [DepDir]), + rebar_test_utils:create_app(DepDir, DepName, Vsn, [kernel, stdlib]), + + + %% move the .app.src file to one of the subdirs, out of src/ + rebar_file_utils:mv(filename:join([DepDir, "src"]), + filename:join([DepDir, "qux"])), + DepRebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}]}, + {src_dirs, ["baz", "qux"]}], + file:write_file(filename:join([DepDir, "rebar.config"]), + io_lib:format("~p.~n~p.~n", DepRebarConfig)), + + rebar_test_utils:run_and_check( + Config, RebarConfig, ["compile"], + {ok, [{checkout, DepName}, {app, AppName}]} + ), + ok. + +app_src_info(Config) -> + PrivDir = ?config(priv_dir, Config), + AppName1 = rebar_test_utils:create_random_name("app_src_info"), + AppDir1 = filename:join(PrivDir, AppName1), + {ok, Info1} = rebar_app_info:new(AppName1, "1.0.0", AppDir1), + AppSrc1 = filename:join([AppDir1, "src", AppName1 ++ ".app.src"]), + ok = filelib:ensure_dir(AppSrc1), + ok = file:write_file(AppSrc1, "[]."), + ?assertEqual(AppSrc1, rebar_app_info:app_file_src(Info1)), + + AppName2 = rebar_test_utils:create_random_name("app_src_info"), + AppDir2 = filename:join(PrivDir, AppName2), + {ok, Info2Tmp} = rebar_app_info:new(AppName2, "1.0.0", AppDir2), + Info2 = rebar_app_info:set(Info2Tmp, src_dirs, ["foo", "bar", "baz"]), + AppSrc2 = filename:join([AppDir2, "bar", AppName2 ++ ".app.src"]), + ok = filelib:ensure_dir(AppSrc2), + ok = file:write_file(AppSrc2, "[]."), + ?assertEqual(AppSrc2, rebar_app_info:app_file_src(Info2)), + ok. diff --git a/test/rebar_test_utils.erl b/test/rebar_test_utils.erl index 8c177c9..3b8ffac 100644 --- a/test/rebar_test_utils.erl +++ b/test/rebar_test_utils.erl @@ -218,7 +218,7 @@ check_results(AppDir, Expected, ProfileRun) -> BuildDirs = filelib:wildcard(filename:join([AppDir, "_build", ProfileRun, "lib", "*"])), PluginDirs = filelib:wildcard(filename:join([AppDir, "_build", ProfileRun, "plugins", "*"])), GlobalPluginDirs = filelib:wildcard(filename:join([AppDir, "global", "plugins", "*"])), - CheckoutsDir = filename:join([AppDir, "_checkouts", "*"]), + CheckoutsDirs = filelib:wildcard(filename:join([AppDir, "_checkouts", "*"])), LockFile = filename:join([AppDir, "rebar.lock"]), Locks = lists:flatten(rebar_config:consult_lock_file(LockFile)), @@ -230,7 +230,7 @@ check_results(AppDir, Expected, ProfileRun) -> Deps = rebar_app_discover:find_apps(BuildDirs, all), DepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Deps], - Checkouts = rebar_app_discover:find_apps([CheckoutsDir], all), + Checkouts = rebar_app_discover:find_apps(CheckoutsDirs, all), 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], |