-
Notifications
You must be signed in to change notification settings - Fork 372
/
install.sh
executable file
·398 lines (339 loc) · 14.9 KB
/
install.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
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
#!/bin/bash
# Exit on fail.
set -eE
RESET='\e[0m'
# Simplify colors and print errors to stderr (2).
echo_error() { echo -e "\e[1;91m${*}${RESET}" >&2; } # Use Light Red for errors.
echo_info() { echo -e "\e[1;33m${*}${RESET}" >&1; } # Use Yellow for informational messages.
echo_success() { echo -e "\e[1;32m${*}${RESET}" >&1; } # Use Green for success messages.
echo_intra() { echo -e "\e[1;34m${*}${RESET}" >&1; } # Use Blue for intrafunction messages.
echo_out() { echo -e "\e[0;37m${*}${RESET}" >&1; } # Use Gray for program output.
# Print a message before exit on error
trap "echo_error 'An error occured during the installation :/'" ERR
# Check if the script is being run as root.
if [ "${EUID}" == "0" ]; then
echo_error "Chromebrew should not be installed or run as root."
echo_info "Please login as 'chronos' and restart the install."
exit 1
fi
# Reject crostini.
if [[ -d /opt/google/cros-containers && "${CREW_FORCE_INSTALL}" != '1' ]]; then
echo_error "Crostini containers are not supported by Chromebrew :/"
echo_info "Run 'CREW_FORCE_INSTALL=1 exec bash --init-file <(curl -Ls git.io/vddgY)' to perform install anyway"
exit 1
fi
# Reject non-stable Chrome OS channels.
if [ -f /etc/lsb-release ]; then
if [[ ! "$(< /etc/lsb-release)" =~ CHROMEOS_RELEASE_TRACK=stable-channel$'\n' && "${CREW_FORCE_INSTALL}" != '1' ]]; then
echo_error "The beta, dev, and canary channel are unsupported by Chromebrew."
echo_info "Run 'CREW_FORCE_INSTALL=1 exec bash --init-file <(curl -Ls git.io/vddgY)' to perform install anyway."
exit 1
fi
export "$(grep CHROMEOS_RELEASE_CHROME_MILESTONE /etc/lsb-release)"
else
echo_info "Unable to detect system information, installation will continue."
fi
# Check if the user owns the CREW_PREFIX directory, as sudo is unnecessary if this is the case.
# Check if the user is on ChromeOS v117+ and not in the VT-2 console, as sudo will not work.
: "${CREW_PREFIX:=/usr/local}"
if [[ "$(stat -c '%u' "${CREW_PREFIX}")" == "$(id -u)" ]] && sudo 2>&1 | grep -q 'no new privileges'; then
echo_error "Please run the installer in the VT-2 shell."
echo_info "To start the VT-2 session, type Ctrl + Alt + ->"
exit 1
fi
# Make sure installation directory is clean.
if [ -d "${CREW_PREFIX}" ]; then
if [ "$(ls -A "${CREW_PREFIX}")" ]; then
echo_error "${CREW_PREFIX} is not empty, would you like it to be cleared?"
echo_info "This will delete ALL files in ${CREW_PREFIX}!"
echo_info "Continue?"
select continue in "Yes" "No"; do
if [[ "${continue}" == "Yes" ]]; then
sudo find "${CREW_PREFIX}" -mindepth 1 -delete
break 2
else
exit 1
fi
done
fi
else
sudo mkdir -p "${CREW_PREFIX}"
fi
# Do not redundantly use sudo if the user already owns the directory.
if [ "$(stat -c '%u' "${CREW_PREFIX}")" != "$(id -u)" ]; then
# This will allow things to work without sudo.
sudo chown "$(id -u)":"$(id -g)" "${CREW_PREFIX}"
fi
# Default chromebrew repo values.
: "${OWNER:=chromebrew}"
: "${REPO:=chromebrew}"
: "${BRANCH:=master}"
# Chromebrew directories.
CREW_LIB_PATH="${CREW_PREFIX}/lib/crew"
CREW_CONFIG_PATH="${CREW_PREFIX}/etc/crew"
CREW_BREW_DIR="${CREW_PREFIX}/tmp/crew"
CREW_DEST_DIR="${CREW_BREW_DIR}/dest"
: "${CREW_CACHE_DIR:=$CREW_PREFIX/tmp/packages}"
# Architecture
# For container usage, where we want to specify i686 arch
# on a x86_64 host by setting ARCH=i686.
: "${ARCH:=$(uname -m)}"
# For container usage, when we are emulating armv7l via linux32, where uname -m will report armv8l.
# Additionally, if the architecture is aarch64, set it to armv7l, as we treat as if it was armv7l.
# When we have proper support for aarch64, remove this.
if [[ "${ARCH}" = "armv8l" ]] || [[ "${ARCH}" = "aarch64" ]]; then
ARCH='armv7l'
fi
if [[ "$ARCH" == "x86_64" ]]; then
LIB_SUFFIX='64'
fi
# Package version string may include LIBC_VERSION.
LIBC_VERSION=$(/lib"$LIB_SUFFIX"/libc.so.6 2>/dev/null | awk 'match($0, /Gentoo ([^-]+)/) {print substr($0, RSTART+7, RLENGTH-7)}')
# Warn users of the AMD segfault issue and allow them to work around it.
# The easiest way to distinguish StoneyRidge platorms is to check for the FMA4
# instruction, as it was first introduced in Bulldozer and later dropped in Zen.
if grep -s "fma4" /proc/cpuinfo ; then
echo_info "Notice: You are running an AMD StoneyRidge device; due to some bugs some packages may fail with a segmentation fault and need to be rebuilt."
echo_info "If this happens, please report them to: https://github.com/chromebrew/chromebrew/issues"
echo_info "If the install fails, try running 'CREW_AMD_INSTALL=1 exec bash --init-file <(curl -Ls git.io/vddgY)'"
if [ "${CREW_AMD_INSTALL}" == "1" ]; then
# Otherwise one may get segfaults during install on stoneyridge devices.
# See https://github.com/chromebrew/chromebrew/issues/8823
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
fi
fi
echo_success "Welcome to Chromebrew!"
# Prompt user to enter the sudo password if it is set.
# If the PASSWD_FILE specified by chromeos-setdevpasswd exist, that means a sudo password is set.
if [[ "$(< /usr/sbin/chromeos-setdevpasswd)" =~ PASSWD_FILE=\'([^\']+) ]] && [ -f "${BASH_REMATCH[1]}" ]; then
echo_intra "Please enter the developer mode password."
# Reset sudo timeout.
sudo -k
sudo /bin/true
fi
# Force curl to use system libraries.
function curl () {
# Retry if download failed.
# The --retry/--retry-all-errors parameter in curl will not work with
# the 'curl: (7) Couldn't connect to server' error, a for loop is used
# here.
for (( i = 0; i < 4; i++ )); do
if [[ "$ARCH" == "i686" ]]; then
# i686 curl throws a "SSL certificate problem: self signed certificate in certificate chain" error.
env -u LD_LIBRARY_PATH curl -kC - "${@}" && return 0
else
# Force TLS as we know GitLab supports it.
env -u LD_LIBRARY_PATH curl --ssl-reqd --tlsv1.2 -C - "${@}" && return 0
fi
echo_info "Retrying, $((3-i)) retries left."
done
# The download failed if we're still here.
echo_error "Download failed :/ Please check your network settings."
return 1
}
# This will create the directories.
crew_folders="bin cache doc docbook include lib/crew/packages lib$LIB_SUFFIX libexec man sbin share var etc/crew/meta etc/env.d tmp/crew/dest"
# shellcheck disable=SC2086
# Quoting crew_folders leads to breakage.
(cd "${CREW_PREFIX}" && mkdir -p ${crew_folders})
# Remove old git config directories if they exist.
find "${CREW_LIB_PATH}" -mindepth 1 -delete
# Download the chromebrew repository.
curl -L --progress-bar https://github.com/"${OWNER}"/"${REPO}"/tarball/"${BRANCH}" | tar -xz --strip-components=1 -C "${CREW_LIB_PATH}"
BOOTSTRAP_PACKAGES='zstd crew_mvdir ruby git ca_certificates libyaml openssl'
# Older i686 systems.
[[ "${ARCH}" == "i686" ]] && BOOTSTRAP_PACKAGES+=' zlibpkg gcc_lib'
if [[ -n "${CHROMEOS_RELEASE_CHROME_MILESTONE}" ]]; then
# shellcheck disable=SC2231
for i in /lib$LIB_SUFFIX/libc.so*
do
sudo cp "$i" "$CREW_PREFIX/lib$LIB_SUFFIX/"
libcname=$(basename "$i")
sudo chown chronos "$CREW_PREFIX/lib$LIB_SUFFIX/${libcname}"
sudo chmod 644 "$CREW_PREFIX/lib$LIB_SUFFIX/${libcname}"
done
if (( "${CHROMEOS_RELEASE_CHROME_MILESTONE}" > "112" )); then
# Recent Arm systems have a cut down system.
[[ "${ARCH}" == "armv7l" ]] && BOOTSTRAP_PACKAGES+=' bzip2 ncurses readline pcre2 gcc_lib'
if (( "${CHROMEOS_RELEASE_CHROME_MILESTONE}" < "123" )); then
# Append the correct packages for systems running M122 and lower.
BOOTSTRAP_PACKAGES+=' glibc_lib235 zlibpkg gmp'
elif (( "${CHROMEOS_RELEASE_CHROME_MILESTONE}" > "122" )); then
# Append the correct packages for systems running M123 onwards.
BOOTSTRAP_PACKAGES+=' glibc_lib237 zlibpkg gmp'
fi
fi
fi
# Create the device.json file.
cd "${CREW_CONFIG_PATH}"
echo_info "\nCreating device.json."
jq --arg key0 'architecture' --arg value0 "${ARCH}" \
--arg key1 'installed_packages' \
'. | .[$key0]=$value0 | .[$key1]=[]' <<<'{}' > device.json
# Functions to maintain packages.
# These functions are for handling packages.
function download_check () {
cd "$CREW_BREW_DIR"
# Use cached file if available and caching is enabled.
if [ -n "$CREW_CACHE_ENABLED" ] && [[ -f "$CREW_CACHE_DIR/${3}" ]] ; then
mkdir -p "$CREW_CACHE_DIR"
sudo chown -R "$(id -u)":"$(id -g)" "$CREW_CACHE_DIR" || true
echo_intra "Verifying cached ${1}..."
echo_success "$(echo "${4}" "$CREW_CACHE_DIR/${3}" | sha256sum -c -)"
case "${?}" in
0)
ln -sf "$CREW_CACHE_DIR/${3}" "$CREW_BREW_DIR/${3}" || true
return
;;
*)
echo_error "Verification of cached ${1} failed, downloading."
esac
fi
# Download
echo_intra "Downloading ${1}..."
curl '-#' -L "${2}" -o "${3}"
# Verify
echo_intra "Verifying ${1}..."
if echo "${4}" "${3}" | sha256sum -c - ; then
if [ -n "$CREW_CACHE_ENABLED" ] ; then
cp "${3}" "$CREW_CACHE_DIR/${3}" || true
fi
echo_success "Verification of ${1} succeeded."
return 0
else
if [[ ${5} -lt 2 ]]; then
echo_error "Verification of ${1} failed, something may be wrong with the download."
exit 1
else
echo_info "Verification of ${1} failed. Will try another sha256 hash if available."
return 1
fi
fi
}
function extract_install () {
# Start with a clean slate.
rm -rf "${CREW_DEST_DIR}"
mkdir "${CREW_DEST_DIR}"
cd "${CREW_DEST_DIR}"
# Extract and install.
echo_intra "Extracting ${1} ..."
# This could be avoided if our zstd was compiled with lzma support.
if [[ "${2##*.}" == "zst" ]]; then
tar -I zstd -xpf ../"${2}"
else
tar xpf ../"${2}"
fi
echo_intra "Installing ${1} ..."
tar cpf - ./*/* | (cd /; tar xp --keep-directory-symlink -m -f -)
mv ./dlist "${CREW_CONFIG_PATH}/meta/${1}.directorylist"
mv ./filelist "${CREW_CONFIG_PATH}/meta/${1}.filelist"
}
function update_device_json () {
cd "${CREW_CONFIG_PATH}"
echo_intra "Adding new information on ${1} to device.json..."
new_info=$(jq --arg name "$1" --arg version "$2" --arg sha256 "$3" '.installed_packages |= . + [{"name": $name, "version": $version, "binary_sha256": $sha256}]' device.json)
cat <<< "${new_info}" > device.json
}
echo_info "Downloading Bootstrap packages...\n"
# Extract, install and register packages.
for package in $BOOTSTRAP_PACKAGES; do
cd "${CREW_LIB_PATH}/packages"
version=$(grep "\ \ version" "${package}.rb" | head -n 1 | sed "s/#{LIBC_VERSION}/$LIBC_VERSION/g" | awk '{print substr($2,2,length($2)-2)}')
binary_compression=$(sed -n "s/.*binary_compression '\([^']*\)'.*/\1/p" "${package}.rb")
if [[ -z "$binary_compression" ]]; then
binary_compression='tar.zst'
fi
url="https://gitlab.com/api/v4/projects/26210301/packages/generic/${package}/${version}_${ARCH}/${package}-${version}-chromeos-${ARCH}.${binary_compression}"
tarfile=$(basename "${url}")
sha256=$(sed -n "s/.*${ARCH}: '\([^']*\)'.*/\1/p" "${package}.rb")
shacount=$(echo "$sha256" | wc -w)
for sha in $sha256
do
if download_check "${package}" "${url}" "${tarfile}" "${sha}" "${shacount}"; then
extract_install "${package}" "${tarfile}"
update_device_json "${package}" "${version}" "${sha}"
fi
done
done
# Work around https://github.com/chromebrew/chromebrew/issues/3305.
# shellcheck disable=SC2024
sudo ldconfig &> /tmp/crew_ldconfig || true
echo_out "\nCreating symlink to 'crew' in ${CREW_PREFIX}/bin/"
ln -sfv "../lib/crew/bin/crew" "${CREW_PREFIX}/bin/"
echo_out "Set up and synchronize local package repo..."
# Set LD_LIBRARY_PATH so crew doesn't break on i686, xz doesn't fail on
# x86_64, and the mandb postinstall doesn't fail in newer arm
# containers.
echo "LD_LIBRARY_PATH=$CREW_PREFIX/lib${LIB_SUFFIX}:/lib${LIB_SUFFIX}" >> "$CREW_PREFIX"/etc/env.d/00-library
export LD_LIBRARY_PATH="${CREW_PREFIX}/lib${LIB_SUFFIX}:/lib${LIB_SUFFIX}"
echo "export CREW_PREFIX=${CREW_PREFIX}" >> "${CREW_PREFIX}/etc/env.d/profile"
# Install activesupport gem for ruby
echo_info 'Installing essential ruby gems.'
gem update -N --system
gem install -N activesupport --conservative
gem install -N concurrent-ruby --conservative
# Since we downloaded the package repo, just update package compatibility information.
crew update compatible
echo_info "Installing core Chromebrew packages...\n"
yes | crew install core
echo_info "\nRunning Bootstrap package postinstall scripts...\n"
# Due to a bug in crew where it accepts spaces in package files names rather than
# splitting strings at spaces, we cannot quote ${BOOTSTRAP_PACKAGES}.
# shellcheck disable=SC2086
crew postinstall ${BOOTSTRAP_PACKAGES}
if ! "${CREW_PREFIX}"/bin/git version &> /dev/null; then
echo_error "\nGit is broken on your system, and crew update will not work properly."
echo_error "Please report this here:"
echo_error "https://github.com/chromebrew/chromebrew/issues\n\n"
else
echo_info "Synchronizng local package repo..."
cd "${CREW_LIB_PATH}"
# Make the git default branch error messages go away.
git config --global init.defaultBranch main
# Setup the folder with git information.
git init --ref-format=reftable
git remote add origin "https://github.com/${OWNER}/${REPO}"
# Checkout, overwriting local files.
git fetch --all
git checkout -f "${BRANCH}"
# Set sparse-checkout folders.
git sparse-checkout set packages "manifest/${ARCH}" lib commands bin crew tests tools
git reset --hard origin/"${BRANCH}"
# Set mtimes of files to when the file was committed.
git-restore-mtime -sq 2>/dev/null
fi
echo -e "${RESET}"
echo " . .
..,:;;;::'..
.':lllllllool,.
...cl;..... ,::;'.
.'oc...;::::..0KKo.
.'od: .:::::, lolc.
.'lNMMMO ;ooc.,XMMWx;:;.
.dMMMMMMXkMMMMxoMMMMMMMMO.
.:O0NMMMMMMMMMM0MMMMMN0Oc.
.:xdloddddddoXMMMk:x:....
.xMNOKX0OOOOxcodlcXMN0O0XKc.
.OMXOKXOOOOOk;ol:OXMK...;N0.
'XMKOXXOOOOOk:docOKMW, .kW;
.cMMKOXXOOOOOOOOOOO0MM; .lMc.
.cMM00XKOOOOkkkkkkOOWMl. .cMo.
.lMWO0XKOOOkkkkkkkkONMo. ;Wk.
.oMNO0X0OOkkkkkkkkkOXMd..,oW0'
.xMNO0X0OOkkkkkkkkkkXMWKXKOx;.
.0MXOOOOOOkkkkkkkkkOKM0..
'NMWNXXKK000000KKXNNMMX.
.;okk0XNWWMMMMWWNKOkdc'.
.....'cc:cc:''..."
echo " ___ _ _
/ (_)|\ |\\
| ||__ ,_ __ _ _ _ __ |/_ ,_ __ _ _ _
| |/ | / | / \/ |/ |/ | |_/ | \/ | |_/ /| | |\_
\___/| |_/ |_/\__/ | | |_/|__/\__/ |_/|__/ \_/ \_/
"
echo_intra "
Edit ${CREW_PREFIX}/etc/env.d/03-pager to change the default PAGER.
most is used by default
You may wish to edit the ${CREW_PREFIX}/etc/env.d/02-editor file for an editor default.
Chromebrew provides nano, vim and emacs as default TUI editor options."
echo_success "Chromebrew installed successfully and package lists updated."