| 
									
										
										
										
											2016-11-12 12:38:16 +00:00
										 |  |  | #!/bin/bash | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | shopt -s extglob | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | array_build() { | 
					
						
							|  |  |  |   local dest=$1 src=$2 i keys values | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # it's an error to try to copy a value which doesn't exist. | 
					
						
							|  |  |  |   declare -p "$2" &>/dev/null || return 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Build an array of the indicies of the source array. | 
					
						
							|  |  |  |   eval "keys=(\"\${!$2[@]}\")" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Clear the destination array | 
					
						
							|  |  |  |   eval "$dest=()" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Read values indirectly via their index. This approach gives us support | 
					
						
							|  |  |  |   # for associative arrays, sparse arrays, and empty strings as elements. | 
					
						
							|  |  |  |   for i in "${keys[@]}"; do | 
					
						
							|  |  |  |     values+=("printf -v '$dest[$i]' %s \"\${$src[$i]}\";") | 
					
						
							|  |  |  |   done | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   eval "${values[*]}" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | funcgrep() { | 
					
						
							|  |  |  |   { declare -f "$1" || declare -f package; } 2>/dev/null | grep -E "$2" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-12 13:05:02 +00:00
										 |  |  | # extract_global_var function compatible with bash 4.2 | 
					
						
							| 
									
										
										
										
											2016-11-12 12:38:16 +00:00
										 |  |  | extract_global_var() { | 
					
						
							| 
									
										
										
										
											2016-11-12 13:05:02 +00:00
										 |  |  | 	# $1: variable name | 
					
						
							|  |  |  | 	# $2: multivalued | 
					
						
							|  |  |  | 	# $3: name of output var | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	local attr=$1 isarray=$2 outputvar=$3 ref | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (( isarray )); then | 
					
						
							|  |  |  | 		array_build ref "$attr" | 
					
						
							|  |  |  | 		[[ ${ref[@]} ]] && array_build "$outputvar" "$attr" | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		[[ ${!attr} ]] && printf -v "$outputvar" %s "${!attr}" | 
					
						
							|  |  |  | 	fi | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # extract global_var function compatible with bash 4.3+ | 
					
						
							|  |  |  | old_extract_global_var() { | 
					
						
							| 
									
										
										
										
											2016-11-12 12:38:16 +00:00
										 |  |  |   # $1: variable name | 
					
						
							|  |  |  |   # $2: multivalued | 
					
						
							|  |  |  |   # $3: name of output var | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   local attr=$1 isarray=$2 outputvar=$3 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (( isarray )); then | 
					
						
							|  |  |  |     declare -n ref=$attr | 
					
						
							|  |  |  |     # Still need to use array_build here because we can't handle the scoping | 
					
						
							|  |  |  |     # semantics that would be included with the use of 'declare -n'. | 
					
						
							|  |  |  |     [[ ${ref[@]} ]] && array_build "$outputvar" "$attr" | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     [[ ${!attr} ]] && printf -v "$outputvar" %s "${!attr}" | 
					
						
							|  |  |  |   fi | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extract_function_var() { | 
					
						
							|  |  |  |   # $1: function name | 
					
						
							|  |  |  |   # $2: variable name | 
					
						
							|  |  |  |   # $3: multivalued | 
					
						
							|  |  |  |   # $4: name of output var | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   local funcname=$1 attr=$2 isarray=$3 outputvar=$4 attr_regex= decl= r=1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (( isarray )); then | 
					
						
							|  |  |  |     printf -v attr_regex '^[[:space:]]* %s\+?=\(' "$2" | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     printf -v attr_regex '^[[:space:]]* %s\+?=[^(]' "$2" | 
					
						
							|  |  |  |   fi | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while read -r; do | 
					
						
							|  |  |  |     # strip leading whitespace and any usage of declare | 
					
						
							|  |  |  |     decl=${REPLY##*([[:space:]])} | 
					
						
							|  |  |  |     eval "${decl/#$attr/$outputvar}" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # entering this loop at all means we found a match, so notify the caller. | 
					
						
							|  |  |  |     r=0 | 
					
						
							|  |  |  |   done < <(funcgrep "$funcname" "$attr_regex") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return $r | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | pkgbuild_get_attribute() { | 
					
						
							|  |  |  |   # $1: package name | 
					
						
							|  |  |  |   # $2: attribute name | 
					
						
							|  |  |  |   # $3: multivalued | 
					
						
							|  |  |  |   # $4: name of output var | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   local pkgname=$1 attrname=$2 isarray=$3 outputvar=$4 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   printf -v "$outputvar" %s '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if [[ $pkgname ]]; then | 
					
						
							|  |  |  |     extract_global_var "$attrname" "$isarray" "$outputvar" | 
					
						
							|  |  |  |     extract_function_var "package_$pkgname" "$attrname" "$isarray" "$outputvar" | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     extract_global_var "$attrname" "$isarray" "$outputvar" | 
					
						
							|  |  |  |   fi | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | srcinfo_open_section() { | 
					
						
							|  |  |  |   printf '%s = %s\n' "$1" "$2" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | srcinfo_close_section() { | 
					
						
							|  |  |  |   echo | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | srcinfo_write_attr() { | 
					
						
							|  |  |  |   # $1: attr name | 
					
						
							|  |  |  |   # $2: attr values | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   local attrname=$1 attrvalues=("${@:2}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # normalize whitespace, strip leading and trailing | 
					
						
							|  |  |  |   attrvalues=("${attrvalues[@]//+([[:space:]])/ }") | 
					
						
							|  |  |  |   attrvalues=("${attrvalues[@]#[[:space:]]}") | 
					
						
							|  |  |  |   attrvalues=("${attrvalues[@]%[[:space:]]}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   printf "\t$attrname = %s\n" "${attrvalues[@]}" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | pkgbuild_extract_to_srcinfo() { | 
					
						
							|  |  |  |   # $1: pkgname | 
					
						
							|  |  |  |   # $2: attr name | 
					
						
							|  |  |  |   # $3: multivalued | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   local pkgname=$1 attrname=$2 isarray=$3 outvalue= | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if pkgbuild_get_attribute "$pkgname" "$attrname" "$isarray" 'outvalue'; then | 
					
						
							|  |  |  |     srcinfo_write_attr "$attrname" "${outvalue[@]}" | 
					
						
							|  |  |  |   fi | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | srcinfo_write_section_details() { | 
					
						
							|  |  |  |   local attr package_arch a | 
					
						
							|  |  |  |   local multivalued_arch_attrs=(source provides conflicts depends replaces | 
					
						
							|  |  |  |                                 optdepends makedepends checkdepends | 
					
						
							|  |  |  |                                 {md5,sha{1,224,256,384,512}}sums) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for attr in "${singlevalued[@]}"; do | 
					
						
							|  |  |  |     pkgbuild_extract_to_srcinfo "$1" "$attr" 0 | 
					
						
							|  |  |  |   done | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for attr in "${multivalued[@]}"; do | 
					
						
							|  |  |  |     pkgbuild_extract_to_srcinfo "$1" "$attr" 1 | 
					
						
							|  |  |  |   done | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   pkgbuild_get_attribute "$1" 'arch' 1 'package_arch' | 
					
						
							|  |  |  |   for a in "${package_arch[@]}"; do | 
					
						
							|  |  |  |     # 'any' is special. there's no support for, e.g. depends_any. | 
					
						
							|  |  |  |     [[ $a = any ]] && continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for attr in "${multivalued_arch_attrs[@]}"; do | 
					
						
							|  |  |  |       pkgbuild_extract_to_srcinfo "$1" "${attr}_$a" 1 | 
					
						
							|  |  |  |     done | 
					
						
							|  |  |  |   done | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | srcinfo_write_global() { | 
					
						
							|  |  |  |   local singlevalued=(pkgdesc pkgver pkgrel epoch url install changelog) | 
					
						
							|  |  |  |   local multivalued=(arch groups license checkdepends makedepends | 
					
						
							|  |  |  |                      depends optdepends provides conflicts replaces | 
					
						
							|  |  |  |                      noextract options backup | 
					
						
							|  |  |  |                      source {md5,sha{1,224,256,384,512}}sums) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   srcinfo_open_section 'pkgbase' "${pkgbase:-$pkgname}" | 
					
						
							|  |  |  |   srcinfo_write_section_details '' | 
					
						
							|  |  |  |   srcinfo_close_section | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | srcinfo_write_package() { | 
					
						
							|  |  |  |   local singlevalued=(pkgdesc url install changelog) | 
					
						
							|  |  |  |   local multivalued=(arch groups license checkdepends depends optdepends | 
					
						
							|  |  |  |                      provides conflicts replaces options backup) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   srcinfo_open_section 'pkgname' "$1" | 
					
						
							|  |  |  |   srcinfo_write_section_details "$1" | 
					
						
							|  |  |  |   srcinfo_close_section | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | srcinfo_write() { | 
					
						
							|  |  |  |   local pkg | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   srcinfo_write_global | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for pkg in "${pkgname[@]}"; do | 
					
						
							|  |  |  |     srcinfo_write_package "$pkg" | 
					
						
							|  |  |  |   done | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | clear_environment() { | 
					
						
							|  |  |  |   local environ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mapfile -t environ < <(compgen -A variable | | 
					
						
							|  |  |  |       grep -xvF "$(printf '%s\n' "$@")") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # expect that some variables marked read only will complain here | 
					
						
							|  |  |  |   unset -v "${environ[@]}" 2>/dev/null | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | srcinfo_write_from_pkgbuild() {( | 
					
						
							|  |  |  |   clear_environment PATH | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   shopt -u extglob | 
					
						
							|  |  |  |   . "$1" || exit 1 | 
					
						
							|  |  |  |   shopt -s extglob | 
					
						
							|  |  |  |   srcinfo_write | 
					
						
							|  |  |  | )} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | usage() { | 
					
						
							|  |  |  |   printf '%s\n' \ | 
					
						
							|  |  |  |       'mksrcinfo v8' \ | 
					
						
							|  |  |  |       '' \ | 
					
						
							|  |  |  |       'mksrcinfo reads the target PKGBUILD and writes an equivalent .SRCINFO.' \ | 
					
						
							|  |  |  |       'Without passing any arguments, mksrcinfo will read from $PWD/PKGBUILD' \ | 
					
						
							|  |  |  |       'and write to $PWD/.SRCINFO.' \ | 
					
						
							|  |  |  |       '' \ | 
					
						
							|  |  |  |       'Usage: mksrcinfo [/path/to/pkgbuild]' \ | 
					
						
							|  |  |  |       '    -h                display this help message and exit' \ | 
					
						
							|  |  |  |       '    -o <file>         write output to <file>' | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | error() { | 
					
						
							|  |  |  |   printf "==> ERROR: $1\n" "${@:2}" >&2 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | die() { | 
					
						
							|  |  |  |   error "$@" | 
					
						
							|  |  |  |   exit 1 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | write_srcinfo_header() { | 
					
						
							|  |  |  |   local timefmt='%a %b %e %H:%M:%S %Z %Y' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # fiddle with the environment to ensure we get the a consistent language and | 
					
						
							|  |  |  |   # timezone. | 
					
						
							|  |  |  |   TZ=UTC LC_TIME=C \ | 
					
						
							|  |  |  |     printf "# Generated by mksrcinfo %s\n# %($timefmt)T\n" 'v8' -1 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | srcinfo_dest=$PWD/.SRCINFO | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | while getopts ':o:h' flag; do | 
					
						
							|  |  |  |   case $flag in | 
					
						
							|  |  |  |     o) | 
					
						
							|  |  |  |       srcinfo_dest=$OPTARG | 
					
						
							|  |  |  |       ;; | 
					
						
							|  |  |  |     :) | 
					
						
							|  |  |  |       die "option '-%s' requires an argument" "$OPTARG" | 
					
						
							|  |  |  |       ;; | 
					
						
							|  |  |  |     h) | 
					
						
							|  |  |  |       usage | 
					
						
							|  |  |  |       exit 0 | 
					
						
							|  |  |  |       ;; | 
					
						
							|  |  |  |     \?) | 
					
						
							|  |  |  |       die "invalid option -- '-%s' (use -h for help)" "$OPTARG" | 
					
						
							|  |  |  |       ;; | 
					
						
							|  |  |  |   esac | 
					
						
							|  |  |  | done | 
					
						
							|  |  |  | shift $(( OPTIND - 1 )) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [[ -f PKGBUILD ]] || die 'PKGBUILD not found in current directory' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # TODO: replace this with 'makepkg --printsrcinfo' once makepkg>=4.3 is released. | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   write_srcinfo_header | 
					
						
							|  |  |  |   srcinfo_write_from_pkgbuild "${1:-$PWD/PKGBUILD}" | 
					
						
							|  |  |  | } >"$srcinfo_dest" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # vim: set et ts=2 sw=2: |