-
Notifications
You must be signed in to change notification settings - Fork 146
/
Copy pathinstall
executable file
·354 lines (276 loc) · 10.7 KB
/
install
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
#!/usr/bin/env bash
set -o nounset -o pipefail -o errexit
# shellcheck source=../lib/utils.sh
source "$(dirname "$0")/../lib/utils.sh"
NODEJS_CHECK_SIGNATURES="${NODEJS_CHECK_SIGNATURES:-strict}"
install_nodejs() {
local install_type="$1"
local version_query="$2"
local install_path="$3"
local tmp_download_dir="$4"
local version="$(resolve_version_query "$version_query")"
if [ "$version" != "$version_query" ]; then
install_aliased_version "$version" "$version_query" "$install_path"
else
install_canon_version "$1" "$version" "$3" "$4"
fi
}
install_canon_version() {
local install_type="$1"
local version="$2"
local install_path="$3"
local tmp_download_dir="$4"
local make_flags="-j${ASDF_CONCURRENCY-1}"
## Do this first as it is fast but could fail.
download_and_verify_checksums "$install_type" "$version" "$tmp_download_dir"
local archive_path
archive_path="${tmp_download_dir}/$(get_archive_file_name "$install_type" "$version")"
local download_result=0
download_file "$(get_download_url "$install_type" "$version")" "${archive_path}" \
|| download_result=$?
if [ $download_result != 0 ]; then
if [ "$install_type" = "ref" ]; then
die "Source code not found for version $version"
fi
echo "Binary not found for version $version. Falling back to source code"
install_type="ref"
download_file "$(get_download_url "$install_type" "$version")" "${archive_path}" \
|| die "Source code not found for version $version"
else
verify_archive "$tmp_download_dir"
fi
# running this in a subshell
# we don't want to disturb current working dir
(
if [ "$install_type" != "version" ]; then
tar zxf "$archive_path" -C "$install_path" --strip-components=1 || exit 1
cd "$install_path" || exit 1
local configure_options
configure_options="$(construct_configure_options "$install_path")"
# shellcheck disable=SC2086
./configure $configure_options || exit 1
make $make_flags || exit 1
make $make_flags install || exit 1
if [ $? -ne 0 ]; then
rm -rf "$install_path"
exit 1
fi
else
tar zxf "$archive_path" -C "$install_path" --strip-components=1 || exit 1
fi
)
}
install_aliased_version() {
local version=$1
local version_query=$2
local install_path=$3
# install the true version and only symlink it to the alias
>&2 echo "Installing alias $version_query as $version"
asdf install "$(plugin_name)" "$version" \
|| die "Could not install version $version"
if [ -L "$install_path" ]; then
rm "$install_path"
else
rmdir "$install_path"
fi
>&2 echo "Linking \"$version_query\" to \"$version\""
ln -s "$(asdf where "$(plugin_name)" "$version")" "$install_path"
}
resolve_version_query() {
local version_query="$1"
local canon_version="$(
# Find the first candidate which the alias match, then print it version
print_index_tab \
| awk -F'\t' -v "alias=$version_query" '$1 == alias { print $2; exit }'
)"
if [ -z "$canon_version" ]; then
echo "$version_query"
else
echo "$canon_version"
fi
}
construct_configure_options() {
local install_path="$1"
if [ -z "${NODEJS_CONFIGURE_OPTIONS:-}" ]; then
local configure_options
configure_options="--dest-cpu=$(get_nodejs_machine_hardware_name)"
if [ "${NODEJS_EXTRA_CONFIGURE_OPTIONS:-}" != "" ]; then
configure_options="$configure_options ${NODEJS_EXTRA_CONFIGURE_OPTIONS:-}"
fi
else
local configure_options="${NODEJS_CONFIGURE_OPTIONS:-}"
fi
configure_options="$configure_options --prefix=$install_path"
echo "$configure_options"
}
get_nodejs_machine_hardware_name() {
local machine_hardware_name
machine_hardware_name="$(uname -m)"
case "$machine_hardware_name" in
'x86_64') local cpu_type="x64";;
# For FreeBSD
'amd64') local cpu_type="x64";;
'i686') local cpu_type="x86";;
'aarch64') local cpu_type="arm64";;
*) local cpu_type="$machine_hardware_name";;
esac
echo "$cpu_type"
}
download_file() {
local download_url="$1"
local download_path="$2"
STATUSCODE=$(curl --write-out "%{http_code}" -Lo "$download_path" "$download_url")
if test $STATUSCODE -eq 404; then
return 1
fi
}
get_archive_file_name() {
local install_type="$1"
local version="$2"
local pkg_name
if [ "$install_type" = "version" ]; then
pkg_name="node-v${version}-$(uname -s | tr '[:upper:]' '[:lower:]')-$(get_nodejs_machine_hardware_name)"
else
pkg_name="v${version}"
fi
echo "${pkg_name}.tar.gz"
}
get_download_url() {
local install_type="$1"
local version="$2"
if [ "$install_type" = "version" ]; then
local download_url_base="${NODEJS_ORG_MIRROR}v${version}"
else
local download_url_base="https://github.com/nodejs/node/archive"
fi
echo "${download_url_base}/$(get_archive_file_name "$install_type" "$version")"
}
get_signed_checksum_download_url() {
local install_type=$1
local version=$2
if [ "$install_type" = "version" ]; then
echo "${NODEJS_ORG_MIRROR}v${version}/SHASUMS256.txt.asc"
else
# Not implemented.
exit 1
fi
}
download_and_verify_checksums() {
local install_type="$1"
local version="$2"
local tmp_download_dir="$3"
if [ "${NODEJS_CHECK_SIGNATURES}" == "no" ]; then
return 0
fi
## Seems nodejs.org started with around 0.10.0 to release properly signed SHA2-256 checksum files.
if verlte "0.10.0" "$version"
then
local signed_checksum_file="$tmp_download_dir/SHASUMS256.txt.asc"
local signed_checksum_download_url
signed_checksum_download_url="$(get_signed_checksum_download_url "$install_type" "$version")"
if [ -z "${signed_checksum_download_url}" ]; then
if [ "${NODEJS_CHECK_SIGNATURES}" == "strict" ]; then
echo "$version did not provide signed checksums or support for them has not been implemented and NODEJS_CHECK_SIGNATURES=strict is set. Exiting." >&2
exit 1
else
echo "$version did not provide signed checksums or support for them has not been implemented. Continue without signature checking." >&2
return 0
fi
fi
download_file "${signed_checksum_download_url}" "$signed_checksum_file" \
|| die "Checksum not found for version $version"
local gnugp_verify_command_name
gnugp_verify_command_name="$(command -v gpg gpg2 | head -n 1 || :)"
if [ -z "${gnugp_verify_command_name}" ]; then
echo "You must install GnuPG to verify the authenticity of the downloaded archives before continuing with the install: https://www.gnupg.org/" >&2
exit 1
fi
(
if [ -z "${GNUPGHOME:-}" ] && [ -d "${ASDF_DIR:-$HOME/.asdf}/keyrings/nodejs" ]; then
export GNUPGHOME="${ASDF_DIR:-$HOME/.asdf}/keyrings/nodejs"
fi
# Automatically add needed PGP keys
"$(dirname "$0")/import-release-team-keyring"
if ! $gnugp_verify_command_name --no-default-keyring --keyring "${ASDF_NODEJS_KEYRING}" --display-charset utf-8 --verify "$signed_checksum_file" 2>/dev/null; then
# Try default keyring
if ! $gnugp_verify_command_name --display-charset utf-8 --verify "$signed_checksum_file" 2>/dev/null; then
echo "Authenticity of checksum file can not be assured! Please be sure to check the README of asdf-nodejs in case you did not yet import the needed PGP keys. Also, make sure the plugin is up-to-date by running \`asdf plugin update $(plugin_name)\`. If you already did that then that is the point to become SUSPICIOUS! There must be a reason why this is failing. If you are installing an older NodeJS version you might need to import OpenPGP keys of previous release managers. Exiting." >&2
exit 1
fi
fi
## Mitigates: https://github.com/nodejs/node/issues/6821
local authentic_checksum_file="$tmp_download_dir/authentic_SHASUMS256.txt"
$gnugp_verify_command_name --no-default-keyring --keyring "${ASDF_NODEJS_KEYRING}" --yes --output "${authentic_checksum_file}" --decrypt "$signed_checksum_file" 2>/dev/null ||
$gnugp_verify_command_name --yes --output "${authentic_checksum_file}" --decrypt "$signed_checksum_file" 2>/dev/null
)
elif [ "${NODEJS_CHECK_SIGNATURES}" == "strict" ]; then
echo "$version did not provide signed checksums or support for them has not been implemented and NODEJS_CHECK_SIGNATURES=strict is set. Exiting." >&2
exit 1
fi
}
checkShasum ()
{
local archive_file_name="${1}"
local authentic_checksum_file="${2}"
if $(command -v sha256sum >/dev/null 2>&1); then
sha256sum \
-c <(grep "\s${archive_file_name}$" "${authentic_checksum_file}")
elif $(command -v shasum >/dev/null 2>&1); then
shasum \
-a 256 \
-c <(grep "\s${archive_file_name}$" "${authentic_checksum_file}")
else
echo "sha256sum or shasum is not available for use" >&2
return 1
fi
}
verify_archive() {
local tmp_download_dir="$1"
local authentic_checksum_file="$tmp_download_dir/authentic_SHASUMS256.txt"
if [ "${NODEJS_CHECK_SIGNATURES}" == "no" ]; then
return 0
fi
if [ "${NODEJS_CHECK_SIGNATURES}" == "yes" ] && [ ! -e "${authentic_checksum_file}" ]; then
return 0
fi
if verlte "0.10.0" "$version"
then
local archive_file_name
archive_file_name="$(basename "$(get_download_url "$install_type" "$version")")"
(
cd "${tmp_download_dir}"
if ! checkShasum "$archive_file_name" "$authentic_checksum_file"; then
echo "Authenticity of package archive can not be assured. Exiting." >&2
exit 1
fi
)
fi
}
# stolen from https://github.com/rbenv/ruby-build/pull/631/files#diff-fdcfb8a18714b33b07529b7d02b54f1dR942
function sort_versions() {
sed 'h; s/[+-]/./g; s/.p\([[:digit:]]\)/.z\1/; s/$/.z/; G; s/\n/ /' | \
LC_ALL=C sort -t. -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5n | awk '{print $2}'
}
verlte() {
## https://stackoverflow.com/questions/4023830/how-compare-two-strings-in-dot-separated-version-format-in-bash/4024263#4024263
[ "$1" = "$(echo -e "$1\n$2" | sort_versions | head -n1)" ]
}
install_default_npm_packages() {
local default_npm_packages="${ASDF_NPM_DEFAULT_PACKAGES_FILE:=$HOME/.default-npm-packages}"
if [ ! -f "$default_npm_packages" ]; then return; fi
cat "$default_npm_packages" | while read -r name; do
echo -ne "\nInstalling \033[33m${name}\033[39m npm package... "
source "$(dirname "$0")/exec-env"
PATH="$ASDF_INSTALL_PATH/bin:$PATH" npm install -g "$name" > /dev/null 2>&1 && rc=$? || rc=$?
if [[ $rc -eq 0 ]]; then
echo -e "\033[32mSUCCESS\033[39m"
else
echo -e "\033[31mFAIL\033[39m"
fi
done
}
tmp_download_dir="$(mktemp -d -t 'asdf_nodejs_XXXXXX')"
trap 'rm -rf "${tmp_download_dir}"' EXIT
install_nodejs "$ASDF_INSTALL_TYPE" "$ASDF_INSTALL_VERSION" "$ASDF_INSTALL_PATH" "$tmp_download_dir"
ASDF_SKIP_RESHIM=1 install_default_npm_packages
asdf reshim "$(plugin_name)" "$ASDF_INSTALL_VERSION"