commit:     f9ad9ccf26dda0d1b50aa8e6a7befbc771245534
Author:     Leonardo H. Neumann <leonardohn <AT> null <DOT> net>
AuthorDate: Tue Jul 27 12:48:01 2021 +0000
Commit:     Georgy Yakovlev <gyakovlev <AT> gentoo <DOT> org>
CommitDate: Tue Aug  3 04:57:25 2021 +0000
URL:        https://gitweb.gentoo.org/proj/cargo-ebuild.git/commit/?id=f9ad9ccf

Initial support for license mapping

Closes: https://github.com/gentoo/cargo-ebuild/pull/8
Signed-off-by: Georgy Yakovlev <gyakovlev <AT> gentoo.org>

 Cargo.lock     | 122 ++++++++++++++++++++++++++++++++++++++++-
 Cargo.toml     |   4 ++
 src/lib.rs     |  22 ++++----
 src/license.rs | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 304 insertions(+), 12 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 4cde09f..562cd61 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -42,12 +42,13 @@ checksum = 
"cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cargo-ebuild"
-version = "0.3.2-alpha.0"
+version = "0.3.2"
 dependencies = [
  "anyhow",
  "cargo-lock",
  "cargo_metadata",
  "itertools",
+ "phf",
  "structopt",
  "time",
 ]
@@ -78,6 +79,12 @@ dependencies = [
  "serde_json",
 ]
 
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
 [[package]]
 name = "clap"
 version = "2.33.3"
@@ -115,6 +122,17 @@ dependencies = [
  "percent-encoding",
 ]
 
+[[package]]
+name = "getrandom"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
 [[package]]
 name = "gumdrop"
 version = "0.7.0"
@@ -229,6 +247,56 @@ dependencies = [
  "indexmap",
 ]
 
