#!/usr/bin/env bash # Common utility functions # Usage: source "$(dirname "$0")/utils.sh" # Requires: logging.sh, colors.sh # Check if a command exists check_command() { command -v "$1" &> /dev/null } # Require a command to exist, exit if not found require_command() { if ! check_command "$1"; then log_error "$1 is not installed. Please install it first." exit 1 fi log_debug "$1 is available" } # Check if a file exists check_file() { [ -f "$1" ] } # Require a file to exist, exit if not found require_file() { if ! check_file "$1"; then log_error "Required file not found: $1" exit 1 fi } # Check if a directory exists check_dir() { [ -d "$1" ] } # Require a directory to exist, exit if not found require_dir() { if ! check_dir "$1"; then log_error "Required directory not found: $1" exit 1 fi } # Get script directory get_script_dir() { local script_path="${BASH_SOURCE[1]}" if [ -z "$script_path" ]; then script_path="${BASH_SOURCE[0]}" fi dirname "$(readlink -f "$script_path")" } # Get project root (assumes scripts/ is in project root) get_project_root() { local script_dir="$(get_script_dir)" # Go up from scripts/ or scripts/subdir/ to project root if [[ "$script_dir" == */scripts ]]; then dirname "$script_dir" elif [[ "$script_dir" == */scripts/* ]]; then dirname "$(dirname "$script_dir")" else echo "." fi } # Create directory if it doesn't exist ensure_dir() { if [ ! -d "$1" ]; then mkdir -p "$1" log_debug "Created directory: $1" fi } # Prompt for confirmation confirm() { local prompt="${1:-Continue?}" local response read -p "$(echo -e ${YELLOW}$prompt [y/N]: ${NC})" response case "$response" in [yY][eE][sS]|[yY]) return 0 ;; *) return 1 ;; esac } # Run command with retry retry() { local max_attempts="${1:-3}" local delay="${2:-1}" shift 2 local attempt=1 while [ $attempt -le $max_attempts ]; do if "$@"; then return 0 fi log_warn "Attempt $attempt/$max_attempts failed. Retrying in ${delay}s..." sleep "$delay" attempt=$((attempt + 1)) done log_error "Command failed after $max_attempts attempts" return 1 }