summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rebar.hrl14
-rw-r--r--src/rebar_app_discover.erl13
-rw-r--r--src/rebar_git_resource.erl28
-rw-r--r--src/rebar_prv_shell.erl43
-rw-r--r--src/rebar_resource_v2.erl3
-rw-r--r--src/rebar_utils.erl14
6 files changed, 90 insertions, 25 deletions
diff --git a/src/rebar.hrl b/src/rebar.hrl
index f11302d..fedf0d0 100644
--- a/src/rebar.hrl
+++ b/src/rebar.hrl
@@ -55,23 +55,9 @@
state :: term(),
implementation :: rebar_resource | rebar_resource_v2}).
--ifdef(namespaced_types).
-type rebar_dict() :: dict:dict().
--else.
--type rebar_dict() :: dict().
--endif.
-
--ifdef(namespaced_types).
-type rebar_digraph() :: digraph:graph().
--else.
--type rebar_digraph() :: digraph().
--endif.
-
--ifdef(namespaced_types).
-type rebar_set() :: sets:set().
--else.
--type rebar_set() :: set().
--endif.
-ifdef(fun_stacktrace).
-define(WITH_STACKTRACE(T, R, S), T:R -> S = erlang:get_stacktrace(),).
diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl
index 21dea29..0c97ad7 100644
--- a/src/rebar_app_discover.erl
+++ b/src/rebar_app_discover.erl
@@ -52,7 +52,7 @@ do(State, LibDirs) ->
Name = rebar_app_info:name(AppInfo),
case enable(State, AppInfo) of
true ->
- {AppInfo1, StateAcc1} = merge_opts(AppInfo, StateAcc),
+ {AppInfo1, StateAcc1} = merge_opts(TopLevelApp, AppInfo, StateAcc),
OutDir = filename:join(DepsDir, Name),
AppInfo2 = rebar_app_info:out_dir(AppInfo1, OutDir),
ProjectDeps1 = lists:delete(Name, ProjectDeps),
@@ -91,9 +91,9 @@ format_error({missing_module, Module}) ->
%% some configuration like erl_opts must be merged into a subapp's opts
%% while plugins and hooks need to be kept defined to only either the
%% top level state or an individual application.
--spec merge_opts(rebar_app_info:t(), rebar_state:t()) ->
+-spec merge_opts(root | binary(), rebar_app_info:t(), rebar_state:t()) ->
{rebar_app_info:t(), rebar_state:t()}.
-merge_opts(AppInfo, State) ->
+merge_opts(TopLevelApp, AppInfo, State) ->
%% These steps make sure that hooks and artifacts are run in the context of
%% the application they are defined at. If an umbrella structure is used and
%% they are defined at the top level they will instead run in the context of
@@ -104,7 +104,12 @@ merge_opts(AppInfo, State) ->
Name = rebar_app_info:name(AppInfo1),
%% We reset the opts here to default so no profiles are applied multiple times
- AppInfo2 = rebar_app_info:apply_overrides(rebar_state:get(State1, overrides, []), AppInfo1),
+ AppInfo2 = case TopLevelApp of
+ Name -> % don't apply to the root app
+ AppInfo;
+ _ -> % apply overrides when in an umbrella project or on deps
+ rebar_app_info:apply_overrides(rebar_state:get(State1, overrides, []), AppInfo1)
+ end,
AppInfo3 = rebar_app_info:apply_profiles(AppInfo2, CurrentProfiles),
%% Will throw an exception if checks fail
diff --git a/src/rebar_git_resource.erl b/src/rebar_git_resource.erl
index ac1316b..4e81c05 100644
--- a/src/rebar_git_resource.erl
+++ b/src/rebar_git_resource.erl
@@ -236,7 +236,17 @@ git_vsn_fetch() ->
end.
make_vsn(AppInfo, _) ->
- make_vsn_(rebar_app_info:dir(AppInfo)).
+ Dir = rebar_app_info:dir(AppInfo),
+ case rebar_app_info:original_vsn(AppInfo) of
+ {git, short} ->
+ git_ref(Dir, "--short");
+ {git, long} ->
+ git_ref(Dir, "");
+ _ ->
+ %% already parsed in rebar_utils to get here so we know it
+ %% is either for git or "git"
+ make_vsn_(Dir)
+ end.
make_vsn_(Dir) ->
case collect_default_refcount(Dir) of
@@ -248,6 +258,19 @@ make_vsn_(Dir) ->
%% Internal functions
+git_ref(Dir, Arg) ->
+ case rebar_utils:sh("git rev-parse " ++ Arg ++ " HEAD",
+ [{use_stdout, false},
+ return_on_error,
+ {cd, Dir}]) of
+ {error, _} ->
+ ?WARN("Getting ref of git repo failed in ~ts. "
+ "Falling back to version 0", [Dir]),
+ {plain, "0"};
+ {ok, String} ->
+ {plain, rebar_string:trim(String, both, "\n")}
+ end.
+
collect_default_refcount(Dir) ->
%% Get the tag timestamp and minimal ref from the system. The
%% timestamp is really important from an ordering perspective.
@@ -256,7 +279,8 @@ collect_default_refcount(Dir) ->
return_on_error,
{cd, Dir}]) of
{error, _} ->
- ?WARN("Getting log of git dependency failed in ~ts. Falling back to version 0.0.0", [rebar_dir:get_cwd()]),
+ ?WARN("Getting log of git repo failed in ~ts. "
+ "Falling back to version 0.0.0", [Dir]),
{plain, "0.0.0"};
{ok, String} ->
RawRef = rebar_string:trim(String, both, "\n"),
diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl
index dd3e6f6..406b90a 100644
--- a/src/rebar_prv_shell.erl
+++ b/src/rebar_prv_shell.erl
@@ -88,6 +88,9 @@ init(State) ->
{start_clean, undefined, "start-clean", boolean,
"Cancel any applications in the 'apps' list "
"or release."},
+ {env_file, undefined, "env-file", string,
+ "Path to file of os environment variables to setup "
+ "before expanding vars in config files."},
{user_drv_args, undefined, "user_drv_args", string,
"Arguments passed to user_drv start function for "
"creating custom shells."}]}
@@ -309,6 +312,7 @@ run_script_file(File) ->
Result.
maybe_boot_apps(State) ->
+ _ = maybe_set_env_vars(State),
case find_apps_to_boot(State) of
undefined ->
%% try to read in sys.config file
@@ -577,6 +581,45 @@ consult_env_config(State, Filename) ->
rebar_file_utils:consult_config_terms(State, Terms)
end.
+maybe_set_env_vars(State) ->
+ EnvFile =debug_get_value(env_file, rebar_state:get(State, shell, []), undefined,
+ "Found env_file from config."),
+ {Opts, _} = rebar_state:command_parsed_args(State),
+ EnvFile1 = debug_get_value(env_file, Opts, EnvFile,
+ "Found env_file from command line option."),
+
+ case maybe_read_file(EnvFile1) of
+ ignore ->
+ ok;
+ {error, _} ->
+ ?WARN("Failed to read file with environment variables: ~p", [EnvFile1]);
+ {ok, Bin} ->
+ Lines = string:split(unicode:characters_to_list(Bin), "\n", all),
+ [handle_env_var_line(Line) || Line <- Lines]
+ end.
+
+handle_env_var_line(Line) ->
+ Trimmed = rebar_string:trim(Line, both, [$\s]),
+ %% ignore lines starting with # and
+ %% fail if there are spaces around =
+ case re:run(Trimmed, "^(?<key>[^#][^\s=]*)=(?<value>[^\s]\.*)",
+ [{capture, [key, value], list}, unicode]) of
+ {match, [Key, Value]} ->
+ os:putenv(Key, Value);
+ _ ->
+ case Trimmed of
+ [$# | _] -> ignore;
+ [] -> ignore;
+ Other ->
+ ?WARN("Unable to parse environment variable from this line: ~ts", [Other])
+ end
+ end.
+
+maybe_read_file(undefined) ->
+ ignore;
+maybe_read_file(EnvFile) ->
+ file:read_file(EnvFile).
+
%% @doc quick and simple variable substitution writeup.
%% Supports `${varname}' but not `$varname' nor nested
%% values such as `${my_${varname}}'.
diff --git a/src/rebar_resource_v2.erl b/src/rebar_resource_v2.erl
index b7ee760..537b5f0 100644
--- a/src/rebar_resource_v2.erl
+++ b/src/rebar_resource_v2.erl
@@ -101,7 +101,8 @@ needs_update(AppInfo, State) ->
resource_run(needs_update, rebar_app_info:source(AppInfo), [AppInfo], State).
%% this is a special case since it is used for project apps as well, not just deps
-make_vsn(AppInfo, VcsType, State) ->
+make_vsn(AppInfo, Vsn, State) ->
+ VcsType = case Vsn of {T, _} -> T; T -> T end,
Resources = rebar_state:resources(State),
case is_resource_type(VcsType, Resources) of
true ->
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index f1e440a..066c673 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -460,7 +460,7 @@ reread_config(ConfigList, Opts) ->
%% NB: we attempt to mimic -config here, which survives app reload,
%% hence {persistent, true}.
SetEnv = case version_tuple(?MODULE:otp_release()) of
- {X, _, _} when X =< 17 ->
+ {X, _, _} when X < 17 ->
fun application:set_env/3;
_ ->
fun (App, Key, Val) -> application:set_env(App, Key, Val, [{persistent, true}]) end
@@ -729,7 +729,7 @@ vcs_vsn(AppInfo, Vcs, State) ->
{plain, VsnString} ->
VsnString;
{cmd, CmdString} ->
- vcs_vsn_invoke(CmdString, rebar_app_info:dir(AppInfo));
+ cmd_vsn_invoke(CmdString, rebar_app_info:dir(AppInfo));
unknown ->
?ABORT("vcs_vsn: Unknown vsn format: ~p", [Vcs]);
{error, Reason} ->
@@ -743,8 +743,14 @@ vcs_vsn_cmd(AppInfo, VCS, State) when VCS =:= semver ; VCS =:= "semver" ->
vcs_vsn_cmd(AppInfo, git, State);
vcs_vsn_cmd(_AppInfo, {cmd, _Cmd}=Custom, _) ->
Custom;
+vcs_vsn_cmd(AppInfo, {file, File}, _) ->
+ Path = filename:join(rebar_app_info:dir(AppInfo), File),
+ {ok, Vsn} = file:read_file(Path),
+ {plain, to_list(rebar_string:trim(Vsn))};
vcs_vsn_cmd(AppInfo, VCS, State) when is_atom(VCS) ->
rebar_resource_v2:make_vsn(AppInfo, VCS, State);
+vcs_vsn_cmd(AppInfo, {VCS, _}=V, State) when is_atom(VCS) ->
+ rebar_resource_v2:make_vsn(AppInfo, V, State);
vcs_vsn_cmd(AppInfo, VCS, State) when is_list(VCS) ->
try list_to_existing_atom(VCS) of
AVCS ->
@@ -759,7 +765,7 @@ vcs_vsn_cmd(AppInfo, VCS, State) when is_list(VCS) ->
vcs_vsn_cmd(_, _, _) ->
unknown.
-vcs_vsn_invoke(Cmd, Dir) ->
+cmd_vsn_invoke(Cmd, Dir) ->
{ok, VsnString} = rebar_utils:sh(Cmd, [{cd, Dir}, {use_stdout, false}]),
rebar_string:trim(VsnString, trailing, "\n").
@@ -966,7 +972,7 @@ get_proxy_auth() ->
{ok, ProxyAuth} -> ProxyAuth
end.
--spec rebar_utils:is_list_of_strings(term()) -> boolean().
+-spec is_list_of_strings(term()) -> boolean().
is_list_of_strings(List) when not is_list(hd(List)) ->
false;
is_list_of_strings(List) when is_list(hd(List)) ->