]> git.lizzy.rs Git - rust.git/blob - src/tools/generate-copyright/src/main.rs
Auto merge of #106780 - flip1995:clippyup, r=Manishearth
[rust.git] / src / tools / generate-copyright / src / main.rs
1 use anyhow::Error;
2 use std::io::Write;
3 use std::path::PathBuf;
4
5 fn main() -> Result<(), Error> {
6     let dest = env_path("DEST")?;
7     let license_metadata = env_path("LICENSE_METADATA")?;
8
9     let metadata: Metadata = serde_json::from_slice(&std::fs::read(&license_metadata)?)?;
10
11     let mut buffer = Vec::new();
12     render_recursive(&metadata.files, &mut buffer, 0)?;
13
14     std::fs::write(&dest, &buffer)?;
15
16     Ok(())
17 }
18
19 fn render_recursive(node: &Node, buffer: &mut Vec<u8>, depth: usize) -> Result<(), Error> {
20     let prefix = std::iter::repeat("> ").take(depth + 1).collect::<String>();
21
22     match node {
23         Node::Root { childs } => {
24             for child in childs {
25                 render_recursive(child, buffer, depth)?;
26             }
27         }
28         Node::Directory { name, childs, license } => {
29             render_license(&prefix, std::iter::once(name), license, buffer)?;
30             if !childs.is_empty() {
31                 writeln!(buffer, "{prefix}")?;
32                 writeln!(buffer, "{prefix}*Exceptions:*")?;
33                 for child in childs {
34                     writeln!(buffer, "{prefix}")?;
35                     render_recursive(child, buffer, depth + 1)?;
36                 }
37             }
38         }
39         Node::FileGroup { names, license } => {
40             render_license(&prefix, names.iter(), license, buffer)?;
41         }
42         Node::File { name, license } => {
43             render_license(&prefix, std::iter::once(name), license, buffer)?;
44         }
45     }
46
47     Ok(())
48 }
49
50 fn render_license<'a>(
51     prefix: &str,
52     names: impl Iterator<Item = &'a String>,
53     license: &License,
54     buffer: &mut Vec<u8>,
55 ) -> Result<(), Error> {
56     for name in names {
57         writeln!(buffer, "{prefix}**`{name}`**  ")?;
58     }
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 { "  " };
62         writeln!(buffer, "{prefix}Copyright: {copyright}{suffix}")?;
63     }
64
65     Ok(())
66 }
67
68 #[derive(serde::Deserialize)]
69 struct Metadata {
70     files: Node,
71 }
72
73 #[derive(serde::Deserialize)]
74 #[serde(rename_all = "kebab-case", tag = "type")]
75 pub(crate) enum Node {
76     Root { childs: Vec<Node> },
77     Directory { name: String, childs: Vec<Node>, license: License },
78     File { name: String, license: License },
79     FileGroup { names: Vec<String>, license: License },
80 }
81
82 #[derive(serde::Deserialize)]
83 struct License {
84     spdx: String,
85     copyright: Vec<String>,
86 }
87
88 fn env_path(var: &str) -> Result<PathBuf, Error> {
89     if let Some(var) = std::env::var_os(var) {
90         Ok(var.into())
91     } else {
92         anyhow::bail!("missing environment variable {var}")
93     }
94 }