summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--src/rebar_prv_update.erl62
2 files changed, 53 insertions, 11 deletions
diff --git a/Makefile b/Makefile
index f36c177..49f5758 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ RETEST=$(PWD)/deps/retest/retest
DEPS_PLT=$(CURDIR)/.depsolver_plt
all:
- @rebar get-deps compile escriptize
+ @./bootstrap/rebar get-deps compile escriptize
clean:
@rm -rf rebar3 ebin/*.beam inttest/rt.work rt.work .eunit
diff --git a/src/rebar_prv_update.erl b/src/rebar_prv_update.erl
index 655e5a3..f4985f3 100644
--- a/src/rebar_prv_update.erl
+++ b/src/rebar_prv_update.erl
@@ -79,18 +79,60 @@ hex_to_graph(Filename) ->
end, ok, T),
Dict1 = ets:foldl(fun({{Pkg, PkgVsn}, [Deps | _]}, Dict) ->
- DepsList = lists:foldl(fun([Dep, DepVsn, _, _], DepsListAcc) ->
- case DepVsn of
- <<"~> ", Vsn/binary>> ->
- digraph:add_edge(Graph, {Pkg, PkgVsn}, {Dep, Vsn}),
- [{Dep, DepVsn} | DepsListAcc];
- Vsn ->
- digraph:add_edge(Graph, {Pkg, PkgVsn}, {Dep, Vsn}),
- [{Dep, Vsn} | DepsListAcc]
- end
- end, [], Deps),
+ DepsList = update_graph(Pkg, PkgVsn, Deps, T, Graph),
dict:store({Pkg, PkgVsn}, DepsList, Dict);
(_, Dict) ->
Dict
end, dict:new(), T),
{Dict1, Graph}.
+
+update_graph(Pkg, PkgVsn, Deps, HexRegistry, Graph) ->
+ lists:foldl(fun([Dep, DepVsn, _, _], DepsListAcc) ->
+ case DepVsn of
+ <<"~> ", Vsn/binary>> ->
+ HighestDepVsn = find_highest_matching(Dep, Vsn, HexRegistry),
+ digraph:add_edge(Graph, {Pkg, PkgVsn}, {Dep, HighestDepVsn}),
+ [{Dep, DepVsn} | DepsListAcc];
+ Vsn ->
+ digraph:add_edge(Graph, {Pkg, PkgVsn}, {Dep, Vsn}),
+ [{Dep, Vsn} | DepsListAcc]
+ end
+ end, [], Deps).
+
+%% Hex supports use of ~> to specify the version required for a dependency.
+%% Since rebar3 requires exact versions to choose from we find the highest
+%% available version of the dep that passes the constraint.
+
+%% `~>` will never include pre-release versions of its upper bound.
+%% It can also be used to set an upper bound on only the major
+%% version part. See the table below for `~>` requirements and
+%% their corresponding translation.
+%% `~>` | Translation
+%% :------------- | :---------------------
+%% `~> 2.0.0` | `>= 2.0.0 and < 2.1.0`
+%% `~> 2.1.2` | `>= 2.1.2 and < 2.2.0`
+%% `~> 2.1.3-dev` | `>= 2.1.3-dev and < 2.2.0`
+%% `~> 2.0` | `>= 2.0.0 and < 3.0.0`
+%% `~> 2.1` | `>= 2.1.0 and < 3.0.0`
+find_highest_matching(Dep, Constraint, T) ->
+ case ets:lookup(T, Dep) of
+ [{Dep, [[Vsn]]}] ->
+ case ec_semver:pes(Vsn, Constraint) of
+ true ->
+ Vsn;
+ false ->
+ ?WARN("Only existing version of ~s is ~s which does not match constraint ~~> ~s. "
+ "Using anyway, but it is not guarenteed to work.", [Dep, Vsn, Constraint]),
+ Vsn
+ end;
+ [{Dep, [[HeadVsn | VsnTail]]}] ->
+ lists:foldl(fun(Version, Highest) ->
+ case ec_semver:pes(Version, Constraint) andalso
+ ec_semver:gt(Version, Highest) of
+ true ->
+ Version;
+ false ->
+ Highest
+ end
+ end, HeadVsn, VsnTail)
+ end.