From d61ea701c8acf2ad4102048e740f9eacd76b9687 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Fri, 13 Sep 2013 21:45:40 -0500 Subject: fix crash instead of error message for bad target action --- src/rlx_state.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rlx_state.erl b/src/rlx_state.erl index d03631d..65b0565 100644 --- a/src/rlx_state.erl +++ b/src/rlx_state.erl @@ -106,7 +106,9 @@ %% API %%============================================================================ %% @doc Create a new 'log level' for the system --spec new(proplists:proplist(), [atom()]) -> t(). +-spec new(proplists:proplist(), undefined | [atom()]) -> t(). +new(PropList, undefined) -> + new(PropList, [release]); new(PropList, Targets) when erlang:is_list(PropList), erlang:is_list(Targets) -> -- cgit v1.2.3 From 5d56280d54d0a02883783bf1b719df1780eb096c Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Fri, 13 Sep 2013 22:54:12 -0500 Subject: only print usage on opt_parse error or new option -h --- src/relx.erl | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/relx.erl b/src/relx.erl index 7419352..bc3fbaa 100644 --- a/src/relx.erl +++ b/src/relx.erl @@ -47,7 +47,12 @@ main(Args) -> OptSpecList = opt_spec_list(), Result = case getopt:parse(OptSpecList, Args) of {ok, {Options, NonOptions}} -> - do([{caller, command_line} | Options], NonOptions); + case lists:member(help, Options) of + true -> + usage(); + false -> + do([{caller, command_line} | Options], NonOptions) + end; {error, Detail} -> ?RLX_ERROR({opt_parse, Detail}) end, @@ -174,6 +179,8 @@ opt_spec_list() -> "Only valid with relup target, specify the release to upgrade from"}, {output_dir, $o, "output-dir", string, "The output directory for the release. This is `./` by default."}, + {help, $h, "help", undefined, + "Print usage"}, {lib_dir, $l, "lib-dir", string, "Additional dirs that should be searched for OTP Apps"}, {disable_default_libs, undefined, "disable-default-libs", @@ -186,14 +193,16 @@ opt_spec_list() -> {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(). +-spec format_error(Reason::term()) -> string(). format_error({invalid_return_value, Provider, Value}) -> - [rlx_provider:format(Provider), " returned an invalid value ", - io_lib:format("~p", [Value])]; + io_lib:format(lists:flatten([rlx_provider:format(Provider), " returned an invalid value ", + io_lib:format("~p", [Value])]), []); format_error({opt_parse, {invalid_option, Opt}}) -> io_lib:format("invalid option ~s~n", [Opt]); format_error({opt_parse, Arg}) -> io_lib:format("~p~n", [Arg]); +format_error({error, {relx, Reason}}) -> + format_error(Reason); format_error({error, {Module, Reason}}) -> io_lib:format("~s~n", [Module:format_error(Reason)]). @@ -268,8 +277,16 @@ usage() -> -spec report_error(rlx_state:t(), error()) -> none() | error(). report_error(State, Error) -> - io:format(format_error(Error)), - usage(), + case Error of + {error, {relx, {opt_parse, _}}} -> + io:format(standard_error, format_error(Error), []), + usage(); + {error, {rlx_cmd_args, _}} -> + io:format(standard_error, format_error(Error), []), + usage(); + _ -> + io:format(standard_error, format_error(Error), []) + end, case rlx_state:caller(State) of command_line -> erlang:halt(127); -- cgit v1.2.3 From 36127c167958d66c36c9bdc58f7110ac02fffe8f Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Fri, 13 Sep 2013 22:56:00 -0500 Subject: fix config option type in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e1223f..e14ec95 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ This creates the executable `relx`. -V *INTEGER*, \--verbose *INTEGER* : The verbosity level of the system. Valid values are 1 - 3 --c *INTEGER*, \--config *INTEGER* +-c *STRING*, \--config *STRING* : The custom config file for the relx system # CONFIGURATION FILES -- cgit v1.2.3 From fcd353f9302a2cd09dc133250b17156b5d29c742 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Fri, 13 Sep 2013 22:56:38 -0500 Subject: fix verbose value range in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e14ec95..19aa1e9 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ This creates the executable `relx`. : Additional dirs that should be searched for OTP Apps -V *INTEGER*, \--verbose *INTEGER* -: The verbosity level of the system. Valid values are 1 - 3 +: The verbosity level of the system. Valid values are 0 - 2 -c *STRING*, \--config *STRING* : The custom config file for the relx system -- cgit v1.2.3 From 8606f9cb6d5f71611643780235bc0e57a757a759 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Fri, 13 Sep 2013 23:12:01 -0500 Subject: simplify and improve README --- README.md | 83 +++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 19aa1e9..ba4b391 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,29 @@ [![Build Status](https://drone.io/github.com/erlware/relx/status.png)](https://drone.io/github.com/erlware/relx/latest) -# NAME +Relx +======= -relx - A release assembler for erlang +A release assembler for Erlang. -# SYNOPSIS +Synopsis +-------- relx [*options*] [*release-specification-file*] -# DESCRIPTION +Description +----------- Relx assembles releases for an Erlang/OTP release. Given a release specification and a list of directories in which to search for OTP 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. - - relx -c relx.config -l ~/my-dirs --relname foo --relvsn 0.0.1 --target-spec myapp --target-spec getopt>=0.5.1 -o output-dir +usually it is simply a well configured release directory. The *release-specification-file* is optional but otherwise contains additional specification information for releases. -# BUILDING +Building +-------- To build relx and generate a standalone escript executable: @@ -29,39 +31,36 @@ To build relx and generate a standalone escript executable: This creates the executable `relx`. -# OPTIONS - --r *STRING*, \--root *STRING* -: Specify the root directory for the project (if different from cwd) - --n *STRING*, \--relname *STRING* -: Specify the name for the release that will be generated - --v *STRING*, \--relvsn=*STRING* -: Specify the version for the release - --g *STRING*, \--goals *STRING* -: Specify a goal to the system. These are usually the OTP - Apps that are part of the release - --o *STRING*, \--output-dir *STRING* -: The output directory for the release. This is `./` by default. - --l *STRING*, \--lib-dir *STRING* -: Additional dirs that should be searched for OTP Apps - --V *INTEGER*, \--verbose *INTEGER* -: The verbosity level of the system. Valid values are 0 - 2 - --c *STRING*, \--config *STRING* -: The custom config file for the relx system - -# CONFIGURATION FILES - -Configuration files - -# SEE ALSO - -`reltool` (1). +Config File +----------- + +By default `relx` looks for `relx.config` in the current working directory: + +```erlang +{release, {relname, "vsn"}, + [app1, + app2]}. + +{extended_start_script, true}. +``` + +Options +------- + +| Short | Long | Type | Default | Description | +|:-----:|:------------:|:-------:|:------:|------------------------------------------------------------------------------------------- | +| -r | --root | string | ./ | Name for the release that will be generated | +| -v | --relvsn | string | | Version for the release | +| -g | --goal | string | | A goal for the system. These are usually the OTP apps that are part of the release | +| -u | --upfrom | string | | The release to upgrade from. Only valid with relup target | +| -o | --output-dir | string | ./ | The output directory for the release | +| -l | --lib-dir | string | | Additional dirs to search for OTP apps | +| | --disable-default-libs | boolean | false | Disable use of the default system added lib dirs | +| -V | --verbose | integer | 0 | The verbosity level between 0 and 2 | +| -a | --override_app | string | | An app name and a directory to override in the form appname:dir | +| -c | --config | string | ./relx.config | Config file path | + +Wiki +---- [relx wiki](https://github.com/erlware/relx/wiki) -- cgit v1.2.3 From d72e2cda09df280e1e690d9233790ebbb9e58812 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Sat, 14 Sep 2013 13:15:47 -0500 Subject: improved user output look --- src/rlx_app_discovery.erl | 4 ++-- src/rlx_log.erl | 34 +++++++++++++++++++++++++++------- src/rlx_prv_assembler.erl | 10 +++++----- src/rlx_prv_overlay.erl | 2 +- src/rlx_prv_release.erl | 2 +- src/rlx_rel_discovery.erl | 4 ++-- src/rlx_release.erl | 10 +++++----- src/rlx_state.erl | 22 +++++++++++----------- src/rlx_topo.erl | 4 ++-- src/rlx_util.erl | 2 +- 10 files changed, 57 insertions(+), 37 deletions(-) diff --git a/src/rlx_app_discovery.erl b/src/rlx_app_discovery.erl index e6b6e2c..6407124 100644 --- a/src/rlx_app_discovery.erl +++ b/src/rlx_app_discovery.erl @@ -40,7 +40,7 @@ do(State, LibDirs) -> rlx_log:info(rlx_state:log(State), fun() -> ["Resolving OTP Applications from directories:\n", - [[rlx_util:indent(1), LibDir, "\n"] || LibDir <- LibDirs]] + [[rlx_util:indent(2), LibDir, "\n"] || LibDir <- LibDirs]] end), resolve_app_metadata(State, LibDirs). @@ -72,7 +72,7 @@ resolve_app_metadata(State, LibDirs) -> rlx_log:debug(rlx_state:log(State), fun() -> ["Resolved the following OTP Applications from the system: \n", - [[rlx_app_info:format(1, App), "\n"] || App <- AppMeta1]] + [[rlx_app_info:format(2, App), "\n"] || App <- AppMeta1]] end), {ok, AppMeta1}; Errors -> diff --git a/src/rlx_log.erl b/src/rlx_log.erl index 901ae7c..6122e9b 100644 --- a/src/rlx_log.erl +++ b/src/rlx_log.erl @@ -59,6 +59,17 @@ -type log_fun() :: fun(() -> iolist()). +-type color() :: 31..36. + +-define(RED, 31). +-define(GREEN, 32). +-define(YELLOW, 33). +-define(BLUE, 34). +-define(MAGENTA, 35). +-define(CYAN, 36). + +-define(PREFIX, "===> "). + %%============================================================================ %% API %%============================================================================ @@ -83,7 +94,7 @@ new(AtomLogLevel) -spec debug(t(), string() | log_fun()) -> ok. debug(LogState, Fun) when erlang:is_function(Fun) -> - log(LogState, ?RLX_DEBUG, Fun); + log(LogState, ?RLX_DEBUG, fun() -> colorize(?CYAN, false, Fun()) end); debug(LogState, String) -> debug(LogState, "~s~n", [String]). @@ -91,14 +102,14 @@ debug(LogState, String) -> %% and argements @see io:format/2 -spec debug(t(), string(), [any()]) -> ok. debug(LogState, FormatString, Args) -> - log(LogState, ?RLX_DEBUG, FormatString, Args). + log(LogState, ?RLX_DEBUG, colorize(?CYAN, false, FormatString), Args). %% @doc log at the info level given the current log state with a string or %% function that returns a string -spec info(t(), string() | log_fun()) -> ok. info(LogState, Fun) when erlang:is_function(Fun) -> - log(LogState, ?RLX_INFO, Fun); + log(LogState, ?RLX_INFO, fun() -> colorize(?GREEN, false, Fun()) end); info(LogState, String) -> info(LogState, "~s~n", [String]). @@ -106,14 +117,14 @@ info(LogState, String) -> %% and argements @see io:format/2 -spec info(t(), string(), [any()]) -> ok. info(LogState, FormatString, Args) -> - log(LogState, ?RLX_INFO, FormatString, Args). + log(LogState, ?RLX_INFO, colorize(?GREEN, false, FormatString), Args). %% @doc log at the error level given the current log state with a string or %% format string that returns a function -spec error(t(), string() | log_fun()) -> ok. error(LogState, Fun) when erlang:is_function(Fun) -> - log(LogState, ?RLX_ERROR, Fun); + log(LogState, ?RLX_ERROR, fun() -> colorize(?RED, false, Fun()) end); error(LogState, String) -> error(LogState, "~s~n", [String]). @@ -121,7 +132,7 @@ error(LogState, String) -> %% and argements @see io:format/2 -spec error(t(), string(), [any()]) -> ok. error(LogState, FormatString, Args) -> - log(LogState, ?RLX_ERROR, FormatString, Args). + log(LogState, ?RLX_ERROR, colorize(?GREEN, false, FormatString), Args). %% @doc Execute the fun passed in if log level is as expected. -spec log(t(), int_log_level(), log_fun()) -> ok. @@ -131,7 +142,6 @@ log({?MODULE, DetailLogLevel}, LogLevel, Fun) log(_, _, _) -> ok. - %% @doc when the module log level is less then or equal to the log level for the %% call then write the log info out. When its not then ignore the call. -spec log(t(), int_log_level(), string(), [any()]) -> ok. @@ -172,6 +182,16 @@ format(Log) -> erlang:atom_to_list(atom_log_level(Log)), <<")">>]. +-spec colorize(color(), boolean(), string()) -> string(). +colorize(Color, false, Msg) when is_integer(Color) -> + colorize_(Color, 0, Msg); +colorize(Color, true, Msg) when is_integer(Color) -> + colorize_(Color, 1, Msg). + +-spec colorize_(color(), integer(), string()) -> string(). +colorize_(Color, Bold, Msg) when is_integer(Color), is_integer(Bold)-> + lists:flatten(io_lib:format("\033[~B;~Bm~s~s\033[0m", [Bold, Color, ?PREFIX, Msg])). + %%%=================================================================== %%% Test Functions %%%=================================================================== diff --git a/src/rlx_prv_assembler.erl b/src/rlx_prv_assembler.erl index 70c38ec..d47a850 100644 --- a/src/rlx_prv_assembler.erl +++ b/src/rlx_prv_assembler.erl @@ -101,19 +101,19 @@ format_error({release_script_generation_error, RelFile}) -> [RelFile]); format_error({release_script_generation_warning, Module, Warnings}) -> ["Warnings generating release \s", - rlx_util:indent(1), Module:format_warning(Warnings)]; + rlx_util:indent(2), Module:format_warning(Warnings)]; format_error({unable_to_create_output_dir, OutputDir}) -> io_lib:format("Unable to create output directory (possible permissions issue): ~s", [OutputDir]); format_error({release_script_generation_error, Module, Errors}) -> ["Errors generating release \n", - rlx_util:indent(1), Module:format_error(Errors)]; + rlx_util:indent(2), Module:format_error(Errors)]; format_error({relup_generation_error, CurrentName, UpFromName}) -> io_lib:format("Unknown internal release error generating the relup from ~s to ~s", [UpFromName, CurrentName]); format_error({relup_generation_warning, Module, Warnings}) -> ["Warnings generating relup \s", - rlx_util:indent(1), Module:format_warning(Warnings)]; + rlx_util:indent(2), Module:format_warning(Warnings)]; format_error({relup_script_generation_error, {relup_script_generation_error, systools_relup, {missing_sasl, _}}}) -> @@ -121,10 +121,10 @@ format_error({relup_script_generation_error, "in both the current release and the release to upgrade from."; format_error({relup_script_generation_error, Module, Errors}) -> ["Errors generating relup \n", - rlx_util:indent(1), Module:format_error(Errors)]; + rlx_util:indent(2), Module:format_error(Errors)]; format_error({unable_to_make_symlink, AppDir, TargetDir, Reason}) -> io_lib:format("Unable to symlink directory ~s to ~s because \n~s~s", - [AppDir, TargetDir, rlx_util:indent(1), + [AppDir, TargetDir, rlx_util:indent(2), file:format_error(Reason)]); format_error({tar_unknown_generation_error, Module, Vsn}) -> io_lib:format("Tarball generation error of ~s ~s", diff --git a/src/rlx_prv_overlay.erl b/src/rlx_prv_overlay.erl index f242d21..e1edb6c 100644 --- a/src/rlx_prv_overlay.erl +++ b/src/rlx_prv_overlay.erl @@ -68,7 +68,7 @@ format_error({dir_render_failed, Dir, Error}) -> [Dir, Error]); format_error({unable_to_make_symlink, AppDir, TargetDir, Reason}) -> io_lib:format("Unable to symlink directory ~s to ~s because \n~s~s", - [AppDir, TargetDir, rlx_util:indent(1), + [AppDir, TargetDir, rlx_util:indent(2), file:format_error(Reason)]); format_error({copy_failed, FromFile, ToFile, Err}) -> io_lib:format("Unable to copy from ~s to ~s because of ~p", diff --git a/src/rlx_prv_release.erl b/src/rlx_prv_release.erl index cf13953..908573b 100644 --- a/src/rlx_prv_release.erl +++ b/src/rlx_prv_release.erl @@ -175,7 +175,7 @@ set_resolved(State, Release0, Pkgs) -> rlx_release:vsn(Release1)]), rlx_log:debug(rlx_state:log(State), fun() -> - rlx_release:format(1, Release1) + rlx_release:format(0, Release1) end), {ok, rlx_state:add_realized_release(State, Release1)}; {error, E} -> diff --git a/src/rlx_rel_discovery.erl b/src/rlx_rel_discovery.erl index 3cdca3e..6f23ad0 100644 --- a/src/rlx_rel_discovery.erl +++ b/src/rlx_rel_discovery.erl @@ -40,8 +40,8 @@ do(State, LibDirs, AppMeta) -> rlx_log:info(rlx_state:log(State), fun() -> - ["Resolving available releases from directories:\n", - [[rlx_util:indent(1), LibDir, "\n"] || LibDir <- LibDirs]] + ["Resolving available OTP Releases from directories:\n", + [[rlx_util:indent(2), LibDir, "\n"] || LibDir <- LibDirs]] end), resolve_rel_metadata(State, LibDirs, AppMeta). diff --git a/src/rlx_release.erl b/src/rlx_release.erl index 68193fa..471a6f7 100644 --- a/src/rlx_release.erl +++ b/src/rlx_release.erl @@ -196,14 +196,14 @@ format(Indent, #release_t{name=Name, vsn=Vsn, erts=ErtsVsn, realized=Realized, goals = Goals, applications=Apps}) -> BaseIndent = rlx_util:indent(Indent), [BaseIndent, "release: ", rlx_util:to_string(Name), "-", Vsn, "\n", - rlx_util:indent(Indent + 1), " erts-", ErtsVsn, + rlx_util:indent(Indent + 2), " erts-", ErtsVsn, ", realized = ", erlang:atom_to_list(Realized), "\n", - BaseIndent, "goals: \n", - [[rlx_util:indent(Indent + 1), format_goal(Goal), ",\n"] || Goal <- Goals], + rlx_util:indent(Indent + 1), "goals: \n", + [[rlx_util:indent(Indent + 2), format_goal(Goal), ",\n"] || Goal <- Goals], case Realized of true -> - [BaseIndent, "applications: \n", - [[rlx_util:indent(Indent + 1), io_lib:format("~p", [App]), ",\n"] || + [rlx_util:indent(Indent + 1), "applications: \n", + [[rlx_util:indent(Indent + 2), io_lib:format("~p", [App]), ",\n"] || App <- Apps]]; false -> [] diff --git a/src/rlx_state.erl b/src/rlx_state.erl index 65b0565..81f6bef 100644 --- a/src/rlx_state.erl +++ b/src/rlx_state.erl @@ -319,17 +319,17 @@ format(#state_t{log=LogState, output_dir=OutDir, lib_dirs=LibDirs, Values1 = ec_dictionary:to_list(Values0), [rlx_util:indent(Indent), <<"state(">>, erlang:atom_to_list(Caller), <<"):\n">>, - rlx_util:indent(Indent + 1), <<"log: ">>, rlx_log:format(LogState), <<",\n">>, - rlx_util:indent(Indent + 1), "config file: ", rlx_util:optional_to_string(ConfigFile), "\n", - rlx_util:indent(Indent + 1), "goals: \n", - [[rlx_util:indent(Indent + 2), rlx_depsolver:format_constraint(Goal), ",\n"] || Goal <- Goals], - rlx_util:indent(Indent + 1), "output_dir: ", OutDir, "\n", - rlx_util:indent(Indent + 1), "lib_dirs: \n", - [[rlx_util:indent(Indent + 2), LibDir, ",\n"] || LibDir <- LibDirs], - rlx_util:indent(Indent + 1), "providers: \n", - [[rlx_util:indent(Indent + 2), rlx_provider:format(Provider), ",\n"] || Provider <- Providers], - rlx_util:indent(Indent + 1), "provider config values: \n", - [[rlx_util:indent(Indent + 2), io_lib:format("~p", [Value]), ",\n"] || Value <- Values1]]. + rlx_util:indent(Indent + 2), <<"log: ">>, rlx_log:format(LogState), <<",\n">>, + rlx_util:indent(Indent + 2), "config file: ", rlx_util:optional_to_string(ConfigFile), "\n", + rlx_util:indent(Indent + 2), "goals: \n", + [[rlx_util:indent(Indent + 3), rlx_depsolver:format_constraint(Goal), ",\n"] || Goal <- Goals], + rlx_util:indent(Indent + 2), "output_dir: ", OutDir, "\n", + rlx_util:indent(Indent + 2), "lib_dirs: \n", + [[rlx_util:indent(Indent + 3), LibDir, ",\n"] || LibDir <- LibDirs], + rlx_util:indent(Indent + 2), "providers: \n", + [[rlx_util:indent(Indent + 3), rlx_provider:format(Provider), ",\n"] || Provider <- Providers], + rlx_util:indent(Indent + 2), "provider config values: \n", + [[rlx_util:indent(Indent + 3), io_lib:format("~p", [Value]), ",\n"] || Value <- Values1]]. %%%=================================================================== %%% Internal Functions diff --git a/src/rlx_topo.erl b/src/rlx_topo.erl index 11928c1..1b3593b 100644 --- a/src/rlx_topo.erl +++ b/src/rlx_topo.erl @@ -71,9 +71,9 @@ format_error({cycle, Pairs}) -> "before we can continue:\n", case Pairs of [{P1, P2}] -> - [rlx_util:indent(1), erlang:atom_to_list(P2), "->", erlang:atom_to_list(P1)]; + [rlx_util:indent(2), erlang:atom_to_list(P2), "->", erlang:atom_to_list(P1)]; [{P1, P2} | Rest] -> - [rlx_util:indent(1), erlang:atom_to_list(P2), "->", erlang:atom_to_list(P1), + [rlx_util:indent(2), erlang:atom_to_list(P2), "->", erlang:atom_to_list(P1), [["-> ", erlang:atom_to_list(PP2), " -> ", erlang:atom_to_list(PP1)] || {PP1, PP2} <- Rest]]; [] -> [] diff --git a/src/rlx_util.erl b/src/rlx_util.erl index ac6af5c..53e9122 100644 --- a/src/rlx_util.erl +++ b/src/rlx_util.erl @@ -30,7 +30,7 @@ indent/1, optional_to_string/1]). --define(ONE_LEVEL_INDENT, " "). +-define(ONE_LEVEL_INDENT, " "). %%============================================================================ %% types %%============================================================================ -- cgit v1.2.3 From e176e1ec394f5ab44a184831238aa49bc9e0cf2b Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Sat, 14 Sep 2013 21:39:51 -0500 Subject: fix dialyzer issues --- src/rlx_app_discovery.erl | 2 +- src/rlx_cmd_args.erl | 7 +++-- src/rlx_depsolver.erl | 1 + src/rlx_dscv_util.erl | 4 +-- src/rlx_log.erl | 76 ++++++++++++++++++++++++++--------------------- src/rlx_rel_discovery.erl | 2 +- src/rlx_state.erl | 15 ++++++---- 7 files changed, 60 insertions(+), 47 deletions(-) diff --git a/src/rlx_app_discovery.erl b/src/rlx_app_discovery.erl index 6407124..d321638 100644 --- a/src/rlx_app_discovery.erl +++ b/src/rlx_app_discovery.erl @@ -35,7 +35,7 @@ %% @doc recursively dig down into the library directories specified in the state %% looking for OTP Applications --spec do(rlx_state:t(), [filename:name()]) -> {ok, [rlx_app_info:t()]} | relx:error(). +-spec do(rlx_state:t(), [file:name()]) -> {ok, [rlx_app_info:t()]} | relx:error(). do(State, LibDirs) -> rlx_log:info(rlx_state:log(State), fun() -> diff --git a/src/rlx_cmd_args.erl b/src/rlx_cmd_args.erl index 4fbadba..d144953 100644 --- a/src/rlx_cmd_args.erl +++ b/src/rlx_cmd_args.erl @@ -100,7 +100,8 @@ handle_config(Opts, Targets, CommandLineConfig) -> convert_targets(Targets) -> convert_targets(Targets, []). --spec convert_targets([string()], [string()]) -> {ok, release | relup} | relx:error(). +-spec convert_targets([string()], [rlx_state:action()]) -> + {ok, [rlx_state:action()]} | relx:error(). convert_targets([], []) -> {ok, [release]}; convert_targets([], Acc) -> @@ -134,7 +135,7 @@ create_log(Opts, Acc) -> LogLevel = proplists:get_value(log_level, Opts, 0), if LogLevel >= 0, LogLevel =< 2 -> - create_goals(Opts, [{log, rlx_log:new(LogLevel)} | Acc]); + create_goals(Opts, [{log, rlx_log:new(LogLevel, command_line)} | Acc]); true -> ?RLX_ERROR({invalid_log_level, LogLevel}) end. @@ -245,7 +246,7 @@ create_disable_default_libs(Opts, Acc) -> Def = proplists:get_value(disable_default_libs, Opts, false), create_upfrom(Opts, [{disable_default_libs, Def} | Acc]). --spec create_upfrom([getopt:option()], rcl:cmd_args()) -> +-spec create_upfrom([getopt:option()], rlx_state:cmd_args()) -> {ok, rlx_state:cmd_args()} | relx:error(). create_upfrom(Opts, Acc) -> case proplists:get_value(upfrom, Opts, undefined) of diff --git a/src/rlx_depsolver.erl b/src/rlx_depsolver.erl index 2b6e420..20423d0 100644 --- a/src/rlx_depsolver.erl +++ b/src/rlx_depsolver.erl @@ -100,6 +100,7 @@ -export_type([t/0, pkg/0, constraint_op/0, + raw_constraint/0, pkg_name/0, vsn/0, constraint/0, diff --git a/src/rlx_dscv_util.erl b/src/rlx_dscv_util.erl index 3d90b08..779534c 100644 --- a/src/rlx_dscv_util.erl +++ b/src/rlx_dscv_util.erl @@ -33,7 +33,7 @@ %% Types %%============================================================================ --type process_fun(Result) :: fun((filename:name(), file | directory) -> +-type process_fun(Result) :: fun((file:name(), file | directory) -> {ok, Result} | {error, term()} | {ok, Result, Recurse::boolean()} | @@ -46,7 +46,7 @@ %% @doc recursively dig down into the library directories specified in the state %% looking for OTP Applications --spec do(process_fun([term()] | term()), [filename:name()]) -> +-spec do(process_fun([term()] | term()), [file:name()]) -> [term() | {error, term()}]. do(ProcessDir, LibDirs) -> lists:flatten(ec_plists:map(fun(LibDir) -> diff --git a/src/rlx_log.erl b/src/rlx_log.erl index 6122e9b..608c0af 100644 --- a/src/rlx_log.erl +++ b/src/rlx_log.erl @@ -23,6 +23,7 @@ -module(rlx_log). -export([new/1, + new/2, log/4, should/2, debug/2, @@ -35,14 +36,27 @@ atom_log_level/1, format/1]). --export_type([int_log_level/0, +-export_type([t/0, + int_log_level/0, atom_log_level/0, log_level/0, - log_fun/0, - t/0]). + log_fun/0]). -include_lib("relx/include/relx.hrl"). +-define(RED, 31). +-define(GREEN, 32). +-define(YELLOW, 33). +-define(BLUE, 34). +-define(MAGENTA, 35). +-define(CYAN, 36). + +-define(PREFIX, "===> "). + +-record(state_t, {mod=?MODULE :: rlx_log, + log_level=0 :: int_log_level(), + caller=api :: api | command_line}). + %%============================================================================ %% types %%============================================================================ @@ -55,29 +69,23 @@ %% and warn -type atom_log_level() :: error | info | debug. --opaque t() :: {?MODULE, int_log_level()}. - -type log_fun() :: fun(() -> iolist()). -type color() :: 31..36. --define(RED, 31). --define(GREEN, 32). --define(YELLOW, 33). --define(BLUE, 34). --define(MAGENTA, 35). --define(CYAN, 36). - --define(PREFIX, "===> "). +-opaque t() :: record(state_t). %%============================================================================ %% API %%============================================================================ %% @doc Create a new 'log level' for the system -spec new(log_level()) -> t(). -new(LogLevel) when LogLevel >= 0, LogLevel =< 2 -> - {?MODULE, LogLevel}; -new(AtomLogLevel) +new(LogLevel) -> + new(LogLevel, api). + +new(LogLevel, Caller) when LogLevel >= 0, LogLevel =< 2 -> + #state_t{mod=?MODULE, log_level=LogLevel, caller=Caller}; +new(AtomLogLevel, Caller) when AtomLogLevel =:= error; AtomLogLevel =:= info; AtomLogLevel =:= debug -> @@ -86,7 +94,7 @@ new(AtomLogLevel) info -> 1; debug -> 2 end, - new(LogLevel). + new(LogLevel, Caller). %% @doc log at the debug level given the current log state with a string or @@ -94,7 +102,7 @@ new(AtomLogLevel) -spec debug(t(), string() | log_fun()) -> ok. debug(LogState, Fun) when erlang:is_function(Fun) -> - log(LogState, ?RLX_DEBUG, fun() -> colorize(?CYAN, false, Fun()) end); + log(LogState, ?RLX_DEBUG, fun() -> colorize(LogState, ?CYAN, false, Fun()) end); debug(LogState, String) -> debug(LogState, "~s~n", [String]). @@ -102,14 +110,14 @@ debug(LogState, String) -> %% and argements @see io:format/2 -spec debug(t(), string(), [any()]) -> ok. debug(LogState, FormatString, Args) -> - log(LogState, ?RLX_DEBUG, colorize(?CYAN, false, FormatString), Args). + log(LogState, ?RLX_DEBUG, colorize(LogState, ?CYAN, false, FormatString), Args). %% @doc log at the info level given the current log state with a string or %% function that returns a string -spec info(t(), string() | log_fun()) -> ok. info(LogState, Fun) when erlang:is_function(Fun) -> - log(LogState, ?RLX_INFO, fun() -> colorize(?GREEN, false, Fun()) end); + log(LogState, ?RLX_INFO, fun() -> colorize(LogState, ?GREEN, false, Fun()) end); info(LogState, String) -> info(LogState, "~s~n", [String]). @@ -117,14 +125,14 @@ info(LogState, String) -> %% and argements @see io:format/2 -spec info(t(), string(), [any()]) -> ok. info(LogState, FormatString, Args) -> - log(LogState, ?RLX_INFO, colorize(?GREEN, false, FormatString), Args). + log(LogState, ?RLX_INFO, colorize(LogState, ?GREEN, false, FormatString), Args). %% @doc log at the error level given the current log state with a string or %% format string that returns a function -spec error(t(), string() | log_fun()) -> ok. error(LogState, Fun) when erlang:is_function(Fun) -> - log(LogState, ?RLX_ERROR, fun() -> colorize(?RED, false, Fun()) end); + log(LogState, ?RLX_ERROR, fun() -> colorize(LogState, ?RED, false, Fun()) end); error(LogState, String) -> error(LogState, "~s~n", [String]). @@ -132,11 +140,11 @@ error(LogState, String) -> %% and argements @see io:format/2 -spec error(t(), string(), [any()]) -> ok. error(LogState, FormatString, Args) -> - log(LogState, ?RLX_ERROR, colorize(?GREEN, false, FormatString), Args). + log(LogState, ?RLX_ERROR, colorize(LogState, ?GREEN, false, FormatString), Args). %% @doc Execute the fun passed in if log level is as expected. -spec log(t(), int_log_level(), log_fun()) -> ok. -log({?MODULE, DetailLogLevel}, LogLevel, Fun) +log(#state_t{mod=?MODULE, log_level=DetailLogLevel}, LogLevel, Fun) when DetailLogLevel >= LogLevel -> io:format("~s~n", [Fun()]); log(_, _, _) -> @@ -145,7 +153,7 @@ log(_, _, _) -> %% @doc when the module log level is less then or equal to the log level for the %% call then write the log info out. When its not then ignore the call. -spec log(t(), int_log_level(), string(), [any()]) -> ok. -log({?MODULE, DetailLogLevel}, LogLevel, FormatString, Args) +log(#state_t{mod=?MODULE, log_level=DetailLogLevel}, LogLevel, FormatString, Args) when DetailLogLevel >= LogLevel, erlang:is_list(Args) -> io:format(FormatString, Args); @@ -155,7 +163,7 @@ log(_, _, _, _) -> %% @doc return a boolean indicating if the system should log for the specified %% levelg -spec should(t(), int_log_level() | any()) -> boolean(). -should({?MODULE, DetailLogLevel}, LogLevel) +should(#state_t{mod=?MODULE, log_level=DetailLogLevel}, LogLevel) when DetailLogLevel >= LogLevel -> true; should(_, _) -> @@ -163,16 +171,16 @@ should(_, _) -> %% @doc get the current log level as an integer -spec log_level(t()) -> int_log_level(). -log_level({?MODULE, DetailLogLevel}) -> +log_level(#state_t{mod=?MODULE, log_level=DetailLogLevel}) -> DetailLogLevel. %% @doc get the current log level as an atom -spec atom_log_level(t()) -> atom_log_level(). -atom_log_level({?MODULE, ?RLX_ERROR}) -> +atom_log_level(#state_t{mod=?MODULE, log_level=?RLX_ERROR}) -> error; -atom_log_level({?MODULE, ?RLX_INFO}) -> +atom_log_level(#state_t{mod=?MODULE, log_level=?RLX_INFO}) -> info; -atom_log_level({?MODULE, ?RLX_DEBUG}) -> +atom_log_level(#state_t{mod=?MODULE, log_level=?RLX_DEBUG}) -> debug. -spec format(t()) -> iolist(). @@ -182,11 +190,11 @@ format(Log) -> erlang:atom_to_list(atom_log_level(Log)), <<")">>]. --spec colorize(color(), boolean(), string()) -> string(). -colorize(Color, false, Msg) when is_integer(Color) -> +-spec colorize(t(), color(), boolean(), string()) -> string(). +colorize(#state_t{caller=command_line}, Color, false, Msg) when is_integer(Color) -> colorize_(Color, 0, Msg); -colorize(Color, true, Msg) when is_integer(Color) -> - colorize_(Color, 1, Msg). +colorize(_LogState, _Color, _Bold, Msg) -> + Msg. -spec colorize_(color(), integer(), string()) -> string(). colorize_(Color, Bold, Msg) when is_integer(Color), is_integer(Bold)-> diff --git a/src/rlx_rel_discovery.erl b/src/rlx_rel_discovery.erl index 6f23ad0..1616f52 100644 --- a/src/rlx_rel_discovery.erl +++ b/src/rlx_rel_discovery.erl @@ -35,7 +35,7 @@ %% @doc recursively dig down into the library directories specified in the state %% looking for OTP Applications --spec do(rlx_state:t(), [filename:name()], [rlx_app_info:t()]) -> +-spec do(rlx_state:t(), [file:name()], [rlx_app_info:t()]) -> {ok, [rlx_release:t()]} | relx:error(). do(State, LibDirs, AppMeta) -> rlx_log:info(rlx_state:log(State), diff --git a/src/rlx_state.erl b/src/rlx_state.erl index 81f6bef..6d3c4ee 100644 --- a/src/rlx_state.erl +++ b/src/rlx_state.erl @@ -66,13 +66,14 @@ -export_type([t/0, - releases/0, - cmd_args/0]). + releases/0, + cmd_args/0, + action/0]). -record(state_t, {log :: rlx_log:t(), root_dir :: file:name(), caller :: caller(), - actions=[] :: [atom()], + actions=[] :: [action()], output_dir :: file:name(), lib_dirs=[] :: [file:name()], config_file=[] :: file:filename() | undefined, @@ -99,6 +100,7 @@ rlx_release:t()). -type cmd_args() :: proplists:proplist(). -type caller() :: command_line | api. +-type action() :: release | relup | tar. -opaque t() :: record(state_t). @@ -113,13 +115,14 @@ new(PropList, Targets) when erlang:is_list(PropList), erlang:is_list(Targets) -> {ok, Root} = file:get_cwd(), + Caller = proplists:get_value(caller, PropList, api), State0 = - #state_t{log = proplists:get_value(log, PropList, rlx_log:new(error)), + #state_t{log = proplists:get_value(log, PropList, rlx_log:new(error, Caller)), output_dir=proplists:get_value(output_dir, PropList, ""), lib_dirs=[to_binary(Dir) || Dir <- proplists:get_value(lib_dirs, PropList, [])], config_file=proplists:get_value(config, PropList, undefined), actions = Targets, - caller = proplists:get_value(caller, PropList, api), + caller = Caller, goals=proplists:get_value(goals, PropList, []), providers = [], configured_releases=ec_dictionary:new(ec_dict), @@ -135,7 +138,7 @@ new(PropList, Targets) proplists:get_value(disable_default_libs, PropList, false)). %% @doc the actions targeted for this system --spec actions(t()) -> atom(). +-spec actions(t()) -> [action()]. actions(#state_t{actions=Actions}) -> Actions. -- cgit v1.2.3 From 26d1d19cc204d3ba63037b703f1b040a960d9725 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Sat, 14 Sep 2013 23:02:43 -0500 Subject: rename examples to relx from relcool --- examples/relcool.config | 81 ------------------------------------------ examples/relcool_simple.config | 19 ---------- examples/relx.config | 81 ++++++++++++++++++++++++++++++++++++++++++ examples/relx_simple.config | 19 ++++++++++ 4 files changed, 100 insertions(+), 100 deletions(-) delete mode 100644 examples/relcool.config delete mode 100644 examples/relcool_simple.config create mode 100644 examples/relx.config create mode 100644 examples/relx_simple.config diff --git a/examples/relcool.config b/examples/relcool.config deleted file mode 100644 index 77d7acf..0000000 --- a/examples/relcool.config +++ /dev/null @@ -1,81 +0,0 @@ -%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- -%% Example Relcool Config -%% ====================== -%% -%% This is an example relcool config whose purpose is to demonstrate all of the -%% options available in relcool. Its not expected that you will use all of the -%% things here. In fact, there is a high likely hood that *your* relcool.config -%% will be extremely minimal, as relcool does a very good job of figuring out -%% things on its own. -%% -%% The Release We Are Building -%% --------------------------- -%% -%% Lets say we have a release called sexpr. The sexpr release supports versions -%% 0.0.1 and 0.0.2 with different dependencies. 0.0.1 requires erlware commons -%% 0.8.0 or lesser. 0.0.2 requires erlware_commons 0.8.1 or greater along with -%% neotoma (any version). We also do not want neotoma to be loaded. We also want -%% our default release. the one we build in the common case to be sexper 0.0.2. - -%% You can tell relcool about additional directories that you want searched for -%% otp apps during the discovery process. You do that in the 'paths' config. You -%% can also specify these paths on the command line with `-p`. Be aware that -%% relcool plays well with rebar so if you have a deps directory in the current -%% directory it will be automatically added. -{paths, ["/opt/erlang_apps"]}. - -%% If needed you can use a specific vm.args file instead of the -%% one automatically generated by relx. -{vm_args, "./config/vm.args"}. - -%% If you have a sys.config file you need to tell relcool where it is. If you do -%% that relcool will include the sys.config in the appropriate place -%% automatically. -{sys_config, "./config/sys.config"}. - -%% relcool will include erts by default. However, if you don't want to include -%% erts you can add the `include_erts` tuple to the config and tell relcool not -%% to include it. -{include_erts, false}. - -%% The default start script relcool creates is basic. For a more complete start -%% script add the extended_start_script option. -{extended_start_script, true}. - -%% When we have multiple releases relcool needs to know which one to build. You -%% can specify that on the command line with the `-n` and `-v` arguments to -%% relcool. However, it is often more convenient to do it in the config. -{default_release, sexpr, "0.0.2"}. - -{release, {sexpr, "0.0.1"}, - [sexpr, - %% There are two syntaxes for constraints. - %% The first is the tuple syntax shown here. - {erlware_commons, "0.8.0", '<='}]}. - -{release, {sexpr, "0.0.2"}, - [sexpr, - - %% This is the second constraint syntax, it is interchangeable with the tuple - %% syntax and its up to you which you find more readable/usable. - "erlware_commons>=0.8.1", - - %% You can put the release load types in the release spec here in exactly the - %% same way that you can do it for a normal relfile. The syntax is - %% {, }. - {neotoma, load}]}. - -%% During development its often the case that you want to substitute the app -%% that you are working on for a 'production' version of an app. You can -%% explicitly tell relcool to override all versions of an app that you specify -%% with an app in an arbitrary directory. Relcool will then symlink that app -%% into the release in place of the specified app. be aware though that relcool -%% will check your app for consistancy so it should be a normal OTP app and -%% already be built. -{overrides, [{sexpr, "../sexpr"}]}. - - -%% In some cases you might want to add additional functionality to relcool. You -%% can do this via a 'provider'. A provider is an implementation of the relcool -%% provider behaviour. This probably shouldn't be needed very often. -{add_providers, [my_custom_functionality]}. diff --git a/examples/relcool_simple.config b/examples/relcool_simple.config deleted file mode 100644 index 88e9e8d..0000000 --- a/examples/relcool_simple.config +++ /dev/null @@ -1,19 +0,0 @@ -%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- -%% Example Relcool Simple Config -%% ============================= -%% -%% This is an example relcool config whose purpose demonstrate the minimal -%% config needed for relcool. For a more complete example see the relcool.config -%% in the examples directory. -%% -%% The Release We Are Building -%% --------------------------- -%% -%% Lets say we have a release called sexpr. The sexpr release has version 0.0.2 -%% 0.0.2 requires erlware_commons 0.8.1 or greater along with neotoma -%% (any version). - -{release, {sexpr, "0.0.2"}, - [sexpr, - {erlware_commons, 0.8.1, '>='}, - neotoma]}. diff --git a/examples/relx.config b/examples/relx.config new file mode 100644 index 0000000..77d7acf --- /dev/null +++ b/examples/relx.config @@ -0,0 +1,81 @@ +%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- +%% Example Relcool Config +%% ====================== +%% +%% This is an example relcool config whose purpose is to demonstrate all of the +%% options available in relcool. Its not expected that you will use all of the +%% things here. In fact, there is a high likely hood that *your* relcool.config +%% will be extremely minimal, as relcool does a very good job of figuring out +%% things on its own. +%% +%% The Release We Are Building +%% --------------------------- +%% +%% Lets say we have a release called sexpr. The sexpr release supports versions +%% 0.0.1 and 0.0.2 with different dependencies. 0.0.1 requires erlware commons +%% 0.8.0 or lesser. 0.0.2 requires erlware_commons 0.8.1 or greater along with +%% neotoma (any version). We also do not want neotoma to be loaded. We also want +%% our default release. the one we build in the common case to be sexper 0.0.2. + +%% You can tell relcool about additional directories that you want searched for +%% otp apps during the discovery process. You do that in the 'paths' config. You +%% can also specify these paths on the command line with `-p`. Be aware that +%% relcool plays well with rebar so if you have a deps directory in the current +%% directory it will be automatically added. +{paths, ["/opt/erlang_apps"]}. + +%% If needed you can use a specific vm.args file instead of the +%% one automatically generated by relx. +{vm_args, "./config/vm.args"}. + +%% If you have a sys.config file you need to tell relcool where it is. If you do +%% that relcool will include the sys.config in the appropriate place +%% automatically. +{sys_config, "./config/sys.config"}. + +%% relcool will include erts by default. However, if you don't want to include +%% erts you can add the `include_erts` tuple to the config and tell relcool not +%% to include it. +{include_erts, false}. + +%% The default start script relcool creates is basic. For a more complete start +%% script add the extended_start_script option. +{extended_start_script, true}. + +%% When we have multiple releases relcool needs to know which one to build. You +%% can specify that on the command line with the `-n` and `-v` arguments to +%% relcool. However, it is often more convenient to do it in the config. +{default_release, sexpr, "0.0.2"}. + +{release, {sexpr, "0.0.1"}, + [sexpr, + %% There are two syntaxes for constraints. + %% The first is the tuple syntax shown here. + {erlware_commons, "0.8.0", '<='}]}. + +{release, {sexpr, "0.0.2"}, + [sexpr, + + %% This is the second constraint syntax, it is interchangeable with the tuple + %% syntax and its up to you which you find more readable/usable. + "erlware_commons>=0.8.1", + + %% You can put the release load types in the release spec here in exactly the + %% same way that you can do it for a normal relfile. The syntax is + %% {, }. + {neotoma, load}]}. + +%% During development its often the case that you want to substitute the app +%% that you are working on for a 'production' version of an app. You can +%% explicitly tell relcool to override all versions of an app that you specify +%% with an app in an arbitrary directory. Relcool will then symlink that app +%% into the release in place of the specified app. be aware though that relcool +%% will check your app for consistancy so it should be a normal OTP app and +%% already be built. +{overrides, [{sexpr, "../sexpr"}]}. + + +%% In some cases you might want to add additional functionality to relcool. You +%% can do this via a 'provider'. A provider is an implementation of the relcool +%% provider behaviour. This probably shouldn't be needed very often. +{add_providers, [my_custom_functionality]}. diff --git a/examples/relx_simple.config b/examples/relx_simple.config new file mode 100644 index 0000000..88e9e8d --- /dev/null +++ b/examples/relx_simple.config @@ -0,0 +1,19 @@ +%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- +%% Example Relcool Simple Config +%% ============================= +%% +%% This is an example relcool config whose purpose demonstrate the minimal +%% config needed for relcool. For a more complete example see the relcool.config +%% in the examples directory. +%% +%% The Release We Are Building +%% --------------------------- +%% +%% Lets say we have a release called sexpr. The sexpr release has version 0.0.2 +%% 0.0.2 requires erlware_commons 0.8.1 or greater along with neotoma +%% (any version). + +{release, {sexpr, "0.0.2"}, + [sexpr, + {erlware_commons, 0.8.1, '>='}, + neotoma]}. -- cgit v1.2.3