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"]) ->
|
start(["list", "realms"]) ->
|
||||||
list_realms();
|
list_realms();
|
||||||
start(["list", "packages", Realm]) ->
|
start(["list", "packages", Realm]) ->
|
||||||
case valid_lower0_9(Realm) of
|
ok = valid_realm(Realm),
|
||||||
true ->
|
list_packages(Realm);
|
||||||
list_packages(Realm);
|
|
||||||
false ->
|
|
||||||
ok = log(error, "Bad realm name."),
|
|
||||||
halt(1)
|
|
||||||
end;
|
|
||||||
start(["list", "versions", Package]) ->
|
start(["list", "versions", Package]) ->
|
||||||
case string:lexemes(Package, "-") of
|
Package = string_to_package(PackageName),
|
||||||
[Realm, Name] ->
|
list_versions(Package);
|
||||||
list_versions({Realm, Name});
|
start(["list", "pending", PackageName]) ->
|
||||||
_ ->
|
Package = string_to_package(PackageName),
|
||||||
ok = log(error, "Bad package name."),
|
list_pending(Package);
|
||||||
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]) ->
|
start(["list", "resigns", Realm]) ->
|
||||||
case valid_lower0_9(Realm) of
|
ok = valid_realm(Realm),
|
||||||
true ->
|
list_resigns(Realm);
|
||||||
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]) ->
|
||||||
@ -130,8 +110,7 @@ start(["add", "packager", Package, UserName]) ->
|
|||||||
start(["add", "maintainer", Package, UserName]) ->
|
start(["add", "maintainer", Package, UserName]) ->
|
||||||
add_maintainer(Package, UserName);
|
add_maintainer(Package, UserName);
|
||||||
start(["review", PackageString]) ->
|
start(["review", PackageString]) ->
|
||||||
PackageID = package_id(PackageString),
|
review(PackageString);
|
||||||
review(PackageID);
|
|
||||||
start(["approve", PackageString]) ->
|
start(["approve", PackageString]) ->
|
||||||
PackageID = package_id(PackageString),
|
PackageID = package_id(PackageString),
|
||||||
approve(PackageID);
|
approve(PackageID);
|
||||||
@ -167,6 +146,8 @@ start(["submit", PackageFile]) ->
|
|||||||
submit(PackageFile);
|
submit(PackageFile);
|
||||||
start(["dialyze"]) ->
|
start(["dialyze"]) ->
|
||||||
dialyze();
|
dialyze();
|
||||||
|
start(["create", "user", Realm, Name]) ->
|
||||||
|
create_user(Realm, Name);
|
||||||
start(["create", "keypair"]) ->
|
start(["create", "keypair"]) ->
|
||||||
create_keypair();
|
create_keypair();
|
||||||
start(["create", "plt"]) ->
|
start(["create", "plt"]) ->
|
||||||
@ -634,6 +615,10 @@ list_packages(Realm) ->
|
|||||||
|
|
||||||
|
|
||||||
-spec list_versions(package()) -> no_return().
|
-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}) ->
|
list_versions(Package = {Realm, Name}) ->
|
||||||
ok = valid_package(Package),
|
ok = valid_package(Package),
|
||||||
@ -656,6 +641,10 @@ list_versions(Package = {Realm, Name}) ->
|
|||||||
|
|
||||||
|
|
||||||
-spec list_pending(package()) -> no_return().
|
-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}) ->
|
list_pending(Package = {Realm, Name}) ->
|
||||||
ok = valid_package(Package),
|
ok = valid_package(Package),
|
||||||
@ -677,7 +666,34 @@ list_pending(Package = {Realm, Name}) ->
|
|||||||
end.
|
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().
|
-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}) ->
|
valid_package({Realm, Name}) ->
|
||||||
case {valid_lower0_9(Realm), valid_lower0_9(Name)} of
|
case {valid_lower0_9(Realm), valid_lower0_9(Name)} of
|
||||||
@ -692,6 +708,40 @@ valid_package({Realm, Name}) ->
|
|||||||
{false, false} ->
|
{false, false} ->
|
||||||
ok = log(error, "Invalid realm ~tp and package ~tp", [Realm, Name]),
|
ok = log(error, "Invalid realm ~tp and package ~tp", [Realm, Name]),
|
||||||
halt(1)
|
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.
|
end.
|
||||||
|
|
||||||
|
|
||||||
@ -776,25 +826,6 @@ add_package(Realm, Name) ->
|
|||||||
halt(0).
|
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) ->
|
add_packager(Package, UserName) ->
|
||||||
ok = log(info, "Would add ~ts to packagers for ~160tp now.", [UserName, Package]),
|
ok = log(info, "Would add ~ts to packagers for ~160tp now.", [UserName, Package]),
|
||||||
halt(0).
|
halt(0).
|
||||||
@ -805,34 +836,34 @@ add_maintainer(Package, UserName) ->
|
|||||||
halt(0).
|
halt(0).
|
||||||
|
|
||||||
|
|
||||||
review(PackageID) ->
|
review(PackageString) ->
|
||||||
PackageString = package_string(PackageID),
|
PackageID = package_id(PackageString),
|
||||||
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(),
|
Socket = connect_auth_or_die(),
|
||||||
ok = send(Socket, {review, PackageID}),
|
ok = send(Socket, {review, PackageID}),
|
||||||
ok = receive_or_die(Socket),
|
sending = recv_or_die(Socket),
|
||||||
{ok, ZrpBin} = recieve_or_die(Socket),
|
{ok, ZrpBin} = recv_or_die(Socket),
|
||||||
ok = file:write_file(ZrpPath, ZrpBin),
|
|
||||||
ok = disconnect(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]),
|
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, _, _}) ->
|
approve(PackageID = {Realm, _, _}) ->
|
||||||
@ -851,8 +882,36 @@ reject(PackageID = {Realm, _, _}) ->
|
|||||||
halt(0).
|
halt(0).
|
||||||
|
|
||||||
|
|
||||||
resign(PackageID) ->
|
resign(PackageString) ->
|
||||||
M = "Pull the indicated package",
|
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]),
|
ok = log(info, M, [PackageID]),
|
||||||
halt(0).
|
halt(0).
|
||||||
|
|
||||||
@ -2392,7 +2451,7 @@ install(PackageID) ->
|
|||||||
{TgzFile, TgzData} = lists:keyfind(TgzFile, 1, Files),
|
{TgzFile, TgzData} = lists:keyfind(TgzFile, 1, Files),
|
||||||
{"zomp.meta", MetaBin} = lists:keyfind("zomp.meta", 1, Files),
|
{"zomp.meta", MetaBin} = lists:keyfind("zomp.meta", 1, Files),
|
||||||
Meta = binary_to_term(MetaBin),
|
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, PubKey} = loadkey(public, KeyID),
|
||||||
ok = ensure_package_dirs(PackageID),
|
ok = ensure_package_dirs(PackageID),
|
||||||
PackageDir = filename:join("lib", PackageString),
|
PackageDir = filename:join("lib", PackageString),
|
||||||
@ -3052,15 +3111,28 @@ usage() ->
|
|||||||
T = "~n"
|
T = "~n"
|
||||||
"zx~n"
|
"zx~n"
|
||||||
"~n"
|
"~n"
|
||||||
"Usage:~n"
|
"Usage: zx [command] [object] [args]~n"
|
||||||
|
"~n"
|
||||||
|
"Examples:~n"
|
||||||
" zx help~n"
|
" zx help~n"
|
||||||
" zx run~n"
|
|
||||||
" zx run PackageID [Args]~n"
|
" zx run PackageID [Args]~n"
|
||||||
" zx init Type PackageID~n"
|
" zx init Type PackageID~n"
|
||||||
" zx install PackageID~n"
|
" zx install PackageID~n"
|
||||||
" zx set dep PackageID~n"
|
" zx set dep PackageID~n"
|
||||||
" zx set version Version~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 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 dep PackageID~n"
|
||||||
" zx drop key Realm KeyName~n"
|
" zx drop key Realm KeyName~n"
|
||||||
" zx drop realm Realm~n"
|
" zx drop realm Realm~n"
|
||||||
@ -3068,6 +3140,7 @@ usage() ->
|
|||||||
" zx runlocal [Args]~n"
|
" zx runlocal [Args]~n"
|
||||||
" zx package [Path]~n"
|
" zx package [Path]~n"
|
||||||
" zx submit Path~n"
|
" zx submit Path~n"
|
||||||
|
" zx create user Realm Username~n"
|
||||||
" zx create keypair~n"
|
" zx create keypair~n"
|
||||||
" zx create plt~n"
|
" zx create plt~n"
|
||||||
" zx create realm~n"
|
" zx create realm~n"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user