diff --git a/get-lit.ps1 b/get-lit.ps1 index 7392d97..270e87e 100644 --- a/get-lit.ps1 +++ b/get-lit.ps1 @@ -1,41 +1,148 @@ +Set-StrictMode -Version Latest -$LUVI_VERSION = "2.14.0" -$LIT_VERSION = "3.8.5" -# Environment variables take precedence -if (test-path env:LUVI_VERSION) { $LUVI_VERSION = $env:LUVI_VERSION } -if (test-path env:LIT_VERSION) { $LIT_VERSION = $env:LIT_VERSION } +# Set up variables and their environment overrides +$LUVI_PREFIX = if ($env:LUVI_PREFIX) { $env:LUVI_PREFIX } else { $PWD } +$LUVI_ENGINE = if ($env:LUVI_ENGINE) { $env:LUVI_ENGINE } else { "luajit" } +$LUVI_VERSION = if ($env:LUVI_VERSION) { $env:LUVI_VERSION } else { "2.15.0" } +$LUVI_FLAVOR = if ($env:LUVI_FLAVOR) { $env:LUVI_FLAVOR } else { "regular" } +$LIT_VERSION = if ($env:LIT_VERSION) { $env:LIT_VERSION } else { "3.9.0" } +$LUVIT_VERSION = if ($env:LUVIT_VERSION) { $env:LUVIT_VERSION } else { "latest" } -if (test-path env:LUVI_ARCH) { - $LUVI_ARCH = $env:LUVI_ARCH -} else { - if ([System.Environment]::Is64BitProcess) { - $LUVI_ARCH = "Windows-amd64" +# OS detection +if ($env:LUVI_OS) { + $LUVI_OS = $env:LUVI_OS +} +else { + if (Get-Variable IsWindows -ErrorAction SilentlyContinue) { + # We are on PS >= 6 + if ($IsWindows) { $LUVI_OS = "Windows" } + elseif ($IsLinux) { $LUVI_OS = "Linux" } + elseif ($IsMacOS) { $LUVI_OS = "Darwin" } + else { $LUVI_OS = "$(uname -s)" } } else { - $LUVI_ARCH = "Windows-ia32" + # We are on PS <= 5.1, only available on Windows + $LUVI_OS = "Windows" + } +} + +# Architecture detection +if ($env:LUVI_ARCH) { + $LUVI_ARCH = $env:LUVI_ARCH +} +else { + $LUVI_ARCH = "amd64" + if ($null -ne $env:PROCESSOR_ARCHITEW6432) { + $LUVI_ARCH = ($env:PROCESSOR_ARCHITEW6432).ToLower() + } + elseif ($null -ne $env:PROCESSOR_ARCHITECTURE) { + $LUVI_ARCH = ($env:PROCESSOR_ARCHITECTURE).ToLower() } + else { + $LUVI_ARCH = "$(uname -m)" + } +} + +$exe_suffix = "" +if ($LUVI_OS -eq "Windows") { $exe_suffix = ".exe" } + +$lit_zip = Join-Path "${LUVI_PREFIX}" "lit.zip" +$luvit_zip = Join-Path "${LUVI_PREFIX}" "luvit.zip" +$luvi_bin = Join-Path "${LUVI_PREFIX}" "luvi${exe_suffix}" +$lit_bin = Join-Path "${LUVI_PREFIX}" "lit${exe_suffix}" +$luvit_bin = Join-Path "${LUVI_PREFIX}" "luvit${exe_suffix}" + +function Cleanup([int] $exit_code) { + Write-Host "[*] Cleaning up" + if (Test-Path $lit_zip) { Remove-Item $lit_zip -Force } + if (Test-Path $luvit_zip) { Remove-Item $luvit_zip -Force } + exit $exit_code +} + +function Download([string] $url, [string] $file) { + Write-Host "[*] Downloading ${file} from ${url}" + + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + for ($i = 5; $i -gt 0; $i--) { + try { + Invoke-WebRequest -Uri "$url" -OutFile "$file" -UseDefaultCredentials -ErrorAction Stop + return + } + catch { + if ($null -ne $_.Exception.Response) { + $status = [int]$_.Exception.Response.StatusCode + Write-Host "[!] Failed to download ${url} to ${file} (HTTP ${status})" + } + else { + Write-Host "[!] Failed to download ${url} to ${file} ($($_.Exception.Message))" + } + + if ($i -ge 1) { + Write-Host "[*] Retrying in 5 seconds ($(5 - $i + 1)/5)" + Start-Sleep -Seconds 5 + } + } + } + + Write-Host "[!] Failed to download ${url} to ${file}" + Cleanup 1 } -$LUVI_URL = "https://github.com/luvit/luvi/releases/download/v$LUVI_VERSION/luvi-regular-$LUVI_ARCH.exe" -$LIT_URL = "https://lit.luvit.io/packages/luvit/lit/v$LIT_VERSION.zip" - -function Download-File { - param ( - [string]$url, - [string]$file - ) - [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls11 -bor [System.Net.SecurityProtocolType]::Tls12; - Write-Host "Downloading $url to $file" - $downloader = new-object System.Net.WebClient - $downloader.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials; - $downloader.DownloadFile($url, $file) -} - -# Download Files -Download-File $LUVI_URL "luvi.exe" -Download-File $LIT_URL "lit.zip" - -# Create lit.exe using lit -Start-Process ".\luvi.exe" -ArgumentList "lit.zip -- make lit.zip lit.exe luvi.exe" -Wait -NoNewWindow -# Cleanup -Remove-Item "lit.zip" -# Create luvit using lit -Start-Process ".\lit.exe" -ArgumentList "make lit://luvit/luvit luvit.exe luvi.exe" -Wait -NoNewWindow + +function VersionGTE([string] $a, [string] $b) { + [version]$verA = $a -replace "v", "" + [version]$verB = $b -replace "v", "" + return $verA -ge $verB +} + +# Allow selecting latest, but real versions need a v prefix +if ($LUVI_VERSION -ne "latest") { $LUVI_VERSION = "v${LUVI_VERSION}" } +if ($LIT_VERSION -ne "latest") { $LIT_VERSION = "v${LIT_VERSION}" } +if ($LUVIT_VERSION -ne "latest") { $LUVIT_VERSION = "v${LUVIT_VERSION}" } + +if (${LUVI_VERSION} -eq "latest") { + $luvi_url = "https://github.com/luvit/luvi/releases/latest/download/luvi-${LUVI_OS}-${LUVI_ARCH}-${LUVI_ENGINE}-${LUVI_FLAVOR}${exe_suffix}" +} +elseif (VersionGTE $LUVI_VERSION "2.15.0") { + $luvi_url = "https://github.com/luvit/luvi/releases/download/${LUVI_VERSION}/luvi-${LUVI_OS}-${LUVI_ARCH}-${LUVI_ENGINE}-${LUVI_FLAVOR}${exe_suffix}" +} +else { + $luvi_url = "https://github.com/luvit/luvi/releases/download/${LUVI_VERSION}/luvi-${LUVI_FLAVOR}-${LUVI_OS}_${LUVI_ARCH}${exe_suffix}" +} +$lit_url = "https://lit.luvit.io/packages/luvit/lit/${LIT_VERSION}.zip" +$luvit_url = "https://lit.luvit.io/packages/luvit/luvit/${LUVIT_VERSION}.zip" + +Write-Host "[+] Installing luvit, lit and luvi to ${LUVI_PREFIX}" + +# Lit 3.9.0 and newer require luvi >= 2.15.0 +if ((VersionGTE $LIT_VERSION "3.9.0") -and !(VersionGTE $LUVI_VERSION "2.15.0")) { + Write-Host "[!] Incompatible luvi version, lit $LIT_VERSION requires luvi 2.15.0 or newer you are using $LUVI_VERSION" + Cleanup 1 +} + +# Download Luvi, and the sources for Lit and Luvit +Download $luvi_url $luvi_bin +Download $lit_url $lit_zip +Download $luvit_url $luvit_zip + +# Install luvi +if ("${LUVI_OS}" -ne "Windows") { + &chmod +x $luvi_bin +} + +# Install lit +Write-Host "[*] Creating lit from lit.zip" +&"${luvi_bin}" "${lit_zip}" -- make "${lit_zip}" "${lit_bin}" "${luvi_bin}" +if (-not (Test-Path $lit_bin)) { + Write-Host "[!] Could not create lit" + Cleanup 1 +} + +# Install Luvit +Write-Host "[*] Creating luvit from luvit.zip" +&"${lit_bin}" make "${luvit_zip}" "${luvit_bin}" "${luvi_bin}" +if (-not (Test-Path $luvit_bin)) { + Write-Host "[!] Could not create luvit" + Cleanup 1 +} + +Write-Host "[+] Installation complete at ${LUVI_PREFIX}" +Cleanup 0 diff --git a/get-lit.sh b/get-lit.sh index 7cf68b5..4a60a65 100755 --- a/get-lit.sh +++ b/get-lit.sh @@ -1,23 +1,120 @@ #!/bin/sh -set -eu -LUVI_VERSION=${LUVI_VERSION:-2.14.0} -LIT_VERSION=${LIT_VERSION:-3.8.5} - -LUVI_ARCH=`uname -s`_`uname -m` -LUVI_URL="https://github.com/luvit/luvi/releases/download/v$LUVI_VERSION/luvi-regular-$LUVI_ARCH" -LIT_URL="https://lit.luvit.io/packages/luvit/lit/v$LIT_VERSION.zip" - -# Download Files -echo "Downloading $LUVI_URL to luvi" -curl -L -f -o luvi $LUVI_URL -chmod +x luvi - -echo "Downloading $LIT_URL to lit.zip" -curl -L -f -o lit.zip $LIT_URL - -# Create lit using lit -./luvi lit.zip -- make lit.zip lit luvi -# Cleanup -rm -f lit.zip -# Create luvit using lit -./lit make lit://luvit/luvit luvit luvi +set -u # exit on unset variables. + +LUVI_PREFIX=${LUVI_PREFIX:-${PWD}} + +LUVI_OS=${LUVI_OS:-"$(uname -s)"} +LUVI_ARCH=${LUVI_ARCH:-"$(uname -m)"} +LUVI_ENGINE=${LUVI_ENGINE:-"luajit"} +LUVI_FLAVOR=${LUVI_FLAVOR:-"regular"} + +LUVI_VERSION=${LUVI_VERSION:-"2.15.0"} +LIT_VERSION=${LIT_VERSION:-"3.9.0"} +LUVIT_VERSION=${LUVIT_VERSION:-"latest"} + +_lit_zip="${LUVI_PREFIX}/lit.zip" +_luvit_zip="${LUVI_PREFIX}/luvit.zip" +_luvi_bin="${LUVI_PREFIX}/luvi" +_lit_bin="${LUVI_PREFIX}/lit" +_luvit_bin="${LUVI_PREFIX}/luvit" + +cleanup() { + _exit=$1 + + echo "[*] Cleaning up" + rm -f "${_lit_zip}" + rm -f "${_luvit_zip}" + exit "${_exit}" +} + +# download a file from $1 and save it as $2 +download() { + _url=$1 + _file=$2 + + echo "[*] Downloading ${_file} from ${_url}" + + # --retry requires curl 7.12.3, from 2004 + _status="$(curl --retry 5 --retry-delay 5 -#Lfo "${_file}" -w "%{http_code}" "${_url}")" + _exit="$?" + if [ "${_exit}" -eq 2 ]; then # curl failed to start, probably not installed or version too old + echo "[!] Failed to download ${_file} (curl initialization failed)" + exit 1 + elif [ "${_exit}" -ne 0 ]; then # curl failed to download + echo "[!] Failed to download ${_file} (curl exit ${_exit})" + echo "curl: ${_status}" + exit 1 + fi + + if [ "${_status}" -ne 200 ]; then # the server did not give us the file + echo "[!] Failed to download ${_file} (HTTP ${_status})" + exit 1 + fi +} + +# check if version $1 is greater than or equal to $2 +version_gte() { + local v1="${1#v}" + local v2="${2#v}" + [ "$(printf '%s\n' "${v1}" "${v2}" | sort -V | head -n 1)" != "$v1" ] || [ "$v1" = "$v2" ] +} + +# allow selecting latest, but real versions need a v prefix +[ "${LUVI_VERSION}" != "latest" ] && LUVI_VERSION="v${LUVI_VERSION}" +[ "${LIT_VERSION}" != "latest" ] && LIT_VERSION="v${LIT_VERSION}" +[ "${LUVIT_VERSION}" != "latest" ] && LUVIT_VERSION="v${LUVIT_VERSION}" + +_luvi_url="https://github.com/luvit/luvi/releases/download/${LUVI_VERSION}/luvi-${LUVI_FLAVOR}-${LUVI_OS}_${LUVI_ARCH}" +_lit_url="https://lit.luvit.io/packages/luvit/lit/${LIT_VERSION}.zip" +_luvit_url="https://lit.luvit.io/packages/luvit/luvit/${LUVIT_VERSION}.zip" + +if [ "${LUVI_VERSION}" = "latest" ]; then # select the latest endpoint + _luvi_url="https://github.com/luvit/luvi/releases/latest/download/luvi-${LUVI_OS}-${LUVI_ARCH}-${LUVI_ENGINE}-${LUVI_FLAVOR}" +elif version_gte "${LUVI_VERSION}" "2.15.0"; then # select the new release format + _luvi_url="https://github.com/luvit/luvi/releases/download/${LUVI_VERSION}/luvi-${LUVI_OS}-${LUVI_ARCH}-${LUVI_ENGINE}-${LUVI_FLAVOR}" +fi + +echo "[+] Installing luvit, lit and luvi to ${LUVI_PREFIX}" +trap 'echo "[#] Cancelling installation"; cleanup 1' INT TERM + +# lit 3.9.0 and newer require luvi >= 2.15.0 +if version_gte "${LIT_VERSION}" "3.9.0" && ! version_gte "${LUVI_VERSION}" "2.15.0"; then + echo "[!] Incompatible luvi version, lit ${LIT_VERSION} requires luvi 2.15.0 or newer" + cleanup 1 +fi + +# Download Luvi, and the sources for Lit and Luvit + +download "${_luvi_url}" "${_luvi_bin}" || cleanup 1 +download "${_lit_url}" "${_lit_zip}" || cleanup 1 +download "${_luvit_url}" "${_luvit_zip}" || cleanup 1 + +# Install luvi + +chmod +x "${_luvi_bin}" +if [ ! -x "${_luvi_bin}" ]; then + echo "[!] Could not make luvi executable" + cleanup 1 +fi + +# Install lit + +echo "[*] Creating lit from lit.zip" +"${_luvi_bin}" "${_lit_zip}" -- make "${_lit_zip}" "${_lit_bin}" "${_luvi_bin}" +if [ ! -x "${_lit_bin}" ]; then + echo "[!] Could not create lit" + cleanup 1 +fi + +# Install luvit + +echo "[*] Creating luvit from luvit.zip" +"${_lit_bin}" make "${_luvit_zip}" "${_luvit_bin}" "${_luvi_bin}" +if [ ! -x "${_luvit_bin}" ]; then + echo "[!] Could not create luvit" + cleanup 1 +fi + +echo "[+] Installation complete at ${LUVI_PREFIX}" + +cleanup 0