Skip to content

Commit bdb5046

Browse files
committed
refactor: move RustDocFingerprint to fingerprint mod
1 parent bd97934 commit bdb5046

File tree

5 files changed

+140
-120
lines changed

5 files changed

+140
-120
lines changed

src/cargo/core/compiler/build_context/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ use crate::util::logger::BuildLogger;
1313
use std::collections::{HashMap, HashSet};
1414

1515
mod target_info;
16-
pub use self::target_info::{
17-
FileFlavor, FileType, RustDocFingerprint, RustcTargetData, TargetInfo,
18-
};
16+
pub use self::target_info::FileFlavor;
17+
pub use self::target_info::FileType;
18+
pub use self::target_info::RustcTargetData;
19+
pub use self::target_info::TargetInfo;
1920

2021
/// The build context, containing complete information needed for a build task
2122
/// before it gets started.

src/cargo/core/compiler/build_context/target_info.rs

Lines changed: 9 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,24 @@
77
//! * [`RustcTargetData::info`] to get a [`TargetInfo`] for an in-depth query.
88
//! * [`TargetInfo::rustc_outputs`] to get a list of supported file types.
99
10+
use crate::core::compiler::CompileKind;
11+
use crate::core::compiler::CompileMode;
12+
use crate::core::compiler::CompileTarget;
13+
use crate::core::compiler::CrateType;
1014
use crate::core::compiler::apply_env_config;
11-
use crate::core::compiler::{BuildRunner, CompileKind, CompileMode, CompileTarget, CrateType};
1215
use crate::core::{Dependency, Package, Target, TargetKind, Workspace};
1316
use crate::util::context::{GlobalContext, StringList, TargetConfig};
1417
use crate::util::interning::InternedString;
1518
use crate::util::{CargoResult, Rustc};
19+
1620
use anyhow::Context as _;
1721
use cargo_platform::{Cfg, CfgExpr};
18-
use cargo_util::{ProcessBuilder, paths};
19-
use serde::{Deserialize, Serialize};
22+
use cargo_util::ProcessBuilder;
23+
use serde::Deserialize;
24+
2025
use std::cell::RefCell;
2126
use std::collections::hash_map::{Entry, HashMap};
22-
use std::path::{Path, PathBuf};
27+
use std::path::PathBuf;
2328
use std::rc::Rc;
2429
use std::str::{self, FromStr};
2530

