b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 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\nhistory, as git will see the move and copy as a rename thus defeating the\npurpose.\n\nFor the original discussion see:\nhttps://lists.openwrt.org/pipermail/openwrt-devel/2023-October/041673.html")" |
| 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 | echo "Deleting merge commit ($(git rev-parse HEAD))." |
| 175 | git rebase HEAD~1 |
| 176 | |
| 177 | echo "Original commitish was '${initial_commitish}'." |
| 178 | echo 'Kernel bump complete. Remember to use `git log --follow`.' |
| 179 | } |
| 180 | |
| 181 | check_requirements() |
| 182 | { |
| 183 | for _cmd in ${REQUIRED_COMMANDS}; do |
| 184 | if ! _test_result="$(command -V "${_cmd}")"; then |
| 185 | _test_result_fail="${_test_result_fail:-}${_test_result}\n" |
| 186 | else |
| 187 | _test_result_pass="${_test_result_pass:-}${_test_result}\n" |
| 188 | fi |
| 189 | done |
| 190 | |
| 191 | echo 'Available commands:' |
| 192 | # As the results contain \n, we expect these to be interpreted. |
| 193 | # shellcheck disable=SC2059 |
| 194 | printf "${_test_result_pass:-none\n}" |
| 195 | echo |
| 196 | echo 'Missing commands:' |
| 197 | # shellcheck disable=SC2059 |
| 198 | printf "${_test_result_fail:-none\n}" |
| 199 | echo |
| 200 | |
| 201 | if [ -n "${_test_result_fail:-}" ]; then |
| 202 | echo 'Command test failed, missing programs.' |
| 203 | test_failed=1 |
| 204 | fi |
| 205 | } |
| 206 | |
| 207 | main() |
| 208 | { |
| 209 | while getopts 'chp:r:s:t:' _options; do |
| 210 | case "${_options}" in |
| 211 | 'c') |
| 212 | config_only='true' |
| 213 | ;; |
| 214 | 'h') |
| 215 | usage |
| 216 | exit 0 |
| 217 | ;; |
| 218 | 'p') |
| 219 | platform_name="${OPTARG}" |
| 220 | ;; |
| 221 | 'r') |
| 222 | subtarget_names="${OPTARG}" |
| 223 | ;; |
| 224 | 's') |
| 225 | source_version="${OPTARG}" |
| 226 | ;; |
| 227 | 't') |
| 228 | target_version="${OPTARG}" |
| 229 | ;; |
| 230 | ':') |
| 231 | e_err "Option -${OPTARG} requires an argument." |
| 232 | exit 1 |
| 233 | ;; |
| 234 | *) |
| 235 | e_err "Invalid option: -${OPTARG}" |
| 236 | exit 1 |
| 237 | ;; |
| 238 | esac |
| 239 | done |
| 240 | shift "$((OPTIND - 1))" |
| 241 | |
| 242 | platform_name="${platform_name:-${PLATFORM_NAME:-}}" |
| 243 | subtarget_names="${subtarget_names:-${SUBTARGET_NAMES:-}}" |
| 244 | source_version="${source_version:-${SOURCE_VERSION:-}}" |
| 245 | target_version="${target_version:-${TARGET_VERSION:-}}" |
| 246 | |
| 247 | if [ -z "${source_version:-}" ] || [ -z "${target_version:-}" ]; then |
| 248 | e_err "Source (${source_version:-missing source version}) and target (${target_version:-missing target version}) versions need to be defined." |
| 249 | echo |
| 250 | usage |
| 251 | exit 1 |
| 252 | fi |
| 253 | |
| 254 | check_requirements |
| 255 | |
| 256 | init |
| 257 | bump_kernel |
| 258 | cleanup |
| 259 | } |
| 260 | |
| 261 | main "${@}" |
| 262 | |
| 263 | exit 0 |