Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

480 rader
19 KiB

  1. -module(rebar_deps_SUITE).
  2. -compile(export_all).
  3. -include_lib("common_test/include/ct.hrl").
  4. -include_lib("eunit/include/eunit.hrl").
  5. all() -> [sub_app_deps, newly_added_dep, newly_added_after_empty_lock,
  6. http_proxy_settings, https_proxy_settings,
  7. http_os_proxy_settings, https_os_proxy_settings,
  8. semver_matching_lt, semver_matching_lte, semver_matching_gt,
  9. valid_version, {group, git}, {group, pkg}].
  10. groups() ->
  11. [{all, [], [flat, pick_highest_left, pick_highest_right,
  12. pick_smallest1, pick_smallest2,
  13. circular1, circular2, circular_skip]},
  14. {git, [], [{group, all}]},
  15. {pkg, [], [{group, all}]}].
  16. init_per_suite(Config) ->
  17. application:start(meck),
  18. Config.
  19. end_per_suite(_Config) ->
  20. application:stop(meck).
  21. init_per_group(git, Config) ->
  22. [{deps_type, git} | Config];
  23. init_per_group(pkg, Config) ->
  24. [{deps_type, pkg} | Config];
  25. init_per_group(_, Config) ->
  26. Config.
  27. end_per_group(_, Config) ->
  28. Config.
  29. init_per_testcase(valid_version, Config) ->
  30. rebar_test_utils:init_rebar_state(Config);
  31. init_per_testcase(semver_matching_lt, Config) ->
  32. rebar_test_utils:init_rebar_state(Config);
  33. init_per_testcase(semver_matching_lte, Config) ->
  34. rebar_test_utils:init_rebar_state(Config);
  35. init_per_testcase(semver_matching_gt, Config) ->
  36. rebar_test_utils:init_rebar_state(Config);
  37. init_per_testcase(newly_added_after_empty_lock, Config) ->
  38. rebar_test_utils:init_rebar_state(Config);
  39. init_per_testcase(newly_added_dep, Config) ->
  40. rebar_test_utils:init_rebar_state(Config);
  41. init_per_testcase(sub_app_deps, Config) ->
  42. rebar_test_utils:init_rebar_state(Config);
  43. init_per_testcase(http_proxy_settings, Config) ->
  44. %% Create private rebar.config
  45. Priv = ?config(priv_dir, Config),
  46. GlobalDir = filename:join(Priv, "global"),
  47. GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]),
  48. GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]),
  49. meck:new(rebar_dir, [passthrough]),
  50. meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end),
  51. meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end),
  52. %% Insert proxy variables into config
  53. rebar_test_utils:create_config(GlobalConfigDir,
  54. [{http_proxy, "http://localhost:1234"}
  55. ]),
  56. rebar_test_utils:init_rebar_state(Config);
  57. init_per_testcase(https_proxy_settings, Config) ->
  58. SupportsHttpsProxy = case erlang:system_info(otp_release) of
  59. "R16"++_ -> true;
  60. "R"++_ -> false;
  61. _ -> true % 17 and up don't have a "R" in the version
  62. end,
  63. if not SupportsHttpsProxy ->
  64. {skip, https_proxy_unsupported_before_R16};
  65. SupportsHttpsProxy ->
  66. %% Create private rebar.config
  67. Priv = ?config(priv_dir, Config),
  68. GlobalDir = filename:join(Priv, "global"),
  69. GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]),
  70. GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]),
  71. meck:new(rebar_dir, [passthrough]),
  72. meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end),
  73. meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end),
  74. %% Insert proxy variables into config
  75. rebar_test_utils:create_config(GlobalConfigDir,
  76. [{https_proxy, "http://localhost:1234"}
  77. ]),
  78. %% Add a bad value by default to show config overtakes default
  79. os:putenv("https_proxy", "unparseable-garbage"),
  80. rebar_test_utils:init_rebar_state(Config)
  81. end;
  82. init_per_testcase(http_os_proxy_settings, Config) ->
  83. %% Create private rebar.config
  84. Priv = ?config(priv_dir, Config),
  85. GlobalDir = filename:join(Priv, "global"),
  86. GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]),
  87. GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]),
  88. meck:new(rebar_dir, [passthrough]),
  89. meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end),
  90. meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end),
  91. %% Insert proxy variables into os env, but not config
  92. os:putenv("http_proxy", "http://localhost:1234"),
  93. rebar_test_utils:create_config(GlobalConfigDir, []),
  94. rebar_test_utils:init_rebar_state(Config);
  95. init_per_testcase(https_os_proxy_settings, Config) ->
  96. SupportsHttpsProxy = case erlang:system_info(otp_release) of
  97. "R16"++_ -> true;
  98. "R"++_ -> false;
  99. _ -> true % 17 and up don't have a "R" in the version
  100. end,
  101. if not SupportsHttpsProxy ->
  102. {skip, https_proxy_unsupported_before_R16};
  103. SupportsHttpsProxy ->
  104. %% Create private rebar.config
  105. Priv = ?config(priv_dir, Config),
  106. GlobalDir = filename:join(Priv, "global"),
  107. GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]),
  108. GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]),
  109. meck:new(rebar_dir, [passthrough]),
  110. meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end),
  111. meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end),
  112. %% Insert proxy variables into os env, not in config
  113. os:putenv("https_proxy", "http://localhost:1234"),
  114. rebar_test_utils:create_config(GlobalConfigDir, []),
  115. rebar_test_utils:init_rebar_state(Config)
  116. end;
  117. init_per_testcase(Case, Config) ->
  118. {Deps, Warnings, Expect} = deps(Case),
  119. Expected = case Expect of
  120. {ok, List} -> {ok, format_expected_deps(List)};
  121. {error, Reason} -> {error, Reason}
  122. end,
  123. DepsType = ?config(deps_type, Config),
  124. mock_warnings(),
  125. [{expect, Expected},
  126. {warnings, Warnings}
  127. | setup_project(Case, Config, rebar_test_utils:expand_deps(DepsType, Deps))].
  128. end_per_testcase(https_proxy_settings, Config) ->
  129. os:putenv("https_proxy", ""),
  130. meck:unload(rebar_dir),
  131. Config;
  132. end_per_testcase(http_proxy_settings, Config) ->
  133. meck:unload(rebar_dir),
  134. Config;
  135. end_per_testcase(http_os_proxy_settings, Config) ->
  136. os:putenv("http_proxy", ""),
  137. meck:unload(rebar_dir),
  138. Config;
  139. end_per_testcase(https_os_proxy_settings, Config) ->
  140. os:putenv("https_proxy", ""),
  141. meck:unload(rebar_dir),
  142. Config;
  143. end_per_testcase(_, Config) ->
  144. meck:unload(),
  145. Config.
  146. format_expected_deps(Deps) ->
  147. [case Dep of
  148. {N,V} -> {dep, N, V};
  149. N -> {dep, N}
  150. end || Dep <- Deps].
  151. %% format:
  152. %% {Spec,
  153. %% [Warning],
  154. %% {ok, Result} | {error, Reason}}
  155. %%
  156. %% Spec is a list of levelled dependencies of two possible forms:
  157. %% - {"Name", Spec}
  158. %% - {"Name", "Vsn", Spec}
  159. %%
  160. %% Warnings are going to match on mocked ?WARN(...)
  161. %% calls to be evaluated. An empty list means we do not care about
  162. %% warnings, not that no warnings will be printed. This means
  163. %% the list of warning isn't interpreted to be exhaustive, and more
  164. %% warnings may be generated than are listed.
  165. deps(flat) ->
  166. {[{"B", []},
  167. {"C", []}],
  168. [],
  169. {ok, ["B", "C"]}};
  170. deps(pick_highest_left) ->
  171. {[{"B", [{"C", "2", []}]},
  172. {"C", "1", []}],
  173. [{"C","2"}],
  174. {ok, ["B", {"C", "1"}]}};
  175. deps(pick_highest_right) ->
  176. {[{"B", "1", []},
  177. {"C", [{"B", "2", []}]}],
  178. [{"B","2"}],
  179. {ok, [{"B","1"}, "C"]}};
  180. deps(pick_smallest1) ->
  181. {[{"B", [{"D", "1", []}]},
  182. {"C", [{"D", "2", []}]}],
  183. [{"D","2"}],
  184. %% we pick D1 because B < C
  185. {ok, ["B","C",{"D","1"}]}};
  186. deps(pick_smallest2) ->
  187. {[{"C", [{"D", "2", []}]},
  188. {"B", [{"D", "1", []}]}],
  189. [{"D","2"}],
  190. %% we pick D1 because B < C
  191. {ok, ["B","C",{"D","1"}]}};
  192. deps(circular1) ->
  193. {[{"B", [{"A", []}]}, % A is the top-level app
  194. {"C", []}],
  195. [],
  196. {error, {rebar_prv_install_deps, {cycles, [[<<"A">>,<<"B">>]]}}}};
  197. deps(circular2) ->
  198. {[{"B", [{"C", [{"B", []}]}]},
  199. {"C", []}],
  200. [],
  201. {error, {rebar_prv_install_deps, {cycles, [[<<"B">>,<<"C">>]]}}}};
  202. deps(circular_skip) ->
  203. %% Never spot the circular dep due to being to low in the deps tree
  204. %% in source deps
  205. {[{"B", [{"C", "2", [{"B", []}]}]},
  206. {"C", "1", [{"D",[]}]}],
  207. [{"C","2"}],
  208. {ok, ["B", {"C","1"}, "D"]}}.
  209. setup_project(Case, Config0, Deps) ->
  210. DepsType = ?config(deps_type, Config0),
  211. Config = rebar_test_utils:init_rebar_state(
  212. Config0,
  213. atom_to_list(Case)++"_"++atom_to_list(DepsType)++"_"
  214. ),
  215. AppDir = ?config(apps, Config),
  216. rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]),
  217. TopDeps = rebar_test_utils:top_level_deps(Deps),
  218. RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]),
  219. {SrcDeps, PkgDeps} = rebar_test_utils:flat_deps(Deps),
  220. mock_git_resource:mock([{deps, SrcDeps}]),
  221. mock_pkg_resource:mock([{pkgdeps, PkgDeps}]),
  222. [{rebarconfig, RebarConf} | Config].
  223. mock_warnings() ->
  224. %% just let it do its thing, we check warnings through
  225. %% the call log.
  226. meck:new(rebar_log, [no_link, passthrough]).
  227. %%% TESTS %%%
  228. flat(Config) -> run(Config).
  229. pick_highest_left(Config) -> run(Config).
  230. pick_highest_right(Config) -> run(Config).
  231. pick_smallest1(Config) -> run(Config).
  232. pick_smallest2(Config) -> run(Config).
  233. circular1(Config) -> run(Config).
  234. circular2(Config) -> run(Config).
  235. circular_skip(Config) -> run(Config).
  236. %% Test that the deps of project apps that have their own rebar.config
  237. %% are included, but that top level rebar.config deps take precedence
  238. sub_app_deps(Config) ->
  239. AppDir = ?config(apps, Config),
  240. Deps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  241. ,{"b", "1.0.0", []}
  242. ,{"b", "2.0.0", []}]),
  243. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  244. mock_git_resource:mock([{deps, SrcDeps}]),
  245. Name = rebar_test_utils:create_random_name("sub_app1_"),
  246. Vsn = rebar_test_utils:create_random_vsn(),
  247. SubAppsDir = filename:join([AppDir, "apps", Name]),
  248. SubDeps = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  249. ,{"b", "2.0.0", []}])),
  250. rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]),
  251. rebar_test_utils:create_config(SubAppsDir, [{deps, SubDeps}]),
  252. TopDeps = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [{"b", "1.0.0", []}])),
  253. {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps}])),
  254. rebar_test_utils:run_and_check(
  255. Config, RebarConfig, ["compile"],
  256. {ok, [{app, Name}, {dep, "a"}, {dep, "b", "1.0.0"}]}).
  257. %% Newly added dependency after locking
  258. newly_added_dep(Config) ->
  259. AppDir = ?config(apps, Config),
  260. Deps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  261. ,{"b", "1.0.0", [{"c", "1.0.0", []}]}
  262. ,{"c", "2.0.0", []}]),
  263. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  264. mock_git_resource:mock([{deps, SrcDeps}]),
  265. Name = rebar_test_utils:create_random_name("app_"),
  266. Vsn = rebar_test_utils:create_random_vsn(),
  267. SubAppsDir = filename:join([AppDir, "apps", Name]),
  268. rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]),
  269. TopDeps = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [{"b", "1.0.0", []}])),
  270. {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps}])),
  271. rebar_test_utils:run_and_check(
  272. Config, RebarConfig, ["compile"],
  273. {ok, [{app, Name}, {dep, "b", "1.0.0"}, {dep, "c", "1.0.0"}]}),
  274. %% Add a and c to top level
  275. TopDeps2 = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  276. ,{"c", "2.0.0", []}
  277. ,{"b", "1.0.0", []}])),
  278. {ok, RebarConfig2} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps2}])),
  279. LockFile = filename:join(AppDir, "rebar.lock"),
  280. RebarConfig3 = rebar_config:merge_locks(RebarConfig2,
  281. rebar_config:consult_lock_file(LockFile)),
  282. %% a should now be installed and c should not change
  283. rebar_test_utils:run_and_check(
  284. Config, RebarConfig3, ["compile"],
  285. {ok, [{app, Name}, {dep, "a"}, {dep, "b", "1.0.0"}, {dep, "c", "1.0.0"}]}).
  286. newly_added_after_empty_lock(Config) ->
  287. AppDir = ?config(apps, Config),
  288. Deps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}]),
  289. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  290. mock_git_resource:mock([{deps, SrcDeps}]),
  291. Name = rebar_test_utils:create_random_name("app_"),
  292. Vsn = rebar_test_utils:create_random_vsn(),
  293. SubAppsDir = filename:join([AppDir, "apps", Name]),
  294. rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]),
  295. TopDeps = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [])),
  296. {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps}])),
  297. rebar_test_utils:run_and_check(
  298. Config, RebarConfig, ["compile"],
  299. {ok, []}),
  300. %% Add a and c to top level
  301. TopDeps2 = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}])),
  302. {ok, RebarConfig2} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps2}])),
  303. LockFile = filename:join(AppDir, "rebar.lock"),
  304. RebarConfig3 = rebar_config:merge_locks(RebarConfig2,
  305. rebar_config:consult_lock_file(LockFile)),
  306. %% a should now be installed and c should not change
  307. rebar_test_utils:run_and_check(
  308. Config, RebarConfig3, ["compile"],
  309. {ok, [{app, Name}, {dep, "a", "1.0.0"}]}).
  310. http_proxy_settings(_Config) ->
  311. %% Load config
  312. rebar_utils:set_httpc_options(),
  313. rebar3:init_config(),
  314. %% Assert variable is right
  315. ?assertEqual({ok,{{"localhost", 1234}, []}},
  316. httpc:get_option(proxy, rebar)).
  317. https_proxy_settings(_Config) ->
  318. %% Load config
  319. rebar_utils:set_httpc_options(),
  320. rebar3:init_config(),
  321. %% Assert variable is right
  322. ?assertEqual({ok,{{"localhost", 1234}, []}},
  323. httpc:get_option(https_proxy, rebar)).
  324. http_os_proxy_settings(_Config) ->
  325. %% Load config
  326. rebar_utils:set_httpc_options(),
  327. rebar3:init_config(),
  328. %% Assert variable is right
  329. ?assertEqual({ok,{{"localhost", 1234}, []}},
  330. httpc:get_option(proxy, rebar)).
  331. https_os_proxy_settings(_Config) ->
  332. %% Load config
  333. rebar_utils:set_httpc_options(),
  334. rebar3:init_config(),
  335. %% Assert variable is right
  336. ?assertEqual({ok,{{"localhost", 1234}, []}},
  337. httpc:get_option(https_proxy, rebar)).
  338. semver_matching_lt(_Config) ->
  339. Dep = <<"test">>,
  340. Dep1 = {Dep, <<"1.0.0">>, Dep},
  341. MaxVsn = <<"0.2.0">>,
  342. Vsns = [<<"0.1.7">>, <<"0.1.9">>, <<"0.1.8">>, <<"0.2.0">>, <<"0.2.1">>],
  343. ?assertEqual([{Dep, <<"0.1.9">>}],
  344. rebar_prv_update:cmpl_(undefined, MaxVsn, Vsns, [], Dep1,
  345. fun ec_semver:lt/2)).
  346. semver_matching_lte(_Config) ->
  347. Dep = <<"test">>,
  348. Dep1 = {Dep, <<"1.0.0">>, Dep},
  349. MaxVsn = <<"0.2.0">>,
  350. Vsns = [<<"0.1.7">>, <<"0.1.9">>, <<"0.1.8">>, <<"0.2.0">>, <<"0.2.1">>],
  351. ?assertEqual([{Dep, <<"0.2.0">>}],
  352. rebar_prv_update:cmpl_(undefined, MaxVsn, Vsns, [], Dep1,
  353. fun ec_semver:lte/2)).
  354. semver_matching_gt(_Config) ->
  355. Dep = <<"test">>,
  356. Dep1 = {Dep, <<"1.0.0">>, Dep},
  357. MaxVsn = <<"0.2.0">>,
  358. Vsns = [<<"0.1.7">>, <<"0.1.9">>, <<"0.1.8">>, <<"0.2.0">>, <<"0.2.1">>],
  359. ?assertEqual([{Dep, <<"0.2.1">>}],
  360. rebar_prv_update:cmp_(undefined, MaxVsn, Vsns, [], Dep1,
  361. fun ec_semver:gt/2)).
  362. semver_matching_gte(_Config) ->
  363. Dep = <<"test">>,
  364. Dep1 = {Dep, <<"1.0.0">>, Dep},
  365. MaxVsn = <<"0.2.0">>,
  366. Vsns = [<<"0.1.7">>, <<"0.1.9">>, <<"0.1.8">>, <<"0.2.0">>],
  367. ?assertEqual([{Dep, <<"0.2.0">>}],
  368. rebar_prv_update:cmp_(undefined, MaxVsn, Vsns, [], Dep1,
  369. fun ec_semver:gt/2)).
  370. valid_version(_Config) ->
  371. ?assert(rebar_prv_update:valid_vsn(<<"0.1">>)),
  372. ?assert(rebar_prv_update:valid_vsn(<<"0.1.0">>)),
  373. ?assert(rebar_prv_update:valid_vsn(<<" 0.1.0">>)),
  374. ?assert(rebar_prv_update:valid_vsn(<<" 0.1.0">>)),
  375. ?assert(rebar_prv_update:valid_vsn(<<"<0.1">>)),
  376. ?assert(rebar_prv_update:valid_vsn(<<"<0.1.0">>)),
  377. ?assert(rebar_prv_update:valid_vsn(<<"< 0.1.0">>)),
  378. ?assert(rebar_prv_update:valid_vsn(<<"< 0.1.0">>)),
  379. ?assert(rebar_prv_update:valid_vsn(<<">0.1">>)),
  380. ?assert(rebar_prv_update:valid_vsn(<<">0.1.0">>)),
  381. ?assert(rebar_prv_update:valid_vsn(<<"> 0.1.0">>)),
  382. ?assert(rebar_prv_update:valid_vsn(<<"> 0.1.0">>)),
  383. ?assert(rebar_prv_update:valid_vsn(<<"<=0.1">>)),
  384. ?assert(rebar_prv_update:valid_vsn(<<"<=0.1.0">>)),
  385. ?assert(rebar_prv_update:valid_vsn(<<"<= 0.1.0">>)),
  386. ?assert(rebar_prv_update:valid_vsn(<<"<= 0.1.0">>)),
  387. ?assert(rebar_prv_update:valid_vsn(<<">=0.1">>)),
  388. ?assert(rebar_prv_update:valid_vsn(<<">=0.1.0">>)),
  389. ?assert(rebar_prv_update:valid_vsn(<<">= 0.1.0">>)),
  390. ?assert(rebar_prv_update:valid_vsn(<<">= 0.1.0">>)),
  391. ?assert(rebar_prv_update:valid_vsn(<<"==0.1">>)),
  392. ?assert(rebar_prv_update:valid_vsn(<<"==0.1.0">>)),
  393. ?assert(rebar_prv_update:valid_vsn(<<"== 0.1.0">>)),
  394. ?assert(rebar_prv_update:valid_vsn(<<"== 0.1.0">>)),
  395. ?assert(rebar_prv_update:valid_vsn(<<"~>0.1">>)),
  396. ?assert(rebar_prv_update:valid_vsn(<<"~>0.1.0">>)),
  397. ?assert(rebar_prv_update:valid_vsn(<<"~> 0.1.0">>)),
  398. ?assert(rebar_prv_update:valid_vsn(<<"~> 0.1.0">>)),
  399. ?assertNot(rebar_prv_update:valid_vsn(<<"> 0.1.0 and < 0.2.0">>)),
  400. ok.
  401. run(Config) ->
  402. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  403. rebar_test_utils:run_and_check(
  404. Config, RebarConfig, ["install_deps"], ?config(expect, Config)
  405. ),
  406. check_warnings(warning_calls(), ?config(warnings, Config), ?config(deps_type, Config)).
  407. warning_calls() ->
  408. History = meck:history(rebar_log),
  409. [{Str, Args} || {_, {rebar_log, log, [warn, Str, Args]}, _} <- History].
  410. check_warnings(_, [], _) ->
  411. ok;
  412. check_warnings(Warns, [{Name, Vsn} | Rest], Type) ->
  413. ct:pal("Checking for warning ~p in ~p", [{Name,Vsn},Warns]),
  414. ?assert(in_warnings(Type, Warns, Name, Vsn)),
  415. check_warnings(Warns, Rest, Type).
  416. in_warnings(git, Warns, NameRaw, VsnRaw) ->
  417. Name = iolist_to_binary(NameRaw),
  418. 1 =< length([1 || {_, [AppName, {git, _, {_, Vsn}}]} <- Warns,
  419. AppName =:= Name, Vsn =:= VsnRaw]);
  420. in_warnings(pkg, Warns, NameRaw, VsnRaw) ->
  421. Name = iolist_to_binary(NameRaw),
  422. Vsn = iolist_to_binary(VsnRaw),
  423. 1 =< length([1 || {_, [AppName, {pkg, _, AppVsn, _}]} <- Warns,
  424. AppName =:= Name, AppVsn =:= Vsn]).