Pārlūkot izejas kodu

Merge pull request #1540 from ferd/allow-profile-deps-upgrade

Allow profile deps upgrade
pull/1555/head
Fred Hebert pirms 8 gadiem
revīziju iesūtīja GitHub
vecāks
revīzija
eaf2e54963
2 mainītis faili ar 130 papildinājumiem un 9 dzēšanām
  1. +39
    -7
      src/rebar_prv_upgrade.erl
  2. +91
    -2
      test/rebar_upgrade_SUITE.erl

+ 39
- 7
src/rebar_prv_upgrade.erl Parādīt failu

@ -70,7 +70,9 @@ do(State) ->
is_atom(Dep) orelse is_atom(element(1, Dep))],
Names = parse_names(ec_cnv:to_binary(proplists:get_value(package, Args, <<"">>)), Locks),
DepsDict = deps_dict(rebar_state:all_deps(State)),
case prepare_locks(Names, Deps, Locks, [], DepsDict) of
AltDeps = find_non_default_deps(Deps, State),
FilteredNames = cull_default_names_if_profiles(Names, Deps, State),
case prepare_locks(FilteredNames, Deps, Locks, [], DepsDict, AltDeps) of
{error, Reason} ->
{error, Reason};
{Locks0, _Unlocks0} ->
@ -115,20 +117,45 @@ parse_names(Bin, Locks) ->
Other -> Other
end.
prepare_locks([], _, Locks, Unlocks, _Dict) ->
%% Find alternative deps in non-default profiles since they may
%% need to be passed through (they are never locked)
find_non_default_deps(Deps, State) ->
AltProfiles = rebar_state:current_profiles(State) -- [default],
AltProfileDeps = lists:append([
rebar_state:get(State, {deps, Profile}, []) || Profile <- AltProfiles]
),
[Dep || Dep <- AltProfileDeps,
is_atom(Dep) orelse is_atom(element(1, Dep))
andalso not lists:member(Dep, Deps)].
%% If any alt profiles are used, remove the default profiles from
%% the upgrade list and warn about it.
cull_default_names_if_profiles(Names, Deps, State) ->
case rebar_state:current_profiles(State) of
[default] ->
Names;
_ ->
?INFO("Dependencies in the default profile will not be upgraded", []),
lists:filter(fun(Name) ->
AtomName = binary_to_atom(Name, utf8),
rebar_utils:tup_find(AtomName, Deps) == false
end, Names)
end.
prepare_locks([], _, Locks, Unlocks, _Dict, _AltDeps) ->
{Locks, Unlocks};
prepare_locks([Name|Names], Deps, Locks, Unlocks, Dict) ->
prepare_locks([Name|Names], Deps, Locks, Unlocks, Dict, AltDeps) ->
AtomName = binary_to_atom(Name, utf8),
case lists:keyfind(Name, 1, Locks) of
{_, _, 0} = Lock ->
case rebar_utils:tup_find(AtomName, Deps) of
false ->
?WARN("Dependency ~s has been removed and will not be upgraded", [Name]),
prepare_locks(Names, Deps, Locks, Unlocks, Dict);
prepare_locks(Names, Deps, Locks, Unlocks, Dict, AltDeps);
Dep ->
{Source, NewLocks, NewUnlocks} = prepare_lock(Dep, Lock, Locks, Dict),
prepare_locks(Names, Deps, NewLocks,
[{Name, Source, 0} | NewUnlocks ++ Unlocks], Dict)
[{Name, Source, 0} | NewUnlocks ++ Unlocks], Dict, AltDeps)
end;
{_, _, Level} = Lock when Level > 0 ->
case rebar_utils:tup_find(AtomName, Deps) of
@ -137,10 +164,15 @@ prepare_locks([Name|Names], Deps, Locks, Unlocks, Dict) ->
Dep -> % Dep has been promoted
{Source, NewLocks, NewUnlocks} = prepare_lock(Dep, Lock, Locks, Dict),
prepare_locks(Names, Deps, NewLocks,
[{Name, Source, 0} | NewUnlocks ++ Unlocks], Dict)
[{Name, Source, 0} | NewUnlocks ++ Unlocks], Dict, AltDeps)
end;
false ->
?PRV_ERROR({unknown_dependency, Name})
case rebar_utils:tup_find(AtomName, AltDeps) of
false ->
?PRV_ERROR({unknown_dependency, Name});
_ -> % non-default profile dependency found, pass through
prepare_locks(Names, Deps, Locks, Unlocks, Dict, AltDeps)
end
end.
prepare_lock(Dep, Lock, Locks, Dict) ->

+ 91
- 2
test/rebar_upgrade_SUITE.erl Parādīt failu

