aboutsummaryrefslogtreecommitdiffstats
path: root/src/rcl_prv_assembler.erl
diff options
context:
space:
mode:
authorEric B Merritt <[email protected]>2013-05-03 09:17:35 -0700
committerEric <[email protected]>2013-05-09 16:43:59 -0700
commit0d5a803a28010cc956948b614408b9d38997e9a1 (patch)
tree56f23e0b7158f2dc2f7d5fc8782bfb0c87c781e4 /src/rcl_prv_assembler.erl
parente68bbac546e084b4949dc01cbe88c03f6c667139 (diff)
downloadrelx-0d5a803a28010cc956948b614408b9d38997e9a1.tar.gz
relx-0d5a803a28010cc956948b614408b9d38997e9a1.tar.bz2
relx-0d5a803a28010cc956948b614408b9d38997e9a1.zip
support the creation or relups
Diffstat (limited to 'src/rcl_prv_assembler.erl')
-rw-r--r--src/rcl_prv_assembler.erl158
1 files changed, 135 insertions, 23 deletions
diff --git a/src/rcl_prv_assembler.erl b/src/rcl_prv_assembler.erl
index 204c8bd..aca783d 100644
--- a/src/rcl_prv_assembler.erl
+++ b/src/rcl_prv_assembler.erl
@@ -80,6 +80,20 @@ format_error({unable_to_create_output_dir, OutputDir}) ->
format_error({release_script_generation_error, Module, Errors}) ->
["Errors generating release \n",
rcl_util:indent(1), Module:format_error(Errors)];
+format_error({relup_generation_error, CurrentName, UpFromName}) ->
+ io_lib:format("Unknown internal release error generating the relup from ~s to ~s",
+ [UpFromName, CurrentName]);
+format_error({relup_generation_warning, Module, Warnings}) ->
+ ["Warnings generating relup \s",
+ rcl_util:indent(1), Module:format_warning(Warnings)];
+format_error({relup_script_generation_error,
+ {relupcript_generation_error, systools_relup,
+ {missing_sasl, _}}}) ->
+ "Unfortunately, due to requirements in systools, you need to have the sasl application "
+ "in both the current release and the release to upgrade from.";
+format_error({relup_script_generation_error, Module, Errors}) ->
+ ["Errors generating relup \n",
+ rcl_util:indent(1), Module:format_error(Errors)];
format_error({unable_to_make_symlink, AppDir, TargetDir, Reason}) ->
io_lib:format("Unable to symlink directory ~s to ~s because \n~s~s",
[AppDir, TargetDir, rcl_util:indent(1),
@@ -193,19 +207,17 @@ copy_dir(AppDir, TargetDir, SubDir) ->
ok
end.
-create_release_info(State, Release, OutputDir) ->
- RelName = erlang:atom_to_list(rcl_release:name(Release)),
- ReleaseDir = filename:join([OutputDir,
- "releases",
- RelName ++ "-" ++
- rcl_release:vsn(Release)]),
+create_release_info(State0, Release0, OutputDir) ->
+ RelName = erlang:atom_to_list(rcl_release:name(Release0)),
+ ReleaseDir = release_output_dir(State0, Release0),
ReleaseFile = filename:join([ReleaseDir, RelName ++ ".rel"]),
ok = ec_file:mkdir_p(ReleaseDir),
- case rcl_release:metadata(Release) of
+ Release1 = rcl_release:relfile(Release0, ReleaseFile),
State1 = rcl_state:update_realized_release(State0, Release1),
+ case rcl_release:metadata(Release1) of
{ok, Meta} ->
ok = ec_file:write_term(ReleaseFile, Meta),
- write_bin_file(State, Release, OutputDir, ReleaseDir);
+ write_bin_file(State1, Release1, OutputDir, ReleaseDir);
E ->
E
end.
@@ -216,7 +228,7 @@ write_bin_file(State, Release, OutputDir, RelDir) ->
RelVsn = rcl_release:vsn(Release),
BinDir = filename:join([OutputDir, "bin"]),
ok = ec_file:mkdir_p(BinDir),
- VsnRel = filename:join(BinDir, RelName ++ "-" ++ RelVsn),
+ VsnRel = filename:join(BinDir, rcl_release:canonical_name(Release)),
BareRel = filename:join(BinDir, RelName),
ErlOpts = rcl_state:get(State, erl_opts, ""),
StartFile = case rcl_state:get(State, extended_start_script, false) of
@@ -320,42 +332,142 @@ make_boot_script(State, Release, OutputDir, RelDir) ->
no_module_tests, silent],
Name = erlang:atom_to_list(rcl_release:name(Release)),
ReleaseFile = filename:join([RelDir, Name ++ ".rel"]),
- rcl_log:debug(rcl_state:log(State),
- "Creating script from release file ~s ~n with options ~p ~n",
- [ReleaseFile, Options]),
- case make_script(Name, Options) of
+ case make_script(Options,
+ fun(CorrectedOptions) ->
+ systools:make_script(Name, CorrectedOptions)
+ end) of
ok ->
rcl_log:error(rcl_state:log(State),
"release successfully created!"),
- {ok, State};
+ make_relup(State, Release);
error ->
?RCL_ERROR({release_script_generation_error, ReleaseFile});
{ok, _, []} ->
rcl_log:error(rcl_state:log(State),
"release successfully created!"),
- {ok, State};
+ make_relup(State, Release);
{ok,Module,Warnings} ->
?RCL_ERROR({release_script_generation_warn, Module, Warnings});
{error,Module,Error} ->
?RCL_ERROR({release_script_generation_error, Module, Error})
end.
--spec make_script(string(), [term()]) ->
- ok |
- error |
- {ok, module(), [term()]} |
- {error,module,[term()]}.
-make_script(Name, Options) ->
+-spec make_script([term()],
+ fun(([term()]) -> Res)) -> Res.
+make_script(Options, RunFun) ->
%% Erts 5.9 introduced a non backwards compatible option to
%% erlang this takes that into account
Erts = erlang:system_info(version),
case ec_semver:gte(Erts, "5.9") of
true ->
- systools:make_script(Name, [no_warn_sasl | Options]);
+ RunFun([no_warn_sasl | Options]);
+ _ ->
+ RunFun(Options)
+ end.
+
+make_relup(State, Release) ->
+ case rcl_state:action(State) of
+ relup ->
+ UpFrom =
+ case rcl_state:upfrom(State) of
+ undefined ->
+ get_last_release(State, Release);
+ Vsn ->
+ get_up_release(State, Release, Vsn)
+ end,
+ case UpFrom of
+ undefined ->
+ ?RCL_ERROR(no_upfrom_release_found);
+ _ ->
+ make_upfrom_script(State, Release, UpFrom)
+ end;
_ ->
- systools:make_script(Name, Options)
+ {ok, State}
end.
+make_upfrom_script(State, Release, UpFrom) ->
+ OutputDir = rcl_state:output_dir(State),
+ Options = [{outdir, OutputDir},
+ {path, get_code_paths(Release, OutputDir) ++
+ get_code_paths(UpFrom, OutputDir)},
+ silent],
+ CurrentRel = strip_rel(rcl_release:relfile(Release)),
+ UpFromRel = strip_rel(rcl_release:relfile(UpFrom)),
+ rcl_log:debug(rcl_state:log(State),
+ "systools:make_relup(~p, ~p, ~p, ~p)",
+ [CurrentRel, UpFromRel, UpFromRel, Options]),
+ case make_script(Options,
+ fun(CorrectOptions) ->
+ systools:make_relup(CurrentRel, [UpFromRel], [UpFromRel], CorrectOptions)
+ end) of
+ ok ->
+ rcl_log:error(rcl_state:log(State),
+ "relup from ~s to ~s successfully created!",
+ [UpFromRel, CurrentRel]),
+ {ok, State};
+ error ->
+ ?RCL_ERROR({relup_script_generation_error, CurrentRel, UpFromRel});
+ {ok, RelUp, _, []} ->
+ rcl_log:error(rcl_state:log(State),
+ "relup successfully created!"),
+ write_relup_file(State, Release, RelUp),
+ {ok, State};
+ {ok,_, Module,Warnings} ->
+ ?RCL_ERROR({relup_script_generation_warn, Module, Warnings});
+ {error,Module,Errors} ->
+ ?RCL_ERROR({relupcript_generation_error, Module, Errors})
+ end.
+
+write_relup_file(State, Release, Relup) ->
+ OutDir = release_output_dir(State, Release),
+ RelName = rcl_util:to_string(rcl_release:name(Release)),
+ RelupFile = filename:join(OutDir, RelName ++ ".relup"),
+ ok = ec_file:write_term(RelupFile, Relup).
+
+strip_rel(Name) ->
+ rcl_util:to_string(filename:join(filename:dirname(Name),
+ filename:basename(Name, ".rel"))).
+
+
+get_up_release(State, Release, Vsn) ->
+ Name = rcl_release:name(Release),
+ try
+ ec_dictionary:get({Name, Vsn}, rcl_state:realized_releases(State))
+ catch
+ throw:notfound ->
+ undefined
+ end.
+
+get_last_release(State, Release) ->
+ Releases0 = [Rel || {{_, _}, Rel} <- ec_dictionary:to_list(rcl_state:realized_releases(State))],
+ Releases1 = lists:sort(fun(R1, R2) ->
+ ec_semver:lte(rcl_release:vsn(R1),
+ rcl_release:vsn(R2))
+ end, Releases0),
+ Res = lists:foldl(fun(_Rel, R = {found, _}) ->
+ R;
+ (Rel, Prev) ->
+ case rcl_release:vsn(Rel) == rcl_release:vsn(Release) of
+ true ->
+ {found, Prev};
+ false ->
+ Rel
+ end
+ end, undefined, Releases1),
+ case Res of
+ {found, R} ->
+ R;
+ Else ->
+ Else
+ end.
+
+-spec release_output_dir(rcl_state:t(), rcl_release:t()) -> string().
+release_output_dir(State, Release) ->
+ OutputDir = rcl_state:output_dir(State),
+ filename:join([OutputDir,
+ "releases",
+ rcl_release:canonical_name(Release)]).
+
%% @doc Generates the correct set of code paths for the system.
-spec get_code_paths(rcl_release:t(), file:name()) -> [file:name()].
get_code_paths(Release, OutDir) ->