Browse Source

experimental mad

Namdak Tonpa 9 years ago
parent
commit
2c5f7b3e50

+ 29 - 58
doc/index.tex

@@ -1,5 +1,34 @@
 \section{MAD: Erlang Containers}
 
+\subsection{Purpose}
+We were trying to make something minimalistic that fits out \footahref{https://github.com/synrc}{application stack}.
+The main idea of mad is to provide clean and simple rebar-like fast dependency manager that
+is able to build several types of packages and provides interface of containered deployments
+to virtualiezed environments.
+
+\subsection{Several Types of Packaging}
+The key feature of mad is ability to create single-file bundled web sites.
+This target escript is ready to run on Windows, Linux and Mac.
+
+\subsection{Deployment Options}
+As a deploy tool mad is also supposed to launch, start, stop and manage containers, locally or remote.
+You can make containers from different type of packages, like making runc container with beam release.
+
+\subsection{OTP Compliant}
+Mad supports ERTS boot files generation with systools and erlang application format used by OTP.
+This is the main format of application repository. Also boot files are suported on both LING and BEAM.
+
+\subsection{Tiny Size}
+And the good part:
+
+\vspace{1\baselineskip}
+\begin{lstlisting}
+                      Sources        Binary
+    mad               967 LOC        52 KB
+    rebar             7717 LOC       181 KB
+\end{lstlisting}
+\vspace{1\baselineskip}
+
 \subsection{History}
 
 We came to conclusion that no matter how perfect your libraries are,
@@ -44,61 +73,3 @@ In a month I forked mad and took over the development under the same name.
     mad compile                    2.521s
 \end{lstlisting}
 \vspace{1\baselineskip}
-
-\subsection{Introduction}
-
-We were trying to make something minimalistic that fits out \footahref{https://github.com/synrc}{Web Stack}.
-Besides we wanted to use our knowledge of other build tools like lein, sbt etc.
-Also for sure we tried sinan, ebt, Makefile-based scripts.
-
-Synrc mad has a simple interface as follows:
-
-\vspace{1\baselineskip}
-\begin{lstlisting}
-  BNF:
-      invoke := mad params
-      params := [] | run params
-         run := command [ options ]
-     command := app | lib | deps | compile | bundle
-                start | stop | repl
-\end{lstlisting}
-\vspace{1\baselineskip}
-
-It seems to us more natural, you can specify random
-commands set with different specifiers (options).
-
-\subsection{Several Types of Packaging}
-
-The key feature of mad is ability to create single-file bundled web sites.
-Thus making dream to boot simpler than node.js come true.
-This target escript is ready to run on Windows, Linux and Mac.
-
-\subsection{Deployment Options}
-
-mad is also supposed to be a deploy tool with ability to
-deploy not only to our resources like Erlang on Xen, Voxoz (LXC/Xen) but
-also to Heroku and others.
-
-\subsection{OTP Compliant}
-
-mad supports rebar umbrella project structure.
-Specifically two kinds of directory layouts:
-
-\subsection{Fast Apps Ordering}
-
-As you may know you can create OTP releases with
-reltool (rebar generate) or systools (relx). mad currently
-creates releases with relx but is going to do it independently soon.
-Now it can only order applications.
-
-\subsection{Tiny Size}
-
-And the good part:
-
-\vspace{1\baselineskip}
-\begin{lstlisting}
-                      Sources        Binary
-    mad               567 LOC        39 KB
-    rebar             7717 LOC       181 KB
-\end{lstlisting}
-\vspace{1\baselineskip}

+ 1 - 1
include/mad.hrl

@@ -1 +1 @@
--define(VERSION,"9b8533").
+-define(VERSION,"801fac").

BIN
mad


+ 1 - 1
src/compilation/mad_app.erl → src/compile/mad_app.erl

@@ -33,7 +33,7 @@ add_modules_property(Properties) ->
         {modules, _} -> Properties;
         _ -> Properties ++ [{modules, []}] end.
 
-apps(AppName) -> {ok,Apps} = mad_plan:orderapps(), {applications,Apps -- [AppName]}.
+apps(AppName) -> {ok,Apps} = mad_resolve:orderapps(), {applications,Apps -- [AppName]}.
 generate_deps(AppName,Properties) ->
     case lists:keyfind(applications, 1, Properties) of
          false -> Properties ++ [apps(AppName)];

+ 1 - 1
src/compilation/mad_compile.erl → src/compile/mad_compile.erl

@@ -14,7 +14,7 @@ compile(Params) ->
 
 deps(_, _, _, []) -> {ok,deps};
 deps(Cwd, Conf, ConfigFile, [H|T]) ->
-    {Name, _} = mad_deps:name_and_repo(H),
+    {Name, _} = mad_utils:name_and_repo(H),
     Res = case get(Name) == compiled of
           true -> {ok,[]};
           _    -> dep(Cwd, Conf, ConfigFile, Name) end,

+ 0 - 0
src/compilation/mad_dtl.erl → src/compile/mad_dtl.erl


+ 0 - 0
src/compilation/mad_erl.erl → src/compile/mad_erl.erl


+ 0 - 0
src/compilation/mad_leex.erl → src/compile/mad_leex.erl


+ 0 - 0
src/compilation/mad_none.erl → src/compile/mad_none.erl


+ 0 - 0
src/compilation/mad_port.erl → src/compile/mad_port.erl


+ 0 - 0
src/compilation/mad_script.erl → src/compile/mad_script.erl


+ 0 - 0
src/compilation/mad_yecc.erl → src/compile/mad_yecc.erl


+ 0 - 139
src/launching/mad_repl.erl

@@ -1,139 +0,0 @@
--module(mad_repl).
--copyright('Maxim Sokhatsky').
--compile(export_all).
-
-disabled() -> [].
-system() -> [compiler,syntax_tools,sasl,tools,mnesia,reltool,xmerl,crypto,kernel,stdlib,ssh,eldap,
-             wx,webtool,ssl,runtime_tools,public_key,observer,inets,asn1,et,eunit,hipe,os_mon].
-
-local_app() ->
-    case filename:basename(filelib:wildcard("ebin/*.app"),".app") of
-         [] -> [];
-         A -> list_to_atom(A) end.
-
-applist() ->
-    Name = ".applist",
-    case file:read_file(Name) of
-         {ok,Binary} -> parse_applist(Binary); 
-         {error,_} ->
-           case mad_repl:load_file(Name) of
-              {error,_} -> mad_plan:main([]);
-              {ok,Plan} -> parse_applist(Plan) end end.
-
-wildcards(List) -> lists:concat([filelib:wildcard(X)||X<-List]).
-
-parse_applist(AppList) ->
-   Res = string:tokens(string:strip(string:strip(binary_to_list(AppList),right,$]),left,$[),","),
-   [ list_to_atom(R) || R <-Res ]  -- disabled().
-
-load_config() ->
-   Config = wildcards(["sys.config"]),
-   Apps = case Config of
-        [] -> case mad_repl:load_file("sys.config") of
-              {error,_} -> [];
-              {ok,Bin} -> parse(binary_to_list(Bin)) end;
-      File -> case file:consult(File) of
-              {error,_} -> [];
-              {ok,[A]} -> A end end,
- [ begin [ application:set_env(App,K,V) || {K,V} <- Cfg ], {App,Cfg} end || {App,Cfg} <- Apps ].
-
-acc_start(A,Acc) ->
-   case application:start(A) of
-         {error,{already_started,_}} -> Acc;
-         {error,{_,{{M,_F,_},_Ret}}} -> [M|Acc];
-         {error,{_Reason,Name}} when is_atom(_Reason) -> [Name|Acc];
-         ok -> Acc;
-         _  -> Acc end.
-
-load_apps([],_,_Acc) ->
-  Res = lists:foldl(fun(A,Acc) -> case lists:member(A,system()) of
-       true -> acc_start(A,Acc);
-          _ -> case load_config(A) of
-                    [] -> acc_start(A,Acc);
-                    _E -> acc_start(_E,Acc) end end end,[], applist()),
-  case Res of
-       [] -> ok;
-       _ -> mad:info("~nApps couldn't be loaded: ~p~n",[Res]) end;
-load_apps(["applist"],Config,Acc) -> load_apps([],Config,Acc);
-load_apps(Params,_,_Acc) -> [ application:ensure_all_started(list_to_atom(A))||A<-Params].
-
-cwd() -> case  file:get_cwd() of {ok, Cwd} -> Cwd; _ -> "." end.
-
-sh(Params) ->
-    { _Cwd,_ConfigFileName,_Config } = mad_utils:configs(),
-    mad_plan:main([]),
-    SystemPath = filelib:wildcard(code:root_dir() ++ "/lib/{"
-              ++ string:join([atom_to_list(X)||X<-mad_repl:system()],",") ++ "}-*/ebin"),
-    UserPath   = wildcards(["{apps,deps}/*/ebin","ebin"]),
-    code:set_path(SystemPath++UserPath),
-    code:add_path(filename:join([cwd(),filename:basename(escript:script_name())])),
-    load(),
-    Config = load_config(),
-    Driver = mad_utils:get_value(shell_driver,_Config,user_drv),
-    pre(Driver),
-    case os:type() of
-         {win32,nt} -> shell:start();
-                  _ -> Driver:start() end,
-    post(Driver),
-    load_apps(Params,Config,[]),
-    case Params of
-        ["applist"] -> skip;
-        _ ->  timer:sleep(infinity) end.
-
-load() ->
-    ets_created(),
-    {ok,Sections} = escript:extract(escript:script_name(),[]),
-    [Bin] = [B||{archive,B}<-Sections],
-    unfold_zips(Bin).
-
-unfold_zips(Bin) ->
-    {ok,Unzip} = zip:unzip(Bin,[memory]),
-    [ begin
-        ets:insert(filesystem,{U,FileBin}),
-        case U of
-            "static.gz" -> unfold_zips(FileBin);
-            _ -> skip end
-      end || {U,FileBin} <- Unzip].
-
-ets_created() ->
-    case ets:info(filesystem) of
-         undefined -> ets:new(filesystem,[set,named_table,{keypos,1},public]);
-         _ -> skip end.
-
-load_file(Name)  ->
-    ets_created(),
-    case ets:lookup(filesystem,Name) of
-        [{Name,Bin}] -> {ok,Bin};
-        _ -> {error,etsfs} end.
-
-load_config(A) when is_atom(A) -> load_config(atom_to_list(A));
-load_config(A) when is_list(A) ->
-    AppFile = A ++".app",
-    Name = wildcards(["{apps,deps}/*/ebin/"++AppFile,"ebin/"++AppFile]),
-    case file:read_file(Name) of
-         {ok,Bin} -> parse(binary_to_list(Bin));
-         {error,_} -> case ets:lookup(filesystem,AppFile) of
-                          [{Name,Bin}] -> parse(binary_to_list(Bin));
-                          _ -> [] end end.
-
-parse(String) ->
-    {ok,Tokens,_EndLine} = erl_scan:string(String),
-    {ok,AbsForm} = erl_parse:parse_exprs(Tokens),
-    {value,Value,_Bs} = erl_eval:exprs(AbsForm, erl_eval:new_bindings()),
-    Value.
-
-% we need to call printing before starting driver for user_drv
-% but for start_kjell we should call after, that's why we have pre and post here.
-
-pre(start_kjell) -> [];
-pre(user_drv) -> unregister(user), appconfig(user_drv);
-pre(Driver) -> appconfig(Driver).
-post(start_kjell) -> appconfig(start_kjell);
-post(_) -> [].
-print(Label,Value,start_kjell) -> io:requests([{put_chars,Label ++ normalize(length(Label)+1,Value) ++ "\n\r"}]);
-print(Label,Value,_) -> mad:info("~s~p~n",[Label,Value]).
-normalize(Padding,V) -> [ case X of 10 -> [13,10]; E -> E end || X <- lists:flatten(pp(Padding,V) )].
-pp(Padding,V) -> k_io_lib_pretty:print(V, Padding, 80, 30, 60, fun(_,_)-> no end).
-appconfig(Driver) ->
-    print("Configuration: ", load_config(), Driver),
-    print("Applications: ",  applist(),     Driver).

+ 0 - 21
src/launching/mad_run.erl

@@ -1,21 +0,0 @@
--module(mad_run).
--compile(export_all).
-
-start(App) ->                            % run_dir > < log_dir
-    mad_plan:main([]),
-    mad:info("Scripting: ~p~n",[escript:script_name()]),
-    {_,Status,X} = sh:run("run_erl",["-daemon",".",".","exec "++escript:script_name()++" sh"],
-      binary,".",
-        [{"RUN_ERL_LOG_GENERATIONS","1000"},
-         {"RUN_ERL_LOG_MAXSIZE","20000000"},
-         {"ERL_LIBS","apps:deps"}]),
-    case Status == 0 of
-         true -> {ok,App};
-         false -> mad:info("Shell Error: ~s~n",[binary_to_list(X)]), {error,X} end.
-
-attach(_) -> mad:info("to_erl .~n"). % use like $(mad attach)
-
-stop(_) -> {ok,[]}.
-
-clean(_) -> [ file:delete(X) || X <- filelib:wildcard("{apps,deps}/*/ebin/**") ++
-                                     filelib:wildcard("ebin/**")], {ok,[]}.

+ 0 - 25
src/launching/mad_vz.erl

@@ -1,25 +0,0 @@
--module(mad_vz).
--compile(export_all).
-
-create(App,_) -> create(App).
-create(App) ->
-    Name = filename:basename(App,".tgz"),
-    mad:info("Unpack Container: ~p~n",[Name]),
-    {ok,Bin} = file:read_file(App),
-    erl_tar:extract({binary,zlib:gunzip(Bin)},[{cwd,lists:concat(["apps/",Name])}]).
-
-start(App) ->
-    mad:info("App: ~p~n",[App]),
-    {ok,Bin}  = file:read_file(lists:concat(["apps/",App,"/config.json"])),
-    {Json   } = jsone:decode(Bin),
-    {Process} = proplists:get_value(<<"process">>,Json),
-    Args      = proplists:get_value(<<"args">>,Process),
-    Concat    = string:join(lists:map(fun(X) -> binary_to_list(X) end,Args)," "),
-    {_,R,S}   = sh:run(Concat,<<"log">>,lists:concat(["apps/",App])),
-    mad:info("Oneliner: ~p~n",[Concat]),
-    {ret(R),S}.
-
-stop(App) -> ok.
-
-ret(0) -> ok;
-ret(_) -> error.

+ 36 - 23
src/mad.erl

@@ -1,4 +1,4 @@
--module(mad).
+-module(mad)..
 -copyright('Maxim Sokhatsky').
 -include("mad.hrl").
 -compile(export_all).
@@ -6,33 +6,46 @@
 
 main([])          -> help();
 main(Params)      ->
-    {Other,F}      = mad_utils:fold_params(Params),
-    unknown(Other),
-    return(lists:any(fun(X) -> element(1,X) == error end,
+
+    { Invalid, Valid } = lists:foldr(
+                               fun (X,{C,R}) when is_atom(X) -> {[],[{X,C}|R]};
+                                   (X,{C,R}) -> {[X|C],R} end,
+                               {[],[]}, lists:map(fun atomize/1, Params)),
+
+    return(lists:any(fun({error,_}) -> true;
+                                (_) -> false end,
            lists:flatten(
            lists:foldl(
-        fun ({Name,Par},Errors) when length(Errors) > 0 -> [{error,Errors}];
-            ({Name,Par},Errors) -> lists:flatten([errors((profile()):Name(Par))|Errors]) end, [], F)))).
-
-deps(Params)      -> mad_deps:deps(Params).
-compile(Params)   -> mad_compile:compile(Params).
-app(Params)       -> mad_static:app(Params).
-clean(Params)     -> mad_run:clean(Params).
-start(Params)     -> mad_run:start(Params).
-attach(Params)    -> mad_run:attach(Params).
-stop(Params)      -> mad_run:stop(Params).
-release(Params)   -> mad_release:release(Params).
-sh(Params)        -> mad_repl:sh(Params).
-up(Params)        -> mad_deps:up(Params).
-profile()         -> application:get_env(mad,profile,mad).
-
-unknown([])       -> skip;
-unknown(Other)    -> info("Unknown: ~p~n",[Other]), help().
+                 fun ({Fun,Arg},[])  -> errors((profile()):Fun(Arg));
+                     ({Fun,Arg},Err) -> errors(Invalid),
+                                        { return, Err } end,
+                 [], Valid)))).
+
+atomize("static") -> 'static';
+atomize("deploy") -> 'deploy';
+atomize("app"++_) -> 'app';
+atomize("dep")    -> 'deps';
+atomize("deps")   -> 'deps';
+atomize("cle"++_) -> 'clean';
+atomize("com"++_) -> 'compile';
+atomize("up")     -> 'up';
+atomize("rel"++_) -> 'release';
+atomize("bun"++_) -> 'release';
+atomize("sta"++_) -> 'start';
+atomize("sto"++_) -> 'stop';
+atomize("att"++_) -> 'attach';
+atomize("sh")     -> 'sh';
+atomize("rep"++_) -> 'sh';
+atomize("pla"++_) -> 'release';
+atomize(Else)     -> Else.
+
+profile()         -> application:get_env(mad,profile,mad_local).
 
