Skip to content

Commit 13efb20

Browse files
committed
add tool to collect license metadata from REUSE
1 parent 17ee25d commit 13efb20

File tree

10 files changed

+522
-0
lines changed

10 files changed

+522
-0
lines changed

Cargo.lock

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ dependencies = [
563563
"libc",
564564
"num-integer",
565565
"num-traits",
566+
"serde",
566567
"time",
567568
"winapi",
568569
]
@@ -712,6 +713,16 @@ dependencies = [
712713
"rustc-semver",
713714
]
714715

716+
[[package]]
717+
name = "collect-license-metadata"
718+
version = "0.1.0"
719+
dependencies = [
720+
"anyhow",
721+
"serde",
722+
"serde_json",
723+
"spdx-rs",
724+
]
725+
715726
[[package]]
716727
name = "color-eyre"
717728
version = "0.6.2"
@@ -4628,6 +4639,35 @@ dependencies = [
46284639
"winapi",
46294640
]
46304641

4642+
[[package]]
4643+
name = "spdx-expression"
4644+
version = "0.5.2"
4645+
source = "registry+https://github.com/rust-lang/crates.io-index"
4646+
checksum = "53d7ac03c67c572d85049d6db815e20a4a19b41b3d5cca732ac582342021ad77"
4647+
dependencies = [
4648+
"nom",
4649+
"serde",
4650+
"thiserror",
4651+
"tracing",
4652+
]
4653+
4654+
[[package]]
4655+
name = "spdx-rs"
4656+
version = "0.5.1"
4657+
source = "registry+https://github.com/rust-lang/crates.io-index"
4658+
checksum = "b3c02f6eb7e7b4100c272f685a9ccaccaab302324e8c7ec3e2ee72340fb29ff3"
4659+
dependencies = [
4660+
"chrono",
4661+
"log",
4662+
"nom",
4663+
"serde",
4664+
"spdx-expression",
4665+
"strum",
4666+
"strum_macros",
4667+
"thiserror",
4668+
"uuid",
4669+
]
4670+
46314671
[[package]]
46324672
name = "stable_deref_trait"
46334673
version = "1.2.0"
@@ -4731,6 +4771,25 @@ version = "0.10.0"
47314771
source = "registry+https://github.com/rust-lang/crates.io-index"
47324772
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
47334773

4774+
[[package]]
4775+
name = "strum"
4776+
version = "0.24.1"
4777+
source = "registry+https://github.com/rust-lang/crates.io-index"
4778+
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
4779+
4780+
[[package]]
4781+
name = "strum_macros"
4782+
version = "0.24.3"
4783+
source = "registry+https://github.com/rust-lang/crates.io-index"
4784+
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
4785+
dependencies = [
4786+
"heck",
4787+
"proc-macro2",
4788+
"quote",
4789+
"rustversion",
4790+
"syn",
4791+
]
4792+
47344793
[[package]]
47354794
name = "syn"
47364795
version = "1.0.102"
@@ -5357,6 +5416,15 @@ version = "0.1.1"
53575416
source = "registry+https://github.com/rust-lang/crates.io-index"
53585417
checksum = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
53595418

5419+
[[package]]
5420+
name = "uuid"
5421+
version = "0.8.2"
5422+
source = "registry+https://github.com/rust-lang/crates.io-index"
5423+
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
5424+
dependencies = [
5425+
"getrandom 0.2.0",
5426+
]
5427+
53605428
[[package]]
53615429
name = "valuable"
53625430
version = "0.1.0"

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ members = [
3939
"src/tools/bump-stage0",
4040
"src/tools/replace-version-placeholder",
4141
"src/tools/lld-wrapper",
42+
"src/tools/collect-license-metadata",
4243
]
4344

