diff --git a/src/rebar3_ex_doc.erl b/src/rebar3_ex_doc.erl index ecae5a5..93cbc43 100644 --- a/src/rebar3_ex_doc.erl +++ b/src/rebar3_ex_doc.erl @@ -170,7 +170,10 @@ gen_chunks(State, App) -> ex_doc(State, App, EdocOutDir) -> AppName = rebar_utils:to_list(rebar_app_info:name(App)), {Opts, _Args} = rebar_state:command_parsed_args(State), - CommandStr = make_command_string(State, App, EdocOutDir, Opts), + % We replace output default ( "doc" ), with undefined here to keep decision logic for which output + % value to use later simple (i.e., output provided on CLI or in config). + Opts1 = lists:map(fun ({output, "doc"}) -> {output, undefined}; (Prop) -> Prop end, Opts), + CommandStr = make_command_string(State, App, EdocOutDir, Opts1), rebar_api:info("Running ex_doc for ~ts", [AppName]), case rebar_utils:sh(CommandStr, [{return_on_error, true}]) of {ok, []} -> @@ -204,10 +207,8 @@ make_command_string(State, App, EdocOutDir, Opts) -> SourceRefVer, "--config", ex_doc_config_file(App, EdocOutDir), - "--output", - output_dir(App, Opts), "--quiet" - ] ++ maybe_package_arg(PkgName, rebar_app_info:get(App, ex_doc, [])), + ] ++ maybe_add_output_dir(App, Opts) ++ maybe_package_arg(PkgName, rebar_app_info:get(App, ex_doc, [])), DepPaths = rebar_state:code_paths(State, all_deps), PathArgs = lists:foldl( fun(Path, Args) -> ["--paths", Path | Args] end, @@ -222,6 +223,16 @@ make_command_string(State, App, EdocOutDir, Opts) -> ), string:join(CommandArgs, " "). +maybe_add_output_dir(App, Opts) -> + case {proplists:get_value(output, Opts, undefined), get_exdoc_opt(App, output)} of + {undefined, undefined} -> + ["--output", output_dir(App, ?DEFAULT_DOC_DIR)]; + {OutputDir, _} when OutputDir =/= undefined -> + ["--output", output_dir(App, OutputDir)]; + {undefined, Specified} -> + ["--output", output_dir(App, Specified)] + end. + maybe_package_arg(PkgName, Opts) when Opts =:= [] orelse is_tuple(hd(Opts)) orelse is_atom(hd(Opts)) -> @@ -270,15 +281,30 @@ win32_ex_doc_script(Path) -> -spec ex_doc_config_file(rebar_app_info:t(), file:filename()) -> file:filename(). ex_doc_config_file(App, EdocOutDir) -> + case get_exdoc_opts(App) of + {config_file, FilePath} -> + FilePath; + Opts -> + ExDocOpts = to_ex_doc_format(Opts), + ExDocConfigFile = filename:join([EdocOutDir, "docs.config"]), + ok = write_config(ExDocConfigFile, ExDocOpts), + ExDocConfigFile + end. + +get_exdoc_opts(App) -> case rebar_app_info:get(App, ex_doc, []) of ExDocOpts0 when ExDocOpts0 =:= [] orelse is_tuple(hd(ExDocOpts0)) orelse is_atom(hd(ExDocOpts0)) -> - ExDocOpts1 = ex_doc_opts_defaults(ExDocOpts0), - ExDocOpts2 = to_ex_doc_format(ExDocOpts1), - ExDocConfigFile = filename:join([EdocOutDir, "docs.config"]), - ok = write_config(ExDocConfigFile, ExDocOpts2), - ExDocConfigFile; + ex_doc_opts_defaults(ExDocOpts0); ExDocConfigFile -> - ExDocConfigFile + {config_file, ExDocConfigFile} + end. + +get_exdoc_opt(App, OptName) -> + case get_exdoc_opts(App) of + {config_file, _} -> + undefined; + Opts -> + proplists:get_value(OptName, Opts, undefined) end. to_ex_doc_format(ExDocOpts) -> @@ -400,9 +426,8 @@ maybe_add_opt(logo, Opts) -> ["--logo", Logo] end. --spec output_dir(rebar_app_info:t(), proplists:proplist()) -> file:filename(). -output_dir(App, Opts) -> - Dir = proplists:get_value(output, Opts, ?DEFAULT_DOC_DIR), +-spec output_dir(any(), file:filename()) -> file:filename(). +output_dir(App, Dir) -> filename:join(rebar_app_info:dir(App), Dir). -spec write_config(file:filename(), proplists:proplist()) -> ok. diff --git a/test/rebar3_ex_doc_SUITE.erl b/test/rebar3_ex_doc_SUITE.erl index ac68ed3..369ca1f 100644 --- a/test/rebar3_ex_doc_SUITE.erl +++ b/test/rebar3_ex_doc_SUITE.erl @@ -11,6 +11,8 @@ all() -> generate_docs_with_current_app_set, generate_docs_with_bad_config, generate_docs_with_alternate_ex_doc, + generate_docs_with_output_set_in_config, + generate_docs_overriding_output_set_in_config, format_errors ]. @@ -43,7 +45,7 @@ generate_docs(Config) -> ok = make_readme(App), ok = make_license(App), {ok, _} = rebar3_ex_doc:do(State), - check_docs(App, StubConfig). + check_docs(App, State, StubConfig). generate_docs_alternate_rebar3_config_format(Config) -> StubConfig = #{ @@ -67,7 +69,7 @@ generate_docs_alternate_rebar3_config_format(Config) -> ok = make_readme(App), ok = make_license(App), {ok, _} = rebar3_ex_doc:do(State), - check_docs(App, StubConfig). + check_docs(App, State, StubConfig). generate_docs_with_alternate_ex_doc(Config) -> Priv = code:priv_dir(rebar3_ex_doc), @@ -93,7 +95,7 @@ generate_docs_with_alternate_ex_doc(Config) -> ok = make_readme(App), ok = make_license(App), {ok, _} = rebar3_ex_doc:do(State), - check_docs(App, StubConfig), + check_docs(App, State, StubConfig), StubConfig1 = #{ app_src => #{version => "0.1.0"}, @@ -130,7 +132,7 @@ generate_docs_with_current_app_set(Config) -> ok = make_readme(App), ok = make_license(App), {ok, _} = rebar3_ex_doc:do(State1), - check_docs(App, StubConfig). + check_docs(App, State, StubConfig). generate_docs_with_bad_config(Config) -> StubConfig = #{ @@ -149,6 +151,47 @@ generate_docs_with_bad_config(Config) -> ok = make_license(App), ?assertError({error, {rebar3_ex_doc, {ex_doc, _}}}, rebar3_ex_doc:do(State)). +generate_docs_with_output_set_in_config(Config) -> + StubConfig = #{ + app_src => #{version => "0.1.0"}, + dir => data_dir(Config), + name => "output_set_in_config_docs", + config => + {ex_doc, [ + {source_url, <<"https://github.com/eh/eh">>}, + {extras, [<<"README.md">>, <<"LICENSE">>]}, + {main, <<"readme">>}, + {output, "foo_docs"} + ]} + }, + {State, App} = make_stub(StubConfig), + + ok = make_readme(App), + ok = make_license(App), + {ok, _} = rebar3_ex_doc:do(State), + check_docs(App, State, StubConfig). + +generate_docs_overriding_output_set_in_config(Config) -> + StubConfig = #{ + app_src => #{version => "0.1.0"}, + dir => data_dir(Config), + args => "--output bar_docs", + name => "override_output_set_in_config_docs", + config => + {ex_doc, [ + {source_url, <<"https://github.com/eh/eh">>}, + {extras, [<<"README.md">>, <<"LICENSE">>]}, + {main, <<"readme">>}, + {output, "foo_docs"} + ]} + }, + {State, App} = make_stub(StubConfig), + + ok = make_readme(App), + ok = make_license(App), + {ok, _} = rebar3_ex_doc:do(State), + check_docs(App, State, StubConfig). + format_errors(_) -> Err = "The app 'foo' specified was not found.", ?assertEqual(Err, rebar3_ex_doc:format_error({app_not_found, foo})), @@ -170,16 +213,17 @@ format_errors(_) -> Err5 = "An unknown error has occurred. Run with DIAGNOSTICS=1 for more details.", ?assertEqual(Err5, rebar3_ex_doc:format_error({eh, some_error})). -check_docs(App, #{config := {ex_doc, DocConfig}} = _Stub) -> +check_docs(App, State, #{config := {ex_doc, DocConfig}} = _Stub) -> Extras = format_extras(proplists:get_value(extras, DocConfig)), AppDir = rebar_app_info:dir(App), BuildDir = filename:join(AppDir, "_build"), {ok, ConfigFile} = file:consult(filename:join([BuildDir, "default/lib/", rebar_app_info:name(App), "doc/docs.config"])), - ExpExtras = proplists:get_value(extras, ConfigFile), + ExpExtras = proplists:get_value(extras, ConfigFile), ?assertMatch(Extras, ExpExtras), AppName = rebar_app_info:name(App), AppNameStr = rebar_utils:to_list(AppName), - DocDir = filename:join(AppDir, "doc"), + {Opts, _Args} = rebar_state:command_parsed_args(State), + DocDir = filename:join(AppDir, get_doc_dir(Opts, DocConfig)), {ok, IndexDoc} = file:read_file(filename:join(DocDir, "index.html")), {ok, ModuleDoc} = file:read_file(filename:join(DocDir, AppNameStr ++ ".html")), {ok, ReadMeDoc} = file:read_file(filename:join(DocDir, "readme.html")), @@ -200,7 +244,15 @@ check_docs(App, #{config := {ex_doc, DocConfig}} = _Stub) -> re:run(EpubReadMe, "PLEASE READ ME", [{capture, [0], binary}]) ). -format_extras(Extras0) -> +get_doc_dir(Opts, DocConfig) -> + case proplists:get_value(output, Opts, proplists:get_value(output, DocConfig, "doc")) of + undefined -> + "doc"; + Doc -> + Doc + end. + +format_extras(Extras0) -> lists:foldr( fun ({Extra, ExtraOpts}, Extras) -> [{list_to_atom(Extra), format_extras_opts(ExtraOpts)} | Extras]; @@ -218,7 +270,7 @@ format_extras_opts(Extras) -> fun (filename, Filename) when is_list(Filename) -> list_to_binary(Filename); (title, Title) when is_list(Title) -> - list_to_binary(Title); + list_to_binary(Title); (_Key, Value) -> Value end,