|
|
- -module(eSync).
- -behaviour(es_gen_ipc).
-
- -compile(inline).
- -compile({inline_size, 128}).
-
- -define(IIF(Cond, Ret1, Ret2), (case Cond of true -> Ret1; _ -> Ret2 end)).
- -define(LOG_ON(Val), Val == true; Val == all; Val == skip_success; is_list(Val), Val =/= []).
-
- -define(Log, log).
- -define(compileCmd, compileCmd).
- -define(extraDirs, extraDirs).
- -define(descendant, descendant).
- -define(onMSyncFun, onMSyncFun).
- -define(onCSyncFun, onCSyncFun).
- -define(swSyncNode, swSyncNode).
- -define(isJustMem, isJustMem).
- -define(debugInfoKeyFun, debugInfoKeyFun).
-
- -define(DefCfgList, [{?Log, all}, {?compileCmd, undefined}, {?extraDirs, undefined}, {?descendant, fix}, {?onMSyncFun, undefined}, {?onCSyncFun, undefined}, {?swSyncNode, false}, {?isJustMem, false}, {?debugInfoKeyFun, undefined}]).
-
- -define(esCfgSync, esCfgSync).
- -define(rootSrcDir, <<"src">>).
-
- -define(logSuccess(Format), canLog(success) andalso error_logger:info_msg("eSync[~p:~p|~p] " ++ Format, [?MODULE, ?FUNCTION_NAME, ?LINE])).
- -define(logSuccess(Format, Args), canLog(success) andalso error_logger:info_msg("eSync[~p:~p|~p] " ++ Format, [?MODULE, ?FUNCTION_NAME, ?LINE] ++ Args)).
-
- -define(logErrors(Format), canLog(errors) andalso error_logger:info_msg("eSync[~p:~p|~p] " ++ Format, [?MODULE, ?FUNCTION_NAME, ?LINE])).
- -define(logErrors(Format, Args), canLog(errors) andalso error_logger:info_msg("eSync[~p:~p|~p] " ++ Format, [?MODULE, ?FUNCTION_NAME, ?LINE] ++ Args)).
-
- -define(logWarnings(Format), canLog(warnings) andalso error_logger:info_msg("eSync[~p:~p|~p] " ++ Format, [?MODULE, ?FUNCTION_NAME, ?LINE])).
- -define(logWarnings(Format, Args), canLog(warnings) andalso error_logger:info_msg("eSync[~p:~p|~p] " ++ Format, [?MODULE, ?FUNCTION_NAME, ?LINE] ++ Args)).
-
- -export([
- start/2,
- start/0,
- stop/0,
- run/0
- ]).
-
- %% API
- -export([
- start_link/0,
- rescan/0,
- pause/0,
- unpause/0,
- setLog/1,
- getLog/0,
- curInfo/0,
- getOnMSync/0,
- setOnMSync/1,
- getOnCSync/0,
- setOnCSync/1,
- swSyncNode/1
- ]).
-
- %% es_gen_ipc callbacks
- -export([
- init/1,
- handleCall/4,
- handleAfter/3,
- handleCast/3,
- handleInfo/3,
- handleOnevent/4,
- terminate/3
- ]).
-
- start(_StartType, _StartArgs) ->
- start_link().
-
- start() ->
- application:ensure_all_started(eSync).
-
- stop() ->
- application:stop(eSync).
-
- run() ->
- case start() of
- {ok, _Started} ->
- unpause(),
- ok;
- {error, Reason} ->
- ?logErrors("start eSync error:~p~n", [Reason])
- end.
-
- -define(SERVER, ?MODULE).
- -define(None, 0).
-
- -record(state, {
- port = undefined
- , onMSyncFun = undefined
- , onCSyncFun = undefined
- , swSyncNode = false
- , srcFiles = #{} :: map()
- , hrlFiles = #{} :: map()
- , configs = #{} :: map()
- , beams = #{} :: map()
- }).
-
- %% ************************************ API start ***************************
- rescan() ->
- es_gen_ipc:cast(?SERVER, miRescan),
- ?logSuccess("start rescaning source files..."),
- ok.
-
- unpause() ->
- es_gen_ipc:cast(?SERVER, miUnpause),
- ok.
-
- pause() ->
- es_gen_ipc:cast(?SERVER, miPause),
- ?logSuccess("Pausing eSync. Call eSync:run() to restart"),
- ok.
-
- curInfo() ->
- es_gen_ipc:call(?SERVER, miCurInfo).
-
- setLog(T) when ?LOG_ON(T) ->
- setEnv(log, T),
- loadCfg(),
- ?logSuccess("Console Notifications Enabled"),
- ok;
- setLog(_) ->
- setEnv(log, none),
- loadCfg(),
- ?logSuccess("Console Notifications Disabled"),
- ok.
-
- getLog() ->
- ?esCfgSync:getv(log).
-
- swSyncNode(IsSync) ->
- es_gen_ipc:cast(?SERVER, {miSyncNode, IsSync}),
- ok.
-
- getOnMSync() ->
- es_gen_ipc:call(?SERVER, miGetOnMSync).
-
- setOnMSync(Fun) ->
- es_gen_ipc:call(?SERVER, {miSetOnMSync, Fun}).
-
- getOnCSync() ->
- es_gen_ipc:call(?SERVER, miGetOnCSync).
-
- setOnCSync(Fun) ->
- es_gen_ipc:call(?SERVER, {miSetOnCSync, Fun}).
-
- %% ************************************ API end ***************************
- start_link() ->
- es_gen_ipc:start_link({local, ?SERVER}, ?MODULE, ?None, []).
-
- %% status :: waiting | running | pause
- init(_Args) ->
- erlang:process_flag(trap_exit, true),
- loadCfg(),
- {ok, waiting, #state{onMSyncFun = ?esCfgSync:getv(?onMSyncFun), onCSyncFun = ?esCfgSync:getv(?onCSyncFun), swSyncNode = ?esCfgSync:getv(?swSyncNode)}, {doAfter, ?None}}.
-
- handleAfter(?None, waiting, State) ->
- %% 启动port 发送监听目录信息
- PortName = fileSyncPath("fileSync"),
- Opts = [{packet, 4}, binary, exit_status, use_stdio],
- Port = erlang:open_port({spawn_executable, PortName}, Opts),
- {kpS, State#state{port = Port}, {sTimeout, 4000, waitConnOver}}.
-
- handleCall(miGetOnMSync, _, #state{onMSyncFun = OnMSyncFun} = State, _From) ->
- {reply, OnMSyncFun, State};
- handleCall({miSetOnMSync, Fun}, _, State, _From) ->
- {reply, ok, State#state{onMSyncFun = Fun}};
- handleCall(miGetOnCSync, _, #state{onCSyncFun = OnCSyncFun} = State, _From) ->
- {reply, OnCSyncFun, State};
- handleCall({miSetOnCSync, Fun}, _, State, _From) ->
- {reply, ok, State#state{onCSyncFun = Fun}};
- handleCall(miCurInfo, Status, State, _Form) ->
- {reply, {Status, erlang:get(), State}, State};
- handleCall(_Request, _, _State, _From) ->
- kpS_S.
-
- handleCast(miPause, running, State) ->
- {nextS, pause, State};
- handleCast(miUnpause, pause, State) ->
- {nextS, running, State};
- handleCast({miSyncNode, IsSync}, _, State) ->
- case IsSync of
- true ->
- {kpS, State#state{swSyncNode = true}};
- _ ->
- {kpS, State#state{swSyncNode = false}}
- end;
- handleCast(miRescan, _, State) ->
- {Srcs, Hrls, Configs, Beams} = collSrcFiles(false),
- {kpS_S, State#state{srcFiles = Srcs, hrlFiles = Hrls, configs = Configs, beams = Beams}};
- handleCast(_Msg, _, _State) ->
- kpS_S.
-
- handleInfo({Port, {data, Data}}, Status, #state{srcFiles = Srcs, hrlFiles = Hrls, configs = Configs, beams = Beams, onMSyncFun = OnMSyncFun, onCSyncFun = OnCSyncFun, swSyncNode = SwSyncNode} = State) ->
- case Status of
- running ->
- FileList = binary:split(Data, <<"\r\n">>, [global]),
- %% 收集改动了beam hrl src 文件 然后执行相应的逻辑
- {CBeams, CConfigs, CHrls, CSrcs, NewSrcs, NewHrls, NewConfigs, NewBeams} = classifyChangeFile(FileList, [], [], #{}, #{}, Srcs, Hrls, Configs, Beams),
- fireOnSync(OnCSyncFun, CConfigs),
- reloadChangedMod(CBeams, SwSyncNode, OnMSyncFun, []),
- case ?esCfgSync:getv(?compileCmd) of
- undefined ->
- LastCHrls = collIncludeCHrls(maps:keys(CHrls), NewHrls, CHrls, #{}),
- NReSrcs = collIncludeCErls(maps:keys(LastCHrls), NewSrcs, CSrcs, #{}),
- recompileChangeSrcFile(maps:iterator(NReSrcs), SwSyncNode),
- {kpS, State#state{srcFiles = NewSrcs, hrlFiles = NewHrls, configs = NewConfigs, beams = NewBeams}};
- CmdStr ->
- case maps:size(CSrcs) > 0 orelse CHrls =/= [] of
- true ->
- RetStr = os:cmd(CmdStr),
- RetList = string:split(RetStr, "\n", all),
- ?logSuccess("compile cmd:~p ~n", [CmdStr]),
- ?logSuccess("the result: ~n ", []),
- [
- begin
- ?logSuccess("~p ~n", [OneRet])
- end || OneRet <- RetList, OneRet =/= []
- ],
- ok;
- _ ->
- ignore
- end,
- kpS_S
- end;
- _ ->
- case Data of
- <<"init">> ->
- %% port启动成功 先发送监听目录配置
- {AddExtraSrcDirs, AddOnlySrcDirs, OnlySrcDirs, DelSrcDirs} = mergeExtraDirs(false),
- AddExtraStr = string:join([filename:nativename(OneDir) || OneDir <- AddExtraSrcDirs], "|"),
- AddOnlyStr = string:join([filename:nativename(OneDir) || OneDir <- AddOnlySrcDirs], "|"),
- OnlyStr = string:join([filename:nativename(OneDir) || OneDir <- OnlySrcDirs], "|"),
- DelStr = string:join([filename:nativename(OneDir) || OneDir <- DelSrcDirs], "|"),
- AllStr = string:join([AddExtraStr, AddOnlyStr, OnlyStr, DelStr], "\r\n"),
- erlang:port_command(Port, AllStr),
- ?logSuccess("eSync connect fileSync success..."),
- %% 然后收集一下监听目录下的src文件
- {BSrcs, BHrls, BConfigs, BBeams} = collSrcFiles(true),
- {nextS, running, State#state{srcFiles = BSrcs, hrlFiles = BHrls, configs = BConfigs, beams = BBeams}, {isHib, true}};
- _ ->
- ?logErrors("error, receive unexpect port msg ~p~n", [Data]),
- kpS_S
- end
- end;
- handleInfo({Port, closed}, running, #state{port = Port} = _State) ->
- ?logErrors("receive port closed ~n"),
- {nextS, port_close, _State};
- handleInfo({'EXIT', Port, Reason}, running, #state{port = Port} = _State) ->
- ?logErrors("receive port exit Reason:~p ~n", [Reason]),
- {nextS, {port_EXIT, Reason}, _State};
- handleInfo({Port, {exit_status, Status}}, running, #state{port = Port} = _State) ->
- ?logErrors("receive port exit_status Status:~p ~p ~n", [Status, Port]),
- {nextS, {port_exit_status, Status}, _State};
- handleInfo({'EXIT', _Pid, _Reason}, running, _State) ->
- kpS_S;
- handleInfo(_Msg, _, _State) ->
- ?logErrors("receive unexpect msg:~p ~n", [_Msg]),
- kpS_S.
-
- handleOnevent(sTimeout, waitConnOver, Status, State) ->
- ?logErrors("failed to connect the fileSync to stop stauts:~p state:~p ~n", [Status, State]),
- stop;
- handleOnevent(_EventType, _EventContent, _Status, _State) ->
- kpS_S.
-
- terminate(_Reason, _Status, _State) ->
- ok.
-
- %% ************************************************* utils start *******************************************************
- getModSrcDir(Module) ->
- case code:is_loaded(Module) of
- {file, _} ->
- try
- %% Get some module info...
- Props = Module:module_info(compile),
- Source = proplists:get_value(source, Props, ""),
- %% Ensure that the file exists, is a decendent of the tree, and how to deal with that
- IsFile = filelib:is_regular(Source),
- IsDescendant = isDescendent(Source),
- Descendant = ?esCfgSync:getv(?descendant),
- LastSource =
- case {IsFile, IsDescendant, Descendant} of
- %% is file and descendant, we're good to go
- {true, true, _} -> Source;
- %% is not a descendant, but we allow them, so good to go
- {true, false, allow} -> Source;
- %% is not a descendant, and we fix non-descendants, so let's fix it
- {_, false, fix} -> fixDescendantSource(Source, IsFile);
- %% Anything else, and we don't know what to do, so let's just bail.
- _ -> undefined
- end,
- case LastSource of
- undefined ->
- undefined;
- _ ->
- %% Get the source dir...
- Dir = filename:dirname(LastSource),
- getSrcDir(Dir)
- end
- catch _ : _ ->
- undefined
- end;
- _ ->
- undefined
- end.
-
- getModOpts(Module) ->
- case code:is_loaded(Module) of
- {file, _} ->
- try
- Props = Module:module_info(compile),
- BeamDir = filename:dirname(code:which(Module)),
- Options1 = proplists:get_value(options, Props, []),
- %% transform `outdir'
- Options2 = transformOutdir(BeamDir, Options1),
- Options3 = ensureInclude(Options2),
- %% transform the include directories
- Options4 = transformAllIncludes(Module, BeamDir, Options3),
- %% maybe_add_compile_info
- Options5 = maybeAddCompileInfo(Options4),
- %% add filetype to options (DTL, LFE, erl, etc)
- Options6 = addFileType(Module, Options5),
- Options7 = lists:keyreplace(debug_info_key, 1, Options6, debugInfoKeyFun()),
- {ok, Options7}
- catch ExType:Error ->
- ?logWarnings("~p:0: ~p looking for options: ~p. ~n", [Module, ExType, Error]),
- undefined
- end;
- _ ->
- undefined
- end.
-
- tryGetModOpts(Module) ->
- try
- Props = Module:module_info(compile),
- BeamDir = filename:dirname(code:which(Module)),
- Options1 = proplists:get_value(options, Props, []),
- %% transform `outdir'
- Options2 = transformOutdir(BeamDir, Options1),
- Options3 = ensureInclude(Options2),
- %% transform the include directories
- Options4 = transformAllIncludes(Module, BeamDir, Options3),
- %% maybe_add_compile_info
- Options5 = maybeAddCompileInfo(Options4),
- %% add filetype to options (DTL, LFE, erl, etc)
- Options6 = addFileType(Module, Options5),
- Options7 = lists:keyreplace(debug_info_key, 1, Options6, debugInfoKeyFun()),
- {ok, Options7}
- catch _ExType:_Error ->
- undefiend
- end.
-
- tryGetSrcOpts(SrcDir) ->
- %% Then we dig back through the parent directories until we find our include directory
- NewDirName = filename:dirname(SrcDir),
- case getOptions(NewDirName) of
- {ok, _Options} = Opts ->
- Opts;
- _ ->
- BaseName = filename:basename(SrcDir),
- IsBaseSrcDir = BaseName == ?rootSrcDir,
- case NewDirName =/= SrcDir andalso not IsBaseSrcDir of
- true ->
- tryGetSrcOpts(NewDirName);
- _ when IsBaseSrcDir ->
- try filelib:fold_files(SrcDir, ".*\\.(erl|dtl|lfe|ex)$", true,
- fun(OneFile, Acc) ->
- Mod = binary_to_atom(filename:basename(OneFile, filename:extension(OneFile))),
- case tryGetModOpts(Mod) of
- {ok, _Options} = Opts ->
- throw(Opts);
- _ ->
- Acc
- end
- end, undefined)
- catch
- {ok, _Options} = Opts ->
- Opts;
- _ExType:_Error ->
- ?logWarnings("looking src options error ~p:~p. ~n", [_ExType, _Error]),
- undefined
- end;
- _ ->
- undefined
- end
- end.
-
- transformOutdir(BeamDir, Options) ->
- [{outdir, BeamDir} | proplists:delete(outdir, Options)].
-
- ensureInclude(Options) ->
- case proplists:get_value(i, Options) of
- undefined -> [{i, "include"} | Options];
- _ -> Options
- end.
-
- transformAllIncludes(Module, BeamDir, Options) ->
- [begin
- case Opt of
- {i, IncludeDir} ->
- {ok, SrcDir} = getModSrcDir(Module),
- {ok, IncludeDir2} = determineIncludeDir(IncludeDir, BeamDir, SrcDir),
- {i, IncludeDir2};
- _ ->
- Opt
- end
- end || Opt <- Options].
-
- maybeAddCompileInfo(Options) ->
- case lists:member(compile_info, Options) of
- true -> Options;
- false -> addCompileInfo(Options)
- end.
-
- addCompileInfo(Options) ->
- CompInfo = [{K, V} || {K, V} <- Options, lists:member(K, [outdir, i])],
- [{compile_info, CompInfo} | Options].
-
- addFileType(Module, Options) ->
- Type = getFileType(Module),
- [{type, Type} | Options].
-
- %% This will check if the given module or source file is an ErlyDTL template.
- %% Currently, this is done by checking if its reported source path ends with
- %% ".dtl.erl".
- getFileType(Module) when is_atom(Module) ->
- Props = Module:module_info(compile),
- Source = proplists:get_value(source, Props, ""),
- getFileType(Source);
-
- getFileType(Source) ->
- Ext = filename:extension(Source),
- Root = filename:rootname(Source),
- SecondExt = filename:extension(Root),
- case Ext of
- <<".erl">> when SecondExt =:= <<".dtl">> -> dtl;
- <<".dtl">> -> dtl;
- <<".erl">> -> erl;
- <<".lfe">> -> lfe;
- <<".ex">> -> elixir;
- ".erl" when SecondExt =:= ".dtl" -> dtl;
- ".dtl" -> dtl;
- ".erl" -> erl;
- ".lfe" -> lfe;
- ".ex" -> elixir
- end.
-
- %% This will search back to find an appropriate include directory, by
- %% searching further back than "..". Instead, it will extract the basename
- %% (probably "include" from the include pathfile, and then search backwards in
- %% the directory tree until it finds a directory with the same basename found
- %% above.
- determineIncludeDir(IncludeDir, BeamDir, SrcDir) ->
- IncludeBase = filename:basename(IncludeDir),
- case determineIncludeDirFromBeamDir(IncludeBase, IncludeDir, BeamDir) of
- {ok, _Dir} = RetD -> RetD;
- undefined ->
- {ok, Cwd} = file:get_cwd(),
- % Cwd2 = normalizeCaseWindowsDir(Cwd),
- % SrcDir2 = normalizeCaseWindowsDir(SrcDir),
- % IncludeBase2 = normalizeCaseWindowsDir(IncludeBase),
- case findIncludeDirFromAncestors(SrcDir, Cwd, IncludeBase) of
- {ok, _Dir} = RetD -> RetD;
- undefined -> {ok, IncludeDir} %% Failed, just stick with original
- end
- end.
-
- %% First try to see if we have an include file alongside our ebin directory, which is typically the case
- determineIncludeDirFromBeamDir(IncludeBase, IncludeDir, BeamDir) ->
- BeamBasedIncDir = filename:join(filename:dirname(BeamDir), IncludeBase),
- case filelib:is_dir(BeamBasedIncDir) of
- true -> {ok, BeamBasedIncDir};
- false ->
- BeamBasedIncDir2 = filename:join(filename:dirname(BeamDir), IncludeDir),
- case filelib:is_dir(BeamBasedIncDir2) of
- true -> {ok, BeamBasedIncDir2};
- _ ->
- undefined
- end
- end.
-
- %% get the src dir
- getRootSrcDirFromSrcDir(SrcDir) ->
- NewDirName = filename:dirname(SrcDir),
- BaseName = filename:basename(SrcDir),
- case BaseName of
- ?rootSrcDir ->
- NewDirName;
- _ ->
- case NewDirName =/= SrcDir of
- true ->
- getRootSrcDirFromSrcDir(NewDirName);
- _ ->
- undefined
- end
- end.
-
- %% Then we dig back through the parent directories until we find our include directory
- findIncludeDirFromAncestors(Cwd, Cwd, _) -> undefined;
- findIncludeDirFromAncestors("/", _, _) -> undefined;
- findIncludeDirFromAncestors(".", _, _) -> undefined;
- findIncludeDirFromAncestors("", _, _) -> undefined;
- findIncludeDirFromAncestors(Dir, Cwd, IncludeBase) ->
- NewDirName = filename:dirname(Dir),
- AttemptDir = filename:join(NewDirName, IncludeBase),
- case filelib:is_dir(AttemptDir) of
- true ->
- {ok, AttemptDir};
- false ->
- case NewDirName =/= Dir of
- true ->
- findIncludeDirFromAncestors(NewDirName, Cwd, IncludeBase);
- _ ->
- undefined
- end
- end.
-
- % normalizeCaseWindowsDir(Dir) ->
- % case os:type() of
- % {win32, _} -> Dir; %string:to_lower(Dir);
- % {unix, _} -> Dir
- % end.
-
- %% This is an attempt to intelligently fix paths in modules when a
- %% release is moved. Essentially, it takes a module name and its original path
- %% from Module:module_info(compile), say
- %% "/some/original/path/site/src/pages/somepage.erl", and then breaks down the
- %% path one by one prefixing it with the current working directory until it
- %% either finds a match, or fails. If it succeeds, it returns the Path to the
- %% new Source file.
- fixDescendantSource([], _IsFile) ->
- undefined;
- fixDescendantSource(Path, IsFile) ->
- {ok, Cwd} = file:get_cwd(),
- PathParts = filename:split(Path),
- case makeDescendantSource(PathParts, Cwd) of
- undefined -> case IsFile of true -> Path; _ -> undefined end;
- FoundPath -> FoundPath
- end.
-
- makeDescendantSource([], _Cwd) ->
- undefined;
- makeDescendantSource([_ | T], Cwd) ->
- PathAttempt = filename:join([Cwd | T]),
- case filelib:is_regular(PathAttempt) of
- true -> PathAttempt;
- false -> makeDescendantSource(T, Cwd)
- end.
-
- isDescendent(Path) ->
- {ok, Cwd} = file:get_cwd(),
- lists:sublist(Path, length(Cwd)) == Cwd.
-
- %% @private Find the src directory for the specified Directory; max 15 iterations
- getSrcDir(Dir) ->
- getSrcDir(Dir, 15).
-
- getSrcDir(_Dir, 0) ->
- undefined;
- getSrcDir(Dir, Ctr) ->
- HasCode = filelib:wildcard("*.erl", Dir) /= [] orelse
- filelib:wildcard("*.hrl", Dir) /= [] orelse
- filelib:wildcard("*.dtl", Dir) /= [] orelse
- filelib:wildcard("*.lfe", Dir) /= [] orelse
- filelib:wildcard("*.ex", Dir) /= [],
- if
- HasCode -> {ok, Dir};
- true -> getSrcDir(filename:dirname(Dir), Ctr - 1)
- end.
-
- mergeExtraDirs(IsAddPath) ->
- case ?esCfgSync:getv(?extraDirs) of
- undefined ->
- {[], [], [], []};
- ExtraList ->
- FunMerge =
- fun(OneExtra, {AddExtraDirs, AddOnlyDirs, OnlyDirs, DelDirs} = AllAcc) ->
- case OneExtra of
- {addExtra, DirsAndOpts} ->
- Adds =
- [
- begin
- case IsAddPath of
- true ->
- case proplists:get_value(outdir, Opts) of
- undefined ->
- true;
- Path ->
- ok = filelib:ensure_dir(Path),
- true = code:add_pathz(Path)
- end;
- _ ->
- ignore
- end,
- filename:absname(Dir)
- end || {Dir, Opts} <- DirsAndOpts
- ],
- setelement(1, AllAcc, Adds ++ AddExtraDirs);
- {addOnly, DirsAndOpts} ->
- Adds =
- [
- begin
- case IsAddPath of
- true ->
- case proplists:get_value(outdir, Opts) of
- undefined ->
- true;
- Path ->
- ok = filelib:ensure_dir(Path),
- true = code:add_pathz(Path)
- end;
- _ ->
- ignore
- end,
- filename:absname(Dir)
- end || {Dir, Opts} <- DirsAndOpts
- ],
- setelement(2, AllAcc, Adds ++ AddOnlyDirs);
- {only, DirsAndOpts} ->
- Onlys =
- [
- begin
- case IsAddPath of
- true ->
- case proplists:get_value(outdir, Opts) of
- undefined ->
- true;
- Path ->
- ok = filelib:ensure_dir(Path),
- true = code:add_pathz(Path)
- end;
- _ ->
- ignore
- end,
- filename:absname(Dir)
- end || {Dir, Opts} <- DirsAndOpts
- ],
- setelement(3, AllAcc, Onlys ++ OnlyDirs);
- {del, DirsAndOpts} ->
- Dels =
- [
- begin
- filename:absname(Dir)
- end || {Dir, _Opts} <- DirsAndOpts
- ],
- setelement(4, AllAcc, Dels ++ DelDirs)
- end
- end,
- lists:foldl(FunMerge, {[], [], [], []}, ExtraList)
- end.
-
- -define(RegExp, <<".*\\.(erl|hrl|beam|config|dtl|lfe|ex)$">>).
- collSrcFiles(IsAddPath) ->
- {AddExtraSrcDirs, AddOnlySrcDirs, OnlySrcDirs, DelSrcDirs} = mergeExtraDirs(IsAddPath),
- CollFiles = filelib:fold_files(filename:absname(<<"./">>), ?RegExp, true,
- fun(OneFile, {Srcs, Hrls, Configs, Beams} = Acc) ->
- case isOnlyDir(OnlySrcDirs, OneFile) andalso (not isDelDir(DelSrcDirs, OneFile)) of
- true ->
- MTimeSec = dateTimeToSec(filelib:last_modified(OneFile)),
- case filename:extension(OneFile) of
- <<".beam">> ->
- BeamMod = binary_to_atom(filename:basename(OneFile, <<".beam">>)),
- setelement(4, Acc, Beams#{BeamMod => MTimeSec});
- <<".config">> ->
- setelement(3, Acc, Configs#{OneFile => MTimeSec});
- <<".hrl">> ->
- setelement(2, Acc, Hrls#{OneFile => MTimeSec});
- <<>> ->
- Acc;
- _ ->
- RootSrcDir =
- case getRootSrcDirFromSrcDir(OneFile) of
- undefined ->
- filename:dirname(OneFile);
- RetSrcDir ->
- RetSrcDir
- end,
- case getOptions(RootSrcDir) of
- undefined ->
- Mod = binary_to_atom(filename:basename(OneFile, filename:extension(OneFile))),
- case getModOpts(Mod) of
- {ok, Options} ->
- setOptions(RootSrcDir, Options);
- _ ->
- ignore
- end;
- _ ->
- ignore
- end,
- setelement(1, Acc, Srcs#{OneFile => MTimeSec})
- end;
- _ ->
- Acc
- end
- end, {#{}, #{}, #{}, #{}}),
-
- FunCollAddExtra =
- fun(OneDir, FilesAcc) ->
- filelib:fold_files(?IIF(is_list(OneDir), list_to_binary(OneDir), OneDir), ?RegExp, true,
- fun(OneFile, {Srcs, Hrls, Configs, Beams} = Acc) ->
- MTimeSec = dateTimeToSec(filelib:last_modified(OneFile)),
- case filename:extension(OneFile) of
- <<".beam">> ->
- BeamMod = binary_to_atom(filename:basename(OneFile, <<".beam">>)),
- setelement(4, Acc, Beams#{BeamMod => MTimeSec});
- <<".config">> ->
- setelement(3, Acc, Configs#{OneFile => MTimeSec});
- <<".hrl">> ->
- setelement(2, Acc, Hrls#{OneFile => MTimeSec});
- <<>> ->
- Acc;
- _ ->
- setelement(1, Acc, Srcs#{OneFile => MTimeSec})
- end
- end, FilesAcc)
- end,
- AddExtraCollFiles = lists:foldl(FunCollAddExtra, CollFiles, AddExtraSrcDirs),
-
- FunCollAddOnly =
- fun(OneDir, FilesAcc) ->
- filelib:fold_files(?IIF(is_list(OneDir), list_to_binary(OneDir), OneDir), ?RegExp, false,
- fun(OneFile, {Srcs, Hrls, Configs, Beams} = Acc) ->
- MTimeSec = dateTimeToSec(filelib:last_modified(OneFile)),
- case filename:extension(OneFile) of
- <<".beam">> ->
- BeamMod = binary_to_atom(filename:basename(OneFile, <<".beam">>)),
- setelement(4, Acc, Beams#{BeamMod => MTimeSec});
- <<".config">> ->
- setelement(3, Acc, Configs#{OneFile => MTimeSec});
- <<".hrl">> ->
- setelement(2, Acc, Hrls#{OneFile => MTimeSec});
- <<>> ->
- Acc;
- _ ->
- setelement(1, Acc, Srcs#{OneFile => MTimeSec})
- end
- end, FilesAcc)
- end,
- lists:foldl(FunCollAddOnly, AddExtraCollFiles, AddOnlySrcDirs).
-
-
- isOnlyDir([], _) ->
- true;
- isOnlyDir(ReplaceDirs, SrcDir) ->
- isMatchDir(ReplaceDirs, SrcDir).
-
- isDelDir([], _) ->
- false;
- isDelDir(ReplaceDirs, SrcDir) ->
- isMatchDir(ReplaceDirs, SrcDir).
-
- isMatchDir([], _SrcDir) ->
- false;
- isMatchDir([SrcDir | _ReplaceDirs], SrcDir) ->
- true;
- isMatchDir([OneDir | ReplaceDirs], SrcDir) ->
- case re:run(SrcDir, OneDir) of
- nomatch -> isMatchDir(ReplaceDirs, SrcDir);
- _ -> true
- end.
-
- getEnv(Var, Default) ->
- case application:get_env(eSync, Var) of
- {ok, Value} ->
- Value;
- _ ->
- Default
- end.
-
- setEnv(Var, Val) ->
- ok = application:set_env(eSync, Var, Val).
-
- canLog(MsgType) ->
- case eSync:getLog() of
- true -> true;
- all -> true;
- none -> false;
- false -> false;
- skip_success -> MsgType == errors orelse MsgType == warnings;
- L when is_list(L) -> lists:member(MsgType, L);
- _ -> false
- end.
-
- %% 注意 map类型的数据不能当做key
- -type key() :: atom() | binary() | bitstring() | float() | integer() | list() | tuple().
- -type value() :: atom() | binary() | bitstring() | float() | integer() | list() | tuple() | map().
-
- -spec load(term(), [{key(), value()}]) -> ok.
- load(Module, KVs) ->
- Forms = forms(Module, KVs),
- {ok, Module, Bin} = compile:forms(Forms),
- code:soft_purge(Module),
- {module, Module} = code:load_binary(Module, atom_to_list(Module), Bin),
- ok.
-
- forms(Module, KVs) ->
- %% -module(Module).
- Mod = erl_syntax:attribute(erl_syntax:atom(module), [erl_syntax:atom(Module)]),
- %% -export([getv/0]).
- ExportList = [erl_syntax:arity_qualifier(erl_syntax:atom(getv), erl_syntax:integer(1))],
- Export = erl_syntax:attribute(erl_syntax:atom(export), [erl_syntax:list(ExportList)]),
- %% getv(K) -> V
- Function = erl_syntax:function(erl_syntax:atom(getv), lookup_clauses(KVs, [])),
- [erl_syntax:revert(X) || X <- [Mod, Export, Function]].
-
- lookup_clause(Key, Value) ->
- Var = erl_syntax:abstract(Key),
- Body = erl_syntax:abstract(Value),
- erl_syntax:clause([Var], [], [Body]).
-
- lookup_clause_anon() ->
- Var = erl_syntax:variable("_"),
- Body = erl_syntax:atom(undefined),
- erl_syntax:clause([Var], [], [Body]).
-
- lookup_clauses([], Acc) ->
- lists:reverse(lists:flatten([lookup_clause_anon() | Acc]));
- lookup_clauses([{Key, Value} | T], Acc) ->
- lookup_clauses(T, [lookup_clause(Key, Value) | Acc]).
-
- getOptions(SrcDir) ->
- case erlang:get(SrcDir) of
- undefined ->
- undefined;
- Options ->
- {ok, Options}
- end.
-
- setOptions(SrcDir, Options) ->
- case erlang:get(SrcDir) of
- undefined ->
- erlang:put(SrcDir, Options);
- OldOptions ->
- NewOptions =
- case lists:keytake(compile_info, 1, Options) of
- {value, {compile_info, ValList1}, Options1} ->
- case lists:keytake(compile_info, 1, OldOptions) of
- {value, {compile_info, ValList2}, Options2} ->
- [{compile_info, lists:usort(ValList1 ++ ValList2)} | lists:usort(Options1 ++ Options2)];
- _ ->
- lists:usort(Options ++ OldOptions)
- end;
- _ ->
- lists:usort(Options ++ OldOptions)
- end,
- erlang:put(SrcDir, NewOptions)
- end.
-
- loadCfg() ->
- KVs = [{Key, getEnv(Key, DefVal)} || {Key, DefVal} <- ?DefCfgList],
- load(?esCfgSync, KVs).
-
- %% ******************************* 加载与编译相关 **********************************************************************
- printResults(_Module, SrcFile, [], []) ->
- ?logSuccess("~s Recompiled", [SrcFile]);
- printResults(_Module, SrcFile, [], Warnings) ->
- formatErrors(logWarnings, SrcFile, [], Warnings);
- printResults(_Module, SrcFile, Errors, Warnings) ->
- formatErrors(logErrors, SrcFile, Errors, Warnings).
-
- %% @private Print error messages in a pretty and user readable way.
- formatErrors(LogFun, File, Errors, Warnings) ->
- AllErrors1 = lists:sort(lists:flatten([X || {_, X} <- Errors])),
- AllErrors2 = [{Line, "Error", Module, Description} || {Line, Module, Description} <- AllErrors1],
- AllWarnings1 = lists:sort(lists:flatten([X || {_, X} <- Warnings])),
- AllWarnings2 = [{Line, "Warning", Module, Description} || {Line, Module, Description} <- AllWarnings1],
- Everything = lists:sort(AllErrors2 ++ AllWarnings2),
- FPck =
- fun({Line, Prefix, Module, ErrorDescription}) ->
- Msg = formatError(Module, ErrorDescription),
- case LogFun of
- logWarnings ->
- ?logWarnings("~s: ~p: ~s: ~s", [File, Line, Prefix, Msg]);
- logErrors ->
- ?logErrors("~s: ~p: ~s: ~s", [File, Line, Prefix, Msg])
- end
- end,
- [FPck(X) || X <- Everything],
- ok.
-
- formatError(Module, ErrorDescription) ->
- case erlang:function_exported(Module, format_error, 1) of
- true -> Module:format_error(ErrorDescription);
- false -> io_lib:format("~s", [ErrorDescription])
- end.
-
- fireOnSync(OnSyncFun, Modules) ->
- case OnSyncFun of
- undefined -> ok;
- Funs when is_list(Funs) -> onSyncApplyList(Funs, Modules);
- Fun -> onSyncApply(Fun, Modules)
- end.
-
- onSyncApplyList(Funs, Modules) ->
- [onSyncApply(Fun, Modules) || Fun <- Funs].
-
- onSyncApply({M, F}, Modules) ->
- try erlang:apply(M, F, [Modules])
- catch
- C:R:S ->
- ?logErrors("apply sync fun ~p:~p(~p) error ~p", [M, F, Modules, {C, R, S}])
- end;
- onSyncApply(Fun, Modules) when is_function(Fun) ->
- try Fun(Modules)
- catch
- C:R:S ->
- ?logErrors("apply sync fun ~p(~p) error ~p", [Fun, Modules, {C, R, S}])
- end.
-
- reloadChangedMod([], _SwSyncNode, OnSyncFun, Acc) ->
- fireOnSync(OnSyncFun, Acc);
- reloadChangedMod([Module | LeftMod], SwSyncNode, OnSyncFun, Acc) ->
- case Module == es_gen_ipc orelse code:get_object_code(Module) of
- true ->
- ignore;
- error ->
- ?logErrors("Error loading object code for ~p", [Module]),
- reloadChangedMod(LeftMod, SwSyncNode, OnSyncFun, Acc);
- {Module, Binary, Filename} ->
- case code:load_binary(Module, Filename, Binary) of
- {module, Module} ->
- ?logSuccess("Reloaded(Beam changed) Mod: ~s Success", [Module]),
- syncLoadModOnAllNodes(SwSyncNode, Module, Binary, changed);
- {error, What} ->
- ?logErrors("Reloaded(Beam changed) Mod: ~s Errors Reason:~p", [Module, What])
- end,
- reloadChangedMod(LeftMod, SwSyncNode, OnSyncFun, [Module | Acc])
- end.
-
- getNodes() ->
- lists:usort(lists:flatten(nodes() ++ [erpc:call(X, erlang, nodes, []) || X <- nodes()])) -- [node()].
-
- syncLoadModOnAllNodes(false, _Module, _Binary, _Reason) ->
- ignore;
- syncLoadModOnAllNodes(true, Module, Binary, Reason) ->
- %% Get a list of nodes known by this node, plus all attached nodes.
- Nodes = getNodes(),
- NumNodes = length(Nodes),
- [
- begin
- ?logSuccess("Do Reloading '~s' on ~p", [Module, Node]),
- erpc:call(Node, code, ensure_loaded, [Module]),
- case erpc:call(Node, code, which, [Module]) of
- Filename when is_binary(Filename) orelse is_list(Filename) ->
- %% File exists, overwrite and load into VM.
- ok = erpc:call(Node, file, write_file, [Filename, Binary]),
- erpc:call(Node, code, purge, [Module]),
-
- case erpc:call(Node, code, load_file, [Module]) of
- {module, Module} ->
- ?logSuccess("Reloaded(Beam ~p) Mod:~s and write Success on node:~p", [Reason, Module, Node]);
- {error, What} ->
- ?logErrors("Reloaded(Beam ~p) Mod:~s and write Errors on node:~p Reason:~p", [Module, Node, What])
- end;
- _ ->
- %% File doesn't exist, just load into VM.
- case erpc:call(Node, code, load_binary, [Module, undefined, Binary]) of
- {module, Module} ->
- ?logSuccess("Reloaded(Beam ~p) Mod:~s Success on node:~p", [Reason, Module, Node]);
- {error, What} ->
- ?logErrors("Reloaded(Beam ~p) Mod:~s Errors on node:~p Reason:~p", [Reason, Module, Node, What])
- end
- end
- end || Node <- Nodes
- ],
- ?logSuccess("Reloaded(Beam changed) Mod: ~s on ~p nodes:~p", [Module, NumNodes, Nodes]).
-
- recompileChangeSrcFile(Iterator, SwSyncNode) ->
- case maps:next(Iterator) of
- {File, _V, NextIterator} ->
- recompileSrcFile(File, SwSyncNode),
- recompileChangeSrcFile(NextIterator, SwSyncNode);
- _ ->
- ok
- end.
-
- erlydtlCompile(SrcFile, Options) ->
- F =
- fun({outdir, OutDir}, Acc) -> [{out_dir, OutDir} | Acc];
- (OtherOption, Acc) -> [OtherOption | Acc]
- end,
- DtlOptions = lists:foldl(F, [], Options),
- Module = binary_to_atom(lists:flatten(filename:basename(SrcFile, ".dtl") ++ "_dtl")),
- Compiler = erlydtl,
- Compiler:compile(SrcFile, Module, DtlOptions).
-
- elixir_compile(SrcFile, Options) ->
- Outdir = proplists:get_value(outdir, Options),
- Compiler = ':Elixir.Kernel.ParallelCompiler',
- Modules = Compiler:files_to_path([SrcFile], Outdir),
- Loader =
- fun(Module) ->
- Outfile = code:which(Module),
- Binary = file:read_file(Outfile),
- {Module, Binary}
- end,
- Results = lists:map(Loader, Modules),
- {ok, multiple, Results, []}.
-
- lfe_compile(SrcFile, Options) ->
- Compiler = lfe_comp,
- Compiler:file(SrcFile, Options).
-
- getCompileFunAndModuleName(SrcFile) ->
- case getFileType(SrcFile) of
- erl ->
- {fun compile:file/2, binary_to_atom(filename:basename(SrcFile, <<".erl">>))};
- dtl ->
- {fun erlydtlCompile/2, list_to_atom(lists:flatten(binary_to_list(filename:basename(SrcFile, <<".dtl">>)) ++ "_dtl"))};
- lfe ->
- {fun lfe_compile/2, binary_to_atom(filename:basename(SrcFile, <<".lfe">>))};
- elixir ->
- {fun elixir_compile/2, binary_to_atom(filename:basename(SrcFile, <<".ex">>))}
- end.
-
- getObjectCode(Module) ->
- case code:get_object_code(Module) of
- {Module, B, Filename} -> {B, Filename};
- _ -> {undefined, undefined}
- end.
-
- reloadIfNecessary(Module, OldBinary, Binary, Filename, SwSyncNode) ->
- case Binary =/= OldBinary of
- true ->
- %% Try to load the module...
- case code:ensure_loaded(Module) of
- {module, Module} ->
- case code:load_binary(Module, Filename, Binary) of
- {module, Module} ->
- ?logSuccess("Reloaded(Beam recompiled) Mod:~s Success", [Module]),
- syncLoadModOnAllNodes(SwSyncNode, Module, Binary, recompiled);
- {error, What} ->
- ?logErrors("Reloaded(Beam recompiled) Mod:~s Errors Reason:~p", [Module, What])
- end;
- {error, nofile} ->
- case code:load_binary(Module, Filename, Binary) of
- {module, Module} ->
- ?logSuccess("Reloaded(Beam recompiled) Mod:~s Success", [Module]),
- syncLoadModOnAllNodes(SwSyncNode, Module, Binary, recompiled);
- {error, What} ->
- ?logErrors("Reloaded(Beam recompiled) Mod:~s Errors Reason:~p", [Module, What])
- end;
- {error, embedded} ->
- case code:load_file(Module) of %% Module is not yet loaded, load it.
- {module, Module} -> ok;
- {error, nofile} ->
- case code:load_binary(Module, Filename, Binary) of
- {module, Module} ->
- ?logSuccess("Reloaded(Beam recompiled) Mod:~s Success", [Module]),
- syncLoadModOnAllNodes(SwSyncNode, Module, Binary, recompiled);
- {error, What} ->
- ?logErrors("Reloaded(Beam recompiled) Mod:~s Errors Reason:~p", [Module, What])
- end
- end
- end;
- _ ->
- ignore
- end.
-
- recompileSrcFile(SrcFile, SwSyncNode) ->
- %% Get the module, src dir, and options...
- RootSrcDir =
- case getRootSrcDirFromSrcDir(SrcFile) of
- undefined ->
- filename:dirname(SrcFile);
- RetSrcDir ->
- RetSrcDir
- end,
- CurSrcDir = filename:dirname(SrcFile),
- {CompileFun, Module} = getCompileFunAndModuleName(SrcFile),
- {OldBinary, Filename} = getObjectCode(Module),
- case Module == es_gen_ipc orelse getOptions(RootSrcDir) of
- true ->
- ignore;
- {ok, Options} ->
- RightFileDir = binary_to_list(filename:join(CurSrcDir, filename:basename(SrcFile))),
- LastOptions = ?IIF(?esCfgSync:getv(?isJustMem), [binary, return | Options], [return | Options]),
- case CompileFun(RightFileDir, LastOptions) of
- {ok, Module, Binary, Warnings} ->
- printResults(Module, RightFileDir, [], Warnings),
- reloadIfNecessary(Module, OldBinary, Binary, Filename, SwSyncNode),
- {ok, [], Warnings};
- {ok, [{ok, Module, Binary, Warnings}], Warnings2} ->
- printResults(Module, RightFileDir, [], Warnings ++ Warnings2),
- reloadIfNecessary(Module, OldBinary, Binary, Filename, SwSyncNode),
- {ok, [], Warnings ++ Warnings2};
- {ok, multiple, Results, Warnings} ->
- printResults(Module, RightFileDir, [], Warnings),
- [reloadIfNecessary(CompiledModule, OldBinary, Binary, Filename, SwSyncNode) || {CompiledModule, Binary} <- Results],
- {ok, [], Warnings};
- {ok, OtherModule, _Binary, Warnings} ->
- Desc = io_lib:format("Module definition (~p) differs from expected (~s)", [OtherModule, filename:rootname(filename:basename(RightFileDir))]),
- Errors = [{RightFileDir, {0, Module, Desc}}],
- printResults(Module, RightFileDir, Errors, Warnings),
- {ok, Errors, Warnings};
- {error, Errors, Warnings} ->
- printResults(Module, RightFileDir, Errors, Warnings),
- {ok, Errors, Warnings};
- {ok, Module, Warnings} ->
- printResults(Module, RightFileDir, [], Warnings),
- {ok, [], Warnings};
- _Err ->
- ?logErrors("compile Mod:~s Errors Reason:~p", [Module, _Err])
- end;
- undefined ->
- case tryGetModOpts(Module) of
- {ok, Options} ->
- setOptions(RootSrcDir, Options),
- recompileSrcFile(SrcFile, SwSyncNode);
- _ ->
- case tryGetSrcOpts(CurSrcDir) of
- {ok, Options} ->
- setOptions(RootSrcDir, Options),
- recompileSrcFile(SrcFile, SwSyncNode);
- _ ->
- ?logErrors("Unable to determine options for ~s", [SrcFile])
- end
- end
- end.
-
- collIncludeCHrls([], AllHrls, CHrls, NewAddMap) ->
- case maps:size(NewAddMap) > 0 of
- true ->
- collIncludeCHrls(maps:keys(NewAddMap), AllHrls, CHrls, #{});
- _ ->
- CHrls
- end;
- collIncludeCHrls([OneHrl | LeftCHrls], AllHrls, CHrls, NewAddMap) ->
- {NewCHrls, NNewAddMap} = whoInclude(OneHrl, AllHrls, CHrls, NewAddMap),
- collIncludeCHrls(LeftCHrls, AllHrls, NewCHrls, NNewAddMap).
-
- collIncludeCErls([], _SrcFiles, CSrcs, _NewAddMap) ->
- CSrcs;
- collIncludeCErls([Hrl | LeftHrl], SrcFiles, CSrcs, NewAddMap) ->
- {NewCSrcs, NNewAddMap} = whoInclude(Hrl, SrcFiles, CSrcs, NewAddMap),
- collIncludeCErls(LeftHrl, SrcFiles, NewCSrcs, NNewAddMap).
-
- whoInclude(HrlFile, AllFiles, CFiles, NewAddMap) ->
- HrlFileBaseName = filename:basename(HrlFile),
- QuoteHrlFileBaseName = <<"\"", HrlFileBaseName/binary, "\"">>,
- doMathEveryFile(maps:iterator(AllFiles), QuoteHrlFileBaseName, CFiles, NewAddMap).
-
- doMathEveryFile(Iterator, HrlFileBaseName, CFiles, NewAddMap) ->
- case maps:next(Iterator) of
- {OneFile, _V, NextIterator} ->
- case file:open(OneFile, [read, binary]) of
- {ok, IoDevice} ->
- IsInclude = doMathEveryLine(IoDevice, HrlFileBaseName),
- file:close(IoDevice),
- case IsInclude of
- true ->
- case maps:is_key(OneFile, CFiles) of
- true ->
- doMathEveryFile(NextIterator, HrlFileBaseName, CFiles, NewAddMap);
- _ ->
- doMathEveryFile(NextIterator, HrlFileBaseName, CFiles#{OneFile => 1}, NewAddMap#{OneFile => 1})
- end;
- _ ->
- doMathEveryFile(NextIterator, HrlFileBaseName, CFiles, NewAddMap)
- end;
- _ ->
- doMathEveryFile(NextIterator, HrlFileBaseName, CFiles, NewAddMap)
- end;
- _ ->
- {CFiles, NewAddMap}
- end.
-
- %% 注释
- %% whoInclude(HrlFile, SrcFiles) ->
- %% HrlFileBaseName = filename:basename(HrlFile),
- %% Pred =
- %% fun(SrcFile, _) ->
- %% {ok, Forms} = epp_dodger:parse_file(SrcFile),
- %% isInclude(binary_to_list(HrlFileBaseName), Forms)
- %% end,
- %% maps:filter(Pred, SrcFiles).
- %% isInclude(_HrlFile, []) ->
- %% false;
- %% isInclude(HrlFile, [{tree, attribute, _, {attribute, _, [{_, _, IncludeFile}]}} | Forms]) when is_list(IncludeFile) ->
- %% IncludeFileBaseName = filename:basename(IncludeFile),
- %% case IncludeFileBaseName of
- %% HrlFile -> true;
- %% _ -> isInclude(HrlFile, Forms)
- %% end;
- %% isInclude(HrlFile, [_SomeForm | Forms]) ->
- %% isInclude(HrlFile, Forms).
-
- doMathEveryLine(IoDevice, HrlFileBaseName) ->
- case file:read_line(IoDevice) of
- {ok, Data} ->
- case re:run(Data, HrlFileBaseName) of
- nomatch ->
- case re:run(Data, <<"->">>) of
- nomatch ->
- doMathEveryLine(IoDevice, HrlFileBaseName);
- _ ->
- false
- end;
- _ ->
- true
- end;
- _ ->
- false
- end.
-
- classifyChangeFile([], Beams, Configs, Hrls, Srcs, ColSrcs, ColHrls, ColConfigs, ColBeams) ->
- {Beams, Configs, Hrls, Srcs, ColSrcs, ColHrls, ColConfigs, ColBeams};
- classifyChangeFile([OneFile | LeftFile], Beams, Configs, Hrls, Srcs, ColSrcs, ColHrls, ColConfigs, ColBeams) ->
- CurMTimeSec = dateTimeToSec(filelib:last_modified(OneFile)),
- case filename:extension(OneFile) of
- <<".beam">> ->
- BinMod = binary_to_atom(filename:basename(OneFile, <<".beam">>)),
- case ColBeams of
- #{BinMod := OldMTimeSec} ->
- case CurMTimeSec =/= OldMTimeSec andalso CurMTimeSec =/= 0 of
- true ->
- classifyChangeFile(LeftFile, [BinMod | Beams], Configs, Hrls, Srcs, ColSrcs, ColHrls, ColConfigs, ColBeams#{BinMod := CurMTimeSec});
- _ ->
- classifyChangeFile(LeftFile, Beams, Configs, Hrls, Srcs, ColSrcs, ColHrls, ColConfigs, ColBeams)
- end;
- _ ->
- classifyChangeFile(LeftFile, [BinMod | Beams], Configs, Hrls, Srcs, ColSrcs, ColHrls, ColConfigs, ColBeams#{BinMod => CurMTimeSec})
- end;
- <<".config">> ->
- AbsFile = filename:absname(OneFile),
- case ColConfigs of
- #{AbsFile := OldMTimeSec} ->
- case CurMTimeSec =/= OldMTimeSec andalso CurMTimeSec =/= 0 of
- true ->
- CfgMod = erlang:binary_to_atom(filename:basename(AbsFile, <<".config">>), utf8),
- classifyChangeFile(LeftFile, Beams, [CfgMod | Configs], Hrls, Srcs, ColSrcs, ColHrls, ColConfigs#{AbsFile := CurMTimeSec}, ColBeams);
- _ ->
- classifyChangeFile(LeftFile, Beams, Configs, Hrls, Srcs, ColSrcs, ColHrls, ColConfigs, ColBeams)
- end;
- _ ->
- CfgMod = erlang:binary_to_atom(filename:basename(AbsFile, <<".config">>), utf8),
- classifyChangeFile(LeftFile, Beams, [CfgMod | Configs], Hrls, Srcs, ColSrcs, ColHrls, ColConfigs#{AbsFile => CurMTimeSec}, ColBeams)
- end;
- <<".hrl">> ->
- AbsFile = filename:absname(OneFile),
- case ColHrls of
- #{AbsFile := OldMTimeSec} ->
- case CurMTimeSec =/= OldMTimeSec andalso CurMTimeSec =/= 0 of
- true ->
- classifyChangeFile(LeftFile, Beams, Configs, Hrls#{AbsFile => 1}, Srcs, ColSrcs, ColHrls#{AbsFile := CurMTimeSec}, ColConfigs, ColBeams);
- _ ->
- classifyChangeFile(LeftFile, Beams, Configs, Hrls, Srcs, ColSrcs, ColHrls, ColConfigs, ColBeams)
- end;
- _ ->
- classifyChangeFile(LeftFile, Beams, Configs, Hrls#{AbsFile => 1}, Srcs, ColSrcs, ColHrls#{AbsFile => CurMTimeSec}, ColConfigs, ColBeams)
- end;
- <<>> ->
- classifyChangeFile(LeftFile, Beams, Configs, Hrls, Srcs, ColSrcs, ColHrls, ColConfigs, ColBeams);
- _ ->
- AbsFile = filename:absname(OneFile),
- case ColSrcs of
- #{AbsFile := OldMTimeSec} ->
- case CurMTimeSec =/= OldMTimeSec andalso CurMTimeSec =/= 0 of
- true ->
- classifyChangeFile(LeftFile, Beams, Configs, Hrls, Srcs#{AbsFile => 1}, ColSrcs#{AbsFile := CurMTimeSec}, ColHrls, ColConfigs, ColBeams);
- _ ->
- classifyChangeFile(LeftFile, Beams, Configs, Hrls, Srcs, ColSrcs, ColHrls, ColConfigs, ColBeams)
- end;
- _ ->
- classifyChangeFile(LeftFile, Beams, Configs, Hrls, Srcs#{AbsFile => 1}, ColSrcs#{AbsFile => CurMTimeSec}, ColHrls, ColConfigs, ColBeams)
- end
- end.
-
- fileSyncPath(ExecName) ->
- case code:priv_dir(?MODULE) of
- {error, _} ->
- case code:which(?MODULE) of
- Filename when is_list(Filename) ->
- filename:join([filename:dirname(filename:dirname(Filename)), "priv", ExecName]);
- _ ->
- filename:join("../priv", ExecName)
- end;
- Dir ->
- filename:join(Dir, ExecName)
- end.
-
- dateTimeToSec(DateTime) ->
- if
- DateTime == 0 ->
- 0;
- true ->
- erlang:universaltime_to_posixtime(DateTime)
- end.
-
- debugInfoKeyFun() ->
- case ?esCfgSync:getv(?debugInfoKeyFun) of
- undefined ->
- {debug_info_key, undefined};
- {Mod, Fun} ->
- Mod:Fun()
- end.
- %% ************************************************* utils end *******************************************************
|