Add "swp" (Service->Worker Pattern) templater
This commit is contained in:
parent
378a30e112
commit
45fb16f5ea
@ -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.11.4
|
||||
version=0.11.6
|
||||
zx="zx-$version"
|
||||
tarball="$zx.tar.gz"
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
0.11.7
|
||||
0.12.0
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{application,zx,
|
||||
[{description,"An Erlang development tool and Zomp user client"},
|
||||
{vsn,"0.11.7"},
|
||||
{vsn,"0.12.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,
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
@ -24,7 +24,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-behavior(application).
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
@ -193,6 +193,9 @@ do(["drop", "mirror", Address, Port]) ->
|
||||
do(["create", "project"]) ->
|
||||
ok = connect(),
|
||||
done(zx_local:create_project());
|
||||
do(["template", "swp"]) ->
|
||||
ok = connect(),
|
||||
done(zx_local:template_swp());
|
||||
do(["runlocal" | ArgV]) ->
|
||||
ok = connect(),
|
||||
not_done(run_local(ArgV));
|
||||
@ -1253,6 +1256,7 @@ usage_user() ->
|
||||
usage_dev() ->
|
||||
"Developer/Packager/Maintainer Actions:~n"
|
||||
" zx create project~n"
|
||||
" zx template swp~n"
|
||||
" zx runlocal [Args]~n"
|
||||
" zx rundir Path [Args]~n"
|
||||
" zx init~n"
|
||||
@ -9,7 +9,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_auth).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
-license("GPL-3.0").
|
||||
@ -7,7 +7,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_conn).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
-license("GPL-3.0").
|
||||
@ -5,7 +5,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_conn_sup).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-behavior(supervisor).
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
@ -138,7 +138,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_daemon).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-behavior(gen_server).
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
@ -412,10 +412,15 @@ unsubscribe(Package = {Realm, Name}) ->
|
||||
gen_server:cast(?MODULE, {unsubscribe, self(), Package}).
|
||||
|
||||
|
||||
-spec list() -> {ok, realm_list()}.
|
||||
-spec list() -> {ok, RequestID}
|
||||
when RequestID :: term().
|
||||
%% @doc
|
||||
%% Request a list of currently configured realms. Because this call is entirely local
|
||||
%% it is the only one that does not involve a round-trip
|
||||
%% This query does not actually require a round trip but is included for completeness
|
||||
%% and convenience when stacking zx_daemon queries into a list for use with
|
||||
%% wait_results/1.
|
||||
%%
|
||||
%% If you only need a list of configured realms and aren't performing a list of queries
|
||||
%% use zx:list/0 instead.
|
||||
|
||||
list() ->
|
||||
request(list).
|
||||
@ -8,7 +8,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_key).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
-license("GPL-3.0").
|
||||
@ -10,7 +10,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_lib).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
-license("GPL-3.0").
|
||||
@ -6,7 +6,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_local).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
-license("GPL-3.0").
|
||||
@ -21,7 +21,7 @@
|
||||
set_timeout/1,
|
||||
add_mirror/0, add_mirror/1, add_mirror/2,
|
||||
drop_mirror/0, drop_mirror/1, drop_mirror/2,
|
||||
create_project/0,
|
||||
create_project/0, template_swp/0,
|
||||
grow_a_pair/0, grow_a_pair/2, drop_key/1,
|
||||
create_user/0, export_user/1, import_user/1,
|
||||
create_realm/0, export_realm/0, export_realm/1]).
|
||||
@ -1484,6 +1484,86 @@ create_project(P = #project{id = {_, Name, Version}}) ->
|
||||
end.
|
||||
|
||||
|
||||
template_swp() ->
|
||||
case find_meta() of
|
||||
{ok, Meta} -> template_swp(Meta);
|
||||
Error -> Error
|
||||
end.
|
||||
|
||||
template_swp(Meta) ->
|
||||
Prefix = maps:get(prefix, Meta),
|
||||
Modules = {_, _, _, Worker} = ask_service_name(Prefix),
|
||||
{_, Name, Version} = maps:get(package_id, Meta),
|
||||
{ok, VersionString} = zx_lib:version_to_string(Version),
|
||||
Credit = maps:get(author, Meta),
|
||||
AEmail = maps:get(a_email, Meta),
|
||||
Holder = maps:get(copyright, Meta),
|
||||
CEmail = maps:get(c_email, Meta),
|
||||
License = maps:get(license, Meta),
|
||||
Substitutions =
|
||||
[{"〘\*PROJECT NAME\*〙", maps:get(name, Meta)},
|
||||
{"〘\*SERVICE\*〙", Worker},
|
||||
{"〘\*CAP SERVICE\*〙", string:titlecase(Worker)},
|
||||
{"〘\*NAME\*〙", Name},
|
||||
{"〘\*VERSION\*〙", VersionString},
|
||||
{"〘\*PREFIX\*〙", Prefix},
|
||||
{"〘\*AUTHOR\*〙", author(Credit, AEmail)},
|
||||
{"〘\*COPYRIGHT\*〙", copyright(Holder, CEmail)},
|
||||
{"〘\*LICENSE\*〙", license(License)}],
|
||||
case template_filenames(Prefix, Modules) of
|
||||
{ok, Templates} -> template_swp(Templates, Substitutions);
|
||||
Error -> Error
|
||||
end.
|
||||
|
||||
template_swp(Templates, Substitutions) ->
|
||||
TemplateDir = filename:join([os:getenv("ZX_DIR"), "templates", "swp"]),
|
||||
Transform =
|
||||
fun({Template, Destination}) ->
|
||||
TemplatePath = filename:join(TemplateDir, Template),
|
||||
{ok, Raw} = file:read_file(TemplatePath),
|
||||
UTF8 = unicode:characters_to_list(Raw, utf8),
|
||||
Cooked = substitute(UTF8, Substitutions),
|
||||
file:write_file(Destination, Cooked)
|
||||
end,
|
||||
lists:foreach(Transform, Templates).
|
||||
|
||||
|
||||
template_filenames(Prefix, Modules) ->
|
||||
Ts = ["workers.erl", "worker_man.erl", "worker_sup.erl", "worker.erl"],
|
||||
Fs = [Prefix ++ "_" ++ S ++ ".erl" || S <- tuple_to_list(Modules)],
|
||||
case lists:any(fun filelib:is_file/1, Fs) of
|
||||
false ->
|
||||
{ok, lists:zip(Ts, Fs)};
|
||||
true ->
|
||||
Format =
|
||||
"The module files ~p would be created by this command.~n"
|
||||
"One or more of these names already exists in the current directory.~n"
|
||||
"Aborting.~n",
|
||||
ok = io:format(Format, [Fs]),
|
||||
{error, "File name conflict."}
|
||||
end.
|
||||
|
||||
|
||||
find_meta() ->
|
||||
{ok, CWD} = file:get_cwd(),
|
||||
find_meta(CWD).
|
||||
|
||||
find_meta(Dir) ->
|
||||
case zx_lib:read_project_meta(Dir) of
|
||||
{ok, Meta} -> {ok, Meta};
|
||||
{error, _, 2} -> dive_down(Dir);
|
||||
Error -> Error
|
||||
end.
|
||||
|
||||
dive_down(Dir) ->
|
||||
case filename:dirname(Dir) of
|
||||
Dir ->
|
||||
{error, "No project zomp.meta file. Wrong directory? Not initialized?", 2};
|
||||
ParentDir ->
|
||||
find_meta(ParentDir)
|
||||
end.
|
||||
|
||||
|
||||
munge_sources(#project{type = lib,
|
||||
id = {_, Name, _},
|
||||
name = ProjectName,
|
||||
@ -1585,7 +1665,8 @@ munge_sources(#project{type = Type,
|
||||
|
||||
transform([Template | Rest], Prefix, Substitutions) ->
|
||||
{ok, Raw} = file:read_file(Template),
|
||||
Data = substitute(Raw, Substitutions),
|
||||
UTF8 = unicode:characters_to_list(Raw, utf8),
|
||||
Data = substitute(UTF8, Substitutions),
|
||||
Path = Prefix ++ filename:basename(Template),
|
||||
ok = file:write_file(Path, Data),
|
||||
transform(Rest, Prefix, Substitutions);
|
||||
@ -1740,8 +1821,8 @@ ask_prefix(Name) ->
|
||||
"in the project are named things like \"es_client\".~n"
|
||||
"Enter the prefix you would like to use below (or enter for the generated "
|
||||
"default).~n",
|
||||
ok = io:format(Instructions),
|
||||
case zx_tty:get_input("[\"~ts\"]", [Default]) of
|
||||
Prompt = io_lib:format("[\"~ts\"]", [Default]),
|
||||
case zx_tty:get_input(Instructions, [], Prompt) of
|
||||
"" ->
|
||||
Default;
|
||||
String ->
|
||||
@ -2292,6 +2373,102 @@ pick_realm() ->
|
||||
end.
|
||||
|
||||
|
||||
-spec ask_service_name(Prefix) -> Modules
|
||||
when Prefix :: string(),
|
||||
Modules :: {Sup :: string(),
|
||||
Man :: string(),
|
||||
WorkerSup :: string(),
|
||||
Worker :: string()}.
|
||||
|
||||
ask_service_name(Prefix) ->
|
||||
Instructions =
|
||||
"~nSERVICE NAME~n"
|
||||
"Enter the name of the service.~n"
|
||||
"Must be a legal module name.~n",
|
||||
case zx_tty:get_input(Instructions) of
|
||||
"" ->
|
||||
ok = io:format("Please enter a service name."),
|
||||
ask_service_name(Prefix);
|
||||
String ->
|
||||
Name = unicode:characters_to_list(String, utf8),
|
||||
ask_service_name2(Prefix, Name)
|
||||
end.
|
||||
|
||||
ask_service_name2(Prefix, Name) ->
|
||||
case zx_lib:valid_lower0_9(Name) of
|
||||
true ->
|
||||
ask_service_name3(Prefix, Name);
|
||||
false ->
|
||||
Message = "Invalid characters. Try something in the range [:a-z0-9:].~n",
|
||||
ok = io:format(Message),
|
||||
ask_service_name(Prefix)
|
||||
end.
|
||||
|
||||
ask_service_name3(Prefix, Worker) ->
|
||||
Sup = Worker ++ "s",
|
||||
Man = Worker ++ "_man",
|
||||
WorkerSup = Worker ++ "_sup",
|
||||
Modules = [Sup, Man, WorkerSup, Worker],
|
||||
Prefixed = [Prefix ++ "_" ++ M || M <- Modules],
|
||||
{ok, Realms} = zx:list(),
|
||||
Combinations = [{R, M} || R <- Realms, M <- Prefixed],
|
||||
Query =
|
||||
fun({Realm, Module}) ->
|
||||
{ok, ID} = zx_daemon:provides(Realm, Module),
|
||||
{ID, Realm, Module}
|
||||
end,
|
||||
Pending = lists:map(Query, Combinations),
|
||||
{ok, Results} = zx_daemon:wait_results([ID || {ID, _, _} <- Pending]),
|
||||
case lists:all(fun({_, {ok, Ps}}) -> Ps == [] end, Results) of
|
||||
true ->
|
||||
list_to_tuple(Modules);
|
||||
false ->
|
||||
Trouble = match(Pending, Results, Prefixed),
|
||||
confirm_service_name(Prefix, Modules, Trouble)
|
||||
end.
|
||||
|
||||
match(Pending, Results, Modules) ->
|
||||
Index = maps:from_list([{M, []} || M <- Modules]),
|
||||
Merge =
|
||||
fun({ID, {ok, Conflicts}}, I) ->
|
||||
{value, {_, Realm, Module}} = lists:keysearch(ID, 1, Pending),
|
||||
maps:put(Module, [{Realm, Conflicts} | maps:get(Module, I)], I)
|
||||
end,
|
||||
lists:foldl(Merge, Index, Results).
|
||||
|
||||
confirm_service_name(Prefix, Modules, Trouble) ->
|
||||
ok = io:format("~nModule name conflicts! OH NOES!!!~n"),
|
||||
ok = lists:foreach(fun show_conflict/1, maps:to_list(Trouble)),
|
||||
Instructions =
|
||||
"~nDECISIONS DECISIONS!~n"
|
||||
"Do you want to use these names anyway?~n"
|
||||
"The name conflict won't be a problem unless you need to include any of "
|
||||
"the conflicting packages as a dependency (now or in the future).~n",
|
||||
case zx_tty:get_input(Instructions, [], "[Y/N]") of
|
||||
"Y" -> list_to_tuple(Modules);
|
||||
"y" -> list_to_tuple(Modules);
|
||||
_ -> ask_service_name(Prefix)
|
||||
end.
|
||||
|
||||
show_conflict({_, []}) ->
|
||||
ok;
|
||||
show_conflict({Module, Packages}) ->
|
||||
Message = "The module name ~tp shows a conflict with the following packages:~n",
|
||||
ok = io:format(Message, [Module]),
|
||||
show_conflict2(Packages).
|
||||
|
||||
show_conflict2([{Realm, Packages} | Rest]) ->
|
||||
Show = fun({Name, Version}) -> show_package({Realm, Name, Version}) end,
|
||||
ok = lists:foreach(Show, Packages),
|
||||
show_conflict2(Rest);
|
||||
show_conflict2([]) ->
|
||||
ok.
|
||||
|
||||
show_package(ID) ->
|
||||
{ok, PackageString} = zx_lib:package_string(ID),
|
||||
io:format("~ts~n", [PackageString]).
|
||||
|
||||
|
||||
-spec ask_project_name() -> string().
|
||||
|
||||
ask_project_name() ->
|
||||
@ -2487,7 +2664,7 @@ edit_tags(Set) ->
|
||||
{"Return", 3}],
|
||||
case zx_tty:select(Options) of
|
||||
1 ->
|
||||
New = string:lowercase(zx_tty:get_input("~nEnter a new tag~n")),
|
||||
New = string:casefold(zx_tty:get_input("~nEnter a new tag~n")),
|
||||
edit_tags(sets:add_element(New, Set));
|
||||
2 ->
|
||||
edit_tags(rem_item(Set));
|
||||
@ -5,7 +5,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_net).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
-license("GPL-3.0").
|
||||
@ -8,7 +8,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_peer).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
-license("GPL-3.0").
|
||||
@ -9,7 +9,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_peer_man).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-behavior(gen_server).
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
@ -6,7 +6,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_peer_sup).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-behaviour(supervisor).
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
@ -10,7 +10,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_peers).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-behavior(supervisor).
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
@ -5,7 +5,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_proxy).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
-license("GPL-3.0").
|
||||
@ -5,7 +5,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_sup).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-behavior(supervisor).
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
@ -6,7 +6,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_tty).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
-license("GPL-3.0").
|
||||
@ -5,7 +5,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_userconf).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
-license("GPL-3.0").
|
||||
@ -7,7 +7,7 @@
|
||||
%%% @end
|
||||
|
||||
-module(zx_zsp).
|
||||
-vsn("0.11.7").
|
||||
-vsn("0.12.0").
|
||||
-author("Craig Everett <zxq9@zxq9.com>").
|
||||
-copyright("Craig Everett <zxq9@zxq9.com>").
|
||||
-license("GPL-3.0").
|
||||
@ -61,6 +61,14 @@ handle_info(Unexpected, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
|
||||
-spec code_change(OldVersion, State, Extra) -> {ok, NewState} | {error, Reason}
|
||||
when OldVersion :: Version | {old, Version},
|
||||
Version :: term(),
|
||||
State :: state(),
|
||||
Extra :: term(),
|
||||
NewState :: term(),
|
||||
Reason :: term().
|
||||
|
||||
code_change(_, State, _) ->
|
||||
{ok, State}.
|
||||
|
||||
@ -80,11 +80,11 @@ handle_info(Unexpected, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
|
||||
handle_down(Mon, PID, Reason, State = #s{clients = Clients}) ->
|
||||
case lists:member(PID, Clients) of
|
||||
handle_down(Mon, PID, Reason, State = #s{〘*SERVICE*〙s = 〘*CAP SERVICE*〙s}) ->
|
||||
case lists:member(PID, 〘*CAP SERVICE*〙s) of
|
||||
true ->
|
||||
NewClients = lists:delete(PID, Clients),
|
||||
State#s{clients = NewClients};
|
||||
New〘*CAP SERVICE*〙s = lists:delete(PID, 〘*CAP SERVICE*〙s),
|
||||
State#s{〘*SERVICE*〙s = New〘*CAP SERVICE*〙s};
|
||||
false ->
|
||||
Unexpected = {'DOWN', Mon, process, PID, Reason},
|
||||
ok = log(warning, "Unexpected info: ~tp", [Unexpected]),
|
||||
@ -9,7 +9,7 @@
|
||||
{license,"MIT"}.
|
||||
{modules,[]}.
|
||||
{name,"zx"}.
|
||||
{package_id,{"otpr","zx",{0,11,7}}}.
|
||||
{package_id,{"otpr","zx",{0,12,0}}}.
|
||||
{prefix,"zx_"}.
|
||||
{repo_url,"https://gitlab.com/zxq9/zx"}.
|
||||
{tags,["tools","package manager","erlang"]}.
|
||||
Loading…
x
Reference in New Issue
Block a user