at 18.09-beta 153 lines 5.5 kB view raw
1# Assert that FILE exists and is executable 2# 3# assertExecutable FILE 4assertExecutable() { 5 local file="$1" 6 [[ -f "$file" && -x "$file" ]] || \ 7 die "Cannot wrap '$file' because it is not an executable file" 8} 9 10# construct an executable file that wraps the actual executable 11# makeWrapper EXECUTABLE ARGS 12 13# ARGS: 14# --argv0 NAME : set name of executed process to NAME 15# (otherwise it’s called …-wrapped) 16# --set VAR VAL : add VAR with value VAL to the executable’s 17# environment 18# --set-default VAR VAL : like --set, but only adds VAR if not already set in 19# the environment 20# --unset VAR : remove VAR from the environment 21# --run COMMAND : run command before the executable 22# The command can push extra flags to a magic list 23# variable extraFlagsArray, which are then added to 24# the invocation of the executable 25# --add-flags FLAGS : add FLAGS to invocation of executable 26 27# --prefix ENV SEP VAL : suffix/prefix ENV with VAL, separated by SEP 28# --suffix 29# --suffix-each ENV SEP VALS : like --suffix, but VALS is a list 30# --prefix-contents ENV SEP FILES : like --suffix-each, but contents of FILES 31# are read first and used as VALS 32# --suffix-contents 33makeWrapper() { 34 local original="$1" 35 local wrapper="$2" 36 local params varName value command separator n fileNames 37 local argv0 flagsBefore flags 38 39 assertExecutable "$original" 40 41 mkdir -p "$(dirname "$wrapper")" 42 43 echo "#! $SHELL -e" > "$wrapper" 44 45 params=("$@") 46 for ((n = 2; n < ${#params[*]}; n += 1)); do 47 p="${params[$n]}" 48 49 if [[ "$p" == "--set" ]]; then 50 varName="${params[$((n + 1))]}" 51 value="${params[$((n + 2))]}" 52 n=$((n + 2)) 53 echo "export $varName=${value@Q}" >> "$wrapper" 54 elif [[ "$p" == "--set-default" ]]; then 55 varName="${params[$((n + 1))]}" 56 value="${params[$((n + 2))]}" 57 n=$((n + 2)) 58 echo "export $varName=\${$varName-${value@Q}}" >> "$wrapper" 59 elif [[ "$p" == "--unset" ]]; then 60 varName="${params[$((n + 1))]}" 61 n=$((n + 1)) 62 echo "unset $varName" >> "$wrapper" 63 elif [[ "$p" == "--run" ]]; then 64 command="${params[$((n + 1))]}" 65 n=$((n + 1)) 66 echo "$command" >> "$wrapper" 67 elif [[ ("$p" == "--suffix") || ("$p" == "--prefix") ]]; then 68 varName="${params[$((n + 1))]}" 69 separator="${params[$((n + 2))]}" 70 value="${params[$((n + 3))]}" 71 n=$((n + 3)) 72 if test -n "$value"; then 73 if test "$p" = "--suffix"; then 74 echo "export $varName=\$$varName\${$varName:+${separator@Q}}${value@Q}" >> "$wrapper" 75 else 76 echo "export $varName=${value@Q}\${$varName:+${separator@Q}}\$$varName" >> "$wrapper" 77 fi 78 fi 79 elif [[ "$p" == "--suffix-each" ]]; then 80 varName="${params[$((n + 1))]}" 81 separator="${params[$((n + 2))]}" 82 values="${params[$((n + 3))]}" 83 n=$((n + 3)) 84 for value in $values; do 85 echo "export $varName=\$$varName\${$varName:+$separator}${value@Q}" >> "$wrapper" 86 done 87 elif [[ ("$p" == "--suffix-contents") || ("$p" == "--prefix-contents") ]]; then 88 varName="${params[$((n + 1))]}" 89 separator="${params[$((n + 2))]}" 90 fileNames="${params[$((n + 3))]}" 91 n=$((n + 3)) 92 for fileName in $fileNames; do 93 contents="$(cat "$fileName")" 94 if test "$p" = "--suffix-contents"; then 95 echo "export $varName=\$$varName\${$varName:+$separator}${contents@Q}" >> "$wrapper" 96 else 97 echo "export $varName=${contents@Q}\${$varName:+$separator}\$$varName" >> "$wrapper" 98 fi 99 done 100 elif [[ "$p" == "--add-flags" ]]; then 101 flags="${params[$((n + 1))]}" 102 n=$((n + 1)) 103 flagsBefore="$flagsBefore $flags" 104 elif [[ "$p" == "--argv0" ]]; then 105 argv0="${params[$((n + 1))]}" 106 n=$((n + 1)) 107 else 108 die "makeWrapper doesn't understand the arg $p" 109 fi 110 done 111 112 # Note: extraFlagsArray is an array containing additional flags 113 # that may be set by --run actions. 114 # Silence warning about unexpanded extraFlagsArray: 115 # shellcheck disable=SC2016 116 echo exec ${argv0:+-a \"$argv0\"} \""$original"\" \ 117 "$flagsBefore" '"${extraFlagsArray[@]}"' '"$@"' >> "$wrapper" 118 119 chmod +x "$wrapper" 120} 121 122addSuffix() { 123 suffix="$1" 124 shift 125 for name in "$@"; do 126 echo "$name$suffix" 127 done 128} 129 130filterExisting() { 131 for fn in "$@"; do 132 if test -e "$fn"; then 133 echo "$fn" 134 fi 135 done 136} 137 138# Syntax: wrapProgram <PROGRAM> <MAKE-WRAPPER FLAGS...> 139wrapProgram() { 140 local prog="$1" 141 local hidden 142 143 assertExecutable "$prog" 144 145 hidden="$(dirname "$prog")/.$(basename "$prog")"-wrapped 146 while [ -e "$hidden" ]; do 147 hidden="${hidden}_" 148 done 149 mv "$prog" "$hidden" 150 # Silence warning about unexpanded $0: 151 # shellcheck disable=SC2016 152 makeWrapper "$hidden" "$prog" --argv0 '$0' "${@:2}" 153}