diff options
author | Heinz N. Gies <heinz@licenser.net> | 2016-02-19 16:59:35 -0500 |
---|---|---|
committer | Heinz N. Gies <heinz@licenser.net> | 2016-02-22 16:30:42 -0500 |
commit | e9e62657c904f7009565c8792866496de72cc87b (patch) | |
tree | 873e59cba71ac81520babce315c9e96c1d15ddd3 /src | |
parent | cb0263667c84ed2b4cf58a16e8de5769a395e394 (diff) |
Add more hex rules so they don't throw errors
Add more version constraints
Allow for any number of whitespaces after compairison opperator
Improve updating and error printing
Fix failing tests
Diffstat (limited to 'src')
-rw-r--r-- | src/rebar_packages.erl | 40 | ||||
-rw-r--r-- | src/rebar_prv_update.erl | 122 |
2 files changed, 139 insertions, 23 deletions
diff --git a/src/rebar_packages.erl b/src/rebar_packages.erl index c56009e..b5e0923 100644 --- a/src/rebar_packages.erl +++ b/src/rebar_packages.erl @@ -7,7 +7,9 @@ ,registry_dir/1 ,package_dir/1 ,registry_checksum/2 + ,find_highest_matching/6 ,find_highest_matching/4 + ,find_all/3 ,verify_table/1 ,format_error/1]). @@ -139,16 +141,26 @@ registry_checksum({pkg, Name, Vsn}, State) -> %% `~> 2.0` | `>= 2.0.0 and < 3.0.0` %% `~> 2.1` | `>= 2.1.0 and < 3.0.0` find_highest_matching(Dep, Constraint, Table, State) -> + find_highest_matching(undefined, undefined, Dep, Constraint, Table, State). + +find_highest_matching(Pkg, PkgVsn, Dep, Constraint, Table, State) -> + try find_all(Dep, Table, State) of + {ok, [Vsn]} -> + handle_single_vsn(Pkg, PkgVsn, Dep, Vsn, Constraint); + {ok, [HeadVsn | VsnTail]} -> + {ok, handle_vsns(Constraint, HeadVsn, VsnTail)} + catch + error:badarg -> + none + end. + +find_all(Dep, Table, State) -> ?MODULE:verify_table(State), try ets:lookup_element(Table, Dep, 2) of - [[HeadVsn | VsnTail]] -> - {ok, handle_vsns(Constraint, HeadVsn, VsnTail)}; - [[Vsn]] -> - handle_single_vsn(Dep, Vsn, Constraint); - [Vsn] -> - handle_single_vsn(Dep, Vsn, Constraint); - [HeadVsn | VsnTail] -> - {ok, handle_vsns(Constraint, HeadVsn, VsnTail)} + [Vsns] when is_list(Vsns)-> + {ok, Vsns}; + Vsns -> + {ok, Vsns} catch error:badarg -> none @@ -165,13 +177,19 @@ handle_vsns(Constraint, HeadVsn, VsnTail) -> end end, HeadVsn, VsnTail). -handle_single_vsn(Dep, Vsn, Constraint) -> +handle_single_vsn(Pkg, PkgVsn, Dep, Vsn, Constraint) -> case ec_semver:pes(Vsn, Constraint) of true -> {ok, Vsn}; false -> - ?WARN("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]), + case {Pkg, PkgVsn} of + {undefined, undefined} -> + ?WARN("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. " + "Using anyway, but it is not guaranteed to work.", [Pkg, PkgVsn, Dep, Vsn, Constraint]) + end, {ok, Vsn} end. diff --git a/src/rebar_prv_update.erl b/src/rebar_prv_update.erl index 0e3b9a0..5e1e253 100644 --- a/src/rebar_prv_update.erl +++ b/src/rebar_prv_update.erl @@ -11,6 +11,10 @@ -export([hex_to_index/1]). +-ifdef(TEST). +-export([cmp_/6, cmpl_/6, valid_vsn/1]). +-endif. + -include("rebar.hrl"). -include_lib("providers/include/providers.hrl"). @@ -99,7 +103,7 @@ hex_to_index(State) -> ets:foldl(fun({{Pkg, PkgVsn}, [Deps, Checksum, BuildTools | _]}, _) when is_list(BuildTools) -> case lists:any(fun is_supported/1, BuildTools) of true -> - DepsList = update_deps_list(Deps, Registry, State), + DepsList = update_deps_list(Pkg, PkgVsn, Deps, Registry, State), ets:insert(?PACKAGE_TABLE, {{Pkg, PkgVsn}, DepsList, Checksum}); false -> true @@ -137,20 +141,114 @@ hex_to_index(State) -> fail end. -update_deps_list(Deps, HexRegistry, State) -> +update_deps_list(Pkg, PkgVsn, Deps, HexRegistry, State) -> lists:foldl(fun([Dep, DepVsn, false, _AppName | _], DepsListAcc) -> - case DepVsn of - <<"~> ", Vsn/binary>> -> - case rebar_packages:find_highest_matching(Dep, Vsn, HexRegistry, State) of - {ok, HighestDepVsn} -> - [{Dep, HighestDepVsn} | DepsListAcc]; - none -> - ?WARN("Missing registry entry for package ~s. Try to fix with `rebar3 update`", [Dep]), - DepsListAcc - end; - Vsn -> + Dep1 = {Pkg, PkgVsn, Dep}, + case {valid_vsn(DepVsn), DepVsn} of + %% Those are all not perfectly implemented! + %% and doubled since spaces seem not to be + %% enforced + {false, Vsn} -> + ?WARN("[~s:~s], Bad dependency version for ~s: ~s.", + [Pkg, PkgVsn, Dep, Vsn]), + DepsListAcc; + {_, <<"~>", Vsn/binary>>} -> + highest_matching(Dep1, rm_ws(Vsn), HexRegistry, + State, DepsListAcc); + {_, <<">=", Vsn/binary>>} -> + cmp(Dep1, rm_ws(Vsn), HexRegistry, State, + DepsListAcc, fun ec_semver:gte/2); + {_, <<">", Vsn/binary>>} -> + cmp(Dep1, rm_ws(Vsn), HexRegistry, State, + DepsListAcc, fun ec_semver:gt/2); + {_, <<"<=", Vsn/binary>>} -> + cmpl(Dep1, rm_ws(Vsn), HexRegistry, State, + DepsListAcc, fun ec_semver:lte/2); + {_, <<"<", Vsn/binary>>} -> + cmpl(Dep1, rm_ws(Vsn), HexRegistry, State, + DepsListAcc, fun ec_semver:lt/2); + {_, <<"==", Vsn/binary>>} -> + [{Dep, Vsn} | DepsListAcc]; + {_, Vsn} -> [{Dep, Vsn} | DepsListAcc] end; ([_Dep, _DepVsn, true, _AppName | _], DepsListAcc) -> DepsListAcc end, [], Deps). + +rm_ws(<<" ", R/binary>>) -> + rm_ws(R); +rm_ws(R) -> + R. + +valid_vsn(Vsn) -> + %% Regepx from https://github.com/sindresorhus/semver-regex/blob/master/index.js + SemVerRegExp = "v?(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))?" + "(-[0-9a-z-]+(\\.[0-9a-z-]+)*)?(\\+[0-9a-z-]+(\\.[0-9a-z-]+)*)?", + SupportedVersions = "^(>=?|<=?|~>|==)?\\s*" ++ SemVerRegExp ++ "$", + re:run(Vsn, SupportedVersions) =/= nomatch. + +highest_matching({Pkg, PkgVsn, Dep}, Vsn, HexRegistry, State, DepsListAcc) -> + case rebar_packages:find_highest_matching(Pkg, PkgVsn, Dep, Vsn, HexRegistry, State) of + {ok, HighestDepVsn} -> + [{Dep, HighestDepVsn} | DepsListAcc]; + none -> + ?WARN("[~s:~s] Missing registry entry for package ~s. Try to fix with `rebar3 update`", + [Pkg, PkgVsn, Dep]), + DepsListAcc + end. + +cmp({_Pkg, _PkgVsn, Dep} = Dep1, Vsn, HexRegistry, State, DepsListAcc, CmpFun) -> + {ok, Vsns} = rebar_packages:find_all(Dep, HexRegistry, State), + cmp_(undefined, Vsn, Vsns, DepsListAcc, Dep1, CmpFun). + + +cmp_(undefined, _MinVsn, [], DepsListAcc, {Pkg, PkgVsn, Dep}, _CmpFun) -> + ?WARN("[~s:~s] Missing registry entry for package ~s. Try to fix with `rebar3 update`", + [Pkg, PkgVsn, Dep]), + DepsListAcc; +cmp_(HighestDepVsn, _MinVsn, [], DepsListAcc, {_Pkg, _PkgVsn, Dep}, _CmpFun) -> + [{Dep, HighestDepVsn} | DepsListAcc]; + +cmp_(BestMatch, MinVsn, [Vsn | R], DepsListAcc, Dep, CmpFun) -> + case CmpFun(Vsn, MinVsn) of + true -> + cmp_(Vsn, Vsn, R, DepsListAcc, Dep, CmpFun); + false -> + cmp_(BestMatch, MinVsn, R, DepsListAcc, Dep, CmpFun) + end. + +%% We need to treat this differently since we want a version that is LOWER but +%% the higest possible one. +cmpl({_Pkg, _PkgVsn, Dep} = Dep1, Vsn, HexRegistry, State, DepsListAcc, CmpFun) -> + {ok, Vsns} = rebar_packages:find_all(Dep, HexRegistry, State), + cmpl_(undefined, Vsn, Vsns, DepsListAcc, Dep1, CmpFun). + +cmpl_(undefined, _MaxVsn, [], DepsListAcc, {Pkg, PkgVsn, Dep}, _CmpFun) -> + ?WARN("[~s:~s] Missing registry entry for package ~s. Try to fix with `rebar3 update`", + [Pkg, PkgVsn, Dep]), + DepsListAcc; + +cmpl_(HighestDepVsn, _MaxVsn, [], DepsListAcc, {_Pkg, _PkgVsn, Dep}, _CmpFun) -> + [{Dep, HighestDepVsn} | DepsListAcc]; + +cmpl_(undefined, MaxVsn, [Vsn | R], DepsListAcc, Dep, CmpFun) -> + case CmpFun(Vsn, MaxVsn) of + true -> + cmpl_(Vsn, MaxVsn, R, DepsListAcc, Dep, CmpFun); + false -> + cmpl_(undefined, MaxVsn, R, DepsListAcc, Dep, CmpFun) + end; + +cmpl_(BestMatch, MaxVsn, [Vsn | R], DepsListAcc, Dep, CmpFun) -> + case CmpFun(Vsn, MaxVsn) of + true -> + case ec_semver:gte(Vsn, BestMatch) of + true -> + cmpl_(Vsn, MaxVsn, R, DepsListAcc, Dep, CmpFun); + false -> + cmpl_(BestMatch, MaxVsn, R, DepsListAcc, Dep, CmpFun) + end; + false -> + cmpl_(BestMatch, MaxVsn, R, DepsListAcc, Dep, CmpFun) + end. |