Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

239 rader
9.3 KiB

support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 år sedan
15 år sedan
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 år sedan
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 år sedan
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 år sedan
14 år sedan
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 år sedan
  1. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ts=4 sw=4 et
  3. %% -------------------------------------------------------------------
  4. %%
  5. %% rebar: Erlang Build Tools
  6. %%
  7. %% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com)
  8. %%
  9. %% Permission is hereby granted, free of charge, to any person obtaining a copy
  10. %% of this software and associated documentation files (the "Software"), to deal
  11. %% in the Software without restriction, including without limitation the rights
  12. %% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. %% copies of the Software, and to permit persons to whom the Software is
  14. %% furnished to do so, subject to the following conditions:
  15. %%
  16. %% The above copyright notice and this permission notice shall be included in
  17. %% all copies or substantial portions of the Software.
  18. %%
  19. %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. %% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. %% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. %% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. %% THE SOFTWARE.
  26. %% -------------------------------------------------------------------
  27. -module(rebar_otp_app).
  28. -export([compile/2,
  29. format_error/1]).
  30. -include("rebar.hrl").
  31. -include_lib("providers/include/providers.hrl").
  32. %% ===================================================================
  33. %% Public API
  34. %% ===================================================================
  35. compile(State, App) ->
  36. %% If we get an .app.src file, it needs to be pre-processed and
  37. %% written out as a ebin/*.app file. That resulting file will then
  38. %% be validated as usual.
  39. App1 = case rebar_app_info:app_file_src_script(App) of
  40. undefined ->
  41. case rebar_app_info:app_file_src(App) of
  42. undefined ->
  43. App;
  44. AppFileSrc ->
  45. File = preprocess(State, App, AppFileSrc),
  46. rebar_app_info:app_file(App, File)
  47. end;
  48. AppFileSrcScript ->
  49. File = preprocess(State, App, AppFileSrcScript),
  50. rebar_app_info:app_file(App, File)
  51. end,
  52. %% Load the app file and validate it.
  53. validate_app(State, App1).
  54. format_error({missing_app_file, Filename}) ->
  55. io_lib:format("App file is missing: ~ts", [Filename]);
  56. format_error({file_read, AppName, File, Reason}) ->
  57. io_lib:format("Failed to read required ~ts file for processing the application '~ts': ~ts",
  58. [File, AppName, file:format_error(Reason)]);
  59. format_error({invalid_name, File, AppName}) ->
  60. io_lib:format("Invalid ~ts: name of application (~p) must match filename.", [File, AppName]).
  61. %% ===================================================================
  62. %% Internal functions
  63. %% ===================================================================
  64. validate_app(State, App) ->
  65. AppFile = rebar_app_info:app_file(App),
  66. case consult_app_file(AppFile) of
  67. {ok, [{application, AppName, AppData}]} ->
  68. case validate_name(AppName, AppFile) of
  69. ok ->
  70. validate_app_modules(State, App, AppData);
  71. Error ->
  72. Error
  73. end;
  74. {error, Reason} ->
  75. ?PRV_ERROR({file_read, rebar_app_info:name(App), ".app", Reason})
  76. end.
  77. validate_app_modules(State, App, AppData) ->
  78. %% In general, the list of modules is an important thing to validate
  79. %% for compliance with OTP guidelines and upgrade procedures.
  80. %% However, some people prefer not to validate this list.
  81. AppVsn = proplists:get_value(vsn, AppData),
  82. case rebar_state:get(State, validate_app_modules, true) of
  83. true ->
  84. case rebar_app_utils:validate_application_info(App, AppData) of
  85. true ->
  86. {ok, rebar_app_info:original_vsn(App, AppVsn)};
  87. Error ->
  88. Error
  89. end;
  90. false ->
  91. {ok, rebar_app_info:original_vsn(App, AppVsn)}
  92. end.
  93. preprocess(State, AppInfo, AppSrcFile) ->
  94. case consult_app_file(AppSrcFile) of
  95. {ok, [{application, AppName, AppData}]} ->
  96. %% Look for a configuration file with vars we want to
  97. %% substitute. Note that we include the list of modules available in
  98. %% ebin/ and update the app data accordingly.
  99. OutDir = rebar_app_info:out_dir(AppInfo),
  100. AppVars = load_app_vars(State) ++ [{modules, ebin_modules(AppInfo, OutDir)}],
  101. A1 = apply_app_vars(AppVars, AppData),
  102. %% AppSrcFile may contain instructions for generating a vsn number
  103. Vsn = app_vsn(AppInfo, AppData, AppSrcFile, State),
  104. A2 = lists:keystore(vsn, 1, A1, {vsn, Vsn}),
  105. %% systools:make_relup/4 fails with {missing_param, registered}
  106. %% without a 'registered' value.
  107. A3 = ensure_registered(A2),
  108. %% some tools complain if a description is not present.
  109. A4 = ensure_description(A3),
  110. %% Build the final spec as a string
  111. Spec = io_lib:format("~p.\n", [{application, AppName, A4}]),
  112. %% Setup file .app filename and write new contents
  113. EbinDir = rebar_app_info:ebin_dir(AppInfo),
  114. rebar_file_utils:ensure_dir(EbinDir),
  115. AppFile = rebar_app_utils:app_src_to_app(OutDir, AppSrcFile),
  116. ok = rebar_file_utils:write_file_if_contents_differ(AppFile, Spec, utf8),
  117. AppFile;
  118. {error, Reason} ->
  119. throw(?PRV_ERROR({file_read, rebar_app_info:name(AppInfo), ".app.src", Reason}))
  120. end.
  121. load_app_vars(State) ->
  122. case rebar_state:get(State, app_vars_file, undefined) of
  123. undefined ->
  124. [];
  125. Filename ->
  126. ?INFO("Loading app vars from ~p", [Filename]),
  127. {ok, Vars} = file:consult(Filename),
  128. Vars
  129. end.
  130. apply_app_vars([], AppData) ->
  131. AppData;
  132. apply_app_vars([{Key, Value} | Rest], AppData) ->
  133. AppData2 = lists:keystore(Key, 1, AppData, {Key, Value}),
  134. apply_app_vars(Rest, AppData2).
  135. validate_name(AppName, File) ->
  136. %% Convert the .app file name to an atom -- check it against the
  137. %% identifier within the file
  138. ExpApp = list_to_atom(filename:basename(File, ".app")),
  139. case ExpApp == AppName of
  140. true ->
  141. ok;
  142. false ->
  143. ?PRV_ERROR({invalid_name, File, AppName})
  144. end.
  145. ebin_modules(AppInfo, Dir) ->
  146. Beams = lists:sort(rebar_utils:beams(filename:join(Dir, "ebin"))),
  147. ExtraDirs = extra_dirs(AppInfo),
  148. F = fun(Beam) -> not in_extra_dir(AppInfo, Beam, ExtraDirs) end,
  149. Filtered = lists:filter(F, Beams),
  150. [rebar_utils:beam_to_mod(N) || N <- Filtered].
  151. extra_dirs(State) ->
  152. Extras = rebar_dir:extra_src_dirs(rebar_app_info:opts(State)),
  153. SrcDirs = rebar_dir:src_dirs(rebar_app_info:opts(State), ["src"]),
  154. %% remove any dirs that are defined in `src_dirs` from `extra_src_dirs`
  155. Extras -- SrcDirs.
  156. in_extra_dir(AppInfo, Beam, Dirs) ->
  157. lists:any(fun(Dir) -> lists:prefix(filename:join([rebar_app_info:out_dir(AppInfo), Dir]),
  158. beam_src(Beam)) end,
  159. Dirs).
  160. beam_src(Beam) ->
  161. case beam_lib:chunks(Beam, [compile_info]) of
  162. {ok, {_mod, Chunks}} ->
  163. CompileInfo = proplists:get_value(compile_info, Chunks, []),
  164. proplists:get_value(source, CompileInfo, []);
  165. {error, beam_lib, Reason} ->
  166. ?WARN("Couldn't read debug info from ~p for reason: ~p", [Beam, Reason]),
  167. []
  168. end.
  169. ensure_registered(AppData) ->
  170. case lists:keyfind(registered, 1, AppData) of
  171. false ->
  172. [{registered, []} | AppData];
  173. {registered, _} ->
  174. %% We could further check whether the value is a list of atoms.
  175. AppData
  176. end.
  177. ensure_description(AppData) ->
  178. case lists:keyfind(description, 1, AppData) of
  179. false ->
  180. %% Required for releases to work.
  181. [{description, ""} | AppData];
  182. {description, _} ->
  183. AppData
  184. end.
  185. %% In the case of *.app.src we want to give the user the ability to
  186. %% dynamically script the application resource file (think dynamic version
  187. %% string, etc.), in a way similar to what can be done with the rebar
  188. %% config. However, in the case of *.app, rebar should not manipulate
  189. %% that file. This enforces that dichotomy between app and app.src.
  190. consult_app_file(Filename) ->
  191. case filelib:is_file(Filename) of
  192. false ->
  193. {error, enoent};
  194. true ->
  195. case lists:suffix(".app.src", Filename)
  196. orelse lists:suffix(".app.src.script", Filename) of
  197. false ->
  198. file:consult(Filename);
  199. true ->
  200. {ok, rebar_config:consult_app_file(Filename)}
  201. end
  202. end.
  203. app_vsn(AppInfo, AppData, AppFile, State) ->
  204. rebar_utils:vcs_vsn(AppInfo, get_value(vsn, AppData, AppFile), State).
  205. get_value(Key, AppInfo, AppFile) ->
  206. case proplists:get_value(Key, AppInfo) of
  207. undefined ->
  208. ?ABORT("Failed to get app value '~p' from '~ts'~n", [Key, AppFile]);
  209. Value ->
  210. Value
  211. end.