Skip to content

Commit

Permalink
feat: support include-dirs opt to search include file (#147)
Browse files Browse the repository at this point in the history
* feat: support include-dirs opt to search include file

* feat: throw error when required=false but reason =/= enoent
  • Loading branch information
zhongwencool authored Oct 13, 2021
1 parent 5538542 commit c47ab8e
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 23 deletions.
2 changes: 2 additions & 0 deletions etc/include-dir-enoent.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include required("node.conf")
include required("not-exist.conf")
2 changes: 2 additions & 0 deletions etc/include-dir.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include required("node.conf")
include required("test-data-dir.conf")
8 changes: 6 additions & 2 deletions src/hocon.erl
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ load(Filename0) ->
-spec(load(file:filename(), opts()) -> {ok, config()} | {error, term()}).
load(Filename0, Opts) ->
Filename = hocon_util:real_file_name(filename:absname(Filename0)),
Ctx = hocon_util:stack_multiple_push([{path, '$root'}, {filename, Filename}], #{}),
IncludeDirs = [filename:dirname(Dir) || Dir <- maps:get(include_dirs, Opts, [])],
CtxList = [{path, '$root'}, {filename, Filename}, {include_dirs, IncludeDirs}],
Ctx = hocon_util:stack_multiple_push(CtxList, #{}),
try
Bytes = hocon_token:read(Filename),
Conf = transform(do_binary(Bytes, Ctx), Opts),
Expand Down Expand Up @@ -90,7 +92,9 @@ binary(Binary) ->

binary(Binary, Opts) ->
try
Ctx = hocon_util:stack_multiple_push([{path, '$root'}, {filename, undefined}], #{}),
IncludeDirs = [filename:dirname(Dir) || Dir <-maps:get(include_dirs, Opts, [])],
CtxList = [{path, '$root'}, {filename, undefined}, {include_dirs, IncludeDirs}],
Ctx = hocon_util:stack_multiple_push(CtxList, #{}),
Map = transform(do_binary(Binary, Ctx), Opts),
{ok, apply_opts(Map, Opts)}
catch
Expand Down
53 changes: 33 additions & 20 deletions src/hocon_token.erl
Original file line number Diff line number Diff line change
Expand Up @@ -215,26 +215,39 @@ do_abspath(Var, [#{?HOCON_T := key}=K | More]) ->
%% @end
load_include(#{?HOCON_T := include, ?HOCON_V := Value, required := Required}, Ctx0) ->
Cwd = filename:dirname(hd(hocon_util:get_stack(filename, Ctx0))),
Filename = binary_to_list(filename:join([Cwd, Value])),
case {file:read_file_info(Filename), Required} of
{{error, enoent}, true} ->
throw({enoent, Filename});
{{error, enoent}, false} ->
nothing;
_ ->
case is_included(Filename, Ctx0) of
true ->
throw({cycle, hocon_util:get_stack(filename, Ctx0)});
false ->
Ctx = hocon_util:stack_push({filename, Filename}, Ctx0),
hocon_util:pipeline(Filename, Ctx,
[ fun read/1
, fun scan/2
, fun trans_key/1
, fun parse/2
, fun include/2
])
end
IncludeDirs = hd(hocon_util:get_stack(include_dirs, Ctx0)),
case search_file([Cwd | IncludeDirs], Value) of
{ok, Filename} ->
case is_included(Filename, Ctx0) of
true ->
throw({cycle, hocon_util:get_stack(filename, Ctx0)});
false ->
Ctx = hocon_util:stack_push({filename, Filename}, Ctx0),
hocon_util:pipeline(Filename, Ctx,
[ fun read/1
, fun scan/2
, fun trans_key/1
, fun parse/2
, fun include/2
])
end;
{error, enoent} when Required -> throw({enoent, Value});
{error, enoent} -> nothing;
{error, Errors} -> throw(Errors)
end.

search_file(Dirs, File) -> search_file(Dirs, File, []).

search_file([], _File, []) -> {error, enoent};
search_file([], _File, Reasons) -> {error, Reasons};
search_file([Dir | Dirs], File, Reasons0) ->
Filename = binary_to_list(filename:join([Dir, File])),
case file:read_file_info(Filename) of
{ok, _} -> {ok, Filename};
{error, enoent} -> search_file(Dirs, File, Reasons0);
{error, Reason} ->
Reasons = [{Reason, Filename} | Reasons0],
search_file(Dirs, File, Reasons)
end.

is_included(Filename, Ctx) ->
Expand Down
1 change: 1 addition & 0 deletions test/data/test-data-dir.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include required("a_1.conf")
23 changes: 22 additions & 1 deletion test/hocon_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,28 @@ delete_null_test() ->

required_test() ->
?assertEqual({ok, #{}}, hocon:load("etc/optional-include.conf")),
?assertMatch({error, {enoent, _}}, hocon:load("etc/required-include.conf")).
RequiredRes = hocon:load("etc/required-include.conf"),
?assertMatch({error, {enoent, <<"no.conf">>}}, RequiredRes).

include_dirs_test() ->
Expect =
#{<<"a">> => 1,
<<"cluster">> =>
#{<<"autoclean">> => <<"5m">>,
<<"autoheal">> => <<"on">>,
<<"discovery">> => <<"manual">>,
<<"name">> => <<"emqxcl">>,
<<"proto_dist">> => <<"inet_tcp">>},
<<"node">> =>
#{<<"cookie">> => <<"emqxsecretcookie">>,
<<"data_dir">> => <<"platform_data_dir">>,
<<"name">> => <<"[email protected]">>}},
Opts = #{include_dirs => ["test/data/", "sample-configs/"]},
{ok, Map} = hocon:load("etc/include-dir.conf", Opts),
?assertEqual(Expect, Map),
{error, Reason} = hocon:load("etc/include-dir-enoent.conf", Opts),
?assertEqual({enoent, <<"not-exist.conf">>}, Reason),
ok.

merge_when_resolve_test() ->
?assertEqual({ok, #{<<"a">> => #{<<"x">> => 1, <<"y">> => 2},
Expand Down

0 comments on commit c47ab8e

Please sign in to comment.