+errors([])        -> [];
 errors(false)     -> [];
 errors(true)      -> {error,unknown};
-errors({error,L}) -> info("ERR: ~tp~n",[L]), {error,L};
-errors({ok,L})    -> info("OK:  ~tp~n",[L]), [];
+errors({error,L}) -> info("ERROR: ~tp~n",[L]), {error,L};
+errors({ok,_})    -> info("OK~n",[]), [];
 errors(X)         -> info("RETURN: ~tp~n",[X]), {error,X}.
 
 return(true)      -> 1;

+ 0 - 118
src/mad_deps.erl

@@ -1,118 +0,0 @@
--module(mad_deps).
--copyright('Sina Samavati').
--compile(export_all).
-
-deps(Params) ->
-    { Cwd, ConfigFile, Conf } = mad_utils:configs(),
-    case mad_utils:get_value(deps, Conf, []) of
-        [] -> {ok,[]};
-        Deps ->
-            Cache = mad_utils:get_value(deps_dir, Conf, deps_fetch),
-            case Cache of
-                deps_fetch -> skip;
-                Dir -> file:make_dir(Dir) end,
-            FetchDir = mad_utils:get_value(deps_dir, Conf, ["deps"]),
-            file:make_dir(FetchDir),
-            mad_deps:fetch(Cwd, Conf, ConfigFile, Deps)
-    end.
-
-pull(_,[])         -> {ok,[]};
-pull(Config,[F|T]) ->
-    mad:info("==> up: ~p~n", [F]),
-    {_,Status,Message} = sh:run(lists:concat(["cd ",F," && git pull && cd -"])),
-    case Status of
-         0 -> mad_utils:verbose(Config,Message), pull(Config,T);
-         _ -> case binary:match(Message,[<<"You are not currently on a branch">>]) of
-                   nomatch -> mad_utils:verbose(Config,Message), true;
-                   _ -> pull(Config,T) end end.
-
-up(Params) ->
-  { _Cwd,_ConfigFileName,Config } = mad_utils:configs(),
-  List = case Params of
-                [] -> [ F || F <- mad_repl:wildcards(["deps/*"]), filelib:is_dir(F) ];
-                Apps -> [ "deps/" ++ A || A <- Apps ] end ++ ["."],
-    pull(Config,List).
-
-fetch(_, _Config, _, []) -> false;
-fetch(Cwd, Config, ConfigFile, [H|T]) when is_tuple(H) =:= false -> fetch(Cwd, Config, ConfigFile, T);
-fetch(Cwd, Config, ConfigFile, [H|T]) ->
-    {Name, Repo} = name_and_repo(H),
-    Res = case get(Name) of
-        fetched -> {ok,Name};
-        _ ->
-            {Cmd, Uri, Co} = case Repo of
-                                 V={_, _, _}          -> V;
-                                 {_Cmd, _Url, _Co, _} -> {_Cmd, _Url, _Co};
-                                 {_Cmd, _Url}         -> {_Cmd, _Url, "master"}
-                             end,
-            Cmd1 = atom_to_list(Cmd),
-            Cache = mad_utils:get_value(cache, Config, deps_fetch),
-            fetch_dep(Cwd, Config, ConfigFile, Name, Cmd1, Uri, Co, Cache)
-    end,
-    case Res of
-         {error,E} -> {error,E};
-         {ok,_} -> fetch(Cwd, Config, ConfigFile, T) end.
-
-git_clone(Uri,Fast,TrunkPath,Rev) when Rev == "head" orelse Rev == "HEAD" orelse Rev == "master" ->
-    {["git clone ",Fast,Uri," ",TrunkPath],Rev};
-git_clone(Uri,_Fast,TrunkPath,Rev) ->
-    {["git clone ",Uri," ",TrunkPath," && cd ",TrunkPath," && git checkout \"",Rev,"\"" ],Rev}.
-
-fetch_dep(Cwd, Config, ConfigFile, Name, Cmd, Uri, Co, Cache) ->
-
-    TrunkPath = case Cache of
-        deps_fetch -> filename:join([mad_utils:get_value(deps_dir,Config,"deps"),Name]);
-        Dir -> filename:join([Dir,get_publisher(Uri),Name]) end,
-
-    mad:info("==> dependency: ~p tag: ~p~n", [Uri,Co]),
-
-    Fast = case mad_utils:get_value(fetch_speed,Config,[]) of
-                fast_master -> " --depth=1 ";
-                    _  -> "" end,
-
-    {R,Co1} = case Co of
-        X when is_list(X) -> git_clone(Uri,Fast,TrunkPath,X);
-        {_,Rev} -> git_clone(Uri,Fast,TrunkPath,Rev);
-        Master  -> git_clone(Uri,Fast,TrunkPath,Master) end,
-
-    %mad:info("Fetch: ~s~n",[R]),
-
-    FetchStatus = case filelib:is_dir(TrunkPath) of
-                       true -> {skip,0,list_to_binary("Directory "++TrunkPath++" exists.")};
-                       false -> sh:run(lists:concat(R)) end,
-
-    case FetchStatus of
-         {_,0,_} -> put(Name, fetched),
-
-                    %% check dependencies of the dependency
-                    TrunkConfigFile = filename:join(TrunkPath, ConfigFile),
-                    Conf = mad_utils:consult(TrunkConfigFile),
-                    Conf1 = mad_utils:script(TrunkConfigFile, Conf, Name),
-                    fetch(Cwd, Config, ConfigFile, mad_utils:get_value(deps, Conf1, [])),
-                    case Cache of
-                         deps_fetch -> {ok,Name};
-                         CacheDir -> build_dep(Cwd, Config, ConfigFile,
-                                        get_publisher(Uri), Name, Cmd, Co1, CacheDir)
-                    end;
-    {_,_,FetchError} -> mad:info("Fetch Error: ~s~n",[binary_to_list(FetchError)]),
-                        {error,binary_to_list(FetchError)} end.
-
-%% build dependency based on branch/tag/commit
-build_dep(Cwd, Conf, _ConfFile, Publisher, Name, _Cmd, _Co, Dir) ->
-    TrunkPath = filename:join([Dir, Publisher, Name]),
-    DepsDir = filename:join([mad_utils:get_value(deps_dir, Conf, ["deps"]),Name]),
-    os:cmd(["cp -r ", TrunkPath, " ", DepsDir]),
-    ok = file:set_cwd(DepsDir),
-    ok = file:set_cwd(Cwd),
-    {ok,Name}.
-
-%% internal
-name_and_repo({Name, _, Repo}) when is_list(Name) -> {Name, Repo};
-name_and_repo({Name, _, Repo, _}) when is_list(Name) -> {Name, Repo};
-name_and_repo({Name, _, Repo}) -> {atom_to_list(Name), Repo};
-name_and_repo({Name, _, Repo, _}) -> {atom_to_list(Name), Repo};
-name_and_repo({Name, Version}) when is_list(Name) -> {Name, Version};
-name_and_repo({Name, Version}) -> {atom_to_list(Name), Version};
-name_and_repo(Name) -> {Name,Name}.
-
-get_publisher(Uri) -> case string:tokens(Uri,"@:/") of [_Proto,_Server,Publisher|_RepoPath] -> Publisher; _ -> core end.

