Packages
elvis_core
5.0.2
5.0.4
5.0.3
5.0.2
5.0.1
5.0.0
retired
4.2.3
4.2.2
4.2.1
4.2.0
4.1.1
4.1.0
4.0.0
3.2.5
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.0
3.0.1
3.0.0
2.0.1
2.0.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.2
1.1.1
1.1.0
1.0.0
0.7.0
0.6.1
0.6.0
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
Core library for the Erlang style reviewer
Current section
Files
Jump to
Current section
Files
src/elvis_project.erl
-module(elvis_project).
-behaviour(elvis_rule).
-export([default/1]).
-export([no_branch_deps/2, protocol_for_deps/2]).
% The whole file is considered to have either callback functions or rules.
-ignore_xref(elvis_project).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Default values
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec default(RuleName :: atom()) -> elvis_rule:def().
default(no_branch_deps) ->
elvis_rule:defmap(#{
ignore => []
});
default(protocol_for_deps) ->
elvis_rule:defmap(#{
ignore => [],
regex => "^(https://|git://|\\d+(\\.\\d+)*)"
});
default(_RuleName) ->
elvis_rule:defmap(#{}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Rules
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec protocol_for_deps(elvis_rule:t(), elvis_config:t()) -> [elvis_result:item()].
protocol_for_deps(Rule, _ElvisConfig) ->
IgnoreDeps = elvis_rule:option(ignore, Rule),
Regex = elvis_rule:option(regex, Rule),
Deps = get_deps(elvis_rule:file(Rule)),
NoHexDeps = lists:filter(fun(Dep) -> not is_hex_dep(Dep) end, Deps),
BadDeps = lists:filter(fun(Dep) -> is_not_git_dep(Dep, Regex) end, NoHexDeps),
lists:filtermap(
fun(Line) ->
AppName = appname_from_line(Line),
case lists:member(AppName, IgnoreDeps) of
true ->
false;
false ->
{true,
elvis_result:new_item(
"Dependency '~s' is not using appropriate protocol; prefer "
"respecting regular expression '~s'",
[AppName, Regex]
)}
end
end,
BadDeps
).
appname_from_line({AppName, _}) ->
AppName;
appname_from_line({AppName, _, _GitInfo}) ->
AppName;
appname_from_line({AppName, _Vsn, _GitInfo, _Opts}) ->
AppName.
-spec no_branch_deps(elvis_rule:t(), elvis_config:t()) -> [elvis_result:item()].
no_branch_deps(Rule, _ElvisConfig) ->
IgnoreDeps = elvis_rule:option(ignore, Rule),
Deps = get_deps(elvis_rule:file(Rule)),
BadDeps = lists:filter(fun is_branch_dep/1, Deps),
lists:filtermap(
fun(Line) ->
AppName = appname_from_line(Line),
case lists:member(AppName, IgnoreDeps) of
true ->
false;
false ->
{true,
elvis_result:new_item(
"Dependency '~s' uses a branch; prefer a tag or a specific commit",
[AppName]
)}
end
end,
BadDeps
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Private
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Rebar
get_deps(File) ->
{Src, _} = elvis_file:src(File),
Terms = ktn_code:consult(Src),
IsDepsTerm =
fun
({deps, _}) ->
true;
(_) ->
false
end,
case lists:filter(IsDepsTerm, Terms) of
[] ->
[];
[{deps, Deps}] ->
Deps
end.
%% Rebar3
is_branch_dep({_AppName, {_SCM, _Location, {branch, _}}}) ->
true;
is_branch_dep({_AppName, {git_subdir, _Url, {branch, _}, _SubDir}}) ->
true;
%% Specific to plugin rebar_raw_resource
is_branch_dep({AppName, {raw, DepResourceSpecification}}) ->
is_branch_dep({AppName, DepResourceSpecification});
%% Rebar2
is_branch_dep({_AppName, _Vsn, {_SCM, _Location, {branch, _}}}) ->
true;
is_branch_dep(_) ->
false.
is_hex_dep(_AppName) when is_atom(_AppName) ->
true;
is_hex_dep({_AppName, _Vsn, {pkg, _PackageName}}) when
is_atom(_AppName), is_list(_Vsn), is_atom(_PackageName)
->
true;
is_hex_dep({_AppName, {pkg, _OtherName}}) when is_atom(_AppName), is_atom(_OtherName) ->
true;
is_hex_dep({_AppName, _Vsn}) when is_atom(_AppName), is_list(_Vsn) ->
true;
is_hex_dep(_) ->
false.
is_not_git_dep({_AppName, {_SCM, Url, _Branch}}, Regex) ->
nomatch =:= re:run(Url, Regex, []);
is_not_git_dep(
{_AppName, {git_subdir, Url, {BranchTagOrRefType, _BranchTagOrRef}, _SubDir}},
Regex
) when
BranchTagOrRefType =:= branch;
BranchTagOrRefType =:= tag;
BranchTagOrRefType =:= ref
->
nomatch =:= re:run(Url, Regex, []);
%% Specific to plugin rebar_raw_resource
is_not_git_dep({AppName, {raw, DepResourceSpecification}}, Regex) ->
is_not_git_dep({AppName, DepResourceSpecification}, Regex);
%% Alternative formats, backwards compatible declarations
is_not_git_dep({_AppName, {_SCM, Url}}, Regex) ->
nomatch =:= re:run(Url, Regex, []);
is_not_git_dep({_AppName, _Vsn, {_SCM, Url}}, Regex) ->
nomatch =:= re:run(Url, Regex, []);
is_not_git_dep({_AppName, _Vsn, {_SCM, Url, _Branch}}, Regex) ->
nomatch =:= re:run(Url, Regex, []);
is_not_git_dep({_AppName, _Vsn, {_SCM, Url, {BranchTagOrRefType, _Branch}}, _Opts}, Regex) when
BranchTagOrRefType =:= branch;
BranchTagOrRefType =:= tag;
BranchTagOrRefType =:= ref
->
nomatch =:= re:run(Url, Regex, []).