#!/usr/bin/env bash # pull-all-dirs - Pull git repositories in all subdirectories that are behind upstream # Usage: pull-all-dirs [directory] set -euo pipefail target_dir="${1:-.}" if [[ ! -d "$target_dir" ]]; then printf 'Error: Directory "%s" does not exist\n' "$target_dir" >&2 exit 1 fi cd "$target_dir" updated_file="$(mktemp)" trap 'rm -f "$updated_file"' EXIT process_repo() { local dir=$1 [[ -d "$dir/.git" ]] || return 0 if ! git -C "$dir" remote update >/dev/null 2>&1; then printf 'Warning: could not update remotes for "%s"\n' "$dir" >&2 return 1 fi if git -C "$dir" status -uno | grep -q "Your branch is behind"; then printf 'Pulling updates for: %s\n' "$dir" if git -C "$dir" pull --ff-only; then printf '%s\n' "$dir" >>"$updated_file" else printf 'Error: failed to pull updates for "%s"\n' "$dir" >&2 return 1 fi fi } pids=() for dir in */; do [[ -d "$dir" ]] || continue dir=${dir%/} process_repo "$dir" & pids+=("$!") done exit_status=0 for pid in "${pids[@]}"; do if ! wait "$pid"; then exit_status=1 fi done if [[ ! -s "$updated_file" ]]; then echo "All repositories are up to date." else echo "Updated repositories:" sort -u "$updated_file" | sed 's/^/ - /' fi exit "$exit_status"