initial prototype of the tool to generate copyright notices
This commit is contained in:
parent
13efb20846
commit
4af7de13d2
@ -1498,6 +1498,15 @@ dependencies = [
|
|||||||
"termcolor",
|
"termcolor",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generate-copyright"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.4"
|
version = "0.14.4"
|
||||||
|
@ -40,6 +40,7 @@ members = [
|
|||||||
"src/tools/replace-version-placeholder",
|
"src/tools/replace-version-placeholder",
|
||||||
"src/tools/lld-wrapper",
|
"src/tools/lld-wrapper",
|
||||||
"src/tools/collect-license-metadata",
|
"src/tools/collect-license-metadata",
|
||||||
|
"src/tools/generate-copyright",
|
||||||
]
|
]
|
||||||
|
|
||||||
exclude = [
|
exclude = [
|
||||||
|
@ -754,6 +754,7 @@ macro_rules! describe {
|
|||||||
run::ReplaceVersionPlaceholder,
|
run::ReplaceVersionPlaceholder,
|
||||||
run::Miri,
|
run::Miri,
|
||||||
run::CollectLicenseMetadata,
|
run::CollectLicenseMetadata,
|
||||||
|
run::GenerateCopyright,
|
||||||
),
|
),
|
||||||
// These commands either don't use paths, or they're special-cased in Build::build()
|
// These commands either don't use paths, or they're special-cased in Build::build()
|
||||||
Kind::Clean | Kind::Format | Kind::Setup => vec![],
|
Kind::Clean | Kind::Format | Kind::Setup => vec![],
|
||||||
|
@ -222,3 +222,33 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
|
|||||||
dest
|
dest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub struct GenerateCopyright;
|
||||||
|
|
||||||
|
impl Step for GenerateCopyright {
|
||||||
|
type Output = PathBuf;
|
||||||
|
const ONLY_HOSTS: bool = true;
|
||||||
|
|
||||||
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||||
|
run.path("src/tools/generate-copyright")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_run(run: RunConfig<'_>) {
|
||||||
|
run.builder.ensure(GenerateCopyright);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(self, builder: &Builder<'_>) -> Self::Output {
|
||||||
|
let license_metadata = builder.ensure(CollectLicenseMetadata);
|
||||||
|
|
||||||
|
// Temporary location, it will be moved to the proper one once it's accurate.
|
||||||
|
let dest = builder.out.join("COPYRIGHT.md");
|
||||||
|
|
||||||
|
let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
|
||||||
|
cmd.env("LICENSE_METADATA", &license_metadata);
|
||||||
|
cmd.env("DEST", &dest);
|
||||||
|
builder.run(&mut cmd);
|
||||||
|
|
||||||
|
dest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -381,6 +381,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
|
|||||||
BumpStage0, "src/tools/bump-stage0", "bump-stage0";
|
BumpStage0, "src/tools/bump-stage0", "bump-stage0";
|
||||||
ReplaceVersionPlaceholder, "src/tools/replace-version-placeholder", "replace-version-placeholder";
|
ReplaceVersionPlaceholder, "src/tools/replace-version-placeholder", "replace-version-placeholder";
|
||||||
CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
|
CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
|
||||||
|
GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
|
||||||
|
11
src/tools/generate-copyright/Cargo.toml
Normal file
11
src/tools/generate-copyright/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "generate-copyright"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0.65"
|
||||||
|
serde = { version = "1.0.147", features = ["derive"] }
|
||||||
|
serde_json = "1.0.85"
|
94
src/tools/generate-copyright/src/main.rs
Normal file
94
src/tools/generate-copyright/src/main.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
use anyhow::Error;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Error> {
|
||||||
|
let dest = env_path("DEST")?;
|
||||||
|
let license_metadata = env_path("LICENSE_METADATA")?;
|
||||||
|
|
||||||
|
let metadata: Metadata = serde_json::from_slice(&std::fs::read(&license_metadata)?)?;
|
||||||
|
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
render_recursive(&metadata.files, &mut buffer, 0)?;
|
||||||
|
|
||||||
|
std::fs::write(&dest, &buffer)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_recursive(node: &Node, buffer: &mut Vec<u8>, depth: usize) -> Result<(), Error> {
|
||||||
|
let prefix = std::iter::repeat("> ").take(depth + 1).collect::<String>();
|
||||||
|
|
||||||
|
match node {
|
||||||
|
Node::Root { childs } => {
|
||||||
|
for child in childs {
|
||||||
|
render_recursive(child, buffer, depth)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Node::Directory { name, childs, license } => {
|
||||||
|
render_license(&prefix, std::iter::once(name), license, buffer)?;
|
||||||
|
if !childs.is_empty() {
|
||||||
|
writeln!(buffer, "{prefix}")?;
|
||||||
|
writeln!(buffer, "{prefix}*Exceptions:*")?;
|
||||||
|
for child in childs {
|
||||||
|
writeln!(buffer, "{prefix}")?;
|
||||||
|
render_recursive(child, buffer, depth + 1)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Node::FileGroup { names, license } => {
|
||||||
|
render_license(&prefix, names.iter(), license, buffer)?;
|
||||||
|
}
|
||||||
|
Node::File { name, license } => {
|
||||||
|
render_license(&prefix, std::iter::once(name), license, buffer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_license<'a>(
|
||||||
|
prefix: &str,
|
||||||
|
names: impl Iterator<Item = &'a String>,
|
||||||
|
license: &License,
|
||||||
|
buffer: &mut Vec<u8>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
for name in names {
|
||||||
|
writeln!(buffer, "{prefix}**`{name}`** ")?;
|
||||||
|
}
|
||||||
|
writeln!(buffer, "{prefix}License: `{}` ", license.spdx)?;
|
||||||
|
for (i, copyright) in license.copyright.iter().enumerate() {
|
||||||
|
let suffix = if i == license.copyright.len() - 1 { "" } else { " " };
|
||||||
|
writeln!(buffer, "{prefix}Copyright: {copyright}{suffix}")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
struct Metadata {
|
||||||
|
files: Node,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
#[serde(rename_all = "kebab-case", tag = "type")]
|
||||||
|
pub(crate) enum Node {
|
||||||
|
Root { childs: Vec<Node> },
|
||||||
|
Directory { name: String, childs: Vec<Node>, license: License },
|
||||||
|
File { name: String, license: License },
|
||||||
|
FileGroup { names: Vec<String>, license: License },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
struct License {
|
||||||
|
spdx: String,
|
||||||
|
copyright: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn env_path(var: &str) -> Result<PathBuf, Error> {
|
||||||
|
if let Some(var) = std::env::var_os(var) {
|
||||||
|
Ok(var.into())
|
||||||
|
} else {
|
||||||
|
anyhow::bail!("missing environment variable {var}")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user