Browse Source

upd to v6.1

221V 1 year ago
parent
commit
419ab30fdf
9 changed files with 316 additions and 166 deletions
  1. 1 1
      README.md
  2. 3 3
      ebin/active.app
  3. 0 10
      include/active.hrl
  4. BIN
      mad
  5. 190 125
      src/active.erl
  6. 7 1
      src/active_app.erl
  7. 64 14
      src/active_events.erl
  8. 33 0
      src/active_sh.erl
  9. 18 12
      src/active_sup.erl

+ 1 - 1
README.md

@@ -1,4 +1,4 @@
-ACTIVE - https://github.com/synrc/active v1.9 fork
+ACTIVE: Continuous Compilation - https://github.com/synrc/active v1.9 fork (upd to v6.1)
 ======
 ======
 
 
 Active is a [sync](https://github.com/rustyio/sync) replacement
 Active is a [sync](https://github.com/rustyio/sync) replacement

+ 3 - 3
ebin/active.app

@@ -1,9 +1,9 @@
 {application, active,
 {application, active,
- [{description, "ACT VXZ Continuous Compilation"},
-  {vsn, "1.9"},
+ [{description, "Active Continuous Compilation"},
+  {vsn, "6.1.1"},
   {registered, [active_sup]},
   {registered, [active_sup]},
   {applications, [kernel, stdlib, fs]},
   {applications, [kernel, stdlib, fs]},
-  {modules, [active_app, active_events, active_sup, active]},
+  {modules, [active_app, active_events, active_sh, active_sup, active]},
   {mod, { active_app, []}},
   {mod, { active_app, []}},
   {env, []}
   {env, []}
  ]}.
  ]}.

+ 0 - 10
include/active.hrl

@@ -1,10 +0,0 @@
-
--type mf() :: {M :: module(), F :: atom()}.
--spec subscribe_onload(Function :: mf()) -> ok.
--spec subscribe_onnew(Function :: mf()) -> ok.
--spec subscribe(Event :: reloaded | loaded_new, Function :: mf()) -> ok.
--record(event_state, {
-    event :: reloaded | loaded_new,
-    function :: mf()
-}).
-

BIN
mad


+ 190 - 125
src/active.erl

@@ -1,103 +1,168 @@
 -module(active).
 -module(active).
+
 -behaviour(gen_server).
 -behaviour(gen_server).
--define(SERVER, ?MODULE).
--compile([export_all, nowarn_export_all]).
--export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
+
+
+-export([
+  start_link/0,
+  init/1,
+  handle_call/3,
+  handle_cast/2,
+  handle_info/2,
+  terminate/2,
+  code_change/3
+]).
+
 -record(state, {last, root}).
 -record(state, {last, root}).
 
 
-start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+start_link() ->
+  gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
 
 
 init([]) ->
 init([]) ->
-    fs:subscribe(),
-    erlang:process_flag(priority, low),
-    gen_server:cast(self(), recompile_all),
-    {ok, #state{last=fresh, root=fs:path()}}.
-handle_call(_Request, _From, State) -> {reply, ok, State}.
+  fs:subscribe(),
+  erlang:process_flag(priority, low),
+  gen_server:cast(self(), recompile_all),
+  {ok, #state{last=fresh, root=fs:path()}}.
+
+
+handle_call(_Request, _From, State) ->
+  {reply, ok, State}.
+
+
 handle_cast(recompile_all, State) ->
 handle_cast(recompile_all, State) ->
-    compile(top(), ["all"]),
-    {noreply, State}.
-handle_info({_Pid, {fs,file_event}, {Path, Flags}}, #state{root=Root} = State) ->
-    Cur = path_shorten(filename:split(Root)),
-    P = filename:split(Path),
+  compile(top(), ["all"], []),
+  {noreply, State}.
+
+
+handle_info({_Pid, {fs, file_event}, {Path, Flags}}, #state{root = Root} = State) ->
+  Cur = path_shorten(filename:split(Root)),
+  P = filename:split(Path),
+  Result = case lists:prefix(Cur, P) of
+    true ->
+      path_event(P -- Cur, Flags, State, Path);
+    false -> ok
+  end,
+  {noreply, State#state{last = {event, Path, Flags, Result}} };
+
+
+handle_info({load_ebin, Atom}, State) ->
+  do_load_ebin(Atom),
+  {noreply, State#state{last = {do_load_ebin, Atom}}};
+
+
+handle_info(Info, State) ->
+  {noreply, State#state{last = {unk, Info}}}.
+
 
 
-    Result = case lists:prefix(Cur, P) of
-        true ->
-            Components = P -- Cur,
-            %mad:info("event: ~p ~p", [Components, Flags]),
-            path_event(Components, Flags, State);
-        false ->
-            ok
-    end,
-
-    {noreply, State#state{last={event, Path, Flags, Result}}};
-handle_info({load_ebin, Atom}, State) -> do_load_ebin(Atom), {noreply, State#state{last={do_load_ebin, Atom}}};
-handle_info(Info, State) -> {noreply, State#state{last={unk, Info}}}.
 terminate(_Reason, _State) -> ok.
 terminate(_Reason, _State) -> ok.
+
+
 code_change(_OldVsn, State, _Extra) -> {ok, State}.
 code_change(_OldVsn, State, _Extra) -> {ok, State}.
 
 
-path_event(C, [E|_Events], _State) when E =:= created; E =:= modified; E =:= renamed ->
-    case path_filter(C) of true -> maybe_otp(C); false -> ignore end;
-path_event(C, [_E|Events], State) -> path_event(C, Events, State);
-path_event(_, [], _State) -> done.
-
-maybe_otp(C) ->
-    case application:get_env(active, handler) of
-         {ok,{M,F}} -> M:F(C);
-                  _ -> otp(C) end.
-
-otp(["deps",App|Rest]) -> maybe_app(App,Rest);
-otp(["apps",App|Rest]) -> maybe_app(App,Rest);
-otp([Some|Path]) -> maybe_app(top(),[Some|Path]);
-otp(_) -> ok.
-
-maybe_app(App, Path) ->
-    EnabledApps = application:get_env(active, apps, undefined),
-    case EnabledApps of
-        undefined ->
-%            mad:info("App ~p Path ~p~n",[App,Path]),
-            app(App, Path);
-        {ok,L} when is_list(L) ->
-            AppAtom = list_to_atom(App),
-            case lists:member(AppAtom, L) of
-                true ->
-%                    mad:info("App ~p Path ~p~n",[App,Path]),
-                    app(App, Path);
-                false ->
-                    skip
-            end
-    end.
 
 
-app( App,["ebin",Module|_])     -> load_ebin(App,Module);
-app(_App,["priv","fdlink"++_])  -> skip;
-app(_App,["priv","mac"++_])     -> skip;
-app(_App,["priv","windows"++_]) -> skip;
-app(_App,["priv","linux"++_])   -> skip;
-app(_App,["priv","static"|_])   -> skip;
-app( App,["priv"|Rest])         -> compile(App,Rest);
-app( App,["include"|Rest])      -> compile(App,Rest);
-app( App,["src"|Rest])          -> compile(App,Rest);
-app(_,_)-> ok.
+path_event(C, [E|_], _, Path) when E =:= created; E =:= modified; E =:= renamed ->
+  case path_filter(C) of
+    true -> maybe_otp(C, Path);
+    false -> ignore
+  end;
+  
+path_event(C, [_E|Events], State, Path) ->
+  path_event(C, Events, State, Path);
+  
+path_event(_, [], _, _) -> done.
+
+
+maybe_otp(C, Path) ->
+  case application:get_env(active, handler) of
+    {ok, {M, F}} -> M:F(C);
+    _ -> otp(C, Path)
+  end.
+
+
+otp([Some, App|Rest], Path) when Some == "deps" orelse Some == "apps" ->
+  maybe_app(App, Rest, Path);
+
+otp([Some|Rest], Path) ->
+  maybe_app(top(), [Some|Rest], Path);
+
+otp(_, _) ->
+  ok.
+
+
+maybe_app(App, SplitPath, Path) ->
+  EnabledApps = application:get_env(active, apps, []),
+  case EnabledApps of
+    [] ->
+      app(App, SplitPath, Path);
+    
+    {ok, L} when erlang:is_list(L) ->
+      AppAtom = erlang:list_to_atom(App),
+      case lists:member(AppAtom, L) of
+        true ->
+          app(App, SplitPath, Path);
+        false -> skip
+      end
+  end.
+
+
+app(App, ["ebin", Module|_], _) -> load_ebin(App, Module);
+app(_App, ["priv", "fdlink" ++ _], _) -> skip;
+app(_App, ["priv", "mac" ++ _], _) -> skip;
+app(_App, ["priv", "windows" ++ _], _) -> skip;
+app(_App, ["priv", "linux" ++ _], _) -> skip;
+app(App, ["priv", "static"|_Rest], Path) ->
+  compile_skip(compile_on_static, App, _Rest, Path);
+app(App, ["priv"|Rest], Path) ->
+  compile_skip(compile_on_priv, App, Rest, Path);
+app(App, ["include"|Rest], Path) ->
+  compile(App, Rest, Path);
+app(App, ["src"|Rest], Path) ->
+  compile(App, Rest, Path);
+app(App, ["lib"|Rest], Path) ->
+  compile(App, Rest, Path);
+app(_, _, _)-> ok.
+
+
+compile_skip(Key, App, Rest, Path) ->
+  case application:get_env(active, Key, false) of
+    false -> skip;
+    _ -> compile(App, Rest, Path)
+  end.
 
 
 top() -> lists:last(filename:split(fs:path())).
 top() -> lists:last(filename:split(fs:path())).
 
 
-compile(App,Rest) ->
-    case lists:last(Rest) of
-         ".#" ++ _ -> skip;
-             _ -> try put(App,updated),
-                      mad_compile:compile(App)
-                catch E:R ->
-                      mad:info("~p", [erlang:get_stacktrace()]),
-                      mad:info("Catch: ~p:~p",[E,R]) end end.
+
+compile(_App, _, []) -> ok;
+compile(_App, [], _Path) -> ok;
+compile(App, Rest, Path) ->
+  case lists:last(Rest) of
+    ".#" ++ _ -> skip;
+    _ ->
+      try
+        erlang:put(App, updated),
+        {M, F} = application:get_env(active, compile, {mad_compile, compile}),
+        M:F(App, Path)
+      catch E:R ->
+        io:format("~p", [erlang:get_stacktrace()]),
+        io:format("Catch: ~p:~p", [E, R])
+      end
+  end.
+
 
 
 load_ebin(_App, EName) ->
 load_ebin(_App, EName) ->
-    case lists:reverse(EName) of
-        "maeb." ++ Tail -> Name = lists:reverse(Tail),
-            LoadRes = do_load_ebin(list_to_atom(lists:flatten(Name))),
-            mad:info("Active: module loaded: ~p~n\n\r", [LoadRes]),
-            active_events:notify_reload(LoadRes);
-        "#aeb." ++ _ -> ok;
-        _ -> mad:info("Active: unknown BEAM file: ~p", [EName]), ok
-    end.
+  case lists:reverse(EName) of
+    "maeb." ++ Tail ->
+      Name = lists:reverse(Tail),
+      LoadRes = do_load_ebin(erlang:list_to_atom(lists:flatten(Name))),
+      io:format("Active: module loaded: ~p~n\n\r", [LoadRes]),
+      active_events:notify_reload(LoadRes);
+    "#aeb." ++ _ -> ok;
+    _ ->
+      io:format("Active: unknown BEAM file: ~p", [EName]), ok
+  end.
+
 
 
 do_load_ebin(Module) ->
 do_load_ebin(Module) ->
     IsLoaded = case code:is_loaded(Module) of
     IsLoaded = case code:is_loaded(Module) of
@@ -116,54 +181,54 @@ do_load_ebin(Module) ->
             {load_error, Module, Reason}
             {load_error, Module, Reason}
     end.
     end.
 
 
-monitor_handles_renames([renamed|_]) -> true;
-monitor_handles_renames([_|Events]) -> monitor_handles_renames(Events);
-monitor_handles_renames([]) -> false.
-
-monitor_handles_renames() ->
-    case get(monitor_handles_renames) of
-        undefined ->
-            R = monitor_handles_renames(fs:known_events()),
-            put(monitor_handles_renames, R),
-            R;
-        V -> V
-    end.
 
 
-% ["a", "b", ".."] -> ["a"]
-path_shorten(Coms) -> path_shorten_r(lists:reverse(Coms), [], 0).
+%% ["a", "b", ".."] -> ["a"]
+path_shorten(Coms) ->
+  path_shorten_r(lists:reverse(Coms), [], 0).
 
 
-path_shorten_r([".."|Rest], Acc, Count) -> path_shorten_r(Rest, Acc, Count + 1);
-path_shorten_r(["."|Rest], Acc, Count) -> path_shorten_r(Rest, Acc, Count);
-path_shorten_r([_C|Rest], Acc, Count) when Count > 0 -> path_shorten_r(Rest, Acc, Count - 1);
-path_shorten_r([C|Rest], Acc, 0) -> path_shorten_r(Rest, [C|Acc], 0);
-path_shorten_r([], Acc, _) -> Acc.
+path_shorten_r([".."|Rest], Acc, Count) ->
+  path_shorten_r(Rest, Acc, Count + 1);
+  
+path_shorten_r(["."|Rest], Acc, Count) ->
+  path_shorten_r(Rest, Acc, Count);
+  
+path_shorten_r([_C|Rest], Acc, Count) when Count > 0 ->
+  path_shorten_r(Rest, Acc, Count - 1);
+  
+path_shorten_r([C|Rest], Acc, 0) ->
+  path_shorten_r(Rest, [C|Acc], 0);
+  
+path_shorten_r([], Acc, _) ->
+  Acc.
 
 
-%
-% Filters
-%
 
 
 path_filter(L) ->
 path_filter(L) ->
-    not lists:any(fun(E) -> not path_filter_dir(E) end, L)
-        andalso path_filter_file(lists:last(L))
-        andalso path_filter_ext(ext(L)).
+  not lists:any(fun(E) -> not path_filter_dir(E) end, L)
+  andalso path_filter_file( lists:last(L) )
+  andalso path_filter_ext( ext(L) ).
 
 
-ext(L) -> filename:extension(lists:last(L)).
+ext(L) -> filename:extension( lists:last(L) ).
 
 
 path_filter_dir(".git") -> false;
 path_filter_dir(".git") -> false;
-path_filter_dir(".hg")  -> false;
+path_filter_dir(".hg") -> false;
 path_filter_dir(".svn") -> false;
 path_filter_dir(".svn") -> false;
-path_filter_dir("CVS")  -> false;
-path_filter_dir("log")  -> false;
-path_filter_dir(_)      -> true.
-
-path_filter_file(".rebarinfo")     -> false;   % new rebars
-path_filter_file("LICENSE")        -> false;
-path_filter_file("4913 (deleted)") -> false;   % vim magical file
-path_filter_file("4913")           -> false;
-path_filter_file(_)                -> true.
-
-path_filter_ext(".app")            -> false;
-path_filter_ext(".jpg")            -> false;
-path_filter_ext(".png")            -> false;
-path_filter_ext(".gif")            -> false;
-path_filter_ext(_)                 -> true.
+path_filter_dir("CVS") -> false;
+%path_filter_dir("ebin") -> false;
+path_filter_dir("build") -> false;
+path_filter_dir("_build") -> false;
+path_filter_dir("log") -> false;
+path_filter_dir("node_modules") -> false;
+path_filter_dir(_) -> true.
+
+path_filter_file(".rebarinfo") -> false;
+path_filter_file("LICENSE") -> false;
+path_filter_file("4913 (deleted)") -> false; %% vim magical file
+path_filter_file("4913") -> false;
+path_filter_file(_) -> true.
+
+path_filter_ext(".app") -> false;
+path_filter_ext(".jpg") -> false;
+path_filter_ext(".png") -> false;
+path_filter_ext(".gif") -> false;
+path_filter_ext(_) -> true.
+

+ 7 - 1
src/active_app.erl

@@ -1,6 +1,12 @@
 -module(active_app).
 -module(active_app).
+
 -behaviour(application).
 -behaviour(application).
+
 -export([start/2, stop/1]).
 -export([start/2, stop/1]).
 
 
-start(_StartType, _StartArgs) -> active_sup:start_link().
+
+start(_StartType, _StartArgs) ->
+  active_sup:start_link().
+
 stop(_State) -> ok.
 stop(_State) -> ok.
+

+ 64 - 14
src/active_events.erl

@@ -1,20 +1,70 @@
 -module(active_events).
 -module(active_events).
--include("active.hrl").
+
 -behaviour(gen_event).
 -behaviour(gen_event).
--export([start_link/0, subscribe_onload/1, subscribe_onnew/1, notify_reload/1, subscribe/2]).
--export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]).
 
 
-start_link() -> gen_event:start_link({local, ?MODULE}).
 
 
-subscribe_onload(Function) -> subscribe(reloaded, Function).
-subscribe_onnew(Function) -> subscribe(loaded_new, Function).
-subscribe(Event, Function) -> ok = gen_event:add_sup_handler(?MODULE, {?MODULE, Event}, [Event, Function]).
-notify_reload(Event) -> gen_event:notify(?MODULE, Event).
+-export([
+  start_link/0,
+  subscribe_onload/1,
+  subscribe_onnew/1,
+  notify_reload/1,
+  subscribe/2
+]).
+
+-export([
+  init/1,
+  handle_event/2,
+  handle_call/2,
+  handle_info/2,
+  terminate/2,
+  code_change/3
+]).
+
+
+-type mf() :: {M :: module(), F :: atom()}.
+-spec subscribe_onload(Function :: mf()) -> ok.
+-spec subscribe_onnew(Function :: mf()) -> ok.
+-spec subscribe(Event :: reloaded | loaded_new, Function :: mf()) -> ok.
+-record(event_state, {
+  event :: reloaded | loaded_new,
+  function :: mf()
+}).
+
+
+start_link() ->
+  gen_event:start_link({local, ?MODULE}).
+
+
+subscribe_onload(Function) ->
+  subscribe(reloaded, Function).
+
+subscribe_onnew(Function) ->
+  subscribe(loaded_new, Function).
 
 
-init([Event, Function]) -> {ok, #event_state{event = Event, function = Function}}.
-handle_event({Event, Module}, State = #event_state{event = Event, function = {Mod, Fun}}) -> erlang:apply(Mod, Fun, [[Module]]), {ok, State};
+subscribe(Event, Function) ->
+  ok = gen_event:add_sup_handler(?MODULE, {?MODULE, Event}, [Event, Function]).
+
+notify_reload(Event) ->
+  gen_event:notify(?MODULE, Event).
+
+
+init([Event, Function]) ->
+  {ok, #event_state{event = Event, function = Function}}.
+
+handle_call(_Request, _State) ->
+  erlang:error(not_implemented).
+
+handle_info(_Info, _State) ->
+  erlang:error(not_implemented).
+
+terminate(_Args, _State) ->
+  ok.
+
+code_change(_OldVsn, State, _Extra) ->
+  {ok, State}.
+
+handle_event({Event, Module}, State = #event_state{event = Event, function = {Mod, Fun}}) ->
+  erlang:apply(Mod, Fun, [[Module]]),
+  {ok, State};
 handle_event(_, State) -> {ok, State}.
 handle_event(_, State) -> {ok, State}.
-handle_call(_Request, _State) -> erlang:error(not_implemented).
-handle_info(_Info, _State) -> erlang:error(not_implemented).
-terminate(_Args, _State) -> ok.
-code_change(_OldVsn, State, _Extra) -> {ok, State}.
+

+ 33 - 0
src/active_sh.erl

@@ -0,0 +1,33 @@
+-module(active_sh).
+
+-export([
+  reduce/0,
+  run/1,
+  sh/1,
+  sh/3
+]).
+
+
+% {status,code,msg} = :active_sh.exe(String.to_charlist("mix compile"))
+
+reduce() ->
+  fun({_, Chunk}, Acc) ->
+    [Chunk|Acc]
+  end.
+
+run(Args) ->
+  erlang:open_port({spawn_executable, os:find_executable("sh")},
+    [stream, in, out, eof, use_stdio, stderr_to_stdout, binary, exit_status,
+     {args, ["-c", Args]}, {cd, erlang:element(2, file:get_cwd())}, {env, []}]).
+
+sh(Port) -> sh(Port, reduce(), []).
+sh(Port, Fun, Acc) ->
+  receive
+    {Port, {exit_status, Status}} -> {done, Status, erlang:iolist_to_binary(lists:reverse(Acc))};
+    {Port, {data, {eol, Line}}}   -> sh(Port, Fun, Fun({eol,   Line}, Acc));
+    {Port, {data, {noeol, Line}}} -> sh(Port, Fun, Fun({noeol, Line}, Acc));
+    {Port, {data, Data}}          -> sh(Port, Fun, Fun({data,Data}, Acc))
+  end.
+
+exe(X) -> sh(run(X)).
+

+ 18 - 12
src/active_sup.erl

@@ -1,16 +1,22 @@
 -module(active_sup).
 -module(active_sup).
+
 -behaviour(supervisor).
 -behaviour(supervisor).
--export([start_link/0]).
--export([init/1]).
--define(CHILD(I, Type, Args), {I, {I, start_link, Args}, permanent, 5000, Type, [I]}).
 
 
-start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-init([]) -> 
-    {ok, { 
-        {one_for_one, 5, 10}, 
-        [
-            ?CHILD(active, worker, []), 
-            ?CHILD(active_events, worker, [])
-        ]
-    }}.
+-export([
+  start_link/0,
+  init/1
+]).
+
+
+start_link() ->
+  supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+
+init([]) ->
+  {ok, {
+    {one_for_one, 5, 10}, [
+      {active, {active, start_link, []}, permanent, 5000, worker, [active]},
+      {active_events, {active_events, start_link, []}, permanent, 5000, worker, [active_events]}
+    ]
+  }}.