#!/usr/bin/env bash set -euo pipefail : "${CARGO:=cargo}" # A list of the licenses that we currently allow in our code. # # If a package supports multiple licenses (using OR), then we are okay # if it supports _any_ of these licenses. # # We don't currently do a good job of understanding AND, so # interesting license combinations that involve AND may need to be given # in quotes. RECOGNIZED_LICENSES=( Apache-2.0 BSD-2-Clause BSD-3-Clause CC0-1.0 ISC MIT MPL-2.0 Unicode-DFS-2016 Unlicense Zlib "(MIT OR Apache-2.0) AND Unicode-DFS-2016" ) # List of packages that don't list a license. NO_LICENSE=( # The license for "ring" is something like "ISC AND openssl AND # ssleay AND MIT"; the openssl license is not up-to-date with # modern openssl. It includes an advertising clause. :P # # See https://gitlab.torproject.org/tpo/core/arti/-/issues/493 for # our related ticket. ring # License appears to be ISC. webpki rustls-webpki ) containsElement () { local e match="$1" shift for e; do [[ "$e" == "$match" ]] && return 0; done return 1 } if ! $CARGO license --help >/dev/null; then echo "cargo-license is not installed!" echo echo "For reasonable results, run:" echo " cargo install cargo-license" exit 2 fi cd "$(dirname "$0")/.." # The caller might reasonably have set CARGO to something containing spaces. # So collect the output before we set IFS. output=$($CARGO license --all-features -t) problems=0 IFS=$'\n' for line in $output; do package=$(echo "$line" | cut -f1) licenses=$(echo "$line" | cut -f5) # skip the first line. if test "$package" = "name" && test "$licenses" = "license"; then continue; fi if test -z "$licenses"; then if ! containsElement "$package" "${NO_LICENSE[@]}"; then echo "$package has no license" problems=1 fi continue fi found_ok=0 if containsElement "$licenses" "${RECOGNIZED_LICENSES[@]}"; then found_ok=1 else # TODO: By Splitting on "OR" without parsing, this can give bogus # elements in the output if the license is something like "(A OR # B) AND C". Fortunately the parenthesis will save us from false # negatives here, but in the end we should probably switch to a # real parser. for lic in ${licenses// OR /$'\n'}; do if containsElement "$lic" "${RECOGNIZED_LICENSES[@]}"; then found_ok=1 break fi done fi if test $found_ok = "0"; then echo "$package does not advertise any supported license!" echo " ($package: $licenses)" problems=1 fi done if test "$problems" = 1; then echo "You can suppress the above warnings by editing $0..." echo "but only do so if we are actually okay with all the licenses!" fi exit "$problems"