From fa0cee6f48c4f7dd885c06583c2a4a17f6a9c532 Mon Sep 17 00:00:00 2001 From: Jake Shadle Date: Mon, 7 Oct 2019 16:19:30 +0200 Subject: [PATCH 1/4] [style] Remove newline so we can go green --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2cba1829..6bd76c7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,4 +63,3 @@ lazy_static = "1.4.0" # We use this for creating fake crate directories for # crawling license files on disk tempfile = "3.1.0" - From 01ea4d20dbf153ed99a2fda9bbe5b7f10f05a57d Mon Sep 17 00:00:00 2001 From: Jake Shadle Date: Tue, 29 Oct 2019 17:03:00 +0100 Subject: [PATCH 2/4] Add copyleft handling (#38) * Update dependencies * Add license.copyleft config * Add copyleft example * Add precedence note --- CHANGELOG.md | 2 + Cargo.lock | 299 ++++++++++++--------------- README.md | 25 ++- deny.toml | 7 +- examples/02_deny_license/Cargo.toml | 2 +- examples/03_deny_copyleft/Cargo.lock | 6 + examples/03_deny_copyleft/Cargo.toml | 10 + examples/03_deny_copyleft/README.md | 25 +++ examples/03_deny_copyleft/deny.toml | 3 + examples/03_deny_copyleft/main.rs | 1 + src/cargo-deny/check.rs | 2 +- src/licenses.rs | 207 +++++++++---------- 12 files changed, 302 insertions(+), 287 deletions(-) create mode 100644 examples/03_deny_copyleft/Cargo.lock create mode 100644 examples/03_deny_copyleft/Cargo.toml create mode 100644 examples/03_deny_copyleft/README.md create mode 100644 examples/03_deny_copyleft/deny.toml create mode 100644 examples/03_deny_copyleft/main.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 55722967..a87b7e0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- Added `[license.copyleft]` config which can be used to determine what happens when a copyleft license is encountered. ## [0.3.0-beta] - 2019-10-07 ### Added diff --git a/Cargo.lock b/Cargo.lock index c8049cec..c51e3112 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,10 +31,10 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -42,16 +42,16 @@ name = "askalono" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "rmp-serde 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -60,38 +60,38 @@ name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.38" +version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -101,11 +101,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "c2-chacha" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -123,8 +122,8 @@ dependencies = [ "crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "fern 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fern 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -132,13 +131,13 @@ dependencies = [ "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "spdx 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "spdx 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -148,14 +147,14 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -168,7 +167,7 @@ name = "chrono" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -181,7 +180,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -193,7 +192,7 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -257,7 +256,7 @@ name = "crossbeam-epoch" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -297,34 +296,35 @@ name = "erased-serde" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fern" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -335,22 +335,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "flate2" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "getrandom" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -374,7 +374,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.62" +version = "0.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -406,18 +406,9 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "miniz-sys" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "miniz_oxide" -version = "0.3.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -425,7 +416,7 @@ dependencies = [ [[package]] name = "nodrop" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -433,7 +424,7 @@ name = "num-integer" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -442,7 +433,7 @@ name = "num-traits" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -450,7 +441,7 @@ name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -475,10 +466,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -493,7 +484,7 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -501,41 +492,25 @@ name = "proc-macro-error" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro2" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quote" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -543,8 +518,8 @@ name = "rand" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -555,7 +530,7 @@ name = "rand_chacha" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -564,7 +539,7 @@ name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -662,7 +637,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rmp 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -680,7 +655,7 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -694,7 +669,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -704,45 +679,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "spdx" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -752,54 +727,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "structopt" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "structopt-derive" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.15.44" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "synstructure" -version = "0.10.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -808,7 +773,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -844,17 +809,17 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "toml" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -872,7 +837,7 @@ name = "unicode-normalization" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -885,11 +850,6 @@ name = "unicode-width" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicode-xid" version = "0.2.0" @@ -951,17 +911,17 @@ dependencies = [ "checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" +"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum askalono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e62de03dfcb3e55b6c05fbcc2fd51d712be3904f3981ee2ae6252087afc3f1e1" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" -"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5" -"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" -"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" +"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" +"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" +"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" "checksum cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426" -"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" +"checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" @@ -978,23 +938,22 @@ dependencies = [ "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3beee4bc16478a1b26f2e80ad819a52d24745e292f521a63c16eea5f74b7eb60" -"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" -"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum fern 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "29d26fa0f4d433d1956746e66ec10d6bf4d6c8b93cd39965cceea7f7cc78c7dd" +"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" +"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" +"checksum fern 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e69ab0d5aca163e388c3a49d284fed6c3d0810700e77c5ae2756a50ec1a4daaa" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" -"checksum flate2 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "2adaffba6388640136149e18ed080b77a78611c1e1d6de75aedcdf78df5d4682" -"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3" +"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -"checksum miniz-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9e3ae51cea1576ceba0dde3d484d30e6e5b86dee0b2d412fe3a16a15c98202" -"checksum miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7108aff85b876d06f22503dcce091e29f76733b2bfdd91eebce81f5e68203a10" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625" +"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" @@ -1002,11 +961,9 @@ dependencies = [ "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" -"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" +"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" "checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afdc77cc74ec70ed262262942ebb7dac3d479e9e5cfa2da1841c0806f6cdabcc" -"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" @@ -1024,33 +981,31 @@ dependencies = [ "checksum rmp-serde 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "011e1d58446e9fa3af7cdc1fb91295b10621d3ac4cb3a85cc86385ee9ca50cd3" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" -"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" -"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" -"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" -"checksum spdx 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea9c247b776cc364282c33ca50a292d5151c8af5e7d27f666202afc1476c4a82" +"checksum serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4b39bd9b0b087684013a792c59e3e07a46a01d2322518d8a1104641a0b1be0" +"checksum serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "ca13fc1a832f793322228923fbb3aba9f3f44444898f835d31ad1b74fa0a2bf8" +"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" +"checksum smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cefaa50e76a6f10b86f36e640eb1739eafbd4084865067778463913e43a77ff3" +"checksum spdx 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b8921789819b4567f9c140543cf4191200ad62d676ce3a1e48f3d385824c0d0" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe8d3289b63ef2f196d89e7701f986583c0895e764b78f052a55b9b5d34d84a" -"checksum structopt-derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f3add731f5b4fb85931d362a3c92deb1ad7113649a8d51701fb257673705f122" -"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" +"checksum structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4f66a4c0ddf7aee4677995697366de0749b0139057342eccbb609b12d0affc" +"checksum structopt-derive 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fe0c13e476b4e21ff7f5c4ace3818b6d7bdc16897c31c73862471bc1663acae" +"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c" +"checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" +"checksum toml 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c04dffffeac90885436d23c692517bb5b8b3f8863e4afc15023628d067d667b7" "checksum twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" "checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" diff --git a/README.md b/README.md index 2e5e42f6..0a0c9c65 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,19 @@ One important aspect that one must always keep in mind when using code from othe So `cargo-deny` allows you to ensure that all of your dependencies have license requirements that align with your configuration. +### Precedence + +Currently, the precedence for determining whether a particular license is accepted or rejected is as follows: + +1. A license specified in the `deny` list is **always rejected**. +1. A license specified in the `allow` list is **always accepted**. +1. If the license is considered [copyleft](https://en.wikipedia.org/wiki/Copyleft), the [`[license.copyleft]`](#the-copyleft-field) configuration determines its status +1. If the license is [OSI Approved](https://opensource.org/licenses) or [FSF Free/Libre](https://www.gnu.org/licenses/license-list.en.html), the [`[license.allow-osi-fsf-free]`](#the-allow-osi-fsf-free-field) configuration determines its status +1. If the license does not match any of the above criteria, it is implicitly **rejected**. + ### The `[licenses]` section -Contains all of the configuration for `cargo deny check license` +Contains all of the configuration for `cargo deny check license`. #### The `unlicensed` field @@ -36,14 +46,22 @@ Determines what happens when a crate has not explicitly specified its license te information could be easily detected via `LICENSE*` files in the crate's source. * `deny` (default) - All unlicensed crates will emit an error and fail the license check -* `allow` - All unlicensed crates will be allowed with no feedback +* `allow` - All unlicensed crates will show a note, but will not fail the license check * `warn` - All unlicensed crates will show a warning, but will not fail the license check #### The `allow` and `deny` fields The licenses that should be allowed or denied. The license must be a valid SPDX v2.1 identifier, which must either be in version 3.6 of the [SPDX License List](https://spdx.org/licenses/), with an optional [exception](https://spdx.org/licenses/exceptions-index.html) specified by `WITH `, or else a user defined license reference denoted by `LicenseRef-` for a license not on the SPDX License List. -The same license cannot appear in both the `allow` and `deny` lists. +**NOTE:** The same license cannot appear in both the `allow` and `deny` lists. + +#### The `copyleft` field + +Determines what happens when a license that is considered [copyleft](https://en.wikipedia.org/wiki/Copyleft) is encountered. + +* `warn` (default) - Will emit a warning that a copyleft license was detected, but will not fail the license check +* `deny` - The license is not accepted if it is copyleft, but might not fail the license check if part of an expression that containe +* `allow` - The license is accepted if it is copyleft #### The `allow-osi-fsf-free` field @@ -88,6 +106,7 @@ Contains one or more files that will be checked to ensure the license expression [licenses] unlicensed = "deny" allow-osi-fsf-free = "either" +copyleft = "ignore" confidence-threshold = 0.92 deny = [ "GPL-3.0-or-later", diff --git a/deny.toml b/deny.toml index 3b3ac2b9..6438f5b0 100644 --- a/deny.toml +++ b/deny.toml @@ -10,18 +10,13 @@ skip = [ { name = "regex", version = "=0.2.11" }, { name = "regex-syntax", version = "=0.5.6" }, { name = "aho-corasick", version = "=0.6.10" }, - - # some macro crates use the pre 1.0 syn dependencies - { name = "syn", version = "<=0.15" }, - { name = "proc-macro2", version = "<=0.4" }, - { name = "quote", version = "<=0.6" }, - { name = "unicode-xid", version = "=0.1" }, ] [licenses] unlicensed = "deny" unknown = "deny" allow-osi-fsf-free = "neither" +copyleft = "deny" # We want really high confidence when inferring licenses from text confidence-threshold = 0.93 allow = [ diff --git a/examples/02_deny_license/Cargo.toml b/examples/02_deny_license/Cargo.toml index 11539dda..44407870 100644 --- a/examples/02_deny_license/Cargo.toml +++ b/examples/02_deny_license/Cargo.toml @@ -6,5 +6,5 @@ license = "MIT AND Apache-2.0" edition = "2018" [[bin]] -name = "allow-license" +name = "deny-license" path = "main.rs" diff --git a/examples/03_deny_copyleft/Cargo.lock b/examples/03_deny_copyleft/Cargo.lock new file mode 100644 index 00000000..ef8dc757 --- /dev/null +++ b/examples/03_deny_copyleft/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "deny-copyleft" +version = "0.1.0" + diff --git a/examples/03_deny_copyleft/Cargo.toml b/examples/03_deny_copyleft/Cargo.toml new file mode 100644 index 00000000..64d466fa --- /dev/null +++ b/examples/03_deny_copyleft/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "deny-copyleft" +version = "0.1.0" +authors = ["Jake Shadle "] +license = "GPL-3.0 AND MIT" +edition = "2018" + +[[bin]] +name = "deny-copyleft" +path = "main.rs" diff --git a/examples/03_deny_copyleft/README.md b/examples/03_deny_copyleft/README.md new file mode 100644 index 00000000..a05bf769 --- /dev/null +++ b/examples/03_deny_copyleft/README.md @@ -0,0 +1,25 @@ +# 02_deny_copyleft + +This example shows how to explicitly deny certain licenses that will be checked against +the license requirements of every crate in your dependency graph. + +## Requirement + +```toml +license = "MIT AND Apache-2.0" +``` + +## Config + +```toml +[licenses] +allow = [ "MIT" ] +deny = [ "Apache-2.0" ] +``` + +## Description + +Just as we can allow specific licenses, we can deny specific ones via `[licenses.deny]`. Note that the license requirement +has changed to use the operator `AND` instead of `OR` which means that the user is required to license the crate under +both of the licenses, so even though we still allow `MIT`, our denial of `Apache-2.0` causes the expression to fail and +cargo-deny to emit an error that we did not accede to the license requirements of the crate. diff --git a/examples/03_deny_copyleft/deny.toml b/examples/03_deny_copyleft/deny.toml new file mode 100644 index 00000000..3028fe79 --- /dev/null +++ b/examples/03_deny_copyleft/deny.toml @@ -0,0 +1,3 @@ +[licenses] +allow = [ "MIT" ] +copyleft = "deny" diff --git a/examples/03_deny_copyleft/main.rs b/examples/03_deny_copyleft/main.rs new file mode 100644 index 00000000..f328e4d9 --- /dev/null +++ b/examples/03_deny_copyleft/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/cargo-deny/check.rs b/src/cargo-deny/check.rs index 7feb571b..ca9086b2 100644 --- a/src/cargo-deny/check.rs +++ b/src/cargo-deny/check.rs @@ -186,7 +186,7 @@ pub fn cmd( move || { if let Some((summary, lic_cfg)) = lic_cfg { log::info!("checking licenses..."); - licenses::check_licenses(summary, max_severity, &lic_cfg, send.clone()); + licenses::check_licenses(summary, &lic_cfg, send.clone()); } if let Some(bans) = ban_cfg { diff --git a/src/licenses.rs b/src/licenses.rs index 6173a281..dcbfee3e 100644 --- a/src/licenses.rs +++ b/src/licenses.rs @@ -18,6 +18,10 @@ const fn lint_deny() -> LintLevel { LintLevel::Deny } +const fn lint_warn() -> LintLevel { + LintLevel::Warn +} + const fn confidence_threshold() -> f32 { 0.8 } @@ -111,6 +115,9 @@ pub struct Config { /// or FSF/Free Libre #[serde(default)] pub allow_osi_fsf_free: BlanketAgreement, + /// Determines what happens when a copyleft license is detected + #[serde(default = "lint_warn")] + pub copyleft: LintLevel, /// The minimum confidence threshold we allow when determining the license /// in a text file, on a 0.0 (none) to 1.0 (maximum) scale #[serde(default = "confidence_threshold")] @@ -235,6 +242,7 @@ impl Config { Ok(ValidConfig { file_id: cfg_file, unlicensed: self.unlicensed, + copyleft: self.copyleft, allow_osi_fsf_free: self.allow_osi_fsf_free, confidence_threshold: self.confidence_threshold, clarifications, @@ -248,6 +256,7 @@ impl Config { pub struct ValidConfig { pub file_id: codespan::FileId, pub unlicensed: LintLevel, + pub copyleft: LintLevel, pub allow_osi_fsf_free: BlanketAgreement, pub confidence_threshold: f32, pub denied: Vec, @@ -944,7 +953,6 @@ impl Gatherer { pub fn check_licenses( summary: Summary<'_>, - max_severity: Option, cfg: &ValidConfig, sender: crossbeam::channel::Sender, ) { @@ -964,9 +972,26 @@ pub fn check_licenses( IsOsiApproved, IsBothFreeAndOsi, ExplicitAllowance, + IsCopyleft, + } + + let mut reasons = smallvec::SmallVec::<[(Reason, bool); 8]>::new(); + + macro_rules! deny { + ($reason:ident) => { + reasons.push((Reason::$reason, false)); + return false; + }; + } + + macro_rules! allow { + ($reason:ident) => { + reasons.push((Reason::$reason, true)); + return true; + }; } - let mut reasons = smallvec::SmallVec::<[Reason; 8]>::new(); + let mut warnings = 0; let eval_res = expr.evaluate_with_failures(|req| { // 1. Licenses explicitly denied are of course hard failures, @@ -979,8 +1004,7 @@ pub fn check_licenses( cfg.denied.binary_search_by(|a| a.partial_cmp(req).unwrap()) { if cfg.denied[maybe_denied].satisfies(req) { - reasons.push(Reason::Denied); - return false; + deny!(Denied); } } @@ -991,8 +1015,7 @@ pub fn check_licenses( .binary_search_by(|a| a.partial_cmp(req).unwrap()) { if cfg.allowed[maybe_allowed].satisfies(req) { - reasons.push(Reason::ExplicitAllowance); - return true; + allow!(ExplicitAllowance); } } @@ -1000,42 +1023,50 @@ pub fn check_licenses( // be allowed by the blanket "OSI Approved" or "FSF Free/Libre" // allowances if let spdx::LicenseItem::SPDX { id, .. } = req.license { + if id.is_copyleft() { + match cfg.copyleft { + LintLevel::Allow => { + allow!(IsCopyleft); + } + LintLevel::Warn => { + warnings += 1; + allow!(IsCopyleft); + } + LintLevel::Deny => { + deny!(IsCopyleft); + } + } + } + match cfg.allow_osi_fsf_free { BlanketAgreement::Neither => {} BlanketAgreement::Either => { if id.is_osi_approved() { - reasons.push(Reason::IsOsiApproved); - return true; + allow!(IsOsiApproved); } else if id.is_fsf_free_libre() { - reasons.push(Reason::IsFsfFree); - return true; + allow!(IsFsfFree); } } BlanketAgreement::Both => { if id.is_fsf_free_libre() && id.is_osi_approved() { - reasons.push(Reason::IsBothFreeAndOsi); - return true; + allow!(IsBothFreeAndOsi); } } BlanketAgreement::OsiOnly => { if id.is_osi_approved() { if id.is_fsf_free_libre() { - reasons.push(Reason::IsFsfFree); - return false; + deny!(IsFsfFree); } else { - reasons.push(Reason::IsOsiApproved); - return true; + allow!(IsOsiApproved); } } } BlanketAgreement::FsfOnly => { if id.is_fsf_free_libre() { if id.is_osi_approved() { - reasons.push(Reason::IsOsiApproved); - return false; + deny!(IsOsiApproved); } else { - reasons.push(Reason::IsFsfFree); - return true; + allow!(IsFsfFree); } } } @@ -1043,100 +1074,68 @@ pub fn check_licenses( } // 4. Whelp, this license just won't do! - reasons.push(Reason::NotExplicitlyAllowed); + reasons.push((Reason::NotExplicitlyAllowed, false)); false }); - match eval_res { - Err(_) => { - let mut secondary = Vec::with_capacity(reasons.len()); - for (reason, failed_req) in reasons.into_iter().zip(expr.requirements()) { - secondary.push(Label::new( - nfo.file_id, - nfo.offset + failed_req.span.start..nfo.offset + failed_req.span.end, - match reason { - Reason::Denied => "explicitly denied", - Reason::NotExplicitlyAllowed => "not explicitly allowed", - Reason::IsFsfFree => "license is FSF approved https://www.gnu.org/licenses/license-list.en.html", - Reason::IsOsiApproved => "license is OSI approved https://opensource.org/licenses", - Reason::ExplicitAllowance => "license is explicitly allowed", - Reason::IsBothFreeAndOsi => "license is FSF approved AND OSI approved", - }, - )); + let (message, severity) = match eval_res { + Err(_) => ("failed to satisfy license requirements", Severity::Error), + Ok(_) => ( + "license requirements satisfied", + if warnings > 0 { + Severity::Warning + } else { + Severity::Help + }, + ), + }; + + let prim_label = Label::new( + nfo.file_id, + nfo.offset..nfo.offset + expr.as_ref().len() as u32, + format!( + "license expression retrieved via {}", + match nfo.source { + LicenseExprSource::Metadata => "Cargo.toml `license`", + LicenseExprSource::UserOverride => "user override", + LicenseExprSource::LicenseFiles => "LICENSE file(s)", + LicenseExprSource::OverlayOverride => unreachable!(), } + ), + ); - diagnostics.push( - Diagnostic::new( - Severity::Error, - "failed to satisfy license requirements", - Label::new( - nfo.file_id, - nfo.offset..nfo.offset + expr.as_ref().len() as u32, - format!( - "license expression retrieved via {}", - match nfo.source { - LicenseExprSource::Metadata => "Cargo.toml `license`", - LicenseExprSource::UserOverride => "user override", - LicenseExprSource::LicenseFiles => "LICENSE file(s)", - LicenseExprSource::OverlayOverride => unreachable!(), - } - ), - ), - ) - .with_secondary_labels( - krate_lic_nfo - .labels - .iter() - .cloned() - .chain(secondary.into_iter()), - ), - ); - } - Ok(_) => { - if max_severity == Some(Severity::Help) { - let mut secondary = Vec::with_capacity(reasons.len()); - for (reason, req) in reasons.into_iter().zip(expr.requirements()) { - secondary.push(Label::new( - nfo.file_id, - nfo.offset + req.span.start..nfo.offset + req.span.end, - match reason { - Reason::Denied => "explicitly denied", - Reason::NotExplicitlyAllowed => "not explicitly allowed", - Reason::IsFsfFree => "license is FSF approved https://www.gnu.org/licenses/license-list.en.html", - Reason::IsOsiApproved => "license is OSI approved https://opensource.org/licenses", - Reason::ExplicitAllowance => "license is explicitly allowed", - Reason::IsBothFreeAndOsi => "license is FSF approved AND OSI approved", - }, - )); + let mut secondary = Vec::with_capacity(reasons.len()); + for (reason, failed_req) in reasons.into_iter().zip(expr.requirements()) { + secondary.push(Label::new( + nfo.file_id, + nfo.offset + failed_req.span.start..nfo.offset + failed_req.span.end, + format!("{}: {}", if reason.1 { "accepted" } else { "rejected" }, + match reason.0 { + Reason::Denied => "explicitly denied", + Reason::NotExplicitlyAllowed => "not explicitly allowed", + Reason::IsFsfFree => "license is FSF approved https://www.gnu.org/licenses/license-list.en.html", + Reason::IsOsiApproved => "license is OSI approved https://opensource.org/licenses", + Reason::ExplicitAllowance => "license is explicitly allowed", + Reason::IsBothFreeAndOsi => "license is FSF AND OSI approved", + Reason::IsCopyleft => "license is considered copyleft", } - - diagnostics.push( - Diagnostic::new( - Severity::Help, - format!( - "license expression retrieved via {}", - match nfo.source { - LicenseExprSource::Metadata => "Cargo.toml `license`", - LicenseExprSource::UserOverride => "user override", - LicenseExprSource::LicenseFiles => "LICENSE file(s)", - LicenseExprSource::OverlayOverride => unreachable!(), - } - ), - Label::new( - nfo.file_id, - nfo.offset..nfo.offset + expr.as_ref().len() as u32, - "license expression", - ), - ) - .with_secondary_labels(secondary), - ); - } - } + ), + )); } + + diagnostics.push( + Diagnostic::new(severity, message, prim_label).with_secondary_labels( + krate_lic_nfo + .labels + .iter() + .cloned() + .chain(secondary.into_iter()), + ), + ); } LicenseInfo::Unlicensed => { let severity = match cfg.unlicensed { - LintLevel::Allow => continue, + LintLevel::Allow => Severity::Note, LintLevel::Warn => Severity::Warning, LintLevel::Deny => Severity::Error, }; From 30f8319b81800d7705c02a5c2e82299affe399ac Mon Sep 17 00:00:00 2001 From: Jake Shadle Date: Wed, 30 Oct 2019 18:08:37 +0100 Subject: [PATCH 3/4] Add skipping of subtrees (#39) * Fix duplicate output in presense of skips * Add skip-tree configuration * Always check denies/allows * Update changelog * Update README --- CHANGELOG.md | 6 +- Cargo.lock | 7 + Cargo.toml | 1 + README.md | 33 +++- src/ban.rs | 417 +++++++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 393 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a87b7e0a..f92187ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- Added `[license.copyleft]` config which can be used to determine what happens when a copyleft license is encountered. +- Added `[license.copyleft]` config, which can be used to determine what happens when a copyleft license is encountered. +- Added `[bans.skip-tree]` config, which can be used to skip entire subtrees of a dependency graph when considering duplicates + +### Fixed +- Fixed displaying of duplicate errors in the presence of a `skip`ped crate ## [0.3.0-beta] - 2019-10-07 ### Added diff --git a/Cargo.lock b/Cargo.lock index c51e3112..83529e31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,6 +94,11 @@ name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitvec" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.3.2" @@ -114,6 +119,7 @@ dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "askalono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bitvec 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -918,6 +924,7 @@ dependencies = [ "checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum bitvec 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a993f74b4c99c1908d156b8d2e0fb6277736b0ecbd833982fd1241d39b2766a6" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" "checksum cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426" diff --git a/Cargo.toml b/Cargo.toml index 6bd76c7e..50b0a0f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ path = "src/cargo-deny/main.rs" [dependencies] ansi_term = "0.11.0" atty = "0.2.13" +bitvec = { version = "0.15.2", features = ["alloc"] } cargo_metadata = "0.8.2" chrono = "0.4.9" clap = "2.33.0" diff --git a/README.md b/README.md index 0a0c9c65..9dca3e00 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,20 @@ edges to the root of the graph, which will often be the best candidate for remov ![Imgur](https://i.imgur.com/xtarzeU.png) +#### Crate specifier + +The `allow`, `deny`, `skip`, and `skip-tree` fields all use a crate identifier to specify what crate(s) they want to match against. + +`{ name = "some-crate-name-here", version = "<= 0.7.0" }` + +##### The `name` field + +The name of the crate. + +##### The `version` field + +An optional version constraint specifying the range of crate versions that will match. Defaults to all versions (`*`). + #### The `allow` and `deny` fields As with `licenses`, these determine which specificy crates and version ranges are actually allowed or denied. @@ -186,17 +200,13 @@ When denying duplicate versions, it sometimes takes time to update versions in t Note entries in the `skip` field that never match a crate in your graph will have a warning printed that they never matched, allowing you to clean up your configuration as your crate graph changes over time. -#### Crate specifier - -The `allow`, `deny`, and `skip` fields all use a crate identifier to specify what crate(s) they want to match against. - -##### The `name` field +#### The `skip-tree` field -The name of the crate. +When dealing with duplicate versions, it's often the case that a particular crate acts as a nexus point for a cascade effect, by either using bleeding edge versions of certain crates while in alpha or beta, or on the opposite end, a crate is using severely outdated dependencies while much of the rest of the ecosystem has moved to more recent versions. In both cases, it can be quite tedious to explicitly `skip` each transitive dependency pulled in by that crate that clashes with your other dependencies, which is where `skip-tree` comes in. -##### The `version` field +`skip-tree` entries are similar to `skip` in that they are used to specify a crate name and version range that will be skipped, but they also have an additional `depth` field that can be used to specify the depth from that root crate that will also be ignored when checking for duplicates. In that sense, a `depth` of `0` would be functionally the same as specifying the same crate name and version constraint in the `skip` list instead. -An optional version constraint specifying the range of crate versions that will match. Defaults to all versions (`*`). +Note that by default, the `depth` is infinite. ### Example Config @@ -220,6 +230,13 @@ skip = [ { name = "quote", version = "<=0.6" }, { name = "unicode-xid", version = "=0.1" }, ] +skip-tree = [ + # tonic is in alpha right now, and pulls in many alpha versions of tokio/tower + # crates, so ignore all of them for now until things stabilize + { name = "tonic", version = "0.1.0-alpha.4" }, + # ignore older rand as many crates still use it instead of the newer 0.7+ version + { name = "rand", version = "=0.6.5" }, +] ``` ## CI Usage diff --git a/src/ban.rs b/src/ban.rs index 5d13cddd..3e468eff 100644 --- a/src/ban.rs +++ b/src/ban.rs @@ -15,6 +15,13 @@ pub struct CrateId { pub version: VersionReq, } +#[derive(Deserialize)] +pub struct TreeSkip { + #[serde(flatten)] + pub id: CrateId, + pub depth: Option, +} + const fn lint_warn() -> LintLevel { LintLevel::Warn } @@ -69,6 +76,10 @@ pub struct Config { /// If specified, disregards the crate completely #[serde(default)] pub skip: Vec>, + /// If specified, disregards the crate's transitive dependencies + /// down to a certain depth + #[serde(default)] + pub skip_tree: Vec>, } impl Config { @@ -151,6 +162,7 @@ impl Config { add_diag((a, "allow"), (&skipped[si], "skip")); } } + if !diagnostics.is_empty() { Err(diagnostics) } else { @@ -161,6 +173,7 @@ impl Config { denied, allowed, skipped, + tree_skipped: self.skip_tree, }) } } @@ -201,6 +214,7 @@ pub struct ValidConfig { denied: Vec, allowed: Vec, skipped: Vec, + tree_skipped: Vec>, } fn binary_search<'a>( @@ -238,6 +252,36 @@ fn binary_search<'a>( } } +fn binary_search_by_name<'a>( + arr: &'a [crate::KrateDetails], + name: &'a str, +) -> Result, usize> { + let lowest = Version::new(0, 0, 0); + + match arr.binary_search_by(|i| match i.name.as_str().cmp(name) { + cmp::Ordering::Equal => i.version.cmp(&lowest), + o => o, + }) { + Ok(i) | Err(i) => { + if arr[i].name != name { + return Err(i); + } + + // Backtrack 1 if the crate name matches, as, for instance, wildcards will be sorted + // before the 0.0.0 version + let begin = if i > 0 && arr[i - 1].name == name { + i - 1 + } else { + i + }; + + let end = arr[begin..].iter().take_while(|kd| kd.name == name).count() + begin; + + Ok(begin..end) + } + } +} + use petgraph::Graph; #[derive(Hash, Copy, Clone, PartialEq, Eq)] @@ -459,22 +503,22 @@ fn create_graph( dup_name: &str, highlight: GraphHighlight, krates: &crate::Krates, - dup_range: std::ops::Range, + duplicates: &[usize], ) -> Result { use petgraph::visit::{EdgeRef, NodeRef}; let mut graph = Graph::new(); let mut node_map = HashMap::new(); - for duplicate in dup_range.clone() { - append_dependency_chain(krates, duplicate, &mut graph, &mut node_map); + for duplicate in duplicates { + append_dependency_chain(krates, *duplicate, &mut graph, &mut node_map); } - let mut edges = Vec::with_capacity(dup_range.end - dup_range.start); + let mut edges = Vec::with_capacity(duplicates.len()); let mut dupes: HashMap<&str, Vec<_>> = HashMap::new(); - for duplicate in dup_range { - let dest = Node::from(&krates.krates[duplicate]); + for duplicate in duplicates { + let dest = Node::from(&krates.krates[*duplicate]); if let Some(id) = node_map.get(&dest) { let mut nodes = vec![*id]; @@ -677,6 +721,56 @@ where Ok(output) } +pub type Pid = cargo_metadata::PackageId; + +struct SkipRoot { + span: std::ops::Range, + skip_crates: Vec, + skip_hits: bitvec::vec::BitVec, +} + +use bitvec::prelude::*; + +fn build_skip_root( + ts: toml::Spanned, + krate: &crate::KrateDetails, + krates: &crate::Krates, +) -> SkipRoot { + let span = ts.start() as u32..ts.end() as u32; + let ts = ts.into_inner(); + + let max_depth = ts.depth.unwrap_or(std::usize::MAX); + + let mut pending = smallvec::SmallVec::<[(Pid, usize); 10]>::new(); + pending.push((krate.id.clone(), 0)); + + let mut skip_crates = Vec::with_capacity(10); + while let Some((pkg_id, depth)) = pending.pop() { + if depth < max_depth { + let node = &krates.resolved.nodes[krates + .resolved + .nodes + .binary_search_by(|n| n.id.cmp(&pkg_id)) + .unwrap()]; + for dep in &node.dependencies { + pending.push((dep.clone(), depth + 1)); + } + } + + if let Err(i) = skip_crates.binary_search(&pkg_id) { + skip_crates.insert(i, pkg_id); + } + } + + let skip_hits = bitvec![0; skip_crates.len()]; + + SkipRoot { + span, + skip_crates, + skip_hits, + } +} + pub struct DupGraph { pub duplicate: String, pub graph: String, @@ -724,7 +818,7 @@ where let lock_id = &lock_contents[cur_offset + krate_start + 10..cur_offset + krate_start + id_end - 1]; - // Git ids will can differ, but they have to start the same + // Git ids can differ, but they have to start the same if &krate.id.repr[..lock_id.len()] != lock_id { failure::bail!( "invalid metadata for package '{}' != '{}'", @@ -742,15 +836,114 @@ where cur_offset = cur_offset + krate_start + krate_end; } + struct TreeSkipper { + roots: Vec, + } + + // If trees are being skipped, walk each one down to the specified depth and add + // each dependency as a skipped crate at the specific version + let mut tree_skip = if !cfg.tree_skipped.is_empty() { + let roots: Vec<_> = cfg + .tree_skipped + .into_iter() + .filter_map(|ts| { + if let Ok(rng) = binary_search_by_name(&krates.krates, &ts.get_ref().id.name) { + for i in rng { + if ts.get_ref().id.version.matches(&krates.krates[i].version) { + let sr = build_skip_root(ts, &krates.krates[i], krates); + return Some(sr); + } + } + } + + None + }) + .collect(); + + Some(TreeSkipper { roots }) + } else { + None + }; + + let file_id = cfg.file_id; + + let mut check_root_filters = |krate: &crate::KrateDetails, diags: &mut Vec| { + if let Some(ref mut tree_skipper) = tree_skip { + let mut skip = false; + + for root in &mut tree_skipper.roots { + if let Ok(i) = root.skip_crates.binary_search(&krate.id) { + diags.push(Diagnostic::new( + Severity::Help, + format!("skipping crate {} = {}", krate.name, krate.version), + Label::new(file_id, root.span.clone(), "matched root filter"), + )); + + root.skip_hits.as_mut_bitslice().set(i, true); + skip = true; + } + } + + skip + } else { + false + } + }; + // Keep track of all the crates we skip, and emit a warning if // we encounter a skip that didn't actually match any crate version // so that people can clean up their config files - let mut skip_hit = vec![0; cfg.skipped.len()]; - let mut multi_detector = (&krates.as_ref()[0].name, 0); + let mut skip_hit = bitvec![0; cfg.skipped.len()]; + + struct MultiDetector<'a> { + name: &'a str, + dupes: smallvec::SmallVec<[usize; 2]>, + } + + let mut multi_detector = MultiDetector { + name: &krates.as_ref()[0].name, + dupes: smallvec::SmallVec::new(), + }; for (i, krate) in krates.iter().enumerate() { let mut diagnostics = Vec::new(); + if let Ok((_, ban)) = binary_search(&cfg.denied, krate) { + diagnostics.push(Diagnostic::new( + Severity::Error, + format!("detected banned crate {} = {}", krate.name, krate.version), + Label::new(cfg.file_id, ban.span.clone(), "matching ban entry"), + )); + } + + if !cfg.allowed.is_empty() { + // Since only allowing specific crates is pretty draconian, + // also emit which allow filters actually passed each crate + match binary_search(&cfg.allowed, krate) { + Ok((_, allow)) => { + diagnostics.push(Diagnostic::new( + Severity::Note, + format!("allowed {} = {}", krate.name, krate.version), + Label::new(cfg.file_id, allow.span.clone(), "matching allow entry"), + )); + } + Err(mut ind) => { + if ind >= cfg.allowed.len() { + ind = cfg.allowed.len() - 1; + } + + diagnostics.push(Diagnostic::new( + Severity::Error, + format!( + "detected crate not specifically allowed {} = {}", + krate.name, krate.version + ), + Label::new(cfg.file_id, cfg.allowed[ind].span.clone(), "closest match"), + )); + } + } + } + if let Ok((index, skip)) = binary_search(&cfg.skipped, krate) { diagnostics.push(Diagnostic::new( Severity::Help, @@ -761,12 +954,12 @@ where // Keep a count of the number of times each skip filter is hit // so that we can report unused filters to the user so that they // can cleanup their configs as their dependency graph changes over time - skip_hit[index] += 1; - } else { - if multi_detector.0 == &krate.name { - multi_detector.1 += 1; + skip_hit.as_mut_bitslice().set(index, true); + } else if !check_root_filters(krate, &mut diagnostics) { + if multi_detector.name == krate.name { + multi_detector.dupes.push(i); } else { - if multi_detector.1 > 1 && cfg.multiple_versions != LintLevel::Allow { + if multi_detector.dupes.len() > 1 && cfg.multiple_versions != LintLevel::Allow { let severity = match cfg.multiple_versions { LintLevel::Warn => Severity::Warning, LintLevel::Deny => Severity::Error, @@ -776,10 +969,10 @@ where let mut all_start = std::u32::MAX; let mut all_end = 0; - let mut dupes = Vec::with_capacity(multi_detector.1); + let mut dupes = Vec::with_capacity(multi_detector.dupes.len()); #[allow(clippy::needless_range_loop)] - for dup in i - multi_detector.1..i { + for dup in multi_detector.dupes.iter().cloned() { if let Some(ref span) = krate_spans[dup] { if span.start < all_start { all_start = span.start @@ -796,8 +989,9 @@ where diagnostics: vec![Diagnostic::new( severity, format!( - "duplicate #{} {} = {}", + "duplicate #{} ({}) {} = {}", dupes.len() + 1, + dup, krate.name, krate.version ), @@ -815,7 +1009,7 @@ where format!( "found {} duplicate entries for crate '{}'", dupes.len(), - multi_detector.0 + multi_detector.name ), Label::new(lock_id, all_start..all_end, "lock entries"), )], @@ -828,57 +1022,22 @@ where if let Some(ref og) = output_graph { let graph = create_graph( - multi_detector.0, + multi_detector.name, cfg.highlight, krates, - i - multi_detector.1..i, + &multi_detector.dupes, )?; og(DupGraph { - duplicate: multi_detector.0.to_owned(), + duplicate: multi_detector.name.to_owned(), graph, })?; } } - multi_detector.0 = &krate.name; - multi_detector.1 = 1; - } - - if let Ok((_, ban)) = binary_search(&cfg.denied, krate) { - diagnostics.push(Diagnostic::new( - Severity::Error, - format!("detected banned crate {} = {}", krate.name, krate.version), - Label::new(cfg.file_id, ban.span.clone(), "matching ban entry"), - )); - } - - if !cfg.allowed.is_empty() { - // Since only allowing specific crates is pretty draconian, - // also emit which allow filters actually passed each crate - match binary_search(&cfg.allowed, krate) { - Ok((_, allow)) => { - diagnostics.push(Diagnostic::new( - Severity::Note, - format!("allowed {} = {}", krate.name, krate.version), - Label::new(cfg.file_id, allow.span.clone(), "matching allow entry"), - )); - } - Err(mut ind) => { - if ind >= cfg.allowed.len() { - ind = cfg.allowed.len() - 1; - } - - diagnostics.push(Diagnostic::new( - Severity::Error, - format!( - "detected crate not specifically allowed {} = {}", - krate.name, krate.version - ), - Label::new(cfg.file_id, cfg.allowed[ind].span.clone(), "closest match"), - )); - } - } + multi_detector.name = &krate.name; + multi_detector.dupes.clear(); + multi_detector.dupes.push(i); } } @@ -892,15 +1051,15 @@ where } } - for (count, skip) in skip_hit.into_iter().zip(cfg.skipped.into_iter()) { - if count == 0 { + for (hit, skip) in skip_hit.into_iter().zip(cfg.skipped.into_iter()) { + if !hit { sender .send(crate::DiagPack { krate_id: None, diagnostics: vec![Diagnostic::new( Severity::Warning, "skipped crate was not encountered", - Label::new(cfg.file_id, skip.span, "no crate matches these criteria"), + Label::new(cfg.file_id, skip.span, "no crate matched these criteria"), )], }) .unwrap(); @@ -1128,4 +1287,138 @@ mod test { ) .is_err()); } + + #[test] + fn binary_search_by_name_() { + use crate::KrateDetails; + + macro_rules! kd { + ($name:expr, $vs:expr) => { + KrateDetails { + name: $name.to_owned(), + version: Version::parse($vs).unwrap(), + ..Default::default() + } + }; + } + + let krates = [ + kd!("adler32", "1.0.4"), + kd!("aho-corasick", "0.7.6"), + kd!("alsa-sys", "0.1.2"), + kd!("andrew", "0.2.1"), + kd!("android_glue", "0.2.3"), + kd!("ansi_term", "0.11.0"), + kd!("anyhow", "1.0.18"), + kd!("anymap", "0.12.1"), + kd!("app_dirs2", "2.0.4"), + kd!("approx", "0.3.2"), + kd!("arrayref", "0.3.5"), + kd!("arrayvec", "0.4.12"), + kd!("arrayvec", "0.5.1"), + kd!("ash", "0.29.0"), + kd!("ash-molten", "0.2.0+37"), + kd!("assert-json-diff", "1.0.1"), + kd!("async-stream", "0.1.2"), + kd!("async-stream-impl", "0.1.1"), + kd!("async-trait", "0.1.17"), + kd!("atk-sys", "0.6.0"), + kd!("atty", "0.2.13"), + kd!("autocfg", "0.1.7"), + kd!("backoff", "0.1.5"), + kd!("backtrace", "0.3.40"), + kd!("backtrace-sys", "0.1.32"), + kd!("base-x", "0.2.6"), + kd!("base64", "0.10.1"), + kd!("bincode", "1.2.0"), + kd!("bindgen", "0.51.1"), + kd!("bitflags", "1.2.1"), + kd!("core-foundation", "0.6.4"), + kd!("core-foundation-sys", "0.6.2"), + kd!("core-graphics", "0.17.3"), + kd!("coreaudio-rs", "0.9.1"), + kd!("coreaudio-sys", "0.2.3"), + kd!("crossbeam", "0.7.2"), + kd!("crossbeam-channel", "0.3.9"), + kd!("crossbeam-deque", "0.7.1"), + kd!("crossbeam-epoch", "0.7.2"), + kd!("crossbeam-queue", "0.1.2"), + kd!("crossbeam-utils", "0.6.6"), + kd!("hex", "0.3.2"), + kd!("hyper", "0.12.35"), + kd!("hyper", "0.13.0-alpha.4"), + kd!("hyper-rustls", "0.17.1"), + kd!("tokio", "0.1.22"), + kd!("tokio", "0.2.0-alpha.6"), + kd!("tokio-buf", "0.1.1"), + kd!("tokio-codec", "0.1.1"), + kd!("tokio-codec", "0.2.0-alpha.6"), + kd!("tokio-current-thread", "0.1.6"), + kd!("tokio-executor", "0.1.8"), + kd!("tokio-executor", "0.2.0-alpha.6"), + kd!("tokio-fs", "0.1.6"), + kd!("tokio-fs", "0.2.0-alpha.6"), + kd!("tokio-io", "0.1.12"), + kd!("tokio-io", "0.2.0-alpha.6"), + kd!("tokio-macros", "0.2.0-alpha.6"), + kd!("tokio-net", "0.2.0-alpha.6"), + kd!("tokio-reactor", "0.1.10"), + kd!("tokio-rustls", "0.10.2"), + kd!("tokio-sync", "0.1.7"), + kd!("tokio-sync", "0.2.0-alpha.6"), + kd!("tokio-tcp", "0.1.3"), + kd!("tokio-threadpool", "0.1.16"), + kd!("tokio-timer", "0.2.11"), + kd!("tokio-timer", "0.3.0-alpha.6"), + kd!("tokio-udp", "0.1.5"), + kd!("tokio-uds", "0.2.5"), + kd!("tonic", "0.1.0-alpha.4"), + kd!("tonic-build", "0.1.0-alpha.4"), + kd!("tower", "0.1.1"), + kd!("tower", "0.3.0-alpha.2"), + kd!("tower-balance", "0.3.0-alpha.2"), + kd!("tower-buffer", "0.1.2"), + kd!("tower-buffer", "0.3.0-alpha.2"), + kd!("tower-discover", "0.1.0"), + kd!("tower-discover", "0.3.0-alpha.2"), + kd!("tower-http-util", "0.1.0"), + kd!("tower-hyper", "0.1.1"), + kd!("tower-layer", "0.1.0"), + kd!("tower-layer", "0.3.0-alpha.2"), + kd!("tower-limit", "0.1.1"), + kd!("tower-limit", "0.3.0-alpha.2"), + kd!("tower-load", "0.3.0-alpha.2"), + kd!("tower-load-shed", "0.1.0"), + kd!("tower-load-shed", "0.3.0-alpha.2"), + kd!("tower-make", "0.3.0-alpha.2a"), + kd!("tower-reconnect", "0.3.0-alpha.2"), + kd!("tower-request-modifier", "0.1.0"), + kd!("tower-retry", "0.1.0"), + kd!("tower-retry", "0.3.0-alpha.2"), + kd!("tower-service", "0.2.0"), + kd!("tower-service", "0.3.0-alpha.2"), + kd!("tower-timeout", "0.1.1"), + kd!("tower-timeout", "0.3.0-alpha.2"), + kd!("tower-util", "0.1.0"), + kd!("tower-util", "0.3.0-alpha.2"), + kd!("tracing", "0.1.10"), + kd!("tracing-attributes", "0.1.5"), + kd!("tracing-core", "0.1.7"), + ]; + + assert_eq!(binary_search_by_name(&krates, "adler32",), Ok(0..1)); + assert_eq!( + binary_search_by_name(&krates, "tower-service",) + .unwrap() + .len(), + 2 + ); + assert_eq!(binary_search_by_name(&krates, "tracing",).unwrap().len(), 1); + assert_eq!( + binary_search_by_name(&krates, "tokio-codec",) + .unwrap() + .len(), + 2 + ); + } } From bf00d7ab58a336a81e44ab9d0cb37356a6252f65 Mon Sep 17 00:00:00 2001 From: Jake Shadle Date: Wed, 30 Oct 2019 18:13:58 +0100 Subject: [PATCH 4/4] Release 0.3.0 (#40) --- CHANGELOG.md | 7 +++++-- Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f92187ea..bf9edc7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [0.3.0] - 2019-10-30 ### Added -- Added `[license.copyleft]` config, which can be used to determine what happens when a copyleft license is encountered. +- Added `[licenses.copyleft]` config, which can be used to determine what happens when a copyleft license is encountered. - Added `[bans.skip-tree]` config, which can be used to skip entire subtrees of a dependency graph when considering duplicates ### Fixed @@ -66,7 +68,8 @@ Now each license has to be explicitly approved, either by listing them in `licen ### Added - Initial implementation release -[Unreleased]: https://github.com/EmbarkStudios/cargo-deny/compare/0.3.0-beta...HEAD +[Unreleased]: https://github.com/EmbarkStudios/cargo-deny/compare/0.3.0...HEAD +[0.3.0]: https://github.com/EmbarkStudios/cargo-deny/compare/0.3.0-beta...0.3.0 [0.3.0-beta]: https://github.com/EmbarkStudios/cargo-deny/compare/0.2.5...0.3.0-beta [0.2.5]: https://github.com/EmbarkStudios/cargo-deny/compare/0.2.4...0.2.5 [0.2.4]: https://github.com/EmbarkStudios/cargo-deny/compare/0.2.3...0.2.4 diff --git a/Cargo.lock b/Cargo.lock index 83529e31..9bd12a3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -114,7 +114,7 @@ dependencies = [ [[package]] name = "cargo-deny" -version = "0.3.0-beta" +version = "0.3.0" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "askalono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 50b0a0f9..c93342ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "cargo-deny" description = "Cargo plugin to help you manage large dependency graphs" repository = "https://github.com/EmbarkStudios/cargo-deny" -version = "0.3.0-beta" +version = "0.3.0" authors = ["Embark ", "Jake Shadle "] edition = "2018" license = "MIT OR Apache-2.0"