summaryrefslogtreecommitdiff
path: root/src/rebar_app_utils.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/rebar_app_utils.erl')
-rw-r--r--src/rebar_app_utils.erl124
1 files changed, 122 insertions, 2 deletions
diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl
index e9745c3..b14c50a 100644
--- a/src/rebar_app_utils.erl
+++ b/src/rebar_app_utils.erl
@@ -32,6 +32,9 @@
app_src_to_app/2,
validate_application_info/1,
validate_application_info/2,
+ parse_deps/5,
+ parse_deps/6,
+ dep_to_app/7,
format_error/1]).
-include("rebar.hrl").
@@ -87,6 +90,109 @@ validate_application_info(AppInfo, AppDetail) ->
end
end.
+-spec parse_deps(binary(), list(), rebar_state:t(), list(), integer()) -> {[rebar_app_info:t()], [tuple()]}.
+parse_deps(DepsDir, Deps, State, Locks, Level) ->
+ parse_deps(root, DepsDir, Deps, State, Locks, Level).
+
+parse_deps(Parent, DepsDir, Deps, State, Locks, Level) ->
+ [parse_dep(Dep, Parent, DepsDir, State, Locks, Level) || Dep <- Deps].
+
+parse_dep(Dep, Parent, DepsDir, State, Locks, Level) ->
+ Name = case Dep of
+ Dep when is_tuple(Dep) ->
+ element(1, Dep);
+ Dep ->
+ Dep
+ end,
+ case lists:keyfind(ec_cnv:to_binary(Name), 1, Locks) of
+ false ->
+ parse_dep(Parent, Dep, DepsDir, false, State);
+ LockedDep ->
+ LockedLevel = element(3, LockedDep),
+ case LockedLevel > Level of
+ true ->
+ parse_dep(Parent, Dep, DepsDir, false, State);
+ false ->
+ parse_dep(Parent, LockedDep, DepsDir, true, State)
+ end
+ end.
+
+parse_dep(Parent, {Name, Vsn}, DepsDir, IsLock, State) when is_list(Vsn); is_binary(Vsn) ->
+ %% Versioned Package dependency
+ CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
+ case rebar_app_info:discover(CheckoutsDir) of
+ {ok, _App} ->
+ dep_to_app(root, DepsDir, Name, [], [], IsLock, State);
+ not_found ->
+ {PkgName, PkgVsn} = parse_goal(ec_cnv:to_binary(Name)
+ ,ec_cnv:to_binary(Vsn)),
+ Source = {pkg, PkgName, PkgVsn},
+ rebar_app_info:resource_type(dep_to_app(Parent, DepsDir, PkgName, PkgVsn, Source, IsLock, State), pkg)
+ end;
+parse_dep(Parent, Name, DepsDir, IsLock, State) when is_atom(Name); is_binary(Name) ->
+ %% Unversioned package dependency
+ {PkgName, PkgVsn} = get_package(ec_cnv:to_binary(Name), State),
+ CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
+ case rebar_app_info:discover(CheckoutsDir) of
+ {ok, _App} ->
+ dep_to_app(root, DepsDir, Name, [], [], IsLock, State);
+ not_found ->
+ Source = {pkg, PkgName, PkgVsn},
+ rebar_app_info:resource_type(dep_to_app(Parent, DepsDir, PkgName, PkgVsn, Source, IsLock, State), pkg)
+ end;
+parse_dep(Parent, {Name, Source}, DepsDir, IsLock, State) when is_tuple(Source) ->
+ dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
+parse_dep(Parent, {Name, _Vsn, Source}, DepsDir, IsLock, State) when is_tuple(Source) ->
+ dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
+parse_dep(Parent, {Name, _Vsn, Source, Opts}, DepsDir, IsLock, State) when is_tuple(Source) ->
+ ?WARN("Dependency option list ~p in ~p is not supported and will be ignored", [Opts, Name]),
+ dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
+parse_dep(Parent, {_Name, {pkg, Name, Vsn}, Level}, DepsDir, IsLock, State) when is_integer(Level) ->
+ CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
+ case rebar_app_info:discover(CheckoutsDir) of
+ {ok, _App} ->
+ dep_to_app(root, DepsDir, Name, [], [], IsLock, State);
+ not_found ->
+ Source = {pkg, Name, Vsn},
+ rebar_app_info:resource_type(dep_to_app(Parent, DepsDir, Name, Vsn, Source, IsLock, State), pkg)
+ end;
+parse_dep(Parent, {Name, Source, Level}, DepsDir, IsLock, State) when is_tuple(Source)
+ , is_integer(Level) ->
+ dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
+parse_dep(_, Dep, _, _, _) ->
+ throw(?PRV_ERROR({parse_dep, Dep})).
+
+dep_to_app(Parent, DepsDir, Name, Vsn, Source, IsLock, State) ->
+ CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
+ BaseDir = rebar_state:get(State, base_dir, []),
+ {ok, Dep} = case rebar_app_info:discover(CheckoutsDir) of
+ {ok, App} ->
+ {ok, rebar_app_info:is_checkout(App, true)};
+ not_found ->
+ Dir = ec_cnv:to_list(filename:join(DepsDir, Name)),
+ case rebar_app_info:discover(Dir) of
+ {ok, App} ->
+ {ok, App};
+ not_found ->
+ rebar_app_info:new(Name, Vsn,
+ ec_cnv:to_list(filename:join(DepsDir, Name)))
+ end
+ end,
+ C = rebar_config:consult(rebar_app_info:dir(Dep)),
+ S = rebar_state:new(rebar_state:new(), C, rebar_app_info:dir(Dep)),
+ Overrides = rebar_state:get(State, overrides, []),
+ ParentOverrides = rebar_state:overrides(State),
+ S1 = rebar_state:set(rebar_state:overrides(S, ParentOverrides++Overrides), base_dir, BaseDir),
+ Dep1 = rebar_app_info:state(Dep, S1),
+ AppInfo = rebar_app_info:is_lock(rebar_app_info:source(Dep1, Source), IsLock),
+ ResourceType = case Source of
+ {pkg, _, _} ->
+ pkg;
+ _ ->
+ src
+ end,
+ rebar_app_info:resource_type(rebar_app_info:parent(AppInfo, Parent), ResourceType).
+
format_error(Error) ->
io_lib:format("~p", [Error]).
@@ -94,11 +200,25 @@ format_error(Error) ->
%% Internal functions
%% ===================================================================
+-spec parse_goal(binary(), binary()) -> {binary(), binary()} | {binary(), binary(), binary()}.
+parse_goal(Name, Constraint) ->
+ case re:run(Constraint, "([^\\d]*)(\\d.*)", [{capture, [1,2], binary}]) of
+ {match, [<<>>, Vsn]} ->
+ {Name, Vsn};
+ {match, [Op, Vsn]} ->
+ {Name, Vsn, binary_to_atom(Op, utf8)};
+ nomatch ->
+ throw(?PRV_ERROR({bad_constraint, Name, Constraint}))
+ end.
+
+get_package(Dep, State) ->
+ {ok, HighestDepVsn} = rebar_packages:find_highest_matching(Dep, "0", ?PACKAGE_TABLE, State),
+ {Dep, HighestDepVsn}.
+
-spec has_all_beams(file:filename_all(), [module()]) ->
true | ?PRV_ERROR({missing_module, module()}).
has_all_beams(EbinDir, [Module | ModuleList]) ->
- BeamFile = filename:join([EbinDir,
- ec_cnv:to_list(Module) ++ ".beam"]),
+ BeamFile = filename:join([EbinDir, ec_cnv:to_list(Module) ++ ".beam"]),
case filelib:is_file(BeamFile) of
true ->
has_all_beams(EbinDir, ModuleList);