#!/bin/sh # Constants PRGN="${0##*/}" LICENSOR_CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/licensor" # Configuration : "${LICENSE_REPO_VERSION:=3.17}" : "${LICENSE_REPO_URL:=https://github.com/spdx/license-list-data/archive/refs/tags/v$LICENSE_REPO_VERSION.tar.gz}" : "${LICENSE_REPO_PATH:=license-list-data-$LICENSE_REPO_VERSION/template}" : "${LICENSOR_LICENSE:=MIT}" : "${LICENSOR_OUTPUT_FILE:=COPYING}" usage() { cat < ". -w WIDTH Fold the output to WIDTH characters. Default: $__width. -o FILE Output the fetched license to FILE. Default: \$PWD/$LICENSOR_OUTPUT_FILE. PARAMETERS: LICENSE The license to use. Default: $LICENSOR_LICENSE. EOF exit ${1:-0} } main() { _force=false _quiet=false _fold=1 _optional=0 __width=70 __output="$LICENSOR_OUTPUT_FILE" __year="$(date +%Y)" __author="$(guess_author)" __email="$(guess_email)" _converter=license_convert while getopts hlLrs:fzZpPqy:a:e:o:w:c: opt; do case "$opt" in # commands h) usage ;; l) list_licenses && exit || exit $? ;; L) list_licenses -f && exit || exit $? ;; r) _converter=lcat ;; s) search_licenses "$OPTARG" ;; # flags f) _force=true ;; z) _fold=1 ;; Z) _fold=0 ;; p) _optional=1 ;; P) _optional=0 ;; q) _quiet=true ;; # options y) __year="$OPTARG" ;; a) __author="$OPTARG" ;; e) __email="$OPTARG" ;; o) __output="$OPTARG" ;; w) __width="$OPTARG" ;; c) __copyright="$OPTARG" ;; *) usage 1 ;; esac done shift $((OPTIND - 1)) __license="${1:-$LICENSOR_LICENSE}" if [ -e "$__output" ] && ! $_force; then log "File exists: $__output" exit 3 fi if [ "x$__output" = x- ]; then __output=/dev/stdout fi if [ -z "$__copyright" ]; then __copyright="Copyright (C) $__year $__author <$__email>" fi license_file="$(get_license "$__license")" || exit $? $_converter <"$LICENSOR_CACHE/$license_file.template.txt" \ "$__copyright" "$_optional" "$_fold" "$__width" >"$__output" [ "$__output" != /dev/stdout ] && log "$__license license written to $__output." } lcat() { set -- cat } get_licenses() { # Get licenses from cache, or download them if ! [ -d "$LICENSOR_CACHE" ] || [ "x$1" = "x-f" ]; then log "Downlading licenses from $LICENSE_REPO_URL..." mkdir -p "$LICENSOR_CACHE" tmpfile="/tmp/licenses.tar.gz" if ! [ -f "$tmpfile" ]; then curl -o "$tmpfile" -L "$LICENSE_REPO_URL" >/dev/null 2>&1 || return 1 fi log "Extracting licenses to $LICENSOR_CACHE..." if tar -C "$LICENSOR_CACHE" \ -xvf "$tmpfile" --strip-components=2 \ "$LICENSE_REPO_PATH" >/dev/null 2>&1; then rm "$tmpfile" else return 1 fi fi } get_license() { list_licenses | grep -iE '^'"$1"'$' || { log "Can't find license \"$1\"." exit 1 } } list_licenses() { get_licenses "$1" || exit 1 find "$LICENSOR_CACHE" -iname '*.template.txt' | sort | xargs basename -s .template.txt } search_licenses() { list_licenses | grep -iE "$1" exit $? } guess_author() { author="$(git config --get user.name)" if [ -z "$author" ]; then author="$(getent passwd "$USER" | awk -F: '{sub(/,+/,"",$5);print $5}')" fi if [ -z "$author" ]; then author="$USER"; fi put "$author" } guess_email() { email="$(git config --get user.email)" put "$email" } put() { printf '%s\n' "$*"; } log() { $_quiet || put "$PRGN: $*" >&2; } license_convert() { copyright="$1" show_optional="${2:-0}" fold_output="${3:-1}" fold_width="${4:-70}" awk 'BEGIN { foldOutput = '"$fold_output"' foldWidth = '"$fold_width"' showOptional = '"$show_optional"' FIELDS["copyright"] = "'"$copyright"'" optional = 0 buffer = "" begOptRx = showOptional ? "<]*>>" : "<]*>>.*" endOptRx = showOptional ? "<]*>>" : ".*<]*>>" } /<>/ { match($0, /<>/) split(substr($0, RSTART + 6, RLENGTH - 8), _rule, ";") for (r in _rule) { key = substr(_rule[r], 1, index(_rule[r], "=") - 1) val = substr(_rule[r], index(_rule[r], "=") + 1) rule[key] = val } for (r in rule) { quoted = match(rule[r], /^".*"$/) if (quoted) { rule[r] = substr(rule[r], RSTART + 1, RLENGTH - 2) } # print r, rule[r] } name = rule["name"] # print FIELDS[name] sub(/<>/, (FIELDS[name] ? FIELDS[name] : rule["original"]), $0) } /<>/ { optional = 1 if (match($0,/<>.*<>/)) { optional = 0 if (! showOptional) { sub(/<>.*<>/, "", $0) } } sub(begOptRx, "", $0) } /<>/ { sub(endOptRx, "", $0) optional = 0 } optional && ! showOptional { next } { bufput() } END { # "Fold" the output if (foldOutput) { buffer = fold(buffer, foldWidth) } print buffer } function bufput(str, sep) { buffer = buffer (buffer ? (sep ? sep : "\n") : "") (str ? str : $0) } function fold(out, foldWidth) { split(out, oa, "\n") out = "" for (l in oa) { split(oa[l], la, FS) lc = 0 for (w in la) { lc += length(la[w]) + 1 if (lc >= foldWidth) { out = out "\n" la[w] " " lc = length(la[w]) + 1 } else { out = out la[w] " " } } out = out "\n" } return out } ' } main "$@"