Skip to content

Commit c6eb03b

Browse files
condense llvm licensing into a single item
1 parent d45eac3 commit c6eb03b

File tree

4 files changed

+116
-12
lines changed

4 files changed

+116
-12
lines changed

.reuse/dep5

+8
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,11 @@ License: MIT OR Apache-2.0
9393
Files: src/doc/rustc-dev-guide/mermaid.min.js
9494
Copyright: Knut Sveidqvist
9595
License: MIT
96+
97+
# Note that the LLVM submodule here only specifies the NCSA as the license for
98+
# LLVM, even though LLVM is in the process of a relicensing to Apache 2.0 with
99+
# the LLVM Exception. That's because relicensed files have a SPDX header with
100+
# the correct license, so it will automatically be included here.
101+
Files: src/llvm-project/*
102+
Copyright: The LLVM Authors
103+
License: NCSA

LICENSES/NCSA.txt

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
Copyright (c) <YEAR> <OWNER ORGANIZATION NAME>. All rights reserved.
2+
3+
Developed by: <NAME OF DEVELOPMENT GROUP>
4+
<NAME OF INSTITUTION>
5+
<URL FOR DEVELOPMENT GROUP/INSTITUTION>
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy of
8+
this software and associated documentation files (the "Software"), to deal with
9+
the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11+
of the Software, and to permit persons to whom the Software is furnished to
12+
do so, subject to the following conditions:
13+
* Redistributions of source code must retain the above copyright notice,
14+
this list of conditions and the following disclaimers.
15+
* Redistributions in binary form must reproduce the above copyright notice,
16+
this list of conditions and the following disclaimers in the documentation
17+
and/or other materials provided with the distribution.
18+
* Neither the names of <NAME OF DEVELOPMENT GROUP>, <NAME OF INSTITUTION>,
19+
nor the names of its contributors may be used to endorse or promote products
20+
derived from this Software without specific prior written permission.
21+
22+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25+
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
28+
SOFTWARE.
29+

src/tools/collect-license-metadata/src/path_tree.rs

+51-5
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,20 @@
44
//! passes over the tree to remove redundant information.
55
66
use crate::licenses::{License, LicenseId, LicensesInterner};
7-
use std::collections::BTreeMap;
7+
use std::collections::{BTreeMap, BTreeSet};
88
use std::path::{Path, PathBuf};
99

10+
// Some directories have too many slight license differences that'd result in a huge report, and
11+
// could be considered a standalone project anyway. Those directories are "condensed" into a single
12+
// licensing block for ease of reading, merging the licensing information.
13+
const CONDENSED_DIRECTORIED: &[&str] = &["./src/llvm-project/"];
14+
1015
#[derive(serde::Serialize)]
1116
#[serde(rename_all = "kebab-case", tag = "type")]
1217
pub(crate) enum Node<L> {
1318
Root { children: Vec<Node<L>> },
1419
Directory { name: PathBuf, children: Vec<Node<L>>, license: Option<L> },
20+
CondensedDirectory { name: PathBuf, licenses: Vec<L> },
1521
File { name: PathBuf, license: L },
1622
Group { files: Vec<PathBuf>, directories: Vec<PathBuf>, license: L },
1723
Empty,
@@ -57,9 +63,9 @@ impl Node<LicenseId> {
5763
Node::Directory { name, mut children, license: None } => {
5864
directories.entry(name).or_insert_with(Vec::new).append(&mut children);
5965
}
60-
file @ Node::File { .. } => {
61-
files.push(file);
62-
}
66+
file @ Node::File { .. } => files.push(file),
67+
// Propagate condensed directories as-is.
68+
condensed @ Node::CondensedDirectory { .. } => files.push(condensed),
6369
Node::Empty => {}
6470
Node::Root { .. } => {
6571
panic!("can't have a root inside another element");
@@ -86,6 +92,7 @@ impl Node<LicenseId> {
8692
}
8793
Node::Empty => {}
8894
Node::File { .. } => {}
95+
Node::CondensedDirectory { .. } => {}
8996
Node::Group { .. } => {
9097
panic!("Group should not be present at this stage");
9198
}
@@ -132,6 +139,7 @@ impl Node<LicenseId> {
132139
}
133140
}
134141
Node::File { .. } => {}
142+
Node::CondensedDirectory { .. } => {}
135143
Node::Group { .. } => panic!("group should not be present at this stage"),
136144
Node::Empty => {}
137145
}
@@ -174,6 +182,9 @@ impl Node<LicenseId> {
174182
Node::Directory { name: child_child_name, .. } => {
175183
*child_child_name = child_name.join(&child_child_name);
176184
}
185+
Node::CondensedDirectory { name: child_child_name, .. } => {
186+
*child_child_name = child_name.join(&child_child_name);
187+
}
177188
Node::File { name: child_child_name, .. } => {
178189
*child_child_name = child_name.join(&child_child_name);
179190
}
@@ -188,6 +199,7 @@ impl Node<LicenseId> {
188199
}
189200
Node::Empty => {}
190201
Node::File { .. } => {}
202+
Node::CondensedDirectory { .. } => {}
191203
Node::Group { .. } => panic!("Group should not be present at this stage"),
192204
}
193205
}
@@ -255,6 +267,7 @@ impl Node<LicenseId> {
255267
}
256268
}
257269
Node::File { .. } => {}
270+
Node::CondensedDirectory { .. } => {}
258271
Node::Group { .. } => panic!("FileGroup should not be present at this stage"),
259272
Node::Empty => {}
260273
}
@@ -270,6 +283,7 @@ impl Node<LicenseId> {
270283
}
271284
children.retain(|child| !matches!(child, Node::Empty));
272285
}
286+
Node::CondensedDirectory { .. } => {}
273287
Node::Group { .. } => {}
274288
Node::File { .. } => {}
275289
Node::Empty => {}
@@ -293,7 +307,19 @@ pub(crate) fn build(mut input: Vec<(PathBuf, LicenseId)>) -> Node<LicenseId> {
293307
// Ensure reproducibility of all future steps.
294308
input.sort();
295309

296-
for (path, license) in input {
310+
let mut condensed_directories = BTreeMap::new();
311+
'outer: for (path, license) in input {
312+
// Files in condensed directories are handled separately.
313+
for directory in CONDENSED_DIRECTORIED {
314+
if path.starts_with(directory) {
315+
condensed_directories
316+
.entry(*directory)
317+
.or_insert_with(BTreeSet::new)
318+
.insert(license);
319+
continue 'outer;
320+
}
321+
}
322+
297323
let mut node = Node::File { name: path.file_name().unwrap().into(), license };
298324
for component in path.parent().unwrap_or_else(|| Path::new(".")).components().rev() {
299325
node = Node::Directory {
@@ -306,6 +332,22 @@ pub(crate) fn build(mut input: Vec<(PathBuf, LicenseId)>) -> Node<LicenseId> {
306332
children.push(node);
307333
}
308334

335+
for (path, licenses) in condensed_directories {
336+
let path = Path::new(path);
337+
let mut node = Node::CondensedDirectory {
338+
name: path.file_name().unwrap().into(),
339+
licenses: licenses.iter().copied().collect(),
340+
};
341+
for name in path.parent().unwrap_or_else(|| Path::new(".")).components().rev() {
342+
node = Node::Directory {
343+
name: name.as_os_str().into(),
344+
children: vec![node],
345+
license: None,
346+
};
347+
}
348+
children.push(node);
349+
}
350+
309351
Node::Root { children }
310352
}
311353

@@ -334,6 +376,10 @@ pub(crate) fn expand_interned_licenses(
334376
Node::Group { files, directories, license } => {
335377
Node::Group { files, directories, license: interner.resolve(license) }
336378
}
379+
Node::CondensedDirectory { name, licenses } => Node::CondensedDirectory {
380+
name,
381+
licenses: licenses.into_iter().map(|license| interner.resolve(license)).collect(),
382+
},
337383
Node::Empty => Node::Empty,
338384
}
339385
}

src/tools/generate-copyright/src/main.rs

+28-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use anyhow::Error;
2+
use std::collections::BTreeSet;
23
use std::io::Write;
34
use std::path::PathBuf;
45

@@ -26,7 +27,7 @@ fn render_recursive(node: &Node, buffer: &mut Vec<u8>, depth: usize) -> Result<(
2627
}
2728
}
2829
Node::Directory { name, children, license } => {
29-
render_license(&prefix, std::iter::once(name), license, buffer)?;
30+
render_license(&prefix, std::iter::once(name), std::iter::once(license), buffer)?;
3031
if !children.is_empty() {
3132
writeln!(buffer, "{prefix}")?;
3233
writeln!(buffer, "{prefix}*Exceptions:*")?;
@@ -36,11 +37,19 @@ fn render_recursive(node: &Node, buffer: &mut Vec<u8>, depth: usize) -> Result<(
3637
}
3738
}
3839
}
40+
Node::CondensedDirectory { name, licenses } => {
41+
render_license(&prefix, std::iter::once(name), licenses.iter(), buffer)?;
42+
}
3943
Node::Group { files, directories, license } => {
40-
render_license(&prefix, directories.iter().chain(files.iter()), license, buffer)?;
44+
render_license(
45+
&prefix,
46+
directories.iter().chain(files.iter()),
47+
std::iter::once(license),
48+
buffer,
49+
)?;
4150
}
4251
Node::File { name, license } => {
43-
render_license(&prefix, std::iter::once(name), license, buffer)?;
52+
render_license(&prefix, std::iter::once(name), std::iter::once(license), buffer)?;
4453
}
4554
}
4655

@@ -50,15 +59,26 @@ fn render_recursive(node: &Node, buffer: &mut Vec<u8>, depth: usize) -> Result<(
5059
fn render_license<'a>(
5160
prefix: &str,
5261
names: impl Iterator<Item = &'a String>,
53-
license: &License,
62+
licenses: impl Iterator<Item = &'a License>,
5463
buffer: &mut Vec<u8>,
5564
) -> Result<(), Error> {
65+
let mut spdxs = BTreeSet::new();
66+
let mut copyrights = BTreeSet::new();
67+
for license in licenses {
68+
spdxs.insert(&license.spdx);
69+
for copyright in &license.copyright {
70+
copyrights.insert(copyright);
71+
}
72+
}
73+
5674
for name in names {
5775
writeln!(buffer, "{prefix}**`{name}`** ")?;
5876
}
59-
writeln!(buffer, "{prefix}License: `{}` ", license.spdx)?;
60-
for (i, copyright) in license.copyright.iter().enumerate() {
61-
let suffix = if i == license.copyright.len() - 1 { "" } else { " " };
77+
for spdx in spdxs.iter() {
78+
writeln!(buffer, "{prefix}License: `{spdx}` ")?;
79+
}
80+
for (i, copyright) in copyrights.iter().enumerate() {
81+
let suffix = if i == copyrights.len() - 1 { "" } else { " " };
6282
writeln!(buffer, "{prefix}Copyright: {copyright}{suffix}")?;
6383
}
6484

@@ -75,6 +95,7 @@ struct Metadata {
7595
pub(crate) enum Node {
7696
Root { children: Vec<Node> },
7797
Directory { name: String, children: Vec<Node>, license: License },
98+
CondensedDirectory { name: String, licenses: Vec<License> },
7899
File { name: String, license: License },
79100
Group { files: Vec<String>, directories: Vec<String>, license: License },
80101
}

0 commit comments

Comments
 (0)