mirror of
https://github.com/InsanusMokrassar/KSLog.git
synced 2026-11-02 09:42:56 +00:00
266 lines
12 KiB
Batchfile
266 lines
12 KiB
Batchfile
@echo off
|
|
|
|
@rem
|
|
@rem Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
|
@rem
|
|
|
|
@rem Possible environment variables:
|
|
@rem KOTLIN_CLI_DOWNLOAD_ROOT Maven repository to download the Kotlin CLI dist from
|
|
@rem default: https://packages.jetbrains.team/maven/p/amper/amper
|
|
@rem KOTLIN_CLI_JRE_DOWNLOAD_ROOT Url prefix to download the Kotlin CLI JRE from.
|
|
@rem default: https:/
|
|
@rem KOTLIN_CLI_BOOTSTRAP_CACHE_DIR Cache directory to store the extracted JRE and Kotlin CLI distribution
|
|
@rem KOTLIN_CLI_JAVA_HOME JRE to run the Kotlin CLI itself (optional, does not affect compilation)
|
|
@rem KOTLIN_CLI_JAVA_OPTIONS JVM options to pass to the JVM running the Kotlin CLI (does not affect the user's application)
|
|
@rem KOTLIN_CLI_NO_WELCOME_BANNER Disables the first-run welcome message if set to a non-empty value
|
|
|
|
setlocal
|
|
|
|
@rem The version of the Kotlin Toolchain distribution to provision and use
|
|
set kotlin_cli_version=0.13.0-dev-4444
|
|
@rem Establish chain of trust from here by specifying the exact checksum of the Kotlin Toolchain distribution to be run
|
|
set kotlin_cli_sha256=13c2448146ac6dba0fa3a4e5d367dab73d8cfd7400bab348bebe905c165adecf
|
|
|
|
if not defined KOTLIN_CLI_DOWNLOAD_ROOT set KOTLIN_CLI_DOWNLOAD_ROOT=https://packages.jetbrains.team/maven/p/amper/amper
|
|
if not defined KOTLIN_CLI_BOOTSTRAP_CACHE_DIR set KOTLIN_CLI_BOOTSTRAP_CACHE_DIR=%LOCALAPPDATA%\JetBrains\Kotlin\cli
|
|
@rem remove trailing \ if present
|
|
if [%KOTLIN_CLI_BOOTSTRAP_CACHE_DIR:~-1%] EQU [\] set KOTLIN_CLI_BOOTSTRAP_CACHE_DIR=%KOTLIN_CLI_BOOTSTRAP_CACHE_DIR:~0,-1%
|
|
|
|
goto :after_function_declarations
|
|
|
|
REM ********** Download and extract any zip or .tar.gz archive **********
|
|
|
|
:download_and_extract
|
|
setlocal
|
|
|
|
set moniker=%~1
|
|
set url=%~2
|
|
set target_dir=%~3
|
|
set sha=%~4
|
|
set sha_size=%~5
|
|
set show_banner_on_cache_miss=%~6
|
|
|
|
setlocal enableDelayedExpansion
|
|
|
|
set flag_file=%target_dir%\.flag
|
|
if exist "%flag_file%" (
|
|
set /p current_flag=<"%flag_file%"
|
|
if "!current_flag!" == "%sha%" exit /b
|
|
)
|
|
|
|
set NL=^
|
|
|
|
|
|
@rem two empty lines required above for the NL character
|
|
|
|
@rem We have to build the welcome banner here as an env var because we
|
|
@rem can't pass a multiline string through the single line powershell
|
|
set welcome_banner=!NL! ^
|
|
Welcome to !NL! ^
|
|
!NL! ^
|
|
@@@ @@@@ @@@ @@@ !NL! ^
|
|
@@@ @@@@ @@@ @@@ @@@ !NL! ^
|
|
@@@ #@@@^" ,@@@ @@@ !NL! ^
|
|
@@@ ,@@@%% ,@@@@@@@, @@@@@@@@@@ @@@ @@@ @@@ ,@@@@@, !NL! ^
|
|
@@@ @@@@ @@@@@%%^"%%@@@@@ @@@@@@@@@@ @@@ @@@ @@@@@@%%%%@@@@@ !NL! ^
|
|
@@@@@@%% @@@%% %%@@@ @@@ @@@ @@@ @@@@ %%@@%% !NL! ^
|
|
@@@ @@@@= #@@@ @@@# @@@ @@@ @@@ @@@ @@@ !NL! ^
|
|
@@@ @@@@ #@@@ @@@# @@@ @@@ @@@ @@@ @@@ !NL! ^
|
|
@@@ *@@@%% @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ !NL! ^
|
|
@@@ %%@@@= %%@@@@*,*@@@@%% @@@@### @@@ @@@ @@@ @@@ !NL! ^
|
|
@@@ @@@@ ^"@@@@@@@^" %%@@@@@ @@@ @@@ @@@ @@@ !NL!
|
|
|
|
@rem This multiline string is actually passed as a single line to powershell, meaning #-comments are not possible.
|
|
@rem So here are a few comments about the code below:
|
|
@rem - we need to support both .zip and .tar.gz archives (for the Kotlin Toolchain distribution and the JRE)
|
|
@rem - tar should be present in all Windows machines since 2018 (and usable from both cmd and powershell)
|
|
@rem - tar requires the destination dir to exist
|
|
@rem - We use (New-Object Net.WebClient).DownloadFile instead of Invoke-WebRequest for performance. See the issue
|
|
@rem https://github.com/PowerShell/PowerShell/issues/16914, which is still not fixed in Windows PowerShell 5.1
|
|
@rem - DownloadFile requires the directories in the destination file's path to exist
|
|
set download_and_extract_ps1= ^
|
|
Set-StrictMode -Version 3.0; ^
|
|
$ErrorActionPreference = 'Stop'; ^
|
|
^
|
|
$createdNew = $false; ^
|
|
$lock = New-Object System.Threading.Mutex($true, ('Global\kotlin-cli-bootstrap.' + '%target_dir%'.GetHashCode().ToString()), [ref]$createdNew); ^
|
|
if (-not $createdNew) { ^
|
|
Write-Host 'Another Kotlin CLI instance is bootstrapping. Waiting for our turn...'; ^
|
|
[void]$lock.WaitOne(); ^
|
|
} ^
|
|
^
|
|
try { ^
|
|
if ((Get-Content '%flag_file%' -ErrorAction Ignore) -ne '%sha%') { ^
|
|
if (('%show_banner_on_cache_miss%' -eq 'true') -and [string]::IsNullOrEmpty('%KOTLIN_CLI_NO_WELCOME_BANNER%')) { ^
|
|
Write-Host \"$env:welcome_banner\"; ^
|
|
Write-Host ''; ^
|
|
Write-Host 'This is the first run of the Kotlin CLI v%kotlin_cli_version%, so we need to download the Kotlin Toolchain.'; ^
|
|
Write-Host 'Please give us a few seconds now, subsequent runs will be faster.'; ^
|
|
Write-Host ''; ^
|
|
} ^
|
|
$temp_file = '%KOTLIN_CLI_BOOTSTRAP_CACHE_DIR%\' + [System.IO.Path]::GetRandomFileName(); ^
|
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; ^
|
|
Write-Host 'Downloading %moniker%...'; ^
|
|
[void](New-Item '%KOTLIN_CLI_BOOTSTRAP_CACHE_DIR%' -ItemType Directory -Force); ^
|
|
if (Get-Command curl.exe -errorAction SilentlyContinue) { ^
|
|
curl.exe -L --silent --show-error --fail --output $temp_file '%url%'; ^
|
|
} else { ^
|
|
(New-Object Net.WebClient).DownloadFile('%url%', $temp_file); ^
|
|
} ^
|
|
^
|
|
$actualSha = (Get-FileHash -Algorithm SHA%sha_size% -Path $temp_file).Hash.ToString(); ^
|
|
if ($actualSha -ne '%sha%') { ^
|
|
$writeErr = if ($Host.Name -eq 'ConsoleHost') { [Console]::Error.WriteLine } else { $host.ui.WriteErrorLine } ^
|
|
$writeErr.Invoke(\"ERROR: Checksum mismatch for $temp_file (downloaded from %url%): expected checksum %sha% but got $actualSha\"); ^
|
|
exit 1; ^
|
|
} ^
|
|
^
|
|
if (Test-Path '%target_dir%') { ^
|
|
Remove-Item '%target_dir%' -Recurse; ^
|
|
} ^
|
|
if ($temp_file -like '*.zip') { ^
|
|
Add-Type -A 'System.IO.Compression.FileSystem'; ^
|
|
[IO.Compression.ZipFile]::ExtractToDirectory($temp_file, '%target_dir%'); ^
|
|
} else { ^
|
|
[void](New-Item '%target_dir%' -ItemType Directory -Force); ^
|
|
tar -xzf $temp_file -C '%target_dir%'; ^
|
|
} ^
|
|
Remove-Item $temp_file; ^
|
|
^
|
|
Set-Content '%flag_file%' -Value '%sha%'; ^
|
|
Write-Host 'Download complete.'; ^
|
|
Write-Host ''; ^
|
|
} ^
|
|
} ^
|
|
finally { ^
|
|
$lock.ReleaseMutex(); ^
|
|
}
|
|
|
|
rem We reset the PSModulePath in case this batch script was called from PowerShell Core
|
|
rem See https://github.com/PowerShell/PowerShell/issues/18108#issuecomment-2269703022
|
|
set PSModulePath=
|
|
set powershell=%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
|
|
"%powershell%" -NonInteractive -NoProfile -NoLogo -Command %download_and_extract_ps1%
|
|
if errorlevel 1 exit /b 1
|
|
exit /b 0
|
|
|
|
:find_project_context
|
|
@rem Search upwards for a kotlin.bat wrapper file and/or project.yaml
|
|
@rem Sets wrapper_script to the found wrapper path, or empty string if not found.
|
|
@rem Returns errorlevel 0 if a valid wrapper (that is not this script itself) was found, 1 otherwise.
|
|
set wrapper_script=
|
|
set this_script=%~f0
|
|
set project_dir=%CD%
|
|
|
|
:find_loop
|
|
set wrapper_candidate=%project_dir%\kotlin.bat
|
|
if "%this_script%"=="%wrapper_candidate%" (
|
|
@rem Found itself (local wrapper case), no need to update any version or search further.
|
|
exit /b 1
|
|
)
|
|
|
|
if exist "%wrapper_candidate%" (
|
|
@rem Found a wrapper — check that a project context exists alongside it
|
|
if exist "%project_dir%\project.yaml" (
|
|
set wrapper_script=%wrapper_candidate%
|
|
exit /b 0
|
|
)
|
|
if exist "%project_dir%\module.yaml" (
|
|
set wrapper_script=%wrapper_candidate%
|
|
exit /b 0
|
|
)
|
|
echo WARNING: Found wrapper script '%wrapper_candidate%', but no project.yaml or module.yaml near it. Skipping. >&2
|
|
@rem Continue the search
|
|
goto :find_next_parent
|
|
)
|
|
|
|
if exist "%project_dir%\project.yaml" (
|
|
@rem Found project.yaml but no wrapper alongside it
|
|
echo WARNING: Found a project.yaml in '%project_dir%', but the wrapper script is missing; using Kotlin Toolchain v%kotlin_cli_version%. >&2
|
|
exit /b 1
|
|
)
|
|
|
|
:find_next_parent
|
|
@rem Move to parent directory
|
|
for %%P in ("%project_dir%\..") do set parent_dir=%%~fP
|
|
if "%parent_dir%"=="%project_dir%" (
|
|
@rem Reached the root, stop searching
|
|
exit /b 1
|
|
)
|
|
set project_dir=%parent_dir%
|
|
goto :find_loop
|
|
|
|
:parse_project_context
|
|
@rem Parse kotlin_cli_version and kotlin_cli_sha256 from the found wrapper_script without executing it.
|
|
set parsed_kotlin_cli_version=
|
|
set parsed_kotlin_cli_sha256=
|
|
|
|
for /f "tokens=2 delims==" %%A in ('findstr /r /c:"^set kotlin_cli_version=[A-Za-z0-9._+-]*$" "%wrapper_script%"') do (
|
|
if not defined parsed_kotlin_cli_version set parsed_kotlin_cli_version=%%A
|
|
)
|
|
for /f "tokens=2 delims==" %%A in ('findstr /r /c:"^set kotlin_cli_sha256=[0-9a-fA-F]*$" "%wrapper_script%"') do (
|
|
if not defined parsed_kotlin_cli_sha256 set parsed_kotlin_cli_sha256=%%A
|
|
)
|
|
|
|
if not defined parsed_kotlin_cli_version (
|
|
echo ERROR: Suspicious local wrapper script: failed to detect the distribution version in '%wrapper_script%' >&2
|
|
exit /b 1
|
|
)
|
|
if not defined parsed_kotlin_cli_sha256 (
|
|
echo ERROR: Suspicious local wrapper script: failed to detect the distribution checksum in '%wrapper_script%' >&2
|
|
exit /b 1
|
|
)
|
|
|
|
@rem Overwrite builtin values and proceed
|
|
set kotlin_cli_version=%parsed_kotlin_cli_version%
|
|
set kotlin_cli_sha256=%parsed_kotlin_cli_sha256%
|
|
exit /b 0
|
|
|
|
:fail
|
|
echo ERROR: Kotlin CLI bootstrap failed, see errors above
|
|
exit /b 1
|
|
|
|
:after_function_declarations
|
|
|
|
REM ********** Project-local version detection **********
|
|
|
|
if defined KOTLIN_CLI_WRAPPER_ALWAYS_USE_INTRINSIC_VERSION goto :after_local_version_detection
|
|
|
|
call :find_project_context
|
|
if errorlevel 1 goto :after_local_version_detection
|
|
call :parse_project_context
|
|
if errorlevel 1 goto fail
|
|
:after_local_version_detection
|
|
|
|
REM ********** Provision the Kotlin Toolchain distribution **********
|
|
|
|
set kotlin_cli_url=%KOTLIN_CLI_DOWNLOAD_ROOT%/org/jetbrains/kotlin/kotlin-cli/%kotlin_cli_version%/kotlin-cli-%kotlin_cli_version%-dist.tgz
|
|
set kotlin_cli_target_dir=%KOTLIN_CLI_BOOTSTRAP_CACHE_DIR%\kotlin-cli-%kotlin_cli_version%
|
|
call :download_and_extract "Kotlin Toolchain distribution v%kotlin_cli_version%" "%kotlin_cli_url%" "%kotlin_cli_target_dir%" "%kotlin_cli_sha256%" "256" "true"
|
|
if errorlevel 1 goto fail
|
|
|
|
REM ********** Launch the Kotlin CLI **********
|
|
|
|
rem Determine the correct busybox binary based on architecture
|
|
if "%PROCESSOR_ARCHITECTURE%"=="ARM64" (
|
|
set busybox_exe=%kotlin_cli_target_dir%\bin\busybox64a.exe
|
|
) else if "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
|
|
set busybox_exe=%kotlin_cli_target_dir%\bin\busybox64u.exe
|
|
) else (
|
|
echo Unsupported architecture %PROCESSOR_ARCHITECTURE% >&2
|
|
goto fail
|
|
)
|
|
|
|
rem We use busybox here because it doesn't reinterpret the user-passed command-line arguments (that we pass via %*).
|
|
rem Also this way we can use the unified launcher script (.sh)
|
|
set KOTLIN_CLI_WRAPPER_PATH=%~f0
|
|
|
|
rem The '& call' after the app run is to avoid the "Terminate batch job (Y/N)?" prompt
|
|
"%busybox_exe%" sh "%kotlin_cli_target_dir%\bin\launcher.sh" %* & call :exitWithErrorLevel
|
|
|
|
:exitWithErrorLevel
|
|
@rem We use "%COMSPEC%" /d /c exit so that and/or operators work properly when calling kotlin.bat directly from a script
|
|
@rem without the `call` command. With a plain `exit /B %ERRORLEVEL%`, using `kotlin.bat && echo success` would print
|
|
@rem 'success' even in case of failure. Consumers would have to use `call kotlin.bat && echo success` for it to work.`
|
|
"%COMSPEC%" /d /c exit %ERRORLEVEL%
|