+ 1 - 1
src/mad_plan.erl → src/mad_resolve.erl

@@ -1,4 +1,4 @@
--module(mad_plan).
+-module(mad_resolve).
 -author('Maxim Sokhatsky').
 -compile(export_all).
 

+ 9 - 9
src/mad_static.erl

@@ -5,14 +5,14 @@
 
 main(Config, ["watch"]) ->
     case mad_utils:get_value(static, Config, []) of
-        [] -> false;
+        [] -> {ok,static};
         SC ->
             Port = mad_utils:get_value(assets_port, SC, 3000),
             install_deps(), serve_static(Port)
     end;
 main(Config, _Params) ->
     case mad_utils:get_value(static, Config, []) of
-        [] -> false;
+        [] -> {ok,static};
         SC ->
             Files = mad_utils:get_value(files, SC, []),
             install_deps(), compile_static(Files)
@@ -20,11 +20,11 @@ main(Config, _Params) ->
 
 install_deps() ->
     case filelib:is_dir("node_modules/mincer-erl") of
-        true -> false;
+        true -> {ok,static};
         _ ->
             case sh:oneliner("npm install mincer-erl") of
-                {_,0,_} -> false;
-                {_,_,_} -> mad:info("error while installing mincer-erl~n"), true
+                {_,0,_} -> {ok,static};
+                {_,_,_} -> mad:info("error while installing mincer-erl~n"), {error,install}
             end
     end.
 
