diff --git a/src/main/bash/sdkman-install.sh b/src/main/bash/sdkman-install.sh index 5de88345f..4045810e8 100644 --- a/src/main/bash/sdkman-install.sh +++ b/src/main/bash/sdkman-install.sh @@ -59,18 +59,36 @@ function __sdk_install() { } function __sdkman_install_candidate_version() { - local candidate version - + local candidate version base_name headers_file archive_type + local metadata_folder="${SDKMAN_DIR}/var/metadata" + candidate="$1" version="$2" + base_name="${candidate}-${version}" + headers_file="${metadata_folder}/${base_name}.headers" + + mkdir -p ${metadata_folder} - __sdkman_download "$candidate" "$version" || return 1 + __sdkman_download "$candidate" "$version" "$headers_file" || return 1 __sdkman_echo_green "Installing: ${candidate} ${version}" mkdir -p "${SDKMAN_CANDIDATES_DIR}/${candidate}" - rm -rf "${SDKMAN_DIR}/tmp/out" - unzip -oq "${SDKMAN_DIR}/tmp/${candidate}-${version}.bin" -d "${SDKMAN_DIR}/tmp/out" + + archive_type=$(sed -n 's/^X-Sdkman-ArchiveType:\(.*\)$/\1/p' ${headers_file} | tr -cd '[:alnum:]') + + if [[ "${archive_type}" == 'zip' ]]; then + unzip -oq "${SDKMAN_DIR}/tmp/${base_name}.bin" -d "${SDKMAN_DIR}/tmp/out" + elif [[ "${archive_type}" == 'tar' ]]; then + mkdir -p "${SDKMAN_DIR}/tmp/out" + tar zxf "${SDKMAN_DIR}/tmp/${base_name}.bin" -C "${SDKMAN_DIR}/tmp/out" + else + echo "" + __sdkman_echo_red "Stop! The archive type cannot be determined! Please try installing again." + rm -f "${SDKMAN_DIR}/tmp/${base_name}.bin" + return 1 + fi + mv -f "$SDKMAN_DIR"/tmp/out/* "${SDKMAN_CANDIDATES_DIR}/${candidate}/${version}" __sdkman_echo_green "Done installing!" echo "" @@ -114,22 +132,18 @@ function __sdkman_install_local_version() { } function __sdkman_download() { - local candidate version + local candidate version headers_file candidate="$1" version="$2" + headers_file="$3" - metadata_folder="${SDKMAN_DIR}/var/metadata" - mkdir -p ${metadata_folder} - local platform_parameter="$(echo $SDKMAN_PLATFORM | tr '[:upper:]' '[:lower:]')" local download_url="${SDKMAN_CANDIDATES_API}/broker/download/${candidate}/${version}/${platform_parameter}" local base_name="${candidate}-${version}" local tmp_headers_file="${SDKMAN_DIR}/tmp/${base_name}.headers.tmp" - local headers_file="${metadata_folder}/${base_name}.headers" export local binary_input="${SDKMAN_DIR}/tmp/${base_name}.bin" - export local zip_output="${SDKMAN_DIR}/tmp/${base_name}.zip" echo "" __sdkman_echo_no_colour "Downloading: ${candidate} ${version}" @@ -142,26 +156,50 @@ 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})" - __sdkman_validate_zip "${binary_input}" || return 1 - __sdkman_checksum_zip "${binary_input}" "${headers_file}" || return 1 - echo "" + if [[ ! -s "${headers_file}" ]]; then + echo "" + __sdkman_echo_red "Metadata file not found (or is empty) at '${headers_file}'" + rm -f "${binary_input}" + return 1 + else + __sdkman_validate "${binary_input}" "${headers_file}" || return 1 + __sdkman_checksum "${binary_input}" "${headers_file}" || return 1 + echo "" + fi } -function __sdkman_validate_zip() { - local zip_archive zip_ok +function __sdkman_validate() { + local -r archive="$1" + local -r headers_file="$2" + local -r archive_type=$(sed -n 's/^X-Sdkman-ArchiveType:\(.*\)$/\1/p' ${headers_file} | tr -cd '[:alnum:]') + local is_ok + + __sdkman_echo_debug "Archive Type: ${archive_type}" + __sdkman_echo_debug "Archive: ${archive}" + + if [[ "${archive_type}" == 'zip' ]]; then + __sdkman_echo_debug "Checking zip archive" + is_ok=$(unzip -t "$archive" | grep 'No errors detected in compressed data') + elif [[ "${archive_type}" == 'tar' ]]; then + __sdkman_echo_debug "Checking tar archive" + is_ok=$(tar tf "$archive" | grep -v 'Error opening archive') + else + echo "" + __sdkman_echo_red "Stop! The archive type cannot be determined! Please try installing again." + rm -f "${archive}" + return 1 + fi - zip_archive="$1" - zip_ok=$(unzip -t "$zip_archive" | grep 'No errors detected in compressed data') - if [ -z "$zip_ok" ]; then - rm -f "$zip_archive" + if [ -z "$is_ok" ]; then + rm -f "$archive" echo "" __sdkman_echo_red "Stop! The archive was corrupt and has been removed! Please try installing again." return 1 fi } -function __sdkman_checksum_zip() { - local -r zip_archive="$1" +function __sdkman_checksum() { + local -r archive="$1" local -r headers_file="$2" local algorithm checksum cmd local shasum_avail=false @@ -198,17 +236,17 @@ function __sdkman_checksum_zip() { if [[ -n ${algorithm} && -n ${checksum} ]]; then if [[ "$algorithm" =~ 'SHA' && "$shasum_avail" == 'true' ]]; then - cmd="echo \"${checksum} *${zip_archive}\" | shasum --check --quiet" + cmd="echo \"${checksum} *${archive}\" | shasum --check --quiet" elif [[ "$algorithm" =~ 'MD5' && "$md5sum_avail" == 'true' ]]; then - cmd="echo \"${checksum} ${zip_archive}\" | md5sum --check --quiet" + cmd="echo \"${checksum} ${archive}\" | md5sum --check --quiet" fi if [[ -n $cmd ]]; then - __sdkman_echo_no_colour "Verifying artifact: ${zip_archive} (${algorithm}:${checksum})" + __sdkman_echo_no_colour "Verifying artifact: ${archive} (${algorithm}:${checksum})" if ! eval "$cmd"; then - rm -f "$zip_archive" + rm -f "$archive" echo "" __sdkman_echo_red "Stop! An invalid checksum was detected and the archive removed! Please try re-installing." return 1 diff --git a/src/test/groovy/sdkman/steps/initialisation_steps.groovy b/src/test/groovy/sdkman/steps/initialisation_steps.groovy index d789ae497..668659ae2 100644 --- a/src/test/groovy/sdkman/steps/initialisation_steps.groovy +++ b/src/test/groovy/sdkman/steps/initialisation_steps.groovy @@ -30,7 +30,7 @@ And(~'^the archive for candidate "([^"]*)" version "([^"]*)" is corrupt$') { Str } And(~'^the archive for candidate "([^"]*)" version "([^"]*)" is removed$') { String candidate, String version -> - def archive = new File("${sdkmanDir}/tmp/${candidate}-${version}.zip") + def archive = new File("${sdkmanDir}/tmp/${candidate}-${version}.bin") assert !archive.exists() } diff --git a/src/test/groovy/sdkman/steps/stub_steps.groovy b/src/test/groovy/sdkman/steps/stub_steps.groovy index 4af30586f..a528733a5 100644 --- a/src/test/groovy/sdkman/steps/stub_steps.groovy +++ b/src/test/groovy/sdkman/steps/stub_steps.groovy @@ -20,13 +20,29 @@ And(~'^an available selfupdate$') { -> And(~'^the candidate "([^"]*)" version "([^"]*)" is available for download$') { String candidate, String version -> primeEndpointWithString("/candidates/validate/${candidate}/${version}/${UnixUtils.inferPlatform()}", "valid") - primeDownloadFor(SERVICE_UP_URL, candidate, version, UnixUtils.inferPlatform()) + primeDownloadFor(SERVICE_UP_URL, candidate, version, UnixUtils.inferPlatform(), + candidate == "java" ? ["X-Sdkman-ArchiveType": "tar"] : ["X-Sdkman-ArchiveType": "zip"]) +} + +And(~'^the candidate "([^"]*)" version "([^"]*)" is available for download with an invalid archive type$') { String candidate, String version -> + primeEndpointWithString("/candidates/validate/${candidate}/${version}/${UnixUtils.inferPlatform()}", "valid") + primeDownloadFor(SERVICE_UP_URL, candidate, version, UnixUtils.inferPlatform(), ["X-Sdkman-ArchiveType": "docx"]) +} + +And(~'^the candidate "([^"]*)" version "([^"]*)" is available for download with no headers$') { + String candidate, String version -> + primeEndpointWithString("/candidates/validate/${candidate}/${version}/${UnixUtils.inferPlatform()}", "valid") + primeDownloadFor(SERVICE_UP_URL, candidate, version, UnixUtils.inferPlatform(), [:]) } And(~'^the candidate "([^"]*)" version "([^"]*)" is available for download with checksum "([^"]*)" using algorithm "([^"]*)"$') { String candidate, String version, String checksum, String algorithm -> primeEndpointWithString("/candidates/validate/${candidate}/${version}/${UnixUtils.inferPlatform()}", "valid") - primeDownloadFor(SERVICE_UP_URL, candidate, version, UnixUtils.inferPlatform(), ["X-Sdkman-Checksum-${algorithm}": "${checksum}"]) + primeDownloadFor(SERVICE_UP_URL, candidate, version, UnixUtils.inferPlatform(), [ + "X-Sdkman-ArchiveType": "zip", + "X-Sdkman-Checksum-${algorithm}": "${checksum}" + ] + ) } And(~'^the candidate "([^"]*)" version "([^"]*)" is not available for download$') { String candidate, String version -> diff --git a/src/test/groovy/sdkman/stubs/WebServiceStub.groovy b/src/test/groovy/sdkman/stubs/WebServiceStub.groovy index 4b22b85e0..60448ecf0 100644 --- a/src/test/groovy/sdkman/stubs/WebServiceStub.groovy +++ b/src/test/groovy/sdkman/stubs/WebServiceStub.groovy @@ -13,7 +13,8 @@ class WebServiceStub { } static primeDownloadFor(String host, String candidate, String version, String platform) { - primeDownloadFor(host, candidate, version, platform, [:]) + def archiveType = (candidate == "java") ? "tar" : "zip" + primeDownloadFor(host, candidate, version, platform, ["X-Sdkman-ArchiveType": archiveType]) } static primeDownloadFor(String host, String candidate, String version, String platform, Map headers) { diff --git a/src/test/resources/__files/jdk-8.0.111-darwinx64.tar.gz b/src/test/resources/__files/jdk-8.0.111-darwinx64.tar.gz new file mode 100644 index 000000000..3a77dd934 Binary files /dev/null and b/src/test/resources/__files/jdk-8.0.111-darwinx64.tar.gz differ diff --git a/src/test/resources/features/install_candidate.feature b/src/test/resources/features/install_candidate.feature index 2b855edd4..42bfac978 100644 --- a/src/test/resources/features/install_candidate.feature +++ b/src/test/resources/features/install_candidate.feature @@ -82,8 +82,36 @@ Feature: Install Candidate And the candidate "grails" version "1.3.9" should be the default And the exit code is 0 + Scenario: Install a tarball candidate and choose to make it default + Given the system is bootstrapped + And the candidate "java" version "8.0.111" is available for download + When I enter "sdk install java 8.0.111" + Then I see "Done installing!" + And I do not see "Do you want java 8.0.111 to be set as default? (Y/n)" + And the candidate "java" version "8.0.111" is installed + And the response headers file is created for candidate "java" and version "8.0.111" + And the exit code is 0 + # revisit to redownload automatically - + + Scenario: Don't perform any validations if metadata is not found + Given the system is bootstrapped + And the candidate "grails" version "1.3.6" is available for download with no headers + When I enter "sdk install grails 1.3.6" + Then I see "Metadata file not found (or is empty)" + And the candidate "grails" version "1.3.6" is not installed + And the archive for candidate "grails" version "1.3.6" is removed + And the exit code is 1 + + Scenario: Abort installation on download of a Candidate without archive type information + Given the system is bootstrapped + And the candidate "grails" version "1.3.6" is available for download with an invalid archive type + When I enter "sdk install grails 1.3.6" + Then I see "Stop! The archive type cannot be determined! Please try installing again." + And the candidate "grails" version "1.3.6" is not installed + And the archive for candidate "grails" version "1.3.6" is removed + And the exit code is 1 + Scenario: Abort installation on download of a corrupt Candidate archive Given the system is bootstrapped And the candidate "grails" version "1.3.6" is available for download