wip
This commit is contained in:
parent
8476f3a89a
commit
8d97664056
231
zx
231
zx
@ -90,37 +90,17 @@ start(["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;
|
||||
ok = valid_realm(Realm),
|
||||
list_packages(Realm);
|
||||
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;
|
||||
Package = string_to_package(PackageName),
|
||||
list_versions(Package);
|
||||
start(["list", "pending", PackageName]) ->
|
||||
Package = string_to_package(PackageName),
|
||||
list_pending(Package);
|
||||
start(["list", "resigns", Realm]) ->
|
||||
case valid_lower0_9(Realm) of
|
||||
true ->
|
||||
list_resigns(Realm);
|
||||
false ->
|
||||
ok = log(error, "Bad realm name."),
|
||||
halt(1)
|
||||
end;
|
||||
ok = valid_realm(Realm),
|
||||
list_resigns(Realm);
|
||||
start(["add", "realm", RealmFile]) ->
|
||||
add_realm(RealmFile);
|
||||
start(["add", "package", PackageName]) ->
|
||||
@ -130,8 +110,7 @@ start(["add", "packager", Package, UserName]) ->
|
||||
start(["add", "maintainer", Package, UserName]) ->
|
||||
add_maintainer(Package, UserName);
|
||||
start(["review", PackageString]) ->
|
||||
PackageID = package_id(PackageString),
|
||||
review(PackageID);
|
||||
review(PackageString);
|
||||
start(["approve", PackageString]) ->
|
||||
PackageID = package_id(PackageString),
|
||||
approve(PackageID);
|
||||
@ -167,6 +146,8 @@ start(["submit", PackageFile]) ->
|
||||
submit(PackageFile);
|
||||
start(["dialyze"]) ->
|
||||
dialyze();
|
||||
start(["create", "user", Realm, Name]) ->
|
||||
create_user(Realm, Name);
|
||||
start(["create", "keypair"]) ->
|
||||
create_keypair();
|
||||
start(["create", "plt"]) ->
|
||||
@ -634,6 +615,10 @@ list_packages(Realm) ->
|
||||
|
||||
|
||||
-spec list_versions(package()) -> no_return().
|
||||
%% @private
|
||||
%% List the available versions of the package indicated. The user enters a string-form
|
||||
%% package name (such as "otpr-zomp") and the return values will be full package strings
|
||||
%% of the form "otpr-zomp-1.2.3", one per line printed to stdout.
|
||||
|
||||
list_versions(Package = {Realm, Name}) ->
|
||||
ok = valid_package(Package),
|
||||
@ -656,6 +641,10 @@ list_versions(Package = {Realm, Name}) ->
|
||||
|
||||
|
||||
-spec list_pending(package()) -> no_return().
|
||||
%% @private
|
||||
%% List the versions of a package that are pending review. The package name is input by the
|
||||
%% user as a string of the form "otpr-zomp" and the output is a list of full package IDs,
|
||||
%% printed one per line to stdout (like "otpr-zomp-3.2.2").
|
||||
|
||||
list_pending(Package = {Realm, Name}) ->
|
||||
ok = valid_package(Package),
|
||||
@ -677,7 +666,34 @@ list_pending(Package = {Realm, Name}) ->
|
||||
end.
|
||||
|
||||
|
||||
-spec list_resigns(realm()) -> no_return().
|
||||
%% @private
|
||||
%% List the package ids of all packages waiting in the resign queue for the given realm,
|
||||
%% printed to stdout one per line.
|
||||
|
||||
list_resigns(Realm) ->
|
||||
Socket = connect_auth_or_die(Realm),
|
||||
ok = send(Socket, {list_resigns, Realm}),
|
||||
case recv_or_die(Socket) of
|
||||
{ok, []} ->
|
||||
Message = "No packages pending signature in ~tp.",
|
||||
ok = log(info, Message, [Realm]),
|
||||
halt(0);
|
||||
{ok, PackageIDs} ->
|
||||
Print =
|
||||
fun(PackageID) ->
|
||||
PackageString = package_string(PackageID),
|
||||
io:format("~ts~n", [PackageString])
|
||||
end,
|
||||
ok = lists:foreach(Print, PackageIDs),
|
||||
halt(0)
|
||||
end.
|
||||
|
||||
|
||||
-spec valid_package(package()) -> ok | no_return().
|
||||
%% @private
|
||||
%% Test whether a package() type is a valid value or not. If not, halt execution with
|
||||
%% a non-zero error code, if so then return `ok'.
|
||||
|
||||
valid_package({Realm, Name}) ->
|
||||
case {valid_lower0_9(Realm), valid_lower0_9(Name)} of
|
||||
@ -692,6 +708,40 @@ valid_package({Realm, Name}) ->
|
||||
{false, false} ->
|
||||
ok = log(error, "Invalid realm ~tp and package ~tp", [Realm, Name]),
|
||||
halt(1)
|
||||
end;
|
||||
valid_package(Bad) ->
|
||||
ok = log(error, "Invalid package() value: ~160tp", [Bad]),
|
||||
halt(1).
|
||||
|
||||
|
||||
-spec string_to_package(string()) -> ok | no_return().
|
||||
%% @private
|
||||
%% Convert a string to a package() type if possible. If not then halt the system.
|
||||
|
||||
string_to_package(String) ->
|
||||
case string:lexemes(Package, "-") of
|
||||
[Realm, Name] ->
|
||||
Package = {Realm, Name},
|
||||
ok = valid_package(Package),
|
||||
Package;
|
||||
_ ->
|
||||
ok = log(error, "Bad package name."),
|
||||
halt(1)
|
||||
end.
|
||||
|
||||
|
||||
-spec valid_realm(realm()) -> ok | no_return().
|
||||
%% @private
|
||||
%% Test whether a realm name is a valid realm() type (that is, a lower0_9()) or not. If not,
|
||||
%% halt execution with a non-zero error code, if so then return `ok'.
|
||||
|
||||
valid_realm(Realm) ->
|
||||
case valid_lower0_9(Realm) of
|
||||
true ->
|
||||
ok;
|
||||
false ->
|
||||
ok = log(error, "Bad realm name."),
|
||||
halt(1)
|
||||
end.
|
||||
|
||||
|
||||
@ -776,25 +826,6 @@ add_package(Realm, Name) ->
|
||||
halt(0).
|
||||
|
||||
|
||||
list_resigns(Realm) ->
|
||||
Socket = connect_auth_or_die(Realm),
|
||||
ok = send(Socket, {list_resigns, Realm}),
|
||||
case recv_or_die(Socket) of
|
||||
{ok, []} ->
|
||||
Message = "No packages pending signature in ~tp.",
|
||||
ok = log(info, Message, [Realm]),
|
||||
halt(0);
|
||||
{ok, PackageIDs} ->
|
||||
Print =
|
||||
fun(PackageID) ->
|
||||
PackageString = package_string(PackageID),
|
||||
io:format("~ts~n", [PackageString])
|
||||
end,
|
||||
ok = lists:foreach(Print, PackageIDs),
|
||||
halt(0)
|
||||
end.
|
||||
|
||||
|
||||
add_packager(Package, UserName) ->
|
||||
ok = log(info, "Would add ~ts to packagers for ~160tp now.", [UserName, Package]),
|
||||
halt(0).
|
||||
@ -805,34 +836,34 @@ add_maintainer(Package, UserName) ->
|
||||
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,
|
||||
review(PackageString) ->
|
||||
PackageID = package_id(PackageString),
|
||||
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),
|
||||
sending = recv_or_die(Socket),
|
||||
{ok, ZrpBin} = recv_or_die(Socket),
|
||||
ok = disconnect(Socket),
|
||||
{"zomp.meta", MetaBin} = erl_tar:extract(ZrpBin, [memory, {files, "zomp.meta"}]),
|
||||
{ok, Files} = erl_tar:extract({binary, ZrpBin}, [memory]),
|
||||
{"zomp.meta", MetaBin} = lists:keyfind("zomp.meta", 1, Files),
|
||||
Meta = binary_to_term(MetaBin, [safe]),
|
||||
|
||||
PackageID = maps:get(package_id, Meta),
|
||||
{KeyID, Signature} = maps:get(sig, Meta),
|
||||
{ok, PubKey} = loadkey(public, KeyID),
|
||||
TgzFile = PackageString ++ ".tgz",
|
||||
{TgzFile, TgzData} = lists:keyfind(TgzFile, 1, Files),
|
||||
ok = verify(TgzData, Signature, PubKey),
|
||||
ok =
|
||||
case file:make_dir(PackageString) of
|
||||
ok ->
|
||||
log(info, "Will unpack to directory ./~ts", [PackageString]);
|
||||
{error, Error} ->
|
||||
Message = "Creating dir ./~ts failed with ~ts. Aborting."
|
||||
ok = log(error, Message, [PackageString, Error]),
|
||||
halt(1)
|
||||
end,
|
||||
ok = erl_tar:extract({binary, TgzData}, [compressed, {cwd, PackageString}]),
|
||||
ok = log(info, "Unpacked and awaiting inspection."),
|
||||
halt(0).
|
||||
|
||||
|
||||
approve(PackageID = {Realm, _, _}) ->
|
||||
@ -851,8 +882,36 @@ reject(PackageID = {Realm, _, _}) ->
|
||||
halt(0).
|
||||
|
||||
|
||||
resign(PackageID) ->
|
||||
M = "Pull the indicated package",
|
||||
resign(PackageString) ->
|
||||
PackageID = {Realm, _, _} = package_id(PackageString),
|
||||
Socket = connect_auth_or_die(Realm),
|
||||
ok = send(Socket, {resign, PackageID}),
|
||||
sending = recv_or_die(Socket),
|
||||
{ok, ZrpBin} = recv_or_die(Socket),
|
||||
{ok, Files} = erl_tar:extract({binary, ZrpBin}, [memory]),
|
||||
{"zomp.meta", MetaBin} = lists:keyfind("zomp.meta", 1, Files),
|
||||
Meta = binary_to_term(MetaBin, [safe]),
|
||||
PackageID = maps:get(package_id, Meta),
|
||||
{KeyID, Signature} = maps:get(sig, Meta),
|
||||
{ok, PubKey} = loadkey(public, KeyID),
|
||||
TgzFile = PackageString ++ ".tgz",
|
||||
{TgzFile, TgzData} = lists:keyfind(TgzFile, 1, Files),
|
||||
ok = verify(TgzData, Signature, PubKey),
|
||||
RealmConf = read_realm_conf(Realm),
|
||||
{package_keys, PackageKeys} = lists:keyfind(package_keys, 1, RealmConf),
|
||||
PackageKeyName = select(PackageKeys),
|
||||
PackageKeyID = {Realm, PackageKeyName}
|
||||
{ok, PackageKey} = loadkey(private, PackageKeyID),
|
||||
ReSignature = public_key:sign(TgzData, sha512, PackageKey),
|
||||
FinalMeta = maps:put(sig, {PackageKeyID, ReSignature}),
|
||||
NewFiles = lists:keystore("zomp.meta", 1, term_to_binary(FinalMeta)),
|
||||
ResignedZrp = PackageString ++ ".zrp",
|
||||
ok = erl_tar:create(ResignedZrp, NewFiles),
|
||||
{ok, ResignedBin} = file:read_file(ResignedFile),
|
||||
ok = send(Socket, {resigned, ResignedBin}),
|
||||
ok = recv_or_die(Socket),
|
||||
ok = file:delete(ResignedZrp),
|
||||
ok = disconnect(Socket),
|
||||
ok = log(info, M, [PackageID]),
|
||||
halt(0).
|
||||
|
||||
@ -2392,7 +2451,7 @@ install(PackageID) ->
|
||||
{TgzFile, TgzData} = lists:keyfind(TgzFile, 1, Files),
|
||||
{"zomp.meta", MetaBin} = lists:keyfind("zomp.meta", 1, Files),
|
||||
Meta = binary_to_term(MetaBin),
|
||||
{sig, {KeyID, Signature}} = lists:keyfind(sig, 1, Meta),
|
||||
{KeyID, Signature} = maps:get(sig, 1, Meta),
|
||||
{ok, PubKey} = loadkey(public, KeyID),
|
||||
ok = ensure_package_dirs(PackageID),
|
||||
PackageDir = filename:join("lib", PackageString),
|
||||
@ -3052,15 +3111,28 @@ usage() ->
|
||||
T = "~n"
|
||||
"zx~n"
|
||||
"~n"
|
||||
"Usage:~n"
|
||||
"Usage: zx [command] [object] [args]~n"
|
||||
"~n"
|
||||
"Examples:~n"
|
||||
" zx help~n"
|
||||
" zx run~n"
|
||||
" zx run PackageID [Args]~n"
|
||||
" zx init Type PackageID~n"
|
||||
" zx install PackageID~n"
|
||||
" zx set dep PackageID~n"
|
||||
" zx set version Version~n"
|
||||
" zx list realms~n"
|
||||
" zx list packages Realm~n"
|
||||
" zx list versions PackageName~n"
|
||||
" zx list pending PackageName~n"
|
||||
" zx list resigns Realm~n"
|
||||
" zx add realm RealmFile~n"
|
||||
" zx add package PackageName~n"
|
||||
" zx add packager PackageName~n"
|
||||
" zx add maintainer PackageName~n"
|
||||
" zx review PackageID~n"
|
||||
" zx approve PackageID~n"
|
||||
" zx reject PackageID~n"
|
||||
" zx resign PackageID~n"
|
||||
" zx drop dep PackageID~n"
|
||||
" zx drop key Realm KeyName~n"
|
||||
" zx drop realm Realm~n"
|
||||
@ -3068,6 +3140,7 @@ usage() ->
|
||||
" zx runlocal [Args]~n"
|
||||
" zx package [Path]~n"
|
||||
" zx submit Path~n"
|
||||
" zx create user Realm Username~n"
|
||||
" zx create keypair~n"
|
||||
" zx create plt~n"
|
||||
" zx create realm~n"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user