Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 87 additions & 16 deletions src/main/bash/sdkman-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,42 @@ function __sdkman_install_candidate_version() {
mkdir -p "${SDKMAN_CANDIDATES_DIR}/${candidate}"

rm -rf "${SDKMAN_DIR}/tmp/out"
unzip -oq "${SDKMAN_DIR}/tmp/${candidate}-${version}.zip" -d "${SDKMAN_DIR}/tmp/out"
__sdkman_extract_install_archive "${candidate}" "${version}"
mv -f "$SDKMAN_DIR"/tmp/out/* "${SDKMAN_CANDIDATES_DIR}/${candidate}/${version}"
__sdkman_echo_green "Done installing!"
echo ""
}

function __sdkman_extract_install_archive() {
# function parameters
local -r candidate="$1"
local -r version="$2"

# copy relevant parts of __sdkman_download
local -r metadata_folder="${SDKMAN_DIR}/var/metadata"
local -r base_name="${candidate}-${version}"
local -r headers_file="${metadata_folder}/${base_name}.headers"

# understand the archive type
local -r archive_type=$(__sdkman_archive_type "${headers_file}")
local -r archive_file="${SDKMAN_DIR}/tmp/${candidate}-${version}.${archive_type}"
local -r out_dir="${SDKMAN_DIR}/tmp/out"

# perform extraction
case $archive_type in
zip*)
unzip -oq "${archive_file}" -d "${out_dir}"
;;
tar*)
(mkdir -p "${out_dir}" && cd "${out_dir}" && tar xvaf "${archive_file}" > /dev/null)
;;
*)
__sdkman_echo_red "Stop! The archive is of an unknown type: '$archive_type'! Please file an issue on https://github.com/sdkman/sdkman-cli/issues ."
return 1
;;
esac
}

function __sdkman_install_local_version() {
local candidate version folder version_length version_length_max

Expand Down Expand Up @@ -122,6 +152,7 @@ function __sdkman_download() {
metadata_folder="${SDKMAN_DIR}/var/metadata"
mkdir -p "${metadata_folder}"

# beware that the final location of the downloaded file is duplicated in __sdkman_extract_install_archive
local platform_parameter="$SDKMAN_PLATFORM"
local download_url="${SDKMAN_CANDIDATES_API}/broker/download/${candidate}/${version}/${platform_parameter}"
local base_name="${candidate}-${version}"
Expand All @@ -142,22 +173,62 @@ function __sdkman_download() {
grep '^X-Sdkman' "${tmp_headers_file}" > "${headers_file}"
__sdkman_echo_debug "Downloaded binary to: ${binary_input} (HTTP headers written to: ${headers_file})"

# post-installation hook: implements function __sdkman_post_installation_hook
# responsible for taking `binary_input` and producing `zip_output`
local post_installation_hook="${SDKMAN_DIR}/tmp/hook_post_${candidate}_${version}.sh"
__sdkman_echo_debug "Get post-installation hook: ${SDKMAN_CANDIDATES_API}/hooks/post/${candidate}/${version}/${platform_parameter}"
__sdkman_secure_curl "${SDKMAN_CANDIDATES_API}/hooks/post/${candidate}/${version}/${platform_parameter}" >| "$post_installation_hook"
__sdkman_echo_debug "Copy remote post-installation hook: ${post_installation_hook}"
source "$post_installation_hook"
__sdkman_post_installation_hook || return 1
__sdkman_echo_debug "Processed binary as: $zip_output"
__sdkman_echo_debug "Completed post-installation hook..."

__sdkman_validate_zip "${zip_output}" || return 1
__sdkman_checksum_zip "${zip_output}" "${headers_file}" || return 1
local archive_type="$(__sdkman_archive_type "${headers_file}")"
local archive_input="${SDKMAN_DIR}/tmp/${base_name}.${archive_type}"
__sdkman_echo_debug "Binary archive type determined to be $archive_type"
# instead of post_installation_hook - simply mv the file
mv "${binary_input}" "${archive_input}"

__sdkman_validate_archive "${archive_input}" "${archive_type}" || return 1
__sdkman_checksum_archive "${archive_input}" "${headers_file}" || return 1
echo ""
}

function __sdkman_archive_type() {
local -r HEADER='X-Sdkman-ArchiveType'
local -r headers_file="$1"

# search for the header with a case insensitive match
# then use same sed technique as __sdkman_checksum_archive
grep -i "$HEADER" "$headers_file" | sed -n "s/^$HEADER:\s*\(.*\)$/\1/p"
}

function __sdkman_validate_archive() {
local -r archive_file="$1"
local -r archive_type="$2"
local test_output
local test_return
local error_text

case $archive_type in
zip*)
__sdkman_validate_zip "$archive_file"
return $?
;;
tar*)
# look for the line 'tar: Error is not recoverable: exiting now'
error_text='Error is not recoverable'
test_output=$(tar tf "$archive_file" 2>&1 > /dev/null)
test_return=$?
;;
*)
__sdkman_echo_red "Stop! The archive is of an unknown type: '$archive_type'! Please file an issue on https://github.com/sdkman/sdkman-cli/issues ."
return 1
;;
esac

# return a failure if the test command failed
if [ 0 != $test_return ]; then
__sdkman_echo_red "Stop! The archive was corrupt (the test for $archive_type archives failed)"
return 1
fi

# if there's way to determine if output is a reported failure,
# return a failure if the test command ran successfully, but reported a failure
[ ! -z "${error_text}" ] && echo "${test_output}" | grep -q "${error_text}" && return 1 || return 0
}


function __sdkman_validate_zip() {
local zip_archive zip_ok

Expand All @@ -171,7 +242,7 @@ function __sdkman_validate_zip() {
fi
}

function __sdkman_checksum_zip() {
function __sdkman_checksum_archive() {
local -r zip_archive="$1"
local -r headers_file="$2"
local algorithm checksum cmd
Expand Down Expand Up @@ -229,4 +300,4 @@ function __sdkman_checksum_zip() {
fi
fi
done < "${headers_file}"
}
}
2 changes: 1 addition & 1 deletion src/test/groovy/sdkman/env/BashEnv.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class BashEnv {
def commandOutput

// Command timeout in milliseconds
def timeout = 5000
def timeout = 11_000 // must be longer than 10 seconds, default sdkman timeout
def workDir
def env

Expand Down
6 changes: 4 additions & 2 deletions src/test/groovy/sdkman/stubs/WebServiceStub.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ class WebServiceStub {
}

static primeDownloadFor(String host, String candidate, String version, String platform, Map<String, String> headers) {
def binary = (candidate == "java") ? "jdk-${version}-${platform}.tar.gz" : "${candidate}-${version}.zip"
def isTar = candidate == "java"
def binary = isTar ? "jdk-${version}-${platform}.tar.gz" : "${candidate}-${version}.zip"
def responseBuilder = aResponse()
.withHeader("Location", "${host}/${binary}")
.withHeader("X-Sdkman-ArchiveType", isTar ? 'tar' : 'zip')
.withStatus(302)
headers.each { responseBuilder.withHeader(it.key, it.value) }

Expand All @@ -57,4 +59,4 @@ class WebServiceStub {
.withHeader("Content-Type", "text/plain")
.withBodyFile("selfupdate.sh")))
}
}
}
25 changes: 0 additions & 25 deletions src/test/resources/features/hooks.feature

This file was deleted.

10 changes: 0 additions & 10 deletions src/test/resources/features/java_installation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,6 @@ Feature: Java Multi Platform Binary Distribution
And I see "Done installing!"
And the candidate "java" version "8.0.111" is installed

Scenario: Platform is supported but download fails
Given an "x86_64" machine with "Linux" installed
And the system is bootstrapped
And the candidate "java" version "8.0.101" is available for download on "Linux" with architecture "x86_64"
And the appropriate multi-platform hook is available for "java" version "8.0.101" on "Linux" with architecture "x86_64"
When I enter "sdk install java 8.0.101"
And I see "Download has failed, aborting!"
And the candidate "java" version "8.0.101" is not installed
And I see "Cannot install java 8.0.101 at this time..."

Scenario: Platform is not supported for specific version and user is notified
And an "x86_64" machine with "Linux" installed
And the system is bootstrapped
Expand Down