This commit is contained in:
Craig Everett 2017-11-15 21:01:56 +09:00
parent 3e3f72359a
commit a1af4182ee

196
zx
View File

@ -144,44 +144,13 @@ run(Identifier, Args) ->
State = #s{realm = Realm,
name = Name,
version = Version},
NextState = #s{version = Installed} = ensure_installed(State),
NewState = #s{version = Installed} = ensure_installed(State),
PackageID = {Realm, Name, Installed},
Dir = filename:join("lib", package_string(PackageID)),
Meta = read_meta(Dir),
Deps = maps:get(deps, Meta),
NewState = ensure_deps(NextState#s{dir = Dir, deps = Deps}),
execute(NewState).
% Required = [PackageID | Deps],
% Needed = scrub(Required),
% Host = {"localhost", 11411},
% Socket = connect(Host, user),
% ok = fetch(Socket, Needed),
% ok = lists:foreach(fun install/1, Needed),
% ok = lists:foreach(fun build/1, Required),
% ok = file:set_cwd(PackageRoot),
% case maps:get(type, Meta) of
% app ->
% true = register(zx, self()),
% ok = inets:start(),
% ok = log(info, "Starting ~ts", [package_string(PackageID)]),
% PackageMod = list_to_atom(Name),
% {ok, Pid} = PackageMod:start(normal, Args),
% Mon = monitor(process, Pid),
% Shell = spawn(shell, start, []),
% ok = log(info, "Your shell is ~p, application is: ~p", [Shell, Pid]),
% State = #s{realm = Realm,
% name = Name,
% version = Version,
% pid = Pid,
% mon = Mon},
% exec_wait(State);
% lib ->
% Message = "Lib ~ts is available on the system, but is not a standalone app.",
% ok = log(info, Message, [package_string(PackageID)]),
% halt(0)
% end.
ok = ensure_deps(Deps),
execute(NewState#s{dir = Dir, deps = Deps}).
@ -348,10 +317,10 @@ ensure_installed(State = #s{realm = Realm, name = Name, version = Version}) ->
| exact
| {ok, Installed :: version()}.
%% @private
%% Resolve the provided PackageID to the latest matching installed package directory version
%% if one exists, returning a value that indicates whether an exact match was found (in the
%% case of a full version input), a version matching a partial version input was found, or no
%% match was found at all.
%% Resolve the provided PackageID to the latest matching installed package directory
%% version if one exists, returning a value that indicates whether an exact match was
%% found (in the case of a full version input), a version matching a partial version
%% input was found, or no match was found at all.
resolve_installed_version(PackageID) ->
PackageString = package_string(PackageID),
@ -371,35 +340,52 @@ resolve_installed_version(PackageID) ->
end.
ensure_deps(State = #s{realm = Realm, deps = Deps, socket = MaybeSocket}) ->
ensure_deps(Deps) ->
case scrub(Deps) of
[] ->
State;
ok;
Needed ->
Sorted = lists:sort(Needed),
Partition =
fun(D = {R, _, _}, M) ->
maps:update_with(R, fun(Ds) -> [D | Ds] end, [D], M)
Partitioned = partition_by_realm(Needed),
EnsureDeps =
fun({Realm, Packages}) ->
Socket = connect_user(Realm),
ok = ensure_deps(Socket, Realm, Packages),
ok = disconnect(Socket),
log(info, "Disconnecting from realm: ~ts", [Realm]),
end,
Partitioned = lists:foldl(Partition, #{}, Needed),
lists:foreach(EnsureDeps, Partitioned)
end.
-spec ensure_dep(package_id()) -> ok | no_return().
partition_by_realm(PackageIDs) ->
Sorted = lists:sort(Needed),
PartitionMap = lists:foldl(fun partition_by_realm/2, #{}, Needed),
maps:to_list(PartitionMap).
partition_by_realm({R, P, V}, M) ->
maps:update_with(R, fun(Ps) -> [{P, V} | Ps] end, [{P, V}], M).
ensure_deps(_, _, []) ->
ok;
ensure_deps(Socket, Realm, [{Name, Version} | Rest]) ->
ok = ensure_dep(Socket, {Realm, Name, Version}),
ensure_deps(Socket, Realm, Rest).
-spec ensure_dep(gen_tcp:socket(), package_id()) -> ok | no_return().
%% @private
%% Given an PackageID as an argument, check whether its package file exists in the
%% system cache, and if not download it. Should return `ok' whenever the file is
%% sourced, but exit with an error if it cannot locate or acquire the package.
ensure_dep(PackageID) ->
ensure_dep(Socket, PackageID) ->
ZrpFile = filename:join("zrp", namify_zrp(PackageID)),
ok =
case filelib:is_regular(ZrpFile) of
true ->
ok;
false ->
PackageString = package_string(PackageID),
log(error, "Would fetch ~ts now, but not implemented", [PackageString]),
halt(0)
true -> ok;
false -> fetch(Socket, PackageID)
end,
install(PackageID).
@ -576,10 +562,9 @@ verup(_) -> usage_exit(22).
run_local(Args) ->
Meta = read_meta(),
{package_id, PackageID} = lists:keyfind(package_id, 1, Meta),
{Realm, Name, Version} = PackageID,
{type, Type} = lists:keyfind(type, 1, Meta),
{deps, Deps} = lists:keyfind(deps, 1, Meta),
{Realm, Name, Version} = maps:get(package_id, Meta),
Type = maps:get(type, Meta),
Deps = maps:get(deps, Meta),
ok = build(),
{ok, Dir} = file:get_cwd(),
ok = file:set_cwd(zomp_dir()),
@ -589,12 +574,8 @@ run_local(Args) ->
type = Type,
deps = Deps,
dir = Dir},
NewState = ensure_deps(State),
execute(State).
ensure_deps(Deps, State) ->
ok = ensure_deps(Deps),
ok = file:set_cwd(Dir),
execute(State).
@ -613,23 +594,14 @@ execute(State = #s{type = app}) ->
pid = Pid,
mon = Mon},
exec_wait(State);
execute(State = #s{type = lib}) ->
execute(State = #s{type = lib, realm = Realm, name = Name, version = Version}) ->
Message = "Lib ~ts is available on the system, but is not a standalone app",
ok = log(info, Message, [package_string(PackageID)]),
PackageString = package_string({Realm, Name, Version}),
ok = log(info, Message, [PackageString]),
halt(0).
% Needed = scrub(Deps),
% Host = {"localhost", 11411},
% Socket = connect(Host, user),
% ok = fetch(Socket, Needed),
% ok = lists:foreach(fun install/1, Needed),
% ok = lists:foreach(fun build/1, Deps),
% ok = file:set_cwd(ProjectRoot),
%%% Package generation
-spec package(TargetDir) -> no_return()
@ -1443,53 +1415,45 @@ verify(Data, Signature, PubKey) ->
end.
-spec fetch(gen_tcp:socket(), [package_id()]) -> ok.
-spec fetch(gen_tcp:socket(), package_id()) -> ok.
%% @private
%% Download a list of deps to the local package cache.
%% Download a package to the local cache.
fetch(Socket, Needed) ->
Namified = lists:map(fun namify_zrp/1, Needed),
{Have, Lack} = lists:partition(fun filelib:is_regular/1, Namified),
ok = lists:foreach(fun(A) -> log(info, "Have ~ts", [A]) end, Have),
ok = lists:foreach(fun(A) -> log(info, "Lack ~ts", [A]) end, Lack),
ok = send(Socket, "Would be sending fetch requests now."),
log(info, "Done fake fetching").
fetch(Socket, PackageID) ->
ok = send(Socket, {fetch, PackageID}),
ok = await_zrp(Socket, PackageID),
ok = receive_zrp(Socket, PackageID),
log(info, "Fetched ~ts", [package_string(PackageID)]).
% Grouped = group_by_realm(Needed),
% Realms = [R || {R, _} <- Grouped],
% Sockets = connect(Realms),
% fetch(Sockets, Groups).
%
%
%-spec group_by_realm(AppIDs) -> GroupedAppIDs
% when AppIDs :: [app_id()],
% GroupedAppIDs :: [{realm(), [app_id()]}].
%%% @private
%%% Group apps by realm.
%
%group_by_realm(AppIDs) ->
% Group =
% fun(AppID = {Realm, _, _}, Groups) ->
% case lists:keyfind(Realm, Groups) of
% {Realm, Members} ->
% lists:keystore(Realm, 1, Groups, {Realm, [AppID | Members]});
% false ->
% lists:keystore(Realm, 1, Groups, {Realm, [AppID]})
% end
% end,
% lists:foldl(Group, AppIDs).
%
%
% ZrpFile = namify_zrp(AppID),
% case filelib:is_regular(filename:join("zrp", ZrpFile)) of
% true ->
% log(info, "Found in cache: ~ts", [ZrpFile]);
% false ->
% log(info, "Would download: ~ts", [ZrpFile])
% end.
await_zrp(Socket, PackageID) ->
receive
{tcp, Socket, Bin} ->
case binary_to_term(Bin, [safe]) of
sending ->
ok;
Error = {error, Reason} ->
PackageString = package_string(PackageID),
Message = "Error receiving package ~ts: ~tp",
ok = log(info, Message, [PackageString, Reason]),
Error
after 60000 ->
{error, timeout}
end.
receive_zrp(Socket, PackageID) ->
receive
{tcp, Socket, Bin} ->
ZrpPath = filename:join("zrp", namify_zrp(PackageID)),
ok = file:write_file(ZrpPath, Bin),
ok = send(Socket, ok),
log(info, "Wrote ~ts", [ZrpPath])
after 60000 ->
ok = log(error, "Timeout in socket receive for ~tp", [PackageID]),
{error, timeout}
end.
%%% Utility functions