diff options
author | feng19 <feng_19@foxmail.com> | 2018-06-21 10:24:56 +0800 |
---|---|---|
committer | feng19 <feng_19@foxmail.com> | 2018-06-21 10:24:56 +0800 |
commit | 482718b8bf31024d919aabad1da2e9116411f2aa (patch) | |
tree | 1c693d007b98b0fc31a23aac19abbf94096ad9ef | |
parent | dc0f8b4d66d12c10ed4df85148b5e8ce13056f40 (diff) | |
parent | 38865da7ba01e7d5e60316e970f01959e85759ee (diff) |
Merge tag '3.6.0' into refresh_paths
Bump to 3.6.0
- Introduce support of add and del operations for overrides
- OTP-21 compatibility
- Bump cth_readable for OTP-21 compat
- upgrade relx to 3.25.0
- upgrade bbmustache to 1.5.0
- run compile provider in default namespace from bare compiling (fixes
hooks for mix builds)
- Resolve string vs list crashing rebar3 in erl_first_files
- Create ERLANG_LIB_*_erl_interface environment variables only if erl_interface exists
- Add hooks to the upgrade command
- Add --start-clean flag to rebar3 shell
- Auto-boot main app in OTP app project templates
- Use maps for child spec examples in templates
-rw-r--r-- | .travis.yml | 4 | ||||
-rwxr-xr-x | bootstrap | 2 | ||||
-rw-r--r-- | priv/templates/app.template | 2 | ||||
-rw-r--r-- | priv/templates/app_rebar.config | 7 | ||||
-rw-r--r-- | priv/templates/escript_rebar.config | 2 | ||||
-rw-r--r-- | priv/templates/sup.erl | 3 | ||||
-rw-r--r-- | rebar.config | 13 | ||||
-rw-r--r-- | rebar.lock | 12 | ||||
-rw-r--r-- | src/rebar.app.src | 2 | ||||
-rw-r--r-- | src/rebar3.erl | 7 | ||||
-rw-r--r-- | src/rebar_env.erl | 54 | ||||
-rw-r--r-- | src/rebar_erlc_compiler.erl | 8 | ||||
-rw-r--r-- | src/rebar_opts.erl | 83 | ||||
-rw-r--r-- | src/rebar_prv_bare_compile.erl | 4 | ||||
-rw-r--r-- | src/rebar_prv_common_test.erl | 34 | ||||
-rw-r--r-- | src/rebar_prv_local_install.erl | 2 | ||||
-rw-r--r-- | src/rebar_prv_shell.erl | 10 | ||||
-rw-r--r-- | src/rebar_prv_upgrade.erl | 13 | ||||
-rw-r--r-- | src/rebar_utils.erl | 11 | ||||
-rw-r--r-- | test/rebar_compile_SUITE.erl | 398 | ||||
-rw-r--r-- | test/rebar_hooks_SUITE.erl | 19 | ||||
-rw-r--r-- | test/rebar_utils_SUITE.erl | 11 |
22 files changed, 598 insertions, 103 deletions
diff --git a/.travis.yml b/.travis.yml index 4755345..1cca5c5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,6 @@ language: erlang matrix: include: - os: linux - otp_release: R16B03-1 - - os: linux otp_release: 17.5 - os: linux otp_release: 18.3 @@ -44,4 +42,4 @@ deploy: on: repo: erlang/rebar3 branch: master - condition: $TRAVIS_OTP_RELEASE = "R16B03-1" + condition: $TRAVIS_OTP_RELEASE = "17.5" @@ -24,7 +24,7 @@ main(_) -> bootstrap_rebar3(), %% Build rebar.app from rebar.app.src - {ok, App} = rebar_app_info:new(rebar, "3.5.2", filename:absname("_build/default/lib/rebar/")), + {ok, App} = rebar_app_info:new(rebar, "3.6.0", filename:absname("_build/default/lib/rebar/")), rebar_otp_app:compile(rebar_state:new(), App), %% Because we are compiling files that are loaded already we want to silence diff --git a/priv/templates/app.template b/priv/templates/app.template index d0bebd7..7d68b2c 100644 --- a/priv/templates/app.template +++ b/priv/templates/app.template @@ -6,7 +6,7 @@ {template, "app.erl", "{{name}}/src/{{name}}_app.erl"}. {template, "sup.erl", "{{name}}/src/{{name}}_sup.erl"}. {template, "otp_app.app.src", "{{name}}/src/{{name}}.app.src"}. -{template, "rebar.config", "{{name}}/rebar.config"}. +{template, "app_rebar.config", "{{name}}/rebar.config"}. {template, "gitignore", "{{name}}/.gitignore"}. {template, "LICENSE", "{{name}}/LICENSE"}. {template, "README.md", "{{name}}/README.md"}. diff --git a/priv/templates/app_rebar.config b/priv/templates/app_rebar.config new file mode 100644 index 0000000..203ce4a --- /dev/null +++ b/priv/templates/app_rebar.config @@ -0,0 +1,7 @@ +{erl_opts, [debug_info]}. +{deps, []}. + +{shell, [ + % {config, [{config, "config/sys.config"}]}, + {apps, [{{name}}]} +]}. diff --git a/priv/templates/escript_rebar.config b/priv/templates/escript_rebar.config index ef498a8..3ed7150 100644 --- a/priv/templates/escript_rebar.config +++ b/priv/templates/escript_rebar.config @@ -5,7 +5,7 @@ [{{name}}]}. {escript_main_app, {{name}}}. {escript_name, {{name}}}. -{escript_emu_args, "%%! +sbtu +A0\n"}. +{escript_emu_args, "%%! +sbtu +A1\n"}. %% Profiles {profiles, [{test, diff --git a/priv/templates/sup.erl b/priv/templates/sup.erl index a2e7209..0db7155 100644 --- a/priv/templates/sup.erl +++ b/priv/templates/sup.erl @@ -26,6 +26,9 @@ start_link() -> %% Supervisor callbacks %%==================================================================== +%% Child :: #{id => Id, start => {M, F, A}} +%% Optional keys are restart, shutdown, type, modules. +%% Before OTP 18 tuples must be used to specify a child. e.g. %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> {ok, { {one_for_all, 0, 1}, []} }. diff --git a/rebar.config b/rebar.config index 4bd205b..5bd4fab 100644 --- a/rebar.config +++ b/rebar.config @@ -6,10 +6,10 @@ {certifi, "2.0.0"}, {providers, "1.7.0"}, {getopt, "1.0.1"}, - {bbmustache, "1.3.0"}, - {relx, "3.24.4"}, + {bbmustache, "1.5.0"}, + {relx, "3.25.0"}, {cf, "0.2.2"}, - {cth_readable, "1.3.4"}, + {cth_readable, "1.4.2"}, {eunit_formatters, "0.5.0"}]}. {post_hooks, [{"(linux|darwin|solaris|freebsd|netbsd|openbsd)", @@ -22,7 +22,7 @@ ]}. {escript_name, rebar3}. -{escript_emu_args, "%%! +sbtu +A0\n"}. +{escript_emu_args, "%%! +sbtu +A1\n"}. %% escript_incl_extra is for internal rebar-private use only. %% Do not use outside rebar. Config interface is not stable. {escript_incl_extra, [{"relx/priv/templates/*", "_build/default/lib/"}, @@ -54,6 +54,10 @@ {bootstrap, []}, {prod, [ + {escript_incl_extra, [ + {"relx/priv/templates/*", "_build/prod/lib/"}, + {"rebar/priv/templates/*", "_build/prod/lib/"} + ]}, {erl_opts, [no_debug_info]}, {overrides, [ {override, erlware_commons, [ @@ -78,4 +82,3 @@ {add, relx, [{erl_opts, [no_debug_info]}]}]} ]} ]}. - @@ -1,24 +1,24 @@ {"1.1.0", -[{<<"bbmustache">>,{pkg,<<"bbmustache">>,<<"1.3.0">>},0}, +[{<<"bbmustache">>,{pkg,<<"bbmustache">>,<<"1.5.0">>},0}, {<<"certifi">>,{pkg,<<"certifi">>,<<"2.0.0">>},0}, {<<"cf">>,{pkg,<<"cf">>,<<"0.2.2">>},0}, - {<<"cth_readable">>,{pkg,<<"cth_readable">>,<<"1.3.4">>},0}, + {<<"cth_readable">>,{pkg,<<"cth_readable">>,<<"1.4.2">>},0}, {<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"1.1.0">>},0}, {<<"eunit_formatters">>,{pkg,<<"eunit_formatters">>,<<"0.5.0">>},0}, {<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},0}, {<<"providers">>,{pkg,<<"providers">>,<<"1.7.0">>},0}, - {<<"relx">>,{pkg,<<"relx">>,<<"3.24.4">>},0}, + {<<"relx">>,{pkg,<<"relx">>,<<"3.25.0">>},0}, {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.3">>},0}]}. [ {pkg_hash,[ - {<<"bbmustache">>, <<"2010ADAE78830992A4C69680115ECD7D475DD03A72C076BBADDCCBF2D4B32035">>}, + {<<"bbmustache">>, <<"8CFDE0602E90A4057E161BF5288ADE854B4E511E2E8924966A8438730E958381">>}, {<<"certifi">>, <<"A0C0E475107135F76B8C1D5BC7EFB33CD3815CB3CF3DEA7AEFDD174DABEAD064">>}, {<<"cf">>, <<"7F2913FFF90ABCABD0F489896CFEB0B0674F6C8DF6C10B17A83175448029896C">>}, - {<<"cth_readable">>, <<"CB85DF77CEB7F05854AE241300DB36A72C371740EDD883D8BF75B5F652B7067D">>}, + {<<"cth_readable">>, <<"0F57B4EB7DA7F5438F422312245F9143A1B3118C11B6BAE5C3D1391C9EE88322">>}, {<<"erlware_commons">>, <<"F69F3D96044C2A9E735CCD76F469FEC5FC851797E5FE23115698B4EDC072191B">>}, {<<"eunit_formatters">>, <<"6A9133943D36A465D804C1C5B6E6839030434B8879C5600D7DDB5B3BAD4CCB59">>}, {<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}, {<<"providers">>, <<"BBF730563914328EC2511D205E6477A94831DB7297DE313B3872A2B26C562EAB">>}, - {<<"relx">>, <<"2132F0ABFA93DB3177E66768DB5A3D4141D4683BB4864B9DD4452EE7123DED07">>}, + {<<"relx">>, <<"460A336514DC209F0FA243A6F2D4ECB33B3652A1588CAF9FCE3C1FA170FACAEC">>}, {<<"ssl_verify_fun">>, <<"6C49665D4326E26CD4A5B7BD54AA442B33DADFB7C5D59A0D0CD0BF5534BBFBD7">>}]} ]. diff --git a/src/rebar.app.src b/src/rebar.app.src index 42aecca..5c76f59 100644 --- a/src/rebar.app.src +++ b/src/rebar.app.src @@ -3,7 +3,7 @@ {application, rebar, [{description, "Rebar: Erlang Build Tool"}, - {vsn, "3.5.2"}, + {vsn, "3.6.0"}, {modules, []}, {registered, []}, {applications, [kernel, diff --git a/src/rebar3.erl b/src/rebar3.erl index 8e9d4b1..ec8e953 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -54,7 +54,7 @@ %% ==================================================================== %% @doc For running with: -%% erl +sbtu +A0 -noinput -mode minimal -boot start_clean -s rebar3 main -extra "$@" +%% erl +sbtu +A1 -noinput -mode minimal -boot start_clean -s rebar3 main -extra "$@" -spec main() -> no_return(). main() -> List = init:get_plain_arguments(), @@ -93,6 +93,7 @@ run(BaseState, Commands) -> %% arguments passed, if they have any relevance; used to translate %% from the escript call-site into a common one with the library %% usage. +-spec run([any(), ...]) -> {ok, rebar_state:t()} | {error, term()}. run(RawArgs) -> start_and_load_apps(command_line), @@ -239,6 +240,7 @@ parse_args([Task | RawRest]) -> {list_to_atom(Task), RawRest}. %% @private actually not too sure what this does anymore. +-spec set_options(rebar_state:t(),{[any()],[any()]}) -> {rebar_state:t(),[any()]}. set_options(State, {Options, NonOptArgs}) -> GlobalDefines = proplists:get_all_values(defines, Options), @@ -387,6 +389,7 @@ state_from_global_config(Config, GlobalConfigFile) -> GlobalConfig3 = rebar_state:set(GlobalConfig2, {plugins, global}, rebar_state:get(GlobalConfigThrowAway, plugins, [])), rebar_state:providers(rebar_state:new(GlobalConfig3, Config), GlobalPlugins). +-spec test_state(rebar_state:t()) -> [{'extra_src_dirs',[string()]} | {'erl_opts',[any()]}]. test_state(State) -> %% Fetch the test profile's erl_opts only Opts = rebar_state:opts(State), @@ -396,6 +399,7 @@ test_state(State) -> TestOpts = safe_define_test_macro(ErlOpts), [{extra_src_dirs, ["test"]}, {erl_opts, TestOpts}]. +-spec safe_define_test_macro([any()]) -> [any()] | [{'d',atom()} | any()]. safe_define_test_macro(Opts) -> %% defining a compile macro twice results in an exception so %% make sure 'TEST' is only defined once @@ -404,6 +408,7 @@ safe_define_test_macro(Opts) -> false -> [{d, 'TEST'}|Opts] end. +-spec test_defined([{d, atom()} | {d, atom(), term()} | term()]) -> boolean(). test_defined([{d, 'TEST'}|_]) -> true; test_defined([{d, 'TEST', true}|_]) -> true; test_defined([_|Rest]) -> test_defined(Rest); diff --git a/src/rebar_env.erl b/src/rebar_env.erl index eea47de..e9adafb 100644 --- a/src/rebar_env.erl +++ b/src/rebar_env.erl @@ -37,26 +37,40 @@ create_env(State) -> -spec create_env(rebar_state:t(), rebar_dict()) -> proplists:proplist(). create_env(State, Opts) -> BaseDir = rebar_dir:base_dir(State), - [ - {"REBAR_DEPS_DIR", filename:absname(rebar_dir:deps_dir(State))}, - {"REBAR_BUILD_DIR", filename:absname(rebar_dir:base_dir(State))}, - {"REBAR_ROOT_DIR", filename:absname(rebar_dir:root_dir(State))}, - {"REBAR_CHECKOUTS_DIR", filename:absname(rebar_dir:checkouts_dir(State))}, - {"REBAR_PLUGINS_DIR", filename:absname(rebar_dir:plugins_dir(State))}, - {"REBAR_GLOBAL_CONFIG_DIR", filename:absname(rebar_dir:global_config_dir(State))}, - {"REBAR_GLOBAL_CACHE_DIR", filename:absname(rebar_dir:global_cache_dir(Opts))}, - {"REBAR_TEMPLATE_DIR", filename:absname(rebar_dir:template_dir(State))}, - {"REBAR_APP_DIRS", join_dirs(BaseDir, rebar_dir:lib_dirs(State))}, - {"REBAR_SRC_DIRS", join_dirs(BaseDir, rebar_dir:all_src_dirs(Opts))}, - {"ERLANG_ERTS_VER", erlang:system_info(version)}, - {"ERLANG_ROOT_DIR", code:root_dir()}, - {"ERLANG_LIB_DIR_erl_interface", code:lib_dir(erl_interface)}, - {"ERLANG_LIB_VER_erl_interface", re_version(code:lib_dir(erl_interface))}, - {"ERL", filename:join([code:root_dir(), "bin", "erl"])}, - {"ERLC", filename:join([code:root_dir(), "bin", "erlc"])}, - {"ERLANG_ARCH" , rebar_api:wordsize()}, - {"ERLANG_TARGET", rebar_api:get_arch()} - ]. + EnvVars = [ + {"REBAR_DEPS_DIR", filename:absname(rebar_dir:deps_dir(State))}, + {"REBAR_BUILD_DIR", filename:absname(rebar_dir:base_dir(State))}, + {"REBAR_ROOT_DIR", filename:absname(rebar_dir:root_dir(State))}, + {"REBAR_CHECKOUTS_DIR", filename:absname(rebar_dir:checkouts_dir(State))}, + {"REBAR_PLUGINS_DIR", filename:absname(rebar_dir:plugins_dir(State))}, + {"REBAR_GLOBAL_CONFIG_DIR", filename:absname(rebar_dir:global_config_dir(State))}, + {"REBAR_GLOBAL_CACHE_DIR", filename:absname(rebar_dir:global_cache_dir(Opts))}, + {"REBAR_TEMPLATE_DIR", filename:absname(rebar_dir:template_dir(State))}, + {"REBAR_APP_DIRS", join_dirs(BaseDir, rebar_dir:lib_dirs(State))}, + {"REBAR_SRC_DIRS", join_dirs(BaseDir, rebar_dir:all_src_dirs(Opts))}, + {"ERLANG_ERTS_VER", erlang:system_info(version)}, + {"ERLANG_ROOT_DIR", code:root_dir()}, + {"ERL", filename:join([code:root_dir(), "bin", "erl"])}, + {"ERLC", filename:join([code:root_dir(), "bin", "erlc"])}, + {"ERLANG_ARCH" , rebar_api:wordsize()}, + {"ERLANG_TARGET", rebar_api:get_arch()} + ], + EInterfaceVars = create_erl_interface_env(), + lists:append([EnvVars, EInterfaceVars]). + +-spec create_erl_interface_env() -> list(). +create_erl_interface_env() -> + case code:lib_dir(erl_interface) of + {error, bad_name} -> + ?WARN("erl_interface is missing. ERLANG_LIB_DIR_erl_interface and " + "ERLANG_LIB_VER_erl_interface will not be added to the environment.", []), + []; + Dir -> + [ + {"ERLANG_LIB_DIR_erl_interface", Dir}, + {"ERLANG_LIB_VER_erl_interface", re_version(Dir)} + ] + end. %% ==================================================================== %% Internal functions diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index c588a25..ebdd9dd 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -285,6 +285,7 @@ gather_src(Opts, BaseDirParts, [Dir|Rest], Srcs, CompileOpts) -> %% files, so that yet to be compiled parse transformations are excluded from it. erl_first_files(Opts, ErlOpts, Dir, NeededErlFiles) -> ErlFirstFilesConf = rebar_opts:get(Opts, erl_first_files, []), + valid_erl_first_conf(ErlFirstFilesConf), NeededSrcDirs = lists:usort(lists:map(fun filename:dirname/1, NeededErlFiles)), %% NOTE: order of files here is important! ErlFirstFiles = @@ -796,3 +797,10 @@ dir_recursive(Opts, Dir, CompileOpts) when is_list(CompileOpts) -> undefined -> rebar_dir:recursive(Opts, Dir); Recursive -> Recursive end. + +valid_erl_first_conf(FileList) -> + case rebar_utils:is_list_of_strings(FileList) of + true -> true; + false -> ?ABORT("An invalid file list (~p) was provided as part of your erl_files_first directive", + [FileList]) + end. diff --git a/src/rebar_opts.erl b/src/rebar_opts.erl index 1a927ba..8195a77 100644 --- a/src/rebar_opts.erl +++ b/src/rebar_opts.erl @@ -73,36 +73,42 @@ filter_debug_info([H|T]) -> apply_overrides(Opts, Name, Overrides) -> %% Inefficient. We want the order we get here though. Opts1 = lists:foldl(fun({override, O}, OptsAcc) -> - lists:foldl(fun({deps, Value}, OptsAcc1) -> - set(OptsAcc1, {deps,default}, Value); - ({Key, Value}, OptsAcc1) -> - set(OptsAcc1, Key, Value) - end, OptsAcc, O); + override_opt(O, OptsAcc); (_, OptsAcc) -> OptsAcc - end, Opts, Overrides), - - Opts2 = lists:foldl(fun({override, N, O}, OptsAcc) when N =:= Name -> - lists:foldl(fun({deps, Value}, OptsAcc1) -> - set(OptsAcc1, {deps,default}, Value); - ({Key, Value}, OptsAcc1) -> - set(OptsAcc1, Key, Value) - end, OptsAcc, O); + end, Opts, Overrides), + + Opts2 = lists:foldl(fun({add, O}, OptsAcc) -> + add_opt(O, OptsAcc); + (_, OptsAcc) -> + OptsAcc + end, Opts1, Overrides), + + Opts3 = lists:foldl(fun({del, O}, OptsAcc) -> + del_opt(O, OptsAcc); (_, OptsAcc) -> OptsAcc - end, Opts1, Overrides), - - lists:foldl(fun({add, N, O}, OptsAcc) when N =:= Name -> - lists:foldl(fun({deps, Value}, OptsAcc1) -> - OldValue = ?MODULE:get(OptsAcc1, {deps,default}, []), - set(OptsAcc1, {deps,default}, Value++OldValue); - ({Key, Value}, OptsAcc1) -> - OldValue = ?MODULE:get(OptsAcc1, Key, []), - set(OptsAcc1, Key, Value++OldValue) - end, OptsAcc, O); - (_, OptsAcc) -> - OptsAcc - end, Opts2, Overrides). + end, Opts2, Overrides), + + Opts4 = lists:foldl(fun({override, N, O}, OptsAcc) when N =:= Name -> + override_opt(O, OptsAcc); + (_, OptsAcc) -> + OptsAcc + end, Opts3, Overrides), + + Opts5 = lists:foldl(fun({add, N, O}, OptsAcc) when N =:= Name -> + add_opt(O, OptsAcc); + (_, OptsAcc) -> + OptsAcc + end, Opts4, Overrides), + + Opts6 = lists:foldl(fun({del, N, O}, OptsAcc) when N =:= Name -> + del_opt(O, OptsAcc); + (_, OptsAcc) -> + OptsAcc + end, Opts5, Overrides), + + Opts6. add_to_profile(Opts, Profile, KVs) when is_atom(Profile), is_list(KVs) -> Profiles = ?MODULE:get(Opts, profiles, []), @@ -133,6 +139,31 @@ merge_opts(NewOpts, OldOpts) -> %% Internal functions +add_opt(Opts1, Opts2) -> + lists:foldl(fun({deps, Value}, OptsAcc) -> + OldValue = ?MODULE:get(OptsAcc, {deps,default}, []), + set(OptsAcc, {deps,default}, Value++OldValue); + ({Key, Value}, OptsAcc) -> + OldValue = ?MODULE:get(OptsAcc, Key, []), + set(OptsAcc, Key, Value++OldValue) + end, Opts2, Opts1). + +del_opt(Opts1, Opts2) -> + lists:foldl(fun({deps, Value}, OptsAcc) -> + OldValue = ?MODULE:get(OptsAcc, {deps,default}, []), + set(OptsAcc, {deps,default}, OldValue--Value); + ({Key, Value}, OptsAcc) -> + OldValue = ?MODULE:get(OptsAcc, Key, []), + set(OptsAcc, Key, OldValue--Value) + end, Opts2, Opts1). + +override_opt(Opts1, Opts2) -> + lists:foldl(fun({deps, Value}, OptsAcc) -> + set(OptsAcc, {deps,default}, Value); + ({Key, Value}, OptsAcc) -> + set(OptsAcc, Key, Value) + end, Opts2, Opts1). + %% %% Function for dict:merge/3 (in merge_opts/2) to merge options by priority. %% diff --git a/src/rebar_prv_bare_compile.erl b/src/rebar_prv_bare_compile.erl index c29a711..5d3e977 100644 --- a/src/rebar_prv_bare_compile.erl +++ b/src/rebar_prv_bare_compile.erl @@ -46,7 +46,9 @@ do(State) -> [AppInfo] = rebar_state:project_apps(State), AppInfo1 = rebar_app_info:out_dir(AppInfo, rebar_dir:get_cwd()), - rebar_prv_compile:compile(State, AppInfo1), + + %% run compile in the default namespace + rebar_prv_compile:compile(rebar_state:namespace(State, default), AppInfo1), rebar_utils:cleanup_code_path(OrigPath), diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index f800610..9e71ee7 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -227,15 +227,20 @@ add_hooks(Opts, State) -> case {readable(State), lists:keyfind(ct_hooks, 1, Opts)} of {false, _} -> Opts; - {true, false} -> - [{ct_hooks, [cth_readable_failonly, cth_readable_shell, cth_retry]} | Opts]; - {true, {ct_hooks, Hooks}} -> + {Other, false} -> + [{ct_hooks, [cth_readable_failonly, readable_shell_type(Other), cth_retry]} | Opts]; + {Other, {ct_hooks, Hooks}} -> %% Make sure hooks are there once only. - ReadableHooks = [cth_readable_failonly, cth_readable_shell, cth_retry], - NewHooks = (Hooks -- ReadableHooks) ++ ReadableHooks, + ReadableHooks = [cth_readable_failonly, readable_shell_type(Other), cth_retry], + AllReadableHooks = [cth_readable_failonly, cth_retry, + cth_readable_shell, cth_readable_compact_shell], + NewHooks = (Hooks -- AllReadableHooks) ++ ReadableHooks, lists:keyreplace(ct_hooks, 1, Opts, {ct_hooks, NewHooks}) end. +readable_shell_type(true) -> cth_readable_shell; +readable_shell_type(compact) -> cth_readable_compact_shell. + select_tests(_, _, _, {error, _} = Error) -> Error; select_tests(State, ProjectApps, CmdOpts, CfgOpts) -> %% set application env if sys_config argument is provided @@ -425,20 +430,21 @@ append(A, B) -> A ++ B. add_transforms(CTOpts, State) when is_list(CTOpts) -> case readable(State) of - true -> - ReadableTransform = [{parse_transform, cth_readable_transform}], - (CTOpts -- ReadableTransform) ++ ReadableTransform; false -> - CTOpts + CTOpts; + Other when Other == true; Other == compact -> + ReadableTransform = [{parse_transform, cth_readable_transform}], + (CTOpts -- ReadableTransform) ++ ReadableTransform end; add_transforms({error, _} = Error, _State) -> Error. readable(State) -> {RawOpts, _} = rebar_state:command_parsed_args(State), case proplists:get_value(readable, RawOpts) of - true -> true; - false -> false; - undefined -> rebar_state:get(State, ct_readable, true) + "true" -> true; + "false" -> false; + "compact" -> compact; + undefined -> rebar_state:get(State, ct_readable, compact) end. test_dirs(State, Apps, Opts) -> @@ -762,7 +768,7 @@ ct_opts(_State) -> {scale_timetraps, undefined, "scale_timetraps", boolean, help(scale_timetraps)}, {create_priv_dir, undefined, "create_priv_dir", string, help(create_priv_dir)}, {include, undefined, "include", string, help(include)}, - {readable, undefined, "readable", boolean, help(readable)}, + {readable, undefined, "readable", string, help(readable)}, {verbose, $v, "verbose", boolean, help(verbose)}, {name, undefined, "name", atom, help(name)}, {sname, undefined, "sname", atom, help(sname)}, @@ -831,7 +837,7 @@ help(create_priv_dir) -> help(include) -> "Directories containing additional include files"; help(readable) -> - "Shows test case names and only displays logs to shell on failures"; + "Shows test case names and only displays logs to shell on failures (true | compact | false)"; help(verbose) -> "Verbose output"; help(name) -> diff --git a/src/rebar_prv_local_install.erl b/src/rebar_prv_local_install.erl index bb019c4..c41812f 100644 --- a/src/rebar_prv_local_install.erl +++ b/src/rebar_prv_local_install.erl @@ -64,7 +64,7 @@ format_error(Reason) -> bin_contents(OutputDir) -> <<"#!/usr/bin/env sh -erl -pz ", (rebar_utils:to_binary(OutputDir))/binary,"/*/ebin +sbtu +A0 -noshell -boot start_clean -s rebar3 main $REBAR3_ERL_ARGS -extra \"$@\" +erl -pz ", (rebar_utils:to_binary(OutputDir))/binary,"/*/ebin +sbtu +A1 -noshell -boot start_clean -s rebar3 main $REBAR3_ERL_ARGS -extra \"$@\" ">>. extract_escript(State, ScriptPath) -> diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl index 9a320ad..af8d99f 100644 --- a/src/rebar_prv_shell.erl +++ b/src/rebar_prv_shell.erl @@ -76,6 +76,9 @@ init(State) -> "shell. (E.g. --apps app1,app2,app3) Defaults " "to rebar.config {shell, [{apps, Apps}]} or " "relx apps if not specified."}, + {start_clean, undefined, "start-clean", boolean, + "Cancel any applications in the 'apps' list " + "or release."}, {user_drv_args, undefined, "user_drv_args", string, "Arguments passed to user_drv start function for " "creating custom shells."}]} @@ -311,7 +314,12 @@ find_apps_option(State) -> {Opts, _} = rebar_state:command_parsed_args(State), case debug_get_value(apps, Opts, no_value, "Found shell apps from command line option.") of - no_value -> no_value; + no_value -> + case debug_get_value(start_clean, Opts, false, + "Found start-clean argument to disable apps") of + false -> no_value; + true -> [] + end; AppsStr -> [ list_to_atom(AppStr) || AppStr <- rebar_string:lexemes(AppsStr, " ,:") ] diff --git a/src/rebar_prv_upgrade.erl b/src/rebar_prv_upgrade.erl index cd75672..e4469cf 100644 --- a/src/rebar_prv_upgrade.erl +++ b/src/rebar_prv_upgrade.erl @@ -43,6 +43,19 @@ init(State) -> -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. do(State) -> + Cwd = rebar_state:dir(State), + Providers = rebar_state:providers(State), + rebar_hooks:run_project_and_app_hooks(Cwd, pre, ?PROVIDER, Providers, State), + case do_(State) of + {ok, NewState} -> + rebar_hooks:run_project_and_app_hooks(Cwd, post, ?PROVIDER, Providers, NewState), + {ok, NewState}; + Other -> + rebar_hooks:run_project_and_app_hooks(Cwd, post, ?PROVIDER, Providers, State), + Other + end. + +do_(State) -> {Args, _} = rebar_state:command_parsed_args(State), Locks = rebar_state:get(State, {locks, default}, []), %% We have 3 sources of dependencies to upgrade from: diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 604abb8..2ded481 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -73,7 +73,8 @@ list_dir/1, user_agent/0, reread_config/1, - get_proxy_auth/0]). + get_proxy_auth/0, + is_list_of_strings/1]). %% for internal use only @@ -919,3 +920,11 @@ get_proxy_auth() -> undefined -> []; {ok, ProxyAuth} -> ProxyAuth end. + +-spec rebar_utils:is_list_of_strings(term()) -> boolean(). +is_list_of_strings(List) when not is_list(hd(List)) -> + false; +is_list_of_strings(List) when is_list(hd(List)) -> + true; +is_list_of_strings(List) when is_list(List) -> + true. diff --git a/test/rebar_compile_SUITE.erl b/test/rebar_compile_SUITE.erl index c5336cf..6470b06 100644 --- a/test/rebar_compile_SUITE.erl +++ b/test/rebar_compile_SUITE.erl @@ -39,8 +39,18 @@ only_default_transitive_deps/1, clean_all/1, override_deps/1, - profile_override_deps/1, + override_add_deps/1, + override_del_deps/1, + override_opts/1, + override_add_opts/1, + override_del_opts/1, profile_deps/1, + profile_override_deps/1, + profile_override_add_deps/1, + profile_override_del_deps/1, + profile_override_opts/1, + profile_override_add_opts/1, + profile_override_del_opts/1, deps_build_in_prod/1, include_file_relative_to_working_directory/1, include_file_in_src/1, @@ -75,9 +85,12 @@ all() -> delete_beam_if_source_deleted, deps_in_path, checkout_priority, highest_version_of_pkg_dep, parse_transform_test, erl_first_files_test, mib_test, - umbrella_mib_first_test, only_default_transitive_deps, - clean_all, override_deps, profile_override_deps, deps_build_in_prod, - profile_override_deps, profile_deps, deps_build_in_prod, + umbrella_mib_first_test, only_default_transitive_deps, clean_all, + profile_deps, deps_build_in_prod, + override_deps, override_add_deps, override_del_deps, + override_opts, override_add_opts, override_del_opts, + profile_override_deps, profile_override_add_deps, profile_override_del_deps, + profile_override_opts, profile_override_add_opts, profile_override_del_opts, include_file_relative_to_working_directory, include_file_in_src, include_file_relative_to_working_directory_test, include_file_in_src_test, include_file_in_src_test_multiapp, @@ -1272,44 +1285,395 @@ clean_all(Config) -> {app, PkgName, invalid}]}). override_deps(Config) -> - mock_git_resource:mock([{deps, [{some_dep, "0.0.1"},{other_dep, "0.0.1"}]}]), Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), + {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), + mock_git_resource:mock([{deps, SrcDeps}]), + RebarConfig = [ {deps, TopDeps}, {overrides, [ {override, some_dep, [ - {deps, []} - ]} - ]} - ], + {deps, []} + ]} + ]} + ], + rebar_test_utils:run_and_check( + Config, RebarConfig, ["compile"], + {ok, [{dep, "some_dep"}, + {dep_not_exist, "other_dep"}]} + ). + +override_add_deps(Config) -> + Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), + TopDeps = rebar_test_utils:top_level_deps(Deps), + + DepA = {dep_a, "0.0.1", {git, "http://site.com/dep_a.git", {tag, "0.0.1"}}}, + DepB = {dep_b, "0.0.1", {git, "http://site.com/dep_b.git", {tag, "0.0.1"}}}, + DepC = {dep_c, "0.0.1", {git, "http://site.com/dep_c.git", {tag, "0.0.1"}}}, + + {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), + mock_git_resource:mock([{deps, [DepA, DepB, DepC | SrcDeps]}]), + + RebarConfig = [ + {deps, TopDeps}, + {overrides, [ + {add, some_dep, [ + {deps, [DepA, DepB]} + ]}, + {add, [ + {deps, [DepC]} + ]} + ]} + ], rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], - {ok, [{dep, "some_dep"},{dep_not_exist, "other_dep"}]} + {ok, [{dep, "some_dep"}, + {dep, "other_dep"}, + {dep, "dep_a"}, + {dep, "dep_b"}, + {dep, "dep_c"}]} ). +override_del_deps(Config) -> + Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"dep_a", "0.0.1", []}, + {"dep_b", "0.0.1", []}, + {"dep_c", "0.0.1", []}]}, + {"other_dep", "0.0.1", [{"dep_c", "0.0.1", []}, + {"dep_d", "0.0.1", []}]}]), + TopDeps = rebar_test_utils:top_level_deps(Deps), + + DepA = {dep_a, "0.0.1", {git, "https://example.org/user/dep_a.git", {tag, "0.0.1"}}}, + DepB = {dep_b, "0.0.1", {git, "https://example.org/user/dep_b.git", {tag, "0.0.1"}}}, + DepC = {dep_c, "0.0.1", {git, "https://example.org/user/dep_c.git", {tag, "0.0.1"}}}, + + {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), + mock_git_resource:mock([{deps, SrcDeps}]), + + RebarConfig = [ + {deps, TopDeps}, + {overrides, [ + {del, some_dep, [ + {deps, [DepA, DepB]} + ]}, + {del, [ + {deps, [DepC]} + ]} + ]} + ], + + rebar_test_utils:run_and_check( + Config, RebarConfig, ["compile"], + {ok, [{dep, "some_dep"}, + {dep, "other_dep"}, + {dep_not_exist, "dep_a"}, + {dep_not_exist, "dep_b"}, + {dep_not_exist, "dep_c"}, + {dep, "dep_d"}]} + ). + +override_opts(Config) -> + AppDir = ?config(apps, Config), + + 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]), + + RebarConfig = [ + {erl_opts, [ + compressed, + warn_missing_spec + ]}, + {overrides, [ + {override, [ + {erl_opts, [compressed]} + ]} + ]} + ], + + rebar_test_utils:create_config(AppDir, RebarConfig), + + rebar_test_utils:run_and_check( + Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), + + Path = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), + code:add_patha(Path), + + Mod = list_to_atom("not_a_real_src_" ++ Name), + + true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), + false = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])). + +override_add_opts(Config) -> + AppDir = ?config(apps, Config), + + 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]), + + RebarConfig = [ + {erl_opts, [ + warn_missing_spec + ]}, + {overrides, [ + {add, [ + {erl_opts, [compressed]} + ]} + ]} + ], + + rebar_test_utils:create_config(AppDir, RebarConfig), + + rebar_test_utils:run_and_check( + Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), + + Path = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), + code:add_patha(Path), + + Mod = list_to_atom("not_a_real_src_" ++ Name), + + true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), + true = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])). + +override_del_opts(Config) -> + AppDir = ?config(apps, Config), + + 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]), + + RebarConfig = [ + {erl_opts, [ + compressed, + warn_missing_spec + ]}, + {overrides, [ + {del, [ + {erl_opts, [warn_missing_spec]} + ]} + ]} + ], + + rebar_test_utils:create_config(AppDir, RebarConfig), + + rebar_test_utils:run_and_check( + Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), + + Path = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), + code:add_patha(Path), + + Mod = list_to_atom("not_a_real_src_" ++ Name), + + true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), + false = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])). + profile_override_deps(Config) -> Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), + {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), RebarConfig = [ {deps, TopDeps}, - {profiles, [{a, - [{overrides, [ - {override, some_dep, [ - {deps, []} - ]} - ]} + {profiles, [ + {a, [ + {overrides, [ + {override, some_dep, [ + {deps, []} ]} + ]} + ]} ]}], rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "a", "compile"], - {ok, [{dep, "some_dep"},{dep_not_exist, "other_dep"}]} + {ok, [{dep, "some_dep"}, + {dep_not_exist, "other_dep"}]} + ). + +profile_override_add_deps(Config) -> + Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), + TopDeps = rebar_test_utils:top_level_deps(Deps), + + DepA = {dep_a, "0.0.1", {git, "http://site.com/dep_a.git", {tag, "0.0.1"}}}, + DepB = {dep_b, "0.0.1", {git, "http://site.com/dep_b.git", {tag, "0.0.1"}}}, + DepC = {dep_c, "0.0.1", {git, "http://site.com/dep_c.git", {tag, "0.0.1"}}}, + + {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), + mock_git_resource:mock([{deps, [DepA, DepB, DepC | SrcDeps]}]), + + RebarConfig = [ + {deps, TopDeps}, + {profiles, [ + {a, [ + {overrides, [ + {add, some_dep, [ + {deps, [DepA, DepB]} + ]}, + {add, [ + {deps, [DepC]} + ]} + ]} + ]} + ]} + ], + rebar_test_utils:run_and_check( + Config, RebarConfig, ["as", "a", "compile"], + {ok, [{dep, "some_dep"}, + {dep, "other_dep"}, + {dep, "dep_a"}, + {dep, "dep_b"}, + {dep, "dep_c"}]} + ). + +profile_override_del_deps(Config) -> + Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"dep_a", "0.0.1", []}, + {"dep_b", "0.0.1", []}, + {"dep_c", "0.0.1", []}]}, + {"other_dep", "0.0.1", [{"dep_c", "0.0.1", []}, + {"dep_d", "0.0.1", []}]}]), + TopDeps = rebar_test_utils:top_level_deps(Deps), + + DepA = {dep_a, "0.0.1", {git, "https://example.org/user/dep_a.git", {tag, "0.0.1"}}}, + DepB = {dep_b, "0.0.1", {git, "https://example.org/user/dep_b.git", {tag, "0.0.1"}}}, + DepC = {dep_c, "0.0.1", {git, "https://example.org/user/dep_c.git", {tag, "0.0.1"}}}, + + {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), + mock_git_resource:mock([{deps, SrcDeps}]), + + RebarConfig = [ + {deps, TopDeps}, + {profiles, [ + {a, [ + {overrides, [ + {del, some_dep, [ + {deps, [DepA, DepB]} + ]}, + {del, [ + {deps, [DepC]} + ]} + ]} + ]} + ]} + ], + rebar_test_utils:run_and_check( + Config, RebarConfig, ["as", "a", "compile"], + {ok, [{dep, "some_dep"}, + {dep, "other_dep"}, + {dep_not_exist, "dep_a"}, + {dep_not_exist, "dep_b"}, + {dep_not_exist, "dep_c"}, + {dep, "dep_d"}]} ). +profile_override_opts(Config) -> + AppDir = ?config(apps, Config), + + 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]), + + RebarConfig = [ + {erl_opts, [ + compressed, + warn_missing_spec + ]}, + {profiles, [ + {a, [ + {overrides, [ + {override, [ + {erl_opts, [compressed]} + ]} + ]} + ]} + ]} + ], + + rebar_test_utils:create_config(AppDir, RebarConfig), + + rebar_test_utils:run_and_check( + Config, RebarConfig, ["as", "a", "compile"], {ok, [{app, Name}]}), + + Path = filename:join([AppDir, "_build", "a", "lib", Name, "ebin"]), + code:add_patha(Path), + + Mod = list_to_atom("not_a_real_src_" ++ Name), + + true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), + false = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])). + +profile_override_add_opts(Config) -> + AppDir = ?config(apps, Config), + + 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]), + + RebarConfig = [ + {erl_opts, [ + warn_missing_spec + ]}, + {profiles, [ + {a, [ + {overrides, [ + {add, [ + {erl_opts, [compressed]} + ]} + ]} + ]} + ]} + ], + + rebar_test_utils:create_config(AppDir, RebarConfig), + + rebar_test_utils:run_and_check( + Config, RebarConfig, ["as", "a", "compile"], {ok, [{app, Name}]}), + + Path = filename:join([AppDir, "_build", "a", "lib", Name, "ebin"]), + code:add_patha(Path), + + Mod = list_to_atom("not_a_real_src_" ++ Name), + + true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), + true = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])). + +profile_override_del_opts(Config) -> + AppDir = ?config(apps, Config), + + 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]), + + RebarConfig = [ + {erl_opts, [ + compressed, + warn_missing_spec + ]}, + {profiles, [ + {a, [ + {overrides, [ + {del, [ + {erl_opts, [warn_missing_spec]} + ]} + ]} + ]} + ]} + ], + + rebar_test_utils:create_config(AppDir, RebarConfig), + + rebar_test_utils:run_and_check( + Config, RebarConfig, ["as", "a", "compile"], {ok, [{app, Name}]}), + + Path = filename:join([AppDir, "_build", "a", "lib", Name, "ebin"]), + code:add_patha(Path), + + Mod = list_to_atom("not_a_real_src_" ++ Name), + + true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), + false = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])). + profile_deps(Config) -> Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), diff --git a/test/rebar_hooks_SUITE.erl b/test/rebar_hooks_SUITE.erl index a36dbe1..1f3edd2 100644 --- a/test/rebar_hooks_SUITE.erl +++ b/test/rebar_hooks_SUITE.erl @@ -13,6 +13,7 @@ run_hooks_for_plugins/1, eunit_app_hooks/1, deps_hook_namespace/1, + bare_compile_hooks_default_ns/1, deps_clean_hook_namespace/1]). -include_lib("common_test/include/ct.hrl"). @@ -37,7 +38,7 @@ end_per_testcase(_, _Config) -> all() -> [build_and_clean_app, run_hooks_once, run_hooks_once_profiles, escriptize_artifacts, run_hooks_for_plugins, deps_hook_namespace, - deps_clean_hook_namespace, eunit_app_hooks]. + bare_compile_hooks_default_ns, deps_clean_hook_namespace, eunit_app_hooks]. %% Test post provider hook cleans compiled project app, leaving it invalid build_and_clean_app(Config) -> @@ -135,6 +136,22 @@ deps_hook_namespace(Config) -> {ok, [{dep, "some_dep"}]} ). +%% tests that hooks to compile when running bare compile run in the default namespace +bare_compile_hooks_default_ns(Config) -> + AppDir = ?config(apps, Config), + + 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]), + + RConfFile = rebar_test_utils:create_config(AppDir, + [{provider_hooks, [{post, [{compile, clean}]}]}]), + {ok, RConf} = file:consult(RConfFile), + rebar_test_utils:run_and_check( + Config, RConf, ["bare", "compile", "--paths", "."], + {ok, []} + ). + deps_clean_hook_namespace(Config) -> mock_git_resource:mock([{deps, [{some_dep, "0.0.1"}]}]), Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", []}]), diff --git a/test/rebar_utils_SUITE.erl b/test/rebar_utils_SUITE.erl index e4a5bd3..233fcff 100644 --- a/test/rebar_utils_SUITE.erl +++ b/test/rebar_utils_SUITE.erl @@ -32,7 +32,8 @@ blacklisted_otp_version/1, sh_does_not_miss_messages/1, tup_merge/1, - proxy_auth/1]). + proxy_auth/1, + is_list_of_strings/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). @@ -48,7 +49,7 @@ all() -> [{group, args_to_tasks}, sh_does_not_miss_messages, tup_merge, - proxy_auth]. + proxy_auth, is_list_of_strings]. groups() -> [{args_to_tasks, [], [empty_arglist, @@ -312,3 +313,9 @@ restore_proxy_env(ProxyEnvKey, false) -> os:putenv(ProxyEnvKey, ""); restore_proxy_env(ProxyEnvKey, ProxySpec) -> os:putenv(ProxyEnvKey, ProxySpec). + +is_list_of_strings(_Config) -> + ?assert(rebar_utils:is_list_of_strings(["foo"])), + ?assert(rebar_utils:is_list_of_strings([])), + ?assert(rebar_utils:is_list_of_strings("")), + ?assert(rebar_utils:is_list_of_strings("foo") == false). |