Skip to content

Commit 5784bed

Browse files
committed
Validate & checksum downloaded artifacts
1 parent b6d270a commit 5784bed

File tree

6 files changed

+118
-31
lines changed

6 files changed

+118
-31
lines changed

src/main/bash/sdkman-install.sh

+64-26
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,36 @@ function __sdk_install() {
5959
}
6060

6161
function __sdkman_install_candidate_version() {
62-
local candidate version
63-
62+
local candidate version base_name headers_file archive_type
63+
local metadata_folder="${SDKMAN_DIR}/var/metadata"
64+
6465
candidate="$1"
6566
version="$2"
67+
base_name="${candidate}-${version}"
68+
headers_file="${metadata_folder}/${base_name}.headers"
69+
70+
mkdir -p ${metadata_folder}
6671

67-
__sdkman_download "$candidate" "$version" || return 1
72+
__sdkman_download "$candidate" "$version" "$headers_file" || return 1
6873
__sdkman_echo_green "Installing: ${candidate} ${version}"
6974

7075
mkdir -p "${SDKMAN_CANDIDATES_DIR}/${candidate}"
71-
7276
rm -rf "${SDKMAN_DIR}/tmp/out"
73-
unzip -oq "${SDKMAN_DIR}/tmp/${candidate}-${version}.bin" -d "${SDKMAN_DIR}/tmp/out"
77+
78+
archive_type=$(sed -n 's/^X-Sdkman-ArchiveType:\(.*\)$/\1/p' ${headers_file} | tr -cd '[:alnum:]')
79+
80+
if [[ "${archive_type}" == 'zip' ]]; then
81+
unzip -oq "${SDKMAN_DIR}/tmp/${base_name}.bin" -d "${SDKMAN_DIR}/tmp/out"
82+
elif [[ "${archive_type}" == 'tar' ]]; then
83+
mkdir -p "${SDKMAN_DIR}/tmp/out"
84+
tar zxf "${SDKMAN_DIR}/tmp/${base_name}.bin" -C "${SDKMAN_DIR}/tmp/out"
85+
else
86+
echo ""
87+
__sdkman_echo_red "Stop! The archive type cannot be determined! Please try installing again."
88+
rm -f "${SDKMAN_DIR}/tmp/${base_name}.bin"
89+
return 1
90+
fi
91+
7492
mv -f "$SDKMAN_DIR"/tmp/out/* "${SDKMAN_CANDIDATES_DIR}/${candidate}/${version}"
7593
__sdkman_echo_green "Done installing!"
7694
echo ""
@@ -114,22 +132,18 @@ function __sdkman_install_local_version() {
114132
}
115133

116134
function __sdkman_download() {
117-
local candidate version
135+
local candidate version headers_file
118136

119137
candidate="$1"
120138
version="$2"
139+
headers_file="$3"
121140

122-
metadata_folder="${SDKMAN_DIR}/var/metadata"
123-
mkdir -p ${metadata_folder}
124-
125141
local platform_parameter="$(echo $SDKMAN_PLATFORM | tr '[:upper:]' '[:lower:]')"
126142
local download_url="${SDKMAN_CANDIDATES_API}/broker/download/${candidate}/${version}/${platform_parameter}"
127143
local base_name="${candidate}-${version}"
128144
local tmp_headers_file="${SDKMAN_DIR}/tmp/${base_name}.headers.tmp"
129-
local headers_file="${metadata_folder}/${base_name}.headers"
130145

131146
export local binary_input="${SDKMAN_DIR}/tmp/${base_name}.bin"
132-
export local zip_output="${SDKMAN_DIR}/tmp/${base_name}.zip"
133147

134148
echo ""
135149
__sdkman_echo_no_colour "Downloading: ${candidate} ${version}"
@@ -142,26 +156,50 @@ function __sdkman_download() {
142156
grep '^X-Sdkman' "${tmp_headers_file}" > "${headers_file}"
143157
__sdkman_echo_debug "Downloaded binary to: ${binary_input} (HTTP headers written to: ${headers_file})"
144158

145-
__sdkman_validate_zip "${binary_input}" || return 1
146-
__sdkman_checksum_zip "${binary_input}" "${headers_file}" || return 1
147-
echo ""
159+
if [[ ! -s "${headers_file}" ]]; then
160+
echo ""
161+
__sdkman_echo_red "Metadata file not found (or is empty) at '${headers_file}'"
162+
rm -f "${binary_input}"
163+
return 1
164+
else
165+
__sdkman_validate "${binary_input}" "${headers_file}" || return 1
166+
__sdkman_checksum "${binary_input}" "${headers_file}" || return 1
167+
echo ""
168+
fi
148169
}
149170

150-
function __sdkman_validate_zip() {
151-
local zip_archive zip_ok
171+
function __sdkman_validate() {
172+
local -r archive="$1"
173+
local -r headers_file="$2"
174+
local -r archive_type=$(sed -n 's/^X-Sdkman-ArchiveType:\(.*\)$/\1/p' ${headers_file} | tr -cd '[:alnum:]')
175+
local is_ok
176+
177+
__sdkman_echo_debug "Archive Type: ${archive_type}"
178+
__sdkman_echo_debug "Archive: ${archive}"
179+
180+
if [[ "${archive_type}" == 'zip' ]]; then
181+
__sdkman_echo_debug "Checking zip archive"
182+
is_ok=$(unzip -t "$archive" | grep 'No errors detected in compressed data')
183+
elif [[ "${archive_type}" == 'tar' ]]; then
184+
__sdkman_echo_debug "Checking tar archive"
185+
is_ok=$(tar tf "$archive" | grep -v 'Error opening archive')
186+
else
187+
echo ""
188+
__sdkman_echo_red "Stop! The archive type cannot be determined! Please try installing again."
189+
rm -f "${archive}"
190+
return 1
191+
fi
152192

153-
zip_archive="$1"
154-
zip_ok=$(unzip -t "$zip_archive" | grep 'No errors detected in compressed data')
155-
if [ -z "$zip_ok" ]; then
156-
rm -f "$zip_archive"
193+
if [ -z "$is_ok" ]; then
194+
rm -f "$archive"
157195
echo ""
158196
__sdkman_echo_red "Stop! The archive was corrupt and has been removed! Please try installing again."
159197
return 1
160198
fi
161199
}
162200

163-
function __sdkman_checksum_zip() {
164-
local -r zip_archive="$1"
201+
function __sdkman_checksum() {
202+
local -r archive="$1"
165203
local -r headers_file="$2"
166204
local algorithm checksum cmd
167205
local shasum_avail=false
@@ -198,17 +236,17 @@ function __sdkman_checksum_zip() {
198236
if [[ -n ${algorithm} && -n ${checksum} ]]; then
199237

200238
if [[ "$algorithm" =~ 'SHA' && "$shasum_avail" == 'true' ]]; then
201-
cmd="echo \"${checksum} *${zip_archive}\" | shasum --check --quiet"
239+
cmd="echo \"${checksum} *${archive}\" | shasum --check --quiet"
202240

203241
elif [[ "$algorithm" =~ 'MD5' && "$md5sum_avail" == 'true' ]]; then
204-
cmd="echo \"${checksum} ${zip_archive}\" | md5sum --check --quiet"
242+
cmd="echo \"${checksum} ${archive}\" | md5sum --check --quiet"
205243
fi
206244

207245
if [[ -n $cmd ]]; then
208-
__sdkman_echo_no_colour "Verifying artifact: ${zip_archive} (${algorithm}:${checksum})"
246+
__sdkman_echo_no_colour "Verifying artifact: ${archive} (${algorithm}:${checksum})"
209247

210248
if ! eval "$cmd"; then
211-
rm -f "$zip_archive"
249+
rm -f "$archive"
212250
echo ""
213251
__sdkman_echo_red "Stop! An invalid checksum was detected and the archive removed! Please try re-installing."
214252
return 1

src/test/groovy/sdkman/steps/initialisation_steps.groovy

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ And(~'^the archive for candidate "([^"]*)" version "([^"]*)" is corrupt$') { Str
3030
}
3131

3232
And(~'^the archive for candidate "([^"]*)" version "([^"]*)" is removed$') { String candidate, String version ->
33-
def archive = new File("${sdkmanDir}/tmp/${candidate}-${version}.zip")
33+
def archive = new File("${sdkmanDir}/tmp/${candidate}-${version}.bin")
3434
assert !archive.exists()
3535
}
3636

src/test/groovy/sdkman/steps/stub_steps.groovy

+22-2
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,35 @@ And(~'^an available selfupdate$') { ->
2323

2424
And(~'^the candidate "([^"]*)" version "([^"]*)" is available for download$') { String candidate, String version ->
2525
primeEndpointWithString("/candidates/validate/${candidate}/${version}/${UnixUtils.inferPlatform()}", "valid")
26-
primeDownloadFor(SERVICE_UP_URL, candidate, version, UnixUtils.inferPlatform())
26+
primeDownloadFor(SERVICE_UP_URL, candidate, version, UnixUtils.inferPlatform(),
27+
candidate == "java" ? ["X-Sdkman-ArchiveType": "tar"] : ["X-Sdkman-ArchiveType": "zip"])
28+
primeEndpointWithString("/hooks/pre/${candidate}/${version}/${UnixUtils.inferPlatform()}", preInstallationHookSuccess())
29+
primeEndpointWithString("/hooks/post/${candidate}/${version}/${UnixUtils.inferPlatform()}", postInstallationHookSuccess())
30+
}
31+
32+
And(~'^the candidate "([^"]*)" version "([^"]*)" is available for download with an invalid archive type$') { String candidate, String version ->
33+
primeEndpointWithString("/candidates/validate/${candidate}/${version}/${UnixUtils.inferPlatform()}", "valid")
34+
primeDownloadFor(SERVICE_UP_URL, candidate, version, UnixUtils.inferPlatform(), ["X-Sdkman-ArchiveType": "docx"])
2735
primeEndpointWithString("/hooks/pre/${candidate}/${version}/${UnixUtils.inferPlatform()}", preInstallationHookSuccess())
2836
primeEndpointWithString("/hooks/post/${candidate}/${version}/${UnixUtils.inferPlatform()}", postInstallationHookSuccess())
2937
}
3038

39+
And(~'^the candidate "([^"]*)" version "([^"]*)" is available for download with no headers$') {
40+
String candidate, String version ->
41+
primeEndpointWithString("/candidates/validate/${candidate}/${version}/${UnixUtils.inferPlatform()}", "valid")
42+
primeDownloadFor(SERVICE_UP_URL, candidate, version, UnixUtils.inferPlatform(), [:])
43+
primeEndpointWithString("/hooks/pre/${candidate}/${version}/${UnixUtils.inferPlatform()}", preInstallationHookSuccess())
44+
primeEndpointWithString("/hooks/post/${candidate}/${version}/${UnixUtils.inferPlatform()}", postInstallationHookSuccess())
45+
}
46+
3147
And(~'^the candidate "([^"]*)" version "([^"]*)" is available for download with checksum "([^"]*)" using algorithm "([^"]*)"$') {
3248
String candidate, String version, String checksum, String algorithm ->
3349
primeEndpointWithString("/candidates/validate/${candidate}/${version}/${UnixUtils.inferPlatform()}", "valid")
34-
primeDownloadFor(SERVICE_UP_URL, candidate, version, UnixUtils.inferPlatform(), ["X-Sdkman-Checksum-${algorithm}": "${checksum}"])
50+
primeDownloadFor(SERVICE_UP_URL, candidate, version, UnixUtils.inferPlatform(), [
51+
"X-Sdkman-ArchiveType": "zip",
52+
"X-Sdkman-Checksum-${algorithm}": "${checksum}"
53+
]
54+
)
3555
primeEndpointWithString("/hooks/pre/${candidate}/${version}/${UnixUtils.inferPlatform()}", preInstallationHookSuccess())
3656
primeEndpointWithString("/hooks/post/${candidate}/${version}/${UnixUtils.inferPlatform()}", postInstallationHookSuccess())
3757
}

src/test/groovy/sdkman/stubs/WebServiceStub.groovy

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ class WebServiceStub {
3030
}
3131

3232
static primeDownloadFor(String host, String candidate, String version, String platform) {
33-
primeDownloadFor(host, candidate, version, platform, [:])
33+
def archiveType = (candidate == "java") ? "tar" : "zip"
34+
primeDownloadFor(host, candidate, version, platform, ["X-Sdkman-ArchiveType": archiveType])
3435
}
3536

3637
static primeDownloadFor(String host, String candidate, String version, String platform, Map<String, String> headers) {
Binary file not shown.

src/test/resources/features/install_candidate.feature

+29-1
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,36 @@ Feature: Install Candidate
8282
And the candidate "grails" version "1.3.9" should be the default
8383
And the exit code is 0
8484

85+
Scenario: Install a tarball candidate and choose to make it default
86+
Given the system is bootstrapped
87+
And the candidate "java" version "8.0.111" is available for download
88+
When I enter "sdk install java 8.0.111"
89+
Then I see "Done installing!"
90+
And I do not see "Do you want java 8.0.111 to be set as default? (Y/n)"
91+
And the candidate "java" version "8.0.111" is installed
92+
And the response headers file is created for candidate "java" and version "8.0.111"
93+
And the exit code is 0
94+
8595
# revisit to redownload automatically
86-
96+
97+
Scenario: Don't perform any validations if metadata is not found
98+
Given the system is bootstrapped
99+
And the candidate "grails" version "1.3.6" is available for download with no headers
100+
When I enter "sdk install grails 1.3.6"
101+
Then I see "Metadata file not found (or is empty)"
102+
And the candidate "grails" version "1.3.6" is not installed
103+
And the archive for candidate "grails" version "1.3.6" is removed
104+
And the exit code is 1
105+
106+
Scenario: Abort installation on download of a Candidate without archive type information
107+
Given the system is bootstrapped
108+
And the candidate "grails" version "1.3.6" is available for download with an invalid archive type
109+
When I enter "sdk install grails 1.3.6"
110+
Then I see "Stop! The archive type cannot be determined! Please try installing again."
111+
And the candidate "grails" version "1.3.6" is not installed
112+
And the archive for candidate "grails" version "1.3.6" is removed
113+
And the exit code is 1
114+
87115
Scenario: Abort installation on download of a corrupt Candidate archive
88116
Given the system is bootstrapped
89117
And the candidate "grails" version "1.3.6" is available for download

0 commit comments

Comments
 (0)