Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

130 lignes
4.9 KiB

il y a 14 ans
il y a 14 ans
  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) 2010 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. %% @author Dave Smith <dizzyd@dizzyd.com>
  28. %% @doc rebar_edoc supports the following command:
  29. %% <ul>
  30. %% <li>doc (essentially erl -noshell -run edoc_run application
  31. %% "'$(&lt;app_name&gt;)'"
  32. %% '"."' '[&lt;options&gt;]')</li>
  33. %% </ul>
  34. %% EDoc options can be given in the <code>edoc_opts</code> option in
  35. %% <code>rebar.config</code>.
  36. %% @copyright 2010 Dave Smith
  37. %% -------------------------------------------------------------------
  38. -module(rebar_edoc).
  39. -export([doc/2]).
  40. %% for internal use only
  41. -export([info/2]).
  42. -include("rebar.hrl").
  43. %% ===================================================================
  44. %% Public API
  45. %% ===================================================================
  46. doc(Config, File) ->
  47. %% Save code path
  48. CodePath = setup_code_path(),
  49. %% Get the edoc_opts and app file info
  50. EDocOpts = rebar_config:get(Config, edoc_opts, []),
  51. {ok, Config1, AppName, _AppData} =
  52. rebar_app_utils:load_app_file(Config, File),
  53. case needs_regen(EDocOpts) of
  54. true ->
  55. ?INFO("Regenerating edocs for ~p\n", [AppName]),
  56. ok = edoc:application(AppName, ".", EDocOpts);
  57. false ->
  58. ?INFO("Skipping regeneration of edocs for ~p\n", [AppName]),
  59. ok
  60. end,
  61. %% Restore code path
  62. true = code:set_path(CodePath),
  63. {ok, Config1}.
  64. %% ===================================================================
  65. %% Internal functions
  66. %% ===================================================================
  67. info(help, doc) ->
  68. ?CONSOLE(
  69. "Generate Erlang program documentation.~n"
  70. "~n"
  71. "Valid rebar.config options:~n"
  72. " {edoc_opts, []} (see edoc:application/3 documentation)~n",
  73. []).
  74. setup_code_path() ->
  75. %% Setup code path prior to calling edoc so that edown, asciiedoc,
  76. %% and the like can work properly when generating their own
  77. %% documentation.
  78. CodePath = code:get_path(),
  79. true = code:add_patha(rebar_utils:ebin_dir()),
  80. CodePath.
  81. -type path_spec() :: {'file', file:filename()} | file:filename().
  82. -spec newer_file_exists(Paths::[path_spec()], OldFile::string()) -> boolean().
  83. newer_file_exists(Paths, OldFile) ->
  84. OldModTime = filelib:last_modified(OldFile),
  85. ThrowIfNewer = fun(Fn, _Acc) ->
  86. FModTime = filelib:last_modified(Fn),
  87. (FModTime > OldModTime) andalso
  88. throw({newer_file_exists, {Fn, FModTime}})
  89. end,
  90. try
  91. lists:foldl(fun({file, F}, _) ->
  92. ThrowIfNewer(F, false);
  93. (P, _) ->
  94. filelib:fold_files(P, ".*.erl", true,
  95. ThrowIfNewer, false)
  96. end, undefined, Paths)
  97. catch
  98. throw:{newer_file_exists, {Filename, FMod}} ->
  99. ?DEBUG("~p is more recent than ~p: "
  100. "~120p > ~120p\n",
  101. [Filename, OldFile, FMod, OldModTime]),
  102. true
  103. end.
  104. %% Needs regen if any dependent file is changed since the last
  105. %% edoc run. Dependent files are the erlang source files,
  106. %% and the overview file, if it exists.
  107. -spec needs_regen(proplists:proplist()) -> boolean().
  108. needs_regen(EDocOpts) ->
  109. DocDir = proplists:get_value(dir, EDocOpts, "doc"),
  110. EDocInfoName = filename:join(DocDir, "edoc-info"),
  111. OverviewFile = proplists:get_value(overview, EDocOpts, "overview.edoc"),
  112. EDocOverviewName = filename:join(DocDir, OverviewFile),
  113. SrcPaths = proplists:get_value(source_path, EDocOpts, ["src"]),
  114. newer_file_exists([{file, EDocOverviewName} | SrcPaths], EDocInfoName).