mirror of
https://github.com/rust-lang/cargo
synced 2024-10-14 03:32:39 +00:00
Check target-dependant doc folders
When checking the fingerprint for rustdoc and applying the corresponding logic, we don't only need to consider the `target/doc` folder (Host target) but also triple targets. So now the actual compilation targets are checked during the rustdoc_fingerprint processing and they're treated as the Host/doc folder.
This commit is contained in:
parent
d2572a2800
commit
7c45021328
|
@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
|
|||
use std::cell::RefCell;
|
||||
use std::collections::hash_map::{Entry, HashMap};
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::{self, FromStr};
|
||||
|
||||
/// Information about the platform target gleaned from querying rustc.
|
||||
|
@ -755,28 +755,20 @@ impl RustcTargetData {
|
|||
/// Structure used to deal with Rustdoc fingerprinting
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct RustDocFingerprint {
|
||||
rustc_vv: String,
|
||||
pub rustc_vv: String,
|
||||
}
|
||||
|
||||
impl RustDocFingerprint {
|
||||
/// Read the `RustDocFingerprint` info from the fingerprint file.
|
||||
fn read<'a, 'cfg>(cx: &Context<'a, 'cfg>) -> CargoResult<Self> {
|
||||
let rustdoc_data = paths::read(
|
||||
&cx.files()
|
||||
.host_root()
|
||||
.join(".rustdoc_fingerprint")
|
||||
.with_extension("json"),
|
||||
)?;
|
||||
let rustdoc_data = paths::read(&cx.files().host_root().join(".rustdoc_fingerprint.json"))?;
|
||||
serde_json::from_str(&rustdoc_data).map_err(|e| anyhow::anyhow!("{:?}", e))
|
||||
}
|
||||
|
||||
/// Write the `RustDocFingerprint` info into the fingerprint file.
|
||||
fn write<'a, 'cfg>(&self, cx: &Context<'a, 'cfg>) -> CargoResult<()> {
|
||||
paths::write(
|
||||
&cx.files()
|
||||
.host_root()
|
||||
.join(".rustdoc_fingerprint.json")
|
||||
.with_extension("json"),
|
||||
&cx.files().host_root().join(".rustdoc_fingerprint.json"),
|
||||
serde_json::to_string(&self)?.as_bytes(),
|
||||
)
|
||||
}
|
||||
|
@ -793,14 +785,28 @@ impl RustDocFingerprint {
|
|||
let actual_rustdoc_target_data = RustDocFingerprint {
|
||||
rustc_vv: cx.bcx.rustc().verbose_version.clone(),
|
||||
};
|
||||
let doc_dir = cx.files().host_root().join("doc");
|
||||
|
||||
// Collect all of the target doc paths for which the docs need to be compiled for.
|
||||
let doc_dirs: Vec<PathBuf> = cx
|
||||
.compilation
|
||||
.root_output
|
||||
.iter()
|
||||
.map(|(ck, _)| match ck {
|
||||
CompileKind::Host => cx.files().host_root().to_path_buf(),
|
||||
CompileKind::Target(t) => cx.files().host_root().join(Path::new(t.rustc_target())),
|
||||
})
|
||||
.map(|path| path.join("doc"))
|
||||
.collect();
|
||||
|
||||
// Check wether `.rustdoc_fingerprint.json` exists
|
||||
match Self::read(cx) {
|
||||
Ok(fingerprint) => {
|
||||
// Check if rustc_version matches the one we just used. Otherways,
|
||||
// remove the `doc` folder to trigger a re-compilation of the docs.
|
||||
if fingerprint.rustc_vv != actual_rustdoc_target_data.rustc_vv {
|
||||
paths::remove_dir_all(&doc_dir)?;
|
||||
doc_dirs
|
||||
.iter()
|
||||
.try_for_each(|path| paths::remove_dir_all(&path))?;
|
||||
actual_rustdoc_target_data.write(cx)?
|
||||
}
|
||||
}
|
||||
|
@ -810,7 +816,9 @@ impl RustDocFingerprint {
|
|||
// exists neither, we simply do nothing and continue.
|
||||
Err(_) => {
|
||||
// We don't care if this suceeds as explained above.
|
||||
let _ = paths::remove_dir_all(doc_dir);
|
||||
let _ = doc_dirs
|
||||
.iter()
|
||||
.try_for_each(|path| paths::remove_dir_all(&path));
|
||||
actual_rustdoc_target_data.write(cx)?
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//! Tests for the `cargo doc` command.
|
||||
|
||||
use cargo::core::compiler::RustDocFingerprint;
|
||||
use cargo_test_support::paths::CargoPathExt;
|
||||
use cargo_test_support::registry::Package;
|
||||
use cargo_test_support::{basic_lib_manifest, basic_manifest, git, project};
|
||||
use cargo_test_support::{is_nightly, rustc_host};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use std::str;
|
||||
|
||||
|
@ -1641,15 +1641,7 @@ fn crate_versions_flag_is_overridden() {
|
|||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn doc_fingerprint_versioning_consistent() {
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct RustDocFingerprint {
|
||||
rustc_vv: String,
|
||||
}
|
||||
|
||||
// Test that using different Rustc versions forces a
|
||||
// doc re-compilation producing new html, css & js files.
|
||||
|
||||
fn doc_fingerprint_is_versioning_consistent() {
|
||||
// Random rustc verbose version
|
||||
let old_rustc_verbose_version = format!(
|
||||
"\
|
||||
|
@ -1730,3 +1722,95 @@ LLVM version: 9.0
|
|||
(String::from_utf8_lossy(&output.stdout).as_ref())
|
||||
);
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn doc_fingerprint_respects_target_paths() {
|
||||
// Random rustc verbose version
|
||||
let old_rustc_verbose_version = format!(
|
||||
"\
|
||||
rustc 1.41.1 (f3e1a954d 2020-02-24)
|
||||
binary: rustc
|
||||
commit-hash: f3e1a954d2ead4e2fc197c7da7d71e6c61bad196
|
||||
commit-date: 2020-02-24
|
||||
host: {}
|
||||
release: 1.41.1
|
||||
LLVM version: 9.0
|
||||
",
|
||||
rustc_host()
|
||||
);
|
||||
|
||||
// Create the dummy project.
|
||||
let dummy_project = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
r#"
|
||||
[package]
|
||||
name = "foo"
|
||||
version = "1.2.4"
|
||||
authors = []
|
||||
"#,
|
||||
)
|
||||
.file("src/lib.rs", "//! These are the docs!")
|
||||
.build();
|
||||
|
||||
dummy_project
|
||||
.cargo("doc --target x86_64-unknown-linux-gnu")
|
||||
.run();
|
||||
|
||||
let fingerprint: RustDocFingerprint =
|
||||
serde_json::from_str(&dummy_project.read_file("target/.rustdoc_fingerprint.json"))
|
||||
.expect("JSON Serde fail");
|
||||
|
||||
// Check that the fingerprint contains the actual rustc version
|
||||
// which has been used to compile the docs.
|
||||
let output = std::process::Command::new("rustc")
|
||||
.arg("-vV")
|
||||
.output()
|
||||
.expect("Failed to get actual rustc verbose version");
|
||||
assert_eq!(
|
||||
fingerprint.rustc_vv,
|
||||
(String::from_utf8_lossy(&output.stdout).as_ref())
|
||||
);
|
||||
|
||||
// As the test shows above. Now we have generated the `doc/` folder and inside
|
||||
// the rustdoc fingerprint file is located with the correct rustc version.
|
||||
// So we will remove it and create a new fingerprint with an old rustc version
|
||||
// inside it. We will also place a bogus file inside of the `doc/` folder to ensure
|
||||
// it gets removed as we expect on the next doc compilation.
|
||||
dummy_project.change_file(
|
||||
"target/.rustdoc_fingerprint.json",
|
||||
&old_rustc_verbose_version,
|
||||
);
|
||||
|
||||
fs::write(
|
||||
dummy_project
|
||||
.build_dir()
|
||||
.join("x86_64-unknown-linux-gnu/doc/bogus_file"),
|
||||
String::from("This is a bogus file and should be removed!"),
|
||||
)
|
||||
.expect("Error writing test bogus file");
|
||||
|
||||
// Now if we trigger another compilation, since the fingerprint contains an old version
|
||||
// of rustc, cargo should remove the entire `/doc` folder (including the fingerprint)
|
||||
// and generating another one with the actual version.
|
||||
// It should also remove the bogus file we created above.
|
||||
dummy_project
|
||||
.cargo("doc --target x86_64-unknown-linux-gnu")
|
||||
.run();
|
||||
|
||||
assert!(!dummy_project
|
||||
.build_dir()
|
||||
.join("x86_64-unknown-linux-gnu/doc/bogus_file")
|
||||
.exists());
|
||||
|
||||
let fingerprint: RustDocFingerprint =
|
||||
serde_json::from_str(&dummy_project.read_file("target/.rustdoc_fingerprint.json"))
|
||||
.expect("JSON Serde fail");
|
||||
|
||||
// Check that the fingerprint contains the actual rustc version
|
||||
// which has been used to compile the docs.
|
||||
assert_eq!(
|
||||
fingerprint.rustc_vv,
|
||||
(String::from_utf8_lossy(&output.stdout).as_ref())
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue