summaryrefslogtreecommitdiff
path: root/src/rebar_utils.erl
diff options
context:
space:
mode:
authorJuhani Rankimies <juhani@juranki.com>2010-12-05 02:07:12 +0200
committerTuncer Ayaz <tuncer.ayaz@gmail.com>2011-01-06 15:02:19 +0100
commit52ca7795feb001f0624ec87e717e3019f8a810bd (patch)
treee66560012ae9789dfaa9d1822d19deff4676f679 /src/rebar_utils.erl
parentf7eb0a71589ec4ebee1315fe2f430d8af607aa36 (diff)
Unify executable invocation
Add flags to rebar_utils:sh to control output and error handling. Replace calls to os:cmd with calls to rebar_utils:sh.
Diffstat (limited to 'src/rebar_utils.erl')
-rw-r--r--src/rebar_utils.erl106
1 files changed, 75 insertions, 31 deletions
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index 98fdbd7..ae27455 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -30,8 +30,7 @@
is_arch/1,
get_arch/0,
get_os/0,
- sh/2, sh/3,
- sh_failfast/2,
+ sh/2,
find_files/2,
now_str/0,
ensure_dir/1,
@@ -73,36 +72,49 @@ get_os() ->
ArchAtom
end.
+%%
+%% Options = [Option] -- defaults to [use_stdout, abort_on_error]
+%% Option = ErrorOption | OutputOption | {cd, string()} | {env, Env}
+%% ErrorOption = return_on_error | abort_on_error | {abort_on_error, string()}
+%% OutputOption = use_stdout | {use_stdout, bool()}
+%% Env = [{string(), Val}]
+%% Val = string() | false
+%%
+sh(Command0, Options0) ->
+ ?INFO("sh: ~s\n~p\n", [Command0, Options0]),
-sh(Command, Env) ->
- sh(Command, Env, get_cwd()).
+ DefaultOptions = [use_stdout, abort_on_error],
+ Options = lists:map(fun expand_sh_flag/1,
+ proplists:compact(Options0 ++ DefaultOptions)),
-sh(Command0, Env, Dir) ->
- ?INFO("sh: ~s\n~p\n", [Command0, Env]),
- Command = patch_on_windows(Command0, os:type()),
- Port = open_port({spawn, Command}, [{cd, Dir}, {env, Env}, exit_status, {line, 16384},
- use_stdio, stderr_to_stdout]),
- case sh_loop(Port) of
- ok ->
- ok;
+ ErrorHandler = proplists:get_value(error_handler, Options),
+ OutputHandler = proplists:get_value(output_handler, Options),
+
+ Command = patch_on_windows(Command0),
+ PortSettings = proplists:get_all_values(port_settings, Options) ++
+ [exit_status, {line, 16384}, use_stdio, stderr_to_stdout, hide],
+ Port = open_port({spawn, Command}, PortSettings),
+
+ case sh_loop(Port, OutputHandler, []) of
+ {ok, Output} ->
+ {ok, Output};
{error, Rc} ->
- ?ABORT("~s failed with error: ~w\n", [Command, Rc])
+ ErrorHandler(Command, Rc)
end.
-
%% We need a bash shell to execute on windows
%% also the port doesn't seem to close from time to time (mingw)
-patch_on_windows(Cmd, {win32,nt}) ->
- case find_executable("bash") of
- false -> Cmd;
- Bash ->
- Bash ++ " -c \"" ++ Cmd ++ "; echo _port_cmd_status_ $?\" "
- end;
-patch_on_windows(Command, _) ->
- Command.
-
-sh_failfast(Command, Env) ->
- sh(Command, Env).
+patch_on_windows(Cmd) ->
+ case os:type() of
+ {win32,nt} ->
+ case find_executable("bash") of
+ false -> Cmd;
+ Bash ->
+ Bash ++ " -c \"" ++ Cmd ++ "; echo _port_cmd_status_ $?\" "
+ end;
+ _ ->
+ Cmd
+ end.
find_files(Dir, Regex) ->
filelib:fold_files(Dir, Regex, true, fun(F, Acc) -> [F | Acc] end, []).
@@ -162,19 +174,51 @@ match_first([{Regex, MatchValue} | Rest], Val) ->
match_first(Rest, Val)
end.
-sh_loop(Port) ->
+expand_sh_flag(return_on_error) ->
+ {error_handler,
+ fun(_Command, Rc) ->
+ {error, Rc}
+ end};
+expand_sh_flag({abort_on_error, Message}) ->
+ {error_handler,
+ fun(_Command, _Rc) ->
+ ?ABORT(Message, [])
+ end};
+expand_sh_flag(abort_on_error) ->
+ {error_handler,
+ fun(Command, Rc) ->
+ ?ABORT("~s failed with error: ~w\n", [Command, Rc])
+ end};
+expand_sh_flag(use_stdout) ->
+ {output_handler,
+ fun(Line, Acc) ->
+ ?CONSOLE("~s", [Line]),
+ [Acc | Line]
+ end};
+expand_sh_flag({use_stdout, false}) ->
+ {output_handler,
+ fun(Line, Acc) ->
+ [Acc | Line]
+ end};
+expand_sh_flag({cd, Dir}) ->
+ {port_settings, {cd, Dir}};
+expand_sh_flag({env, Env}) ->
+ {port_settings, {env, Env}}.
+
+sh_loop(Port, Fun, Acc) ->
receive
{Port, {data, {_, "_port_cmd_status_ " ++ Status}}} ->
(catch erlang:port_close(Port)), % sigh () for indentation
case list_to_integer(Status) of
- 0 -> ok;
+ 0 -> {ok, lists:flatten(Acc)};
Rc -> {error, Rc}
end;
- {Port, {data, {_, Line}}} ->
- ?CONSOLE("~s\n", [Line]),
- sh_loop(Port);
+ {Port, {data, {eol, Line}}} ->
+ sh_loop(Port, Fun, Fun(Line ++ "\n", Acc));
+ {Port, {data, {noeol, Line}}} ->
+ sh_loop(Port, Fun, Fun(Line, Acc));
{Port, {exit_status, 0}} ->
- ok;
+ {ok, lists:flatten(Acc)};
{Port, {exit_status, Rc}} ->
{error, Rc}
end.