Skip to content

Commit 0786642

Browse files
committed
rustdoc: clean up and further test mergeable CCI
This fixes a limitation that prevented me from adding it to Cargo. The rust compiler-docs bundle is built by running multiple `cargo` commands in succession, and I want to support that, so I'm stuck putting the doc parts all in one directory, so that subsequent `cargo` runs can pick up the previous runs' data. It's less clean, but it should still be usable in hermetic build environments if you give every crate its own directory (which you needed to do before, oddly enough).
1 parent 24be917 commit 0786642

File tree

7 files changed

+92
-17
lines changed

7 files changed

+92
-17
lines changed

src/librustdoc/config.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -975,15 +975,16 @@ fn parse_extern_html_roots(
975975
Ok(externs)
976976
}
977977

978-
/// Path directly to crate-info file.
978+
/// Path directly to crate-info directory.
979979
///
980-
/// For example, `/home/user/project/target/doc.parts/<crate>/crate-info`.
980+
/// For example, `/home/user/project/target/doc.parts`.
981+
/// Each crate has its info stored in a file called `CRATENAME.json`.
981982
#[derive(Clone, Debug)]
982983
pub(crate) struct PathToParts(pub(crate) PathBuf);
983984

984985
impl PathToParts {
985986
fn from_flag(path: String) -> Result<PathToParts, String> {
986-
let mut path = PathBuf::from(path);
987+
let path = PathBuf::from(path);
987988
// check here is for diagnostics
988989
if path.exists() && !path.is_dir() {
989990
Err(format!(
@@ -992,20 +993,22 @@ impl PathToParts {
992993
))
993994
} else {
994995
// if it doesn't exist, we'll create it. worry about that in write_shared
995-
path.push("crate-info");
996996
Ok(PathToParts(path))
997997
}
998998
}
999999
}
10001000

1001-
/// Reports error if --include-parts-dir / crate-info is not a file
1001+
/// Reports error if --include-parts-dir is not a directory
10021002
fn parse_include_parts_dir(m: &getopts::Matches) -> Result<Vec<PathToParts>, String> {
10031003
let mut ret = Vec::new();
10041004
for p in m.opt_strs("include-parts-dir") {
10051005
let p = PathToParts::from_flag(p)?;
10061006
// this is just for diagnostic
1007-
if !p.0.is_file() {
1008-
return Err(format!("--include-parts-dir expected {} to be a file", p.0.display()));
1007+
if !p.0.is_dir() {
1008+
return Err(format!(
1009+
"--include-parts-dir expected {} to be a directory",
1010+
p.0.display()
1011+
));
10091012
}
10101013
ret.push(p);
10111014
}

src/librustdoc/html/render/write_shared.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//! or contains "invocation-specific".
1515
1616
use std::cell::RefCell;
17-
use std::ffi::OsString;
17+
use std::ffi::{OsStr, OsString};
1818
use std::fs::File;
1919
use std::io::{self, Write as _};
2020
use std::iter::once;
@@ -83,9 +83,11 @@ pub(crate) fn write_shared(
8383
};
8484

8585
if let Some(parts_out_dir) = &opt.parts_out_dir {
86-
create_parents(&parts_out_dir.0)?;
86+
let mut parts_out_file = parts_out_dir.0.clone();
87+
parts_out_file.push(&format!("{crate_name}.json"));
88+
create_parents(&parts_out_file)?;
8789
try_err!(
88-
fs::write(&parts_out_dir.0, serde_json::to_string(&info).unwrap()),
90+
fs::write(&parts_out_file, serde_json::to_string(&info).unwrap()),
8991
&parts_out_dir.0
9092
);
9193
}
@@ -237,13 +239,25 @@ impl CrateInfo {
237239
pub(crate) fn read_many(parts_paths: &[PathToParts]) -> Result<Vec<Self>, Error> {
238240
parts_paths
239241
.iter()
240-
.map(|parts_path| {
241-
let path = &parts_path.0;
242-
let parts = try_err!(fs::read(path), &path);
243-
let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), &path);
244-
Ok::<_, Error>(parts)
242+
.fold(Ok(Vec::new()), |acc, parts_path| {
243+
let mut acc = acc?;
244+
let dir = &parts_path.0;
245+
acc.append(&mut try_err!(std::fs::read_dir(dir), dir.as_path())
246+
.filter_map(|file| {
247+
let to_crate_info = |file: Result<std::fs::DirEntry, std::io::Error>| -> Result<Option<CrateInfo>, Error> {
248+
let file = try_err!(file, dir.as_path());
249+
if file.path().extension() != Some(OsStr::new("json")) {
250+
return Ok(None);
251+
}
252+
let parts = try_err!(fs::read(file.path()), file.path());
253+
let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), file.path());
254+
Ok(Some(parts))
255+
};
256+
to_crate_info(file).transpose()
257+
})
258+
.collect::<Result<Vec<CrateInfo>, Error>>()?);
259+
Ok(acc)
245260
})
246-
.collect::<Result<Vec<CrateInfo>, Error>>()
247261
}
248262
}
249263

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//@ hasraw crates.js 'dep1'
2+
//@ hasraw search.index/name/*.js 'Dep1'
3+
//@ has dep1/index.html
4+
pub struct Dep1;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//@ hasraw crates.js 'dep1'
2+
//@ hasraw search.index/name/*.js 'Dep1'
3+
//@ has dep2/index.html
4+
pub struct Dep2;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//@ !hasraw crates.js 'dep_missing'
2+
//@ !hasraw search.index/name/*.js 'DepMissing'
3+
//@ has dep_missing/index.html
4+
pub struct DepMissing;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Running --merge=finalize without an input crate root should not trigger ICE.
2+
// Issue: https://github.com/rust-lang/rust/issues/146646
3+
4+
//@ needs-target-std
5+
6+
use run_make_support::{htmldocck, path, rustdoc};
7+
8+
fn main() {
9+
let out_dir = path("out");
10+
let merged_dir = path("merged");
11+
let parts_out_dir = path("parts");
12+
13+
rustdoc()
14+
.input("dep1.rs")
15+
.out_dir(&out_dir)
16+
.arg("-Zunstable-options")
17+
.arg(format!("--parts-out-dir={}", parts_out_dir.display()))
18+
.arg("--merge=none")
19+
.run();
20+
assert!(parts_out_dir.join("dep1.json").exists());
21+
22+
rustdoc()
23+
.input("dep2.rs")
24+
.out_dir(&out_dir)
25+
.arg("-Zunstable-options")
26+
.arg(format!("--parts-out-dir={}", parts_out_dir.display()))
27+
.arg("--merge=none")
28+
.run();
29+
assert!(parts_out_dir.join("dep2.json").exists());
30+
31+
// dep_missing is different, because --parts-out-dir is not supplied
32+
rustdoc().input("dep_missing.rs").out_dir(&out_dir).run();
33+
assert!(parts_out_dir.join("dep2.json").exists());
34+
35+
let output = rustdoc()
36+
.arg("-Zunstable-options")
37+
.out_dir(&out_dir)
38+
.arg(format!("--include-parts-dir={}", parts_out_dir.display()))
39+
.arg("--merge=finalize")
40+
.run();
41+
output.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug.");
42+
43+
htmldocck().arg(&out_dir).arg("dep1.rs").run();
44+
htmldocck().arg(&out_dir).arg("dep2.rs").run();
45+
htmldocck().arg(out_dir).arg("dep_missing.rs").run();
46+
}

tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fn main() {
1616
.arg(format!("--parts-out-dir={}", parts_out_dir.display()))
1717
.arg("--merge=none")
1818
.run();
19-
assert!(parts_out_dir.join("crate-info").exists());
19+
assert!(parts_out_dir.join("sierra.json").exists());
2020

2121
let output = rustdoc()
2222
.arg("-Zunstable-options")

0 commit comments

Comments
 (0)