diff --git a/src/rebar_prv_clean.erl b/src/rebar_prv_clean.erl index 3c8a0c3f..5d0d0a50 100644 --- a/src/rebar_prv_clean.erl +++ b/src/rebar_prv_clean.erl @@ -28,28 +28,32 @@ init(State) -> {short_desc, "Remove compiled beam files from apps."}, {desc, "Remove compiled beam files from apps."}, {opts, [{all, $a, "all", undefined, "Clean all apps include deps"}, + {apps, undefined, "apps", string, "Clean a specific list of apps or dependencies"}, {profile, $p, "profile", string, "Clean under profile. Equivalent to `rebar3 as clean`"}]}])), {ok, State1}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. do(State) -> Providers = rebar_state:providers(State), - {All, Profiles} = handle_args(State), + {All, Profiles, Specific} = handle_args(State), State1 = rebar_state:apply_profiles(State, [list_to_atom(X) || X <- Profiles]), Cwd = rebar_dir:get_cwd(), rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State1), - case All of - true -> - DepsDir = rebar_dir:deps_dir(State1), - DepsDirs = filelib:wildcard(filename:join(DepsDir, "*")), - AllApps = rebar_app_discover:find_apps(DepsDirs, all), - clean_apps(State1, Providers, AllApps); - false -> - ProjectApps = rebar_state:project_apps(State1), - clean_apps(State1, Providers, ProjectApps) + if All; Specific =/= [] -> + DepsDir = rebar_dir:deps_dir(State1), + DepsDirs = filelib:wildcard(filename:join(DepsDir, "*")), + AllApps = rebar_app_discover:find_apps(DepsDirs, all), + Filter = case All of + true -> fun(_) -> true end; + false -> fun(AppInfo) -> filter_name(AppInfo, Specific) end + end, + clean_apps(State1, Providers, AllApps, Filter); + true -> + ProjectApps = rebar_state:project_apps(State1), + clean_apps(State1, Providers, ProjectApps, fun(_) -> true end) end, clean_extras(State1), @@ -66,7 +70,7 @@ format_error(Reason) -> %% Internal functions %% =================================================================== -clean_apps(State, Providers, Apps) -> +clean_apps(State, Providers, Apps, Filter) -> Compilers = rebar_state:compilers(State), [begin ?INFO("Cleaning out ~ts...", [rebar_app_info:name(AppInfo)]), @@ -74,7 +78,7 @@ clean_apps(State, Providers, Apps) -> AppInfo1 = rebar_hooks:run_all_hooks(AppDir, pre, ?PROVIDER, Providers, AppInfo, State), rebar_compiler:clean(Compilers, AppInfo1), rebar_hooks:run_all_hooks(AppDir, post, ?PROVIDER, Providers, AppInfo1, State) - end || AppInfo <- Apps]. + end || AppInfo <- Apps, Filter(AppInfo)]. clean_extras(State) -> BaseDir = rebar_dir:base_dir(State), @@ -84,4 +88,17 @@ handle_args(State) -> {Args, _} = rebar_state:command_parsed_args(State), All = proplists:get_value(all, Args, false), Profiles = proplists:get_all_values(profile, Args), - {All, Profiles}. + DepsRaw = proplists:get_value(apps, Args), + Deps = parse_deps(DepsRaw), + {All, Profiles, Deps}. + +parse_deps(undefined) -> []; +parse_deps(Bin) -> + case lists:usort(re:split(Bin, <<" *, *">>, [trim, unicode])) of + [<<"">>] -> []; % nothing submitted + Other -> Other + end. + +filter_name(AppInfo, Names) -> + Name = rebar_app_info:name(AppInfo), + lists:member(Name, Names). diff --git a/test/rebar_compile_SUITE.erl b/test/rebar_compile_SUITE.erl index 30523678..bb7f9e8b 100644 --- a/test/rebar_compile_SUITE.erl +++ b/test/rebar_compile_SUITE.erl @@ -24,7 +24,7 @@ all() -> deps_in_path, checkout_priority, highest_version_of_pkg_dep, parse_transform_test, erl_first_files_test, mib_test, umbrella_mib_first_test, only_default_transitive_deps, clean_all, - profile_deps, deps_build_in_prod, only_deps, + clean_specific, profile_deps, deps_build_in_prod, only_deps, override_deps, override_add_deps, override_del_deps, override_opts, override_add_opts, override_del_opts, apply_overrides_exactly_once, override_only_deps, @@ -1351,6 +1351,38 @@ clean_all(Config) -> {app, DepName, invalid}, {app, PkgName, invalid}]}). +clean_specific(Config) -> + AppDir = ?config(apps, Config), + + Name = rebar_test_utils:create_random_name("app1_"), + Vsn = rebar_test_utils:create_random_vsn(), + rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + + DepName = rebar_test_utils:create_random_name("dep1_"), + PkgName = rebar_test_utils:create_random_name("pkg1_"), + mock_git_resource:mock([]), + mock_pkg_resource:mock([ + {pkgdeps, [{{iolist_to_binary(PkgName), iolist_to_binary(Vsn)}, []}]} + ]), + + RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ + {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}}, + {list_to_atom(PkgName), Vsn} + ]}]), + {ok, RConf} = file:consult(RConfFile), + + %% Build things + rebar_test_utils:run_and_check( + Config, RConf, ["compile"], + {ok, [{app, Name}, {app, DepName}, {app, PkgName}]} + ), + + %% Clean all + rebar_test_utils:run_and_check(Config, [], ["clean", "--apps="++DepName++","++Name], + {ok, [{app, Name, invalid}, + {app, DepName, invalid}, + {app, PkgName, valid}]}). + override_deps(Config) -> Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps),