split-config.escript 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. #!/usr/bin/env escript
  2. %% This script reads up emqx.conf and split the sections
  3. %% and dump sections to separate files.
  4. %% Sections are grouped between CONFIG_SECTION_BGN and
  5. %% CONFIG_SECTION_END pairs
  6. %%
  7. %% NOTE: this feature is so far not used in opensource
  8. %% edition due to backward-compatibility reasons.
  9. -mode(compile).
  10. -define(BASE, <<"emqx">>).
  11. main(_) ->
  12. {ok, Bin} = file:read_file(conf_file()),
  13. Lines = binary:split(Bin, <<"\n">>, [global]),
  14. Sections0 = parse_sections(Lines),
  15. {value, _, Sections1} = lists:keytake(<<"modules">>, 1, Sections0),
  16. {value, {N, Base}, Sections2} = lists:keytake(<<"emqx">>, 1, Sections1),
  17. IncludeNames = proplists:get_keys(Sections2),
  18. Includes = lists:map(fun(Name) ->
  19. iolist_to_binary(["include {{ platform_etc_dir }}/", Name, ".conf"])
  20. end, IncludeNames),
  21. ok = dump_sections([{N, Base ++ Includes}| Sections2]).
  22. etc_dir() -> filename:join(["apps", "emqx", "etc"]).
  23. conf_file() -> filename:join([etc_dir(), "emqx.conf"]).
  24. parse_sections(Lines) ->
  25. {ok, P} = re:compile("#+\s*CONFIG_SECTION_(BGN|END)\s*=\s*([^\s-]+)\s*="),
  26. Parser =
  27. fun(Line) ->
  28. case re:run(Line, P, [{capture, all_but_first, binary}]) of
  29. {match, [<<"BGN">>, Name]} -> {section_bgn, Name};
  30. {match, [<<"END">>, Name]} -> {section_end, Name};
  31. nomatch -> continue
  32. end
  33. end,
  34. parse_sections(Lines, Parser, ?BASE, #{?BASE => []}).
  35. parse_sections([], _Parse, _Section, Sections) ->
  36. lists:map(fun({N, Lines}) -> {N, lists:reverse(Lines)} end,
  37. maps:to_list(Sections));
  38. parse_sections([Line | Lines], Parse, Section, Sections) ->
  39. case Parse(Line) of
  40. {section_bgn, Name} ->
  41. ?BASE = Section, %% assert
  42. true = (Name =/= ?BASE), %% assert
  43. false = maps:is_key(Name, Sections), %% assert
  44. NewSections = Sections#{?BASE := maps:get(?BASE, Sections), Name => []},
  45. parse_sections(Lines, Parse, Name, NewSections);
  46. {section_end, Name} ->
  47. true = (Name =:= Section), %% assert
  48. parse_sections(Lines, Parse, ?BASE, Sections);
  49. continue ->
  50. Acc = maps:get(Section, Sections),
  51. parse_sections(Lines, Parse, Section, Sections#{Section => [Line | Acc]})
  52. end.
  53. dump_sections([]) -> ok;
  54. dump_sections([{Name, Lines0} | Rest]) ->
  55. Filename = filename:join([etc_dir(), iolist_to_binary([Name, ".conf.seg"])]),
  56. Lines = [[L, "\n"] || L <- Lines0],
  57. ok = file:write_file(Filename, Lines),
  58. dump_sections(Rest).