diff --git a/.gitignore b/.gitignore index 59ebdd433..c702d3955 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ emqx_dialyzer_*_plt */emqx_dashboard/priv/www dist.zip scripts/git-token +etc/*.seg diff --git a/scripts/split-config.escript b/scripts/split-config.escript new file mode 100755 index 000000000..07caf6503 --- /dev/null +++ b/scripts/split-config.escript @@ -0,0 +1,62 @@ +#!/usr/bin/env escript + +%% This script reads up emqx.conf and split the sections +%% and dump sections to separate files. +%% Sections are grouped between CONFIG_SECTION_BGN and +%% CONFIG_SECTION_END pairs +%% +%% NOTE: this feature is so far not used in opensource +%% edition due to backward-compatibility reasons. + +-mode(compile). + +-define(BASE, <<"emqx">>). + +main(_) -> + {ok, Bin} = file:read_file("etc/emqx.conf"), + Lines = binary:split(Bin, <<"\n">>, [global]), + Sections0 = parse_sections(Lines), + Sections = lists:filter(fun({<<"modules">>, _}) -> false; + (_) -> true + end, Sections0), + ok = dump_sections(Sections). + +parse_sections(Lines) -> + {ok, P} = re:compile("#+\s*CONFIG_SECTION_(BGN|END)\s*=\s*([^\s-]+)\s*="), + Parser = + fun(Line) -> + case re:run(Line, P, [{capture, all_but_first, binary}]) of + {match, [<<"BGN">>, Name]} -> {section_bgn, Name}; + {match, [<<"END">>, Name]} -> {section_end, Name}; + nomatch -> continue + end + end, + parse_sections(Lines, Parser, ?BASE, #{?BASE => []}). + +parse_sections([], _Parse, _Section, Sections) -> + lists:map(fun({N, Lines}) -> {N, lists:reverse(Lines)} end, + maps:to_list(Sections)); +parse_sections([Line | Lines], Parse, Section, Sections) -> + case Parse(Line) of + {section_bgn, Name} -> + ?BASE = Section, %% assert + true = (Name =/= ?BASE), %% assert + false = maps:is_key(Name, Sections), %% assert + Include = iolist_to_binary(["include {{ platform_etc_dir }}/", Name, ".conf"]), + Base = maps:get(?BASE, Sections), + NewSections = Sections#{?BASE := [Include | Base], Name => []}, + parse_sections(Lines, Parse, Name, NewSections); + {section_end, Name} -> + true = (Name =:= Section), %% assert + parse_sections(Lines, Parse, ?BASE, Sections); + continue -> + Acc = maps:get(Section, Sections), + parse_sections(Lines, Parse, Section, Sections#{Section => [Line | Acc]}) + end. + +dump_sections([]) -> ok; +dump_sections([{Name, Lines0} | Rest]) -> + Filename = filename:join(["etc", iolist_to_binary([Name, ".conf.seg"])]), + Lines = [[L, "\n"] || L <- Lines0], + ok = file:write_file(Filename, Lines), + dump_sections(Rest).