|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +# Mason Client Version 1.0.0 |
| 4 | + |
| 5 | +# See below for `set -euo pipefail` |
| 6 | + |
| 7 | +# Print file + line number when not in CLI mode |
| 8 | +if [[ "$0" != "$BASH_SOURCE" ]]; then |
| 9 | +function mason_error { |
| 10 | + local _LINE _FN _FILE |
| 11 | + read _LINE _FN _FILE <<< "`caller 1`" |
| 12 | + if [ -t 1 ]; then |
| 13 | + >&2 echo -e "\033[1m\033[31m$@ in ${_FILE} on line ${_LINE}\033[0m" |
| 14 | + else |
| 15 | + >&2 echo "$@ in ${_FILE} on line ${_LINE}" |
| 16 | + fi |
| 17 | +} |
| 18 | +else |
| 19 | +function mason_error { |
| 20 | + if [ -t 1 ]; then |
| 21 | + >&2 echo -e "\033[1m\033[31m$@\033[0m" |
| 22 | + else |
| 23 | + >&2 echo "$@" |
| 24 | + fi |
| 25 | +} |
| 26 | +fi |
| 27 | + |
| 28 | +function mason_info { |
| 29 | + if [ -t 1 ]; then |
| 30 | + >&2 echo -e "\033[1m\033[36m$@\033[0m" |
| 31 | + else |
| 32 | + >&2 echo "$@" |
| 33 | + fi |
| 34 | +} |
| 35 | + |
| 36 | +function mason_detect_platform { |
| 37 | + # Determine platform |
| 38 | + if [[ -z "${MASON_PLATFORM:-}" ]]; then |
| 39 | + if [[ "`uname -s`" = 'Darwin' ]]; then |
| 40 | + MASON_PLATFORM="osx" |
| 41 | + else |
| 42 | + MASON_PLATFORM="linux" |
| 43 | + fi |
| 44 | + fi |
| 45 | + |
| 46 | + # Determine platform version string |
| 47 | + if [[ -z "${MASON_PLATFORM_VERSION:-}" ]]; then |
| 48 | + MASON_PLATFORM_VERSION="`uname -m`" |
| 49 | + fi |
| 50 | +} |
| 51 | + |
| 52 | +function mason_trim { |
| 53 | + local _TMP="${1#"${1%%[![:space:]]*}"}" |
| 54 | + echo -n "${_TMP%"${_TMP##*[![:space:]]}"}" |
| 55 | +} |
| 56 | + |
| 57 | +function mason_uppercase { |
| 58 | + echo -n "$1" | tr "[a-z]" "[A-Z]" |
| 59 | +} |
| 60 | + |
| 61 | +function mason_use { |
| 62 | + local _HEADER_ONLY=false _PACKAGE _SAFE_PACKAGE _VERSION _PLATFORM_ID _SLUG _INSTALL_PATH _INSTALL_PATH_RELATIVE |
| 63 | + |
| 64 | + while [[ $# -gt 0 ]]; do |
| 65 | + if [[ $1 == "--header-only" ]]; then |
| 66 | + _HEADER_ONLY=true |
| 67 | + elif [[ -z "${_PACKAGE:-}" ]]; then |
| 68 | + _PACKAGE="$1" |
| 69 | + elif [[ -z "${_VERSION:-}" ]]; then |
| 70 | + _VERSION="$1" |
| 71 | + else |
| 72 | + mason_error "[Mason] mason_use() called with unrecognized arguments: '$@'" |
| 73 | + exit 1 |
| 74 | + fi |
| 75 | + shift |
| 76 | + done |
| 77 | + |
| 78 | + if [[ -z "${_PACKAGE:-}" ]]; then |
| 79 | + mason_error "[Mason] No package name given" |
| 80 | + exit 1 |
| 81 | + fi |
| 82 | + |
| 83 | + # Create a package name that we can use as shell variable names. |
| 84 | + _SAFE_PACKAGE="${_PACKAGE//[![:alnum:]]/_}" |
| 85 | + |
| 86 | + if [[ -z "${_VERSION:-}" ]]; then |
| 87 | + mason_error "[Mason] Specifying a version is required" |
| 88 | + exit 1 |
| 89 | + fi |
| 90 | + |
| 91 | + _PLATFORM_ID="${MASON_PLATFORM}-${MASON_PLATFORM_VERSION}" |
| 92 | + if [[ "${_HEADER_ONLY}" = true ]] ; then |
| 93 | + _PLATFORM_ID="headers" |
| 94 | + fi |
| 95 | + |
| 96 | + _SLUG="${_PLATFORM_ID}/${_PACKAGE}/${_VERSION}" |
| 97 | + _INSTALL_PATH="${MASON_PACKAGE_DIR}/${_SLUG}" |
| 98 | + _INSTALL_PATH_RELATIVE="${_INSTALL_PATH#`pwd`/}" |
| 99 | + |
| 100 | + if [[ ! -d "${_INSTALL_PATH}" ]]; then |
| 101 | + local _CACHE_PATH _URL _CACHE_DIR _ERROR |
| 102 | + _CACHE_PATH="${MASON_PACKAGE_DIR}/.binaries/${_SLUG}.tar.gz" |
| 103 | + if [ ! -f "${_CACHE_PATH}" ]; then |
| 104 | + # Download the package |
| 105 | + _URL="${MASON_REPOSITORY}/${_SLUG}.tar.gz" |
| 106 | + mason_info "[Mason] Downloading package ${_URL}..." |
| 107 | + _CACHE_DIR="`dirname "${_CACHE_PATH}"`" |
| 108 | + mkdir -p "${_CACHE_DIR}" |
| 109 | + if ! _ERROR=$(curl --retry 3 --silent --fail --show-error --location "${_URL}" --output "${_CACHE_PATH}.tmp" 2>&1); then |
| 110 | + mason_error "[Mason] ${_ERROR}" |
| 111 | + exit 1 |
| 112 | + else |
| 113 | + # We downloaded to a temporary file to prevent half-finished downloads |
| 114 | + mv "${_CACHE_PATH}.tmp" "${_CACHE_PATH}" |
| 115 | + fi |
| 116 | + fi |
| 117 | + |
| 118 | + # Unpack the package |
| 119 | + mason_info "[Mason] Unpacking package to ${_INSTALL_PATH_RELATIVE}..." |
| 120 | + mkdir -p "${_INSTALL_PATH}" |
| 121 | + tar xzf "${_CACHE_PATH}" -C "${_INSTALL_PATH}" |
| 122 | + fi |
| 123 | + |
| 124 | + # Error out if there is no config file. |
| 125 | + if [[ ! -f "${_INSTALL_PATH}/mason.ini" ]]; then |
| 126 | + mason_error "[Mason] Could not find mason.ini for package ${_PACKAGE} ${_VERSION}" |
| 127 | + exit 1 |
| 128 | + fi |
| 129 | + |
| 130 | + # We use this instead of declare, since it declare makes local variables when run in a function. |
| 131 | + read "MASON_PACKAGE_${_SAFE_PACKAGE}_PREFIX" <<< "${_INSTALL_PATH}" |
| 132 | + |
| 133 | + # Load the configuration from the ini file |
| 134 | + local _LINE _KEY _VALUE |
| 135 | + while read _LINE; do |
| 136 | + _KEY="`mason_trim "${_LINE%%=*}"`" |
| 137 | + if [[ "${_KEY}" =~ ^[a-z_]+$ ]]; then |
| 138 | + _KEY="`mason_uppercase "${_KEY}"`" # Convert to uppercase |
| 139 | + _LINE="${_LINE%%;*}" # Trim trailing comments |
| 140 | + _VALUE="`mason_trim "${_LINE#*=}"`" |
| 141 | + _VALUE="${_VALUE//\{prefix\}/${_INSTALL_PATH}}" # Replace {prefix} |
| 142 | + read "MASON_PACKAGE_${_SAFE_PACKAGE}_${_KEY}" <<< "${_VALUE}" |
| 143 | + fi |
| 144 | + done < "${_INSTALL_PATH}/mason.ini" |
| 145 | + |
| 146 | + # We're using the fact that this variable is declared to pass back the package name we parsed |
| 147 | + # from the argument string to avoid polluting the global namespace. |
| 148 | + if [ ! -z ${_MASON_SAFE_PACKAGE_NAME+x} ]; then |
| 149 | + _MASON_SAFE_PACKAGE_NAME="${_SAFE_PACKAGE}" |
| 150 | + fi |
| 151 | +} |
| 152 | + |
| 153 | +function mason_cli { |
| 154 | + local _MASON_SAFE_PACKAGE_NAME= _PROP _VAR |
| 155 | + if [[ $# -lt 1 ]]; then |
| 156 | + mason_error "[Mason] Usage: $0 <property> [--header-only] <name> <version>" |
| 157 | + mason_error "[Mason] <property> is one of 'include_dirs', 'definitions', 'options', 'ldflags', 'static_libs', or any custom variables in the package's mason.ini." |
| 158 | + exit 1 |
| 159 | + fi |
| 160 | + |
| 161 | + # Store first argument and pass the remaining arguments to mason_use |
| 162 | + _PROP="`mason_uppercase "$1"`" |
| 163 | + shift |
| 164 | + mason_use "$@" |
| 165 | + |
| 166 | + # Optionally print variables |
| 167 | + _VAR="MASON_PACKAGE_${_MASON_SAFE_PACKAGE_NAME}_${_PROP}" |
| 168 | + if [[ ! -z "${!_VAR:-}" ]]; then |
| 169 | + echo "${!_VAR}" |
| 170 | + fi |
| 171 | +} |
| 172 | + |
| 173 | +# Directory where Mason packages are located; typically ends with mason_packages |
| 174 | +if [[ -z "${MASON_PACKAGE_DIR:-}" ]]; then |
| 175 | + MASON_PACKAGE_DIR="`pwd`/mason_packages" |
| 176 | +fi |
| 177 | + |
| 178 | +# URL prefix of where packages are located. |
| 179 | +if [[ -z "${MASON_REPOSITORY:-}" ]]; then |
| 180 | + MASON_REPOSITORY="https://mason-binaries.s3.amazonaws.com" |
| 181 | +fi |
| 182 | + |
| 183 | +mason_detect_platform |
| 184 | + |
| 185 | +# Print variables if this shell script is invoked directly. |
| 186 | +if [[ "$0" = "$BASH_SOURCE" ]]; then |
| 187 | + set -euo pipefail |
| 188 | + mason_cli "$@" |
| 189 | +fi |
0 commit comments