diff --git a/.mill-cs-opts b/.mill-cs-opts new file mode 100644 index 0000000000..e463660ded --- /dev/null +++ b/.mill-cs-opts @@ -0,0 +1,7 @@ +# Java 17 required for domain socket stuff +--jvm +temurin:17 +# fixes some issues when fetching snapshot artifacts +io.get-coursier::coursier:2.1.0-M2 +--scala +2.13.8 diff --git a/mill b/mill index c0cb1a18de..c051e83856 100755 --- a/mill +++ b/mill @@ -1,25 +1,197 @@ #!/usr/bin/env bash + +# This is a wrapper script, that automatically download mill via coursier +# You can give the required mill version with --mill-version parameter +# If no version is given, it falls back to the value of DEFAULT_MILL_VERSION +# +# Project page: https://github.com/coursier/millw +# Original project page: https://github.com/lefou/millw +# Script Version: 0.4.0-cs +# +# If you want to improve this script, please also contribute your changes back! +# +# Licensed under the Apache License, Version 2.0 + + +DEFAULT_MILL_VERSION=0.9.10 + set -e -# This script ensures: -# - that we're using the right JVM (currently, temurin:17) -# - that we run the mill launcher script with bash rather than sh, -# as the latter has issues with '+' characters, that can appear -# in the JVM entry put in PATH by 'cs'. +MILL_REPO_URL="https://github.com/com-lihaoyi/mill" + +if [ "x${CURL_CMD}" = "x" ] ; then + CURL_CMD=curl +fi + +# Explicit commandline argument takes precedence over all other methods +if [ "x$1" = "x--mill-version" ] ; then + shift + if [ "x$1" != "x" ] ; then + MILL_VERSION="$1" + shift + else + echo "You specified --mill-version without a version." 1>&2 + echo "Please provide a version that matches one provided on" 1>&2 + echo "${MILL_REPO_URL}/releases" 1>&2 + false + fi +fi + +# Please note, that if a MILL_VERSION is already set in the environment, +# We reuse it's value and skip searching for a value. + +# If not already set, read .mill-version file +if [ "x${MILL_VERSION}" = "x" ] ; then + if [ -f ".mill-version" ] ; then + MILL_VERSION="$(head -n 1 .mill-version 2> /dev/null)" + fi +fi + +if [ "x${XDG_CACHE_HOME}" != "x" ] ; then + MILL_DOWNLOAD_PATH="${XDG_CACHE_HOME}/mill/download" +else + MILL_DOWNLOAD_PATH="${HOME}/.cache/mill/download" +fi + +# If not already set, try to fetch newest from Github +if [ "x${MILL_VERSION}" = "x" ] ; then + # TODO: try to load latest version from release page + echo "No mill version specified." 1>&2 + echo "You should provide a version via '.mill-version' file or --mill-version option." 1>&2 + + mkdir -p "${MILL_DOWNLOAD_PATH}" + LANG=C touch -d '1 hour ago' "${MILL_DOWNLOAD_PATH}/.expire_latest" 2>/dev/null || ( + # we might be on OSX or BSD which don't have -d option for touch + # but probably a -A [-][[hh]mm]SS + touch "${MILL_DOWNLOAD_PATH}/.expire_latest"; touch -A -010000 "${MILL_DOWNLOAD_PATH}/.expire_latest" + ) || ( + # in case we still failed, we retry the first touch command with the intention + # to show the (previously suppressed) error message + LANG=C touch -d '1 hour ago' "${MILL_DOWNLOAD_PATH}/.expire_latest" + ) + + if [ "${MILL_DOWNLOAD_PATH}/.latest" -nt "${MILL_DOWNLOAD_PATH}/.expire_latest" ] ; then + # we know a current latest version + MILL_VERSION="$(head -n 1 ${MILL_DOWNLOAD_PATH}/.latest 2> /dev/null)" + fi + + if [ "x${MILL_VERSION}" = "x" ] ; then + # we don't know a current latest version + echo "Retrieving latest mill version ..." 1>&2 + LANG=C ${CURL_CMD} -s -i -f -I ${MILL_REPO_URL}/releases/latest 2> /dev/null | grep --ignore-case Location: | sed s'/^.*tag\///' | tr -d '\r\n' > "${MILL_DOWNLOAD_PATH}/.latest" + MILL_VERSION="$(head -n 1 ${MILL_DOWNLOAD_PATH}/.latest 2> /dev/null)" + fi + + if [ "x${MILL_VERSION}" = "x" ] ; then + # Last resort + MILL_VERSION="${DEFAULT_MILL_VERSION}" + echo "Falling back to hardcoded mill version ${MILL_VERSION}" 1>&2 + else + echo "Using mill version ${MILL_VERSION}" 1>&2 + fi +fi + +unset MILL_DOWNLOAD_PATH +unset MILL_OLD_DOWNLOAD_PATH +unset OLD_MILL +unset MILL_VERSION_TAG +unset MILL_REPO_URL + +if [ "x$1" == "x-i" -o "x$1" == "x--interactive" ]; then + MILL_APP_NAME="mill-interactive" +else + MILL_APP_NAME="mill" +fi + +mill_cs_opts=() + +# Adapted from Mill 0.10.0-M5 assembly +init_mill_jvm_opts() { + if [ -z $MILL_JVM_OPTS_PATH ] ; then + mill_jvm_opts_file=".mill-jvm-opts" + else + mill_jvm_opts_file=$MILL_JVM_OPTS_PATH + fi + + if [ -f "$mill_jvm_opts_file" ] ; then + while IFS= read line + do + case $line in + "-X"*) mill_cs_opts=("${mill_cs_opts[@]}" "--java-opt" "$line") + esac + done <"$mill_jvm_opts_file" + fi +} + +init_mill_cs_opts() { + if [ -z $MILL_CS_OPTS_PATH ] ; then + mill_cs_opts_file=".mill-cs-opts" + else + mill_cs_opts_file=$MILL_CS_OPTS_PATH + fi + + if [ -f "$mill_cs_opts_file" ] ; then + while IFS= read line + do + case $line in + "#"*) ;; + *) mill_cs_opts=("${mill_cs_opts[@]}" "$line") ;; + esac + done <"$mill_cs_opts_file" + fi +} -DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)" -if ! command -v cs >/dev/null; then - cat 1>&2 << EOF -cs command not found. +# Adapted from -Please download a cs launcher from - https://github.com/coursier/coursier/releases/tag/v2.1.0-M2 -and install it as 'cs' in your PATH. -EOF - exit 1 +coursier_version="2.1.0-M2" + +# https://stackoverflow.com/questions/3466166/how-to-check-if-running-in-cygwin-mac-or-linux/17072017#17072017 +if [ "$(expr substr $(uname -s) 1 5 2>/dev/null)" == "Linux" ]; then + cs_url="https://github.com/coursier/coursier/releases/download/v$coursier_version/cs-x86_64-pc-linux.gz" + cache_base="$HOME/.cache/coursier/v1" +elif [ "$(uname)" == "Darwin" ]; then + cs_url="https://github.com/coursier/coursier/releases/download/v$coursier_version/cs-x86_64-apple-darwin.gz" + cache_base="$HOME/Library/Caches/Coursier/v1" +else + # assuming Windows… + cs_url="https://github.com/coursier/coursier/releases/download/v$coursier_version/cs-x86_64-pc-win32.zip" + cache_base="$LOCALAPPDATA/Coursier/v1" # TODO Check that + ext=".exe" + do_chmod="0" +fi + +cache_dest="$cache_base/$(echo "$cs_url" | sed 's@://@/@')" + +if [ ! -f "$cache_dest" ]; then + mkdir -p "$(dirname "$cache_dest")" + tmp_dest="$cache_dest.tmp-setup" + echo "Downloading $cs_url" + curl -fLo "$tmp_dest" "$cs_url" + mv "$tmp_dest" "$cache_dest" +fi + +if [[ "$cache_dest" == *.gz ]]; then + cs="$(dirname "$cache_dest")/$(basename "$cache_dest" .gz)" + if [ ! -f "$cs" ]; then + gzip -d < "$cache_dest" > "$cs" + fi + if [ ! -x "$cs" ]; then + chmod +x "$cs" + fi +elif [[ "$cache_dest" == *.zip ]]; then + cs="$(dirname "$cache_dest")/$(basename "$cache_dest" .zip).exe" + if [ ! -f "$cs" ]; then + unzip -p "$cache_dest" "$(basename "$cache_dest" .zip).exe" > "$cs" + fi fi eval "$(cs java --env --jvm temurin:17 || cs java --env --jvm openjdk:1.17.0)" +export PATH=".:$PATH" + + + +init_mill_jvm_opts +init_mill_cs_opts -exec /usr/bin/env bash "$DIR/millw" "$@" +exec "$cs" launch "$MILL_APP_NAME:$MILL_VERSION" "${mill_cs_opts[@]}" -- "$@" diff --git a/mill.bat b/mill.bat index 879689f1f2..b121d98178 100644 --- a/mill.bat +++ b/mill.bat @@ -1,10 +1,12 @@ @echo off -rem This is a wrapper script, that automatically download mill from GitHub release pages +rem This is a wrapper script, that automatically download mill via coursier rem You can give the required mill version with --mill-version parameter rem If no version is given, it falls back to the value of DEFAULT_MILL_VERSION rem -rem Project page: https://github.com/lefou/millw +rem Project page: https://github.com/coursier/millw +rem Original project page: https://github.com/lefou/millw +rem Script Version: 0.4.0-cs rem rem If you want to improve this script, please also contribute your changes back! rem @@ -42,57 +44,6 @@ if [!MILL_VERSION!]==[] ( set MILL_VERSION=%DEFAULT_MILL_VERSION% ) -set MILL_DOWNLOAD_PATH=%USERPROFILE%\.mill\download - -rem without bat file extension, cmd doesn't seem to be able to run it -set MILL=%MILL_DOWNLOAD_PATH%\!MILL_VERSION!.bat - -if not exist "%MILL%" ( - set VERSION_PREFIX=%MILL_VERSION:~0,4% - set DOWNLOAD_SUFFIX=-assembly - if [!VERSION_PREFIX!]==[0.0.] set DOWNLOAD_SUFFIX= - if [!VERSION_PREFIX!]==[0.1.] set DOWNLOAD_SUFFIX= - if [!VERSION_PREFIX!]==[0.2.] set DOWNLOAD_SUFFIX= - if [!VERSION_PREFIX!]==[0.3.] set DOWNLOAD_SUFFIX= - if [!VERSION_PREFIX!]==[0.4.] set DOWNLOAD_SUFFIX= - set VERSION_PREFIX= - - for /F "delims=-" %%A in ("!MILL_VERSION!") do ( - set MILL_BASE_VERSION=%%A - ) - - rem there seems to be no way to generate a unique temporary file path (on native Windows) - set DOWNLOAD_FILE=%MILL%.tmp - - set DOWNLOAD_URL=%MILL_REPO_URL%/releases/download/!MILL_BASE_VERSION!/!MILL_VERSION!!DOWNLOAD_SUFFIX! - - echo Downloading mill %MILL_VERSION% from %MILL_REPO_URL%/releases ... - - if not exist "%MILL_DOWNLOAD_PATH%" mkdir "%MILL_DOWNLOAD_PATH%" - rem curl is bundled with recent Windows 10 - rem but I don't think we can expect all the users to have it in 2019 - where /Q curl - if %ERRORLEVEL% EQU 0 ( - curl -L "!DOWNLOAD_URL!" -o "!DOWNLOAD_FILE!" - ) else ( - rem bitsadmin seems to be available on Windows 7 - rem without /dynamic, github returns 403 - rem bitsadmin is sometimes needlessly slow but it looks better with /priority foreground - bitsadmin /transfer millDownloadJob /dynamic /priority foreground "!DOWNLOAD_URL!" "!DOWNLOAD_FILE!" - ) - if not exist "!DOWNLOAD_FILE!" ( - echo Could not download mill %MILL_VERSION% - exit /b 1 - ) - - move /y "!DOWNLOAD_FILE!" "%MILL%" - - set DOWNLOAD_FILE= - set DOWNLOAD_SUFFIX= -) - -set MILL_DOWNLOAD_PATH= -set MILL_VERSION= set MILL_REPO_URL= set MILL_PARAMS=%* @@ -106,4 +57,66 @@ if defined STRIP_VERSION_PARAMS ( ) ) -"%MILL%" %MILL_PARAMS% +if "%1" == "-i" set _I_=true +if "%1" == "--interactive" set _I_=true +if defined _I_ ( + set MILL_APP_NAME="mill-interactive" +) else ( + set MILL_APP_NAME="mill" +) + +set "mill_cs_opts=" + +set "mill_jvm_opts_file=.mill-jvm-opts" +if not "%MILL_JVM_OPTS_PATH%"=="" set "mill_jvm_opts_file=%MILL_JVM_OPTS_PATH%" +if exist %mill_jvm_opts_file% ( + for /f "delims=" %%G in (%mill_jvm_opts_file%) do ( + set line=%%G + if "!line:~0,2!"=="-X" set "mill_cs_opts=!mill_cs_opts! --java-opt !line!" + ) +) + +set "mill_cs_opts_file=.mill-cs-opts" +if not "%MILL_CS_OPTS_PATH%"=="" set "mill_cs_opts_file=%MILL_CS_OPTS_PATH%" +if exist %mill_cs_opts_file% ( + for /f "delims=" %%G in (%mill_cs_opts_file%) do ( + set line=%%G + if not "!line:~0,1!"=="#" set "mill_cs_opts=!mill_cs_opts! !line!" + ) +) + +rem Disabled for now, having issues with 'tar', that seems to use a Git Bash-provided (?) +rem binary rather than a Windows-provided one, when run from Git Bash. The latter accepts +rem zip files, while the former doesn't. + +rem Adapted from the Mill 0.10.0-M5 assembly header +rem set "CS_DOWNLOAD_PATH=out" +rem set "CS_VERSION=2.1.0-M2" +rem set "CS=%CS_DOWNLOAD_PATH%\cs-%CS_VERSION%.exe" +rem set "DOWNLOAD_URL=https://github.com/coursier/coursier/releases/download/v%CS_VERSION%/cs-x86_64-pc-win32.zip" +rem set "DOWNLOAD_FILE=%CS_DOWNLOAD_PATH%\cs-%CS_VERSION%.zip" +rem if not exist "%CS_DOWNLOAD_PATH%" mkdir "%CS_DOWNLOAD_PATH%" +rem if not exist "%CS%" ( +rem rem curl is bundled with recent Windows 10 +rem rem but I don't think we can expect all the users to have it in 2019 +rem where /Q curl +rem if %ERRORLEVEL% EQU 0 ( +rem curl -f -L "!DOWNLOAD_URL!" -o "!DOWNLOAD_FILE!" +rem ) else ( +rem rem bitsadmin seems to be available on Windows 7 +rem rem without /dynamic, github returns 403 +rem rem bitsadmin is sometimes needlessly slow but it looks better with /priority foreground +rem bitsadmin /transfer millDownloadJob /dynamic /priority foreground "!DOWNLOAD_URL!" "!DOWNLOAD_FILE!" +rem ) +rem if not exist "!DOWNLOAD_FILE!" ( +rem echo Could not download cs %CS_VERSION% 1>&2 +rem exit /b 1 REM Seems this doesn't actually make the script exit with an error code… +rem ) +rem +rem tar -xf "!DOWNLOAD_FILE!" +rem move /y "cs-x86_64-pc-win32.exe" "%CS%" +rem ) + +echo Using system found cs command. If anything goes wrong, ensure it's at least coursier 2.1.0-M2. 1>&2 + +cs launch --shared org.scala-lang:scala-library "%MILL_APP_NAME%:%MILL_VERSION%" !mill_cs_opts! -- %MILL_PARAMS%