dotfiles/scripts/bin/update-repos-simple/update-repos-simple

107 lines
2.3 KiB
Bash
Executable file

#!/usr/bin/env bash
# shellcheck shell=bash disable=2155
# shellcheck source=../../lib/common.sh
source "${0%/*}/../share/dotfiles/lib/common.sh" || exit 1
lock_file="/tmp/update_git_repositories.lock"
acquire_lock() {
declare -gi lock_id=$RANDOM
exec 200>>"$lock_file"
if ! flock -n 200; then
_die "Another instance is running. Exiting."
fi
lock_id=$RANDOM
echo "$lock_id" >"$lock_file"
}
release_lock() {
local current_lock_id
if [[ ! -e $lock_file ]]; then
exit 0
fi
read -r current_lock_id <"$lock_file"
if [[ $current_lock_id == "$lock_id" ]]; then
flock -u 200
rm -f "$lock_file"
fi
}
trap 'release_lock' EXIT INT TERM
acquire_lock
if ! _has git; then
_die "git is required but not installed."
fi
if ! _has parallel; then
_die "GNU parallel is required but not installed."
fi
update_repo() {
declare -i max_retries=5
declare -i initial_delay=2
is_git_repo() {
local repo_path="$1"
git -C "$repo_path" symbolic-ref -q --short HEAD >/dev/null 2>&1
}
remote_branch_exists() {
local repo_path="$1"
git -C "$repo_path" ls-remote --exit-code --heads >/dev/null 2>&1
}
local repo_path="$1"
declare -i retries=0
declare -i delay="$initial_delay"
local repo_name="$(basename "$repo_path")"
if [[ ! -d $repo_path ]]; then
_msg "Directory does not exist. Skipping."
return
fi
if ! is_git_repo "$repo_path"; then
_msg "${repo_name} is not a Git repository. Skipping."
return
fi
if ! remote_branch_exists "$repo_path"; then
_msg "No remote branch configured for ${repo_name}. Skipping."
return
fi
while ((retries < max_retries)); do
if git -C "$repo_path" pull >/dev/null 2>&1; then
_msg "$repo_name" "updated successfully."
break
else
_msg "Network error or update failed for ${repo_name}. Retrying in ${delay} seconds."
((retries++))
sleep "$delay"
((delay *= 2))
fi
done
if ((retries == max_retries)); then
_msg "Max retries reached for ${repo_name}. Skipping."
fi
}
export -f _msg update_repo
if (($# != 1)); then
_die "Usage: $0 <repository_directory>"
fi
repo_dir="$1"
if [[ ! -d $repo_dir ]]; then
_die "Error: Repository directory '${repo_dir}' does not exist."
fi
find "$repo_dir" -mindepth 1 -maxdepth 1 -type d | parallel --group update_repo {}
# vi: set ft=sh ts=4 sw=0 sts=-1 sr noet nosi tw=0 fdm=manual: