collect-license-metadata: Print a diff of the expected output

Previously, `x test collect-license-metadata` gave the following message
on errors:
```
gathering license information from REUSE (this might take a minute...)
finished gathering the license information from REUSE in 78.69s
loading existing license information
The existing /home/runner/work/ferrocene/ferrocene/license-metadata.json
file is out of date.
Run ./x run collect-license-metadata to update it.
Error: The existing
/home/runner/work/ferrocene/ferrocene/license-metadata.json file doesn't
match what REUSE reports.
Bootstrap failed while executing `test collect-license-metadata`
```

Notable, this doesn't actually say what went wrong.
Print a diff in addition so it's more clear what broke:
```
...
                "license": {
                   "copyright": [
+                    "2010 The Rust Project Developers",
                     "2016, 2017, 2018, 2019, 2020, 2021 AXE Consultants. All Rights",
+                    "License. Subject to the terms and conditions of this",
                     "Notice",
-                    "The Ferrocene Developers"
+                    "The Ferrocene Developers",
+                    "[yyyy] [name of copyright owner]"
                   ],
...
```

Currently, this prints the entire text of the JSON file as context.
That's not ideal, but it's rare for this to fail, so I think it's ok for
now.

I considered using `assert_json_diff` instead of `similar`, but its
errors are a lot harder to read IMO, even though they are better at
omitting unnecessary context:

```
Diff: json atoms at path ".files.children[0].children[10].license.copyright[0]" are not equal:
    lhs:
        "2016 The Fuchsia Authors"
    rhs:
        "2019 The Crossbeam Project Developers"

json atoms at path ".files.children[0].children[10].license.spdx" are not equal:
    lhs:
        "BSD-2-Clause AND (Apache-2.0 OR MIT)"
    rhs:
        "Apache-2.0 OR MIT"

json atom at path ".files.children[0].children[10].children" is missing from lhs

json atoms at path ".files.children[0].children[10].name" are not equal:
    lhs:
        "library/std/src/sys/sync/mutex/fuchsia.rs"
    rhs:
        "library/std/src/sync/mpmc"
...
```
This commit is contained in:
Jynn Nelson 2025-10-06 11:56:08 -04:00
parent dc2c3564d2
commit bc930cd2d1
3 changed files with 16 additions and 0 deletions

View file

@ -686,6 +686,7 @@ dependencies = [
"anyhow",
"serde",
"serde_json",
"similar",
"spdx-rs",
]

View file

@ -9,4 +9,5 @@ license = "MIT OR Apache-2.0"
anyhow = "1.0.65"
serde = { version = "1.0.147", features = ["derive"] }
serde_json = "1.0.85"
similar = "2.7.0"
spdx-rs = "0.5.1"

View file

@ -5,9 +5,21 @@ mod reuse;
use std::path::PathBuf;
use anyhow::{Context, Error};
use similar::{ChangeTag, TextDiff};
use crate::licenses::LicensesInterner;
fn diff_text(expected: &str, actual: &str) {
for change in TextDiff::from_lines(expected, actual).iter_all_changes() {
let sign = match change.tag() {
ChangeTag::Delete => "-",
ChangeTag::Insert => "+",
ChangeTag::Equal => " ",
};
print!("{}{}", sign, change);
}
}
/// The entry point to the binary.
///
/// You should probably let `bootstrap` execute this program instead of running it directly.
@ -41,6 +53,8 @@ fn main() -> Result<(), Error> {
if existing_json != output {
eprintln!("The existing {} file is out of date.", dest.display());
eprintln!("Run ./x run collect-license-metadata to update it.");
eprintln!("Diff:");
diff_text(&existing, &serde_json::to_string_pretty(&output).unwrap());
anyhow::bail!("The existing {} file doesn't match what REUSE reports.", dest.display());
}
println!("license information matches");