diff --git a/src/erlfmt_cli.erl b/src/erlfmt_cli.erl index 8ba30f9..bea1e6c 100644 --- a/src/erlfmt_cli.erl +++ b/src/erlfmt_cli.erl @@ -107,8 +107,26 @@ with_parsed(Name, Config) -> erlang:halt(127) end. +-spec set_difference([file:name_all()], [file:name_all()]) -> [file:name_all()]. set_difference(Files, Excludes) -> - sets:to_list(sets:subtract(sets:from_list(Files), sets:from_list(Excludes))). + {ok, Cwd} = file:get_cwd(), + AbsoluteFiles = maps:from_list([{resolve_path(Cwd, F), F} || F <- Files]), + AbsoluteExcludes = [resolve_path(Cwd, E) || E <- Excludes], + maps:values(maps:without(AbsoluteExcludes, AbsoluteFiles)). + +resolve_path(Dir, Filename) -> + resolve_path2(filename:absname(Filename, Dir)). + +resolve_path2(AbsPath) -> + [Volume | Components] = filename:split(AbsPath), + filename:join(resolve_path2(Components, [Volume])). + +resolve_path2([".." | T1], [Volume]) -> resolve_path2(T1, [Volume]); +resolve_path2([<<"..">> | T1], [Volume]) -> resolve_path2(T1, [Volume]); +resolve_path2([".." | T1], [_H2 | T2]) -> resolve_path2(T1, T2); +resolve_path2([<<"..">> | T1], [_H2 | T2]) -> resolve_path2(T1, T2); +resolve_path2([H1 | T1], Components) -> resolve_path2(T1, [H1 | Components]); +resolve_path2([], Components) -> lists:reverse(Components). %% needed because of getopt -dialyzer({nowarn_function, [unprotected_with_config/2]}). diff --git a/test/erlfmt_cli_SUITE.erl b/test/erlfmt_cli_SUITE.erl index 8afcdc1..6866f18 100644 --- a/test/erlfmt_cli_SUITE.erl +++ b/test/erlfmt_cli_SUITE.erl @@ -51,6 +51,7 @@ noformat_pragma/1, noformat_pragma_file/1, exclude_check/1, + exclude_absolute_check/1, range_check_full/1, range_check_partial/1 ]). @@ -98,6 +99,7 @@ groups() -> noformat_pragma, noformat_pragma_file, exclude_check, + exclude_absolute_check, range_check_full, range_check_partial ]} @@ -250,16 +252,14 @@ noformat_pragma(Config) when is_list(Config) -> exclude_check(Config) when is_list(Config) -> Files = filename:join(?config(data_dir, Config), "*.erl"), Exclude = filename:join(?config(data_dir, Config), "broken.erl"), - WithBroken = os:cmd( - escript() ++ " -c " ++ Files - ), - ?assertNotMatch(nomatch, string:find(WithBroken, "[warn]")), - ?assertNotMatch(nomatch, string:find(WithBroken, "broken.erl")), - WithoutBroken = os:cmd( - escript() ++ " -c " ++ Files ++ " --exclude-files=" ++ Exclude - ), - ?assertNotMatch(nomatch, string:find(WithoutBroken, "[warn]")), - ?assertMatch(nomatch, string:find(WithoutBroken, "broken.erl")). + exclude_test(Files, Exclude). + +exclude_absolute_check(Config) when is_list(Config) -> + {ok, ProjectRoot} = file:get_cwd(), + DataDirRelPath = make_relative_path(?config(data_dir, Config), ProjectRoot), + Files = filename:join(?config(data_dir, Config), "*.erl"), + Exclude = filename:join(DataDirRelPath, "broken.erl"), + exclude_test(Files, Exclude). range_check_full(Config) when is_list(Config) -> %% Mainly check the options is properly recognized. @@ -284,6 +284,27 @@ stdio_test(FileName, Options, Config) -> {ok, Expected} = file:read_file(Path), assert_diagnostic:assert_binary_match(Expected, unicode:characters_to_binary(Formatted)). +exclude_test(Files, Exclude) -> + WithBroken = os:cmd( + escript() ++ " -c " ++ Files + ), + ?assertNotMatch(nomatch, string:find(WithBroken, "[warn]")), + ?assertNotMatch(nomatch, string:find(WithBroken, "broken.erl")), + WithoutBroken = os:cmd( + escript() ++ " -c " ++ Files ++ " --exclude-files=" ++ Exclude + ), + ?assertNotMatch(nomatch, string:find(WithoutBroken, "[warn]")), + ?assertMatch(nomatch, string:find(WithoutBroken, "broken.erl")). + escript() -> %% this relies on the _build structure rebar3 uses filename:join(code:lib_dir(erlfmt), "../../bin/erlfmt"). + +make_relative_path(Source, Target) -> + make_relative_path2(filename:split(Source), filename:split(Target)). + +make_relative_path2([H | T1], [H | T2]) -> + make_relative_path2(T1, T2); +make_relative_path2(Source, Target) -> + Base = lists:duplicate(length(Target), ".."), + filename:join(Base ++ Source).