Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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