1a6e5e5ea768a18d57d17e4c782f553b07963fde
[openwrt/staging/stintel.git] / scripts / kernel_bump.sh
1 #!/bin/sh
2 # SPDX-License-Identifier: GPL-2.0-or-later
3 #
4 # Copyright (C) 2024 Olliver Schinagl <oliver@schinagl.nl>
5
6 set -eu
7 if [ -n "${DEBUG_TRACE_SH:-}" ] && \
8 [ "${DEBUG_TRACE_SH:-}" != "${DEBUG_TRACE_SH#*"$(basename "${0}")"*}" ] || \
9 [ "${DEBUG_TRACE_SH:-}" = 'all' ]; then
10 set -x
11 fi
12
13 REQUIRED_COMMANDS='
14 [
15 basename
16 command
17 echo
18 exit
19 git
20 printf
21 sed
22 set
23 shift
24 sort
25 '
26
27 _msg()
28 {
29 _level="${1:?Missing argument to function}"
30 shift
31
32 if [ "${#}" -le 0 ]; then
33 echo "${_level}: No content for this message ..."
34 return
35 fi
36
37 echo "${_level}: ${*}"
38 }
39
40 e_err()
41 {
42 _msg 'err' "${*}" >&2
43 }
44
45 e_warn()
46 {
47 _msg 'warning' "${*}"
48 }
49
50 e_notice()
51 {
52 _msg 'notice' "${*}"
53 }
54
55 usage()
56 {
57 echo "Usage: ${0}"
58 echo 'Helper script to bump the target kernel version, whilst keeping history.'
59 echo ' -c Migrate config files (e.g. subtargets) only.'
60 echo " -p Optional Platform name (e.g. 'ath79' [PLATFORM_NAME]"
61 echo " -r Optional comma separated list of sub-targets (e.g. 'rtl930x' [SUBTARGET_NAMES]"
62 echo " -s Source version of kernel (e.g. 'v6.1' [SOURCE_VERSION])"
63 echo " -t Target version of kernel (e.g. 'v6.6' [TARGET_VERSION]')"
64 echo
65 echo 'All options can also be passed in environment variables (listed between [BRACKETS]).'
66 echo 'Note that this script must be run from within the OpenWrt git repository.'
67 echo 'Example: scripts/kernel_bump.sh -p realtek -s v6.1 -t v6.6'
68 }
69
70 cleanup()
71 {
72 trap - EXIT HUP INT QUIT ABRT ALRM TERM
73
74 if [ -n "${initial_branch:-}" ] && \
75 [ "$(git rev-parse --abbrev-ref HEAD)" != "${initial_branch:-}" ]; then
76 git switch "${initial_branch}"
77 fi
78 }
79
80 init()
81 {
82 src_file="$(readlink -f "${0}")"
83 src_dir="${src_file%%"${src_file##*'/'}"}"
84 initial_branch="$(git rev-parse --abbrev-ref HEAD)"
85 initial_commitish="$(git rev-parse HEAD)"
86
87 if [ -n "$(git status --porcelain | grep -v '^?? .*')" ]; then
88 echo 'Git respository not in a clean state, will not continue.'
89 exit 1
90 fi
91
92 if [ -n "${src_dir##*'/scripts/'}" ]; then
93 echo "This script '${src_file}' is not in the scripts subdirectory, this is unexpected, cannot continue."
94 exit 1
95 fi
96
97 source_version="${source_version#v}"
98 target_version="${target_version#v}"
99
100 trap cleanup EXIT HUP INT QUIT ABRT ALRM TERM
101 }
102
103 bump_kernel()
104 {
105 if [ -z "${platform_name}" ] || \
106 [ -d "${PWD}/image" ]; then
107 platform_name="${PWD}"
108 fi
109 platform_name="${platform_name##*'/'}"
110
111 _target_dir="${src_dir}/../target/linux/${platform_name}"
112
113 if [ ! -d "${_target_dir}/image" ]; then
114 e_err "Cannot find target linux directory '${_target_dir:-not defined}'. Not in a platform directory, or -p not set."
115 exit 1
116 fi
117
118 git switch --force-create '__openwrt_kernel_files_mover'
119
120 if [ "${config_only:-false}" != 'true' ]; then
121 for _path in $(git ls-tree -d -r --name-only '__openwrt_kernel_files_mover' "${_target_dir}" |
122 sed -n "s|^\(.*-${source_version}\).*|\1|p" |
123 sort -u); do
124 if [ ! -e "${_path}" ] || \
125 [ "${_path}" = "${_path%%"-${source_version}"}" ]; then
126 continue
127 fi
128
129 _target_path="${_path%%"-${source_version}"}-${target_version}"
130 if [ -e "${_target_path}" ]; then
131 e_err "Target '${_target_path}' already exists!"
132 exit 1
133 fi
134
135 git mv \
136 "${_path}" \
137 "${_target_path}"
138 done
139 fi
140
141 for _config in $(git ls-files "${_target_dir}" |
142 sed -n "s|^\(.*config-${source_version}\).*|\1|p" |
143 sort -u); do
144 if [ ! -e "${_config}" ]; then
145 continue
146 fi
147
148 _subtarget="${_config%%"/config-${source_version}"}"
149 if [ -n "${subtarget_names:-}" ]; then
150 echo "${subtarget_names:-}" | while IFS=',' read -r _subtarget_name; do
151 if [ "${_subtarget_name}" = "${_subtarget##*'/'}" ]; then
152 git mv "${_config}" "${_subtarget}/config-${target_version}"
153 fi
154 done
155 else
156 git mv "${_config}" "${_subtarget}/config-${target_version}"
157 fi
158 done
159
160 git commit \
161 --signoff \
162 --message "kernel/${platform_name}: Create kernel files for v${target_version} (from v${source_version})" \
163 --message 'This is an automatically generated commit.' \
164 --message 'When doing `git bisect`, consider `git bisect --skip`.'
165
166 git checkout 'HEAD~' "${_target_dir}"
167 git commit \
168 --signoff \
169 --message "kernel/${platform_name}: Restore kernel files for v${source_version}" \
170 --message "$(printf "This is an automatically generated commit which aids following Kernel patch history,\nas git will see the move and copy as a rename thus defeating the purpose.\n\nSee: https://lists.openwrt.org/pipermail/openwrt-devel/2023-October/041673.html\nfor the original discussion.")"
171 git switch "${initial_branch:?Unable to switch back to original branch. Quitting.}"
172 GIT_EDITOR=true git merge --no-ff '__openwrt_kernel_files_mover'
173 git branch --delete '__openwrt_kernel_files_mover'
174
175 echo "Original commitish was '${initial_commitish}'."
176 echo 'Kernel bump complete. Remember to use `git log --follow`.'
177 }
178
179 check_requirements()
180 {
181 for _cmd in ${REQUIRED_COMMANDS}; do
182 if ! _test_result="$(command -V "${_cmd}")"; then
183 _test_result_fail="${_test_result_fail:-}${_test_result}\n"
184 else
185 _test_result_pass="${_test_result_pass:-}${_test_result}\n"
186 fi
187 done
188
189 echo 'Available commands:'
190 # As the results contain \n, we expect these to be interpreted.
191 # shellcheck disable=SC2059
192 printf "${_test_result_pass:-none\n}"
193 echo
194 echo 'Missing commands:'
195 # shellcheck disable=SC2059
196 printf "${_test_result_fail:-none\n}"
197 echo
198
199 if [ -n "${_test_result_fail:-}" ]; then
200 echo 'Command test failed, missing programs.'
201 test_failed=1
202 fi
203 }
204
205 main()
206 {
207 while getopts 'chp:r:s:t:' _options; do
208 case "${_options}" in
209 'c')
210 config_only='true'
211 ;;
212 'h')
213 usage
214 exit 0
215 ;;
216 'p')
217 platform_name="${OPTARG}"
218 ;;
219 'r')
220 subtarget_names="${OPTARG}"
221 ;;
222 's')
223 source_version="${OPTARG}"
224 ;;
225 't')
226 target_version="${OPTARG}"
227 ;;
228 ':')
229 e_err "Option -${OPTARG} requires an argument."
230 exit 1
231 ;;
232 *)
233 e_err "Invalid option: -${OPTARG}"
234 exit 1
235 ;;
236 esac
237 done
238 shift "$((OPTIND - 1))"
239
240 platform_name="${platform_name:-${PLATFORM_NAME:-}}"
241 subtarget_names="${subtarget_names:-${SUBTARGET_NAMES:-}}"
242 source_version="${source_version:-${SOURCE_VERSION:-}}"
243 target_version="${target_version:-${TARGET_VERSION:-}}"
244
245 if [ -z "${source_version:-}" ] || [ -z "${target_version:-}" ]; then
246 e_err "Source (${source_version:-missing source version}) and target (${target_version:-missing target version}) versions need to be defined."
247 echo
248 usage
249 exit 1
250 fi
251
252 check_requirements
253
254 init
255 bump_kernel
256 cleanup
257 }
258
259 main "${@}"
260
261 exit 0