Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

115 строки
4.5 KiB

10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
  1. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ts=4 sw=4 et
  3. -module(rebar_prv_upgrade).
  4. -behaviour(provider).
  5. -export([init/1,
  6. do/1,
  7. format_error/1]).
  8. -include("rebar.hrl").
  9. -define(PROVIDER, upgrade).
  10. -define(DEPS, []).
  11. %% Also only upgrade top-level (0) deps. Transitive deps shouldn't be
  12. %% upgradable -- if the user wants this, they should declare it at the
  13. %% top level and then upgrade.
  14. %% ===================================================================
  15. %% Public API
  16. %% ===================================================================
  17. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
  18. init(State) ->
  19. State1 =
  20. rebar_state:add_provider(State,
  21. providers:create([{name, ?PROVIDER},
  22. {module, ?MODULE},
  23. {bare, false},
  24. {deps, ?DEPS},
  25. {example, "rebar upgrade cowboy[,ranch]"},
  26. {short_desc, "Upgrade dependency."},
  27. {desc, ""},
  28. {opts, [
  29. {package, undefined, undefined, string, "Packages to upgrade."}
  30. ]}])),
  31. {ok, State1}.
  32. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
  33. do(State) ->
  34. {Args, _} = rebar_state:command_parsed_args(State),
  35. Names = parse_names(ec_cnv:to_binary(proplists:get_value(package, Args))),
  36. %% TODO: support many names. Only a subtree can be updated per app
  37. %% mentioned. When no app is named, unlock *everything*
  38. Locks = rebar_state:get(State, {locks, default}, []),
  39. Deps = rebar_state:get(State, deps),
  40. case prepare_locks(Names, Deps, Locks, []) of
  41. {error, Reason} ->
  42. {error, Reason};
  43. {Locks0, Unlocks0} ->
  44. Deps0 = top_level_deps(Deps, Locks),
  45. State1 = rebar_state:set(State, {deps, default}, Deps0),
  46. State2 = rebar_state:set(State1, {locks, default}, Locks0),
  47. State3 = rebar_state:set(State2, upgrade, true),
  48. Res = rebar_prv_install_deps:do(State3),
  49. case Res of
  50. {ok, S} ->
  51. ct:pal("original locks ~p", [Locks]),
  52. ct:pal("new locks ~p", [Locks0]),
  53. ct:pal("old deps: ~p", [Deps]),
  54. ct:pal("new deps: ~p", [Deps0]),
  55. ct:pal("Unlocks: ~p", [Unlocks0]),
  56. %% TODO: replace new locks onto the old locks list
  57. rebar_prv_lock:do(S);
  58. _ -> Res
  59. end
  60. end.
  61. parse_names(Bin) ->
  62. lists:usort(re:split(Bin, <<" *, *">>, [trim])).
  63. prepare_locks([], _, Locks, Unlocks) ->
  64. {Locks, Unlocks};
  65. prepare_locks([Name|Names], Deps, Locks, Unlocks) ->
  66. case lists:keyfind(Name, 1, Locks) of
  67. {_, _, 0} = Lock ->
  68. AtomName = binary_to_atom(Name, utf8),
  69. case lists:keyfind(AtomName, 1, Deps) of
  70. false ->
  71. {error, {unknown_dependency, Name}};
  72. Dep ->
  73. Source = case Dep of
  74. {_, Src} -> Src;
  75. {_, _, Src} -> Src
  76. end,
  77. {NewLocks, NewUnlocks} = unlock_higher_than(0, Locks -- [Lock]),
  78. prepare_locks(Names,
  79. %deps_like_locks(Deps, [{Name,Source,0} | NewLocks]),
  80. Deps,
  81. NewLocks,
  82. [{Name, Source, 0} | NewUnlocks ++ Unlocks])
  83. end;
  84. {_, _, Level} when Level > 0 ->
  85. {error, {transitive_dependency,Name}};
  86. false ->
  87. {error, {unknown_dependency,Name}}
  88. end.
  89. top_level_deps(Deps, Locks) ->
  90. [Dep || Dep <- Deps, lists:keymember(0, 3, Locks)].
  91. unlock_higher_than(Level, Locks) -> unlock_higher_than(Level, Locks, [], []).
  92. unlock_higher_than(_, [], Locks, Unlocks) ->
  93. {Locks, Unlocks};
  94. unlock_higher_than(Level, [App = {_,_,AppLevel} | Apps], Locks, Unlocks) ->
  95. if AppLevel > Level -> unlock_higher_than(Level, Apps, Locks, [App | Unlocks]);
  96. AppLevel =< Level -> unlock_higher_than(Level, Apps, [App | Locks], Unlocks)
  97. end.
  98. -spec format_error(any()) -> iolist().
  99. format_error(Reason) ->
  100. io_lib:format("~p", [Reason]).