diff options
Diffstat (limited to 'lib/reltool/bin/reltool.escript')
-rw-r--r-- | lib/reltool/bin/reltool.escript | 249 |
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), []}. |