diff options
-rw-r--r-- | src/rebar_app_discover.erl | 60 | ||||
-rw-r--r-- | test/rebar_src_dirs_SUITE.erl | 40 |
2 files changed, 87 insertions, 13 deletions
diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl index 66319a4..db74cd3 100644 --- a/src/rebar_app_discover.erl +++ b/src/rebar_app_discover.erl @@ -183,13 +183,31 @@ reset_hooks(Opts) -> rebar_opts:set(OptsAcc, Key, []) end, Opts, [post_hooks, pre_hooks, provider_hooks, artifacts]). -%% @doc find the directories for all apps based on their source dirs --spec all_app_dirs([file:name()], [file:name()]) -> [file:name()]. +%% @private find the directories for all apps, while detecting their source dirs +%% Returns the app dir with the respective src_dirs for them, in that order, +%% for every app found. +-spec all_app_dirs([file:name()]) -> [{file:name(), [file:name()]}]. +all_app_dirs(LibDirs) -> + lists:flatmap(fun(LibDir) -> + SrcDirs = find_config_src(LibDir, ["src"]), + app_dirs(LibDir, SrcDirs) + end, LibDirs). + +%% @private find the directories for all apps based on their source dirs +%% Returns the app dir with the respective src_dirs for them, in that order, +%% for every app found. +-spec all_app_dirs([file:name()], [file:name()]) -> [{file:name(), [file:name()]}]. all_app_dirs(LibDirs, SrcDirs) -> lists:flatmap(fun(LibDir) -> app_dirs(LibDir, SrcDirs) end, LibDirs). -%% @doc find the directories based on the library directories --spec app_dirs([file:name()], [file:name()]) -> [file:name()]. +%% @private find the directories based on the library directories. +%% Returns the app dir with the respective src_dirs for them, in that order, +%% for every app found. +%% +%% The function returns the src directories since they might have been +%% detected in a top-level loop and we want to skip further detection +%% starting now. +-spec app_dirs([file:name()], [file:name()]) -> [{file:name(), [file:name()]}]. app_dirs(LibDir, SrcDirs) -> Paths = lists:append([ [filename:join([LibDir, SrcDir, "*.app.src"]), @@ -199,8 +217,9 @@ app_dirs(LibDir, SrcDirs) -> EbinPath = filename:join([LibDir, "ebin", "*.app"]), lists:usort(lists:foldl(fun(Path, Acc) -> - Files = filelib:wildcard(ec_cnv:to_list(Path)), - [app_dir(File) || File <- Files] ++ Acc + Files = filelib:wildcard(ec_cnv:to_list(Path)), + [{app_dir(File), SrcDirs} + || File <- Files] ++ Acc end, [], [EbinPath | Paths])). %% @doc find all apps that haven't been built in a list of directories @@ -212,14 +231,19 @@ find_unbuilt_apps(LibDirs) -> %% Returns all the related app info records. -spec find_apps([file:filename_all()]) -> [rebar_app_info:t()]. find_apps(LibDirs) -> - find_apps(LibDirs, ["src"], valid). + find_apps(LibDirs, valid). %% @doc for each directory passed, find all apps according %% to the validity rule passed in. Returns all the related %% app info records. -spec find_apps([file:filename_all()], valid | invalid | all) -> [rebar_app_info:t()]. find_apps(LibDirs, Validate) -> - find_apps(LibDirs, ["src"], Validate). + rebar_utils:filtermap( + fun({AppDir, AppSrcDirs}) -> + find_app(rebar_app_info:new(), AppDir, AppSrcDirs, Validate) + end, + all_app_dirs(LibDirs) + ). %% @doc for each directory passed, with the configured source directories, %% find all apps according to the validity rule passed in. @@ -227,8 +251,8 @@ find_apps(LibDirs, Validate) -> -spec find_apps([file:filename_all()], [file:filename_all()], valid | invalid | all) -> [rebar_app_info:t()]. find_apps(LibDirs, SrcDirs, Validate) -> rebar_utils:filtermap( - fun(AppDir) -> - find_app(rebar_app_info:new(), AppDir, SrcDirs, Validate) + fun({AppDir, AppSrcDirs}) -> + find_app(rebar_app_info:new(), AppDir, AppSrcDirs, Validate) end, all_app_dirs(LibDirs, SrcDirs) ). @@ -238,7 +262,8 @@ find_apps(LibDirs, SrcDirs, Validate) -> %% app info record. -spec find_app(file:filename_all(), valid | invalid | all) -> {true, rebar_app_info:t()} | false. find_app(AppDir, Validate) -> - find_app(rebar_app_info:new(), AppDir, ["src"], Validate). + SrcDirs = find_config_src(AppDir, ["src"]), + find_app(rebar_app_info:new(), AppDir, SrcDirs, Validate). %% @doc check that a given app in a directory is there, and whether it's %% valid or not based on the second argument. Returns the related @@ -385,3 +410,16 @@ enable(State, AppInfo) -> -spec to_atom(binary()) -> atom(). to_atom(Bin) -> list_to_atom(binary_to_list(Bin)). + +%% @private when looking for unknown apps, it's possible they have a +%% rebar.config file specifying non-standard src_dirs. Check for a +%% possible config file and extract src_dirs from it. +find_config_src(AppDir, Default) -> + case rebar_config:consult(AppDir) of + [] -> + Default; + Terms -> + %% TODO: handle profiles I guess, but we don't have that info + proplists:get_value(src_dirs, Terms, Default) + end. + diff --git a/test/rebar_src_dirs_SUITE.erl b/test/rebar_src_dirs_SUITE.erl index 1982301..677dbaf 100644 --- a/test/rebar_src_dirs_SUITE.erl +++ b/test/rebar_src_dirs_SUITE.erl @@ -15,7 +15,8 @@ extra_src_dirs_at_root_and_in_erl_opts/1, build_basic_app/1, build_multi_apps/1, - src_dir_takes_precedence_over_extra/1]). + src_dir_takes_precedence_over_extra/1, + src_dir_checkout_dep/1]). -include_lib("common_test/include/ct.hrl"). @@ -39,7 +40,8 @@ all() -> src_dirs_at_root_and_in_erl_opts, dupe_src_dirs_at_root_and_in_erl_opts, extra_src_dirs_at_root_and_in_erl_opts, - build_basic_app, build_multi_apps, src_dir_takes_precedence_over_extra]. + build_basic_app, build_multi_apps, src_dir_takes_precedence_over_extra, + src_dir_checkout_dep]. src_dirs_at_root(Config) -> AppDir = ?config(apps, Config), @@ -271,3 +273,37 @@ src_dir_takes_precedence_over_extra(Config) -> [{application, _, KVs}] = App, Mods = proplists:get_value(modules, KVs), true = lists:member(extra, Mods). + +src_dir_checkout_dep(Config) -> + AppDir = ?config(apps, Config), + AppName = rebar_test_utils:create_random_name("src_dir_checkout_app"), + DepName = rebar_test_utils:create_random_name("src_dir_checkout_dep"), + AtomDep = list_to_atom(DepName), + + Vsn = rebar_test_utils:create_random_vsn(), + rebar_test_utils:create_app(AppDir, AppName, Vsn, [kernel, stdlib]), + RebarConfig = [{deps, [AtomDep]}], + + DepDir = filename:join([?config(checkouts, Config), DepName]), + ct:pal("checkouts dir: ~p", [DepDir]), + rebar_test_utils:create_app(DepDir, DepName, Vsn, [kernel, stdlib]), + + + %% move the .app.src file to one of the subdirs, out of src/ + rebar_file_utils:mv(filename:join([DepDir, "src"]), + filename:join([DepDir, "qux"])), + DepRebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}]}, + {src_dirs, ["baz", "qux"]}], + file:write_file(filename:join([DepDir, "rebar.config"]), + io_lib:format("~p.~n~p.~n", DepRebarConfig)), + + rebar_test_utils:run_and_check( + Config, RebarConfig, ["compile"], + {ok, [{checkout, DepName}, {app, AppName}]} + ), + + % {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), + % ["bar", "baz", "foo", "qux"] = rebar_dir:src_dirs(rebar_state:opts(State), []), + % rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], + % {ok, [{app, Name}]}), + ok. |