diff options
Diffstat (limited to 'lib/util.bash')
-rw-r--r-- | lib/util.bash | 135 |
1 files changed, 101 insertions, 34 deletions
diff --git a/lib/util.bash b/lib/util.bash index 6ad69e1..ad84247 100644 --- a/lib/util.bash +++ b/lib/util.bash @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# SPDX-FileCopyrightText: 2022 Patrick Spek <p.spek@tyil.nl> +# SPDX-FileCopyrightText: 2023 Patrick Spek <p.spek@tyil.nl> # # SPDX-License-Identifier: AGPL-3.0-or-later @@ -18,6 +18,11 @@ chgdir() { cd -- "$1" || die "Failed to change directory to $1" } +# Removes whitespace surrounding a given text. +chomp() { + awk '{$1=$1};1' <<< "$@" +} + # Create a datetime stamp. This is a wrapper around the date utility, ensuring # that the date being formatted is always in UTC and respect SOURCE_DATE_EPOCH, # if it is set. @@ -56,6 +61,26 @@ die() { exit "${code:-1}" } +# Recursively hash files in a directory, and hashing the output of all those +# hashes again. This results in a single hash representing the state of files +# in a directory. It can be used to check whether contents changed after +# templating files in a given directory. +dir_hash() { + local path + + path="$1" ; shift + + for entry in "$path"/* + do + if [[ -d "$entry" ]] + then + dir_hash "$entry" + fi + + file_hash "$entry" + done | file_hash - +} + # Fetch a file from an URL. Using this function introduces a dependency on curl. fetch_http() { local OPTIND @@ -96,45 +121,35 @@ fetch_http_wget() { wget --quiet --output-document "$2" "$1" } -# Check if the first argument given appears in the list of all following -# arguments. -in_args() { - local needle="$1" - shift - - for arg in "$@" - do - [[ $needle == "$arg" ]] && return 0 - done - - return 1 +# Hash a given file. This is a convenience function to work around different +# systems calling their file hashing programs differently, and generating +# different output. This function only expects 1 file as argument, and only +# outputs the hash of this particular file. +file_hash() { + file_hash_md5 "$@" } -# Join a list of arguments into a single string. By default, this will join -# using a ",", but you can set a different character using -c. Note that this -# only joins with a single character, not a string of characters. -join_args() { - local OPTIND - local IFS="," - - while getopts ":c:" opt - do - case "$opt" in - c) IFS="$OPTARG" ;; - *) warn "bashtard/join_args" "Unused opt specified: $opt" ;; - esac - done +file_hash_md5() { + local file - shift $(( OPTIND - 1)) + file="$1" ; shift - printf "%s" "$*" + case "${BASHTARD_PLATFORM[key]}" in + freebsd) md5 "$file" | awk '{ print $NF }' ;; + linux-*) md5sum "$file" | awk '{ print $1 }' ;; + esac } +# A very simple means of templating a file, using sed and awk. The template +# file is assumed to exist within the share directory of the current playbook. +# Variables are passed as key=value pairs to this function. Inside the +# template, they are expected to be written as ${key}. file_template() { - local file="$BASHTARD_ETCDIR/playbooks.d/$BASHTARD_PLAYBOOK/share/$1" ; shift + local file local sedfile + file="$(playbook_path "base")/share/$1" ; shift sedfile="$(tmpfile)" if [[ ! -f $file ]] @@ -147,18 +162,18 @@ file_template() do debug "bashtard/template" "Adding $kv to sedfile at $sedfile" - key="$(awk -F= '{ print $1 }' <<< "$kv")" + key="$(cut -d'=' -f -1 <<< "$kv")" if [[ -z "$key" ]] then - crit "bashtard/template" "Empty key in '$kv' while rendering $file?" + crit "bashtard/template" "Empty key in '$kv' while rendering $file" fi - value="$(awk -F= '{ print $NF }' <<< "$kv")" + value="$(cut -d'=' -f 2- <<< "$kv")" if [[ -z "$value" ]] then - crit "bashtard/template" "Empty key in '$kv' while rendering $file?" + crit "bashtard/template" "Empty key in '$kv' while rendering $file" fi # shellcheck disable=SC2016 @@ -168,6 +183,58 @@ file_template() sed -f "$sedfile" "$file" } +# Check if the first argument given appears in the list of all following +# arguments. +in_args() { + local needle="$1" + shift + + for arg in "$@" + do + [[ $needle == "$arg" ]] && return 0 + done + + return 1 +} + +# Join a list of arguments into a single string. By default, this will join +# using a ",", but you can set a different character using -c. Note that this +# only joins with a single character, not a string of characters. +join_args() { + local OPTIND + local IFS="," + + while getopts ":c:" opt + do + case "$opt" in + c) IFS="$OPTARG" ;; + *) warn "bashtard/join_args" "Unused opt specified: $opt" ;; + esac + done + + shift $(( OPTIND - 1)) + + printf "%s" "$*" +} + +# Convenience function to easily get paths used by the playbook, or to use in +# your playbook. +playbook_path() { + if [[ -z "$BASHTARD_PLAYBOOK" ]] + then + crit "bashtard/playbook_path" "Called outside of a playbook" + return 1 + fi + + case "$1" in + base) printf "%s/playbooks.d/%s" "$BASHTARD_ETCDIR" "$BASHTARD_PLAYBOOK" ;; + data) printf "%s/data.d/%s" "$BASHTARD_ETCDIR" "$BASHTARD_PLAYBOOK" ;; + *) + crit "bashtard/playbook_path" "Invalid path '$1'" + return 1 + esac +} + # Create a temporary directory. Similar to tempfile, but you'll get a directory # instead. tmpdir() { |