Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

166 рядки
5.9 KiB

10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
  1. -module(rebar_app_discover).
  2. -export([do/2,
  3. find_unbuilt_apps/1,
  4. find_apps/1,
  5. find_apps/2,
  6. find_app/2,
  7. validate_application_info/1]).
  8. do(State, LibDirs) ->
  9. BaseDir = rebar_state:dir(State),
  10. Dirs = [filename:join(BaseDir, LibDir) || LibDir <- LibDirs],
  11. Apps = find_apps(Dirs, all),
  12. ProjectDeps = rebar_state:deps_names(State),
  13. lists:foldl(fun(AppInfo, StateAcc) ->
  14. rebar_state:project_apps(StateAcc, rebar_app_info:deps(AppInfo, ProjectDeps))
  15. end, State, Apps).
  16. -spec all_app_dirs(list(file:name())) -> list(file:name()).
  17. all_app_dirs(LibDirs) ->
  18. lists:flatmap(fun(LibDir) ->
  19. app_dirs(LibDir)
  20. end, LibDirs).
  21. app_dirs(LibDir) ->
  22. Path1 = filename:join([LibDir,
  23. "*",
  24. "src",
  25. "*.app.src"]),
  26. Path2 = filename:join([LibDir,
  27. "src",
  28. "*.app.src"]),
  29. Path3 = filename:join([LibDir,
  30. "*",
  31. "ebin",
  32. "*.app"]),
  33. Path4 = filename:join([LibDir,
  34. "ebin",
  35. "*.app"]),
  36. lists:usort(lists:foldl(fun(Path, Acc) ->
  37. Files = filelib:wildcard(ec_cnv:to_list(Path)),
  38. [app_dir(File) || File <- Files] ++ Acc
  39. end, [], [Path1, Path2, Path3, Path4])).
  40. find_unbuilt_apps(LibDirs) ->
  41. find_apps(LibDirs, invalid).
  42. find_apps(LibDirs) ->
  43. find_apps(LibDirs, valid).
  44. find_apps(LibDirs, Validate) ->
  45. rebar_utils:filtermap(fun(AppDir) ->
  46. find_app(AppDir, Validate)
  47. end, all_app_dirs(LibDirs)).
  48. -spec find_app(list(), boolean()) -> rebar_app_info:t() | false.
  49. find_app(AppDir, Validate) ->
  50. AppFile = filelib:wildcard(filename:join([AppDir, "ebin", "*.app"])),
  51. AppSrcFile = filelib:wildcard(filename:join([AppDir, "src", "*.app.src"])),
  52. case AppFile of
  53. [File] ->
  54. AppInfo = create_app_info(AppDir, File),
  55. AppInfo1 = rebar_app_info:app_file(AppInfo, File),
  56. AppInfo2 = case AppSrcFile of
  57. [F] ->
  58. rebar_app_info:app_file_src(AppInfo1, F);
  59. [] ->
  60. AppInfo1
  61. end,
  62. case Validate of
  63. valid ->
  64. case validate_application_info(AppInfo2) of
  65. true ->
  66. {true, AppInfo2};
  67. false ->
  68. false
  69. end;
  70. invalid ->
  71. case validate_application_info(AppInfo2) of
  72. false ->
  73. {true, AppInfo2};
  74. true ->
  75. false
  76. end;
  77. all ->
  78. {true, AppInfo2}
  79. end;
  80. [] ->
  81. case AppSrcFile of
  82. [File] ->
  83. case Validate of
  84. V when V =:= invalid ; V =:= all ->
  85. AppInfo = create_app_info(AppDir, File),
  86. {true, rebar_app_info:app_file_src(AppInfo, File)};
  87. valid ->
  88. false
  89. end;
  90. [] ->
  91. false
  92. end
  93. end.
  94. app_dir(AppFile) ->
  95. filename:join(rebar_utils:droplast(filename:split(filename:dirname(AppFile)))).
  96. -spec create_app_info(file:name(), file:name()) -> rebar_app_info:t() | error.
  97. create_app_info(AppDir, AppFile) ->
  98. case file:consult(AppFile) of
  99. {ok, [{application, AppName, AppDetails}]} ->
  100. AppVsn = proplists:get_value(vsn, AppDetails),
  101. AbsCwd = filename:absname(rebar_utils:get_cwd()),
  102. {ok, AppInfo} = rebar_app_info:new(AppName, AppVsn, AppDir),
  103. RebarConfig = filename:join(AppDir, "rebar.config"),
  104. AppState = case filelib:is_file(RebarConfig) of
  105. true ->
  106. Terms = rebar_config:consult_file(RebarConfig),
  107. rebar_state:new(Terms);
  108. false ->
  109. rebar_state:new()
  110. end,
  111. AppState1 = rebar_state:set(AppState, base_dir, AbsCwd),
  112. AppInfo1 = rebar_app_info:config(
  113. rebar_app_info:app_details(AppInfo, AppDetails), AppState1),
  114. rebar_app_info:dir(AppInfo1, AppDir);
  115. _ ->
  116. error
  117. end.
  118. -spec validate_application_info(rebar_app_info:t()) -> boolean().
  119. validate_application_info(AppInfo) ->
  120. EbinDir = rebar_app_info:ebin_dir(AppInfo),
  121. AppFile = rebar_app_info:app_file(AppInfo),
  122. AppDetail = rebar_app_info:app_details(AppInfo),
  123. case get_modules_list(AppFile, AppDetail) of
  124. {ok, List} ->
  125. has_all_beams(EbinDir, List);
  126. _Error ->
  127. false
  128. end.
  129. -spec get_modules_list(file:name(), proplists:proplist()) ->
  130. {ok, list()} |
  131. {warning, Reason::term()} |
  132. {error, Reason::term()}.
  133. get_modules_list(AppFile, AppDetail) ->
  134. case proplists:get_value(modules, AppDetail) of
  135. undefined ->
  136. {warning, {invalid_app_file, AppFile}};
  137. ModulesList ->
  138. {ok, ModulesList}
  139. end.
  140. -spec has_all_beams(file:name(), list()) -> boolean().
  141. has_all_beams(EbinDir, [Module | ModuleList]) ->
  142. BeamFile = filename:join([EbinDir,
  143. ec_cnv:to_list(Module) ++ ".beam"]),
  144. case filelib:is_file(BeamFile) of
  145. true ->
  146. has_all_beams(EbinDir, ModuleList);
  147. false ->
  148. false
  149. end;
  150. has_all_beams(_, []) ->
  151. true.