forked from android-linux-stable/script
-
Notifications
You must be signed in to change notification settings - Fork 1
/
linux-stable.sh
executable file
·282 lines (231 loc) · 9.02 KB
/
linux-stable.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
#!/usr/bin/env bash
#
# Pull in linux-stable updates to a kernel tree
#
# Copyright (C) 2017-2018 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/>
# Colors for script
BOLD="\033[1m"
GRN="\033[01;32m"
RED="\033[01;31m"
RST="\033[0m"
YLW="\033[01;33m"
# Log function
branch=$(git rev-parse --abbrev-ref HEAD)
KARNAL="--tags https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/"
USER=$(git config --get user.name)
EMAIL=$(git config --get user.email)
# 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 ${KARNAL}; 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 tag_logs() {
git log --oneline --pretty=format:' %s' ${RANGE}
}
function create_merge_message {
[[ -f '/tmp/merge_msg' ]] && rm -f '/tmp/merge_msg'
echo "Linux: ${TARGET_VERSION} release" > '/tmp/merge_msg'
echo -en "\n" >> '/tmp/merge_msg'
echo "Changes in '${TARGET_VERSION}': ($(git rev-list v${CURRENT_VERSION}..v${TARGET_VERSION} --count) commits)" >> '/tmp/merge_msg'
echo "$(tag_logs)" >> '/tmp/merge_msg'
echo "\nSigned-off-by: ${USER} <${EMAIL}>" >> '/tmp/merge_msg'
}
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 --edit -F '/tmp/merge_msg' "v${TARGET_VERSION}" --no-edit; then
die "Merge needs manual intervention!
Resolve conflicts then run git commit!"
else
header "${TARGET_VERSION} MERGED CLEANLY!" "${GRN}"
git commit -q --amend -F '/tmp/merge_msg' --no-edit
fi ;;
esac
}
parse_parameters "$@"
update_remote
generate_versions
create_merge_message
update_to_target_version