Compare commits

..

10 Commits

60 changed files with 165 additions and 91 deletions

View File

@ -3,7 +3,7 @@
# A convenience script that will download the ZX installer, unpack it, and clean up.
# For maximum portability this script uses the gzipped package version.
version=0.12.7
version=0.14.0
zx="zx-$version"
tarball="$zx.tar.gz"
target="https://zxq9.com/projects/zomp/$tarball"

View File

@ -35,21 +35,20 @@ if [[ ":$PATH:" == *":$bin:"* ]]
export PATH="$bin:$PATH"
fi
for rc in "$HOME/.profile" "$HOME/.bashrc" "$HOME/.bash_profile"
do
if [ -f "$rc" ]
for rc in ~/.bashrc ~/.bash_profile ~/.profile ~/.zshrc ~/.zprofile ~/.zshenv
do
if [[ -f "$rc" ]]
then
if grep -q "PATH=\"\$HOME/bin:\$PATH\"" "$rc"
if ! grep -q "export PATH=.*[:=]$HOME/bin[:$]" "$rc"
then
echo "Path adjustment found in $rc."
else
echo "Path adjustment not found in $rc. Adding it."
echo "export PATH=\"\$HOME/bin:\$PATH\"" >> "$rc"
# This actually fixes the stupid newline thing
echo -e "\n"'export PATH="$HOME/bin:$PATH"' >> "$rc"
fi
else
echo "No $rc is present. Skipping."
touch "$rc"
echo -e 'export PATH="$HOME/bin:$PATH"' >> "$rc"
fi
done
done
cp -r zomp "$zomp_dir"
cp unix/zx "$zomp_dir"

View File

@ -1 +1 @@
0.13.5
0.14.0

View File