@@ -1110,113 +1115,3 @@ impl<'gctx> RustcTargetData<'gctx> {
11101115
&self.requested_kinds
11111116
}
11121117
}
1113-
1114-
/// Structure used to deal with Rustdoc fingerprinting
1115-
#[derive(Debug, Serialize, Deserialize)]
1116-
pub struct RustDocFingerprint {
1117-
pub rustc_vv: String,
1118-
}
1119-
1120-
impl RustDocFingerprint {
1121-
/// This function checks whether the latest version of `Rustc` used to compile this
1122-
/// `Workspace`'s docs was the same as the one is currently being used in this `cargo doc`
1123-
/// call.
1124-
///
1125-
/// In case it's not, it takes care of removing the `doc/` folder as well as overwriting
1126-
/// the rustdoc fingerprint info in order to guarantee that we won't end up with mixed
1127-
/// versions of the `js/html/css` files that `rustdoc` autogenerates which do not have
1128-
/// any versioning.
1129-
pub fn check_rustdoc_fingerprint(build_runner: &BuildRunner<'_, '_>) -> CargoResult<()> {
1130-
if build_runner
1131-
.bcx
1132-
.gctx
1133-
.cli_unstable()
1134-
.skip_rustdoc_fingerprint
1135-
{
1136-
return Ok(());
1137-
}
1138-
let actual_rustdoc_target_data = RustDocFingerprint {
1139-
rustc_vv: build_runner.bcx.rustc().verbose_version.clone(),
1140-
};
1141-
1142-
let fingerprint_path = build_runner
1143-
.files()
1144-
.host_build_root()
1145-
.join(".rustdoc_fingerprint.json");
1146-
let write_fingerprint = || -> CargoResult<()> {
1147-
paths::write(
1148-
&fingerprint_path,
1149-
serde_json::to_string(&actual_rustdoc_target_data)?,
1150-
)
1151-
};
1152-
let Ok(rustdoc_data) = paths::read(&fingerprint_path) else {
1153-
// If the fingerprint does not exist, do not clear out the doc
1154-
// directories. Otherwise this ran into problems where projects
1155-
// like bootstrap were creating the doc directory before running
1156-
// `cargo doc` in a way that deleting it would break it.
1157-
return write_fingerprint();
1158-
};
1159-
match serde_json::from_str::<RustDocFingerprint>(&rustdoc_data) {
1160-
Ok(fingerprint) => {
1161-
if fingerprint.rustc_vv == actual_rustdoc_target_data.rustc_vv {
1162-
return Ok(());
1163-
} else {
1164-
tracing::debug!(
1165-
"doc fingerprint changed:\noriginal:\n{}\nnew:\n{}",
1166-
fingerprint.rustc_vv,
1167-
actual_rustdoc_target_data.rustc_vv
1168-
);
1169-
}
1170-
}
1171-
Err(e) => {
1172-
tracing::debug!("could not deserialize {:?}: {}", fingerprint_path, e);
1173-
}
1174-
};
1175-
// Fingerprint does not match, delete the doc directories and write a new fingerprint.
1176-
tracing::debug!(
1177-
"fingerprint {:?} mismatch, clearing doc directories",
1178-
fingerprint_path
1179-
);
1180-
build_runner
1181-
.bcx
1182-
.all_kinds
1183-
.iter()
1184-
.map(|kind| {
1185-
build_runner
1186-
.files()
1187-
.layout(*kind)
1188-
.artifact_dir()
1189-
.expect("artifact-dir was not locked")
1190-
.doc()
1191-
})
1192-
.filter(|path| path.exists())
1193-
.try_for_each(|path| clean_doc(path))?;
1194-
write_fingerprint()?;
1195-
return Ok(());
1196-
1197-
fn clean_doc(path: &Path) -> CargoResult<()> {
1198-
let entries = path
1199-
.read_dir()
1200-
.with_context(|| format!("failed to read directory `{}`", path.display()))?;
1201-
for entry in entries {
1202-
let entry = entry?;
1203-
// Don't remove hidden files. Rustdoc does not create them,
1204-
// but the user might have.
1205-
if entry
1206-
.file_name()
1207-
.to_str()
1208-
.map_or(false, |name| name.starts_with('.'))
1209-
{
1210-
continue;
1211-
}
1212-
let path = entry.path();
1213-
if entry.file_type()?.is_dir() {
1214-
paths::remove_dir_all(path)?;
1215-
} else {
1216-
paths::remove_file(path)?;
1217-
}
1218-
}
1219-
Ok(())
1220-
}
1221-
}
1222-
}

src/cargo/core/compiler/fingerprint/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@
371371
372372
mod dep_info;
373373
mod dirty_reason;
374+
mod rustdoc;
374375

375376
use std::collections::hash_map::{Entry, HashMap};
376377
use std::env;
@@ -409,6 +410,7 @@ pub use self::dep_info::parse_dep_info;
409410
pub use self::dep_info::parse_rustc_dep_info;
410411
pub use self::dep_info::translate_dep_info;
411412
pub use self::dirty_reason::DirtyReason;
413+
pub use self::rustdoc::RustDocFingerprint;
412414

