about summary refs log tree commit diff
path: root/src/tools/generate-copyright
diff options
context:
space:
mode:
authorPietro Albini <pietro.albini@ferrous-systems.com>2022-11-15 11:27:19 +0100
committerPietro Albini <pietro.albini@ferrous-systems.com>2022-11-15 15:02:03 +0100
commit4af7de13d26aabe9bc459771bd5641c140407954 (patch)
tree5374bab7b7b1e267ba0e7595aed994e91ff53280 /src/tools/generate-copyright
parent13efb20846dc3b3916e44c67ebd4141a39c54d9b (diff)
downloadrust-4af7de13d26aabe9bc459771bd5641c140407954.tar.gz
rust-4af7de13d26aabe9bc459771bd5641c140407954.zip
initial prototype of the tool to generate copyright notices
Diffstat (limited to 'src/tools/generate-copyright')
-rw-r--r--src/tools/generate-copyright/Cargo.toml11
-rw-r--r--src/tools/generate-copyright/src/main.rs94
2 files changed, 105 insertions, 0 deletions
diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml
new file mode 100644
index 00000000000..899ef0f8a6c
--- /dev/null
+++ b/src/tools/generate-copyright/Cargo.toml
@@ -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"
diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs
new file mode 100644
index 00000000000..d172c9e157b
--- /dev/null
+++ b/src/tools/generate-copyright/src/main.rs
@@ -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}")
+    }
+}