wip
This commit is contained in:
parent
58aafaf692
commit
8476f3a89a
310
zx
310
zx
@ -87,10 +87,60 @@ start(["set", "dep", PackageString]) ->
|
|||||||
set_dep(PackageID);
|
set_dep(PackageID);
|
||||||
start(["set", "version", VersionString]) ->
|
start(["set", "version", VersionString]) ->
|
||||||
set_version(VersionString);
|
set_version(VersionString);
|
||||||
|
start(["list", "realms"]) ->
|
||||||
|
list_realms();
|
||||||
|
start(["list", "packages", Realm]) ->
|
||||||
|
case valid_lower0_9(Realm) of
|
||||||
|
true ->
|
||||||
|
list_packages(Realm);
|
||||||
|
false ->
|
||||||
|
ok = log(error, "Bad realm name."),
|
||||||
|
halt(1)
|
||||||
|
end;
|
||||||
|
start(["list", "versions", Package]) ->
|
||||||
|
case string:lexemes(Package, "-") of
|
||||||
|
[Realm, Name] ->
|
||||||
|
list_versions({Realm, Name});
|
||||||
|
_ ->
|
||||||
|
ok = log(error, "Bad package name."),
|
||||||
|
halt(1)
|
||||||
|
end;
|
||||||
|
start(["list", "pending", Package]) ->
|
||||||
|
case string:lexemes(Package, "-") of
|
||||||
|
[Realm, Name] ->
|
||||||
|
list_pending({Realm, Name});
|
||||||
|
_ ->
|
||||||
|
ok = log(error, "Bad package name."),
|
||||||
|
halt(1)
|
||||||
|
end;
|
||||||
|
start(["list", "resigns", Realm]) ->
|
||||||
|
case valid_lower0_9(Realm) of
|
||||||
|
true ->
|
||||||
|
list_resigns(Realm);
|
||||||
|
false ->
|
||||||
|
ok = log(error, "Bad realm name."),
|
||||||
|
halt(1)
|
||||||
|
end;
|
||||||
start(["add", "realm", RealmFile]) ->
|
start(["add", "realm", RealmFile]) ->
|
||||||
add_realm(RealmFile);
|
add_realm(RealmFile);
|
||||||
start(["add", "package", PackageName]) ->
|
start(["add", "package", PackageName]) ->
|
||||||
add_package(PackageName);
|
add_package(PackageName);
|
||||||
|
start(["add", "packager", Package, UserName]) ->
|
||||||
|
add_packager(Package, UserName);
|
||||||
|
start(["add", "maintainer", Package, UserName]) ->
|
||||||
|
add_maintainer(Package, UserName);
|
||||||
|
start(["review", PackageString]) ->
|
||||||
|
PackageID = package_id(PackageString),
|
||||||
|
review(PackageID);
|
||||||
|
start(["approve", PackageString]) ->
|
||||||
|
PackageID = package_id(PackageString),
|
||||||
|
approve(PackageID);
|
||||||
|
start(["reject", PackageString]) ->
|
||||||
|
PackageID = package_id(PackageString),
|
||||||
|
reject(PackageID);
|
||||||
|
start(["resign", PackageString]) ->
|
||||||
|
PackageID = package_id(PackageString),
|
||||||
|
resign(PackageID);
|
||||||
start(["drop", "dep", PackageString]) ->
|
start(["drop", "dep", PackageString]) ->
|
||||||
PackageID = package_id(PackageString),
|
PackageID = package_id(PackageString),
|
||||||
drop_dep(PackageID);
|
drop_dep(PackageID);
|
||||||
@ -548,6 +598,104 @@ update_version(Realm, Name, OldVersion, NewVersion, OldMeta) ->
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%%% List Functions
|
||||||
|
|
||||||
|
-spec list_realms() -> no_return().
|
||||||
|
%% @private
|
||||||
|
%% List all currently configured realms. The definition of a "configured realm" is a
|
||||||
|
%% realm for which a .realm file exists in ~/.zomp/. The realms will be printed to
|
||||||
|
%% stdout and the program will exit.
|
||||||
|
|
||||||
|
list_realms() ->
|
||||||
|
Pattern = filename:join(zomp_dir(), "*.realm"),
|
||||||
|
RealmFiles = filelib:wildcard(Pattern),
|
||||||
|
Realms = [filename:basename(RF, ".realm") || RF <- RealmFiles],
|
||||||
|
ok = lists:foreach(fun(R) -> io:format("~ts~n", [R]) end, Realms),
|
||||||
|
halt(0).
|
||||||
|
|
||||||
|
|
||||||
|
-spec list_packages(realm()) -> no_return().
|
||||||
|
%% @private
|
||||||
|
%% Contact the indicated realm and query it for a list of registered packages and print
|
||||||
|
%% them to stdout.
|
||||||
|
|
||||||
|
list_packages(Realm) ->
|
||||||
|
Socket = connect_user(Realm),
|
||||||
|
ok = send(Socket, {list, Realm}),
|
||||||
|
case recv_or_die(Socket) of
|
||||||
|
{ok, []} ->
|
||||||
|
ok = log(info, "Realm ~tp has no packages available.", [Realm]),
|
||||||
|
halt(0);
|
||||||
|
{ok, Packages} ->
|
||||||
|
Print = fun({R, N}) -> io:format("~ts-~ts~n", [R, N]) end,
|
||||||
|
ok = lists:foreach(Print, Packages),
|
||||||
|
halt(0);
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
-spec list_versions(package()) -> no_return().
|
||||||
|
|
||||||
|
list_versions(Package = {Realm, Name}) ->
|
||||||
|
ok = valid_package(Package),
|
||||||
|
Socket = connect_user(Realm),
|
||||||
|
ok = send(Socket, {list, Realm, Name}),
|
||||||
|
case recv_or_die(Socket) of
|
||||||
|
{ok, []} ->
|
||||||
|
Message = "Package ~ts-~ts has no versions available.",
|
||||||
|
ok = log(info, Message, [Realm, Name]),
|
||||||
|
halt(0);
|
||||||
|
{ok, Versions} ->
|
||||||
|
Print =
|
||||||
|
fun(Version) ->
|
||||||
|
PackageString = package_string({Realm, Name, Version}),
|
||||||
|
io:format("~ts~n", [PackageString])
|
||||||
|
end,
|
||||||
|
ok = lists:foreach(Print, Versions),
|
||||||
|
halt(0)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
-spec list_pending(package()) -> no_return().
|
||||||
|
|
||||||
|
list_pending(Package = {Realm, Name}) ->
|
||||||
|
ok = valid_package(Package),
|
||||||
|
Socket = connect_user(Realm),
|
||||||
|
ok = send(Socket, {pending, Package}),
|
||||||
|
case recv_or_die(Socket) of
|
||||||
|
{ok, []} ->
|
||||||
|
Message = "Package ~ts-~ts has no versions pending.",
|
||||||
|
ok = log(info, Message, [Realm, Name]),
|
||||||
|
halt(0);
|
||||||
|
{ok, Versions} ->
|
||||||
|
Print =
|
||||||
|
fun(Version) ->
|
||||||
|
PackageString = package_string({Realm, Name, Version}),
|
||||||
|
io:format("~ts~n", [PackageString])
|
||||||
|
end,
|
||||||
|
ok = lists:foreach(Print, Versions),
|
||||||
|
halt(0)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
-spec valid_package(package()) -> ok | no_return().
|
||||||
|
|
||||||
|
valid_package({Realm, Name}) ->
|
||||||
|
case {valid_lower0_9(Realm), valid_lower0_9(Name)} of
|
||||||
|
{true, true} ->
|
||||||
|
ok;
|
||||||
|
{false, true} ->
|
||||||
|
ok = log(error, "Invalid realm name: ~tp", [Realm]),
|
||||||
|
halt(1);
|
||||||
|
{true, false} ->
|
||||||
|
ok = log(error, "Invalid package name: ~tp", [Name]),
|
||||||
|
halt(1);
|
||||||
|
{false, false} ->
|
||||||
|
ok = log(error, "Invalid realm ~tp and package ~tp", [Realm, Name]),
|
||||||
|
halt(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%% Add realm
|
%%% Add realm
|
||||||
|
|
||||||
-spec add_realm(Path) -> no_return()
|
-spec add_realm(Path) -> no_return()
|
||||||
@ -621,35 +769,95 @@ add_package(PackageName) ->
|
|||||||
%% This sysop-only command can add a package to a realm operated by the caller.
|
%% This sysop-only command can add a package to a realm operated by the caller.
|
||||||
|
|
||||||
add_package(Realm, Name) ->
|
add_package(Realm, Name) ->
|
||||||
Socket =
|
Socket = connect_auth_or_die(Realm),
|
||||||
case connect_auth(Realm) of
|
|
||||||
{ok, S} ->
|
|
||||||
S;
|
|
||||||
Error ->
|
|
||||||
M1 = "Connection failed to realm prime with ~160tp.",
|
|
||||||
ok = log(warning, M1, [Error]),
|
|
||||||
halt(1)
|
|
||||||
end,
|
|
||||||
ok = send(Socket, {add_package, {Realm, Name}}),
|
ok = send(Socket, {add_package, {Realm, Name}}),
|
||||||
receive
|
ok = recv_or_die(Socket),
|
||||||
{tcp, Socket, Bin} ->
|
ok = log(info, "\"~ts-~ts\" added successfully.", [Realm, Name]),
|
||||||
case binary_to_term(Bin, [safe]) of
|
halt(0).
|
||||||
ok ->
|
|
||||||
ok = log(info, "\"~ts-~ts\" added successfully.", [Realm, Name]),
|
|
||||||
halt(0);
|
list_resigns(Realm) ->
|
||||||
{error, Reason} ->
|
Socket = connect_auth_or_die(Realm),
|
||||||
M2 = "Operation failed. Server sends reason: ~160tp",
|
ok = send(Socket, {list_resigns, Realm}),
|
||||||
ok = log(error, M2, [Reason]),
|
case recv_or_die(Socket) of
|
||||||
halt(1)
|
{ok, []} ->
|
||||||
end;
|
Message = "No packages pending signature in ~tp.",
|
||||||
{tcp_closed, Socket} ->
|
ok = log(info, Message, [Realm]),
|
||||||
halt_on_unexpected_close()
|
halt(0);
|
||||||
after 5000 ->
|
{ok, PackageIDs} ->
|
||||||
ok = log(warning, "Operation timed After submission to server."),
|
Print =
|
||||||
halt(1)
|
fun(PackageID) ->
|
||||||
|
PackageString = package_string(PackageID),
|
||||||
|
io:format("~ts~n", [PackageString])
|
||||||
|
end,
|
||||||
|
ok = lists:foreach(Print, PackageIDs),
|
||||||
|
halt(0)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
add_packager(Package, UserName) ->
|
||||||
|
ok = log(info, "Would add ~ts to packagers for ~160tp now.", [UserName, Package]),
|
||||||
|
halt(0).
|
||||||
|
|
||||||
|
|
||||||
|
add_maintainer(Package, UserName) ->
|
||||||
|
ok = log(info, "Would add ~ts to maintainer for ~160tp now.", [UserName, Package]),
|
||||||
|
halt(0).
|
||||||
|
|
||||||
|
|
||||||
|
review(PackageID) ->
|
||||||
|
PackageString = package_string(PackageID),
|
||||||
|
ZrpPath = PackageString ++ ".zrp",
|
||||||
|
ok = log(info, "Saving to ~ts, unpacking to ./~ts/", [ZrpPath, PackageString]),
|
||||||
|
ok =
|
||||||
|
case {filelib:is_file(ZrpPath), filelib:is_file(PackageString)} of
|
||||||
|
{false, false} ->
|
||||||
|
ok;
|
||||||
|
{true, false} ->
|
||||||
|
ok = log(error, "~ts already exists. Aborting.", [ZrpPath]),
|
||||||
|
halt(1);
|
||||||
|
{false, true} ->
|
||||||
|
ok = log(error, "~ts already exists. Aborting.", [PackageString]),
|
||||||
|
halt(1);
|
||||||
|
{true true} ->
|
||||||
|
Message = "~ts and ~ts already exist. Aborting.",
|
||||||
|
ok = log(error, Message, [ZrpPath, PackageString]),
|
||||||
|
halt(1);
|
||||||
|
end,
|
||||||
|
Socket = connect_auth_or_die(),
|
||||||
|
ok = send(Socket, {review, PackageID}),
|
||||||
|
ok = receive_or_die(Socket),
|
||||||
|
{ok, ZrpBin} = recieve_or_die(Socket),
|
||||||
|
ok = file:write_file(ZrpPath, ZrpBin),
|
||||||
|
ok = disconnect(Socket),
|
||||||
|
{"zomp.meta", MetaBin} = erl_tar:extract(ZrpBin, [memory, {files, "zomp.meta"}]),
|
||||||
|
Meta = binary_to_term(MetaBin, [safe]),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
approve(PackageID = {Realm, _, _}) ->
|
||||||
|
Socket = connect_auth_or_die(Realm),
|
||||||
|
ok = send(Socket, {approve, PackageID}),
|
||||||
|
ok = recv_or_die(Socket),
|
||||||
|
ok = log(info, "ok"),
|
||||||
|
halt(0).
|
||||||
|
|
||||||
|
|
||||||
|
reject(PackageID = {Realm, _, _}) ->
|
||||||
|
Socket = connect_auth_or_die(Realm),
|
||||||
|
ok = send(Socket, {reject, PackageID}),
|
||||||
|
ok = recv_or_die(Socket),
|
||||||
|
ok = log(info, "ok"),
|
||||||
|
halt(0).
|
||||||
|
|
||||||
|
|
||||||
|
resign(PackageID) ->
|
||||||
|
M = "Pull the indicated package",
|
||||||
|
ok = log(info, M, [PackageID]),
|
||||||
|
halt(0).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%% Drop dependency
|
%%% Drop dependency
|
||||||
|
|
||||||
-spec drop_dep(package_id()) -> no_return().
|
-spec drop_dep(package_id()) -> no_return().
|
||||||
@ -1057,6 +1265,43 @@ send(Socket, Message) ->
|
|||||||
gen_tcp:send(Socket, Bin).
|
gen_tcp:send(Socket, Bin).
|
||||||
|
|
||||||
|
|
||||||
|
-spec recv_or_die(Socket) -> Result | no_return()
|
||||||
|
when Socket :: gen_tcp:socket(),
|
||||||
|
Result :: ok | {ok, term()}.
|
||||||
|
|
||||||
|
recv_or_die(Socket) ->
|
||||||
|
receive
|
||||||
|
{tcp, Socket, Bin} ->
|
||||||
|
case binary_to_term(Bin, [safe]) of
|
||||||
|
ok ->
|
||||||
|
ok;
|
||||||
|
{ok, Response} ->
|
||||||
|
{ok, Response};
|
||||||
|
{error, bad_realm} ->
|
||||||
|
ok = log(warning, "No such realm at the connected node.").
|
||||||
|
halt(1);
|
||||||
|
{error, bad_package} ->
|
||||||
|
ok = log(warning, "No such package.").
|
||||||
|
halt(1)
|
||||||
|
{error, bad_version} ->
|
||||||
|
ok = log(warning, "No such version."),
|
||||||
|
halt(1);
|
||||||
|
{error, not_in_queue} ->
|
||||||
|
ok = log(warning, "Version is not queued."),
|
||||||
|
halt(1);
|
||||||
|
{error, bad_message} ->
|
||||||
|
ok = log(error, "Oh noes! zx sent an illegal message!"),
|
||||||
|
halt(1)
|
||||||
|
end;
|
||||||
|
{tcp_closed, Socket} ->
|
||||||
|
ok = log(warning, "Lost connection to node unexpectedly."),
|
||||||
|
halt(1)
|
||||||
|
after 5000 ->
|
||||||
|
ok = log(warning, "Node timed out."),
|
||||||
|
halt(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
-spec halt_on_unexpected_close() -> no_return().
|
-spec halt_on_unexpected_close() -> no_return().
|
||||||
|
|
||||||
halt_on_unexpected_close() ->
|
halt_on_unexpected_close() ->
|
||||||
@ -1169,7 +1414,7 @@ confirm_serial(Realm, Socket, Hosts) ->
|
|||||||
Socket;
|
Socket;
|
||||||
{ok, Current} when Current > Serial ->
|
{ok, Current} when Current > Serial ->
|
||||||
ok = log(info, "Node's serial newer than ours. Storing."),
|
ok = log(info, "Node's serial newer than ours. Storing."),
|
||||||
NewSerials = lists:keystore(Realm, 1, Current, {Realm, Serials}),
|
NewSerials = lists:keystore(Realm, 1, Serials, {Realm, Current}),
|
||||||
{ok, Host} = inet:peername(Socket),
|
{ok, Host} = inet:peername(Socket),
|
||||||
ok = write_terms(hosts_cache_file(Realm), [Host | Hosts]),
|
ok = write_terms(hosts_cache_file(Realm), [Host | Hosts]),
|
||||||
ok = write_terms(SerialFile, NewSerials),
|
ok = write_terms(SerialFile, NewSerials),
|
||||||
@ -1193,6 +1438,19 @@ confirm_serial(Realm, Socket, Hosts) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
-spec connect_auth_or_die(realm()) -> gen_tcp:socket() | no_return().
|
||||||
|
|
||||||
|
connect_auth_or_die(Realm) ->
|
||||||
|
case connect_auth(Realm) of
|
||||||
|
{ok, Socket} ->
|
||||||
|
Socket;
|
||||||
|
Error ->
|
||||||
|
M1 = "Connection failed to realm prime with ~160tp.",
|
||||||
|
ok = log(warning, M1, [Error]),
|
||||||
|
halt(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
-spec connect_auth(Realm) -> Result
|
-spec connect_auth(Realm) -> Result
|
||||||
when Realm :: realm(),
|
when Realm :: realm(),
|
||||||
Result :: {ok, gen_tcp:socket()}
|
Result :: {ok, gen_tcp:socket()}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user