@ -1,6 +1,6 @@
{application,zx,
[{description,"An Erlang development tool and Zomp user client"},
{vsn,"0.13.5"},
{vsn,"0.14.0"},
{applications,[stdlib,kernel]},
{modules,[zx,zx_auth,zx_conn,zx_conn_sup,zx_daemon,zx_key,
zx_lib,zx_local,zx_net,zx_peer,zx_peer_man,

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -24,7 +24,7 @@
%%% @end
-module(zx).
-vsn("0.13.5").
-vsn("0.14.0").
-behavior(application).
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
@ -318,11 +318,18 @@ do(_) ->
done(ok) ->
ok = zx_daemon:idle(),
init:stop(0);
done({error, shutdown}) ->
ok = tell(info, "Shutdown message received."),
ok = zx_daemon:idle(),
init:stop(0);
done({error, Code}) when is_integer(Code) ->
ok = zx_daemon:idle(),
Message = "Operation failed with code: ~w",
ok = tell(error, Message, [Code]),
init:stop(Code);
done({error, Reason}) when is_atom(Reason) ->
ok = tell(error, "Operation failed with: ~160tp", [Reason]),
init:stop(1);
done({error, Reason}) ->
ok = zx_daemon:idle(),
{Message, Subs} =
@ -332,6 +339,9 @@ done({error, Reason}) ->
end,
ok = tell(error, Message, [Subs]),
init:stop(1);
done({error, Reason, Code}) when is_atom(Reason) ->
ok = tell(error, "Operation failed with: ~160tp", [Reason]),
init:stop(Code);
done({error, Reason, Code}) ->
ok = zx_daemon:idle(),
{Message, Subs} =
@ -947,9 +957,13 @@ run4(PackageID, RunArgs) ->
run5(Type, PackageID, Meta, Dir, Deps, NewArgs) ->
true = os:putenv("zx_include", filename:join(os:getenv("ZX_DIR"), "include")),
Required = [{fetch, PackageID} | Deps],
{ok, CWD} = file:get_cwd(),
case prepare(Required) of
ok -> execute(Type, PackageID, Meta, Dir, NewArgs);
Error -> Error
ok ->
ok = file:set_cwd(CWD),
execute(Type, PackageID, Meta, Dir, NewArgs);
Error ->
Error
end.
@ -1210,13 +1224,21 @@ upgrade() ->
fetch(PackageID) ->
{ok, PackageName} = zx_lib:package_string(PackageID),
ok = tell("Fetching ~ts", [PackageName]),
{ok, ID} = zx_daemon:fetch(PackageID),
{ok, ID} = zx_daemon:fetch(PackageID, [self()]),
fetch2(ID).
fetch2(ID) ->
receive
{result, ID, done} ->
ok;
{rx, Size, Received} ->
ok = zx_tty:dl(Size, Received),
fetch2(ID);
{rx, done} ->
ok = zx_tty:dl(1, 1),
fetch2(ID);
{rx, overflow} ->
{error, overflow};
{result, ID, {hops, Count}} ->
ok = tell("Inbound; ~w hops away.", [Count]),
fetch2(ID);

View File

@ -9,7 +9,7 @@
%%% @end
-module(zx_auth).
-vsn("0.13.5").
-vsn("0.14.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0").

View File

@ -7,7 +7,7 @@
%%% @end
-module(zx_conn).
-vsn("0.13.5").
-vsn("0.14.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0").
@ -292,7 +292,7 @@ dispatch(Socket, ID, Action) ->
{search, R, String} -> send_query(Socket, 9, {R, String});
{list_deps, R, N, V} -> send_query(Socket, 10, {R, N, V});
{list_sysops, R} -> send_query(Socket, 11, R);
{fetch, R, N, V} -> fetch(Socket, ID, {R, N, V});
{fetch, R, N, V, W} -> fetch(Socket, ID, W, {R, N, V});
{keychain, R, K} -> send_query(Socket, 13, {R, K});
{list_type, R, T} -> send_query(Socket, 14, {R, T});
Unexpected ->
@ -328,22 +328,23 @@ pong(Socket) ->
gen_tcp:send(Socket, <<1:1, 0:7>>).
-spec fetch(Socket, ID, PackageID) -> Result
-spec fetch(Socket, ID, Watchers, PackageID) -> Result
when Socket :: gen_tcp:socket(),
ID :: zx_daemon:id(),
Watchers :: [pid()],
PackageID :: zx:package_id(),
Result :: {done, binary()}
| {error, Reason :: term()}.
%% @private
%% Download a package to the local cache.
fetch(Socket, ID, PackageID) ->
fetch(Socket, ID, Watchers, PackageID) ->
PIDB = term_to_binary(PackageID),
Message = <<0:1, 12:7, PIDB/binary>>,
ok = gen_tcp:send(Socket, Message),
case wait_hops(Socket, ID, PIDB) of
ok ->
{ok, Bin} = zx_net:rx(Socket),
{ok, Bin} = zx_net:rx(Socket, 5000, Watchers),
{done, Bin};
Error ->
Error

View File

@ -5,7 +5,7 @@
%%% @end
-module(zx_conn_sup).
-vsn("0.13.5").
-vsn("0.14.0").
-behavior(supervisor).
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").

View File

@ -138,7 +138,7 @@
%%% @end
-module(zx_daemon).
-vsn("0.13.5").
-vsn("0.14.0").
-behavior(gen_server).
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
@ -152,7 +152,7 @@
list/0, list/1, list/2, list/3, list_type/1, latest/1,
describe/1, provides/2, list_deps/1, search/1,
list_sysops/1,
fetch/1, install/1, build/1,
fetch/1, fetch/2, install/1, build/1,
wait_result/1, wait_results/1]).
-export([register_key/2, get_key/2, get_keybin/2,
have_key/2, list_keys/2]).
@ -269,7 +269,7 @@
| {list_sysops, zx:realm()}
| {pending, zx:realm(), zx:name()}
| {approved, zx:realm()}
| {fetch, zx:realm(), zx:name(), zx:version()}
| {fetch, zx:realm(), zx:name(), zx:version(), [pid()]}
| {keychain, zx:realm(), zx:key_name()}.
% Outgoing Result Messages
@ -558,13 +558,28 @@ list_sysops(Realm) ->
request({list_sysops, Realm}).
-spec fetch(zx:package_id()) -> {ok, id()}.
-spec fetch(PackageID) -> Result
when PackageID :: zx:package_id(),
Result :: {ok, JobID :: id()}.
%% @doc
%% Install the specified package. This returns an id() that will be referenced
%% in a later response message.
%% @equiv fetch(PackageID, []).
fetch(PackageID) ->
fetch(PackageID, []).
-spec fetch(PackageID, Watchers) -> Result
when PackageID :: zx:package_id(),
Watchers :: [pid()],
Result :: {ok, JobID :: id()}.
%% @doc
%% Install the specified package. This returns an id() that will be referenced
%% in a later response message.
fetch(PackageID) ->
gen_server:call(?MODULE, {fetch, PackageID}).
fetch(PackageID, Watchers) ->
gen_server:call(?MODULE, {fetch, PackageID, Watchers}).
-spec install(Path :: file:filename()) -> zx:outcome().
@ -595,8 +610,9 @@ build(PackageID) ->
wait_result(ID) ->
receive
{result, ID, Result} -> Result;
Message -> {error, {unexpected, Message}}
after 5000 -> {error, timeout}
Reason when is_atom(Reason) -> {error, Reason};
Message -> {error, Message}
after 60000 -> {error, timeout}
end.
@ -629,7 +645,7 @@ wait_results(IDs, Results) ->
end;
Message ->
{error, {unexpected, Message}}
after 5000 ->
after 60000 ->
{error, timeout}
end.
@ -736,7 +752,7 @@ drop_realm(Realm) ->
%% Private function to wrap the necessary bits up.
request(Action) ->
gen_server:call(?MODULE, {request, Action}).
gen_server:call(?MODULE, {request, Action}, 60000).
@ -860,11 +876,11 @@ handle_call({request, Action}, From, State = #s{id = ID}) ->
NextState = do_request(Requestor, Action, State#s{id = NewID}),
NewState = eval_queue(NextState),
{noreply, NewState};
handle_call({fetch, PackageID}, From, State = #s{id = ID}) ->
handle_call({fetch, PackageID, Watchers}, From, State = #s{id = ID}) ->
NewID = ID + 1,
_ = gen_server:reply(From, {ok, NewID}),
ok = gen_server:reply(From, {ok, NewID}),
Requestor = element(1, From),
NextState = do_fetch(PackageID, Requestor, State#s{id = NewID}),
NextState = do_fetch(PackageID, Watchers, Requestor, State#s{id = NewID}),
NewState = eval_queue(NextState),
{noreply, NewState};
handle_call({install, Path}, _, State) ->
@ -1317,7 +1333,7 @@ do_result(ID, Result, State = #s{requests = Requests, dropped = Dropped, mx = MX
State#s{requests = NewRequests, dropped = NewDropped, mx = NewMX}.
handle_fetch_result(ID, {done, Bin}, {Requestor, {fetch, R, N, V}}, Requests, MX) ->
handle_fetch_result(ID, {done, Bin}, {Requestor, {fetch, R, N, V, _}}, Requests, MX) ->
Result =
case do_import_package(Bin) of
ok ->
@ -1417,7 +1433,7 @@ eval_queue(Actions, State) ->
local_dispatch([], State) ->
State;
local_dispatch([{request, Pid, ID, {fetch, R, N, V}} | Rest], State) ->
local_dispatch([{request, Pid, ID, {fetch, R, N, V, _}} | Rest], State) ->
Result =
case zomp_realm_man:lookup(R) of
{ok, RealmPID} -> local_fetch(RealmPID, {R, N, V});
@ -1666,15 +1682,16 @@ drop_requests(ReqIDs, Dropped, Requests) ->
lists:foldl(Partition, {Dropped, Requests}, ReqIDs).
-spec do_fetch(PackageID, Requestor, State) -> NewState
-spec do_fetch(PackageID, Watchers, Requestor, State) -> NewState
when PackageID :: zx:package_id(),
Watchers :: [pid()],
Requestor :: pid(),
State :: state(),
NewState :: state().
%% @private
%% Provide a chance to bypass if the package is in cache.
do_fetch(PackageID, Requestor, State = #s{id = ID}) ->
do_fetch(PackageID, Watchers, Requestor, State = #s{id = ID}) ->
{ok, PackageString} = zx_lib:package_string(PackageID),
ok = log(info, "Fetching ~ts", [PackageString]),
Path = zx_lib:zsp_path(PackageID),
@ -1684,7 +1701,7 @@ do_fetch(PackageID, Requestor, State = #s{id = ID}) ->
State;
{error, enoent} ->
{Realm, Name, Version} = PackageID,
Action = {fetch, Realm, Name, Version},
Action = {fetch, Realm, Name, Version, Watchers},
do_request(Requestor, Action, State);
Error ->
Requestor ! {result, ID, Error},

View File

@ -8,7 +8,7 @@
%%% @end
-module(zx_key).
-vsn("0.13.5").
-vsn("0.14.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0").

View File

@ -10,7 +10,7 @@
%%% @end
-module(zx_lib).
-vsn("0.13.5").
-vsn("0.14.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0").

View File

@ -6,7 +6,7 @@
%%% @end
-module(zx_local).
-vsn("0.13.5").
-vsn("0.14.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0").
@ -259,7 +259,7 @@ project_check(P = #project{id = PackageID}, Continue, Retry) ->
2 -> Continue(P);
3 -> ok
end;
maybe ->
weather_permitting ->
Message =
"~n∑(。・Д・。)???~nHmmm...~n"
"zx_daemon wasn't able to check whether this package already exists.~n"
@ -1894,7 +1894,7 @@ package_exists({Realm, Package, _}) ->
{ok, ID} = zx_daemon:list(Realm),
case zx_daemon:wait_result(ID) of
{ok, Packages} -> lists:member(Package, Packages);
_ -> maybe
_ -> weather_permitting
end.

View File

@ -5,7 +5,7 @@
%%% @end
-module(zx_net).
-vsn("0.13.5").
-vsn("0.14.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0").
@ -179,34 +179,33 @@ rx(Socket, Timeout, Watchers) ->
ok = gen_tcp:send(Socket, <<1:32, 0:8>>),
receive
{tcp, Socket, <<Size:32, Bin/binary>>} ->
ok = broadcast({rx, Socket, start, Size}, Watchers),
Left = Size - byte_size(Bin),
rx(Socket, Watchers, Left, Bin, Timeout);
Received = byte_size(Bin),
rx(Socket, Watchers, Size, Received, Bin, Timeout);
{tcp_closed, Socket} ->
{error, tcp_closed}
after Timeout ->
{error, timeout}
end.
rx(Socket, Watchers, 0, Bin, _) ->
ok = inet:setopts(Socket, [{packet, 4}]),
ok = gen_tcp:send(Socket, <<0:8>>),
ok = broadcast({rx, Socket, done}, Watchers),
{ok, Bin};
rx(Socket, Watchers, Left, Buffer, Timeout) when Left > 0 ->
ok = broadcast({rx, Socket, pending, Left}, Watchers),
rx(Socket, Watchers, Size, Received, Buffer, Timeout) when Size > Received ->
ok = broadcast({rx, Size, Received}, Watchers),
ok = inet:setopts(Socket, [{active, once}]),
receive
{tcp, Socket, Bin} ->
NewLeft = Left - byte_size(Bin),
rx(Socket, Watchers, NewLeft, <<Buffer/binary, Bin/binary>>, Timeout);
NewReceived = Received + byte_size(Bin),
rx(Socket, Watchers, Size, NewReceived, <<Buffer/binary, Bin/binary>>, Timeout);
{tcp_closed, Socket} ->
{error, tcp_closed}
after Timeout ->
{error, timeout}
end;
rx(Socket, Watchers, Left, _, _) when Left < 0 ->
ok = broadcast({rx, Socket, overflow}, Watchers),
rx(Socket, Watchers, Size, Size, Bin, _) ->
ok = inet:setopts(Socket, [{packet, 4}]),
ok = gen_tcp:send(Socket, <<0:8>>),
ok = broadcast({rx, done}, Watchers),
{ok, Bin};
rx(_, Watchers, Size, Received, _, _) when Size < Received ->
ok = broadcast({rx, overflow}, Watchers),
{error, bad_message}.

View File

@ -8,7 +8,7 @@
%%% @end
-module(zx_peer).
-vsn("0.13.5").
-vsn("0.14.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0").

View File

@ -9,7 +9,7 @@
%%% @end
-module(zx_peer_man).
-vsn("0.13.5").
-vsn("0.14.0").
-behavior(gen_server).
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").

View File

@ -6,7 +6,7 @@
%%% @end
-module(zx_peer_sup).
-vsn("0.13.5").
-vsn("0.14.0").
-behaviour(supervisor).
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").

View File

@ -10,7 +10,7 @@
%%% @end
-module(zx_peers).
-vsn("0.13.5").
-vsn("0.14.0").
-behavior(supervisor).
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").

View File

@ -5,7 +5,7 @@
%%% @end
-module(zx_proxy).
-vsn("0.13.5").
-vsn("0.14.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0").
@ -49,6 +49,12 @@ unsubscribe(Package) ->
request(Action) ->
Proxy = whereis(?MODULE),
Mon = monitor(process, Proxy),
request(Proxy, Mon, Action).
request(Proxy, Mon, {fetch, R, N, V, Watchers}) ->
Proxy ! {request, self(), Mon, {fetch, R, N, V}},
progress(Proxy, Mon, Watchers);
request(Proxy, Mon, Action) ->
Proxy ! {request, self(), Mon, Action},
receive
{result, Mon, Result} ->
@ -60,6 +66,21 @@ request(Action) ->
{error, timeout}
end.
progress(Proxy, Mon, Watchers) ->
receive
Report when element(1, Report) =:= rx ->
Notify = fun(Watcher) -> Watcher ! Report end,
ok = lists:foreach(Notify, Watchers),
progress(Proxy, Mon, Watchers);
{result, Mon, Result} ->
true = demonitor(Mon),
Result;
{'DOWN', Mon, process, Proxy, Info} ->
{error, Info}
after 5000 ->
{error, timeout}
end.
-spec connect(Port) -> Result
when Port :: inet:port_number(),

View File

@ -5,7 +5,7 @@
%%% @end
-module(zx_sup).
-vsn("0.13.5").
-vsn("0.14.0").
-behavior(supervisor).
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").

View File

@ -6,7 +6,7 @@
%%% @end
-module(zx_tty).
-vsn("0.13.5").
-vsn("0.14.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0").
@ -14,6 +14,7 @@
-export([get_input/0, get_input/1, get_input/2, get_input/3,
get_lower0_9/1, get_lower0_9/2, get_lower0_9/3,
select/1, select_string/1,
dl/0, dl/2,
derp/0]).
@ -170,6 +171,20 @@ pick({I, _}, Max) when 0 < I, I =< Max -> I;
pick(_, _) -> error.
-spec dl(Size, Received) -> ok
when Size :: pos_integer(),
Received :: non_neg_integer().
dl() ->
io:format("~n[ 0.00%]").
dl(Size, Size) ->
io:format("\r[~6.2f%]~n", [100.0]);
dl(Size, Received) ->
P = (Received * 100) / Size,
io:format("\r[~6.2f%]", [P]).
-spec hurr() -> ok.
%% @private
%% Present an appropriate response when the user derps on selection.

View File

@ -5,7 +5,7 @@
%%% @end
-module(zx_userconf).
-vsn("0.13.5").
-vsn("0.14.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0").

View File

@ -7,7 +7,7 @@
%%% @end
-module(zx_zsp).
-vsn("0.13.5").
-vsn("0.14.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0").

View File

@ -4,7 +4,7 @@
{prefix,"zx_"}.
{author,"Craig Everett"}.
{desc,"An Erlang development tool and Zomp user client"}.
{package_id,{"otpr","zx",{0,13,5}}}.
{package_id,{"otpr","zx",{0,14,0}}}.
{deps,[]}.
{key_name,none}.
{a_email,"zxq9@zxq9.com"}.