Skip to content

Commit b29d9d5

Browse files
committed
Use a crate to produce rustdoc tree comparisons instead of the diff command
It doesn't exist on Windows, so we bring our own unified diff implementation. Fixes #82409
1 parent 09db057 commit b29d9d5

File tree

3 files changed

+82
-13
lines changed

3 files changed

+82
-13
lines changed

Cargo.lock

+11
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ dependencies = [
676676
name = "compiletest"
677677
version = "0.0.0"
678678
dependencies = [
679+
"colored",
679680
"diff",
680681
"getopts",
681682
"glob",
@@ -688,6 +689,7 @@ dependencies = [
688689
"serde_json",
689690
"tracing",
690691
"tracing-subscriber",
692+
"unified-diff",
691693
"walkdir",
692694
"winapi 0.3.9",
693695
]
@@ -5517,6 +5519,15 @@ version = "0.1.1"
55175519
source = "registry+https://github.com/rust-lang/crates.io-index"
55185520
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
55195521

5522+
[[package]]
5523+
name = "unified-diff"
5524+
version = "0.2.1"
5525+
source = "registry+https://github.com/rust-lang/crates.io-index"
5526+
checksum = "496a3d395ed0c30f411ceace4a91f7d93b148fb5a9b383d5d4cff7850f048d5f"
5527+
dependencies = [
5528+
"diff",
5529+
]
5530+
55205531
[[package]]
55215532
name = "unstable-book-gen"
55225533
version = "0.1.0"

src/tools/compiletest/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ version = "0.0.0"
55
edition = "2018"
66

77
[dependencies]
8+
colored = "2"
89
diff = "0.1.10"
10+
unified-diff = "0.2.1"
911
getopts = "0.2"
1012
tracing = "0.1"
1113
tracing-subscriber = { version = "0.2.13", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }

src/tools/compiletest/src/runtest.rs

+69-13
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::header::TestProps;
1313
use crate::json;
1414
use crate::util::get_pointer_width;
1515
use crate::util::{logv, PathBufExt};
16+
use crate::ColorConfig;
1617
use regex::{Captures, Regex};
1718
use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
1819

@@ -2440,37 +2441,92 @@ impl<'test> TestCx<'test> {
24402441
}
24412442
})
24422443
};
2443-
let mut diff = Command::new("diff");
2444-
// diff recursively, showing context, and excluding .css files
2445-
diff.args(&["-u", "-r", "-x", "*.css"]).args(&[&compare_dir, out_dir]);
24462444

2447-
let output = if let Some(pager) = pager {
2448-
let diff_pid = diff.stdout(Stdio::piped()).spawn().expect("failed to run `diff`");
2445+
let diff_filename = format!("build/tmp/rustdoc-compare-{}.diff", std::process::id());
2446+
2447+
{
2448+
let mut diff_output = File::create(&diff_filename).unwrap();
2449+
for entry in walkdir::WalkDir::new(out_dir) {
2450+
let entry = entry.expect("failed to read file");
2451+
let extension = entry.path().extension().and_then(|p| p.to_str());
2452+
if entry.file_type().is_file()
2453+
&& (extension == Some("html".into()) || extension == Some("js".into()))
2454+
{
2455+
let expected_path =
2456+
compare_dir.join(entry.path().strip_prefix(&out_dir).unwrap());
2457+
let expected =
2458+
if let Ok(s) = std::fs::read(&expected_path) { s } else { continue };
2459+
let actual_path = entry.path();
2460+
let actual = std::fs::read(&actual_path).unwrap();
2461+
diff_output
2462+
.write_all(&unified_diff::diff(
2463+
&expected,
2464+
&expected_path.to_string_lossy(),
2465+
&actual,
2466+
&actual_path.to_string_lossy(),
2467+
3,
2468+
))
2469+
.unwrap();
2470+
}
2471+
}
2472+
}
2473+
2474+
match self.config.color {
2475+
ColorConfig::AlwaysColor => colored::control::set_override(true),
2476+
ColorConfig::NeverColor => colored::control::set_override(false),
2477+
_ => {}
2478+
}
2479+
2480+
if let Some(pager) = pager {
24492481
let pager = pager.trim();
24502482
if self.config.verbose {
24512483
eprintln!("using pager {}", pager);
24522484
}
24532485
let output = Command::new(pager)
24542486
// disable paging; we want this to be non-interactive
24552487
.env("PAGER", "")
2456-
.stdin(diff_pid.stdout.unwrap())
2488+
.stdin(File::open(&diff_filename).unwrap())
24572489
// Capture output and print it explicitly so it will in turn be
24582490
// captured by libtest.
24592491
.output()
24602492
.unwrap();
24612493
assert!(output.status.success());
2462-
output
2494+
println!("{}", String::from_utf8_lossy(&output.stdout));
2495+
eprintln!("{}", String::from_utf8_lossy(&output.stderr));
24632496
} else {
2464-
eprintln!("warning: no pager configured, falling back to `diff --color`");
2497+
use colored::Colorize;
2498+
eprintln!("warning: no pager configured, falling back to unified diff");
24652499
eprintln!(
24662500
"help: try configuring a git pager (e.g. `delta`) with `git config --global core.pager delta`"
24672501
);
2468-
let output = diff.arg("--color").output().unwrap();
2469-
assert!(output.status.success() || output.status.code() == Some(1));
2470-
output
2502+
let mut out = io::stdout();
2503+
let mut diff = BufReader::new(File::open(&diff_filename).unwrap());
2504+
let mut line = Vec::new();
2505+
loop {
2506+
line.truncate(0);
2507+
match diff.read_until(b'\n', &mut line) {
2508+
Ok(0) => break,
2509+
Ok(_) => {}
2510+
Err(e) => eprintln!("ERROR: {:?}", e),
2511+
}
2512+
match String::from_utf8(line.clone()) {
2513+
Ok(line) => {
2514+
if line.starts_with("+") {
2515+
write!(&mut out, "{}", line.green()).unwrap();
2516+
} else if line.starts_with("-") {
2517+
write!(&mut out, "{}", line.red()).unwrap();
2518+
} else if line.starts_with("@") {
2519+
write!(&mut out, "{}", line.blue()).unwrap();
2520+
} else {
2521+
out.write_all(line.as_bytes()).unwrap();
2522+
}
2523+
}
2524+
Err(_) => {
2525+
write!(&mut out, "{}", String::from_utf8_lossy(&line).reversed()).unwrap();
2526+
}
2527+
}
2528+
}
24712529
};
2472-
println!("{}", String::from_utf8_lossy(&output.stdout));
2473-
eprintln!("{}", String::from_utf8_lossy(&output.stderr));
24742530
}
24752531

24762532
fn run_rustdoc_json_test(&self) {

0 commit comments

Comments
 (0)