summaryrefslogtreecommitdiff
path: root/src/rebar_prv_upgrade.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/rebar_prv_upgrade.erl')
-rw-r--r--src/rebar_prv_upgrade.erl48
1 files changed, 34 insertions, 14 deletions
diff --git a/src/rebar_prv_upgrade.erl b/src/rebar_prv_upgrade.erl
index c0a56c3..4609f57 100644
--- a/src/rebar_prv_upgrade.erl
+++ b/src/rebar_prv_upgrade.erl
@@ -12,7 +12,10 @@
-include("rebar.hrl").
-define(PROVIDER, upgrade).
--define(DEPS, []).
+-define(DEPS, [lock]).
+%% Also only upgrade top-level (0) deps. Transitive deps shouldn't be
+%% upgradable -- if the user wants this, they should declare it at the
+%% top level and then upgrade.
%% ===================================================================
%% Public API
@@ -38,19 +41,36 @@ init(State) ->
do(State) ->
{Args, _} = rebar_state:command_parsed_args(State),
Name = ec_cnv:to_binary(proplists:get_value(package, Args)),
- Locks = rebar_state:get(State, locks, []),
- case lists:keyfind(Name, 1, Locks) of
- {_, _, _, Level} ->
- Deps = rebar_state:get(State, deps),
- case lists:keyfind(binary_to_atom(Name, utf8), 1, Deps) of
- false ->
- {error, io_lib:format("No such dependency ~s~n", [Name])};
- Dep ->
- rebar_prv_install_deps:handle_deps(State, [Dep], {true, Name, Level}),
- {ok, State}
- end;
- _ ->
- {error, io_lib:format("No such dependency ~s~n", [Name])}
+ Locks = rebar_state:lock(State),
+ %% TODO: optimize by running the find + unlock in one sweep
+ case find_app(Name, Locks) of
+ {AppInfo, 0} ->
+ %% Unlock the app and all those with a lock level higher than
+ %% it has
+ NewLocks = unlock_higher_than(0, Locks -- [AppInfo]),
+ {ok, rebar_state:lock(State, NewLocks)};
+ {_AppInfo, Level} when Level > 0 ->
+ {error, transitive_dependency};
+ false ->
+ {error, unknown_dependency}
+ end.
+
+find_app(_Name, []) -> false;
+find_app(Name, [App|Apps]) ->
+ case rebar_app_info:name(App) of
+ Name -> {App, rebar_app_info:dep_level(App)};
+ _ -> find_app(Name, Apps)
+ end.
+
+%% Because we operate on a lock list, removing the app from the list
+%% unlocks it.
+unlock_higher_than(_, []) -> [];
+unlock_higher_than(Level, [App | Apps]) ->
+ case rebar_app_info:dep_level(App) of
+ N when N > Level ->
+ unlock_higher_than(Level, Apps);
+ N when N =< Level ->
+ [App | unlock_higher_than(Level, Apps)]
end.
-spec format_error(any()) -> iolist().