Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

shell task

  • Loading branch information...
commit 6fc9f34e7e0ae0cb2b0533bfb7aa0868d5c511cf 1 parent 3053987
Felix Lange authored
View
1  Emakefile
@@ -1 +1,2 @@
+{'src/tetrapak_task', [{outdir, "ebin"}, {i, "include"}]}.
{'src/*', [{outdir, "ebin"}, {i, "include"}]}.
View
48 bin/tetrapak
@@ -1,47 +1,5 @@
-#!/usr/bin/env escript
-%% vim: filetype=erlang
-%%! -smp auto
+#!/bin/sh
-main([]) ->
- ensure_code_path(),
- usage(),
- halt(1);
-main([[$- | _] | _ ]) ->
- ensure_code_path(),
- io:format(standard_error, "Error: options should be specified after <command>~n", []),
- usage(),
- halt(1);
-main(Commands) ->
- ensure_code_path(),
- {ok, Cwd} = file:get_cwd(),
- case tetrapak:run(Cwd, Commands) of
- {unknown, Key} ->
- io:format(standard_error, "Error: no such command: ~s~n", [Key]),
- halt(1);
- error ->
- halt(2);
- ok ->
- halt(0)
- end.
+HERE=`dirname $0`
-usage() ->
- io:format(standard_error,
- "Usage: tetrapak <command> [ options ]~n~n"
- "Available Tasks~n~s",
- [tablist(tetrapak:all_commands())]).
-
-tablist(Lis) ->
- MaxWidth = lists:foldl(fun ({K, _}, Max) -> erlang:max(iolist_size(K), Max) end, 0, Lis),
- lists:foldr(fun ({Name, Desc}, Acc) ->
- Space = lists:duplicate(MaxWidth - iolist_size(Name), $ ),
- [" " ++ Name ++ " " ++ Space ++ "- " ++ Desc ++ "\n" | Acc]
- end, [], Lis).
-
-ensure_code_path() ->
- RealPath = case file:read_link(?FILE) of
- {ok, R} -> R;
- {error, einval} -> ?FILE;
- {error, enotsup} -> ?FILE
- end,
- Root = filename:absname(filename:dirname(filename:dirname(RealPath))),
- code:add_patha(filename:join(Root, "ebin")).
+exec erl -pa "$HERE/../ebin" -noinput -noshell -user tetrapak_io -smp auto -run tetrapak_cli boot -- $@
View
9 ebin/tetrapak.app
@@ -5,17 +5,20 @@
{modules, [tetrapak,
tetrapak_context,
tetrapak_task,
+ tetrapak_cli,
+ tetrapak_io,
tpk_util,
tpk_file,
tpk_log,
- %% passes
+ %% tasks
tetrapak_task_config,
tetrapak_task_erlc,
tetrapak_task_check,
tetrapak_task_pkg_deb,
- tetrapak_task_doc
+ tetrapak_task_doc,
+ tetrapak_task_shell
]},
{applications, [kernel, stdlib, compiler, edoc, tools]},
- {registered, []}
+ {registered, [tetrapak_io]}
]}.
View
46 src/tetrapak_cli.erl
@@ -0,0 +1,46 @@
+% __ __ _
+% / /__________ __ _____ / /___ (_)___ ____ _
+% / __/ ___/ __ `/ | / / _ \/ / __ \/ / __ \/ __ `/
+% / /_/ / / /_/ /| |/ / __/ / /_/ / / / / / /_/ /
+% \__/_/ \__,_/ |___/\___/_/ .___/_/_/ /_/\__, /
+% /_/ /____/
+%
+% Copyright (c) Travelping GmbH <info@travelping.com>
+
+-module(tetrapak_cli).
+-export([boot/0, start/1]).
+-export([shell_dummy/0]).
+
+boot() ->
+ start(init:get_plain_arguments()).
+
+start([]) ->
+ usage(),
+ halt(1);
+start(Commands) ->
+ {ok, Cwd} = file:get_cwd(),
+ case tetrapak:run(Cwd, Commands) of
+ {unknown, Key} ->
+ io:format(standard_error, "Error: no such command: ~s~n", [Key]),
+ halt(1);
+ error ->
+ halt(2);
+ ok ->
+ halt(0)
+ end.
+
+usage() ->
+ io:format(standard_error,
+ "Usage: tetrapak <command> [ options ]~n~n"
+ "Available Tasks~n~s",
+ [tablist(tetrapak:all_commands())]).
+
+tablist(Lis) ->
+ MaxWidth = lists:foldl(fun ({K, _}, Max) -> erlang:max(iolist_size(K), Max) end, 0, Lis),
+ lists:foldr(fun ({Name, Desc}, Acc) ->
+ Space = lists:duplicate(MaxWidth - iolist_size(Name), $ ),
+ [" " ++ Name ++ " " ++ Space ++ "- " ++ Desc ++ "\n" | Acc]
+ end, [], Lis).
+
+shell_dummy() ->
+ timer:sleep(infinity).
View
6 src/tetrapak_context.erl
@@ -44,10 +44,10 @@ wait_loop(Ctx, WaitList) ->
{error, {failed, Name}}
end.
-wait_shutdown(Ctx) ->
- MRef = monitor(process, Ctx),
+wait_shutdown(Process) ->
+ MRef = monitor(process, Process),
receive
- {'DOWN', MRef, process, Ctx, _Info} -> ok
+ {'DOWN', MRef, process, Process, _Info} -> ok
end.
%% ------------------------------------------------------------
View
102 src/tetrapak_io.erl
@@ -0,0 +1,102 @@
+% __ __ _
+% / /__________ __ _____ / /___ (_)___ ____ _
+% / __/ ___/ __ `/ | / / _ \/ / __ \/ / __ \/ __ `/
+% / /_/ / / /_/ /| |/ / __/ / /_/ / / / / / /_/ /
+% \__/_/ \__,_/ |___/\___/_/ .___/_/_/ /_/\__, /
+% /_/ /____/
+%
+% Copyright (c) Travelping GmbH <info@travelping.com>
+
+-module(tetrapak_io).
+-export([start/0, can_start_shell/0, start_shell/0, start_shell/1]).
+-export([ioreq_output/1]).
+
+-define(SERVER, tetrapak_io).
+
+start() ->
+ proc_lib:spawn(fun () -> server({fd,1,1}) end).
+
+start_shell() ->
+ start_shell({shell, start, [false]}).
+start_shell(Shell = {_M,_F,_A}) ->
+ whereis(?SERVER) ! {start_shell, Shell},
+ ok.
+
+can_start_shell() ->
+ case whereis(?SERVER) of
+ undefined -> false;
+ P when is_pid(P) -> true
+ end.
+
+server(PortName) ->
+ Group = group:start(self(), {}),
+ register(user, Group),
+ Port = open_port(PortName, [out]),
+ register(?SERVER, self()),
+ server_loop(Port, Group).
+
+server_loop(Port, Group) ->
+ receive
+ {io_request, From, ReplyAs, Request} when is_pid(From) ->
+ {Reply, Chars} = ioreq_output(Request),
+ port_command(Port, Chars),
+ From ! {io_reply, ReplyAs, Reply},
+ server_loop(Port, Group);
+ {Group, get_unicode_state} ->
+ Group ! {self(), get_unicode_state, true},
+ server_loop(Port, Group);
+ {Group, set_unicode_state} ->
+ Group ! {self(), set_unicode_state, true},
+ server_loop(Port, Group);
+ {Group, Req} ->
+ {_Reply, Chars} = ioreq_output(Req),
+ port_command(Port, Chars),
+ server_loop(Port, Group);
+ {start_shell, Shell} ->
+ tpk_log:debug("io: starting shell: ~p", Shell),
+ erlang:unregister(?SERVER),
+ user_drv:server('tty_sl -c -e', Shell);
+ _Other ->
+ tpk_log:debug("io other: ~p", [_Other]),
+ server_loop(Port, Group)
+ end.
+
+ioreq_output({put_chars, Encoding, Chars}) ->
+ {ok, unicode:characters_to_binary(Chars, Encoding)};
+ioreq_output({put_chars, Encoding, M, F, A}) ->
+ case output_function(M, F, A) of
+ {ok, Output} ->
+ {ok, unicode:characters_to_binary(Output, Encoding)};
+ Error ->
+ {Error, []}
+ end;
+ioreq_output({put_chars, Chars}) ->
+ {ok, Chars};
+ioreq_output({put_chars, M, F, A}) ->
+ output_function(M, F, A);
+ioreq_output({requests, Requests}) ->
+ io_requests(Requests, []);
+ioreq_output(_OtherRequest) ->
+ {{error, enotsup}, []}.
+
+output_function(M, F, A) ->
+ try apply(M, F, A) of
+ Output when is_list(Output); is_binary(Output) ->
+ {ok, Output};
+ _ ->
+ {{error, F}, []}
+ catch
+ _:_ ->
+ {{error, F}, []}
+ end.
+
+%% Process a list of output requests as long as the previous status is 'ok'.
+io_requests([R|Rs], Acc) ->
+ case ioreq_output(R) of
+ {ok, Chars} ->
+ io_requests(Rs, [Chars | Acc]);
+ {ErrorReply, _Chars} ->
+ {ErrorReply, lists:reverse(Acc)}
+ end;
+io_requests([], Acc) ->
+ {ok, lists:reverse(Acc)}.
View
33 src/tetrapak_task.erl
@@ -46,11 +46,13 @@ worker(#task{name = TaskName, modules = [TaskModule | _OtherModules]}, Context,
erlang:put(?DIRECTORY, Directory),
case try_check(TaskModule, TaskName) of
{done, Variables} ->
+ tpk_log:debug("worker: check/1 -> done"),
tetrapak_context:task_done(Context, TaskName, Variables),
exit({?TASK_DONE, TaskName});
{needs_run, TaskData} ->
case try_run(TaskModule, TaskName, TaskData) of
{done, Variables} ->
+ tpk_log:debug("worker: run/2 -> done"),
tetrapak_context:task_done(Context, TaskName, Variables),
exit({?TASK_DONE, TaskName})
end
@@ -188,7 +190,7 @@ output_collector_loop(Context, TaskName, TaskProcess, Buffer) ->
output_collector_loop(Context, TaskName, TaskProcess, NewBuffer);
{reply, Context, output_ok} ->
print_output_header(TaskName),
- do_output(console, Buffer),
+ io:put_chars(Buffer),
output_collector_loop(Context, TaskName, TaskProcess, console);
{'EXIT', TaskProcess, _Reason} ->
case Buffer of
@@ -203,37 +205,22 @@ wait_output_ok(Context, TaskName, TaskProcess, Buffer) ->
receive
{reply, Context, output_ok} ->
print_output_header(TaskName),
- do_output(console, Buffer),
+ io:put_chars(Buffer),
tetrapak_context:task_output_done(Context, TaskProcess)
end.
+handle_io(Req, console) ->
+ group_leader() ! Req,
+ console;
handle_io({io_request, From, ReplyAs, Request}, Buffer) ->
- case ioreq_chars([Request], []) of
- {notsup, Chars} ->
- NewBuffer = do_output(Buffer, Chars),
- From ! {io_reply, ReplyAs, {error, request}};
- {ok, Chars} ->
- NewBuffer = do_output(Buffer, Chars),
- From ! {io_reply, ReplyAs, ok}
- end,
+ {Reply, Chars} = tetrapak_io:ioreq_output(Request),
+ NewBuffer = do_output(Buffer, Chars),
+ From ! {io_reply, ReplyAs, Reply},
NewBuffer.
-do_output(console, Chars) ->
- io:put_chars(Chars),
- console;
do_output(Buffer, Chars) ->
<<Buffer/binary, (iolist_to_binary(Chars))/binary>>.
-ioreq_chars([{put_chars, _Enc, Chars} | R], Acc) -> ioreq_chars(R, [Chars | Acc]);
-ioreq_chars([{put_chars, _Enc, M, F, A} | R], Acc) -> ioreq_chars(R, [apply(M, F, A) | Acc]);
-ioreq_chars([{put_chars, Chars} | R], Acc) -> ioreq_chars(R, [Chars | Acc]);
-ioreq_chars([{put_chars, M, F, A} | R], Acc) -> ioreq_chars(R, [apply(M, F, A) | Acc]);
-ioreq_chars([{requests, Requests} | _R], Acc) -> ioreq_chars(Requests, Acc);
-ioreq_chars([_OtherRequest | _R], Acc) ->
- {notsup, lists:reverse(Acc)};
-ioreq_chars([], Acc) ->
- {ok, lists:reverse(Acc)}.
-
print_output_header(TaskName) ->
io:put_chars(["== ", TaskName, " ", lists:duplicate(max(0, ?LineWidth - length(TaskName)), $=), $\n]).
View
24 src/tetrapak_task_shell.erl
@@ -0,0 +1,24 @@
+% __ __ _
+% / /__________ __ _____ / /___ (_)___ ____ _
+% / __/ ___/ __ `/ | / / _ \/ / __ \/ / __ \/ __ `/
+% / /_/ / / /_/ /| |/ / __/ / /_/ / / / / / /_/ /
+% \__/_/ \__,_/ |___/\___/_/ .___/_/_/ /_/\__, /
+% /_/ /____/
+%
+% Copyright (c) Travelping GmbH <info@travelping.com>
+
+-module(tetrapak_task_shell).
+-behaviour(tetrapak_task).
+-export([run/2]).
+
+-task({"shell", "Start the Erlang shell"}).
+
+run("shell", _) ->
+ code:add_patha(tetrapak:subdir("ebin")),
+ case tetrapak_io:can_start_shell() of
+ true ->
+ tetrapak_io:start_shell(),
+ timer:sleep(infinity);
+ false ->
+ tetrapak:fail("Cannot start shell")
+ end.
Please sign in to comment.
Something went wrong with that request. Please try again.