diff options
Diffstat (limited to 'contrib/util.sh')
-rw-r--r-- | contrib/util.sh | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/contrib/util.sh b/contrib/util.sh new file mode 100644 index 0000000..5f846be --- /dev/null +++ b/contrib/util.sh @@ -0,0 +1,215 @@ +#!/bin/bash +set -e + +# Logging +TASKS=() +_last() { + echo -n "${TASKS[0]}" +} +start() { + for n in "${TASKS[@]}"; do + echo -n ' ' + done + TASKS=( + "$@" + "${TASKS[@]}" + ) + echo -e "\x1b[0;1;34m@\x1b[0;34m $@\x1b[0m" +} +complete() { + last="$(_last)" + if [[ "$NOSHIFT" != 1 ]]; then + TASKS=( + "${TASKS[@]:1}" + ) + fi + if [[ "$1" == "" ]] && [[ "$last" != "" ]]; then + NOSHIFT=1 complete "$last" + else + for n in "${TASKS[@]}"; do + echo -n ' ' + done + echo -e "\x1b[0;1;32m+\x1b[0;32m $@\x1b[0m" + fi +} +err() { + last="$(_last)" + if [[ "$NOSHIFT" != 1 ]]; then + TASKS=( + "${TASKS[@]:1}" + ) + fi + if [[ "$1" == "" ]] && [[ "$last" != "" ]]; then + NOSHIFT=1 err "$last" + else + for n in "${TASKS[@]}"; do + echo -n ' ' + done + echo -e "\x1b[0;1;31m!\x1b[0;31m $@\x1b[0m" 1>&2; + fi +} +info() { + echo -e "\x1b[0;1;94mi\x1b[0;94m $@\x1b[0m" 1>&2; +} + +# Bash Array Joiner +join_array() { + printf -v __ "${1//%/%%}%s" "${@:2}" + echo -n "${__:${#1}}" +} + +# jq abstraction layer + +# Determines where to store the JSON - if the value is `IN_MEM`, then the value is kept in the JQ_BUFFER variable +JSON_STORAGE_LOCATION="IN_MEM" +JQ_BUFFER="" +JQ_BUFFER_OUTPUT_FILE="" +JQ_TRANSACTION=() +JQ_IS_DOING_TRANSACTION=false +JQ_POSITIONALS=() +JQ_POSITIONAL_IDX=1 +ARG=null +jsettempstorage() { + newstorage="${1:-"IN_MEM"}" + if [[ "$newstorage" == "$JSON_STORAGE_LOCATION" ]]; then return 0; fi + if [[ "$JSON_STORAGE_LOCATION" == "IN_MEM" ]]; then + touch "$newstorage" + <<< "$JQ_BUFFER" > "$newstorage" + JQ_BUFFER="" + elif [[ "$newstorage" == "IN_MEM" ]]; then + JQ_BUFFER="$(<"$JSON_STORAGE_LOCATION")" + rm "$JSON_STORAGE_LOCATION" + else + mv "$JSON_STORAGE_LOCATION" "$newstorage" + fi + JSON_STORAGE_LOCATION="$newstorage" +} +# Reads the storage buffer +jreadbuffer() { + if [[ "$JSON_STORAGE_LOCATION" == "IN_MEM" ]]; then + echo -n "$JQ_BUFFER" + else + cat "$JSON_STORAGE_LOCATION" + fi +} +# Writes the storage buffer +jwritebuffer() { + if [[ "$JSON_STORAGE_LOCATION" == "IN_MEM" ]]; then + JQ_BUFFER="$@" + else + echo -n "$@" > "$JSON_STORAGE_LOCATION" + fi +} + +# Creates a new jq blank file +jnew() { + JQ_BUFFER_OUTPUT_FILE="$(realpath "${1:-"/dev/null"}")" + jwritebuffer "${2:-"{}"}" +} +# Loads an existing jq file, falling back to creating a blank one if it doesnt exist +jload() { + JQ_BUFFER_OUTPUT_FILE="$(realpath "${1:-"/dev/null"}")" + if [[ -f "$JQ_BUFFER_OUTPUT_FILE" ]]; then + jwritebuffer "$(cat $JQ_BUFFER_OUTPUT_FILE)" + else + jwritebuffer "${2:-"{}"}" + fi +} + +# SQL-like Transaction Logic +jtransaction() { + if [[ "$JQ_IS_DOING_TRANSACTION" == "true" ]]; then + err "Already performing transaction!" + return 1 + fi + JQ_IS_DOING_TRANSACTION=true + JQ_TRANSACTION=() +} +jabort() { + if [[ "$JQ_IS_DOING_TRANSACTION" == "false" ]]; then + err "No pending transaction!" + return 1 + fi + JQ_IS_DOING_TRANSACTION=false + JQ_TRANSACTION=() +} +jcommit() { + if [[ "$JQ_IS_DOING_TRANSACTION" == "false" ]]; then + err "No pending transaction!" + return 1 + fi + JQ_IS_DOING_TRANSACTION=false + # Incase it's empty: + JQ_TRANSACTION+=( + "." + ) + # As we are no longer in a transaction, jrun will run the pipe-delimited query + jrun "$(join_array ' | ' "${JQ_TRANSACTION[@]}")" + # We can, after running, clear the transaction + JQ_TRANSACTION=() +} + +# Loads a string that jq can positionally access later +jsetasset() { + ARG="(\$ARGS.positional[$JQ_POSITIONAL_IDX] | @base64d)" + JQ_POSITIONALS+=( + "$(base64 -w 0 <<< "$@")" + ); + ((JQ_POSITIONAL_IDX=JQ_POSITIONAL_IDX+1)) +} +jgetassetref() { + echo -n "$ARG" + ARG=null +} + +# Perform a jq write operation +jrun() { + if [[ "$JQ_IS_DOING_TRANSACTION" == "true" ]]; then + # If we're in a transaction, just push it to the list + JQ_TRANSACTION+=( + "($@)" + ) + else + # Otherwise, perform the operation and write to the buffer + if [[ "$JSON_STORAGE_LOCATION" == "IN_MEM" ]]; then + JQ_BUFFER="$(jq -Mc "$@" --args owo ${JQ_POSITIONALS[@]} <<< "$JQ_BUFFER")" + else + jq -Mc "$@" --args owo ${JQ_POSITIONALS[@]} < "$JSON_STORAGE_LOCATION" > "$JSON_STORAGE_LOCATION~" + mv "$JSON_STORAGE_LOCATION~" "$JSON_STORAGE_LOCATION" + fi + JQ_POSITIONALS=() + JQ_POSITIONAL_IDX=1 + fi +} +# Perform a jq write operation using a temp file +_jrun_file() { + if [[ "$JQ_IS_DOING_TRANSACTION" == "true" ]]; then + # Does not work for transactions + err "Cannot use _jrun_file in transaction!"; + return 1; + else + # Otherwise, perform the operation and write to the buffer + if [[ "$JSON_STORAGE_LOCATION" == "IN_MEM" ]]; then + echo -n "$@" > /tmp/.operation.jq + JQ_BUFFER="$(jq -Mcf /tmp/.operation.jq --args owo ${JQ_POSITIONALS[@]} <<< "$JQ_BUFFER")" + rm /tmp/.operation.jq + else + echo -n "$@" > /tmp/.operation.jq + jq -Mcf /tmp/.operation.jq --args owo ${JQ_POSITIONALS[@]} < "$JSON_STORAGE_LOCATION" > "$JSON_STORAGE_LOCATION~" + rm /tmp/.operation.jq + mv "$JSON_STORAGE_LOCATION~" "$JSON_STORAGE_LOCATION" + fi + JQ_POSITIONALS=() + JQ_POSITIONAL_IDX=1 + fi +} +jsave() { + if [[ "$JQ_IS_DOING_TRANSACTION" == "true" ]]; then + err "There is a pending transaction." + return 1 + fi + jreadbuffer | jq -M . > "${1:-"$JQ_BUFFER_OUTPUT_FILE"}" +} +escape_str() { + jq '.=$ARGS.positional[0]' --args "$@" -M <<< '""' +} |