@@ -33,14 +33,14 @@ serve_static(Port) ->
     PortStr = integer_to_list(Port),
     Res = sh:oneliner([?NODE("mincer-erl-serve"), "-p " ++ PortStr]),
     case Res of
-        {_,0,_} -> false;
-        {_,_,_} -> mad:info("error while serving assets~n"), true end.
+        {_,0,_} -> {ok,static};
+        {_,_,_} -> mad:info("error while serving assets~n"), {error,assests} end.
 
 compile_static(Files) ->
     Res = sh:oneliner([?NODE("mincer-erl-compile")] ++ Files),
     case Res of
-        {_,0,_} -> false;
-        {_,_,_} -> mad:info("error while compiling assets~n"), true end.
+        {_,0,_} -> {ok,static};
+        {_,_,_} -> mad:info("error while compiling assets~n"), {error,compile} end.
 
 app([]) -> app(["sample"]);
 app(Params) ->

+ 8 - 30
src/mad_utils.erl

@@ -2,28 +2,17 @@
 -copyright('Sina Samavati').
 -compile(export_all).
 
-atomize("static") -> static;
-atomize("deploy") -> deploy;
-atomize("app"++_) -> app;
-atomize("dep")    -> deps;
-atomize("deps")   -> deps;
-atomize("cle"++_) -> clean;
-atomize("com"++_) -> compile;
-atomize("up")     -> up;
-atomize("rel"++_) -> release;
-atomize("bun"++_) -> release;
-atomize("sta"++_) -> start;
-atomize("sto"++_) -> stop;
-atomize("att"++_) -> attach;
-atomize("sh")     -> sh;
-atomize("rep"++_) -> sh;
-atomize("pla"++_) -> release;
-atomize(Else)     -> Else.
+%% internal
+name_and_repo({Name, _, Repo}) when is_list(Name) -> {Name, Repo};
+name_and_repo({Name, _, Repo, _}) when is_list(Name) -> {Name, Repo};
+name_and_repo({Name, _, Repo}) -> {atom_to_list(Name), Repo};
+name_and_repo({Name, _, Repo, _}) -> {atom_to_list(Name), Repo};
+name_and_repo({Name, Version}) when is_list(Name) -> {Name, Version};
+name_and_repo({Name, Version}) -> {atom_to_list(Name), Version};
+name_and_repo(Name) -> {Name,Name}.
 
 cwd() -> {ok, Cwd} = file:get_cwd(), Cwd.
