From 0e979aefb4270a19df562e094123a9bcf38a6e3c Mon Sep 17 00:00:00 2001 From: FantasqueX Date: Fri, 26 Jan 2024 18:01:43 +0800 Subject: [PATCH] Add a PowerShell wrapper (#58) [PowerShell](https://github.com/PowerShell/PowerShell) is a modern command line shell for Windows. This patch adds a PowerShell wrapper. This version is more maintainable than bat version. There are some difference with existing bat wrapper. First, Downloaded mill is stored in `$Env:LOCALAPPDATA\mill` instead of `$Env:%USERPROFILE%\.mill` because according to https://en.wikipedia.org/wiki/Environment_variable#Windows, `%LOCALAPPDATA%` is the temporary files of Applications. And folder starting with "." is not hidden in Windows. Second, argument to set mill version is changed to `-MillVersion` to follow PowerShell converion, just like `-RelativeBasePath` of `Resolve-Path` https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/resolve-path. Pull request: https://github.com/lefou/millw/pull/58 --- README.adoc | 6 +-- millw.ps1 | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 millw.ps1 diff --git a/README.adoc b/README.adoc index 8d6fd32..08832a9 100644 --- a/README.adoc +++ b/README.adoc @@ -10,7 +10,7 @@ Small script to automatically fetch and execute {mill-url}[mill build tool]. == Installation -On any platform, you can download the `millw` (Mac / Linux) or `millw.bat` (Windows) scripts found in this repo, into the root of your project. +On any platform, you can download the `millw` (Mac / Linux) or `millw.bat` / `millw.ps1` (Windows) scripts found in this repo, into the root of your project. You can then use the script file as a drop-in replacement for Mill. For convenience on Mac and Linux, use your terminal to navigate to the root of your project, then run the following command: @@ -25,11 +25,11 @@ $ curl -L https://raw.githubusercontent.com/lefou/millw/{version}/millw > mill & == How it works `millw` is a small wrapper script around mill and works almost identical to mill. -It automatically downloads the correct mill version (into `${XDG_CACHE_HOME}/mill/download` or `~/.cache/mill/download`). +It automatically downloads the correct mill version (into `${XDG_CACHE_HOME}/mill/download` or `~/.cache/mill/download` on Linux/Mac and `$Env:LOCALAPPDATA\mill\download` on Windows). I recommend to rename the tool to just `mill`. It is designed to be a drop-in replacement for the official mill binary. -The project name and also the script name was primarily choosen to be `millw` to disambiguate references. +The project name and also the script name was primarily chosen to be `millw` to disambiguate references. The mill version to be used will be determined by the following steps. The search ends, after the first step that results in a version. diff --git a/millw.ps1 b/millw.ps1 new file mode 100644 index 0000000..747df3f --- /dev/null +++ b/millw.ps1 @@ -0,0 +1,134 @@ +# This is a wrapper script, that automatically download mill from GitHub release pages +# You can give the required mill version with -MillVersion parameter +# If no version is given, it falls back to the value of DEFAULT_MILL_VERSION +# +# Project page: https://github.com/lefou/millw +# Script Version: 0.4.11 +# +# If you want to improve this script, please also contribute your changes back! +# +# Licensed under the Apache License, Version 2.0 + +[CmdletBinding(PositionalBinding = $false)] + +param( + [Parameter(ValueFromRemainingArguments = $true, Position = 0)] + [string[]] $remainingArgs +) + +$DEFAULT_MILL_VERSION = $Env:DEFAULT_MILL_VERSION ?? '0.11.6' + +$GITHUB_RELEASE_CDN = $Env:GITHUB_RELEASE_CDN ?? '' + +$MILL_REPO_URL = 'https://github.com/com-lihaoyi/mill' + +$MILL_VERSION = $null + +if ($null -ne $remainingArgs) { + if ($remainingArgs[0] -eq '--mill-version') { + $remainingArgs = Select-Object -InputObject $remainingArgs -Skip 1 + if ($null -ne $remainingArgs) { + $MILL_VERSION = $remainingArgs[0] + $remainingArgs = Select-Object -InputObject $remainingArgs -Skip 1 + } + else { + Write-Error -Message "Please provide a version that matches one provided on $MILL_REPO_URL/releases" + throw [System.ArgumentNullException] '--mill-version' + } + } +} + +if ($null -eq $MILL_VERSION) { + if (Test-Path -Path '.mill-version' -PathType Leaf) { + $MILL_VERSION = Get-Content -Path '.mill-version' -TotalCount 1 + } + elseif (Test-Path -Path '.config/mill-version' -PathType Leaf) { + $MILL_VERSION = Get-Content -Path '.config/mill-version' -TotalCount 1 + } +} + +$MILL_USER_CACHE_DIR = Join-Path -Path $Env:LOCALAPPDATA -ChildPath 'mill' + +$MILL_DOWNLOAD_PATH = $Env:MILL_DOWNLOAD_PATH ?? @(Join-Path -Path ${MILL_USER_CACHE_DIR} -ChildPath 'download') + +if ($null -eq $MILL_VERSION) { + Write-Warning -Message 'No mill version specified.' + Write-Warning -Message "You should provide a version via '.mill-version' file or --mill-version option." + + if (-not (Test-Path -Path "$MILL_DOWNLOAD_PATH" -PathType Container)) { + New-Item "$MILL_DOWNLOAD_PATH" -ItemType Directory | Out-Null + } + + $MILL_LATEST_PATH = Join-Path -Path $MILL_DOWNLOAD_PATH -ChildPath '.latest' + + if (Test-Path -Path $MILL_LATEST_PATH -PathType Leaf) { + if ($(Get-Item -Path $MILL_LATEST_PATH).LastWriteTime -lt $(Get-Date).AddHours(-1)) { + $MILL_VERSION = Get-Content -Path $MILL_LATEST_PATH -TotalCount 1 + } + } + + if ($null -eq $MILL_VERSION) { + Write-Output 'Retrieving latest mill version ...' + + # https://github.com/PowerShell/PowerShell/issues/20964 + $targetUrl = + try { + Invoke-WebRequest -Uri "$MILL_REPO_URL/releases/latest" -MaximumRedirection 0 + } + catch { + $_.Exception.Response.Headers.Location.AbsoluteUri + } + + $targetUrl -match "^$MILL_REPO_URL/releases/tag/(.+)$" | Out-Null + + $MILL_VERSION = $Matches.1 + + if ($null -ne $MILL_VERSION) { + Set-Content -Path $MILL_LATEST_PATH -Value $MILL_VERSION + } + } + + if ($null -eq $MILL_VERSION) { + $MILL_VERSION = $DEFAULT_MILL_VERSION + Write-Warning "Falling back to hardcoded mill version $MILL_VERSION" + } + else { + Write-Output "Using mill version $MILL_VERSION" + } +} + +$MILL = "$MILL_DOWNLOAD_PATH/$MILL_VERSION.bat" + +if (-not (Test-Path -Path $MILL -PathType Leaf)) { + $DOWNLOAD_SUFFIX, $DOWNLOAD_FROM_MAVEN = switch -Regex ($MILL_VERSION) { + '^0\.[0-4]\..*$' { '', $false } + '0\.(?:[5-9]\.|10\.|11\.0-M).*' { '-assembly', $false } + Default { '-assembly', $true } + } + + if ($DOWNLOAD_FROM_MAVEN) { + $DOWNLOAD_URL = "https://repo1.maven.org/maven2/com/lihaoyi/mill-dist/$MILL_VERSION/mill-dist-$MILL_VERSION.jar" + } + else { + $MILL_VERSION -match '(\d+\.\d+\.\d+(?:-M\d+)?)' | Out-Null + $MILL_VERSION_TAG = $Matches.1 + $DOWNLOAD_URL = "$GITHUB_RELEASE_CDN$MILL_REPO_URL/releases/download/$MILL_VERSION_TAG/$MILL_VERSION$DOWNLOAD_SUFFIX" + } + Write-Output "Downloading mill $MILL_VERSION from $DOWNLOAD_URL ..." + + Invoke-WebRequest -Uri $DOWNLOAD_URL -OutFile $MILL +} + +$MILL_MAIN_CLI = $Env:MILL_MAIN_CLI ?? $PSCommandPath + +$MILL_FIRST_ARG = $null +$REMAINING_ARGUMENTS = $remainingArgs + +if ($null -ne $remainingArgs) { + if ($remainingArgs[0] -eq '--bsp' -or $remainingArgs -eq '-i' -or $remainingArgs -eq '--interactive' -or $remainingArgs -eq '--no-server') { + $MILL_FIRST_ARG = $remainingArgs[0] + $REMAINING_ARGUMENTS = Select-Object -InputObject $remainingArgs -Skip 1 + } +} + +& $MILL $MILL_FIRST_ARG -D "mill.main.cli=$MILL_MAIN_CLI" $REMAINING_ARGUMENTS