forked from erlware-deprecated/sinan
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add new script runner borrowed from rebar
- Loading branch information
1 parent
3198e8c
commit 53fe047
Showing
1 changed file
with
86 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- | ||
%%%--------------------------------------------------------------------------- | ||
%%% @author Dave Smith | ||
%%% @author Eric Merritt | ||
%%% @doc | ||
%%% Run sh command with reasonable return values. This was originally taken | ||
%%% from rebar and but has been much changed since then. | ||
%%% @end | ||
%%%--------------------------------------------------------------------------- | ||
-module(sin_sh). | ||
|
||
%% API | ||
-export([sh/3]). | ||
|
||
%%==================================================================== | ||
%% API | ||
%%==================================================================== | ||
%% | ||
%% Env = [{string(), Val}] | ||
%% Val = string() | false | ||
%% | ||
sh(Config, Command0, Options0) -> | ||
Options = [expand_sh_flag(V) | ||
|| V <- proplists:compact(Options0)], | ||
|
||
Command = patch_on_windows(Command0, proplists:get_value(env, Options, [])), | ||
PortSettings = proplists:get_all_values(port_settings, Options) ++ | ||
[exit_status, {line, 16384}, use_stdio, stderr_to_stdout, hide], | ||
Port = open_port({spawn, Command}, PortSettings), | ||
sh_loop(Port, | ||
fun(Output, Acc) -> | ||
sin_log:normal(Config, Output), | ||
[Output | Acc] | ||
end, []). | ||
|
||
%%==================================================================== | ||
%% Internal Functions | ||
%%==================================================================== | ||
sh_loop(Port, Fun, Acc) -> | ||
receive | ||
{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, lists:flatten(lists:reverse(Acc))}; | ||
{Port, {exit_status, Rc}} -> | ||
{error, {Rc, lists:flatten(lists:reverse(Acc))}} | ||
end. | ||
|
||
%% We do the shell variable substitution ourselves on Windows and hope that the | ||
%% command doesn't use any other shell magic. | ||
patch_on_windows(Cmd, Env) -> | ||
case os:type() of | ||
{win32,nt} -> | ||
"cmd /q /c " | ||
++ lists:foldl(fun({Key, Value}, Acc) -> | ||
expand_env_variable(Acc, Key, Value) | ||
end, Cmd, Env); | ||
_ -> | ||
Cmd | ||
end. | ||
|
||
%% | ||
%% Given env. variable FOO we want to expand all references to | ||
%% it in InStr. References can have two forms: $FOO and ${FOO} | ||
%% The end of form $FOO is delimited with whitespace or eol | ||
%% | ||
expand_env_variable(InStr, VarName, RawVarValue) -> | ||
case string:chr(InStr, $$) of | ||
0 -> | ||
%% No variables to expand | ||
InStr; | ||
_ -> | ||
VarValue = re:replace(RawVarValue, "\\\\", "\\\\\\\\", [global]), | ||
%% Use a regex to match/replace: | ||
%% Given variable "FOO": match $FOO\s | $FOOeol | ${FOO} | ||
RegEx = io_lib:format("\\\$(~s(\\s|$)|{~s})", [VarName, VarName]), | ||
ReOpts = [global, {return, list}], | ||
re:replace(InStr, RegEx, [VarValue, "\\2"], ReOpts) | ||
end. | ||
|
||
expand_sh_flag({cd, _CdArg} = Cd) -> | ||
{port_settings, Cd}; | ||
expand_sh_flag({env, _EnvArg} = Env) -> | ||
{port_settings, Env}. |