diff --git a/priv/templates/install_upgrade_escript b/priv/templates/install_upgrade_escript index 0910c3871..a3e5dd39f 100644 --- a/priv/templates/install_upgrade_escript +++ b/priv/templates/install_upgrade_escript @@ -14,10 +14,18 @@ main(["unpack", RelName, NameTypeArg, NodeName, Cookie, VersionArg]) -> case proplists:get_value(Version, WhichReleases) of undefined -> %% not installed, so unpack tarball: - ?INFO("Release ~s not found, attempting to unpack releases/~s/~s.tar.gz~n",[Version,Version,RelName]), - ReleasePackage = Version ++ "/" ++ RelName, + %% look for a release package with the intended version in the following order: + %% releases/-.tar.gz + %% releases//-.tar.gz + %% releases//.tar.gz + ReleasePackage = find_and_link_release_package(Version, RelName), + ?INFO("Release ~s not found, attempting to unpack ~s~n", + [Version, ReleasePackage]), + %% regardless of the location of the release package, we'll + %% always give release handle the same thing which is the symlink + ReleasePackageLink = filename:join(Version, RelName), case rpc:call(TargetNode, release_handler, unpack_release, - [ReleasePackage], ?TIMEOUT) of + [ReleasePackageLink], ?TIMEOUT) of {ok, Vsn} -> ?INFO("Unpacked successfully: ~p~n", [Vsn]); {error, UnpackReason} -> @@ -42,16 +50,24 @@ main(["install", RelName, NameTypeArg, NodeName, Cookie, VersionArg]) -> case proplists:get_value(Version, WhichReleases) of undefined -> %% not installed, so unpack tarball: - ?INFO("Release ~s not found, attempting to unpack releases/~s/~s.tar.gz~n",[Version,Version,RelName]), - ReleasePackage = Version ++ "/" ++ RelName, + %% look for a release package with the intended version in the following order: + %% releases/-.tar.gz + %% releases//-.tar.gz + %% releases//.tar.gz + ReleasePackage = find_and_link_release_package(Version, RelName), + ?INFO("Release ~s not found, attempting to unpack ~s~n", + [Version, ReleasePackage]), + %% regardless of the location of the release package, we'll + %% always give release handle the same thing which is the symlink + ReleasePackageLink = filename:join(Version, RelName), case rpc:call(TargetNode, release_handler, unpack_release, - [ReleasePackage], ?TIMEOUT) of + [ReleasePackageLink], ?TIMEOUT) of {ok, Vsn} -> ?INFO("Unpacked successfully: ~p~n", [Vsn]), install_and_permafy(TargetNode, RelName, Vsn); {error, UnpackReason} -> - print_existing_versions(TargetNode), ?INFO("Unpack failed: ~p~n",[UnpackReason]), + print_existing_versions(TargetNode), erlang:halt(2) end; old -> @@ -70,6 +86,50 @@ main(["install", RelName, NameTypeArg, NodeName, Cookie, VersionArg]) -> main(_) -> erlang:halt(1). +%% look for a release package with the provided version in the following order: +%% releases/-.tar.gz +%% releases//-.tar.gz +%% releases//.tar.gz +find_and_link_release_package(Version, RelName) -> + %% this is the symlink name we'll create once + %% we've found where the actual release package is located + ReleaseLink = filename:join(["releases", Version, + RelName ++ ".tar.gz"]), + case first_value(fun filelib:is_file/1, + [filename:join(["releases", + RelName ++ "-" ++ Version ++ ".tar.gz"]), + filename:join(["releases", Version, + RelName ++ "-" ++ Version ++ ".tar.gz"]), + filename:join(["releases", Version, + RelName ++ ".tar.gz"])]) of + no_value -> + undefined; + %% no need to create the link since the release package we + %% found is located in the same place as the link would be + {ok, Filename} when is_list(Filename) andalso + Filename =:= ReleaseLink -> + Filename; + {ok, Filename} when is_list(Filename) -> + %% we now have the location of the release package, however + %% release handler expects a fixed nomenclature (.tar.gz) + %% so give it just that by creating a symlink to the tarball + %% we found. + %% make sure that the dir where we're creating the link exists + ok = filelib:ensure_dir(filename:join([filename:dirname(ReleaseLink), "dummy"])), + %% create the symlink pointing to the full path name + ok = file:make_symlink(filename:absname(Filename), ReleaseLink), + Filename + end. + +first_value(_Fun, []) -> no_value; +first_value(Fun, [Value | Rest]) -> + case Fun(Value) of + false -> + first_value(Fun, Rest); + true -> + {ok, Value} + end. + parse_version(V) when is_list(V) -> hd(string:tokens(V,"/")).