+[[package]]
+name = "phf"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "b2ac8b67553a7ca9457ce0e526948cad581819238f4a9d1ea74545851fa24f37"
+dependencies = [
+ "phf_macros",
+ "phf_shared",
+ "proc-macro-hack",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "0fc1437ada0f3a97d538f0bb608137bf53c53969028cab74c89893e1e9a12f0e"
+dependencies = [
+ "phf_shared",
+ "rand",
+]
+
+[[package]]
+name = "phf_macros"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "b706f5936eb50ed880ae3009395b43ed19db5bff2ebd459c95e7bf013a89ab86"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "a68318426de33640f02be62b4ae8eb1261be2efbc337b60c54d845bf4484e0d9"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+
 [[package]]
 name = "proc-macro-error"
 version = "1.0.4"
@@ -253,6 +321,12 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.19"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
+
 [[package]]
 name = "proc-macro2"
 version = "1.0.27"
@@ -271,6 +345,46 @@ dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "rand"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
+dependencies = [
+ "rand_core",
+]
+
 [[package]]
 name = "ryu"
 version = "1.0.5"
@@ -324,6 +438,12 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "siphasher"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "729a25c17d72b06c68cb47955d44fda88ad2d3e7d77e025663fdd69b93dd71a1"
+
 [[package]]
 name = "strsim"
 version = "0.8.0"

diff --git a/Cargo.toml b/Cargo.toml
index 037dce3..e208659 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -35,3 +35,7 @@ cargo_metadata = "^0.9"
 itertools = "^0.8"
 structopt = "^0.3"
 time = "^0.1"
+
+[dependencies.phf]
+version = "0.9"
+features = ["macros"]

diff --git a/src/lib.rs b/src/lib.rs
index b7616b7..01d915b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -8,6 +8,7 @@
  * except according to those terms.
  */
 
+mod license;
 mod metadata;
 
 use anyhow::{format_err, Context, Result};
@@ -20,17 +21,9 @@ use std::io::Write;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
+use license::{normalize_license, split_spdx_license};
 use metadata::EbuildConfig;
 
-fn parse_license<'a>(lic_str: &'a str) -> Vec<&'a str> {
-    lic_str
-        .split('/')
-        .flat_map(|l| l.split(" OR "))
-        .flat_map(|l| l.split(" AND "))
-        .map(str::trim)
-        .collect()
-}
-
 fn generate_lockfile(manifest_path: Option<PathBuf>) -> Result<()> {
     let cargo = std::env::var("CARGO")
         .map(PathBuf::from)
@@ -86,9 +79,16 @@ pub fn gen_ebuild_data(manifest_path: Option<PathBuf>) -> 
Result<EbuildConfig> {
             root_pkg = Some(pkg.clone());
         }
 
-        if let Some(lic_list) = pkg.license.as_ref().map(|l| 
parse_license(&l)) {
+        if let Some(lic_list) = pkg.license.as_ref().map(|l| 
split_spdx_license(&l)) {
             for lic in lic_list.iter() {
-                licenses.insert(lic.to_string());
+                if let Some(norm) = normalize_license(&lic) {
+                    // Add the normalized license name
+                    licenses.insert(norm.to_string());
+                } else {
+                    // Add the unknown license name to be corrected manually
+                    println!("WARNING: unknown license \"{}\", please correct 
manually", &lic);
+                    licenses.insert(lic.to_string());
+                }
             }
         }
 

diff --git a/src/license.rs b/src/license.rs
new file mode 100644
index 0000000..0789829
--- /dev/null
+++ b/src/license.rs
@@ -0,0 +1,168 @@
+use phf::phf_map;
+
+static SPDX_TO_LICENSE: phf::Map<&'static str, &'static str> = phf_map! {
+    "0BSD" => "0BSD",
+    "AFL-2.1" => "AFL-2.1",
+    "AFL-3.0" => "AFL-3.0",
+    "AGPL-3.0" => "AGPL-3",
+    "AGPL-3.0-only" => "AGPL-3",
+    "AGPL-3.0-or-later" => "AGPL-3+",
+    "Aladdin" => "Aladdin",
+    "AMPAS" => "AMPAS",
+    "Apache-1.0" => "Apache-1.0",
+    "Apache-1.1" => "Apache-1.1",
+    "Apache-2.0" => "Apache-2.0",
+    "APL-1.0" => "APL-1.0",
+    "APSL-2.0" => "APSL-2",
+    "Artistic-1.0" => "Artistic",
+    "Artistic-2.0" => "Artistic-2",
+    "Beerware" => "BEER-WARE",
+    "BSD-1-Clause" => "BSD-1",
+    "BSD-2-Clause" => "BSD-2",
+    "BSD-3-Clause" => "BSD",
+    "BSD-4-Clause" => "BSD-4",
+    "BSL-1.0" => "Boost-1.0",
+    "bzip2-1.0.5" => "BZIP2",
+    "bzip2-1.0.6" => "BZIP2",
+    "CC-BY-2.0" => "CC-BY-2.0",
+    "CC-BY-2.5" => "CC-BY-2.5",
+    "CC-BY-3.0" => "CC-BY-3.0",
+    "CC-BY-4.0" => "CC-BY-4.0",
+    "CC-BY-NC-4.0" => "CC-BY-NC-4.0",
+    "CC-BY-NC-ND-2.0" => "CC-BY-NC-ND-2.0",
+    "CC-BY-NC-ND-2.5" => "CC-BY-NC-ND-2.5",
+    "CC-BY-NC-ND-3.0" => "CC-BY-NC-ND-3.0",
+    "CC-BY-NC-ND-4.0" => "CC-BY-NC-ND-4.0",
+    "CC-BY-NC-SA-2.5" => "CC-BY-NC-SA-2.5",
+    "CC-BY-NC-SA-3.0" => "CC-BY-NC-SA-3.0",
+    "CC-BY-NC-SA-4.0" => "CC-BY-NC-SA-4.0",
+    "CC-BY-ND-3.0" => "CC-BY-ND-3.0",
+    "CC-BY-ND-4.0" => "CC-BY-ND-4.0",
+    "CC-BY-SA-1.0" => "CC-BY-SA-1.0",
+    "CC-BY-SA-2.0" => "CC-BY-SA-2.0",
+    "CC-BY-SA-2.5" => "CC-BY-SA-2.5",
+    "CC-BY-SA-3.0" => "CC-BY-SA-3.0",
+    "CC-BY-SA-4.0" => "CC-BY-SA-4.0",
+    "CC-PD" => "CC-PDDC",
+    "CC0-1.0" => "CC0-1.0",
+    "CDDL-1.0" => "CDDL",
+    "CDDL-1.1" => "CDDL-1.1",
+    "CECILL-2.0" => "CeCILL-2",
+    "CECILL-B" => "CeCILL-B",
+    "CECILL-C" => "CeCILL-C",
+    "CPAL-1.0" => "CPAL-1.0",
+    "CPL-1.0" => "CPL-1.0",
+    "CPOL-1.02" => "CPOL",
+    "curl" => "curl",
+    "ECL-2.0" => "ECL-2.0",
+    "EPL-1.0" => "EPL-1.0",
+    "EPL-2.0" => "EPL-2.0",
+    "ErlPL-1.1" => "ErlPL-1.1",
+    "EUPL-1.1" => "EUPL-1.1",
+    "EUPL-1.2" => "EUPL-1.2",
+    "Fair" => "fairuse",
+    "FSFAP" => "FSFAP",
+    "FTL" => "FTL",
+    "GD" => "gd",
+    "Glulxe" => "Glulxe",
+    "gnuplot" => "gnuplot",
+    "GPL-1.0" => "GPL-1",
+    "GPL-1.0+" => "GPL-1+",
+    "GPL-1.0-only" => "GPL-1",
+    "GPL-1.0-or-later" => "GPL-1+",
+    "GPL-2.0" => "GPL-2",
+    "GPL-2.0+" => "GPL-2+",
+    "GPL-2.0-only" => "GPL-2",
+    "GPL-2.0-or-later" => "GPL-2+",
+    "GPL-2.0-with-classpath-exception" => "GPL-2-with-classpath-exception",
+    "GPL-2.0-with-font-exception" => "GPL-2-with-font-exception",
+    "GPL-3.0" => "GPL-3",
+    "GPL-3.0+" => "GPL-3+",
+    "GPL-3.0-only" => "GPL-3",
+    "GPL-3.0-or-later" => "GPL-3+",
+    "GPL-3.0-with-autoconf-exception" => "GPL-3-with-autoconf-exception",
+    "gSOAP-1.3b" => "gSOAP",
+    "HPND" => "HPND",
+    "ICU" => "icu",
+    "IJG" => "IJG",
+    "ImageMagick" => "imagemagick",
+    "Info-ZIP" => "Info-ZIP",
+    "Interbase-1.0" => "Interbase-1.0",
+    "IPA" => "IPAfont",
+    "ISC" => "ISC",
+    "JSON" => "JSON",
+    "LGPL-2.0" => "LGPL-2",
+    "LGPL-2.0+" => "LGPL-2+",
+    "LGPL-2.0-only" => "LGPL-2",
+    "LGPL-2.0-or-later" => "LGPL-2+",
+    "LGPL-2.1" => "LGPL-2.1",
+    "LGPL-2.1+" => "LGPL-2.1+",
+    "LGPL-2.1-only" => "LGPL-2.1",
+    "LGPL-2.1-or-later" => "LGPL-2.1+",
+    "LGPL-3.0" => "LGPL-3",
+    "LGPL-3.0+" => "LGPL-3+",
+    "LGPL-3.0-only" => "LGPL-3",
+    "LGPL-3.0-or-later" => "LGPL-3+",
+    "Libpng" => "libpng",
+    "libpng-2.0" => "libpng2",
+    "libtiff" => "libtiff",
+    "LPPL-1.2" => "LPPL-1.2",
+    "LPPL-1.3a" => "LPPL-1.3",
+    "LPPL-1.3c" => "LPPL-1.3c",
+    "MirOS" => "MirOS",
+    "MIT" => "MIT",
+    "MIT-advertising" => "MIT-with-advertising",
+    "mpich2" => "mpich2",
+    "MPL-1.0" => "MPL-1.0",
+    "MPL-1.1" => "MPL-1.1",
+    "MPL-2.0" => "MPL-2.0",
+    "MS-PL" => "Ms-PL",
+    "NPL-1.1" => "NPL-1.1",
+    "OFL-1.0" => "OFL",
+    "OFL-1.1" => "OFL-1.1",
+    "OLDAP-2.7" => "OPENLDAP",
+    "OpenSSL" => "openssl",
+    "OPL-1.0" => "OPL",
+    "OSL-1.1" => "OSL-1.1",
+    "OSL-2.0" => "OSL-2.0",
+    "OSL-2.1" => "OSL-2.1",
+    "PHP-3.0" => "PHP-3",
+    "PHP-3.01" => "PHP-3.01",
+    "PostgreSQL" => "POSTGRESQL",
+    "PSF-2.0" => "PSF-2",
+    "psutils" => "psutils",
+    "Python-2.0" => "PYTHON",
+    "QPL-1.0" => "QPL-1.0",
+    "Rdisc" => "rdisc",
+    "RSA-MD" => "RSA",
+    "Ruby" => "Ruby",
+    "Sendmail" => "Sendmail",
+    "SGI-B-2.0" => "SGI-B-2.0",
+    "Sleepycat" => "Sleepycat",
+    "SSPL-1.0" => "SSPL-1",
+    "TCL" => "tcltk",
+    "TCP-wrappers" => "tcp_wrappers_license",
+    "Unlicense" => "Unlicense",
+    "Vim" => "vim",
+    "VOSTROM" => "VOSTROM",
+    "W3C" => "W3C",
+    "W3C-19980720" => "W3C-document",
+    "Watcom-1.0" => "Watcom-1.0",
+    "WTFPL" => "WTFPL-2",
+    "wxWindows" => "wxWinLL-3.1",
+    "Zend-2.0" => "Zend-2.0",
+    "Zlib" => "ZLIB",
+    "ZPL-2.1" => "ZPL",
+};
+
+pub fn split_spdx_license(str: &str) -> Vec<&str> {
+    str.split('/')
+        .flat_map(|l| l.split(" OR "))
+        .flat_map(|l| l.split(" AND "))
+        .map(str::trim)
+        .collect()
+}
+
+pub fn normalize_license(str: &str) -> Option<&'static str> {
+    SPDX_TO_LICENSE.get(str).copied()
+}

Reply via email to