Generate license attributions from JSON

JSON is mainly generated by cargo-license-hound
This commit is contained in:
Magnus Hoff 2017-11-14 13:06:50 +01:00
parent f2ad17b33f
commit 1911a914ef
8 changed files with 2029 additions and 18 deletions

3
Cargo.lock generated
View file

@ -132,6 +132,9 @@ version = "0.1.0"
dependencies = [ dependencies = [
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]

View file

@ -5,10 +5,13 @@ authors = ["Magnus Hoff <maghoff@gmail.com>"]
license = "GPL-3.0" license = "GPL-3.0"
[dependencies] [dependencies]
quote = "0.3.10"
syn = "0.10.5"
sha2 = "0.6"
base64 = "0.6" base64 = "0.6"
quote = "0.3.10"
serde = "1.0.0"
serde_derive = "1.0.0"
serde_json = "1.0"
sha2 = "0.6"
syn = "0.10.5"
[lib] [lib]
proc-macro = true proc-macro = true

View file

@ -1,17 +1,25 @@
#![recursion_limit="128"] #![recursion_limit="128"]
#[macro_use] extern crate quote; #[macro_use] extern crate quote;
#[macro_use] extern crate serde_derive;
extern crate base64; extern crate base64;
extern crate proc_macro; extern crate proc_macro;
extern crate serde_json;
extern crate serde;
extern crate sha2; extern crate sha2;
extern crate syn; extern crate syn;
use proc_macro::TokenStream; use proc_macro::TokenStream;
mod licenses;
mod static_resource; mod static_resource;
#[proc_macro_derive(StaticResource, attributes(filename, mime))] #[proc_macro_derive(StaticResource, attributes(filename, mime))]
pub fn static_resource(input: TokenStream) -> TokenStream { pub fn static_resource(input: TokenStream) -> TokenStream {
static_resource::static_resource(input) static_resource::static_resource(input)
} }
#[proc_macro_derive(Licenses)]
pub fn licenses(input: TokenStream) -> TokenStream {
licenses::licenses(input)
}

View file

@ -0,0 +1,86 @@
use std::fs::File;
use proc_macro::TokenStream;
use quote;
use serde_json;
use serde::de::IgnoredAny;
const SOURCES: &[&str] = &[
"src/licenses/license-hound.json",
"src/licenses/other.json",
];
#[derive(Debug, Copy, Clone, Deserialize)]
pub enum LicenseId {
Bsd3Clause,
Mit,
Mpl2,
Ofl11,
}
impl quote::ToTokens for LicenseId {
fn to_tokens(&self, tokens: &mut quote::Tokens) {
use self::LicenseId::*;
tokens.append(match self {
&Bsd3Clause => "Bsd3Clause",
&Mit => "Mit",
&Mpl2 => "Mpl2",
&Ofl11 => "Ofl11",
});
}
}
#[derive(Debug, Deserialize)]
struct LicenseDescription {
chosen_license: LicenseId,
copyright_notice: String,
link: Option<String>,
}
#[derive(Debug, Deserialize)]
struct LicenseReport {
package_name: String,
conclusion: Result<LicenseDescription, IgnoredAny>,
}
impl quote::ToTokens for LicenseReport {
fn to_tokens(&self, tokens: &mut quote::Tokens) {
let c: &LicenseDescription = self.conclusion.as_ref().unwrap();
let (name, link, copyright, license) =
(&self.package_name, &c.link, &c.copyright_notice, &c.chosen_license);
let link = match link {
&Some(ref link) => quote! { Some(#link) },
&None => quote! { None },
};
tokens.append(quote! {
LicenseInfo {
name: #name,
link: #link,
copyright: #copyright,
license: License::#license,
}
});
}
}
pub fn licenses(_input: TokenStream) -> TokenStream {
let mut license_infos = SOURCES
.iter()
.map(|x| -> Vec<LicenseReport> { serde_json::from_reader(File::open(x).unwrap()).unwrap() })
.map(|x| x.into_iter().filter(|x| x.conclusion.is_ok()))
.fold(vec![], |mut a, b| { a.extend(b); a });
license_infos.sort_unstable_by_key(|x| x.package_name.to_lowercase());
let gen = quote! {
lazy_static! {
static ref LICENSE_INFOS: &'static [LicenseInfo] = &[
#(#license_infos,)*
];
}
};
gen.parse().unwrap()
}

File diff suppressed because one or more lines are too long

11
src/licenses/other.json Normal file
View file

@ -0,0 +1,11 @@
[
{
"package_name": "Amatic SC",
"conclusion": {
"Ok": {
"chosen_license": "Ofl11",
"copyright_notice": "Copyright 2015 The Amatic SC Project Authors (contact@sansoxygen.com)"
}
}
}
]

View file

@ -7,6 +7,7 @@ use mimes::*;
use site::Layout; use site::Layout;
use web::{Resource, ResponseFuture}; use web::{Resource, ResponseFuture};
#[derive(Licenses)]
pub struct AboutResource; pub struct AboutResource;
impl AboutResource { impl AboutResource {
@ -47,26 +48,17 @@ impl License {
} }
} }
struct Dependency { struct LicenseInfo {
name: &'static str, name: &'static str,
link: Option<&'static str>,
copyright: &'static str, copyright: &'static str,
license: License, license: License,
} }
lazy_static! {
static ref DEPS: &'static [Dependency] = &[
Dependency {
name: "Amatic SC",
copyright: "Copyright 2015 The Amatic SC Project Authors (contact@sansoxygen.com)",
license: License::Ofl11,
},
];
}
#[derive(BartDisplay)] #[derive(BartDisplay)]
#[template="templates/about.html"] #[template="templates/about.html"]
struct Template<'a> { struct Template<'a> {
deps: &'a [Dependency] deps: &'a [LicenseInfo]
} }
impl<'a> Template<'a> { impl<'a> Template<'a> {
@ -96,7 +88,7 @@ impl Resource for AboutResource {
base: None, // Hmm, should perhaps accept `base` as argument base: None, // Hmm, should perhaps accept `base` as argument
title: "About Sausagewiki", title: "About Sausagewiki",
body: &Template { body: &Template {
deps: &*DEPS deps: &*LICENSE_INFOS
}, },
}.to_string())) }.to_string()))
})) }))

View file

@ -34,7 +34,7 @@ copyright holders and distributed under various licenses:
<thead><tr><th>Project</th><th>Copyright notice</th><th>License</th></tr></thead> <thead><tr><th>Project</th><th>Copyright notice</th><th>License</th></tr></thead>
<tbody> <tbody>
{{#deps}} {{#deps}}
<tr><td>{{.name}}</td><td>{{.copyright}}</td><td><a href="_about/{{.license.link()}}">{{.license.name()}}</a></td></tr> <tr><td>{{#.link}}<a href="{{.}}">{{..name}}</a>{{/.link}}{{^.link}}{{..name}}{{/.link}}</td><td>{{.copyright}}</td><td><a href="_about/{{.license.link()}}">{{.license.name()}}</a></td></tr>
{{/deps}} {{/deps}}
</tbody> </tbody>
</table> </table>