Quellcode durchsuchen

Fix Recursive Behaviour Lookup Regression

This was due to a subtle mistake in the new code in
https://github.com/erlang/rebar3/pull/2322 which optimized the search
behaviour of files not found by EPP. The patch mistakenly always kept
the top-level src/ directory for an app even if it did a lookup in
recursive ones.

This patch tracks and maintains the proper subdirectory hierarchy. To
keep performance adequate, the lists:keyfind/3 function is used, which
is also now a NIF to the same extent as lists:member/2; manual lookups
would likely end up reducing performance, particularly in deep
hierarchies.

A test case has been added to track the regression.
Reported by @elbrujohalcon
pull/2339/head
Fred Hebert vor 4 Jahren
Ursprung
Commit
37396c7f8b
2 geänderte Dateien mit 52 neuen und 4 gelöschten Zeilen
  1. +4
    -4
      src/rebar_compiler_epp.erl
  2. +48
    -0
      test/rebar_compile_SUITE.erl

+ 4
- 4
src/rebar_compiler_epp.erl Datei anzeigen

@ -101,9 +101,9 @@ resolve(_Name, Fs, []) ->
{false, Fs};
resolve(Name, Fs, [Dir | Tail]) ->
{NewFs, Files} = list_directory(Dir, Fs),
case lists:member(Name, Files) of
true ->
{{true, filename:join(Dir, Name)}, NewFs};
case lists:keyfind(Name, 2, Files) of
{FullDir, _} ->
{{true, filename:join(FullDir, Name)}, NewFs};
false ->
resolve(Name, NewFs, Tail)
end.
@ -136,7 +136,7 @@ list_directory(Dir, Cache) ->
%% ignore all but *.erl files
case filename:extension(File) =:= ".erl" of
true ->
{DirCache, [File | Files]};
{DirCache, [{Dir, File} | Files]};
false ->
Acc
end

+ 48
- 0
test/rebar_compile_SUITE.erl Datei anzeigen

@ -20,6 +20,7 @@ all() ->
recompile_when_opts_included_hrl_changes,
recompile_when_foreign_included_hrl_changes,
recompile_when_foreign_behaviour_changes,
recompile_when_recursive_behaviour_changes,
recompile_when_opts_change, recompile_when_dag_opts_change,
dont_recompile_when_opts_dont_change, dont_recompile_yrl_or_xrl,
delete_beam_if_source_deleted,
@ -890,6 +891,53 @@ recompile_when_foreign_behaviour_changes(Config) ->
?assert(ModTime =/= NewModTime).
recompile_when_recursive_behaviour_changes(Config) ->
AppDir = ?config(apps, Config),
AppsDir = filename:join([AppDir, "apps"]),
Name1 = rebar_test_utils:create_random_name("app1_"),
Vsn = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_app(filename:join(AppsDir, Name1),
Name1, Vsn, [kernel, stdlib]),
ExtraSrc = <<"-module(test_behaviour_include).\n"
"-export([main/0]).\n"
"-behaviour(app1_behaviour).\n"
"main() -> 1.\n">>,
Behaviour = <<"-module(app1_behaviour).\n"
"-callback main() -> term().\n">>,
ok = filelib:ensure_dir(filename:join([AppsDir, Name1, "src", "dummy"])),
ok = filelib:ensure_dir(filename:join([AppsDir, Name1, "src", "sub", "dummy"])),
BehaviourFile = filename:join([AppsDir, Name1, "src", "sub", "app1_behaviour.erl"]),
ok = file:write_file(filename:join([AppsDir, Name1, "src", "test_behaviour_include.erl"]), ExtraSrc),
ok = file:write_file(BehaviourFile, Behaviour),
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}),
EbinDir = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin"]),
{ok, Files} = rebar_utils:list_dir(EbinDir),
ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
|| F <- Files,
filename:extension(F) == ".beam",
filename:basename(F) =/= "app1_behaviour.beam"],
timer:sleep(1000),
NewBehaviour = <<"-module(app1_behaviour).\n"
"-callback main(_) -> term().\n">>,
ok = file:write_file(BehaviourFile, NewBehaviour),
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}),
{ok, NewFiles} = rebar_utils:list_dir(EbinDir),
NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
|| F <- NewFiles,
filename:extension(F) == ".beam",
filename:basename(F) =/= "app1_behaviour.beam"],
?assert(ModTime =/= NewModTime).
recompile_when_opts_change(Config) ->
AppDir = ?config(apps, Config),

Laden…
Abbrechen
Speichern