summaryrefslogtreecommitdiff
path: root/src/rebar_dir.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/rebar_dir.erl')
-rw-r--r--src/rebar_dir.erl111
1 files changed, 93 insertions, 18 deletions
diff --git a/src/rebar_dir.erl b/src/rebar_dir.erl
index 79a1c7f..069d8fd 100644
--- a/src/rebar_dir.erl
+++ b/src/rebar_dir.erl
@@ -1,3 +1,4 @@
+%%% @doc utility functions for directory and path handling of all kind.
-module(rebar_dir).
-export([base_dir/1,
@@ -29,10 +30,14 @@
-include("rebar.hrl").
+%% @doc returns the directory root for build artifacts
+%% for the current profile, such as `_build/default/'.
-spec base_dir(rebar_state:t()) -> file:filename_all().
base_dir(State) ->
profile_dir(rebar_state:opts(State), rebar_state:current_profiles(State)).
+%% @doc returns the directory root for build artifacts for a given set
+%% of profiles.
-spec profile_dir(rebar_dict(), [atom()]) -> file:filename_all().
profile_dir(Opts, Profiles) ->
{BaseDir, ProfilesStrings} = case [ec_cnv:to_list(P) || P <- Profiles] of
@@ -46,25 +51,36 @@ profile_dir(Opts, Profiles) ->
ProfilesDir = string:join(ProfilesStrings, "+"),
filename:join(BaseDir, ProfilesDir).
+%% @doc returns the directory where dependencies should be placed
+%% given the current profile.
-spec deps_dir(rebar_state:t()) -> file:filename_all().
deps_dir(State) ->
filename:join(base_dir(State), rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR)).
+%% @doc returns the directory where a dependency should be placed
+%% given the current profile, based on its app name. Expects to be passed
+%% the result of `deps_dir/1' as a first argument.
-spec deps_dir(file:filename_all(), file:filename_all()) -> file:filename_all().
deps_dir(DepsDir, App) ->
filename:join(DepsDir, App).
+%% @doc returns the absolute path for the project root (by default,
+%% the current working directory for the currently running escript).
root_dir(State) ->
filename:absname(rebar_state:get(State, root_dir, ?DEFAULT_ROOT_DIR)).
+%% @doc returns the expected location of the `_checkouts' directory.
-spec checkouts_dir(rebar_state:t()) -> file:filename_all().
checkouts_dir(State) ->
filename:join(root_dir(State), rebar_state:get(State, checkouts_dir, ?DEFAULT_CHECKOUTS_DIR)).
+%% @doc returns the expected location of a given app in the checkouts
+%% directory for the project.
-spec checkouts_dir(rebar_state:t(), file:filename_all()) -> file:filename_all().
checkouts_dir(State, App) ->
filename:join(checkouts_dir(State), App).
+%% @doc Returns the directory where plugins are located.
-spec plugins_dir(rebar_state:t()) -> file:filename_all().
plugins_dir(State) ->
case lists:member(global, rebar_state:current_profiles(State)) of
@@ -74,33 +90,50 @@ plugins_dir(State) ->
filename:join(base_dir(State), rebar_state:get(State, plugins_dir, ?DEFAULT_PLUGINS_DIR))
end.
+%% @doc returns the list of relative path where the project applications can
+%% be located.
-spec lib_dirs(rebar_state:t()) -> file:filename_all().
lib_dirs(State) ->
rebar_state:get(State, project_app_dirs, ?DEFAULT_PROJECT_APP_DIRS).
+%% @doc returns the user's home directory.
+-spec home_dir() -> file:filename_all().
home_dir() ->
{ok, [[Home]]} = init:get_argument(home),
Home.
+%% @doc returns the directory where the global configuration files for rebar3
+%% may be stored.
+-spec global_config_dir(rebar_state:t()) -> file:filename_all().
global_config_dir(State) ->
Home = home_dir(),
rebar_state:get(State, global_rebar_dir, filename:join([Home, ".config", "rebar3"])).
+%% @doc returns the path of the global rebar.config file
+-spec global_config(rebar_state:t()) -> file:filename_all().
global_config(State) ->
filename:join(global_config_dir(State), "rebar.config").
+%% @doc returns the default path of the global rebar.config file
+-spec global_config() -> file:filename_all().
global_config() ->
Home = home_dir(),
filename:join([Home, ".config", "rebar3", "rebar.config"]).
+%% @doc returns the location for the global cache directory
-spec global_cache_dir(rebar_dict()) -> file:filename_all().
global_cache_dir(Opts) ->
Home = home_dir(),
rebar_opts:get(Opts, global_rebar_dir, filename:join([Home, ".cache", "rebar3"])).
+%% @doc appends the cache directory to the path passed to this function.
+-spec local_cache_dir(file:filename_all()) -> file:filename_all().
local_cache_dir(Dir) ->
filename:join(Dir, ".rebar3").
+%% @doc returns the current working directory, with some specific
+%% conversions and handling done to be cross-platform compatible.
+-spec get_cwd() -> file:filename_all().
get_cwd() ->
{ok, Dir} = file:get_cwd(),
%% On windows cwd may return capital letter for drive,
@@ -109,20 +142,33 @@ get_cwd() ->
%% cwd as soon as it possible.
filename:join([Dir]).
+%% @doc returns the file location for the global template
+%% configuration variables file.
+-spec template_globals(rebar_state:t()) -> file:filename_all().
template_globals(State) ->
filename:join([global_config_dir(State), "templates", "globals"]).
+%% @doc returns the location for the global template directory
+-spec template_dir(rebar_state:t()) -> file:filename_all().
template_dir(State) ->
filename:join([global_config_dir(State), "templates"]).
+%% @doc checks if the current working directory is the base directory
+%% for the project.
+-spec processing_base_dir(rebar_state:t()) -> boolean().
processing_base_dir(State) ->
Cwd = get_cwd(),
processing_base_dir(State, Cwd).
+%% @doc checks if the passed in directory is the base directory for
+%% the project.
+-spec processing_base_dir(rebar_state:t(), file:filename()) -> boolean().
processing_base_dir(State, Dir) ->
AbsDir = filename:absname(Dir),
AbsDir =:= rebar_state:get(State, base_dir).
+%% @doc make a path absolute
+-spec make_absolute_path(file:filename()) -> file:filename().
make_absolute_path(Path) ->
case filename:pathtype(Path) of
absolute ->
@@ -136,11 +182,16 @@ make_absolute_path(Path) ->
filename:join([Dir, Path])
end.
+%% @doc normalizing a path removes all of the `..' and the
+%% `.' segments it may contain.
+-spec make_normalized_path(file:filename()) -> file:filename().
make_normalized_path(Path) ->
AbsPath = make_absolute_path(Path),
Components = filename:split(AbsPath),
make_normalized_path(Components, []).
+%% @private drops path fragments for normalization
+-spec make_normalized_path([string()], [string()]) -> file:filename().
make_normalized_path([], NormalizedPath) ->
filename:join(lists:reverse(NormalizedPath));
make_normalized_path([H|T], NormalizedPath) ->
@@ -150,48 +201,67 @@ make_normalized_path([H|T], NormalizedPath) ->
_ -> make_normalized_path(T, [H|NormalizedPath])
end.
+%% @doc take a source and a target path, and relativize the target path
+%% onto the source.
+%%
+%% Example:
+%% ```
+%% 1> rebar_dir:make_relative_path("a/b/c/d/file", "a/b/file").
+%% "c/d/file"
+%% 2> rebar_dir:make_relative_path("a/b/file", "a/b/c/d/file").
+%% "../../file"
+%% '''
+-spec make_relative_path(file:filename(), file:filename()) -> file:filename().
make_relative_path(Source, Target) ->
AbsSource = make_normalized_path(Source),
AbsTarget = make_normalized_path(Target),
do_make_relative_path(filename:split(AbsSource), filename:split(AbsTarget)).
+%% @private based on fragments of paths, replace the number of common
+%% segments by `../' bits, and add the rest of the source alone after it
+-spec do_make_relative_path([string()], [string()]) -> file:filename().
do_make_relative_path([H|T1], [H|T2]) ->
do_make_relative_path(T1, T2);
do_make_relative_path(Source, Target) ->
Base = lists:duplicate(max(length(Target) - 1, 0), ".."),
filename:join(Base ++ Source).
-%%%-----------------------------------------------------------------
-%%% 'src_dirs' and 'extra_src_dirs' can be configured with options
+%%% @doc
+%%% `src_dirs' and `extra_src_dirs' can be configured with options
%%% like this:
-%%%
+%%% ```
%%% {src_dirs,[{"foo",[{recursive,false}]}]}
%%% {extra_src_dirs,[{"bar",[recursive]}]} (equivalent to {recursive,true})
-%%%
-%%% src_dirs/1,2 and extra_src_dirs/1,2 return only the list of
-%%% directories for the 'src_dirs' and 'extra_src_dirs' options
-%%% respectively, while src_dirs_opts/2 return the options list for
-%%% the given directory, no matter if it is configured as 'src_dirs' or
-%%% 'extra_src_dirs'.
-%%%
+%%% '''
+%%% `src_dirs/1,2' and `extra_src_dirs/1,2' return only the list of
+%%% directories for the `src_dirs' and `extra_src_dirs' options
+%%% respectively, while `src_dirs_opts/2' returns the options list for
+%%% the given directory, no matter if it is configured as `src_dirs' or
+%%% `extra_src_dirs'.
-spec src_dirs(rebar_dict()) -> list(file:filename_all()).
src_dirs(Opts) -> src_dirs(Opts, []).
+%% @doc same as `src_dirs/1', but allows to pass in a list of default options.
-spec src_dirs(rebar_dict(), list(file:filename_all())) -> list(file:filename_all()).
src_dirs(Opts, Default) ->
src_dirs(src_dirs, Opts, Default).
+%% @doc same as `src_dirs/1', but for the `extra_src_dirs' options
-spec extra_src_dirs(rebar_dict()) -> list(file:filename_all()).
extra_src_dirs(Opts) -> extra_src_dirs(Opts, []).
+%% @doc same as `src_dirs/2', but for the `extra_src_dirs' options
-spec extra_src_dirs(rebar_dict(), list(file:filename_all())) -> list(file:filename_all()).
extra_src_dirs(Opts, Default) ->
src_dirs(extra_src_dirs, Opts, Default).
+%% @private agnostic version of src_dirs and extra_src_dirs.
src_dirs(Type, Opts, Default) ->
lists:usort([case D0 of {D,_} -> D; _ -> D0 end ||
D0 <- raw_src_dirs(Type,Opts,Default)]).
+%% @private extracts the un-formatted src_dirs or extra_src_dirs
+%% options as configured.
raw_src_dirs(Type, Opts, Default) ->
ErlOpts = rebar_opts:erl_opts(Opts),
Vs = proplists:get_all_values(Type, ErlOpts),
@@ -200,19 +270,23 @@ raw_src_dirs(Type, Opts, Default) ->
Dirs -> Dirs
end.
+%% @doc returns all the source directories (`src_dirs' and
+%% `extra_src_dirs').
-spec all_src_dirs(rebar_dict()) -> list(file:filename_all()).
all_src_dirs(Opts) -> all_src_dirs(Opts, [], []).
+%% @doc returns all the source directories (`src_dirs' and
+%% `extra_src_dirs') while being able to configure defaults for both.
-spec all_src_dirs(rebar_dict(), list(file:filename_all()), list(file:filename_all())) ->
list(file:filename_all()).
all_src_dirs(Opts, SrcDefault, ExtraDefault) ->
lists:usort(src_dirs(Opts, SrcDefault) ++ extra_src_dirs(Opts, ExtraDefault)).
-%%%-----------------------------------------------------------------
+%%% @doc
%%% Return the list of options for the given src directory
%%% If the same option is given multiple times for a directory in the
-%%% config, the priority order is: first occurence of 'src_dirs'
-%%% followed by first occurence of 'extra_src_dirs'.
+%%% config, the priority order is: first occurence of `src_dirs'
+%%% followed by first occurence of `extra_src_dirs'.
-spec src_dir_opts(rebar_dict(), file:filename_all()) -> [{atom(),term()}].
src_dir_opts(Opts, Dir) ->
RawSrcDirs = raw_src_dirs(src_dirs, Opts, []),
@@ -221,7 +295,7 @@ src_dir_opts(Opts, Dir) ->
D==Dir],
lists:ukeysort(1,proplists:unfold(lists:append(AllOpts))).
-%%%-----------------------------------------------------------------
+%%% @doc
%%% Return the value of the 'recursive' option for the given directory.
%%% If not given, the value of 'recursive' in the 'erlc_compiler'
%%% options is used, and finally the default is 'true'.
@@ -234,16 +308,17 @@ recursive(Opts, Dir) ->
R = proplists:get_value(recursive, DirOpts, Default),
R.
-%% given a path if that path is an ancestor of an app dir return the path relative to that
-%% apps outdir. if the path is not an ancestor to any app dirs but is an ancestor of the
-%% project root return the path relative to the project base_dir. if it is not an ancestor
+%% @doc given a path if that path is an ancestor of an app dir, return the path relative to that
+%% apps outdir. If the path is not an ancestor to any app dirs but is an ancestor of the
+%% project root, return the path relative to the project base_dir. If it is not an ancestor
%% of either return it unmodified
-spec retarget_path(rebar_state:t(), string()) -> string().
-
retarget_path(State, Path) ->
ProjectApps = rebar_state:project_apps(State),
retarget_path(State, Path, ProjectApps).
+%% @private worker for retarget_path/2
+%% @end
%% not relative to any apps in project, check to see it's relative to
%% project root
retarget_path(State, Path, []) ->