diff --git a/priv/shell-completion/bash/rebar b/priv/shell-completion/bash/rebar index 6814cce..7fce89f 100644 --- a/priv/shell-completion/bash/rebar +++ b/priv/shell-completion/bash/rebar @@ -11,8 +11,8 @@ _rebar() cmdsnvars="check-deps clean compile create create-app create-node \ ct doc delete-deps eunit get-deps generate generate-upgrade \ help list-deps list-templates update-deps version xref overlay \ - case= force=1 jobs= suite= verbose=1 appid= previous_release= \ - root_dir= skip_deps=true skip_app= template= template_dir=" + apps= case= force=1 jobs= suite= verbose=1 appid= previous_release= \ + root_dir= skip_deps=true skip_apps= template= template_dir=" if [[ ${cur} == --* ]] ; then COMPREPLY=( $(compgen -W "${lopts}" -- ${cur}) ) diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl index f68f41c..cbbfe38 100644 --- a/src/rebar_app_utils.erl +++ b/src/rebar_app_utils.erl @@ -32,7 +32,7 @@ app_name/1, app_applications/1, app_vsn/1, - is_skipped_app/0]). + is_skipped_app/1]). -export([load_app_file/1]). % TEMPORARY @@ -105,40 +105,26 @@ app_vsn(AppFile) -> [AppFile, Reason]) end. -%% -%% Return: true, if we are in the context of a 'Skipped App', else: false -%% (Example: rebar xref skip_app=mochiweb,webmachine) -is_skipped_app() -> - case rebar_config:get_global(skip_app, undefined) of +is_skipped_app(AppFile) -> + ThisApp = app_name(AppFile), + %% Check for apps global parameter; this is a comma-delimited list + %% of apps on which we want to run commands + case get_apps() of undefined -> - %% no skip list - false; - - SkipApps -> - - case string:tokens(SkipApps, ",") of - [] -> - %% no tokens + %% No apps parameter specified, check the skip_apps list.. + case get_skip_apps() of + undefined -> + %% No skip_apps list, run everything.. false; - - SkipAppsTokens -> - - %% Where we are at the moment - Cwd = rebar_utils:get_cwd(), - - %% Return true if app should be skipped - SkipPred = fun(App) -> - case re:run(Cwd, App) of - {match,_} -> true; - _ -> false - end - end, - - %% Check if 'we' are among the skipped apps. - lists:foldl(fun(SkippedApp, Bool) -> - SkipPred(SkippedApp) or Bool - end, false, SkipAppsTokens) - end + SkipApps -> + TargetApps = [list_to_atom(A) || + A <- string:tokens(SkipApps, ",")], + is_skipped_app(ThisApp, TargetApps) + end; + Apps -> + %% run only selected apps + TargetApps = [list_to_atom(A) || A <- string:tokens(Apps, ",")], + is_selected_app(ThisApp, TargetApps) end. %% =================================================================== @@ -224,3 +210,47 @@ vcs_vsn_cmd(Version) -> {unknown, Version}. vcs_vsn_invoke(Cmd, Dir) -> {ok, VsnString} = rebar_utils:sh(Cmd, [{cd, Dir}, {use_stdout, false}]), string:strip(VsnString, right, $\n). + +%% apps= for selecting apps +is_selected_app(ThisApp, TargetApps) -> + case lists:member(ThisApp, TargetApps) of + false -> + {true, ThisApp}; + true -> + false + end. + +%% skip_apps= for filtering apps +is_skipped_app(ThisApp, TargetApps) -> + case lists:member(ThisApp, TargetApps) of + false -> + false; + true -> + {true, ThisApp} + end. + +get_apps() -> + get_global_cs_opt(app, apps). + +get_skip_apps() -> + get_global_cs_opt(skip_app, skip_apps). + +get_global_cs_opt(Old, New) -> + Apps = rebar_config:get_global(New, undefined), + case rebar_config:get_global(Old, undefined) of + undefined -> + case Apps of + undefined -> + undefined; + Apps -> + Apps + end; + App -> + rebar_utils:deprecated(Old, Old, New, "soon"), + case Apps of + undefined -> + App; + Apps -> + string:join([App, Apps], ",") + end + end. diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 56f0aca..44ad355 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -114,81 +114,111 @@ process_dir(Dir, ParentConfig, Command, DirSet) -> %% CWD to see if it's a fit -- if it is, use that set of modules %% to process this dir. {ok, AvailModuleSets} = application:get_env(rebar, modules), - {DirModules, ModuleSetFile} = choose_module_set(AvailModuleSets, - Dir), + ModuleSet = choose_module_set(AvailModuleSets, Dir), + {_DirModules, ModuleSetFile} = ModuleSet, - %% Get the list of modules for "any dir". This is a catch-all list - %% of modules that are processed in addition to modules associated - %% with this directory type. These any_dir modules are processed - %% FIRST. - {ok, AnyDirModules} = application:get_env(rebar, any_dir_modules), + case lists:reverse(ModuleSetFile) of + "ppa." ++ _ -> + %% .app file + maybe_process_dir0(ModuleSetFile, ModuleSet, Config, + CurrentCodePath, Dir, + Command, DirSet); + "crs.ppa." ++ _ -> + %% .app.src file + maybe_process_dir0(ModuleSetFile, ModuleSet, Config, + CurrentCodePath, Dir, + Command, DirSet); + _ -> + process_dir0(Dir, Command, DirSet, Config, + CurrentCodePath, ModuleSet) + end + end. - Modules = AnyDirModules ++ DirModules, +maybe_process_dir0(AppFile, ModuleSet, Config, CurrentCodePath, + Dir, Command, DirSet) -> + case rebar_app_utils:is_skipped_app(AppFile) of + {true, SkippedApp} -> + ?DEBUG("Skipping app: ~p~n", [SkippedApp]), + increment_operations(), + DirSet; + false -> + process_dir0(Dir, Command, DirSet, Config, + CurrentCodePath, ModuleSet) + end. - %% Invoke 'preprocess' on the modules -- this yields a list of other - %% directories that should be processed _before_ the current one. - Predirs = acc_modules(Modules, preprocess, Config, ModuleSetFile), +process_dir0(Dir, Command, DirSet, Config, CurrentCodePath, + {DirModules, ModuleSetFile}) -> + %% Get the list of modules for "any dir". This is a catch-all list + %% of modules that are processed in addition to modules associated + %% with this directory type. These any_dir modules are processed + %% FIRST. + {ok, AnyDirModules} = application:get_env(rebar, any_dir_modules), - %% Get the list of plug-in modules from rebar.config. These - %% modules may participate in preprocess and postprocess. - {ok, PluginModules} = plugin_modules(Config), + Modules = AnyDirModules ++ DirModules, - PluginPredirs = acc_modules(PluginModules, preprocess, - Config, ModuleSetFile), + %% Invoke 'preprocess' on the modules -- this yields a list of other + %% directories that should be processed _before_ the current one. + Predirs = acc_modules(Modules, preprocess, Config, ModuleSetFile), - AllPredirs = Predirs ++ PluginPredirs, + %% Get the list of plug-in modules from rebar.config. These + %% modules may participate in preprocess and postprocess. + {ok, PluginModules} = plugin_modules(Config), - ?DEBUG("Predirs: ~p\n", [AllPredirs]), - DirSet2 = process_each(AllPredirs, Command, Config, - ModuleSetFile, DirSet), - - %% Make sure the CWD is reset properly; processing the dirs may have - %% caused it to change - ok = file:set_cwd(Dir), - - %% Check that this directory is not on the skip list - case is_skip_dir(Dir) of - true -> - %% Do not execute the command on the directory, as some - %% module as requested a skip on it. - ?INFO("Skipping ~s in ~s\n", [Command, Dir]); - - false -> - %% Execute any before_command plugins on this directory - execute_pre(Command, PluginModules, + PluginPredirs = acc_modules(PluginModules, preprocess, Config, ModuleSetFile), - %% Execute the current command on this directory - execute(Command, Modules ++ PluginModules, - Config, ModuleSetFile), + AllPredirs = Predirs ++ PluginPredirs, - %% Execute any after_command plugins on this directory - execute_post(Command, PluginModules, - Config, ModuleSetFile) - end, + ?DEBUG("Predirs: ~p\n", [AllPredirs]), + DirSet2 = process_each(AllPredirs, Command, Config, + ModuleSetFile, DirSet), - %% Mark the current directory as processed - DirSet3 = sets:add_element(Dir, DirSet2), + %% Make sure the CWD is reset properly; processing the dirs may have + %% caused it to change + ok = file:set_cwd(Dir), - %% Invoke 'postprocess' on the modules. This yields a list of other - %% directories that should be processed _after_ the current one. - Postdirs = acc_modules(Modules ++ PluginModules, postprocess, - Config, ModuleSetFile), - ?DEBUG("Postdirs: ~p\n", [Postdirs]), - DirSet4 = process_each(Postdirs, Command, Config, - ModuleSetFile, DirSet3), + %% Check that this directory is not on the skip list + case is_skip_dir(Dir) of + true -> + %% Do not execute the command on the directory, as some + %% module as requested a skip on it. + ?INFO("Skipping ~s in ~s\n", [Command, Dir]); - %% Make sure the CWD is reset properly; processing the dirs may have - %% caused it to change - ok = file:set_cwd(Dir), + false -> + %% Execute any before_command plugins on this directory + execute_pre(Command, PluginModules, + Config, ModuleSetFile), - %% Once we're all done processing, reset the code path to whatever - %% the parent initialized it to - restore_code_path(CurrentCodePath), + %% Execute the current command on this directory + execute(Command, Modules ++ PluginModules, + Config, ModuleSetFile), - %% Return the updated dirset as our result - DirSet4 - end. + %% Execute any after_command plugins on this directory + execute_post(Command, PluginModules, + Config, ModuleSetFile) + end, + + %% Mark the current directory as processed + DirSet3 = sets:add_element(Dir, DirSet2), + + %% Invoke 'postprocess' on the modules. This yields a list of other + %% directories that should be processed _after_ the current one. + Postdirs = acc_modules(Modules ++ PluginModules, postprocess, + Config, ModuleSetFile), + ?DEBUG("Postdirs: ~p\n", [Postdirs]), + DirSet4 = process_each(Postdirs, Command, Config, + ModuleSetFile, DirSet3), + + %% Make sure the CWD is reset properly; processing the dirs may have + %% caused it to change + ok = file:set_cwd(Dir), + + %% Once we're all done processing, reset the code path to whatever + %% the parent initialized it to + restore_code_path(CurrentCodePath), + + %% Return the updated dirset as our result + DirSet4. maybe_load_local_config(Dir, ParentConfig) -> %% We need to ensure we don't overwrite custom @@ -274,9 +304,7 @@ execute(Command, Modules, Config, ModuleFile) -> Dir = rebar_utils:get_cwd(), ?CONSOLE("==> ~s (~s)\n", [filename:basename(Dir), Command]), - %% Increment the count of operations, since some module - %% responds to this command - erlang:put(operations, erlang:get(operations) + 1), + increment_operations(), %% Check for and get command specific environments Env = setup_envs(Config, Modules), @@ -300,6 +328,11 @@ execute(Command, Modules, Config, ModuleFile) -> end end. +%% Increment the count of operations, since some module +%% responds to this command +increment_operations() -> + erlang:put(operations, erlang:get(operations) + 1). + update_code_path(Config) -> case rebar_config:get_local(Config, lib_dirs, []) of diff --git a/src/rebar_ct.erl b/src/rebar_ct.erl index 0303787..54e97e9 100644 --- a/src/rebar_ct.erl +++ b/src/rebar_ct.erl @@ -46,20 +46,7 @@ %% =================================================================== ct(Config, File) -> - case rebar_config:get_global(app, undefined) of - undefined -> - %% No app parameter specified, run everything.. - run_test_if_present("test", Config, File); - Apps -> - TargetApps = [list_to_atom(A) || A <- string:tokens(Apps, ",")], - ThisApp = rebar_app_utils:app_name(File), - case lists:member(ThisApp, TargetApps) of - true -> - run_test_if_present("test", Config, File); - false -> - ?DEBUG("Skipping common_test on app: ~p\n", [ThisApp]) - end - end. + run_test_if_present("test", Config, File). %% =================================================================== %% Internal functions diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl index 439b8f9..2b887ee 100644 --- a/src/rebar_eunit.erl +++ b/src/rebar_eunit.erl @@ -63,40 +63,7 @@ %% Public API %% =================================================================== -eunit(Config, AppFile) -> - %% Check for app global parameter; this is a comma-delimited list - %% of apps on which we want to run eunit - case rebar_config:get_global(app, undefined) of - undefined -> - %% No app parameter specified, check the skip list.. - case rebar_config:get_global(skip_app, undefined) of - undefined -> - %% no skip list, run everything.. - ok; - SkipApps -> - TargetApps = [list_to_atom(A) || - A <- string:tokens(SkipApps, ",")], - ThisApp = rebar_app_utils:app_name(AppFile), - case lists:member(ThisApp, TargetApps) of - false -> - ok; - true -> - ?DEBUG("Skipping eunit on app: ~p\n", [ThisApp]), - throw(ok) - end - end; - Apps -> - TargetApps = [list_to_atom(A) || A <- string:tokens(Apps, ",")], - ThisApp = rebar_app_utils:app_name(AppFile), - case lists:member(ThisApp, TargetApps) of - true -> - ok; - false -> - ?DEBUG("Skipping eunit on app: ~p\n", [ThisApp]), - throw(ok) - end - end, - +eunit(Config, _AppFile) -> %% Make sure ?EUNIT_DIR/ and ebin/ directory exists (tack on dummy module) ok = filelib:ensure_dir(eunit_dir() ++ "/foo"), ok = filelib:ensure_dir(ebin_dir() ++ "/foo"), diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 838b71a..3fa8030 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -56,7 +56,6 @@ get_cwd() -> {ok, Dir} = file:get_cwd(), Dir. - is_arch(ArchRegex) -> case re:run(get_arch(), ArchRegex, [{capture, none}]) of match -> diff --git a/src/rebar_xref.erl b/src/rebar_xref.erl index 0af741f..84d422e 100644 --- a/src/rebar_xref.erl +++ b/src/rebar_xref.erl @@ -40,17 +40,7 @@ %% Public API %% =================================================================== -xref(Config, _X) -> - case rebar_app_utils:is_skipped_app() of - true -> ok; - false -> xref0(Config, _X) - end. - -%% =================================================================== -%% Internal functions -%% =================================================================== - -xref0(Config, _) -> +xref(Config, _) -> %% Spin up xref {ok, _} = xref:start(xref), ok = xref:set_library_path(xref, code_path()), @@ -100,6 +90,10 @@ xref0(Config, _) -> ?FAIL end. +%% =================================================================== +%% Internal functions +%% =================================================================== + check_exports_not_used() -> {ok, UnusedExports0} = xref:analyze(xref, exports_not_used), UnusedExports = filter_away_ignored(UnusedExports0),