aboutsummaryrefslogtreecommitdiffstats
path: root/lib/reltool/bin
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2010-04-28 04:53:39 +0000
committerErlang/OTP <[email protected]>2010-04-28 04:53:39 +0000
commit39e5ca57147c08502806f873c107c77e197a78ab (patch)
tree91e8cad7d4b2e340c1dd8389b693be20fbb50f87 /lib/reltool/bin
parent9658ff5a3b14bf3189986682023c614077d32143 (diff)
parente57e7f332fcf9ea26a7f7536b18a24181b680463 (diff)
downloadotp-39e5ca57147c08502806f873c107c77e197a78ab.tar.gz
otp-39e5ca57147c08502806f873c107c77e197a78ab.tar.bz2
otp-39e5ca57147c08502806f873c107c77e197a78ab.zip
Merge branch 'hawk/reltool' into dev
* hawk/reltool: Make some cleanups Ensure that {error, Reason} is returned even when server dies Introduced a new embedded_app_type option Removed spurious CDATA in documentation Automatically include applications that must be started Add app test SUITE Add app and appup files to reltool Add function to return status about the configuration Improved handling of applications explicitly included releases Created escript for simplified usage from makefiles OTP-8590 hawk/reltool
Diffstat (limited to 'lib/reltool/bin')
-rw-r--r--lib/reltool/bin/reltool.escript249
1 files changed, 249 insertions, 0 deletions
diff --git a/lib/reltool/bin/reltool.escript b/lib/reltool/bin/reltool.escript
new file mode 100644
index 0000000000..0dcd5ad1e9
--- /dev/null
+++ b/lib/reltool/bin/reltool.escript
@@ -0,0 +1,249 @@
+#!/usr/bin/env escript
+%% -*- erlang -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+
+-include_lib("reltool/src/reltool.hrl").
+
+main(Args) ->
+ process_flag(trap_exit, true),
+ try
+ Tokens = scan_args(Args, [], []),
+ {Options, Actions} = parse_args(Tokens, []),
+ case invoke(Options, Actions) of
+ ok ->
+ safe_stop(0);
+ {error, ReasonString} ->
+ fatal_error(ReasonString, 2)
+ end
+ catch
+ throw:usage ->
+ usage(),
+ safe_stop(1);
+ exit:Reason ->
+ String = lists:flatten(io_lib:format("EXIT: ~p", [Reason])),
+ fatal_error(String, 3)
+ end.
+
+usage() ->
+ Usage =
+ [
+ "[Config] [--window]",
+ "[Config] --create_config [-defaults] [-derived] [ConfigFile]",
+ "[Config] --create_rel RelName [RelFile]",
+ "[Config] --create_script RelName [ScriptFile]",
+ "[Config] --create_target TargetDir",
+ "[Config] --create_target_spec [SpecFile]",
+ "[Config] --eval_target_spec Spec TargetDir RootDir"
+ ],
+ Script = script_name(),
+ String = lists:flatten([[Script, " ", U, "\n"] || U <- Usage]),
+ io:format("Erlang/OTP release management tool\n\n"
+ "~s\nConfig = ConfigFile | '{sys, [sys()]}'\n"
+ "Spec = SpecFile | '{spec, [target_spec()}']\n\n"
+ "See User's guide and Reference manual for more info.\n",
+ [String]).
+
+safe_stop(Code) ->
+ init:stop(Code),
+ timer:sleep(infinity).
+
+invoke(Options, Actions) ->
+ case Actions of
+ [] ->
+ invoke(Options, [["--window"]]);
+ [["--window"]] ->
+ start_window(Options);
+ [["--create_config" | OptArgs]] ->
+ DefArg = "-defaults",
+ DerivArg = "-derived",
+ InclDef = lists:member(DefArg, OptArgs),
+ InclDeriv = lists:member(DerivArg, OptArgs),
+ case reltool:get_config(Options, InclDef, InclDeriv) of
+ {ok, Config} ->
+ String = pretty("config", Config),
+ case OptArgs -- [DefArg, DerivArg] of
+ [] ->
+ format("~s", [String]);
+ [ConfigFile] ->
+ write_file(ConfigFile, String);
+ _ ->
+ throw(usage)
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ [["--create_rel", RelName | OptArgs]] ->
+ case reltool:get_rel(Options, RelName) of
+ {ok, Rel} ->
+ String = pretty("rel", Rel),
+ case OptArgs of
+ [] ->
+ format("~s", [String]);
+ [RelFile] ->
+ write_file(RelFile, String);
+ _ ->
+ throw(usage)
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ [["--create_script", RelName | OptArgs]] ->
+ case reltool:get_script(Options, RelName) of
+ {ok, Script} ->
+ String = pretty("script", Script),
+ case OptArgs of
+ [] ->
+ format("~s", [String]);
+ [ScriptFile] ->
+ write_file(ScriptFile, String);
+ _ ->
+ throw(usage)
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ [["--create_target", TargetDir]] ->
+ reltool:create_target(Options, TargetDir);
+ [["--create_target_spec" | OptArgs]] ->
+ case reltool:get_target_spec(Options) of
+ {ok, Script} ->
+ String = pretty("target_spec", Script),
+ case OptArgs of
+ [] ->
+ format("~s", [String]);
+ [SpecFile] ->
+ write_file(SpecFile, String);
+ _ ->
+ throw(usage)
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ [["--eval_target_spec", TargetSpec, TargetDir, RootDir]] ->
+ try
+ {ok, Tokens, _} = erl_scan:string(TargetSpec ++ ". "),
+ {ok, {spec, Spec}} = erl_parse:parse_term(Tokens),
+ reltool:eval_target_spec(Spec, TargetDir, RootDir)
+ catch
+ error:{badmatch, _} ->
+ case file:consult(TargetSpec) of
+ {ok, Spec2} ->
+ reltool:eval_target_spec(Spec2, TargetDir, RootDir);
+ {error, Reason} ->
+ Text = file:format_error(Reason),
+ {error, TargetSpec ++ ": " ++ Text}
+ end
+ end;
+ _ ->
+ throw(usage)
+ end.
+
+start_window(Options) ->
+ case reltool:start_link(Options) of
+ {ok, WinPid} ->
+ receive
+ {'EXIT', WinPid, shutdown} ->
+ ok;
+ {'EXIT', WinPid, normal} ->
+ ok;
+ {'EXIT', WinPid, Reason} ->
+ exit(Reason)
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Helpers
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+script_name() ->
+ filename:basename(escript:script_name(), ".escript").
+
+fatal_error(String, Code) ->
+ io:format(standard_error, "~s: ~s\n", [script_name(), String]),
+ safe_stop(Code).
+
+write_file(File, IoList) ->
+ case file:write_file(File, IoList) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ {error, file:format_error(Reason)}
+ end.
+
+format(Format, Args) ->
+ io:format(Format, Args),
+ %% Wait a while for the I/O to be processed
+ timer:sleep(timer:seconds(1)).
+
+pretty(Tag, Term) ->
+ lists:flatten(io_lib:format("%% ~s generated at ~w ~w\n~p.\n\n",
+ [Tag, date(), time(), Term])).
+
+scan_args([H | T], Single, Multi) ->
+ case H of
+ "--" ++ _ when Single =:= [] ->
+ scan_args(T, [H], Multi);
+ "--" ++ _ ->
+ scan_args(T, [H], [lists:reverse(Single) | Multi]);
+ _ ->
+ scan_args(T, [H | Single], Multi)
+ end;
+scan_args([], [], Multi) ->
+ lists:reverse(Multi);
+scan_args([], Single, Multi) ->
+ lists:reverse([lists:reverse(Single) | Multi]).
+
+parse_args([H | T] = Args, Options) ->
+ case H of
+ ["--wx_debug" | Levels] ->
+ Dbg =
+ fun(L) ->
+ case catch list_to_integer(L) of
+ {'EXIT', _} ->
+ case catch list_to_atom(L) of
+ {'EXIT', _} ->
+ exit("Illegal wx debug level: " ++ L);
+ Atom ->
+ Atom
+ end;
+ Int ->
+ Int
+ end
+ end,
+ Levels2 = lists:map(Dbg, Levels),
+ parse_args(T, [{wx_debug, Levels2} | Options]);
+ ["--" ++ _ | _] ->
+ %% No more options
+ {lists:reverse(Options), Args};
+ [Config] ->
+ try
+ {ok, Tokens, _} = erl_scan:string(Config ++ ". "),
+ {ok, {sys, _} = Sys} = erl_parse:parse_term(Tokens),
+ parse_args(T, [{config, Sys} | Options])
+ catch
+ error:{badmatch, _} ->
+ parse_args(T, [{config, Config} | Options]);
+ X:Y ->
+ io:format("\n\n~p\n\n", [{X, Y}])
+ end
+ end;
+parse_args([], Options) ->
+ {lists:reverse(Options), []}.