#!/usr/bin/env bash set -Eeuo pipefail die() { printf 'ERROR: %s\n' "$*" >&2 exit 1 } show_help() { local script_name="$1" local description="$2" printf '%s\n' "$description" printf 'Usage: %s -v|--version \n' "$script_name" printf ' %s \n' "$script_name" printf ' %s --help | -h\n' "$script_name" } parse_postgresql_version() { local version="" local positional_seen=0 while (($#)); do case "$1" in -v|--version) (($# >= 2)) || die "$1 requires a PostgreSQL version" [[ -n "$2" ]] || die "PostgreSQL version must not be empty" [[ -z "$version" ]] || die "PostgreSQL version was specified more than once" version="$2" shift 2 ;; --version=*) [[ -n "${1#*=}" ]] || die "PostgreSQL version must not be empty" [[ -z "$version" ]] || die "PostgreSQL version was specified more than once" version="${1#*=}" shift ;; -*) die "unknown option: $1" ;; *) (( positional_seen == 0 )) || die "unexpected argument: $1" [[ -z "$version" ]] || die "PostgreSQL version was specified more than once" version="$1" positional_seen=1 shift ;; esac done [[ -n "$version" ]] || die "PostgreSQL version is required" validate_postgresql_version "$version" printf '%s\n' "$version" } require_tools() { local tool for tool in "$@"; do command -v "$tool" >/dev/null || die "$tool is required" done } validate_postgresql_version() { local version="$1" [[ "$version" =~ ^[0-9]+\.[0-9]+([.][0-9]+)?$ ]] || die "invalid PostgreSQL version: $version" } latest_tag() { local repository="$1" local tag tag="$( curl -fsSL "https://api.github.com/repos/$repository/releases/latest" | sed -nE 's/^[[:space:]]*"tag_name":[[:space:]]*"([^"]+)".*/\1/p' | head -n 1 || true )" if [[ -n "$tag" ]]; then printf '%s\n' "$tag" return fi curl -fsSL "https://api.github.com/repos/$repository/tags?per_page=1" | sed -nE 's/^[[:space:]]*"name":[[:space:]]*"([^"]+)".*/\1/p' | head -n 1 || true } latest_pgaudit_tag() { local repository="$1" local major="$2" local tag tag="$( curl -fsSL "https://api.github.com/repos/$repository/tags?per_page=100" | sed -nE 's/^[[:space:]]*"name":[[:space:]]*"([^"]+)".*/\1/p' | grep -E "^${major//./\\.}\." | head -n 1 || true )" printf '%s\n' "${tag:-$(latest_tag "$repository")}" } reset_staging_dir() { local staging_dir="$1" [[ "$staging_dir" != "/" ]] || die "STAGING_DIR must not be the filesystem root" rm -rf -- "$staging_dir" mkdir -p "$staging_dir" } copy_install_source() { local source_directory="$1" local prefix="$2" local source_name="$3" local complete_version complete_version="$(basename -- "$prefix")" local sources_directory="$SCRIPT_DIR/sources/$complete_version" local destination="$sources_directory/$source_name" mkdir -p "$sources_directory" rm -rf -- "$destination" cp -a -- "$source_directory" "$destination" printf '%s\n' "$destination" } write_install_recipe() { local source_directory="$1" local postgresql_version="$2" local prefix="$3" local configure_options="${4:-}" local recipe="$source_directory/install_$postgresql_version.sh" { printf '#!/usr/bin/env bash\n\nset -Eeuo pipefail\n\n' printf 'SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"\n' printf 'readonly PREFIX=%q\n' "$prefix" printf 'readonly POSTGRES_VERSION=%q\n' "$postgresql_version" printf 'readonly POSTGRES_CONFIGURE_OPTIONS=%q\n' "$configure_options" cat <<'RECIPE_HEADER' if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then printf 'Re-run the saved installation steps for PostgreSQL %s.\n' "$POSTGRES_VERSION" printf 'Usage: %s\n' "$0" printf ' %s --help | -h\n' "$0" exit 0 fi [[ $# -eq 0 ]] || { printf 'Usage: %s [--help|-h]\n' "$0" >&2 exit 2 } readonly PG_CONFIG="$PREFIX/bin/pg_config" readonly JOBS="${JOBS:-$(nproc)}" RECIPE_HEADER cat } > "$recipe" chmod +x "$recipe" printf 'Saved installation recipe: %s\n' "$recipe" } require_postgresql_installation() { local prefix="$1" local pg_config="$prefix/bin/pg_config" [[ "$prefix" != "/" ]] || die "PREFIX must not be the filesystem root" [[ -x "$pg_config" ]] || die "PostgreSQL is not installed at $prefix" } download_source() { local staging_dir="$1" local repository="$2" local tag="$3" local archive_name="$4" local source_dir="$5" local archive="$staging_dir/$archive_name" curl -fL --retry 3 --retry-delay 2 \ -o "$archive" \ "https://github.com/$repository/archive/refs/tags/$tag.tar.gz" tar -xzf "$archive" -C "$staging_dir" [[ -d "$source_dir" ]] || die "source directory was not created: $source_dir" } if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then printf 'Shared helper functions used by PostgreSQL component installers.\n' printf 'This file is sourced by the install scripts and does not install a component.\n' exit 0 fi printf 'This helper is not an installer; run a component installer with .\n' >&2 printf 'Usage: %s --help | -h\n' "$0" >&2 exit 2 fi