#!/usr/bin/env bash # # SPDX-License-Identifier: GPL-2.0-only # Description: # Check all submodules for updates. If there are more than a minimum # number of changes, create a commit to update the submodule to the # new version. set -eu -o pipefail VERSION="1.01" PROGRAM=$0 PROGNAME="$(basename "${PROGRAM}")" export LANG=C export LC_ALL=C export TZ=UTC0 min_commits=10 TOP=${PWD} SUBMODULES_WITH_UPDATES=0 submodule_dirs=() skip_sync="" max_commits_to_list=65 show_version() { echo "${PROGNAME} version ${VERSION}" echo } usage() { echo "Usage: ${PROGNAME} [options]" echo echo "Options:" echo " -c | --changes <#> Specify the minimum number of changes to update a repo" echo " -h | --help Print usage and exit" echo " -R | --repo Specify a single repo directory to update" echo " -s | --skipsync Assume that repos are already synced" echo " -V | --version Print the version and exit" echo } get_args() { args=$(getopt -l changes:,help,repo:,skipsync,version -o c:hR:sV -- "$@") getopt_ret=$? eval set -- "${args}" if [ ${getopt_ret} != 0 ]; then usage exit 1 fi while true; do local opt opt="$1" shift case "${opt}" in -c | --changes) min_commits="${1}" shift ;; -h | --help) usage exit 0 ;; -R | --repo) submodule_dirs=("$(readlink -f "${1}")") shift if [[ ! -d "${submodule_dirs[0]}" ]]; then echo "Error: ${submodule_dirs[0]} is not valid." usage exit 1 fi ;; -s | --skipsync) skip_sync=1 ;; -V | --version) exit 0 ;; *) break ;; esac done } main() { show_version get_args "$@" if (( ${#submodule_dirs[@]} == 0 )); then readarray -t submodule_dirs < <(git submodule foreach pwd | grep -v "Entering") fi for submodule in "${submodule_dirs[@]}"; do echo "Checking submodule ${submodule}" if ! cd "$submodule"; then echo "Error: could not cd to $submodule" exit 1 fi initial_commit_id="$(git log --pretty='%h' -n 1 --abbrev=12)" initial_commit_description="$(git log --pretty='%ci - (%s)' -n 1)" if [[ ${skip_sync} != "1" ]]; then git fetch 2>/dev/null fi declare -a branches=("origin/main" "origin/master" "origin/trunk") for branch in "${branches[@]}"; do if git branch -a | grep "${branch}" > /dev/null; then branch_name="${branch}" break fi done updated_commit_id="$(git log --pretty='%h' -n 1 --abbrev=12 "${branch_name}" -- )" updated_commit_description="$(git log --pretty='%ci - (%s)' -n 1 "${updated_commit_id}")" if [ "${initial_commit_id}" = "${updated_commit_id}" ]; then echo "No updates for ${submodule}" continue fi SUBMODULES_WITH_UPDATES+=1 update_log="$(git log --oneline --abbrev=12 "${initial_commit_id}..${updated_commit_id}")" update_count="$(echo "${update_log}" | wc -l)" if [[ "${update_count}" -gt "${max_commits_to_list}" ]]; then update_log="" new_commit_terminator="." else new_commit_terminator=":" fi echo "${update_count} new commits for ${submodule}" if [ "${update_count}" -ge "${min_commits}" ]; then echo "Creating commit to update ${submodule##*/} submodule" git checkout "${updated_commit_id}" > /dev/null 2>&1 cd "${TOP}" || exit 1 git add "${submodule}" > /dev/null 2>&1 || exit 1 git commit -s -F- > /dev/null 2>&1 <<-EOF Update ${submodule##*/} submodule to upstream ${branch##*/} Updating from commit id ${initial_commit_id}: $initial_commit_description to commit id ${updated_commit_id}: ${updated_commit_description} This brings in ${update_count} new commits${new_commit_terminator} ${update_log} EOF fi done if [ "${SUBMODULES_WITH_UPDATES}" = "0" ]; then echo "No submodules with any updates." fi } main "$@"