mirror of
https://github.com/end-4/dots-hyprland.git
synced 2026-06-05 14:59:27 -05:00
Update the update, update tester, functions scripts
This commit is contained in:
@@ -117,3 +117,178 @@ function log_die() {
|
||||
log_error "$1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Enhanced: Check if command exists
|
||||
function command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Enhanced: Require a command or die
|
||||
function require_command() {
|
||||
if ! command_exists "$1"; then
|
||||
log_die "Required command '$1' not found. Please install it first."
|
||||
fi
|
||||
}
|
||||
|
||||
# Enhanced: Sanitize file paths to prevent directory traversal
|
||||
function sanitize_path() {
|
||||
local path="$1"
|
||||
|
||||
# Remove null bytes, newlines, and control characters
|
||||
path=$(echo "$path" | tr -d '\000-\037')
|
||||
|
||||
# Prevent directory traversal beyond current context
|
||||
case "$path" in
|
||||
..|../*|*/../*|*/..|\.\./*)
|
||||
log_die "Invalid path detected (directory traversal attempt): $path"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$path"
|
||||
}
|
||||
|
||||
# Enhanced: Safe file comparison that checks existence first
|
||||
function files_differ() {
|
||||
local file1="$1"
|
||||
local file2="$2"
|
||||
|
||||
# Check if both files exist
|
||||
if [[ ! -f "$file1" ]] || [[ ! -f "$file2" ]]; then
|
||||
return 0 # Consider them different if either doesn't exist
|
||||
fi
|
||||
|
||||
# Quick size check first (faster than byte comparison)
|
||||
local size1 size2
|
||||
if command -v stat &>/dev/null; then
|
||||
# Try both BSD and GNU stat formats
|
||||
size1=$(stat -f%z "$file1" 2>/dev/null || stat -c%s "$file1" 2>/dev/null)
|
||||
size2=$(stat -f%z "$file2" 2>/dev/null || stat -c%s "$file2" 2>/dev/null)
|
||||
|
||||
if [[ "$size1" != "$size2" ]]; then
|
||||
return 0 # Different sizes = different files
|
||||
fi
|
||||
fi
|
||||
|
||||
# Then byte-by-byte comparison
|
||||
cmp -s "$file1" "$file2" && return 1 || return 0
|
||||
}
|
||||
|
||||
# Enhanced: Create backup of a file with timestamp
|
||||
function backup_file_simple() {
|
||||
local file="$1"
|
||||
local backup_suffix="${2:-.bak}"
|
||||
|
||||
if [[ ! -f "$file" ]]; then
|
||||
log_warning "Cannot backup non-existent file: $file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local timestamp
|
||||
timestamp=$(date +%Y%m%d-%H%M%S)
|
||||
local backup_name="${file}${backup_suffix}.${timestamp}"
|
||||
|
||||
if cp -p "$file" "$backup_name" 2>/dev/null; then
|
||||
log_info "Backed up: $file → $backup_name"
|
||||
return 0
|
||||
else
|
||||
log_error "Failed to backup: $file"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Enhanced: Validate that a file path is within allowed directory
|
||||
function validate_path_in_directory() {
|
||||
local file_path="$1"
|
||||
local allowed_dir="$2"
|
||||
|
||||
# Resolve to absolute paths
|
||||
local abs_file
|
||||
local abs_dir
|
||||
|
||||
abs_file=$(cd "$(dirname "$file_path")" 2>/dev/null && pwd -P)/$(basename "$file_path") || return 1
|
||||
abs_dir=$(cd "$allowed_dir" 2>/dev/null && pwd -P) || return 1
|
||||
|
||||
# Check if file path starts with allowed directory
|
||||
case "$abs_file" in
|
||||
"$abs_dir"/*)
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
log_error "Path validation failed: $file_path is not within $allowed_dir"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Enhanced: Check if script is running in a CI/CD environment
|
||||
function is_ci_environment() {
|
||||
[[ -n "${CI:-}" ]] || \
|
||||
[[ -n "${GITHUB_ACTIONS:-}" ]] || \
|
||||
[[ -n "${GITLAB_CI:-}" ]] || \
|
||||
[[ -n "${TRAVIS:-}" ]] || \
|
||||
[[ -n "${CIRCLECI:-}" ]]
|
||||
}
|
||||
|
||||
# Enhanced: Progress bar (optional, for long operations)
|
||||
function show_progress() {
|
||||
local current="$1"
|
||||
local total="$2"
|
||||
local message="${3:-Processing}"
|
||||
|
||||
if ! command_exists tput; then
|
||||
return
|
||||
fi
|
||||
|
||||
local percent=$((current * 100 / total))
|
||||
local bar_length=40
|
||||
local filled=$((bar_length * current / total))
|
||||
local empty=$((bar_length - filled))
|
||||
|
||||
printf "\r${message}: [" >&2
|
||||
printf "%${filled}s" | tr ' ' '=' >&2
|
||||
printf "%${empty}s" | tr ' ' ' ' >&2
|
||||
printf "] %d%%" "$percent" >&2
|
||||
|
||||
if [[ $current -eq $total ]]; then
|
||||
echo >&2
|
||||
fi
|
||||
}
|
||||
|
||||
# Enhanced: Cleanup temporary files on exit
|
||||
declare -a TEMP_FILES_TO_CLEANUP=()
|
||||
|
||||
function register_temp_file() {
|
||||
local temp_file="$1"
|
||||
TEMP_FILES_TO_CLEANUP+=("$temp_file")
|
||||
}
|
||||
|
||||
function cleanup_temp_files() {
|
||||
for temp_file in "${TEMP_FILES_TO_CLEANUP[@]}"; do
|
||||
if [[ -f "$temp_file" ]]; then
|
||||
rm -f "$temp_file" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
TEMP_FILES_TO_CLEANUP=()
|
||||
}
|
||||
|
||||
# Enhanced: Check disk space before operations
|
||||
function check_disk_space() {
|
||||
local path="${1:-.}"
|
||||
local required_mb="${2:-100}" # Default 100MB
|
||||
|
||||
if ! command_exists df; then
|
||||
log_warning "df command not available, skipping disk space check"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local available_kb
|
||||
available_kb=$(df -k "$path" | awk 'NR==2 {print $4}')
|
||||
local available_mb=$((available_kb / 1024))
|
||||
|
||||
if [[ $available_mb -lt $required_mb ]]; then
|
||||
log_warning "Low disk space: ${available_mb}MB available, ${required_mb}MB recommended"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user