Yegor Timoshenko | c2e4941 | 2018-10-07 01:58:27 +0000 | [diff] [blame] | 1 | #!/usr/bin/env bash |
Martin Roth | 5cb2263 | 2017-07-22 21:31:56 -0600 | [diff] [blame] | 2 | # |
Patrick Georgi | 7333a11 | 2020-05-08 20:48:04 +0200 | [diff] [blame] | 3 | # SPDX-License-Identifier: GPL-2.0-only |
Martin Roth | 5cb2263 | 2017-07-22 21:31:56 -0600 | [diff] [blame] | 4 | |
| 5 | # Description: |
| 6 | # Check all submodules for updates. If there are more than a minimum |
| 7 | # number of changes, create a commit to update the submodule to the |
| 8 | # new version. |
| 9 | |
Martin Roth | 3201e1e | 2022-01-05 22:54:30 -0700 | [diff] [blame] | 10 | set -eu -o pipefail |
| 11 | |
| 12 | VERSION="1.01" |
| 13 | PROGRAM=$0 |
| 14 | PROGNAME="$(basename "${PROGRAM}")" |
| 15 | |
Martin Roth | 5cb2263 | 2017-07-22 21:31:56 -0600 | [diff] [blame] | 16 | export LANG=C |
| 17 | export LC_ALL=C |
Paul Menzel | 38a906b | 2017-09-27 15:06:57 +0200 | [diff] [blame] | 18 | export TZ=UTC0 |
Martin Roth | 5cb2263 | 2017-07-22 21:31:56 -0600 | [diff] [blame] | 19 | |
| 20 | min_commits=10 |
Martin Roth | 5cb2263 | 2017-07-22 21:31:56 -0600 | [diff] [blame] | 21 | TOP=${PWD} |
| 22 | SUBMODULES_WITH_UPDATES=0 |
Martin Roth | 3201e1e | 2022-01-05 22:54:30 -0700 | [diff] [blame] | 23 | submodule_dirs=() |
| 24 | skip_sync="" |
| 25 | max_commits_to_list=65 |
Martin Roth | 5cb2263 | 2017-07-22 21:31:56 -0600 | [diff] [blame] | 26 | |
Martin Roth | 3201e1e | 2022-01-05 22:54:30 -0700 | [diff] [blame] | 27 | show_version() { |
| 28 | echo "${PROGNAME} version ${VERSION}" |
| 29 | echo |
| 30 | } |
| 31 | |
| 32 | usage() { |
| 33 | echo "Usage: ${PROGNAME} [options]" |
| 34 | echo |
| 35 | echo "Options:" |
| 36 | echo " -c | --changes <#> Specify the minimum number of changes to update a repo" |
| 37 | echo " -h | --help Print usage and exit" |
| 38 | echo " -R | --repo <dir> Specify a single repo directory to update" |
| 39 | echo " -s | --skipsync Assume that repos are already synced" |
| 40 | echo " -V | --version Print the version and exit" |
| 41 | echo |
| 42 | } |
| 43 | |
| 44 | get_args() { |
| 45 | args=$(getopt -l changes:,help,repo:,skipsync,version -o c:hR:sV -- "$@") |
| 46 | getopt_ret=$? |
| 47 | eval set -- "${args}" |
| 48 | |
| 49 | if [ ${getopt_ret} != 0 ]; then |
| 50 | usage |
| 51 | exit 1 |
Martin Roth | 5cb2263 | 2017-07-22 21:31:56 -0600 | [diff] [blame] | 52 | fi |
Martin Roth | 5cb2263 | 2017-07-22 21:31:56 -0600 | [diff] [blame] | 53 | |
Martin Roth | 3201e1e | 2022-01-05 22:54:30 -0700 | [diff] [blame] | 54 | while true; do |
| 55 | local opt |
| 56 | opt="$1" |
| 57 | shift |
| 58 | case "${opt}" in |
| 59 | -c | --changes) |
| 60 | min_commits="${1}" |
| 61 | shift |
| 62 | ;; |
| 63 | -h | --help) |
| 64 | usage |
| 65 | exit 0 |
| 66 | ;; |
| 67 | -R | --repo) |
| 68 | submodule_dirs=("$(readlink -f "${1}")") |
| 69 | shift |
| 70 | if [[ ! -d "${submodule_dirs[0]}" ]]; then |
| 71 | echo "Error: ${submodule_dirs[0]} is not valid." |
| 72 | usage |
| 73 | exit 1 |
| 74 | fi |
| 75 | ;; |
| 76 | -s | --skipsync) |
| 77 | skip_sync=1 |
| 78 | ;; |
| 79 | -V | --version) |
| 80 | exit 0 |
| 81 | ;; |
| 82 | *) |
| 83 | break |
| 84 | ;; |
| 85 | esac |
| 86 | done |
| 87 | } |
Martin Roth | 5cb2263 | 2017-07-22 21:31:56 -0600 | [diff] [blame] | 88 | |
Martin Roth | 5cb2263 | 2017-07-22 21:31:56 -0600 | [diff] [blame] | 89 | |
Martin Roth | 3201e1e | 2022-01-05 22:54:30 -0700 | [diff] [blame] | 90 | main() { |
| 91 | show_version |
| 92 | get_args "$@" |
| 93 | |
| 94 | if (( ${#submodule_dirs[@]} == 0 )); then |
| 95 | readarray -t submodule_dirs < <(git submodule foreach pwd | grep -v "Entering") |
Martin Roth | 5cb2263 | 2017-07-22 21:31:56 -0600 | [diff] [blame] | 96 | fi |
Martin Roth | 5cb2263 | 2017-07-22 21:31:56 -0600 | [diff] [blame] | 97 | |
Martin Roth | 3201e1e | 2022-01-05 22:54:30 -0700 | [diff] [blame] | 98 | for submodule in "${submodule_dirs[@]}"; do |
| 99 | echo "Checking submodule ${submodule}" |
| 100 | if ! cd "$submodule"; then |
| 101 | echo "Error: could not cd to $submodule" |
| 102 | exit 1 |
| 103 | fi |
| 104 | |
| 105 | initial_commit_id="$(git log --pretty='%h' -n 1)" |
| 106 | initial_commit_description="$(git log --pretty='%ci - (%s)' -n 1)" |
| 107 | if [[ ${skip_sync} != "1" ]]; then |
| 108 | git fetch 2>/dev/null |
| 109 | fi |
| 110 | |
Yu-Ping Wu | 42af60c | 2023-08-08 17:54:05 +0800 | [diff] [blame] | 111 | declare -a branches=("origin/main" "origin/master" "origin/trunk") |
| 112 | for branch in "${branches[@]}"; do |
| 113 | if git branch -a | grep "${branch}" > /dev/null; then |
| 114 | branch_name="${branch}" |
| 115 | break |
| 116 | fi |
| 117 | done |
Martin Roth | 3201e1e | 2022-01-05 22:54:30 -0700 | [diff] [blame] | 118 | |
| 119 | updated_commit_id="$(git log --pretty='%h' -n 1 "${branch_name}" -- )" |
| 120 | updated_commit_description="$(git log --pretty='%ci - (%s)' -n 1 "${updated_commit_id}")" |
| 121 | if [ "${initial_commit_id}" = "${updated_commit_id}" ]; then |
| 122 | echo "No updates for ${submodule}" |
| 123 | continue |
| 124 | fi |
| 125 | SUBMODULES_WITH_UPDATES+=1 |
| 126 | update_log="$(git log --oneline "${initial_commit_id}..${updated_commit_id}")" |
| 127 | update_count="$(echo "${update_log}" | wc -l)" |
| 128 | if [[ "${update_count}" -gt "${max_commits_to_list}" ]]; then |
| 129 | update_log="" |
| 130 | new_commit_terminator="." |
| 131 | else |
| 132 | new_commit_terminator=":" |
| 133 | fi |
| 134 | echo "${update_count} new commits for ${submodule}" |
| 135 | if [ "${update_count}" -ge "${min_commits}" ]; then |
| 136 | echo "Creating commit to update ${submodule##*/} submodule" |
| 137 | git checkout "${updated_commit_id}" > /dev/null 2>&1 |
| 138 | cd "${TOP}" || exit 1 |
| 139 | git add "${submodule}" > /dev/null 2>&1 || exit 1 |
| 140 | git commit -s -F- > /dev/null 2>&1 <<-EOF |
Yu-Ping Wu | 42af60c | 2023-08-08 17:54:05 +0800 | [diff] [blame] | 141 | Update ${submodule##*/} submodule to upstream ${branch##*/} |
Martin Roth | 3201e1e | 2022-01-05 22:54:30 -0700 | [diff] [blame] | 142 | |
| 143 | Updating from commit id ${initial_commit_id}: |
| 144 | $initial_commit_description |
| 145 | |
| 146 | to commit id ${updated_commit_id}: |
| 147 | ${updated_commit_description} |
| 148 | |
| 149 | This brings in ${update_count} new commits${new_commit_terminator} |
| 150 | ${update_log} |
| 151 | EOF |
| 152 | fi |
| 153 | done |
| 154 | |
| 155 | if [ "${SUBMODULES_WITH_UPDATES}" = "0" ]; then |
| 156 | echo "No submodules with any updates." |
| 157 | fi |
| 158 | } |
| 159 | |
| 160 | main "$@" |