diff options
-rw-r--r-- | src/rebar.app.src | 1 | ||||
-rw-r--r-- | src/rebar_prv_path.erl | 123 |
2 files changed, 124 insertions, 0 deletions
diff --git a/src/rebar.app.src b/src/rebar.app.src index 6b0f315..655506e 100644 --- a/src/rebar.app.src +++ b/src/rebar.app.src @@ -52,6 +52,7 @@ rebar_prv_lock, rebar_prv_new, rebar_prv_packages, + rebar_prv_path, rebar_prv_plugins, rebar_prv_plugins_upgrade, rebar_prv_release, diff --git a/src/rebar_prv_path.erl b/src/rebar_prv_path.erl new file mode 100644 index 0000000..2da41ea --- /dev/null +++ b/src/rebar_prv_path.erl @@ -0,0 +1,123 @@ +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% ex: ts=4 sw=4 et + +-module(rebar_prv_path). + +-behaviour(provider). + +-export([init/1, + do/1, + format_error/1]). + +-include("rebar.hrl"). + +-define(PROVIDER, path). +-define(DEPS, [app_discovery]). + +%% =================================================================== +%% Public API +%% =================================================================== + +-spec init(rebar_state:t()) -> {ok, rebar_state:t()}. +init(State) -> + State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER}, + {module, ?MODULE}, + {bare, true}, + {deps, ?DEPS}, + {example, "rebar3 path"}, + {short_desc, "Print paths to build dirs in current profile."}, + {desc, "Print paths to build dirs in current profile."}, + {opts, eunit_opts(State)}])), + + {ok, State1}. + +-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. +do(State) -> + {RawOpts, _} = rebar_state:command_parsed_args(State), + %% retrieve apps to filter by for other args + Apps = filter_apps(RawOpts, State), + %% remove apps opt from options + Paths = lists:filter(fun({app, _}) -> false; (_) -> true end, RawOpts), + %% if no paths requested in opts print the base_dir instead + P = case Paths of [] -> [{base, true}]; _ -> Paths end, + case paths(P, Apps, State, []) of + ok -> {ok, State}; + {error, Error} -> {error, Error} + end. + +-spec format_error(any()) -> iolist(). +format_error(Reason) -> + io_lib:format("~p", [Reason]). + +filter_apps(RawOpts, State) -> + RawApps = proplists:get_all_values(app, RawOpts), + Apps = lists:foldl(fun(String, Acc) -> string:tokens(String, ",") ++ Acc end, [], RawApps), + case Apps of + [] -> + ProjectDeps = project_deps(State), + ProjectApps = rebar_state:project_apps(State), + lists:map(fun(A) -> binary_to_list(rebar_app_info:name(A)) end, ProjectApps) ++ ProjectDeps; + _ -> Apps + end. + + +paths([], _, _, Acc) -> print_paths_if_exist(lists:reverse(Acc)); +paths([{base, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, [base_dir(State)|Acc]); +paths([{bin, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, [bin_dir(State)|Acc]); +paths([{ebin, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, ebin_dirs(Apps, State) ++ Acc); +paths([{lib, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, [lib_dir(State)|Acc]); +paths([{priv, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, priv_dirs(Apps, State) ++ Acc); +paths([{src, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, src_dirs(Apps, State) ++ Acc); +paths([{rel, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, [rel_dir(State)|Acc]). + +base_dir(State) -> io_lib:format("~s", [rebar_dir:base_dir(State)]). +bin_dir(State) -> io_lib:format("~s/bin", [rebar_dir:base_dir(State)]). +lib_dir(State) -> io_lib:format("~s/lib", [rebar_dir:base_dir(State)]). +rel_dir(State) -> io_lib:format("~s/rel", [rebar_dir:base_dir(State)]). + +ebin_dirs(Apps, State) -> + lists:map(fun(App) -> io_lib:format("~s/lib/~s/ebin", [rebar_dir:base_dir(State), App]) end, Apps). +priv_dirs(Apps, State) -> + lists:map(fun(App) -> io_lib:format("~s/lib/~s/priv", [rebar_dir:base_dir(State), App]) end, Apps). +src_dirs(Apps, State) -> + lists:map(fun(App) -> io_lib:format("~s/lib/~s/src", [rebar_dir:base_dir(State), App]) end, Apps). + +print_paths_if_exist(Paths) -> + RealPaths = lists:filter(fun(P) -> ec_file:is_dir(P) end, Paths), + io:format("~s", [string:join(RealPaths, ",")]). + +project_deps(State) -> + Profiles = rebar_state:current_profiles(State), + List = lists:foldl(fun(Profile, Acc) -> rebar_state:get(State, {deps, Profile}, []) ++ Acc end, [], Profiles), + Deps = [normalize(Name) || {Name, _} <- List], + lists:usort(Deps). + +normalize(AppName) when is_list(AppName) -> AppName; +normalize(AppName) when is_atom(AppName) -> atom_to_list(AppName); +normalize(AppName) when is_binary(AppName) -> binary_to_list(AppName). + +eunit_opts(_State) -> + [{app, undefined, "app", string, help(app)}, + {base, undefined, "base", boolean, help(base)}, + {bin, undefined, "bin", boolean, help(bin)}, + {ebin, undefined, "ebin", boolean, help(ebin)}, + {lib, undefined, "lib", boolean, help(lib)}, + {priv, undefined, "priv", boolean, help(priv)}, + {src, undefined, "src", boolean, help(src)}, + {rel, undefined, "rel", boolean, help(rel)}]. + +help(app) -> "Comma seperated list of applications to return paths for."; +help(base) -> "Return the `base' path of the current profile."; +help(bin) -> "Return the `bin' path of the current profile."; +help(ebin) -> "Return all `ebin' paths of the current profile's applications."; +help(lib) -> "Return the `lib' path of the current profile."; +help(priv) -> "Return the `priv' path of the current profile's applications."; +help(src) -> "Return the `src' path of the current profile's applications."; +help(rel) -> "Return the `rel' path of the current profile.".
\ No newline at end of file |