Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

152 Zeilen
6.5 KiB

vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
vor 10 Jahren
  1. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ts=4 sw=4 et
  3. -module(rebar_plugins).
  4. -export([project_plugins_install/1
  5. ,top_level_install/1
  6. ,project_apps_install/1
  7. ,install/2
  8. ,handle_plugins/3
  9. ,handle_plugins/4]).
  10. -include("rebar.hrl").
  11. %% ===================================================================
  12. %% Public API
  13. %% ===================================================================
  14. -spec project_plugins_install(rebar_state:t()) -> rebar_state:t().
  15. project_plugins_install(State) ->
  16. Profiles = rebar_state:current_profiles(State),
  17. State1 = rebar_state:allow_provider_overrides(State, true),
  18. State2 = lists:foldl(fun(Profile, StateAcc) ->
  19. Plugins = rebar_state:get(State, {project_plugins, Profile}, []),
  20. handle_plugins(Profile, Plugins, StateAcc)
  21. end, State1, Profiles),
  22. rebar_state:allow_provider_overrides(State2, false).
  23. -spec top_level_install(rebar_state:t()) -> rebar_state:t().
  24. top_level_install(State) ->
  25. Profiles = rebar_state:current_profiles(State),
  26. lists:foldl(fun(Profile, StateAcc) ->
  27. Plugins = rebar_state:get(State, {plugins, Profile}, []),
  28. handle_plugins(Profile, Plugins, StateAcc)
  29. end, State, Profiles).
  30. -spec project_apps_install(rebar_state:t()) -> rebar_state:t().
  31. project_apps_install(State) ->
  32. Profiles = rebar_state:current_profiles(State),
  33. ProjectApps = rebar_state:project_apps(State),
  34. lists:foldl(fun(Profile, StateAcc) ->
  35. Plugins = rebar_state:get(State, {plugins, Profile}, []),
  36. StateAcc1 = handle_plugins(Profile, Plugins, StateAcc),
  37. lists:foldl(fun(AppInfo, StateAcc2) ->
  38. C = rebar_config:consult(rebar_app_info:dir(AppInfo)),
  39. AppInfo0 = rebar_app_info:update_opts(AppInfo, rebar_app_info:opts(AppInfo), C),
  40. Plugins2 = rebar_app_info:get(AppInfo0, {plugins, Profile}, []),
  41. handle_plugins(Profile, Plugins2, StateAcc2)
  42. end, StateAcc1, ProjectApps)
  43. end, State, Profiles).
  44. -spec install(rebar_state:t(), rebar_app_info:t()) -> rebar_state:t().
  45. install(State, AppInfo) ->
  46. Profiles = rebar_state:current_profiles(State),
  47. %% don't lose the overrides of the dep we are processing plugins for
  48. Overrides = rebar_app_info:get(AppInfo, overrides, []),
  49. StateOverrides = rebar_state:get(State, overrides, []),
  50. AllOverrides = Overrides ++ StateOverrides,
  51. State1 = rebar_state:set(State, overrides, AllOverrides),
  52. State2 = lists:foldl(fun(Profile, StateAcc) ->
  53. Plugins = rebar_app_info:get(AppInfo, {plugins, Profile}, []),
  54. handle_plugins(Profile, Plugins, StateAcc)
  55. end, State1, Profiles),
  56. %% Reset the overrides after processing the dep
  57. rebar_state:set(State2, overrides, StateOverrides).
  58. handle_plugins(Profile, Plugins, State) ->
  59. handle_plugins(Profile, Plugins, State, false).
  60. handle_plugins(Profile, Plugins, State, Upgrade) ->
  61. %% Set deps dir to plugins dir so apps are installed there
  62. Locks = rebar_state:lock(State),
  63. DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR),
  64. State1 = rebar_state:set(State, deps_dir, ?DEFAULT_PLUGINS_DIR),
  65. %% Install each plugin individually so if one fails to install it doesn't effect the others
  66. {_PluginProviders, State2} =
  67. lists:foldl(fun(Plugin, {PluginAcc, StateAcc}) ->
  68. {NewPlugins, NewState} = handle_plugin(Profile, Plugin, StateAcc, Upgrade),
  69. NewState1 = rebar_state:create_logic_providers(NewPlugins, NewState),
  70. {PluginAcc++NewPlugins, NewState1}
  71. end, {[], State1}, Plugins),
  72. %% reset deps dir
  73. State3 = rebar_state:set(State2, deps_dir, DepsDir),
  74. rebar_state:lock(State3, Locks).
  75. handle_plugin(Profile, Plugin, State, Upgrade) ->
  76. try
  77. {Apps, State2} = rebar_prv_install_deps:handle_deps_as_profile(Profile, State, [Plugin], Upgrade),
  78. {no_cycle, Sorted} = rebar_prv_install_deps:find_cycles(Apps),
  79. ToBuild = rebar_prv_install_deps:cull_compile(Sorted, []),
  80. %% Add already built plugin deps to the code path
  81. CodePaths = [rebar_app_info:ebin_dir(A) || A <- Apps -- ToBuild],
  82. code:add_pathsa(CodePaths),
  83. %% Build plugin and its deps
  84. [build_plugin(AppInfo, Apps, State2) || AppInfo <- ToBuild],
  85. %% Add newly built deps and plugin to code path
  86. State3 = rebar_state:update_all_plugin_deps(State2, Apps),
  87. NewCodePaths = [rebar_app_info:ebin_dir(A) || A <- ToBuild],
  88. code:add_pathsa(CodePaths),
  89. %% Store plugin code paths so we can remove them when compiling project apps
  90. State4 = rebar_state:update_code_paths(State3, all_plugin_deps, CodePaths++NewCodePaths),
  91. {plugin_providers(Plugin), State4}
  92. catch
  93. C:T ->
  94. ?DEBUG("~p ~p ~p", [C, T, erlang:get_stacktrace()]),
  95. ?WARN("Plugin ~p not available. It will not be used.", [Plugin]),
  96. {[], State}
  97. end.
  98. build_plugin(AppInfo, Apps, State) ->
  99. Providers = rebar_state:providers(State),
  100. %Providers1 = rebar_state:providers(rebar_app_info:state(AppInfo)),
  101. %rebar_app_info:state_or_new(State, AppInfo)
  102. S = rebar_state:all_deps(State, Apps),
  103. S1 = rebar_state:set(S, deps_dir, ?DEFAULT_PLUGINS_DIR),
  104. rebar_prv_compile:compile(S1, Providers, AppInfo).
  105. plugin_providers({Plugin, _, _, _}) when is_atom(Plugin) ->
  106. validate_plugin(Plugin);
  107. plugin_providers({Plugin, _, _}) when is_atom(Plugin) ->
  108. validate_plugin(Plugin);
  109. plugin_providers({Plugin, _}) when is_atom(Plugin) ->
  110. validate_plugin(Plugin);
  111. plugin_providers(Plugin) when is_atom(Plugin) ->
  112. validate_plugin(Plugin).
  113. validate_plugin(Plugin) ->
  114. _ = application:load(Plugin),
  115. case application:get_env(Plugin, providers) of
  116. {ok, Providers} ->
  117. Providers;
  118. undefined ->
  119. Exports = Plugin:module_info(exports),
  120. case lists:member({init,1}, Exports) of
  121. false ->
  122. ?WARN("Plugin ~p does not export init/1. It will not be used.", [Plugin]),
  123. [];
  124. true ->
  125. [Plugin]
  126. end
  127. end.