Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

167 rindas
7.2 KiB

pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
  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. StateAcc1 = case Profile of
  36. default ->
  37. %% default profile top level plugins
  38. %% are installed in run_aux
  39. StateAcc;
  40. _ ->
  41. Plugins = rebar_state:get(State, {plugins, Profile}, []),
  42. handle_plugins(Profile, Plugins, StateAcc)
  43. end,
  44. lists:foldl(fun(AppInfo, StateAcc2) ->
  45. Plugins2 = rebar_app_info:get(AppInfo, {plugins, Profile}, []),
  46. handle_plugins(Profile, Plugins2, StateAcc2)
  47. end, StateAcc1, ProjectApps)
  48. end, State, Profiles).
  49. -spec install(rebar_state:t(), rebar_app_info:t()) -> rebar_state:t().
  50. install(State, AppInfo) ->
  51. Profiles = rebar_state:current_profiles(State),
  52. %% don't lose the overrides of the dep we are processing plugins for
  53. Overrides = rebar_app_info:get(AppInfo, overrides, []),
  54. StateOverrides = rebar_state:get(State, overrides, []),
  55. AllOverrides = Overrides ++ StateOverrides,
  56. State1 = rebar_state:set(State, overrides, AllOverrides),
  57. State2 = lists:foldl(fun(Profile, StateAcc) ->
  58. Plugins = rebar_app_info:get(AppInfo, {plugins, Profile}, []),
  59. Plugins1 = filter_existing_plugins(Plugins, StateAcc),
  60. handle_plugins(Profile, Plugins1, StateAcc)
  61. end, State1, Profiles),
  62. %% Reset the overrides after processing the dep
  63. rebar_state:set(State2, overrides, StateOverrides).
  64. filter_existing_plugins(Plugins, State) ->
  65. PluginNames = lists:zip(Plugins, rebar_state:deps_names(Plugins)),
  66. AllPlugins = rebar_state:all_plugin_deps(State),
  67. lists:filtermap(fun({Plugin, PluginName}) ->
  68. case rebar_app_utils:find(PluginName, AllPlugins) of
  69. {ok, _} ->
  70. false;
  71. _ ->
  72. {true, Plugin}
  73. end
  74. end, PluginNames).
  75. handle_plugins(Profile, Plugins, State) ->
  76. handle_plugins(Profile, Plugins, State, false).
  77. handle_plugins(Profile, Plugins, State, Upgrade) ->
  78. %% Set deps dir to plugins dir so apps are installed there
  79. Locks = rebar_state:lock(State),
  80. DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR),
  81. State1 = rebar_state:set(State, deps_dir, ?DEFAULT_PLUGINS_DIR),
  82. %% Install each plugin individually so if one fails to install it doesn't effect the others
  83. {_PluginProviders, State2} =
  84. lists:foldl(fun(Plugin, {PluginAcc, StateAcc}) ->
  85. {NewPlugins, NewState} = handle_plugin(Profile, Plugin, StateAcc, Upgrade),
  86. NewState1 = rebar_state:create_logic_providers(NewPlugins, NewState),
  87. {PluginAcc++NewPlugins, NewState1}
  88. end, {[], State1}, Plugins),
  89. %% reset deps dir
  90. State3 = rebar_state:set(State2, deps_dir, DepsDir),
  91. rebar_state:lock(State3, Locks).
  92. handle_plugin(Profile, Plugin, State, Upgrade) ->
  93. try
  94. {Apps, State2} = rebar_prv_install_deps:handle_deps_as_profile(Profile, State, [Plugin], Upgrade),
  95. {no_cycle, Sorted} = rebar_prv_install_deps:find_cycles(Apps),
  96. ToBuild = rebar_prv_install_deps:cull_compile(Sorted, []),
  97. %% Add already built plugin deps to the code path
  98. PreBuiltPaths = [rebar_app_info:ebin_dir(A) || A <- Apps] -- ToBuild,
  99. code:add_pathsa(PreBuiltPaths),
  100. %% Build plugin and its deps
  101. [build_plugin(AppInfo, Apps, State2) || AppInfo <- ToBuild],
  102. %% Add newly built deps and plugin to code path
  103. State3 = rebar_state:update_all_plugin_deps(State2, Apps),
  104. NewCodePaths = [rebar_app_info:ebin_dir(A) || A <- ToBuild],
  105. %% Store plugin code paths so we can remove them when compiling project apps
  106. State4 = rebar_state:update_code_paths(State3, all_plugin_deps, PreBuiltPaths++NewCodePaths),
  107. rebar_paths:set_paths([plugins], State4),
  108. {plugin_providers(Plugin), State4}
  109. catch
  110. ?WITH_STACKTRACE(C,T,S)
  111. ?DEBUG("~p ~p ~p", [C, T, S]),
  112. ?WARN("Plugin ~p not available. It will not be used.", [Plugin]),
  113. {[], State}
  114. end.
  115. build_plugin(AppInfo, Apps, State) ->
  116. Providers = rebar_state:providers(State),
  117. S = rebar_state:all_deps(State, Apps),
  118. S1 = rebar_state:set(S, deps_dir, ?DEFAULT_PLUGINS_DIR),
  119. rebar_prv_compile:compile(S1, Providers, AppInfo).
  120. plugin_providers({Plugin, _, _, _}) when is_atom(Plugin) ->
  121. validate_plugin(Plugin);
  122. plugin_providers({Plugin, _, _}) when is_atom(Plugin) ->
  123. validate_plugin(Plugin);
  124. plugin_providers({Plugin, _}) when is_atom(Plugin) ->
  125. validate_plugin(Plugin);
  126. plugin_providers(Plugin) when is_atom(Plugin) ->
  127. validate_plugin(Plugin).
  128. validate_plugin(Plugin) ->
  129. _ = application:load(Plugin),
  130. case application:get_env(Plugin, providers) of
  131. {ok, Providers} ->
  132. Providers;
  133. undefined ->
  134. Exports = Plugin:module_info(exports),
  135. case lists:member({init,1}, Exports) of
  136. false ->
  137. ?WARN("Plugin ~p does not export init/1. It will not be used.", [Plugin]),
  138. [];
  139. true ->
  140. [Plugin]
  141. end
  142. end.