You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 regels
5.9 KiB

10 jaren geleden
10 jaren geleden
10 jaren geleden
10 jaren geleden
10 jaren geleden
10 jaren geleden
10 jaren geleden
10 jaren geleden
10 jaren geleden
  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.