@ -11,7 +11,8 @@ groups() ->
triplet_a, triplet_b, triplet_c,
tree_a, tree_b, tree_c, tree_c2, tree_cj, tree_ac, tree_all,
delete_d, promote, stable_lock, fwd_lock,
compile_upgrade_parity, umbrella_config]},
compile_upgrade_parity, umbrella_config,
profiles, profiles_exclusion]},
{git, [], [{group, all}]},
{pkg, [], [{group, all}]}].
@ -78,6 +79,23 @@ setup_project(Case=umbrella_config, Config0, Deps, UpDeps) ->
[{rebarconfig, TopConf},
{rebarumbrella, RebarConf},
{next_top_deps, rebar_test_utils:top_level_deps(UpDeps)} | Config];
setup_project(Case, Config0, Deps, UpDeps) when Case == profiles;
Case == profiles_exclusion ->
DepsType = ?config(deps_type, Config0),
NameRoot = atom_to_list(Case)++"_"++atom_to_list(DepsType),
Config = rebar_test_utils:init_rebar_state(Config0, NameRoot++"_"),
AppDir = filename:join([?config(apps, Config), "apps", NameRoot]),
rebar_test_utils:create_app(AppDir, "Root", "0.0.0", [kernel, stdlib]),
[Top|ProfileDeps] = rebar_test_utils:top_level_deps(Deps),
RebarConf = rebar_test_utils:create_config(AppDir, [
{deps, [Top]},
{profiles, [{fake, [{deps, ProfileDeps}]}]}
]),
[NextTop|NextPDeps] = rebar_test_utils:top_level_deps(UpDeps),
NextConfig = [{deps, [NextTop]},
{profiles, [{fake, [{deps, NextPDeps}]}]}],
[{rebarconfig, RebarConf},
{next_config, NextConfig} | Config];
setup_project(Case, Config0, Deps, UpDeps) ->
DepsType = ?config(deps_type, Config0),
Config = rebar_test_utils:init_rebar_state(
@ -454,7 +472,47 @@ upgrades(umbrella_config) ->
{[{"A", "1", []}],
[{"A", "2", []}],
["A"],
{"A", [{"A","2"}]}}.
{"A", [{"A","2"}]}};
upgrades(profiles) ->
%% Ensure that we can unlock deps under a given profile;
%% B and C should both be in a custom profile
%% and must not be locked.
{[{"A", "1", [{"D",[]},
{"E","3",[]}]},
{"B", "1", [{"F","1",[]},
{"G",[]}]},
{"C", "0", [{"H","3",[]},
{"I",[]}]}],
[{"A", "2", [{"D",[]},
{"E","2",[]}]},
{"B", "2", [{"F","2",[]},
{"G",[]}]},
{"C", "1", [{"H","4",[]},
{"I",[]}]}],
["A","B","C","E","F","H"],
{"C", [{"A","1"}, "D", {"E","3"},
{"B","2"}, {"F","2"}, "G",
{"C","1"}, {"H","4"}, "I"]}};
upgrades(profiles_exclusion) ->
%% Ensure that we can unlock deps under a given profile;
%% B and C should both be in a custom profile
%% and must not be locked.
{[{"A", "1", [{"D",[]},
{"E","3",[]}]},
{"B", "1", [{"F","1",[]},
{"G",[]}]},
{"C", "0", [{"H","3",[]},
{"I",[]}]}],
[{"A", "2", [{"D",[]},
{"E","2",[]}]},
{"B", "2", [{"F","2",[]},
{"G",[]}]},
{"C", "1", [{"H","4",[]},
{"I",[]}]}],
["A","B","C","E","F","H"],
{"A", [{"A","1"}, "D", {"E","3"},
{"B","2"}, {"F","2"}, "G",
{"C","1"}, {"H","4"}, "I"]}}.
%% TODO: add a test that verifies that unlocking files and then
%% running the upgrade code is enough to properly upgrade things.
@ -613,6 +671,37 @@ umbrella_config(Config) ->
),
meck:unload(rebar_prv_upgrade).
profiles(Config) ->
apply(?config(mock, Config), []),
{ok, TopConfig} = file:consult(?config(rebarconfig, Config)),
%% Install dependencies before re-mocking for an upgrade
rebar_test_utils:run_and_check(Config, TopConfig, ["lock"], {ok, []}),
%% Install test deps along with them
rebar_test_utils:run_and_check(Config, TopConfig, ["as","fake","lock"], {ok, []}),
{App, Unlocks} = ?config(expected, Config),
ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
Expectation = case Unlocks of
{error, Term} -> {error, Term};
_ -> {ok, [T || T <- Unlocks,
element(1,T) == dep orelse
lists:member(element(2,T), ["A","D","E"])]}
end,
meck:new(rebar_prv_app_discovery, [passthrough]),
meck:expect(rebar_prv_app_discovery, do, fun(S) ->
apply(?config(mock_update, Config), []),
meck:passthrough([S])
end),
NewRebarConf = rebar_test_utils:create_config(?config(apps, Config),
?config(next_config, Config)),
{ok, NewRebarConfig} = file:consult(NewRebarConf),
rebar_test_utils:run_and_check(
Config, NewRebarConfig, ["as","fake","upgrade", App], Expectation
),
meck:unload(rebar_prv_app_discovery).
profiles_exclusion(Config) -> profiles(Config).
run(Config) ->
apply(?config(mock, Config), []),
ConfigPath = ?config(rebarconfig, Config),

Notiek ielāde…
Atcelt
Saglabāt