aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/relx.app.src18
-rw-r--r--src/relx.erl3
-rw-r--r--src/rlx_cmd_args.erl13
-rw-r--r--src/rlx_config.erl38
-rw-r--r--src/rlx_depsolver.erl2
-rw-r--r--src/rlx_depsolver_culprit.erl2
-rw-r--r--src/rlx_prv_archive.erl3
-rw-r--r--src/rlx_prv_assembler.erl4
-rw-r--r--src/rlx_prv_overlay.erl21
-rw-r--r--src/rlx_string.erl10
-rw-r--r--src/rlx_util.erl120
11 files changed, 134 insertions, 100 deletions
diff --git a/src/relx.app.src b/src/relx.app.src
index c8915d5..c845982 100644
--- a/src/relx.app.src
+++ b/src/relx.app.src
@@ -1,11 +1,9 @@
{application,relx,
- [{description,"Release assembler for Erlang/OTP Releases"},
- {vsn,"git"},
- {modules,[]},
- {registered,[]},
- {applications,[kernel,stdlib,getopt,erlware_commons,bbmustache,
- providers]},
- {maintainers,["Eric Merritt","Tristan Sloughter",
- "Jordan Wilberding"]},
- {licenses,["Apache"]},
- {links,[{"Github","https://github.com/erlware/relx"}]}]}.
+ [{description,"Release assembler for Erlang/OTP Releases"},
+ {vsn,"git"},
+ {modules,[]},
+ {registered,[]},
+ {applications,[kernel,stdlib,getopt,erlware_commons,bbmustache,
+ providers]},
+ {licenses,["Apache"]},
+ {links,[{"Github","https://github.com/erlware/relx"}]}]}.
diff --git a/src/relx.erl b/src/relx.erl
index 8027fd4..b5c3ec5 100644
--- a/src/relx.erl
+++ b/src/relx.erl
@@ -214,7 +214,8 @@ opt_spec_list() ->
{sys_config, undefined, "sys_config", string, "Path to a file to use for sys.config"},
{system_libs, undefined, "system_libs", string, "Path to dir of Erlang system libs"},
{version, undefined, "version", undefined, "Print relx version"},
- {root_dir, $r, "root", string, "The project root directory"}].
+ {root_dir, $r, "root", string, "The project root directory"},
+ {provider, undefined, "provider", atom, "Specify an additional relx provider"}].
-spec format_error(Reason::term()) -> string().
format_error({invalid_return_value, Provider, Value}) ->
diff --git a/src/rlx_cmd_args.erl b/src/rlx_cmd_args.erl
index b20344c..4f5e9da 100644
--- a/src/rlx_cmd_args.erl
+++ b/src/rlx_cmd_args.erl
@@ -285,6 +285,19 @@ create(include_erts, Opts) ->
create(warnings_as_errors, Opts) ->
WarningsAsErrors = proplists:get_value(warnings_as_errors, Opts, false),
{warnings_as_errors, WarningsAsErrors};
+create(provider, Opts) ->
+ case proplists:get_all_values(provider, Opts) of
+ [] ->
+ [];
+ Providers ->
+ {add_providers, Providers}
+ end;
+create(add_providers, Opts) ->
+ Providers = proplists:get_value(add_providers, Opts, []),
+ {add_providers, Providers};
+create(providers, Opts) ->
+ Providers = proplists:get_value(providers, Opts, []),
+ {providers, Providers};
create(_, _) ->
[].
diff --git a/src/rlx_config.erl b/src/rlx_config.erl
index c67bf16..90cfe7c 100644
--- a/src/rlx_config.erl
+++ b/src/rlx_config.erl
@@ -333,8 +333,9 @@ list_of_overlay_vars_files(undefined) ->
[];
list_of_overlay_vars_files([]) ->
[];
-list_of_overlay_vars_files([H | _]=FileNames) when erlang:is_list(H) ->
- FileNames;
+list_of_overlay_vars_files([H | _]=Vars) when erlang:is_list(H) ;
+ is_tuple(H) ->
+ Vars;
list_of_overlay_vars_files(FileName) when is_list(FileName) ->
[FileName].
@@ -358,7 +359,8 @@ merge_configs([{Key, Value} | CliTerms], ConfigTerms) ->
end;
overlay_vars ->
case lists:keyfind(overlay_vars, 1, ConfigTerms) of
- {_, [H | _] = Vars} when is_list(H) ->
+ {_, [H | _] = Vars} when is_list(H) ;
+ is_tuple(H) ->
MergedValue = Vars ++ Value,
merge_configs(CliTerms, lists:keyreplace(overlay_vars, 1, ConfigTerms, {Key, MergedValue}));
{_, Vars} when is_list(Vars) ->
@@ -367,10 +369,23 @@ merge_configs([{Key, Value} | CliTerms], ConfigTerms) ->
false ->
merge_configs(CliTerms, ConfigTerms++[{Key, Value}])
end;
+ default_release when Value =:= {undefined, undefined} ->
+ %% No release specified in cli. Prevent overwriting default_release in ConfigTerms.
+ merge_configs(CliTerms, lists:keymerge(1, ConfigTerms, [{Key, Value}]));
_ ->
merge_configs(CliTerms, lists:reverse(lists:keystore(Key, 1, lists:reverse(ConfigTerms), {Key, Value})))
end.
+parse_vsn(Vsn) when Vsn =:= git ; Vsn =:= "git" ->
+ {ok, V} = ec_git_vsn:vsn(ec_git_vsn:new()),
+ V;
+parse_vsn({git, short}) ->
+ git_ref("--short");
+parse_vsn({git, long}) ->
+ git_ref("");
+parse_vsn({file, File}) ->
+ {ok, Vsn} = file:read_file(File),
+ binary_to_list(rlx_string:trim(Vsn, both, "\n"));
parse_vsn(Vsn) when Vsn =:= semver ; Vsn =:= "semver" ->
{ok, V} = ec_git_vsn:vsn(ec_git_vsn:new()),
V;
@@ -382,3 +397,20 @@ parse_vsn({cmd, Command}) ->
V;
parse_vsn(Vsn) ->
Vsn.
+
+git_ref(Arg) ->
+ case os:cmd("git rev-parse " ++ Arg ++ " HEAD") of
+ String ->
+ Vsn = rlx_string:trim(String, both, "\n"),
+ case length(Vsn) =:= 40 orelse length(Vsn) =:= 7 of
+ true ->
+ Vsn;
+ false ->
+ %% if the result isn't exactly either 40 or 7 characters then
+ %% it must have failed
+ {ok, Dir} = file:get_cwd(),
+ ec_cmd_log:warn("Getting ref of git repo failed in ~ts. "
+ "Falling back to version 0", [Dir]),
+ {plain, "0"}
+ end
+ end.
diff --git a/src/rlx_depsolver.erl b/src/rlx_depsolver.erl
index 88f2da4..0bde8c7 100644
--- a/src/rlx_depsolver.erl
+++ b/src/rlx_depsolver.erl
@@ -1,5 +1,5 @@
%% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*-
-%% ex: ts=4 sx=4 et
+%% ex: ts=4 sw=4 et
%%
%% Copyright 2012 Opscode, Inc. All Rights Reserved.
%%
diff --git a/src/rlx_depsolver_culprit.erl b/src/rlx_depsolver_culprit.erl
index cf6dcb2..6368d24 100644
--- a/src/rlx_depsolver_culprit.erl
+++ b/src/rlx_depsolver_culprit.erl
@@ -1,5 +1,5 @@
%% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*-
-%% ex: ts=4 sx=4 et
+%% ex: ts=4 sw=4 et
%%
%% @author Eric Merritt <[email protected]>
%%
diff --git a/src/rlx_prv_archive.erl b/src/rlx_prv_archive.erl
index e1735d1..8fd03c1 100644
--- a/src/rlx_prv_archive.erl
+++ b/src/rlx_prv_archive.erl
@@ -141,9 +141,10 @@ update_tar(State, TempDir, OutputDir, Name, Vsn, ErtsVersion) ->
config_files(Vsn, OutputDir) ->
VMArgs = {filename:join(["releases", Vsn, "vm.args"]), filename:join([OutputDir, "releases", Vsn, "vm.args"])},
+ VMArgsSrc = {filename:join(["releases", Vsn, "vm.args.src"]), filename:join([OutputDir, "releases", Vsn, "vm.args.src"])},
VMArgsOrig = {filename:join(["releases", Vsn, "vm.args.orig"]), filename:join([OutputDir, "releases", Vsn, "vm.args.orig"])},
SysConfigOrig = {filename:join(["releases", Vsn, "sys.config.orig"]), filename:join([OutputDir, "releases", Vsn, "sys.config.orig"])},
- [{NameInArchive, Filename} || {NameInArchive, Filename} <- [VMArgs, VMArgsOrig, SysConfigOrig], filelib:is_file(Filename)].
+ [{NameInArchive, Filename} || {NameInArchive, Filename} <- [VMArgsSrc, VMArgs, VMArgsOrig, SysConfigOrig], filelib:is_file(Filename)].
overlay_files(_, undefined, _) ->
diff --git a/src/rlx_prv_assembler.erl b/src/rlx_prv_assembler.erl
index cb5bbed..4f9a41e 100644
--- a/src/rlx_prv_assembler.erl
+++ b/src/rlx_prv_assembler.erl
@@ -433,13 +433,13 @@ write_bin_file(State, Release, OutputDir, RelDir) ->
win32 -> rlx_string:concat(VsnRel, ".cmd")
end,
ok = file:write_file(VsnRelStartFile, StartFile),
- ok = file:change_mode(VsnRelStartFile, 8#777),
+ ok = file:change_mode(VsnRelStartFile, 8#755),
BareRelStartFile = case OsFamily of
unix -> BareRel;
win32 -> rlx_string:concat(BareRel, ".cmd")
end,
ok = file:write_file(BareRelStartFile, StartFile),
- ok = file:change_mode(BareRelStartFile, 8#777)
+ ok = file:change_mode(BareRelStartFile, 8#755)
end,
ReleasesDir = filename:join(OutputDir, "releases"),
generate_start_erl_data_file(Release, ReleasesDir),
diff --git a/src/rlx_prv_overlay.erl b/src/rlx_prv_overlay.erl
index 645f691..516d238 100644
--- a/src/rlx_prv_overlay.erl
+++ b/src/rlx_prv_overlay.erl
@@ -145,7 +145,8 @@ get_overlay_vars_from_file(State, OverlayVars) ->
OverlayVars;
[] ->
OverlayVars;
- [H | _]=FileNames when is_list(H) ->
+ [H | _]=FileNames when is_list(H) ;
+ is_tuple(H) ->
read_overlay_vars(State, OverlayVars, FileNames);
FileName when is_list(FileName) ->
read_overlay_vars(State, OverlayVars, [FileName])
@@ -181,30 +182,24 @@ check_overlay_inclusion(_State, _RelativeRoot, [], Terms) ->
proplists:proplist().
merge_overlay_vars(State, FileNames) ->
RelativeRoot = get_relative_root(State),
- lists:foldl(fun(FileName, Acc) ->
- RelativePath = filename:join(RelativeRoot, erlang:iolist_to_binary(FileName)),
+ lists:foldl(fun(FileName, Acc) when is_list(FileName) ->
+ RelativePath = filename:join(RelativeRoot, iolist_to_binary(FileName)),
case file:consult(RelativePath) of
- %% {ok, [Terms]} ->
- %% lists:ukeymerge(1, lists:ukeysort(1, Terms), Acc);
- %% % the location of the included overlay files will be relative
- %% %% to the current one being read
- %% %% OverlayRelativeRoot = filename:dirname(FileName),
- %% %% NewTerms = check_overlay_inclusion(State, OverlayRelativeRoot, Terms),
-
- %% %% lists:ukeymerge(1, lists:ukeysort(1, NewTerms), Acc);
{ok, Terms} ->
%% the location of the included overlay files will be relative
%% to the current one being read
OverlayRelativeRoot = filename:dirname(FileName),
NewTerms = check_overlay_inclusion(State, OverlayRelativeRoot, Terms),
lists:foldl(fun(NewTerm, A) ->
- lists:keystore(element(1, NewTerm), 1, A, NewTerm)
+ lists:keystore(element(1, NewTerm), 1, A, NewTerm)
end, Acc, NewTerms);
{error, Reason} ->
ec_cmd_log:warn(rlx_state:log(State),
format_error({unable_to_read_varsfile, FileName, Reason})),
Acc
- end
+ end;
+ (Var, Acc) ->
+ lists:keystore(element(1, Var), 1, Acc, Var)
end, [], FileNames).
-spec render_overlay_vars(proplists:proplist(), proplists:proplist(),
diff --git a/src/rlx_string.erl b/src/rlx_string.erl
index 1f9cc0c..d5f5046 100644
--- a/src/rlx_string.erl
+++ b/src/rlx_string.erl
@@ -2,14 +2,22 @@
%% OTP-19 and OTP-21, where Unicode support means the deprecation
%% of a lot of string functions.
-module(rlx_string).
--export([concat/2, lexemes/2, join/2]).
+-export([concat/2, lexemes/2, join/2, trim/3]).
-ifdef(unicode_str).
concat(Str1, Str2) -> unicode:characters_to_list([Str1,Str2]).
lexemes(Str, Separators) -> string:lexemes(Str, Separators).
+trim(Str, Direction, Cluster=[_]) -> string:trim(Str, Direction, Cluster).
-else.
concat(Str1, Str2) -> string:concat(Str1, Str2).
lexemes(Str, Separators) -> string:tokens(Str, Separators).
+trim(Str, Direction, [Char]) ->
+ Dir = case Direction of
+ both -> both;
+ leading -> left;
+ trailing -> right
+ end,
+ string:strip(Str, Dir, Char).
-endif.
%% string:join/2 copy; string:join/2 is getting obsoleted
diff --git a/src/rlx_util.erl b/src/rlx_util.erl
index b3fc2b7..5d3744d 100644
--- a/src/rlx_util.erl
+++ b/src/rlx_util.erl
@@ -45,6 +45,8 @@
-define(DFLT_INTENSITY, high).
-define(ONE_LEVEL_INDENT, " ").
+
+-include_lib("kernel/include/file.hrl").
%%============================================================================
%% types
%%============================================================================
@@ -233,81 +235,65 @@ symlink_or_copy(Source, Target) ->
ok;
{error, eexist} ->
{error, eexist};
- {error, _} ->
- case os:type() of
- {win32, _} ->
- S = unicode:characters_to_list(Source),
- T = unicode:characters_to_list(Target),
- win32_symlink(filename:nativename(S), filename:nativename(T));
+ {error, Err} ->
+ case {os:type(), Err} of
+ {{win32, _}, eperm} ->
+ % We get eperm on Windows if we do not have
+ % SeCreateSymbolicLinkPrivilege
+ % Try the next alternative
+ win32_make_junction_or_copy(Source, Target);
_ ->
- case filelib:is_dir(Target) of
- true -> ok;
- false ->
- cp_r([Source], Target)
- end
+ % On other systems we try to copy next
+ cp_r(Source, Target)
end
end.
+cp_r(Source, Target) ->
+ ec_file:copy(Source, Target, [{recursive, true}, {fileinfo, [mode, time, owner, group]}]).
-win32_symlink(Source, Target) ->
- os:cmd("cmd /c mklink /j " ++ Target ++ " " ++ Source),
- ok.
-
--spec cp_r(list(string()), file:filename()) -> 'ok'.
-cp_r(Sources, Dest) ->
- case os:type() of
- {unix, _} ->
- ok;
- {win32, _} ->
- lists:foreach(fun(Src) -> ok = cp_r_win32(Src,Dest) end, Sources),
- ok
+win32_make_junction_or_copy(Source, Target) ->
+ case filelib:is_dir(Source) of
+ true ->
+ win32_make_junction(Source, Target);
+ _ ->
+ cp_r(Source, Target)
end.
-xcopy_win32(Source,Dest)->
- %% "xcopy \"~s\" \"~s\" /q /y /e 2> nul", Chanegd to robocopy to
- %% handle long names. May have issues with older windows.
- os:cmd("robocopy " ++ Source ++ " " ++ Dest ++ " /e /is"),
- ok.
-
-cp_r_win32({true, SourceDir}, {true, DestDir}) ->
- %% from directory to directory
- ok = case file:make_dir(DestDir) of
- {error, eexist} -> ok;
- Other -> Other
- end,
- ok = xcopy_win32(SourceDir, DestDir);
-cp_r_win32({false, Source} = S,{true, DestDir}) ->
- %% from file to directory
- cp_r_win32(S, {false, filename:join(DestDir, filename:basename(Source))});
-cp_r_win32({false, Source},{false, Dest}) ->
- %% from file to file
- {ok,_} = file:copy(Source, Dest),
- ok;
-cp_r_win32({true, SourceDir}, {false, DestDir}) ->
- case filelib:is_regular(DestDir) of
- true ->
- %% From directory to file? This shouldn't happen
- {error, lists:flatten(
- io_lib:format("Cannot copy dir (~p) to file (~p)\n",
- [SourceDir, DestDir]))};
- false ->
- %% Specifying a target directory that doesn't currently exist.
- %% So let's attempt to create this directory
- case filelib:ensure_dir(filename:join(DestDir, "dummy")) of
- ok ->
- ok = xcopy_win32(SourceDir, DestDir);
+win32_make_junction(Source, Target) ->
+ % The mklink will fail if the target already exists, check for that first
+ case file:read_link_info(Target) of
+ {error, enoent} ->
+ win32_make_junction_cmd(Source, Target);
+ {ok, #file_info{type = symlink}} ->
+ case file:read_link(Target) of
+ {ok, Source} ->
+ ok;
+ {ok, _} ->
+ ok = file:del_dir(Target),
+ win32_make_junction_cmd(Source, Target);
{error, Reason} ->
- {error, lists:flatten(
- io_lib:format("Unable to create dir ~p: ~p\n",
- [DestDir, Reason]))}
- end
- end;
-cp_r_win32(Source,Dest) ->
- Dst = {filelib:is_dir(Dest), Dest},
- lists:foreach(fun(Src) ->
- ok = cp_r_win32({filelib:is_dir(Src), Src}, Dst)
- end, filelib:wildcard(Source)),
- ok.
+ {error, {readlink, Reason}}
+ end;
+ {ok, #file_info{type = _Type}} ->
+ % Directory already exists, so we overwrite the copy
+ cp_r(Source, Target);
+ Error ->
+ Error
+ end.
+
+win32_make_junction_cmd(Source, Target) ->
+ S = unicode:characters_to_list(Source),
+ T = unicode:characters_to_list(Target),
+ Cmd = "cmd /c mklink /j " ++ filename:nativename(T) ++ " " ++ filename:nativename(S),
+ case os:cmd(Cmd) of
+ "Junction created " ++ _ ->
+ ok;
+ [] ->
+ % When mklink fails it prints the error message to stderr which
+ % is not picked up by os:cmd() hence this case switch is for
+ % an empty message
+ cp_r(Source, Target)
+ end.
%% @doc Returns the color intensity, we first check the application envorinment
%% if that is not set we check the environment variable RELX_COLOR.