blob: 75254405119937d606068d94467751c6f010783c [file] [log] [blame]
#!/usr/bin/env bash
#
# Pull in linux-stable updates to a kernel tree
#
# Copyright (C) 2017 Nathan Chancellor
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
# Get main tree location
TREE=$( cd $( dirname $( readlink -f "${BASH_SOURCE[0]}" ) )/../../.. && pwd )
# 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}
echo "====$(for i in $(seq ${#1}); do echo "=\c"; done)===="
echo "== ${1} =="
echo "====$(for i in $(seq ${#1}); do echo "=\c"; done)===="
echo ${RST}
}
# Prints an error in bold red
function report_error() {
echo
echo ${RED}${1}${RST}
if [[ ${2} = "-h" ]]; then
${0} -h
fi
exit 1
}
# Prints a warning in bold yellow
function report_warning() {
echo
echo ${YLW}${1}${RST}
if [[ -z ${2} ]]; then
echo
fi
}
# 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}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 " -k | --kernel-folder"
echo " The device's kernel source's location relative to the \"kernel\" folder in the root of the ROM tree"
echo " If unsure, run \"croot; cd kernel; ls --directory */*\" in your terminal (assuming you ran \". build/envsetup.sh\""
echo
echo "${BOLD}Optional parameters"
echo " -f | --fetch-only"
echo " Simply fetches the tags from linux-stable then exits"
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 " By default, only ONE version is picked at a time (e.g. 3.18.31 to 3.18.32)"
echo
exit 1 ;;
# Kernel source location
"-k"|"--kernel-folder")
shift
if [[ $# -lt 1 ]]; then
report_error "Please specify a device directory!"
fi
KERNEL_FOLDER=${TREE}/kernel/${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"|"--latest")
PRINT_LATEST=true ;;
# Update to the specified version
"-v"|"--version")
shift
if [[ $# -lt 1 ]]; then
report_error "Please specify a version to update!"
fi
TARGET_VERSION=${1} ;;
*)
report_error "Invalid parameter!" ;;
esac
shift
done
# Sanity checks
if [[ ! ${UPDATE_METHOD} ]]; then
report_error "Neither cherry-pick nor merge were specified, please supply one!" -h
elif [[ ! -d ${KERNEL_FOLDER} ]]; then
report_error "Invalid kernel source location specified! Folder does not exist" -h
elif [[ ! -f ${KERNEL_FOLDER}/Makefile ]]; then
report_error "Invalid kernel source location specified! No Makefile present" -h
fi
# Default update mode is one version at a time
if [[ -z ${UPDATE_MODE} ]]; then
UPDATE_MODE=0
fi
}
# 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}
git fetch --tags https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/
if [[ $? -ne 0 ]]; then
report_error "linux-stable update failed!"
else
echo "linux-stable updated successfully!"
fi
if [[ ${FETCH_REMOTE_ONLY} ]]; then
echo
exit 0
fi
}
# Generate versions
function generate_versions() {
header "Calculating versions"
# Full kernel version
CURRENT_VERSION=$(make 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)
if [[ ${TARGET_SUBLEVEL} -le ${CURRENT_SUBLEVEL} ]]; then
report_error "${TARGET_VERSION} is already present in ${CURRENT_VERSION}!\n"
elif [[ ${TARGET_SUBLEVEL} -gt ${LATEST_SUBLEVEL} ]]; then
report_error "${CURRENT_VERSION} is the latest!\n"
fi
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")
git cherry-pick ${RANGE}
if [[ $? -ne 0 ]]; then
report_error "Cherry-pick needs manual intervention! Resolve conflicts then run:
git add . && git cherry-pick --continue"
else
header "${TARGET_VERSION} PICKED CLEANLY!" ${GRN}
fi ;;
"merge")
GIT_MERGE_VERBOSITY=1 git merge --no-edit v${TARGET_VERSION}
if [[ $? -ne 0 ]]; then
report_error "Merge needs manual intervention!
Resolve conflicts then run git merge --continue!"
else
header "${TARGET_VERSION} MERGED CLEANLY!" ${GRN}
fi ;;
esac
}
parse_parameters $@
update_remote
generate_versions
update_to_target_version