Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

232 рядки
7.6 KiB

10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
  1. -module(rebar_state).
  2. -export([new/0, new/1, new/2, new/3,
  3. get/2, get/3, set/3,
  4. lock/1,
  5. lock/2,
  6. current_profile/1,
  7. current_profile/2,
  8. command_args/1, command_args/2,
  9. command_parsed_args/1, command_parsed_args/2,
  10. apply_profile/2,
  11. dir/1, dir/2,
  12. create_logic_providers/2,
  13. project_apps/1, project_apps/2,
  14. all_deps/1, all_deps/2,
  15. deps_names/1,
  16. prepend_hook/3, append_hook/3, hooks/2,
  17. providers/1, providers/2, add_provider/2]).
  18. -include("rebar.hrl").
  19. -record(state_t, {dir :: file:name(),
  20. opts = dict:new() :: rebar_dict(),
  21. default = dict:new() :: rebar_dict(),
  22. lock = [],
  23. current_profile = default :: atom(),
  24. command_args = [],
  25. command_parsed_args = [],
  26. project_apps = [] :: [rebar_app_into:t()],
  27. all_deps = [] :: [rebar_app_into:t()],
  28. providers = []}).
  29. -export_type([t/0]).
  30. -type t() :: record(state_t).
  31. -spec new() -> t().
  32. new() ->
  33. #state_t{dir = rebar_utils:get_cwd()}.
  34. -spec new(list()) -> t().
  35. new(Config) when is_list(Config) ->
  36. Opts = dict:from_list(Config),
  37. #state_t { dir = rebar_utils:get_cwd(),
  38. default = Opts,
  39. opts = Opts }.
  40. -spec new(t() | atom(), list()) -> t().
  41. new(Profile, Config) when is_atom(Profile)
  42. , is_list(Config) ->
  43. Opts = dict:from_list(Config),
  44. #state_t { dir = rebar_utils:get_cwd(),
  45. current_profile = Profile,
  46. default = Opts,
  47. opts = Opts };
  48. new(ParentState=#state_t{}, Config) ->
  49. %% Load terms from rebar.config, if it exists
  50. Dir = rebar_utils:get_cwd(),
  51. new(ParentState, Config, Dir).
  52. -spec new(t(), list(), file:name()) -> t().
  53. new(ParentState, Config, Dir) ->
  54. Opts = ParentState#state_t.opts,
  55. LocalOpts = case rebar_config:consult_file(?LOCK_FILE) of
  56. [D] ->
  57. dict:from_list([{locks, D} | Config]);
  58. _ ->
  59. dict:from_list(Config)
  60. end,
  61. NewOpts = dict:merge(fun(_Key, Value1, _Value2) ->
  62. Value1
  63. end, LocalOpts, Opts),
  64. ProviderModules = [],
  65. create_logic_providers(ProviderModules
  66. ,ParentState#state_t{dir=Dir
  67. ,opts=NewOpts
  68. ,default=NewOpts}).
  69. get(State, Key) ->
  70. {ok, Value} = dict:find(Key, State#state_t.opts),
  71. Value.
  72. get(State, Key, Default) ->
  73. case dict:find(Key, State#state_t.opts) of
  74. {ok, Value} ->
  75. Value;
  76. error ->
  77. Default
  78. end.
  79. -spec set(t(), any(), any()) -> t().
  80. set(State=#state_t{opts=Opts}, Key, Value) ->
  81. State#state_t{ opts = dict:store(Key, Value, Opts) }.
  82. current_profile(#state_t{current_profile=Profile}) ->
  83. Profile.
  84. current_profile(State, Profile) ->
  85. State#state_t{current_profile=Profile}.
  86. lock(#state_t{lock=Lock}) ->
  87. Lock.
  88. lock(State=#state_t{lock=Lock}, App) ->
  89. State#state_t{lock=[App | Lock]}.
  90. command_args(#state_t{command_args=CmdArgs}) ->
  91. CmdArgs.
  92. command_args(State, CmdArgs) ->
  93. State#state_t{command_args=CmdArgs}.
  94. command_parsed_args(#state_t{command_parsed_args=CmdArgs}) ->
  95. CmdArgs.
  96. command_parsed_args(State, CmdArgs) ->
  97. State#state_t{command_parsed_args=CmdArgs}.
  98. %% Only apply profiles to the default profile
  99. apply_profile(State=#state_t{default=Opts}, Profile) ->
  100. ConfigProfiles = rebar_state:get(State, profiles, []),
  101. Deps = rebar_state:get(State, deps, []),
  102. Opts1 = dict:store({deps, default}, Deps, dict:erase(deps, Opts)),
  103. ProfileOpts = dict:from_list(proplists:get_value(Profile, ConfigProfiles, [])),
  104. State#state_t{opts=merge_opts(Profile, ProfileOpts, Opts1)}.
  105. merge_opts(Profile, Opts1, Opts2) ->
  106. dict:fold(fun(deps, Value, OptsAcc) ->
  107. dict:store({deps, Profile}, Value, OptsAcc);
  108. (Key, Value, OptsAcc) ->
  109. case dict:fetch(Key, 1, Opts2) of
  110. {_, OldValue} when is_list(OldValue) ->
  111. case io_lib:printable_list(Value) of
  112. true ->
  113. dict:store(Key, OptsAcc, {Key, Value});
  114. false ->
  115. dict:store(Key, OptsAcc, {Key, lists:keymerge(1, lists:keysort(1, OldValue), lists:keysort(1, Value))})
  116. end;
  117. error ->
  118. dict:store(Key, Value, OptsAcc)
  119. end
  120. end, Opts2, Opts1).
  121. dir(#state_t{dir=Dir}) ->
  122. Dir.
  123. dir(State=#state_t{}, Dir) ->
  124. State#state_t{dir=filename:absname(Dir)}.
  125. deps_names(Deps) when is_list(Deps) ->
  126. lists:map(fun(Dep) when is_tuple(Dep) ->
  127. ec_cnv:to_binary(element(1, Dep));
  128. (Dep) when is_atom(Dep) ->
  129. ec_cnv:to_binary(Dep)
  130. end, Deps);
  131. deps_names(State) ->
  132. Deps = rebar_state:get(State, deps, []),
  133. deps_names(Deps).
  134. project_apps(#state_t{project_apps=Apps}) ->
  135. Apps.
  136. project_apps(State=#state_t{}, NewApps) when is_list(NewApps) ->
  137. State#state_t{project_apps=NewApps};
  138. project_apps(State=#state_t{project_apps=Apps}, App) ->
  139. State#state_t{project_apps=lists:keystore(rebar_app_info:name(App), 2, Apps, App)}.
  140. all_deps(#state_t{all_deps=Apps}) ->
  141. Apps.
  142. all_deps(State=#state_t{}, NewApps) ->
  143. State#state_t{all_deps=NewApps}.
  144. providers(#state_t{providers=Providers}) ->
  145. Providers.
  146. providers(State, NewProviders) ->
  147. State#state_t{providers=NewProviders}.
  148. -spec add_provider(t(), providers:t()) -> t().
  149. add_provider(State=#state_t{providers=Providers}, Provider) ->
  150. State#state_t{providers=[Provider | Providers]}.
  151. create_logic_providers(ProviderModules, State0) ->
  152. lists:foldl(fun(ProviderMod, Acc) ->
  153. case providers:new(ProviderMod, Acc) of
  154. {error, Reason} ->
  155. ?ERROR(Reason++"~n", []),
  156. Acc;
  157. {ok, State1} ->
  158. State1
  159. end
  160. end, State0, ProviderModules).
  161. prepend_hook(State=#state_t{providers=Providers}, Target, Hook) ->
  162. State#state_t{providers=add_hook(pre, Providers, Target, Hook)}.
  163. append_hook(State=#state_t{providers=Providers}, Target, Hook) ->
  164. State#state_t{providers=add_hook(post, Providers, Target, Hook)}.
  165. -spec hooks(t(), atom()) -> {[providers:t()], [providers:t()]}.
  166. hooks(_State=#state_t{providers=Providers}, Target) ->
  167. Provider = providers:get_provider(Target, Providers),
  168. providers:hooks(Provider).
  169. %% ===================================================================
  170. %% Internal functions
  171. %% ===================================================================
  172. add_hook(Which, Providers, Target, Hook) ->
  173. Provider = providers:get_provider(Target, Providers),
  174. Hooks = providers:hooks(Provider),
  175. NewHooks = add_hook(Which, Hooks, Hook),
  176. NewProvider = providers:hooks(Provider, NewHooks),
  177. [NewProvider | lists:delete(Provider, Providers)].
  178. add_hook(pre, {PreHooks, PostHooks}, Hook) ->
  179. {[Hook | PreHooks], PostHooks};
  180. add_hook(post, {PreHooks, PostHooks}, Hook) ->
  181. {PreHooks, [Hook | PostHooks]}.