blob: 9f6c14f5b00067c77683f170e1a272caa80f5829 [file] [log] [blame]
Yegor Timoshenkoc2e49412018-10-07 01:58:27 +00001#!/usr/bin/env bash
Martin Roth5cb22632017-07-22 21:31:56 -06002#
Patrick Georgi7333a112020-05-08 20:48:04 +02003# SPDX-License-Identifier: GPL-2.0-only
Martin Roth5cb22632017-07-22 21:31:56 -06004
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 Roth3201e1e2022-01-05 22:54:30 -070010set -eu -o pipefail
11
12VERSION="1.01"
13PROGRAM=$0
14PROGNAME="$(basename "${PROGRAM}")"
15
Martin Roth5cb22632017-07-22 21:31:56 -060016export LANG=C
17export LC_ALL=C
Paul Menzel38a906b2017-09-27 15:06:57 +020018export TZ=UTC0
Martin Roth5cb22632017-07-22 21:31:56 -060019
20min_commits=10
Martin Roth5cb22632017-07-22 21:31:56 -060021TOP=${PWD}
22SUBMODULES_WITH_UPDATES=0
Martin Roth3201e1e2022-01-05 22:54:30 -070023submodule_dirs=()
24skip_sync=""
25max_commits_to_list=65
Martin Roth5cb22632017-07-22 21:31:56 -060026
Martin Roth3201e1e2022-01-05 22:54:30 -070027show_version() {
28 echo "${PROGNAME} version ${VERSION}"
29 echo
30}
31
32usage() {
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
44get_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 Roth5cb22632017-07-22 21:31:56 -060052 fi
Martin Roth5cb22632017-07-22 21:31:56 -060053
Martin Roth3201e1e2022-01-05 22:54:30 -070054 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 Roth5cb22632017-07-22 21:31:56 -060088
Martin Roth5cb22632017-07-22 21:31:56 -060089
Martin Roth3201e1e2022-01-05 22:54:30 -070090main() {
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 Roth5cb22632017-07-22 21:31:56 -060096 fi
Martin Roth5cb22632017-07-22 21:31:56 -060097
Martin Roth3201e1e2022-01-05 22:54:30 -070098 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 Wu42af60c2023-08-08 17:54:05 +0800111 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 Roth3201e1e2022-01-05 22:54:30 -0700118
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 Wu42af60c2023-08-08 17:54:05 +0800141 Update ${submodule##*/} submodule to upstream ${branch##*/}
Martin Roth3201e1e2022-01-05 22:54:30 -0700142
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
160main "$@"