-
 home() -> {ok, [[H|_]]} = init:get_argument(home), H.
-
 consult(File) ->
     AbsFile = filename:absname(File),
     case file:consult(AbsFile) of
@@ -89,17 +78,6 @@ to_atom(X) when is_list(X) -> list_to_atom(X);
 to_atom(X) when is_binary(X) -> to_atom(binary_to_list(X));
 to_atom(X) -> X.
 
-atomize_params_commands(Params) -> atomize_params_commands(Params,[]).
-atomize_params_commands([],New) -> New;
-atomize_params_commands([H|T], New) -> atomize_params_commands(T,[atomize(H)|New]).
-
-fold_params(Params) ->
-   Atomized = atomize_params_commands(Params),
-   lists:foldl(fun(X,{Current,Result}) -> 
-      case atomize(X) of
-           X when is_atom(X) -> {[],[{X,Current}|Result]};
-           E -> {[E|Current],Result} end
-      end, {[],[]}, Atomized).
 
 verbose(Config,Message) ->
     case mad_utils:get_value(verbose, Config, 0) of

+ 0 - 41
src/packaging/mad_bundle.erl

@@ -1,41 +0,0 @@
--module(mad_bundle).
--description("ESCRIPT bundles").
--compile(export_all).
-
-main(N) ->
-    App = filename:basename(case N of [] -> mad_utils:cwd(); E -> E end),
-    mad_plan:main([]),
-    EmuArgs = "-noshell -noinput +pc unicode",
-    Files = static() ++ beams(fun filename:basename/1, fun read_file/1) ++ overlay(),
-    escript:create(App,[shebang,{comment,""},{emu_args,EmuArgs},{archive,Files,[memory]}]),
-    file:change_mode(App, 8#764),
-    {ok,App}.
-
-id(X) -> X.
-read_file(File) -> {ok, Bin} = file:read_file(filename:absname(File)), Bin.
-static() ->
-    Name = "static.gz",
-    {ok,{_,Bin}} = zip:create(Name,
-        [ F || F <- mad_repl:wildcards(["{apps,deps}/*/priv/**","priv/**"]), not filelib:is_dir(F) ],
-        [{compress,all},memory]),
-    [ { Name, Bin } ].
-
-beams() -> beams(fun id/1,  fun read_file/1).
-beams(Fun,Read) ->
-    [ { Fun(F), Read(F) } ||
-        F <- mad_repl:wildcards(["ebin/*","{apps,deps}/*/ebin/*","sys.config",".applist"]) ].
-
-privs() -> privs(fun id/1,  fun read_file/1).
-privs(Fun,Read) ->
-    [ { Fun(F), Read(F) } ||
-        F <- mad_repl:wildcards(["{apps,deps}/*/priv/**","priv/**"]), not filelib:is_dir(F) ].
-
-system_files() -> lists:flatten([system_files(A) || A<- mad_repl:applist(), lists:member(A,mad_repl:system()) ]).
-system_files(App) ->
-    [ { F, mad_bundle:read_file(F) } ||
-        F <- mad_repl:wildcards([lists:concat([code:lib_dir(App),"/ebin/*.{app,beam}"])]) ].
-
-overlay() -> overlay(fun id/1,  fun read_file/1).
-overlay(Fun,Read) ->
-    [ { Fun(F), Read(F) } ||
-        F <- mad_repl:wildcards(["deps/ling/apps/*/ebin/*.beam"]) ].

+ 0 - 138
src/packaging/mad_ling.erl

@@ -1,138 +0,0 @@
--module(mad_ling).
--description("LING Erlang Virtual Machine Bundle Packaging").
--copyright('Cloudozer, LLP').
--compile(export_all).
--define(ARCH, list_to_atom( case os:getenv("ARCH") of false -> "posix"; A -> A end)).
-
-ling(Params) ->
-    mad_plan:main(),
-    _App = filename:basename(case Params of [] ->   mad_utils:cwd(); E -> E end),
-    mad:info("ARCH: ~p~n",         [?ARCH]),
-    mad:info("Bundle Name: ~p~n",  [mad_repl:local_app()]),
-    mad:info("System: ~p~n",       [mad_repl:system()]),
-    mad:info("Apps: ~p~n",         [mad_repl:applist()]),
-%    mad:info("Overlay: ~p~n",      [[{filename:basename(N),size(B)}||{N,B} <- mad_bundle:overlay()]]),
-%    mad:info("Files: ~p~n",        [[{filename:basename(N),size(B)}||{N,B} <- bundle()]]),
-    mad:info("Overlay: ~p~n",      [[filename:basename(N)||{N,_B} <- mad_bundle:overlay()]]),
-    add_apps(),
-    {ok,_App}.
-
-cache_dir()       -> ".madaline/".
-local_map(Bucks)  -> list_to_binary(lists:map(fun({B,M,_}) -> io_lib:format("~s /~s\n",[M,B]) end,Bucks)).
-bundle()          -> lists:flatten([ mad_bundle:X() || X <- [beams,privs,system_files,overlay] ]).
-library(Filename) -> case filename:split(Filename) of
-    ["deps","ling","apps",Lib|_] -> list_to_atom(Lib);
-                      ["ebin"|_] -> mad_repl:local_app();
-                      ["priv"|_] -> mad_repl:local_app();
-           A when length(A) >= 3 -> list_to_atom(hd(string:tokens(lists:nth(3,lists:reverse(A)),"-")));
-                  ["apps",Lib|_] -> list_to_atom(Lib);
-                  ["deps",Lib|_] -> list_to_atom(Lib);
-                               _ -> mad_repl:local_app() end.
-
-apps(Ordered) ->
-    Overlay = [ {filename:basename(N),B} || {N,B} <- mad_bundle:overlay() ],
-    lists:foldl(fun({N,B},Acc) ->
-        A = library(N),
-        Base = filename:basename(N),
-        Body = case lists:keyfind(Base,1,Overlay) of
-                    false -> B;
-                    {Base,Bin} -> 'overlay', Bin end,
-         case lists:keyfind(A,1,Acc) of
-              false -> [{A,[{A,Base,Body}]}|Acc];
-              {A,Files} -> lists:keyreplace(A,1,Acc,{A,[{A,Base,Body}|Files]}) end
-    end,lists:zip(Ordered,lists:duplicate(length(Ordered),[])),bundle()).
-
-lib({App,Files}) ->
-    { App, lists:concat(["/erlang/lib/",App,"/ebin"]), Files }.
-
-boot(Ordered) ->
-    BootCode = element(2,file:read_file(lists:concat([code:root_dir(),"/bin/start.boot"]))),
-    { script, Erlang, Boot } = binary_to_term(BootCode),
-    AutoLaunch = {script,Erlang,Boot++[{apply,{application,start,[App]}} || App <- Ordered]},
-    mad:info("Boot Code: ~p~n",[AutoLaunch]),
-    { boot, "start.boot", term_to_binary(AutoLaunch) }.
-
-add_apps() ->
-    {ok,Ordered} = mad_plan:orderapps(),
-    Bucks = [{boot,"/boot",[local_map, boot(Ordered)]}] ++ [ lib(E) || E <- apps(Ordered) ],
-    %mad:info("Bucks: ~p~n",[[{App,Mount,[{filename:basename(F),size(Bin)}||{_,F,Bin}<-Files]}||{App,Mount,Files}<-Bucks]]),
-    mad:info("Bucks: ~p~n",[[{App,Mount,length(Files)}||{App,Mount,Files}<-Bucks]]),
-    filelib:ensure_dir(cache_dir()),
-    EmbedFsPath = lists:concat([cache_dir(),"/embed.fs"]),
-    mad:info("Initializing EMBED.FS:"),
-    Res = embed_fs(EmbedFsPath,Bucks),
-	{ok, EmbedFsObject} = embedfs_object(EmbedFsPath),
-	Oneliner = ld() ++
-               ["../deps/ling/core/vmling.o"] ++
-               ["-lm", "-lpthread", "-ldl"] ++
-               [EmbedFsObject, "-o", "../" ++ atom_to_list(mad_repl:local_app()) ++ ".img"],
-    mad:info("LD: ~p~n",[Oneliner]),
-	Res = case sh:oneliner(Oneliner,cache_dir()) of
-	           {_,0,_} -> ok;
-	           {_,_,M} -> binary_to_list(M) end,
-    mad:info("Linking Image: ~p~n",[Res]).
-
-embed_fs(EmbedFsPath,Bucks)  ->
-    {ok, EmbedFs} = file:open(EmbedFsPath, [write]),
-    BuckCount = length(Bucks),
-    BinCount = lists:foldl(fun({_,_,Bins},Count) -> Count + length(Bins) end,0,Bucks),
-    file:write(EmbedFs, <<BuckCount:32>>),
-	file:write(EmbedFs, <<BinCount:32>>),
-    lists:foreach(fun({Buck,_,Bins}) ->
-          BuckName = binary:list_to_bin(atom_to_list(Buck)),
-          BuckNameSize = size(BuckName),
-          BuckBinCount = length(Bins),
-          file:write(EmbedFs, <<BuckNameSize, BuckName/binary, BuckBinCount:32>>),
-          lists:foreach(fun
-                    (local_map) -> LocalMap = local_map(Bucks),
-                                   mad:info("~nMount View:~n ~s",[LocalMap]),
-                                   write_bin(EmbedFs, "local.map", LocalMap);
-                  ({_App,F,Bin}) -> write_bin(EmbedFs, filename:basename(F), Bin)
-          end,Bins)
-    end,Bucks),
-    file:close(EmbedFs),
-	ok.
-
-embedfs_object(EmbedFsPath) ->
-	EmbedCPath  = filename:join(filename:absname(cache_dir()), "embedfs.c"),
-	OutPath     = filename:join(filename:absname(cache_dir()), "embedfs.o"),
-	{ok, Embed} = file:read_file(EmbedFsPath),
-	mad:info("Creating EMBED.FS C file: ..."),
-	Res = bfd_objcopy:blob_to_src(EmbedCPath, "_binary_embed_fs", Embed),
-    mad:info("~p~n",[Res]),
-	mad:info("Compilation of Filesystem object: ..."),
-	Res = case sh:oneliner(cc() ++ ["-o", OutPath, "-c", EmbedCPath]) of
-	           {_,0,_} -> ok;
-	           {_,_,M} -> binary_to_list(M) end,
-	mad:info("~p~n",[Res]),
-	mad:info("Out Path: ~p~n",[OutPath]),
-	{ok, OutPath}.
-
-write_bin(Dev, F, Bin) ->
-    {ListName,Data} = case filename:extension(F) of
-        ".beam" ->  { filename:rootname(F) ++ ".ling", beam_to_ling(Bin) };
-              _ ->  { F, Bin } end,
-    Name = binary:list_to_bin(ListName),
-    NameSize = size(Name),
-    DataSize = size(Data),
-    file:write(Dev, <<NameSize, Name/binary, DataSize:32, Data/binary>>).
-
-beam_to_ling(B) ->
-    ling_lib:specs_to_binary(element(2,ling_code:ling_to_specs(element(2,ling_code:beam_to_ling(B))))).
-
-gold() -> gold("ld").
-gold(Prog) -> [Prog, "-T", "ling.lds", "-nostdlib"].
-
-ld() -> ld(?ARCH).
-ld(arm) -> gold("arm-none-eabi-ld");
-ld(xen_x86) -> case os:type() of {unix, darwin} -> ["x86_64-pc-linux-ld"]; _ -> gold() end;
-ld(posix) -> case os:type() of {unix, darwin} ->
-    ["clang","-image_base","0x8000","-pagezero_size","0x8000","-arch","x86_64"];
-	_ -> gold() end;
-ld(_) -> gold().
-
-cc() -> cc(?ARCH).
-cc(arm) -> ["arm-none-eabi-gcc", "-mfpu=vfp", "-mfloat-abi=hard"];
-cc(xen_x86) -> case os:type() of {unix, darwin} -> ["x86_64-pc-linux-gcc"]; _ -> ["cc"] end;
-cc(_) -> ["cc"].
-

+ 0 - 41
src/packaging/mad_release.erl

@@ -1,41 +0,0 @@
--module(mad_release).
--description("MAD precompiled binary packages").
--copyright('Synrc Research Center, s.r.o').
--compile(export_all).
-
-% depot releases for synrc.com/apps
-
-contains(X,String,Acc) ->
-    case string:str(String,atom_to_list(X)) > 0 of true -> [{X}|Acc]; _ -> [] end.
-
-wildcards(Depot,X,Pattern) ->
-    mad_repl:wildcards([Depot++atom_to_list(X)++Pattern]).
-
-atomlist(TARGETS) ->
-    string:join(lists:map(fun(X) -> atom_to_list(X) end,TARGETS),",").
-
-depot_release(Name) ->
-    mad_plan:main([]),
-    TARGETS   = [beam,ling],
-    HOSTS     = [mac,bsd,windows],
-    Depot     = "/Users/5HT/depot/synrc/synrc.com/apps/",
-    {ok,Apps} = file:consult(Depot++"index.txt"),
-    Files     = lists:flatten([[
-                    lists:foldl(fun(A,Acc) -> [{A}|Acc] end,
-                        [], wildcards(Depot,X,lists:concat(["/ebin/**/*.{app,",atomlist(TARGETS),"}"]))),
-                    lists:foldl(fun(B,Acc)->[contains(P,B,Acc)||P<-HOSTS] end,
-                        [], wildcards(Depot,X,"/{bin,priv}/**/*")) ]
-    || {_,[X],_} <- lists:flatten(Apps) ]),
-    io:format("DEPOT Apps: ~p~n",[Files]),
-    {ok,Name}.
-
-release([])              -> release(["script"]);
-release(["depot"])       -> release(["depot", "sample"]);
-release(["beam"])        -> release(["beam",  "sample"]);
-release(["ling"])        -> release(["ling",  "sample"]);
-release(["script"])      -> release(["script","sample"]);
-release(["ling",N])      -> mad_ling:ling(N);
-release(["script",N])    -> mad_bundle:main(N);
-release(["depot",N])     -> mad_release:depot_release(N);
-release(["beam",N])      -> mad_systools:beam_release(N);
-release([X])             -> release(["script",X]).

+ 0 - 51
src/packaging/mad_systools.erl

@@ -1,51 +0,0 @@
--module(mad_systools).
--description("ERTS releases with systools").
--compile(export_all).
-
-% beam releases
-
-scripts(N) ->
-    mad_repl:load(),
-    {ok,Bin} = mad_repl:load_file("priv/systools/start"),
-    [{"/bin/start",list_to_binary(re:replace(binary_to_list(Bin),"{release}",N,[global,{return,list}]))},
-     {"/bin/attach",element(2,mad_repl:load_file("priv/systools/attach"))},
-     {"/bin/daemon",element(2,mad_repl:load_file("priv/systools/daemon"))},
-     {"/etc/"++N++".boot",N++".boot"},
-     {"/etc/vm.args","vm.args"},
-     {"/etc/sys.config","sys.config"}].
-
-apps(List) ->
-    lists:flatten([[[ {filename:join([lib,
-        lists:concat([App,"-",Version]),Class,filename:basename(F)]),F}
-    || F <- mad_repl:wildcards([filename:join([Dir,Class,"*"])]) ]
-    || {App,{Version,Dir}} <- List ] || Class <- [ebin,priv] ]).
-
-release(Name) ->
-    Triples = mad_plan:triples(),
-    Apps = lists:usort(fun({Name,_},{Name2,_})-> Name =< Name2 end,
-                [{A,{B,F}}||{_,A,{B,F}}<-Triples]) ++
-      [{kernel,{proplists:get_value(vsn,element(2,
-                application:get_all_key(kernel)),[]),
-                filename:absname(code:lib_dir(kernel))}}],
-    Sorted = [ lists:keyfind(A,1,Apps) || A <- element(2,mad_plan:orderapps())],
-    {L,R}     = lists:unzip(Sorted),
-    {Ver,Dir} = lists:unzip(R),
-    NameVer   = [ X || X <- lists:zip(L,Ver), element(1,X) /= active,
-                                              element(1,X) /= fs ],
-    {{release,{Name,"1"},{erts,erlang:system_info(version)},NameVer},Sorted}.
-
-beam_release(N) ->
-    mad_plan:main([]),
-    Directories = mad_repl:wildcards(["{deps,apps}/*/ebin","ebin"]),
-    code:add_paths(Directories),
-    {Release,Apps} = release(N),
-    file:write_file(N ++ ".rel",io_lib:format("~p.",[Release])),
-    Res = systools:make_script(N),
-    Files = [ {"/bin/" ++ filename:basename(F), F}
-        || F <- mad_repl:wildcards([code:root_dir() ++
-            "/erts-" ++ erlang:system_info(version) ++
-            "/bin/{epmd,erlexec,run_erl,to_erl,escript,beam.smp}"]) ] ++
-        apps(Apps) ++ scripts(N),
-    erl_tar:create(N ++ ".tgz",Files,[compressed]),
-    mad:info("~s.boot: ~p~n",[N,Res]),
-    {ok,N}.

+ 4 - 3
src/profiles/openvz.erl → src/profile/mad_vz.erl

@@ -1,7 +1,6 @@
--module(openvz).
+-module(mad_vz).
 -compile(export_all).
 
-deps(Params)      -> mad_deps:deps(Params).
 compile(Params)   -> mad_compile:compile(Params).
 app(Params)       -> mad_static:app(Params).
 clean(Params)     -> mad_vz:clean(Params).
@@ -10,4 +9,6 @@ attach(Params)    -> mad_vz:attach(Params).
 stop(Params)      -> mad_vz:stop(Params).
 release(Params)   -> mad_release:release(Params).
 sh(Params)        -> {error,'N/A'}.
-up(Params)        -> mad_deps:up(Params).
+deps(Params)      -> mad_synrc:deps(Params).
+up(Params)        -> mad_synrc:up(Params).
+fetch(Params)     -> mad_synrc:fetch(Params).