maxwen | 87a7ed6 | 2018-01-14 14:36:53 +0100 | [diff] [blame^] | 1 | #!/usr/bin/env bash |
| 2 | # |
| 3 | # Pull in linux-stable updates to a kernel tree |
| 4 | # |
| 5 | # Copyright (C) 2017 Nathan Chancellor |
| 6 | # |
| 7 | # This program is free software: you can redistribute it and/or modify |
| 8 | # it under the terms of the GNU General Public License as published by |
| 9 | # the Free Software Foundation, either version 3 of the License, or |
| 10 | # (at your option) any later version. |
| 11 | # |
| 12 | # This program is distributed in the hope that it will be useful, |
| 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | # GNU General Public License for more details. |
| 16 | # |
| 17 | # You should have received a copy of the GNU General Public License |
| 18 | # along with this program. If not, see <http://www.gnu.org/licenses/> |
| 19 | |
| 20 | |
| 21 | # Get main tree location |
| 22 | TREE=$( cd $( dirname $( readlink -f "${BASH_SOURCE[0]}" ) )/../../.. && pwd ) |
| 23 | |
| 24 | |
| 25 | # Colors for script |
| 26 | BOLD="\033[1m" |
| 27 | GRN="\033[01;32m" |
| 28 | RED="\033[01;31m" |
| 29 | RST="\033[0m" |
| 30 | YLW="\033[01;33m" |
| 31 | |
| 32 | |
| 33 | # Alias for echo to handle escape codes like colors |
| 34 | function echo() { |
| 35 | command echo -e "$@" |
| 36 | } |
| 37 | |
| 38 | |
| 39 | # Prints a formatted header to point out what is being done to the user |
| 40 | function header() { |
| 41 | if [[ -n ${2} ]]; then |
| 42 | COLOR=${2} |
| 43 | else |
| 44 | COLOR=${RED} |
| 45 | fi |
| 46 | echo ${COLOR} |
| 47 | echo "====$(for i in $(seq ${#1}); do echo "=\c"; done)====" |
| 48 | echo "== ${1} ==" |
| 49 | echo "====$(for i in $(seq ${#1}); do echo "=\c"; done)====" |
| 50 | echo ${RST} |
| 51 | } |
| 52 | |
| 53 | |
| 54 | # Prints an error in bold red |
| 55 | function report_error() { |
| 56 | echo |
| 57 | echo ${RED}${1}${RST} |
| 58 | if [[ ${2} = "-h" ]]; then |
| 59 | ${0} -h |
| 60 | fi |
| 61 | exit 1 |
| 62 | } |
| 63 | |
| 64 | |
| 65 | # Prints a warning in bold yellow |
| 66 | function report_warning() { |
| 67 | echo |
| 68 | echo ${YLW}${1}${RST} |
| 69 | if [[ -z ${2} ]]; then |
| 70 | echo |
| 71 | fi |
| 72 | } |
| 73 | |
| 74 | |
| 75 | # Parse the provided parameters |
| 76 | function parse_parameters() { |
| 77 | while [[ $# -ge 1 ]]; do |
| 78 | case ${1} in |
| 79 | # Use git cherry-pick |
| 80 | "-c"|"--cherry-pick") |
| 81 | UPDATE_METHOD=cherry-pick ;; |
| 82 | |
| 83 | # Only update the linux-stable remote |
| 84 | "-f"|"--fetch-only") |
| 85 | FETCH_REMOTE_ONLY=true ;; |
| 86 | |
| 87 | # Help menu |
| 88 | "-h"|"--help") |
| 89 | echo |
| 90 | echo "${BOLD}Script description:${RST} Merges/cherry-picks Linux upstream into a kernel tree" |
| 91 | echo |
| 92 | echo "${BOLD}Required parameters:${RST}" |
| 93 | echo " -c | --cherry-pick" |
| 94 | echo " -m | --merge" |
| 95 | echo " Call either git cherry-pick or git merge when updating from upstream" |
| 96 | echo |
| 97 | echo " -k | --kernel-folder" |
| 98 | echo " The device's kernel source's location relative to the \"kernel\" folder in the root of the ROM tree" |
| 99 | echo " If unsure, run \"croot; cd kernel; ls --directory */*\" in your terminal (assuming you ran \". build/envsetup.sh\"" |
| 100 | echo |
| 101 | echo "${BOLD}Optional parameters" |
| 102 | echo " -f | --fetch-only" |
| 103 | echo " Simply fetches the tags from linux-stable then exits" |
| 104 | echo |
| 105 | echo " -l | --latest" |
| 106 | echo " Updates to the latest version available for the current kernel tree" |
| 107 | echo |
| 108 | echo " -p | --print-latest" |
| 109 | echo " Prints the latest version available for the current kernel tree then exits" |
| 110 | echo |
| 111 | echo " -v | --version" |
| 112 | echo " Updates to the specified version (e.g. -v 3.18.78)" |
| 113 | echo |
| 114 | echo " By default, only ONE version is picked at a time (e.g. 3.18.31 to 3.18.32)" |
| 115 | echo |
| 116 | exit 1 ;; |
| 117 | |
| 118 | # Kernel source location |
| 119 | "-k"|"--kernel-folder") |
| 120 | shift |
| 121 | if [[ $# -lt 1 ]]; then |
| 122 | report_error "Please specify a device directory!" |
| 123 | fi |
| 124 | |
| 125 | KERNEL_FOLDER=${TREE}/kernel/${1} ;; |
| 126 | |
| 127 | # Update to the latest version upstream unconditionally |
| 128 | "-l"|"--latest") |
| 129 | UPDATE_MODE=1 ;; |
| 130 | |
| 131 | # Use git merge |
| 132 | "-m"|"--merge") |
| 133 | UPDATE_METHOD=merge ;; |
| 134 | |
| 135 | # Print the latest version from kernel.org |
| 136 | "-p"|"--latest") |
| 137 | PRINT_LATEST=true ;; |
| 138 | |
| 139 | # Update to the specified version |
| 140 | "-v"|"--version") |
| 141 | shift |
| 142 | if [[ $# -lt 1 ]]; then |
| 143 | report_error "Please specify a version to update!" |
| 144 | fi |
| 145 | |
| 146 | TARGET_VERSION=${1} ;; |
| 147 | |
| 148 | *) |
| 149 | report_error "Invalid parameter!" ;; |
| 150 | esac |
| 151 | |
| 152 | shift |
| 153 | done |
| 154 | |
| 155 | # Sanity checks |
| 156 | if [[ ! ${UPDATE_METHOD} ]]; then |
| 157 | report_error "Neither cherry-pick nor merge were specified, please supply one!" -h |
| 158 | elif [[ ! -d ${KERNEL_FOLDER} ]]; then |
| 159 | report_error "Invalid kernel source location specified! Folder does not exist" -h |
| 160 | elif [[ ! -f ${KERNEL_FOLDER}/Makefile ]]; then |
| 161 | report_error "Invalid kernel source location specified! No Makefile present" -h |
| 162 | fi |
| 163 | |
| 164 | # Default update mode is one version at a time |
| 165 | if [[ -z ${UPDATE_MODE} ]]; then |
| 166 | UPDATE_MODE=0 |
| 167 | fi |
| 168 | } |
| 169 | |
| 170 | |
| 171 | # Update the linux-stable remote (and add it if it doesn't exist) |
| 172 | function update_remote() { |
| 173 | header "Updating linux-stable" |
| 174 | |
| 175 | # Add remote if it isn't already present |
| 176 | cd ${KERNEL_FOLDER} |
| 177 | |
| 178 | git fetch --tags https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/ |
| 179 | |
| 180 | if [[ $? -ne 0 ]]; then |
| 181 | report_error "linux-stable update failed!" |
| 182 | else |
| 183 | echo "linux-stable updated successfully!" |
| 184 | fi |
| 185 | |
| 186 | if [[ ${FETCH_REMOTE_ONLY} ]]; then |
| 187 | echo |
| 188 | exit 0 |
| 189 | fi |
| 190 | } |
| 191 | |
| 192 | |
| 193 | # Generate versions |
| 194 | function generate_versions() { |
| 195 | header "Calculating versions" |
| 196 | |
| 197 | # Full kernel version |
| 198 | CURRENT_VERSION=$(make kernelversion) |
| 199 | # First two numbers (3.4 | 3.10 | 3.18 | 4.4) |
| 200 | CURRENT_MAJOR_VERSION=$(echo ${CURRENT_VERSION} | cut -f 1,2 -d .) |
| 201 | # Last number |
| 202 | CURRENT_SUBLEVEL=$(echo ${CURRENT_VERSION} | cut -d . -f 3) |
| 203 | |
| 204 | # Get latest update from upstream |
| 205 | LATEST_VERSION=$(git tag --sort=-taggerdate -l v${CURRENT_MAJOR_VERSION}* | head -n 1 | sed s/v//) |
| 206 | LATEST_SUBLEVEL=$(echo ${LATEST_VERSION} | cut -d . -f 3) |
| 207 | |
| 208 | # Print the current/latest version and exit if requested |
| 209 | echo "${BOLD}Current kernel version:${RST} ${CURRENT_VERSION}" |
| 210 | echo |
| 211 | echo "${BOLD}Latest kernel version:${RST} ${LATEST_VERSION}" |
| 212 | if [[ ${PRINT_LATEST} ]]; then |
| 213 | echo |
| 214 | exit 0 |
| 215 | fi |
| 216 | |
| 217 | # UPDATE_MODES: |
| 218 | # 0. Update one version |
| 219 | # 1. Update to the latest version |
| 220 | case ${UPDATE_MODE} in |
| 221 | 0) |
| 222 | TARGET_SUBLEVEL=$((${CURRENT_SUBLEVEL} + 1)) |
| 223 | TARGET_VERSION=${CURRENT_MAJOR_VERSION}.${TARGET_SUBLEVEL} ;; |
| 224 | 1) |
| 225 | TARGET_VERSION=${LATEST_VERSION} ;; |
| 226 | esac |
| 227 | |
| 228 | # Make sure target version is between current version and latest version |
| 229 | TARGET_SUBLEVEL=$(echo ${TARGET_VERSION} | cut -d . -f 3) |
| 230 | if [[ ${TARGET_SUBLEVEL} -le ${CURRENT_SUBLEVEL} ]]; then |
| 231 | report_error "${TARGET_VERSION} is already present in ${CURRENT_VERSION}!\n" |
| 232 | elif [[ ${TARGET_SUBLEVEL} -gt ${LATEST_SUBLEVEL} ]]; then |
| 233 | report_error "${CURRENT_VERSION} is the latest!\n" |
| 234 | fi |
| 235 | |
| 236 | RANGE=v${CURRENT_VERSION}..v${TARGET_VERSION} |
| 237 | |
| 238 | echo |
| 239 | echo "${BOLD}Target kernel version:${RST} ${TARGET_VERSION}" |
| 240 | echo |
| 241 | } |
| 242 | |
| 243 | |
| 244 | function update_to_target_version() { |
| 245 | case ${UPDATE_METHOD} in |
| 246 | "cherry-pick") |
| 247 | git cherry-pick ${RANGE} |
| 248 | if [[ $? -ne 0 ]]; then |
| 249 | report_error "Cherry-pick needs manual intervention! Resolve conflicts then run: |
| 250 | |
| 251 | git add . && git cherry-pick --continue" |
| 252 | else |
| 253 | header "${TARGET_VERSION} PICKED CLEANLY!" ${GRN} |
| 254 | fi ;; |
| 255 | |
| 256 | "merge") |
| 257 | GIT_MERGE_VERBOSITY=1 git merge --no-edit v${TARGET_VERSION} |
| 258 | if [[ $? -ne 0 ]]; then |
| 259 | report_error "Merge needs manual intervention! |
| 260 | |
| 261 | Resolve conflicts then run git merge --continue!" |
| 262 | else |
| 263 | header "${TARGET_VERSION} MERGED CLEANLY!" ${GRN} |
| 264 | fi ;; |
| 265 | esac |
| 266 | } |
| 267 | |
| 268 | |
| 269 | parse_parameters $@ |
| 270 | update_remote |
| 271 | generate_versions |
| 272 | update_to_target_version |