diff options
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | src/rcl_cmd_args.erl | 78 | ||||
-rw-r--r-- | src/rcl_state.erl | 12 | ||||
-rw-r--r-- | src/relcool.erl | 8 | ||||
-rw-r--r-- | test/rclt_command_SUITE.erl | 2 | ||||
-rw-r--r-- | test/rclt_discover_SUITE.erl | 2 | ||||
-rw-r--r-- | test/rclt_release_SUITE.erl | 24 |
7 files changed, 77 insertions, 54 deletions
@@ -14,7 +14,7 @@ applications it will generate a release output. That output depends heavily on what plugins available and what options are defined, but usually it is simple a well configured release directory. - relcool -l ~/my-dirs --relname foo --relvsn 0.0.1 --target-spec myapp --target-spec getopt>=0.5.1 -o output-dir --targz + relcool -c relcool.config -l ~/my-dirs --relname foo --relvsn 0.0.1 --target-spec myapp --target-spec getopt>=0.5.1 -o output-dir The *release-specification-file* is optional but otherwise contains additional specification information for releases. @@ -43,6 +43,9 @@ additional specification information for releases. -V *INTEGER*, \--verbose *INTEGER* : The verbosity level of the system. Valid values are 1 - 3 +-c *INTEGER*, \--config *INTEGER* +: The custom config file for the relcool system + # CONFIGURATION FILES Configuration files diff --git a/src/rcl_cmd_args.erl b/src/rcl_cmd_args.erl index 99a3d7d..973abe3 100644 --- a/src/rcl_cmd_args.erl +++ b/src/rcl_cmd_args.erl @@ -38,18 +38,17 @@ args2state({ok, {Opts, Target}}) when erlang:length(Target) == 0; erlang:length(Target) == 1 -> RelName = proplists:get_value(relname, Opts, undefined), RelVsn = proplists:get_value(relvsn, Opts, undefined), - case create_log(Opts, - [{relname, RelName}, - {relvsn, RelVsn}]) of - Error = {error, _} -> - Error; - {ok, CommandLineConfig} -> - case validate_configs(Target) of + case convert_target(Target) of + {ok, AtomizedTarget} -> + case create_log(Opts, [{relname, RelName}, + {relvsn, RelVsn}]) of Error = {error, _} -> Error; - {ok, Configs} -> - {ok, rcl_state:new(CommandLineConfig, Configs)} - end + {ok, CommandLineConfig} -> + handle_config(Opts, AtomizedTarget, CommandLineConfig) + end; + Error -> + Error end; args2state({ok, {_Opts, Targets}}) -> ?RCL_ERROR({invalid_targets, Targets}). @@ -84,32 +83,47 @@ format_error({not_directory, Dir}) -> io_lib:format("Library directory does not exist: ~s", [Dir]); format_error({invalid_log_level, LogLevel}) -> io_lib:format("Invalid log level specified -V ~p, log level must be in the" - " range 0..2", [LogLevel]). + " range 0..2", [LogLevel]); +format_error({invalid_target, Target}) -> + io_lib:format("Invalid action specified: ~s", [Target]). + %%%=================================================================== %%% Internal Functions %%%=================================================================== --spec validate_configs([file:filename()]) -> - {ok, [file:filename()]} | relcool:error(). -validate_configs(Configs) -> - Result = - lists:foldl(fun(_Config, Err = {error, _}) -> - Err; - (Config, Acc) -> - case filelib:is_regular(Config) of - true -> - [filename:absname(Config) | Acc]; - false -> - ?RCL_ERROR({invalid_config_file, Config}) - end - end, [], Configs), - case Result of - {error, _} -> - Result; - _ -> - %% Order may be important so lets make sure they remain in the same - %% order they came in as - {ok, lists:reverse(Result)} +-spec handle_config([getopt:option()], atom(), proplists:proplist()) -> + {ok, {rcl_state:t(), [string()]}} | + relcool:error(). +handle_config(Opts, Target, CommandLineConfig) -> + case validate_config(proplists:get_value(config, Opts, [])) of + Error = {error, _} -> + Error; + {ok, Config} -> + {ok, rcl_state:new([{config, Config} | CommandLineConfig], Target)} + end. + +-spec convert_target([string()]) -> {ok, release | relup} | relcool:error(). +convert_target([]) -> + {ok, release}; +convert_target(["release"]) -> + {ok, release}; +convert_target(["relup"]) -> + {ok, relup}; +convert_target(Target) -> + ?RCL_ERROR({invalid_target, Target}). + +-spec validate_config(file:filename() | undefined) -> + {ok, file:filename() | undefined} | relcool:error(). +validate_config(undefined) -> + {ok, undefined}; +validate_config("") -> + {ok, undefined}; +validate_config(Config) -> + case filelib:is_regular(Config) of + true -> + filename:absname(Config); + false -> + ?RCL_ERROR({invalid_config_file, Config}) end. -spec create_log([getopt:option()], rcl_state:cmd_args()) -> diff --git a/src/rcl_state.erl b/src/rcl_state.erl index a2e6c66..ecf3115 100644 --- a/src/rcl_state.erl +++ b/src/rcl_state.erl @@ -62,6 +62,7 @@ -record(state_t, {log :: rcl_log:t(), root_dir :: file:name(), caller :: caller(), + action :: atom(), output_dir :: file:name(), lib_dirs=[] :: [file:name()], config_file=[] :: file:filename(), @@ -92,14 +93,17 @@ %% API %%============================================================================ %% @doc Create a new 'log level' for the system --spec new(proplists:proplist(), [file:filename()] | file:filename()) -> t(). -new(PropList, Target) when erlang:is_list(PropList) -> +-spec new(proplists:proplist(), atom()) -> t(). +new(PropList, Target) + when erlang:is_list(PropList), + erlang:is_atom(Target) -> {ok, Root} = file:get_cwd(), State0 = #state_t{log = proplists:get_value(log, PropList, rcl_log:new(error)), output_dir=proplists:get_value(output_dir, PropList, ""), lib_dirs=proplists:get_value(lib_dirs, PropList, ""), - config_file=Target, + config_file=proplists:get_value(config, PropList, ""), + action = Target, goals=proplists:get_value(goals, PropList, []), providers = [], releases=ec_dictionary:new(ec_dict), @@ -286,7 +290,7 @@ create_logic_providers(State0) -> new_test() -> LogState = rcl_log:new(error), - RCLState = new([{log, LogState}], []), + RCLState = new([{log, LogState}], release), ?assertMatch(LogState, log(RCLState)). -endif. diff --git a/src/relcool.erl b/src/relcool.erl index 42923c4..83886c5 100644 --- a/src/relcool.erl +++ b/src/relcool.erl @@ -48,7 +48,7 @@ main(Args) -> {ok, State} -> run_relcool_process(rcl_state:caller(State, command_line)); Error={error, _} -> - report_error(rcl_state:caller(rcl_state:new([], []), + report_error(rcl_state:caller(rcl_state:new([], undefined), command_line), Error) end. @@ -106,8 +106,9 @@ do(RootDir, RelName, RelVsn, Goals, LibDirs, LogLevel, OutputDir, Overrides, Con {output_dir, OutputDir}, {lib_dirs, LibDirs}, {root_dir, RootDir}, - {log, rcl_log:new(LogLevel)}], - Config), + {log, rcl_log:new(LogLevel)}, + {config, Config}], + release), run_relcool_process(rcl_state:caller(State, api)). @@ -127,6 +128,7 @@ opt_spec_list() -> "Disable the default system added lib dirs (means you must add them all manually"}, {log_level, $V, "verbose", {integer, 1}, "Verbosity level, maybe between 0 and 2"}, + {config, $c, "config", string, "The path to a config file"}, {root_dir, $r, "root", string, "The project root directory"}]. -spec format_error(Reason::term()) -> iolist(). diff --git a/test/rclt_command_SUITE.erl b/test/rclt_command_SUITE.erl index 78f05fc..3d06dad 100644 --- a/test/rclt_command_SUITE.erl +++ b/test/rclt_command_SUITE.erl @@ -88,6 +88,6 @@ spec_parse_fail_case(_Config) -> config_fail_case(_Config) -> ConfigFile = "does-not-exist", - CmdLine = [ConfigFile], + CmdLine = ["-c", ConfigFile], ?assertMatch({error, {_, {invalid_config_file, ConfigFile}}}, rcl_cmd_args:args2state(getopt:parse(relcool:opt_spec_list(), CmdLine))). diff --git a/test/rclt_discover_SUITE.erl b/test/rclt_discover_SUITE.erl index f8dc8a3..4b6cb2a 100644 --- a/test/rclt_discover_SUITE.erl +++ b/test/rclt_discover_SUITE.erl @@ -46,7 +46,7 @@ init_per_testcase(_, Config) -> LibDir2 = filename:join([DataDir, create_random_name("lib_dir2_")]), ok = rcl_util:mkdir_p(LibDir1), ok = rcl_util:mkdir_p(LibDir2), - State = rcl_state:new([{lib_dirs, [LibDir1, LibDir2]}], []), + State = rcl_state:new([{lib_dirs, [LibDir1, LibDir2]}], release), [{lib1, LibDir1}, {lib2, LibDir2}, {state, State} | Config]. diff --git a/test/rclt_release_SUITE.erl b/test/rclt_release_SUITE.erl index 23cdb9e..95aa385 100644 --- a/test/rclt_release_SUITE.erl +++ b/test/rclt_release_SUITE.erl @@ -52,7 +52,7 @@ init_per_testcase(_, Config) -> DataDir = proplists:get_value(data_dir, Config), LibDir1 = filename:join([DataDir, create_random_name("lib_dir1_")]), ok = rcl_util:mkdir_p(LibDir1), - State = rcl_state:new([{lib_dirs, [LibDir1]}], []), + State = rcl_state:new([{lib_dirs, [LibDir1]}], release), [{lib1, LibDir1}, {state, State} | Config]. @@ -86,7 +86,7 @@ make_release(Config) -> OutputDir = filename:join([proplists:get_value(data_dir, Config), create_random_name("relcool-output")]), {ok, State} = relcool:do(undefined, undefined, [], [LibDir1], 2, - OutputDir, [ConfigFile]), + OutputDir, ConfigFile), [{{foo, "0.0.1"}, Release}] = ec_dictionary:to_list(rcl_state:releases(State)), AppSpecs = rcl_release:applications(Release), ?assert(lists:keymember(stdlib, 1, AppSpecs)), @@ -122,7 +122,7 @@ make_invalid_config_release(Config) -> create_random_name("relcool-output")]), {error, {rcl_prv_config, {consult, _, _}}} = relcool:do(undefined, undefined, [], [LibDir1], 2, - OutputDir, [ConfigFile]). + OutputDir, ConfigFile). make_scriptless_release(Config) -> LibDir1 = proplists:get_value(lib1, Config), @@ -149,7 +149,7 @@ make_scriptless_release(Config) -> OutputDir = filename:join([proplists:get_value(data_dir, Config), create_random_name("relcool-output")]), {ok, State} = relcool:do(undefined, undefined, [], [LibDir1], 2, - OutputDir, [ConfigFile]), + OutputDir, ConfigFile), ?assert(not ec_file:exists(filename:join([OutputDir, "bin", "foo"]))), ?assert(not ec_file:exists(filename:join([OutputDir, "bin", "foo-0.0.1"]))), @@ -200,7 +200,7 @@ make_overridden_release(Config) -> {ok, Cwd} = file:get_cwd(), {ok, State} = relcool:do(Cwd, undefined, undefined, [], [LibDir1], 2, OutputDir, [{OverrideAppName, OverrideAppDir}], - [ConfigFile]), + ConfigFile), [{{foo, "0.0.1"}, Release}] = ec_dictionary:to_list(rcl_state:releases(State)), AppSpecs = rcl_release:applications(Release), ?assert(lists:keymember(stdlib, 1, AppSpecs)), @@ -289,13 +289,13 @@ make_rerun_overridden_release(Config) -> create_random_name("relcool-output")]), {ok, Cwd} = file:get_cwd(), {ok, State} = relcool:do(Cwd, undefined, undefined, [], [LibDir1], 2, - OutputDir, [{OverrideAppName, OverrideAppDir}], - [ConfigFile]), + OutputDir, [{OverrideAppName, OverrideAppDir}], + ConfigFile), %% Now we run it again to see if it failse. {ok, State} = relcool:do(Cwd,undefined, undefined, [], [LibDir1], 2, - OutputDir, [{OverrideAppName, OverrideAppDir}], - [ConfigFile]), + OutputDir, [{OverrideAppName, OverrideAppDir}], + ConfigFile), [{{foo, "0.0.1"}, Release}] = ec_dictionary:to_list(rcl_state:releases(State)), AppSpecs = rcl_release:applications(Release), @@ -358,7 +358,7 @@ overlay_release(Config) -> create_random_name("relcool-output")]), {ok, State} = relcool:do(undefined, undefined, [], [LibDir1], 2, - OutputDir, [ConfigFile]), + OutputDir, ConfigFile), [{{foo, "0.0.1"}, Release}] = ec_dictionary:to_list(rcl_state:releases(State)), AppSpecs = rcl_release:applications(Release), @@ -469,7 +469,7 @@ make_goalless_release(Config) -> create_random_name("relcool-output")]), ?assertMatch({error,{rcl_prv_release,no_goals_specified}}, relcool:do(undefined, undefined, [], [LibDir1], 2, - OutputDir, [ConfigFile])). + OutputDir, ConfigFile)). make_depfree_release(Config) -> LibDir1 = proplists:get_value(lib1, Config), @@ -494,7 +494,7 @@ make_depfree_release(Config) -> OutputDir = filename:join([proplists:get_value(data_dir, Config), create_random_name("relcool-output")]), {ok, State} = relcool:do(undefined, undefined, [], [LibDir1], 2, - OutputDir, [ConfigFile]), + OutputDir, ConfigFile), [{{foo, "0.0.1"}, Release}] = ec_dictionary:to_list(rcl_state:releases(State)), AppSpecs = rcl_release:applications(Release), ?assert(lists:keymember(stdlib, 1, AppSpecs)), |