-
-
Save Artnoc1/69238e76bf7648de8f11a0dd9e4b06a4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # | |
| # Colors for script | |
| BOLD="\033[1m" | |
| GRN="\033[01;32m" | |
| RED="\033[01;31m" | |
| RST="\033[0m" | |
| YLW="\033[01;33m" | |
| # Alias for echo to handle escape codes like colors | |
| function echo() { | |
| command echo -e "$@" | |
| } | |
| # Prints a formatted header to point out what is being done to the user | |
| function header() { | |
| if [[ -n ${2} ]]; then | |
| COLOR=${2} | |
| else | |
| COLOR=${RED} | |
| fi | |
| echo "${COLOR}" | |
| # shellcheck disable=SC2034 | |
| echo "====$(for i in $(seq ${#1}); do echo "=\c"; done)====" | |
| echo "== ${1} ==" | |
| # shellcheck disable=SC2034 | |
| echo "====$(for i in $(seq ${#1}); do echo "=\c"; done)====" | |
| echo "${RST}" | |
| } | |
| # Prints an error in bold red | |
| function die() { | |
| echo | |
| echo "${RED}${1}${RST}" | |
| [[ ${2} = "-h" ]] && ${0} -h | |
| exit 1 | |
| } | |
| # Prints a statement in bold green | |
| function success() { | |
| echo | |
| echo "${GRN}${1}${RST}" | |
| [[ -z ${2} ]] && echo | |
| } | |
| # Prints a warning in bold yellow | |
| function warn() { | |
| echo | |
| echo "${YLW}${1}${RST}" | |
| [[ -z ${2} ]] && echo | |
| } | |
| # Parse the provided parameters | |
| function parse_parameters() { | |
| while [[ $# -ge 1 ]]; do | |
| case ${1} in | |
| # Use git cherry-pick | |
| "-c"|"--cherry-pick") | |
| UPDATE_METHOD=cherry-pick ;; | |
| # Only update the linux-stable remote | |
| "-f"|"--fetch-only") | |
| FETCH_REMOTE_ONLY=true ;; | |
| # Help menu | |
| "-h"|"--help") | |
| echo | |
| echo "${BOLD}Command:${RST} ./$(basename "${0}") <options>" | |
| echo | |
| echo "${BOLD}Script description:${RST} Merges/cherry-picks Linux upstream into a kernel tree" | |
| echo | |
| echo "${BOLD}Required parameters:${RST}" | |
| echo " -c | --cherry-pick" | |
| echo " -m | --merge" | |
| echo " Call either git cherry-pick or git merge when updating from upstream" | |
| echo | |
| echo "${BOLD}Optional parameters:${RST}" | |
| echo " -f | --fetch-only" | |
| echo " Simply fetches the tags from linux-stable then exits" | |
| echo | |
| echo " -k | --kernel-folder" | |
| echo " The device's kernel source's location; this can either be a full path or relative to where the script is being executed." | |
| echo | |
| echo " -l | --latest" | |
| echo " Updates to the latest version available for the current kernel tree" | |
| echo | |
| echo " -p | --print-latest" | |
| echo " Prints the latest version available for the current kernel tree then exits" | |
| echo | |
| echo " -v | --version" | |
| echo " Updates to the specified version (e.g. -v 3.18.78)" | |
| echo | |
| echo "${BOLD}Defaults:${RST}" | |
| echo " If -l or -v are not specified, ONE version is picked at a time (e.g. 3.18.31 to 3.18.32)" | |
| echo | |
| echo " If -k is not specified, the script assumes it is in the kernel source folder already" | |
| echo | |
| exit 1 ;; | |
| # Kernel source location | |
| "-k"|"--kernel-folder") | |
| shift | |
| [[ $# -lt 1 ]] && die "Please specify a kernel source location!" | |
| KERNEL_FOLDER=${1} ;; | |
| # Update to the latest version upstream unconditionally | |
| "-l"|"--latest") | |
| UPDATE_MODE=1 ;; | |
| # Use git merge | |
| "-m"|"--merge") | |
| UPDATE_METHOD=merge ;; | |
| # Print the latest version from kernel.org | |
| "-p"|"--print-latest") | |
| PRINT_LATEST=true ;; | |
| # Update to the specified version | |
| "-v"|"--version") | |
| shift | |
| [[ $# -lt 1 ]] && die "Please specify a version to update!" | |
| TARGET_VERSION=${1} ;; | |
| *) | |
| die "Invalid parameter!" ;; | |
| esac | |
| shift | |
| done | |
| # If kernel source isn't specified, assume we're there | |
| [[ -z ${KERNEL_FOLDER} ]] && KERNEL_FOLDER=$(pwd) | |
| # Sanity checks | |
| [[ ! ${UPDATE_METHOD} ]] && die "Neither cherry-pick nor merge were specified, please supply one!" -h | |
| [[ ! -d ${KERNEL_FOLDER} ]] && die "Invalid kernel source location specified! Folder does not exist" -h | |
| [[ ! -f ${KERNEL_FOLDER}/Makefile ]] && die "Invalid kernel source location specified! No Makefile present" -h | |
| # Default update mode is one version at a time | |
| [[ -z ${UPDATE_MODE} && -z ${TARGET_VERSION} ]] && UPDATE_MODE=0 | |
| } | |
| # Update the linux-stable remote (and add it if it doesn't exist) | |
| function update_remote() { | |
| header "Updating linux-stable" | |
| # Add remote if it isn't already present | |
| cd "${KERNEL_FOLDER}" || die "Could not change into ${KERNEL_FOLDER}!" | |
| if git fetch --tags https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/; then | |
| success "linux-stable updated successfully!" | |
| else | |
| die "linux-stable update failed!" | |
| fi | |
| [[ ${FETCH_REMOTE_ONLY} ]] && exit 0 | |
| } | |
| # Generate versions | |
| function generate_versions() { | |
| header "Calculating versions" | |
| # Full kernel version | |
| CURRENT_VERSION=$(make -s CC=gcc CROSS_COMPILE="" kernelversion) | |
| # First two numbers (3.4 | 3.10 | 3.18 | 4.4) | |
| CURRENT_MAJOR_VERSION=$(echo "${CURRENT_VERSION}" | cut -f 1,2 -d .) | |
| # Last number | |
| CURRENT_SUBLEVEL=$(echo "${CURRENT_VERSION}" | cut -d . -f 3) | |
| # Get latest update from upstream | |
| LATEST_VERSION=$(git tag --sort=-taggerdate -l "v${CURRENT_MAJOR_VERSION}"* | head -n 1 | sed s/v//) | |
| LATEST_SUBLEVEL=$(echo "${LATEST_VERSION}" | cut -d . -f 3) | |
| # Print the current/latest version and exit if requested | |
| echo "${BOLD}Current kernel version:${RST} ${CURRENT_VERSION}" | |
| echo | |
| echo "${BOLD}Latest kernel version:${RST} ${LATEST_VERSION}" | |
| if [[ ${PRINT_LATEST} ]]; then | |
| echo | |
| exit 0 | |
| fi | |
| # UPDATE_MODES: | |
| # 0. Update one version | |
| # 1. Update to the latest version | |
| case ${UPDATE_MODE} in | |
| 0) | |
| TARGET_SUBLEVEL=$((CURRENT_SUBLEVEL + 1)) | |
| TARGET_VERSION=${CURRENT_MAJOR_VERSION}.${TARGET_SUBLEVEL} ;; | |
| 1) | |
| TARGET_VERSION=${LATEST_VERSION} ;; | |
| esac | |
| # Make sure target version is between current version and latest version | |
| TARGET_SUBLEVEL=$(echo "${TARGET_VERSION}" | cut -d . -f 3) | |
| [[ ${TARGET_SUBLEVEL} -le ${CURRENT_SUBLEVEL} ]] && die "${TARGET_VERSION} is already present in ${CURRENT_VERSION}!" | |
| [[ ${TARGET_SUBLEVEL} -gt ${LATEST_SUBLEVEL} ]] && die "${CURRENT_VERSION} is the latest!" | |
| [[ ${CURRENT_SUBLEVEL} -eq 0 ]] && CURRENT_VERSION=${CURRENT_MAJOR_VERSION} | |
| RANGE=v${CURRENT_VERSION}..v${TARGET_VERSION} | |
| echo | |
| echo "${BOLD}Target kernel version:${RST} ${TARGET_VERSION}" | |
| echo | |
| } | |
| function update_to_target_version() { | |
| case ${UPDATE_METHOD} in | |
| "cherry-pick") | |
| if ! git cherry-pick "${RANGE}"; then | |
| die "Cherry-pick needs manual intervention! Resolve conflicts then run: | |
| git add . && git cherry-pick --continue" | |
| else | |
| header "${TARGET_VERSION} PICKED CLEANLY!" "${GRN}" | |
| fi ;; | |
| "merge") | |
| if ! GIT_MERGE_VERBOSITY=1 git merge --no-edit "v${TARGET_VERSION}"; then | |
| die "Merge needs manual intervention! | |
| Resolve conflicts then run git commit!" | |
| else | |
| header "${TARGET_VERSION} MERGED CLEANLY!" "${GRN}" | |
| fi ;; | |
| esac | |
| } | |
| parse_parameters "$@" | |
| update_remote | |
| generate_versions | |
| update_to_target_version |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment