diff options
Diffstat (limited to 'tools/build-license-metadata.sh')
-rwxr-xr-x | tools/build-license-metadata.sh | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/tools/build-license-metadata.sh b/tools/build-license-metadata.sh new file mode 100755 index 0000000000..a138dbe7c4 --- /dev/null +++ b/tools/build-license-metadata.sh @@ -0,0 +1,313 @@ +#!/bin/sh + +set -u + +ME=$(basename $0) + +USAGE="Usage: ${ME} {options} + +Builds a license metadata specification and outputs it to stdout or {outfile}. + +The available options are: + +-k kind... license kinds +-c condition... license conditions +-p package... license package name +-n notice... license notice file +-d dependency... license metadata file dependency +-t target... targets +-m target:installed... map dependent targets to their installed names +-is_container preserved dependent target name when given +-o outfile output file +" + +# Global flag variables +license_kinds= +license_conditions= +license_package_name= +license_notice= +license_deps= +targets= +installmap= +is_container=false +ofile= + +# Global variables +depfiles=" " +effective_conditions= + + +# Exits with a message. +# +# When the exit status is 2, assumes a usage error and outputs the usage message +# to stderr before outputting the specific error message to stderr. +# +# Parameters: +# Optional numeric exit status (defaults to 2, i.e. a usage error.) +# Remaining args treated as an error message sent to stderr. +die() { + lstatus=2 + case "${1:-}" in *[^0-9]*) ;; *) lstatus="$1"; shift ;; esac + case "${lstatus}" in 2) echo "${USAGE}" >&2; echo >&2 ;; esac + if [ -n "$*" ]; then + echo -e "$*\n" >&2 + fi + exit $lstatus +} + + +# Sets the flag variables based on the command-line. +# +# invoke with: process_args "$@" +process_args() { + lcurr_flag= + while [ "$#" -gt '0' ]; do + case "${1}" in + -h) + echo "${USAGE}" + exit 0 + ;; + -k) + lcurr_flag=kind + ;; + -c) + lcurr_flag=condition + ;; + -p) + lcurr_flag=package + ;; + -n) + lcurr_flag=notice + ;; + -d) + lcurr_flag=dependency + ;; + -t) + lcurr_flag=target + ;; + -m) + lcurr_flag=installmap + ;; + -o) + lcurr_flag=ofile + ;; + -is_container) + lcurr_flag= + is_container=true + ;; + -*) + die "Unknown flag: \"${1}\"" + ;; + *) + case "${lcurr_flag}" in + kind) + license_kinds="${license_kinds}${license_kinds:+ }${1}" + ;; + condition) + license_conditions="${license_conditions}${license_conditions:+ }${1}" + ;; + package) + license_package_name="${license_package_name}${license_package_name:+ }${1}" + ;; + notice) + license_notice="${license_notice}${license_notice:+ }${1}" + ;; + dependency) + license_deps="${license_deps}${license_deps:+ }${1}" + ;; + target) + targets="${targets}${targets:+ }${1}" + ;; + installmap) + installmap="${installmap}${installmap:+ }${1}" + ;; + ofile) + if [ -n "${ofile}" ]; then + die "Output file -o appears twice as \"${ofile}\" and \"${1}\"" + fi + ofile="${1}" + ;; + *) + die "Must precede argument \"${1}\" with type flag." + ;; + esac + ;; + esac + shift + done +} + +# Reads a license metadata file from stdin, and outputs the named dependencies. +# +# No parameters. +extract_deps() { + awk '$1 == "dep_name:" { sub(/^"/, "", $2); sub(/"$/, "", $2); print $2; }' +} + +# Populates the depfiles variable identifying dependency files. +# +# Starting with the dependencies enumerated in license_deps, calculates the +# transitive closure of all dependencies. +# +# Dependency names ending in .meta_module indirectly reference license +# metadata with 1 license metadata filename per line. +# +# No parameters; no output. +read_deps() { + lnewdeps= + for d in ${license_deps}; do + case "${d}" in + *.meta_module) + lnewdeps="${lnewdeps}${lnewdeps:+ }"$(cat "${d}") ;; + *) + lnewdeps="${lnewdeps}${lnewdeps:+ }${d}" ;; + esac + done + lnewdeps=$(echo "${lnewdeps}" | tr ' ' '\n' | sort -u) + lalldeps= + ldeps= + lmod= + ldep= + while [ "${#lnewdeps}" -gt '0' ]; do + ldeps="${lnewdeps}" + lnewdeps= + for ldep in ${ldeps}; do + depfiles="${depfiles}${ldep} " + lalldeps="${lalldeps}${lalldeps:+ }"$(cat "${ldep}" | extract_deps) + done + lalldeps=$(for d in ${lalldeps}; do echo "${d}"; done | sort -u) + for d in ${lalldeps}; do + ldeps="${d}" + case "${d}" in *.meta_module) ldeps=$(cat "${d}") ;; esac + for lmod in ${ldeps}; do + if ! expr "${depfiles}" : ".* ${lmod} .*" >/dev/null 2>&1; then + lnewdeps="${lnewdeps}${lnewdeps:+ }${lmod}" + fi + done + done + lalldeps= + done +} + +# Returns the effective license conditions for the current license metadata. +# +# If a module is restricted or links in a restricted module, the effective +# license has a restricted condition. +calculate_effective_conditions() { + lconditions="${license_conditions}" + case "${license_conditions}" in + *restricted*) : do nothing ;; + *) + for d in ${depfiles}; do + if cat "${d}" | egrep -q 'effective_condition\s*:.*restricted' ; then + lconditions="${lconditions}${lconditions:+ }restricted" + break + fi + done + ;; + esac + echo "${lconditions}" +} + + +process_args "$@" + +if [ -n "${ofile}" ]; then + # truncate the output file before appending results + : >"${ofile}" +else + ofile=/dev/stdout +fi + +# spit out the license metadata file content +( + echo 'license_package_name: "'${license_package_name}'"' + for kind in ${license_kinds}; do + echo 'license_kind: "'${kind}'"' + done + for condition in ${license_conditions}; do + echo 'license_condition: "'${condition}'"' + done + for f in ${license_notice}; do + echo 'license_text: "'${f}'"' + done + echo "is_container: ${is_container}" + for t in ${targets}; do + echo 'target: "'${t}'"' + done + for m in ${installmap}; do + echo 'install_map: "'${m}'"' + done +) >>"${ofile}" +read_deps +effective_conditions=$(calculate_effective_conditions) +for condition in ${effective_conditions}; do + echo 'effective_condition: "'${condition}'"' +done >>"${ofile}" +for dep in ${depfiles}; do + echo 'dep {' + cat "${dep}" | \ + awk -v name="${dep}" ' + function strip_type() { + $1 = "" + sub(/^\s*/, "") + } + BEGIN { + print " dep_name: " name + } + $1 == "license_package_name:" { + strip_type() + print " dep_package_name: "$0 + } + $1 == "dep_name:" { + print " dep_sub_dep: "$2 + } + $1 == "license_kind:" { + print " dep_license_kind: "$2 + } + $1 == "license_condition:" { + print " dep_license_condition: "$2 + } + $1 == "is_container:" { + print " dep_is_container: "$2 + } + $1 == "license_text:" { + strip_type() + print " dep_license_text: "$0 + } + $1 == "target:" { + print " dep_target: "$2 + } + $1 == "install_map:" { + print " dep_install_map: "$2 + } + ' + # The restricted license kind is contagious to all linked dependencies. + dep_conditions=$(echo $( + cat "${dep}" | awk ' + $1 == "effective_condition:" { + $1 = "" + sub(/^\s*/, "") + gsub(/"/, "") + print + } + ' + )) + for condition in ${dep_conditions}; do + echo ' dep_effective_condition: "'${condition}'"' + done + if ! ${is_container}; then + case "${dep_conditions}" in + *restricted*) : already restricted -- nothing to inherit ;; + *) + case "${effective_conditions}" in + *restricted*) + # "contagious" restricted infects everything linked to restricted + echo ' dep_effective_condition: "restricted"' + ;; + esac + ;; + esac + fi + echo '}' +done >>"${ofile}" |