413415
/// Determines if a [`Unit`] is up-to-date, and if not prepares necessary work to
414416
/// update the persisted fingerprint.
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
use std::path::Path;
2+
3+
use anyhow::Context as _;
4+
use cargo_util::paths;
5+
use serde::Deserialize;
6+
use serde::Serialize;
7+
8+
use crate::CargoResult;
9+
use crate::core::compiler::BuildRunner;
10+
11+
/// Structure used to deal with Rustdoc fingerprinting
12+
#[derive(Debug, Serialize, Deserialize)]
13+
pub struct RustDocFingerprint {
14+
pub rustc_vv: String,
15+
}
16+
17+
impl RustDocFingerprint {
18+
/// This function checks whether the latest version of `Rustc` used to compile this
19+
/// `Workspace`'s docs was the same as the one is currently being used in this `cargo doc`
20+
/// call.
21+
///
22+
/// In case it's not, it takes care of removing the `doc/` folder as well as overwriting
23+
/// the rustdoc fingerprint info in order to guarantee that we won't end up with mixed
24+
/// versions of the `js/html/css` files that `rustdoc` autogenerates which do not have
25+
/// any versioning.
26+
pub fn check_rustdoc_fingerprint(build_runner: &BuildRunner<'_, '_>) -> CargoResult<()> {
27+
if build_runner
28+
.bcx
29+
.gctx
30+
.cli_unstable()
31+
.skip_rustdoc_fingerprint
32+
{
33+
return Ok(());
34+
}
35+
let actual_rustdoc_target_data = RustDocFingerprint {
36+
rustc_vv: build_runner.bcx.rustc().verbose_version.clone(),
37+
};
38+
39+
let fingerprint_path = build_runner
40+
.files()
41+
.host_build_root()
42+
.join(".rustdoc_fingerprint.json");
43+
let write_fingerprint = || -> CargoResult<()> {
44+
paths::write(
45+
&fingerprint_path,
46+
serde_json::to_string(&actual_rustdoc_target_data)?,
47+
)
48+
};
49+
let Ok(rustdoc_data) = paths::read(&fingerprint_path) else {
50+
// If the fingerprint does not exist, do not clear out the doc
51+
// directories. Otherwise this ran into problems where projects
52+
// like bootstrap were creating the doc directory before running
53+
// `cargo doc` in a way that deleting it would break it.
54+
return write_fingerprint();
55+
};
56+
match serde_json::from_str::<RustDocFingerprint>(&rustdoc_data) {
57+
Ok(fingerprint) => {
58+
if fingerprint.rustc_vv == actual_rustdoc_target_data.rustc_vv {
59+
return Ok(());
60+
} else {
61+
tracing::debug!(
62+
"doc fingerprint changed:\noriginal:\n{}\nnew:\n{}",
63+
fingerprint.rustc_vv,
64+
actual_rustdoc_target_data.rustc_vv
65+
);
66+
}
67+
}
68+
Err(e) => {
69+
tracing::debug!("could not deserialize {:?}: {}", fingerprint_path, e);
70+
}
71+
};
72+
// Fingerprint does not match, delete the doc directories and write a new fingerprint.
73+
tracing::debug!(
74+
"fingerprint {:?} mismatch, clearing doc directories",
75+
fingerprint_path
76+
);
77+
build_runner
78+
.bcx
79+
.all_kinds
80+
.iter()
81+
.map(|kind| {
82+
build_runner
83+
.files()
84+
.layout(*kind)
85+
.artifact_dir()
86+
.expect("artifact-dir was not locked")
87+
.doc()
88+
})
89+
.filter(|path| path.exists())
90+
.try_for_each(|path| clean_doc(path))?;
91+
write_fingerprint()?;
92+
return Ok(());
93+
94+
fn clean_doc(path: &Path) -> CargoResult<()> {
95+
let entries = path
96+
.read_dir()
97+
.with_context(|| format!("failed to read directory `{}`", path.display()))?;
98+
for entry in entries {
99+
let entry = entry?;
100+
// Don't remove hidden files. Rustdoc does not create them,
101+
// but the user might have.
102+
if entry
103+
.file_name()
104+
.to_str()
105+
.map_or(false, |name| name.starts_with('.'))
106+
{
107+
continue;
108+
}
109+
let path = entry.path();
110+
if entry.file_type()?.is_dir() {
111+
paths::remove_dir_all(path)?;
112+
} else {
113+
paths::remove_file(path)?;
114+
}
115+
}
116+
Ok(())
117+
}
118+
}
119+
}

src/cargo/core/compiler/mod.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,19 @@ use tracing::{debug, instrument, trace};
7272

7373
pub use self::build_config::UserIntent;
7474
pub use self::build_config::{BuildConfig, CompileMode, MessageFormat, TimingOutput};
75-
pub use self::build_context::{
76-
BuildContext, FileFlavor, FileType, RustDocFingerprint, RustcTargetData, TargetInfo,
77-
};
75+
pub use self::build_context::BuildContext;
76+
pub use self::build_context::FileFlavor;
77+
pub use self::build_context::FileType;
78+
pub use self::build_context::RustcTargetData;
79+
pub use self::build_context::TargetInfo;
7880
pub use self::build_runner::{BuildRunner, Metadata, UnitHash};
7981
pub use self::compilation::{Compilation, Doctest, UnitOutput};
8082
pub use self::compile_kind::{CompileKind, CompileKindFallback, CompileTarget};
8183
pub use self::crate_type::CrateType;
8284
pub use self::custom_build::LinkArgTarget;
8385
pub use self::custom_build::{BuildOutput, BuildScriptOutputs, BuildScripts, LibraryPath};
8486
pub(crate) use self::fingerprint::DirtyReason;
87+
pub use self::fingerprint::RustDocFingerprint;
8588
pub use self::job_queue::Freshness;
8689
use self::job_queue::{Job, JobQueue, JobState, Work};
8790
pub(crate) use self::layout::Layout;

0 commit comments

Comments
 (0)