Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

328 rindas
15 KiB

pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
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
pirms 6 gadiem
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
pirms 6 gadiem
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
pirms 6 gadiem
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
pirms 6 gadiem
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
pirms 6 gadiem
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
pirms 6 gadiem
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
pirms 6 gadiem
  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_app_utils).
  28. -export([find/2,
  29. find/3,
  30. is_app_src/1,
  31. app_src_to_app/2,
  32. validate_application_info/1,
  33. validate_application_info/2,
  34. parse_deps/5,
  35. parse_deps/6,
  36. expand_deps_sources/2,
  37. dep_to_app/7,
  38. format_error/1]).
  39. -include("rebar.hrl").
  40. -include_lib("providers/include/providers.hrl").
  41. %% ===================================================================
  42. %% Public API
  43. %% ===================================================================
  44. %% @doc finds the proper app info record for a given app name in a list of
  45. %% such records.
  46. -spec find(binary(), [rebar_app_info:t()]) -> {ok, rebar_app_info:t()} | error.
  47. find(Name, Apps) ->
  48. ec_lists:find(fun(App) -> rebar_app_info:name(App) =:= Name end, Apps).
  49. %% @doc finds the proper app info record for a given app name at a given version
  50. %% in a list of such records.
  51. -spec find(binary(), binary(), [rebar_app_info:t()]) -> {ok, rebar_app_info:t()} | error.
  52. find(Name, Vsn, Apps) ->
  53. ec_lists:find(fun(App) ->
  54. rebar_app_info:name(App) =:= Name
  55. andalso rebar_app_info:original_vsn(App) =:= Vsn
  56. end, Apps).
  57. %% @doc checks if a given file is .app.src file
  58. is_app_src(Filename) ->
  59. %% If removing the extension .app.src yields a shorter name,
  60. %% this is an .app.src file.
  61. Filename =/= filename:rootname(Filename, ".app.src").
  62. %% @doc translates the name of the .app.src[.script] file to where
  63. %% its .app counterpart should be stored.
  64. -spec app_src_to_app(OutDir, SrcFilename) -> OutFilename when
  65. OutDir :: file:filename(),
  66. SrcFilename :: file:filename(),
  67. OutFilename :: file:filename().
  68. app_src_to_app(OutDir, Filename) ->
  69. AppFile =
  70. case lists:suffix(".app.src", Filename) of
  71. true ->
  72. filename:join([OutDir, "ebin", filename:basename(Filename, ".app.src") ++ ".app"]);
  73. false ->
  74. filename:join([OutDir, "ebin", filename:basename(Filename,
  75. ".app.src.script") ++ ".app"])
  76. end,
  77. filelib:ensure_dir(AppFile),
  78. AppFile.
  79. %% @doc checks whether the .app file has all the required data to be valid,
  80. %% and cross-references it with compiled modules on disk
  81. -spec validate_application_info(rebar_app_info:t()) -> boolean().
  82. validate_application_info(AppInfo) ->
  83. validate_application_info(AppInfo, rebar_app_info:app_details(AppInfo)).
  84. %% @doc checks whether the .app file has all the required data to be valid
  85. %% and cross-references it with compiled modules on disk.
  86. %% The app info is passed explicitly as a second argument.
  87. -spec validate_application_info(rebar_app_info:t(), list()) -> boolean().
  88. validate_application_info(AppInfo, AppDetail) ->
  89. EbinDir = rebar_app_info:ebin_dir(AppInfo),
  90. case rebar_app_info:app_file(AppInfo) of
  91. undefined ->
  92. false;
  93. AppFile ->
  94. case proplists:get_value(modules, AppDetail) of
  95. undefined ->
  96. ?PRV_ERROR({module_list, AppFile});
  97. List ->
  98. has_all_beams(EbinDir, List)
  99. end
  100. end.
  101. %% @doc parses all dependencies from the root of the project
  102. -spec parse_deps(Dir, Deps, State, Locks, Level) -> [rebar_app_info:t()] when
  103. Dir :: file:filename(),
  104. Deps :: [tuple() | atom() | binary()], % TODO: meta to source() | lock()
  105. State :: rebar_state:t(),
  106. Locks :: [tuple()], % TODO: meta to [lock()]
  107. Level :: non_neg_integer().
  108. parse_deps(DepsDir, Deps, State, Locks, Level) ->
  109. parse_deps(root, DepsDir, Deps, State, Locks, Level).
  110. %% @doc runs `parse_dep/6' for a set of dependencies.
  111. -spec parse_deps(Parent, Dir, Deps, State, Locks, Level) -> [rebar_app_info:t()] when
  112. Parent :: root | binary(),
  113. Dir :: file:filename(),
  114. Deps :: [tuple() | atom() | binary()], % TODO: meta to source() | lock()
  115. State :: rebar_state:t(),
  116. Locks :: [tuple()], % TODO: meta to [lock()]
  117. Level :: non_neg_integer().
  118. parse_deps(Parent, DepsDir, Deps, State, Locks, Level) ->
  119. [parse_dep(Dep, Parent, DepsDir, State, Locks, Level) || Dep <- Deps].
  120. %% @doc for a given dep, return its app info record. The function
  121. %% also has to choose whether to define the dep from its immediate spec
  122. %% (if it is a newer thing) or from the locks specified in the lockfile.
  123. -spec parse_dep(Dep, Parent, Dir, State, Locks, Level) -> rebar_app_info:t() when
  124. Dep :: tuple() | atom() | binary(), % TODO: meta to source() | lock()
  125. Parent :: root | binary(),
  126. Dir :: file:filename(),
  127. State :: rebar_state:t(),
  128. Locks :: [tuple()], % TODO: meta to [lock()]
  129. Level :: non_neg_integer().
  130. parse_dep(Dep, Parent, DepsDir, State, Locks, Level) ->
  131. Name = case Dep of
  132. Dep when is_tuple(Dep) ->
  133. element(1, Dep);
  134. Dep ->
  135. Dep
  136. end,
  137. case lists:keyfind(rebar_utils:to_binary(Name), 1, Locks) of
  138. false ->
  139. parse_dep(Parent, Dep, DepsDir, false, State);
  140. LockedDep ->
  141. LockedLevel = element(3, LockedDep),
  142. case LockedLevel > Level of
  143. true ->
  144. parse_dep(Parent, Dep, DepsDir, false, State);
  145. false ->
  146. parse_dep(Parent, LockedDep, DepsDir, true, State)
  147. end
  148. end.
  149. %% @doc converts a dependency definition and a location for it on disk
  150. %% into an app info tuple representing it.
  151. -spec parse_dep(Parent, Dep, Dir, IsLock, State) -> rebar_app_info:t() when
  152. Parent :: root | binary(),
  153. Dep :: tuple() | atom() | binary(), % TODO: meta to source() | lock()
  154. Dir :: file:filename(),
  155. IsLock :: boolean(),
  156. State :: rebar_state:t().
  157. parse_dep(Parent, {Name, Vsn, {pkg, PkgName}}, DepsDir, IsLock, State) ->
  158. {PkgName1, PkgVsn} = {rebar_utils:to_binary(PkgName),
  159. rebar_utils:to_binary(Vsn)},
  160. dep_to_app(Parent, DepsDir, Name, PkgVsn, {pkg, PkgName1, PkgVsn, undefined}, IsLock, State);
  161. parse_dep(Parent, {Name, {pkg, PkgName}}, DepsDir, IsLock, State) ->
  162. %% Package dependency with different package name from app name
  163. dep_to_app(Parent, DepsDir, Name, undefined, {pkg, rebar_utils:to_binary(PkgName), undefined, undefined}, IsLock, State);
  164. parse_dep(Parent, {Name, Vsn}, DepsDir, IsLock, State) when is_list(Vsn); is_binary(Vsn) ->
  165. %% Versioned Package dependency
  166. {PkgName, PkgVsn} = {rebar_utils:to_binary(Name),
  167. rebar_utils:to_binary(Vsn)},
  168. dep_to_app(Parent, DepsDir, PkgName, PkgVsn, {pkg, PkgName, PkgVsn, undefined}, IsLock, State);
  169. parse_dep(Parent, Name, DepsDir, IsLock, State) when is_atom(Name); is_binary(Name) ->
  170. %% Unversioned package dependency
  171. dep_to_app(Parent, DepsDir, rebar_utils:to_binary(Name), undefined, {pkg, rebar_utils:to_binary(Name), undefined, undefined}, IsLock, State);
  172. parse_dep(Parent, {Name, Source}, DepsDir, IsLock, State) when is_tuple(Source) ->
  173. dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
  174. parse_dep(Parent, {Name, _Vsn, Source}, DepsDir, IsLock, State) when is_tuple(Source) ->
  175. dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
  176. parse_dep(Parent, {Name, _Vsn, Source, Opts}, DepsDir, IsLock, State) when is_tuple(Source),
  177. is_list(Opts) ->
  178. ?WARN("Dependency option list ~p in ~p is not supported and will be ignored", [Opts, Name]),
  179. dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
  180. parse_dep(Parent, {Name, Source, Opts}, DepsDir, IsLock, State) when is_tuple(Source),
  181. is_list(Opts) ->
  182. ?WARN("Dependency option list ~p in ~p is not supported and will be ignored", [Opts, Name]),
  183. dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
  184. parse_dep(Parent, {Name, {pkg, PkgName, Vsn}, Level}, DepsDir, IsLock, State) when is_integer(Level) ->
  185. dep_to_app(Parent, DepsDir, Name, Vsn, {pkg, PkgName, Vsn, undefined}, IsLock, State);
  186. parse_dep(Parent, {Name, {pkg, PkgName, Vsn, Hash}, Level}, DepsDir, IsLock, State) when is_integer(Level) ->
  187. dep_to_app(Parent, DepsDir, Name, Vsn, {pkg, PkgName, Vsn, Hash}, IsLock, State);
  188. parse_dep(Parent, {Name, Source, Level}, DepsDir, IsLock, State) when is_tuple(Source)
  189. , is_integer(Level) ->
  190. dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
  191. parse_dep(_, Dep, _, _, _) ->
  192. throw(?PRV_ERROR({parse_dep, Dep})).
  193. %% @doc convert a dependency that has just been fetched into
  194. %% an app info record related to it
  195. -spec dep_to_app(Parent, Dir, Name, Vsn, Source, IsLock, State) -> rebar_app_info:t() when
  196. Parent :: root | binary(),
  197. Dir :: file:filename(),
  198. Name :: binary(),
  199. Vsn :: iodata() | undefined,
  200. Source :: tuple(),
  201. IsLock :: boolean(),
  202. State :: rebar_state:t().
  203. dep_to_app(Parent, DepsDir, Name, Vsn, Source, IsLock, State) ->
  204. CheckoutsDir = rebar_utils:to_list(rebar_dir:checkouts_dir(State, Name)),
  205. AppInfo = case rebar_app_info:discover(CheckoutsDir) of
  206. {ok, App} ->
  207. rebar_app_info:source(rebar_app_info:is_checkout(App, true), checkout);
  208. not_found ->
  209. Dir = rebar_utils:to_list(filename:join(DepsDir, Name)),
  210. {ok, AppInfo0} =
  211. case rebar_app_info:discover(Dir) of
  212. {ok, App} ->
  213. {ok, rebar_app_info:is_available(rebar_app_info:parent(App, Parent),
  214. true)};
  215. not_found ->
  216. rebar_app_info:new(Parent, Name, Vsn, Dir, [])
  217. end,
  218. rebar_app_info:source(AppInfo0, Source)
  219. end,
  220. Overrides = rebar_app_info:get(AppInfo, overrides, []) ++ rebar_state:get(State, overrides, []),
  221. AppInfo2 = rebar_app_info:set(AppInfo, overrides, Overrides),
  222. AppInfo5 = rebar_app_info:profiles(AppInfo2, [default]),
  223. rebar_app_info:is_lock(AppInfo5, IsLock).
  224. %% @doc Takes a given application app_info record along with the project.
  225. %% If the app is a package, resolve and expand the package definition.
  226. -spec expand_deps_sources(rebar_app_info:t(), rebar_state:t()) ->
  227. rebar_app_info:t().
  228. expand_deps_sources(Dep, State) ->
  229. update_source(Dep, rebar_app_info:source(Dep), State).
  230. %% @doc sets the source for a given dependency or app along with metadata
  231. %% around version if required.
  232. -spec update_source(rebar_app_info:t(), Source, rebar_state:t()) ->
  233. rebar_app_info:t() when
  234. Source :: rebar_resource_v2:source().
  235. update_source(AppInfo, {pkg, PkgName, PkgVsn, Hash}, State) ->
  236. case rebar_packages:resolve_version(PkgName, PkgVsn, Hash,
  237. ?PACKAGE_TABLE, State) of
  238. {ok, Package, RepoConfig} ->
  239. #package{key={_, PkgVsn1, _},
  240. checksum=Hash1,
  241. dependencies=Deps,
  242. retired=Retired} = Package,
  243. maybe_warn_retired(PkgName, PkgVsn1, Hash, Retired),
  244. PkgVsn2 = list_to_binary(lists:flatten(ec_semver:format(PkgVsn1))),
  245. AppInfo1 = rebar_app_info:source(AppInfo, {pkg, PkgName, PkgVsn2, Hash1, RepoConfig}),
  246. AppInfo2 = rebar_app_info:update_opts_deps(AppInfo1, Deps),
  247. rebar_app_info:original_vsn(AppInfo2, PkgVsn2);
  248. not_found ->
  249. throw(?PRV_ERROR({missing_package, PkgName, PkgVsn}));
  250. {error, {invalid_vsn, InvalidVsn}} ->
  251. throw(?PRV_ERROR({invalid_vsn, PkgName, InvalidVsn}))
  252. end;
  253. update_source(AppInfo, Source, _State) ->
  254. rebar_app_info:source(AppInfo, Source).
  255. %% @doc convert a given exception's payload into an io description.
  256. -spec format_error(any()) -> iolist().
  257. format_error({missing_package, Name, undefined}) ->
  258. io_lib:format("Package not found in any repo: ~ts", [rebar_utils:to_binary(Name)]);
  259. format_error({missing_package, Name, Constraint}) ->
  260. io_lib:format("Package not found in any repo: ~ts ~ts", [Name, Constraint]);
  261. format_error({parse_dep, Dep}) ->
  262. io_lib:format("Failed parsing dep ~p", [Dep]);
  263. format_error({invalid_vsn, Dep, InvalidVsn}) ->
  264. io_lib:format("Dep ~ts has invalid version ~ts", [Dep, InvalidVsn]);
  265. format_error(Error) ->
  266. io_lib:format("~p", [Error]).
  267. %% ===================================================================
  268. %% Internal functions
  269. %% ===================================================================
  270. maybe_warn_retired(_, _, _, false) ->
  271. ok;
  272. maybe_warn_retired(_, _, Hash, _) when is_binary(Hash) ->
  273. %% don't warn if this is a lock
  274. ok;
  275. maybe_warn_retired(Name, Vsn, _, R=#{reason := Reason}) ->
  276. Message = maps:get(message, R, ""),
  277. ?WARN("Warning: package ~s-~s is retired: (~s) ~s",
  278. [Name, ec_semver:format(Vsn), retire_reason(Reason), Message]);
  279. maybe_warn_retired(_, _, _, _) ->
  280. ok.
  281. %% TODO: move to hex_core
  282. retire_reason('RETIRED_OTHER') ->
  283. "other";
  284. retire_reason('RETIRED_INVALID') ->
  285. "invalid";
  286. retire_reason('RETIRED_SECURITY') ->
  287. "security";
  288. retire_reason('RETIRED_DEPRECATED') ->
  289. "deprecated";
  290. retire_reason('RETIRED_RENAMED') ->
  291. "renamed";
  292. retire_reason(_Other) ->
  293. "other".
  294. %% @private checks that all the beam files have been properly
  295. %% created.
  296. -spec has_all_beams(file:filename_all(), [module()]) ->
  297. true | ?PRV_ERROR({missing_module, module()}).
  298. has_all_beams(EbinDir, [Module | ModuleList]) ->
  299. BeamFile = filename:join([EbinDir, rebar_utils:to_list(Module) ++ ".beam"]),
  300. case filelib:is_file(BeamFile) of
  301. true ->
  302. has_all_beams(EbinDir, ModuleList);
  303. false ->
  304. ?PRV_ERROR({missing_module, Module})
  305. end;
  306. has_all_beams(_, []) ->
  307. true.