diff options
Diffstat (limited to 'src/rebar_prv_upgrade.erl')
-rw-r--r-- | src/rebar_prv_upgrade.erl | 48 |
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(). |