diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 49d3a9664f9..c6d03ab3c9f 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -49,6 +49,8 @@ use crate::util::machine_message::Message; use crate::util::{self, machine_message, ProcessBuilder}; use crate::util::{internal, join_paths, paths, profile}; +const RUSTDOC_CRATE_VERSION_FLAG: &str = "--crate-version"; + /// A glorified callback for executing calls to rustc. Rather than calling rustc /// directly, we'll use an `Executor`, giving clients an opportunity to intercept /// the build calls. @@ -562,7 +564,6 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult let mut rustdoc = cx.compilation.rustdoc_process(unit.pkg, unit.target)?; rustdoc.inherit_jobserver(&cx.jobserver); rustdoc.arg("--crate-name").arg(&unit.target.crate_name()); - add_crate_versions_if_requested(bcx, unit, &mut rustdoc); add_path_args(bcx, unit, &mut rustdoc); add_cap_lints(bcx, unit, &mut rustdoc); @@ -593,6 +594,8 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult rustdoc.args(bcx.rustdocflags_args(unit)); + add_crate_versions_if_requested(bcx, unit, &mut rustdoc); + let name = unit.pkg.name().to_string(); let build_script_outputs = Arc::clone(&cx.build_script_outputs); let package_id = unit.pkg.package_id(); @@ -629,19 +632,31 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult })) } -fn add_crate_versions_if_requested( - bcx: &BuildContext<'_, '_>, - unit: &Unit<'_>, +fn add_crate_versions_if_requested<'a>( + bcx: &BuildContext<'a, '_>, + unit: &Unit<'a>, rustdoc: &mut ProcessBuilder, ) { - if !bcx.config.cli_unstable().crate_versions { - return; + if bcx.config.cli_unstable().crate_versions && !crate_version_flag_already_present(rustdoc) { + append_crate_version_flag(unit, rustdoc); } +} + +// The --crate-version flag could have already been passed in RUSTDOCFLAGS +// or as an extra compiler argument for rustdoc +fn crate_version_flag_already_present(rustdoc: &ProcessBuilder) -> bool { + rustdoc.get_args().iter().any(|flag| { + flag.to_str() + .map_or(false, |flag| flag.starts_with(RUSTDOC_CRATE_VERSION_FLAG)) + }) +} + +fn append_crate_version_flag(unit: &Unit<'_>, rustdoc: &mut ProcessBuilder) { rustdoc .arg("-Z") .arg("unstable-options") - .arg("--crate-version") - .arg(&unit.pkg.version().to_string()); + .arg(RUSTDOC_CRATE_VERSION_FLAG) + .arg(unit.pkg.version().to_string()); } // The path that we pass to rustc is actually fairly important because it will diff --git a/tests/testsuite/doc.rs b/tests/testsuite/doc.rs index 5ac3540a916..91b62a98d22 100644 --- a/tests/testsuite/doc.rs +++ b/tests/testsuite/doc.rs @@ -1534,12 +1534,50 @@ fn crate_versions() { .masquerade_as_nightly_cargo() .run(); - let doc_file = p.root().join("target/doc/foo/index.html"); - let mut doc_html = String::new(); - File::open(&doc_file) - .unwrap() - .read_to_string(&mut doc_html) - .unwrap(); + let output_path = p.root().join("target/doc/foo/index.html"); + let output_documentation = fs::read_to_string(&output_path).unwrap(); + + assert!(output_documentation.contains("Version 1.2.4")); +} + +#[cargo_test] +fn crate_versions_flag_is_overridden() { + // Testing unstable flag + if !is_nightly() { + return; + } + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.2.4" + authors = [] + "#, + ) + .file("src/lib.rs", "") + .build(); - assert!(doc_html.contains("Version 1.2.4")); + let output_documentation = || { + let output_path = p.root().join("target/doc/foo/index.html"); + fs::read_to_string(&output_path).unwrap() + }; + let asserts = |html: String| { + assert!(!html.contains("1.2.4")); + assert!(html.contains("Version 2.0.3")); + }; + + p.cargo("-Z crate-versions doc") + .masquerade_as_nightly_cargo() + .env("RUSTDOCFLAGS", "-Z unstable-options --crate-version 2.0.3") + .run(); + asserts(output_documentation()); + + p.build_dir().rm_rf(); + + p.cargo("-Z crate-versions rustdoc -- -Z unstable-options --crate-version 2.0.3") + .masquerade_as_nightly_cargo() + .run(); + asserts(output_documentation()); }