#!/bin/bash -ex verbose=0 git_verbose=0 max_jobs=16 lockfile="$(pwd)/version_check.lock" resultfile="$(pwd)/version_check_results.txt" if [ "$1" = "-v" ]; then verbose=1 elif [ "$1" = "-vv" ]; then verbose=1 git_verbose=1 fi # Limit concurrent jobs job_control() { while [ "$(jobs | wc -l)" -ge "$max_jobs" ]; do sleep 0.1 done } git_call() { if [ "$git_verbose" -eq 1 ]; then eval "git $@" elif [[ "$1" == "fetch" ]]; then eval "git $@ >/dev/null 2>&1" else eval "git $@ 2>/dev/null" fi } check_tags() { local path=$(echo "$1" | sed 's:/*$::') echo "Checking $path" # git_call fetch --prune --all # Get the latest tag (by commit date, not tag name) local tag_list=$(git_call rev-list --tags --max-count=1) local latest_tag=$(git_call describe --tags "$tag_list") if [ -n "$latest_tag" ]; then # Get the current tag local current_tag=$(git_call describe --tags --abbrev=0) if [ -n "$current_tag" ]; then if [ "$verbose" -eq 1 ]; then echo "$path -> latest: $latest_tag, current: $current_tag" fi local ts1=$(git_call log -1 --format=%ct $latest_tag) local ts2=$(git_call log -1 --format=%ct $current_tag) if (( ts1 > ts2 )); then if [ "$verbose" -eq 1 ]; then echo -e "\t $path: latest is newer" elif [ "$verbose" -eq 0 ]; then echo "$path -> latest: $latest_tag, current: $current_tag" fi # Critical section guarded by flock ( flock 200 echo "$path -> latest: $latest_tag, current: $current_tag" >> "$resultfile" ) 200>"$lockfile" fi elif [ "$verbose" -eq 1 ]; then echo "$path -> latest: $latest_tag" fi elif [ "$verbose" -eq 1 ]; then if [ -n "$current_tag" ]; then echo "$path -> current: $current_tag" else echo "$path -> no tags found" fi fi } # Fetch and check repositories multi threaded for submoduledir in */ ; do cd "$submoduledir" || continue if [ -e ".git" ]; then job_control check_tags "$submoduledir" & else for sub in */ ; do if [ -e "$sub/.git" ]; then cd "$sub" || continue job_control check_tags "$submoduledir$sub" & cd .. || exit fi done fi cd .. || exit done # Wait for all background jobs to finish wait # Print results echo -e "\n\nResult:\n" # Find the max length of the paths (before '->') max_len=0 while IFS='->' read -r left _; do len=$(echo -n "$left" | wc -c) if (( len > max_len )); then max_len=$len fi done < "$resultfile" # Print with padding so '->' lines up while IFS='->' read -r left right; do right=$(echo "$right" | sed 's/^[[:space:]]*>*[[:space:]]*//') printf "%-${max_len}s -> %s\n" "$left" "$right" done < "$resultfile" # Remove tmp files rm -f "$resultfile" rm -f "$lockfile"