Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

175 строки
6.1 KiB

  1. %% -------------------------------------------------------------------
  2. %%
  3. %% rebar: Erlang Build Tools
  4. %%
  5. %% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com)
  6. %%
  7. %% Permission is hereby granted, free of charge, to any person obtaining a copy
  8. %% of this software and associated documentation files (the "Software"), to deal
  9. %% in the Software without restriction, including without limitation the rights
  10. %% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. %% copies of the Software, and to permit persons to whom the Software is
  12. %% furnished to do so, subject to the following conditions:
  13. %%
  14. %% The above copyright notice and this permission notice shall be included in
  15. %% all copies or substantial portions of the Software.
  16. %%
  17. %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. %% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. %% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. %% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. %% THE SOFTWARE.
  24. %% -------------------------------------------------------------------
  25. -module(rebar_reltool).
  26. -export([generate/2,
  27. clean/2]).
  28. -include("rebar.hrl").
  29. -include_lib("reltool/src/reltool.hrl").
  30. %% ===================================================================
  31. %% Public API
  32. %% ===================================================================
  33. generate(Config, ReltoolFile) ->
  34. %% Load the reltool configuration from the file
  35. ReltoolConfig = load_config(ReltoolFile),
  36. %% Spin up reltool server and load our config into it
  37. {ok, Server} = reltool:start_server([{sys, ReltoolConfig}]),
  38. %% Do some validation of the reltool configuration; error messages out of
  39. %% reltool are still pretty cryptic
  40. validate_rel_apps(Server, ReltoolConfig),
  41. %% Finally, run reltool
  42. case catch(run_reltool(Config, ReltoolConfig)) of
  43. ok ->
  44. ok;
  45. {error, failed} ->
  46. ?FAIL;
  47. Other2 ->
  48. ?ERROR("Unexpected error: ~p\n", [Other2]),
  49. ?FAIL
  50. end.
  51. clean(Config, ReltoolFile) ->
  52. ReltoolConfig = load_config(ReltoolFile),
  53. TargetDir = target_dir(Config, ReltoolConfig),
  54. rebar_file_utils:rm_rf(TargetDir),
  55. rebar_file_utils:delete_each(["reltool.spec"]).
  56. %% ===================================================================
  57. %% Internal functions
  58. %% ===================================================================
  59. load_config(ReltoolFile) ->
  60. %% Load the reltool configuration from the file
  61. case file:consult(ReltoolFile) of
  62. {ok, [{sys, ReltoolConfig}]} ->
  63. ReltoolConfig;
  64. Other ->
  65. ?ERROR("Failed to load expected config from ~s: ~p\n", [ReltoolFile, Other]),
  66. ?FAIL
  67. end.
  68. %%
  69. %% Determine the name of the target directory; try the user provided name
  70. %% first, or fall back to the release name if that's available. If neither
  71. %% is available, just use "target"
  72. %%
  73. target_dir(Config, ReltoolConfig) ->
  74. case rebar_config:get(Config, target_name, undefined) of
  75. undefined ->
  76. case lists:keysearch(rel, 1, ReltoolConfig) of
  77. {value, {rel, Name, _Vsn, _Apps}} ->
  78. Name;
  79. false ->
  80. "target"
  81. end;
  82. Name ->
  83. Name
  84. end.
  85. validate_rel_apps(ReltoolServer, ReltoolConfig) ->
  86. case lists:keysearch(rel, 1, ReltoolConfig) of
  87. {value, {rel, _Name, _Vsn, Apps}} ->
  88. %% Identify all the apps that do NOT exist, based on what's available
  89. %% from the reltool server
  90. Missing = lists:sort([App || App <- Apps,
  91. app_exists(App, ReltoolServer) == false]),
  92. case Missing of
  93. [] ->
  94. ok;
  95. _ ->
  96. ?ERROR("Apps in {rel, ...} section not found by reltool: ~p\n", [Missing]),
  97. ?FAIL
  98. end;
  99. {value, Rel} ->
  100. %% Invalid release format!
  101. ?ERROR("Invalid {rel, ...} section in reltools.config: ~p\n", [Rel]),
  102. ?FAIL;
  103. false ->
  104. ok
  105. end.
  106. app_exists(App, Server) when is_atom(App) ->
  107. case reltool_server:get_app(Server, App) of
  108. {ok, _} ->
  109. true;
  110. _ ->
  111. false
  112. end;
  113. app_exists(AppTuple, Server) when is_tuple(AppTuple) ->
  114. app_exists(element(1, AppTuple), Server).
  115. run_reltool(Config, ReltoolConfig) ->
  116. {ok, Server} = reltool:start_server([{sys, ReltoolConfig}]),
  117. case reltool:get_target_spec(Server) of
  118. {ok, Spec} ->
  119. dump_spec(Spec),
  120. TargetDir = target_dir(Config, ReltoolConfig),
  121. case file:make_dir(TargetDir) of
  122. ok ->
  123. ok;
  124. {error, eexist} ->
  125. %% Output directory already exists; if force=1, wipe it out
  126. case rebar_config:get_global(force, "0") of
  127. "1" ->
  128. rebar_file_utils:rm_rf(TargetDir),
  129. ok = file:make_dir(TargetDir);
  130. _ ->
  131. ?ERROR("Release target directory ~p already exists!\n", [TargetDir]),
  132. ?FAIL
  133. end
  134. end,
  135. case reltool:eval_target_spec(Spec, code:root_dir(), TargetDir) of
  136. ok ->
  137. ok;
  138. {error, Reason} ->
  139. ?ERROR("Failed to generate target from spec: ~p\n", [Reason]),
  140. ?FAIL
  141. end;
  142. {error, Reason} ->
  143. ?ERROR("Unable to generate spec: ~s\n", [Reason]),
  144. ?FAIL
  145. end.
  146. dump_spec(Spec) ->
  147. case rebar_config:get_global(dump_spec, "0") of
  148. "1" ->
  149. SpecBin = list_to_binary(io_lib:print(Spec, 1, 120, -1)),
  150. ok = file:write_file("reltool.spec", SpecBin);
  151. _ ->
  152. ok
  153. end.