4445
exclude = [

src/bootstrap/builder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,7 @@ impl<'a> Builder<'a> {
753753
run::BumpStage0,
754754
run::ReplaceVersionPlaceholder,
755755
run::Miri,
756+
run::CollectLicenseMetadata,
756757
),
757758
// These commands either don't use paths, or they're special-cased in Build::build()
758759
Kind::Clean | Kind::Format | Kind::Setup => vec![],

src/bootstrap/run.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::path::PathBuf;
12
use std::process::Command;
23

34
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
@@ -189,3 +190,35 @@ impl Step for Miri {
189190
builder.run(&mut miri);
190191
}
191192
}
193+
194+
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
195+
pub struct CollectLicenseMetadata;
196+
197+
impl Step for CollectLicenseMetadata {
198+
type Output = PathBuf;
199+
const ONLY_HOSTS: bool = true;
200+
201+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
202+
run.path("src/tools/collect-license-metadata")
203+
}
204+
205+
fn make_run(run: RunConfig<'_>) {
206+
run.builder.ensure(CollectLicenseMetadata);
207+
}
208+
209+
fn run(self, builder: &Builder<'_>) -> Self::Output {
210+
let Some(reuse) = &builder.config.reuse else {
211+
panic!("REUSE is required to collect the license metadata");
212+
};
213+
214+
// Temporary location, it will be moved to src/etc once it's accurate.
215+
let dest = builder.out.join("license-metadata.json");
216+
217+
let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
218+
cmd.env("REUSE_EXE", reuse);
219+
cmd.env("DEST", &dest);
220+
builder.run(&mut cmd);
221+
222+
dest
223+
}
224+
}

src/bootstrap/tool.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ bootstrap_tool!(
380380
HtmlChecker, "src/tools/html-checker", "html-checker";
381381
BumpStage0, "src/tools/bump-stage0", "bump-stage0";
382382
ReplaceVersionPlaceholder, "src/tools/replace-version-placeholder", "replace-version-placeholder";
383+
CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
383384
);
384385

385386
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "collect-license-metadata"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
anyhow = "1.0.65"
8+
serde = { version = "1.0.147", features = ["derive"] }
9+
serde_json = "1.0.85"
10+
spdx-rs = "0.5.1"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use std::collections::HashMap;
2+
3+
pub(crate) struct LicensesInterner {
4+
by_id: Vec<License>,
5+
by_struct: HashMap<License, usize>,
6+
}
7+
8+
impl LicensesInterner {
9+
pub(crate) fn new() -> Self {
10+
LicensesInterner { by_id: Vec::new(), by_struct: HashMap::new() }
11+
}
12+
13+
pub(crate) fn intern(&mut self, license: License) -> LicenseId {
14+
if let Some(id) = self.by_struct.get(&license) {
15+
LicenseId(*id)
16+
} else {
17+
let id = self.by_id.len();
18+
self.by_id.push(license.clone());
19+
self.by_struct.insert(license, id);
20+
LicenseId(id)
21+
}
22+
}
23+
24+
pub(crate) fn resolve(&self, id: LicenseId) -> &License {
25+
&self.by_id[id.0]
26+
}
27+
}
28+
29+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize)]
30+
#[serde(transparent)]
31+
pub(crate) struct LicenseId(usize);
32+
33+
#[derive(Clone, Hash, PartialEq, Eq, serde::Serialize)]
34+
pub(crate) struct License {
35+
pub(crate) spdx: String,
36+
pub(crate) copyright: Vec<String>,
37+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
mod licenses;
2+
mod path_tree;
3+
mod reuse;
4+
5+
use crate::licenses::LicensesInterner;
6+
use anyhow::Error;
7+
use std::path::PathBuf;
8+
9+
fn main() -> Result<(), Error> {
10+
let reuse_exe: PathBuf = std::env::var_os("REUSE_EXE").expect("Missing REUSE_EXE").into();
11+
let dest: PathBuf = std::env::var_os("DEST").expect("Missing DEST").into();
12+
13+
let mut interner = LicensesInterner::new();
14+
let paths = crate::reuse::collect(&reuse_exe, &mut interner)?;
15+
16+
let mut tree = crate::path_tree::build(paths);
17+
tree.simplify();
18+
19+
if let Some(parent) = dest.parent() {
20+
std::fs::create_dir_all(parent)?;
21+
}
22+
std::fs::write(
23+
&dest,
24+
&serde_json::to_vec_pretty(&serde_json::json!({
25+
"files": crate::path_tree::strip_interning(tree, &interner),
26+
}))?,
27+
)?;
28+
29+
Ok(())
30+
}

0 commit comments

Comments
 (0)