您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

243 行
7.8 KiB

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