-module(rebar_state). -export([new/0, new/1, new/2, new/3, get/2, get/3, set/3, command_args/1, command_args/2, set_skip_dir/2, is_skip_dir/2, reset_skip_dirs/1, create_logic_providers/2, apps_to_build/1, apps_to_build/2, providers/1, providers/2, add_provider/2]). -include("rebar.hrl"). -ifdef(namespaced_types). %% dict:dict() exists starting from Erlang 17. -type rebar_dict() :: dict:dict(term(), term()). -else. %% dict() has been obsoleted in Erlang 17 and deprecated in 18. -type rebar_dict() :: dict(). -endif. -record(state_t, {dir :: file:filename(), opts = [] :: list(), local_opts = [] :: list(), config = new_globals() :: rebar_dict(), envs = new_env() :: rebar_dict(), command_args = [] :: list(), apps = dict:new() :: rebar_dict(), goals = [], providers = [], apps_to_build = [], skip_dirs = new_skip_dirs() :: rebar_dict() }). -export_type([t/0]). -opaque t() :: #state_t{}. -spec new() -> t(). new() -> #state_t{dir = rebar_utils:get_cwd()}. -spec new(list()) -> t(). new(Config) when is_list(Config) -> #state_t { dir = rebar_utils:get_cwd(), opts = Config }. -spec new(t(), list()) -> t(). new(ParentState=#state_t{}, Config) -> %% Load terms from rebar.config, if it exists Dir = rebar_utils:get_cwd(), new(ParentState, Config, Dir). -spec new(t(), list(), file:name()) -> t(). new(ParentState, Config, Dir) -> _Opts = ParentState#state_t.opts, LocalOpts = case rebar_config:consult_file(?LOCK_FILE) of {ok, [D]} -> [{lock_deps, D} | Config]; _ -> Config end, ProviderModules = [], create_logic_providers(ProviderModules, ParentState#state_t{dir=Dir ,opts=LocalOpts}). get(State, Key) -> proplists:get_value(Key, State#state_t.opts). get(State, Key, Default) -> proplists:get_value(Key, State#state_t.opts, Default). set(State, Key, Value) -> Opts = proplists:delete(Key, State#state_t.opts), State#state_t { opts = [{Key, Value} | Opts] }. set_skip_dir(State, Dir) -> OldSkipDirs = State#state_t.skip_dirs, NewSkipDirs = case is_skip_dir(State, Dir) of false -> ?DEBUG("Adding skip dir: ~s\n", [Dir]), dict:store(Dir, true, OldSkipDirs); true -> OldSkipDirs end, State#state_t{skip_dirs = NewSkipDirs}. is_skip_dir(State, Dir) -> dict:is_key(Dir, State#state_t.skip_dirs). reset_skip_dirs(State) -> State#state_t{skip_dirs = new_skip_dirs()}. command_args(#state_t{command_args=CmdArgs}) -> CmdArgs. command_args(State, CmdArgs) -> State#state_t{command_args=CmdArgs}. apps_to_build(#state_t{apps_to_build=Apps}) -> Apps. apps_to_build(State=#state_t{apps_to_build=Apps}, Apps) when is_list(Apps) -> State#state_t{apps_to_build=Apps}; apps_to_build(State=#state_t{apps_to_build=Apps}, App) -> State#state_t{apps_to_build=[App | Apps]}. providers(#state_t{providers=Providers}) -> Providers. providers(State, NewProviders) -> State#state_t{providers=NewProviders}. add_provider(State=#state_t{providers=Providers}, Provider) -> State#state_t{providers=[Provider | Providers]}. create_logic_providers(ProviderModules, State0) -> lists:foldl(fun(ProviderMod, Acc) -> {ok, State1} = rebar_provider:new(ProviderMod, Acc), State1 end, State0, ProviderModules). %% =================================================================== %% Internal functions %% =================================================================== new_globals() -> dict:new(). new_env() -> dict:new(). new_skip_dirs() -> dict:new().