summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Brown <derekbrown121@gmail.com>2015-06-02 15:12:12 -0400
committerTristan Sloughter <t@crashfast.com>2015-07-24 21:27:39 -0500
commit04fedc7422c26002785f6e7cb6e814fdb8a2f0dd (patch)
treeb6c3cdfd066db917f5de4a651f36484e36b17d03
parent5cbc22c45d09f49d3867d71f4aac78326b9a8493 (diff)
Add functions to validate OTP release in use
In the spirit of Original Rebar's "require_min_otp_vsn", this adds rebar_utils:check_min_otp_version/1 (taking a string containing the minimum version) and rebar_utils:check_blacklisted_otp_versions/1 (taking a list of regular expression strings), as well as tests in rebar_utils_SUITE. They're currently only called by the tests- how/where to best place calls to them from non-test code needs to be determined (at which point two corresponding rebar.config keys can be supported). For example, the version probably shouldn't be enforced when just running "rebar3 help".
-rw-r--r--src/rebar_utils.erl46
-rw-r--r--test/rebar_utils_SUITE.erl51
2 files changed, 95 insertions, 2 deletions
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index 6eb4f4b..26125a3 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -60,7 +60,9 @@
set_httpc_options/0,
escape_chars/1,
escape_double_quotes/1,
- escape_double_quotes_weak/1]).
+ escape_double_quotes_weak/1,
+ check_min_otp_version/1,
+ check_blacklisted_otp_versions/1]).
%% for internal use only
-export([otp_release/0]).
@@ -299,10 +301,52 @@ line_count(PatchLines) ->
Tokenized = string:tokens(PatchLines, "\n"),
{ok, length(Tokenized)}.
+check_min_otp_version(undefined) ->
+ ok;
+check_min_otp_version(MinOtpVersion) ->
+ %% Fully-qualify with ?MODULE so the function can be meck'd in rebar_utils_SUITE
+ OtpRelease = ?MODULE:otp_release(),
+ {MinMajor, MinMinor} = split_version(MinOtpVersion),
+ {OtpMajor, OtpMinor} = split_version(OtpRelease),
+
+ case {OtpMajor, OtpMinor} >= {MinMajor, MinMinor} of
+ true ->
+ ?DEBUG("~s satisfies the requirement for minimum OTP version ~s",
+ [OtpRelease, MinOtpVersion]);
+ false ->
+ ?ABORT("OTP release ~s or later is required. Verion in use: ~s",
+ [MinOtpVersion, OtpRelease])
+ end.
+
+check_blacklisted_otp_versions(undefined) ->
+ ok;
+check_blacklisted_otp_versions(BlacklistedRegexes) ->
+ %% Fully-qualify with ?MODULE so the function can be meck'd in rebar_utils_SUITE
+ OtpRelease = ?MODULE:otp_release(),
+ lists:foreach(
+ fun(BlacklistedRegex) -> abort_if_blacklisted(BlacklistedRegex, OtpRelease) end,
+ BlacklistedRegexes).
+
+abort_if_blacklisted(BlacklistedRegex, OtpRelease) ->
+ case re:run(OtpRelease, BlacklistedRegex, [{capture, none}]) of
+ match ->
+ ?ABORT("OTP release ~s matches blacklisted version ~s",
+ [OtpRelease, BlacklistedRegex]);
+ nomatch ->
+ ?DEBUG("~s does not match blacklisted OTP version ~s",
+ [OtpRelease, BlacklistedRegex])
+ end.
+
+
%% ====================================================================
%% Internal functions
%% ====================================================================
+split_version(Version) ->
+ list_to_tuple(lists:map(
+ fun(S) -> list_to_integer(S) end,
+ string:tokens(Version, "."))).
+
otp_release() ->
otp_release1(erlang:system_info(otp_release)).
diff --git a/test/rebar_utils_SUITE.erl b/test/rebar_utils_SUITE.erl
index f04ab63..d766af4 100644
--- a/test/rebar_utils_SUITE.erl
+++ b/test/rebar_utils_SUITE.erl
@@ -1,6 +1,8 @@
-module(rebar_utils_SUITE).
-export([all/0,
+ init_per_testcase/2,
+ end_per_testcase/2,
groups/0,
init_per_group/2,
end_per_group/2,
@@ -22,12 +24,22 @@
task_with_flag_with_commas/1,
task_with_multiple_flags/1,
special_task_do/1,
+ valid_otp_version/1,
+ valid_otp_version_equal/1,
+ invalid_otp_version/1,
+ nonblacklisted_otp_version/1,
+ blacklisted_otp_version/1,
sh_does_not_miss_messages/1]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
-include_lib("kernel/include/file.hrl").
+init_per_testcase(_, Config) ->
+ rebar_test_utils:init_rebar_state(Config).
+
+end_per_testcase(_, _Config) ->
+ catch meck:unload().
all() ->
[{group, args_to_tasks},
@@ -51,7 +63,13 @@ groups() ->
task_with_flag_with_trailing_comma,
task_with_flag_with_commas,
task_with_multiple_flags,
- special_task_do]}].
+ special_task_do,
+ valid_otp_version,
+ valid_otp_version_equal,
+ invalid_otp_version,
+ nonblacklisted_otp_version,
+ blacklisted_otp_version
+ ]}].
init_per_group(_, Config) -> Config.
end_per_group(_, Config) -> Config.
@@ -120,6 +138,37 @@ special_task_do(_Config) ->
"do",
"bar,",
"baz"]).
+
+valid_otp_version(_Config) ->
+ meck:new(rebar_utils, [passthrough]),
+ meck:expect(rebar_utils, otp_release, fun() -> "42.4" end),
+ rebar_utils:check_min_otp_version("42.3"),
+ meck:unload(rebar_utils).
+
+valid_otp_version_equal(_Config) ->
+ meck:new(rebar_utils, [passthrough]),
+ meck:expect(rebar_utils, otp_release, fun() -> "42.3" end),
+ rebar_utils:check_min_otp_version("42.3"),
+ meck:unload(rebar_utils).
+
+invalid_otp_version(_Config) ->
+ meck:new(rebar_utils, [passthrough]),
+ meck:expect(rebar_utils, otp_release, fun() -> "17.4" end),
+ ?assertException(throw, rebar_abort, rebar_utils:check_min_otp_version("42.3")),
+ meck:unload(rebar_utils).
+
+nonblacklisted_otp_version(_Config) ->
+ meck:new(rebar_utils, [passthrough]),
+ meck:expect(rebar_utils, otp_release, fun() -> "42.4" end),
+ rebar_utils:check_blacklisted_otp_versions(["1\\.2", "42\\.3"]),
+ meck:unload(rebar_utils).
+
+blacklisted_otp_version(_Config) ->
+ meck:new(rebar_utils, [passthrough]),
+ meck:expect(rebar_utils, otp_release, fun() -> "42.4" end),
+ ?assertException(throw, rebar_abort, rebar_utils:check_blacklisted_otp_versions(["1\\.2", "42\\.[1-4]"])),
+ meck:unload(rebar_utils).
+
sh_does_not_miss_messages(_Config) ->
Source = "~nmain(_) ->~n io:format(\"donotmissme\").~n",
file:write_file("do_not_miss_messages", io_lib:format(Source,[])),