From d49cb99f566539323c6967d4724ca41054cb752b Mon Sep 17 00:00:00 2001 From: Qiheng He Date: Tue, 3 Nov 2026 13:49:39 +0800 Subject: [PATCH] fix: make `.sdkmanrc` with SDKMAN's Oracle GraalVM and GraalVM Community identifiers, such as `java=25.0.5.0+3-graal`, select the build they name --- docs/changes.md | 6 +++++- docs/development.md | 4 ++-- docs/e2e.md | 6 ++++++ docs/sdkmanrc.md | 9 ++++++--- docs/zh-CN/changes.md | 6 +++++- docs/zh-CN/development.md | 4 ++-- docs/zh-CN/e2e.md | 2 +- docs/zh-CN/sdkmanrc.md | 9 ++++++--- hooks/parse_legacy_file.lua | 26 ++++++++++++++++++++++++-- tests/e2e/common/common.go | 23 +++++++++++++++++++++++ tests/e2e/common/common_test.go | 27 +++++++++++++++++++++++++++ tests/e2e/linux/setup.go | 24 ++++++++++++++++++++++-- tests/e2e/windows/setup.go | 17 +++++++++++++++++ tests/parse_legacy_file_test.lua | 27 +++++++++++++++++++++++++-- 14 files changed, 171 insertions(+), 19 deletions(-) diff --git a/docs/changes.md b/docs/changes.md index fdd24bd..86f7e36 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -2,7 +2,11 @@ [中文](zh-CN/changes.md) | [English](changes.md) -What changed in each release, as a user notices it. GitHub's release pages list the pull requests. +What changed in each release, as a user notices it. GitHub's release pages list the pull requests. The newest release at the time of writing is 0.6.4, and `main` is ahead of it by everything under "Unreleased". [install-from-source.md](install-from-source.md) gets you those changes now. + +## Unreleased + +- A `.sdkmanrc` takes SDKMAN's identifiers of Oracle GraalVM and GraalVM Community, which write the fifth number of GraalVM's version after the `+`: `java=25.0.5.0+3-graal` selects `25.0.5.0.3-graal`, and `java=25.4.4.1+1-graalce` selects `25.4.4.1.1-graalce`. Release 0.6.4 takes that number for a build of the release 25.0.5 and finds no such name. So it selects `25.0.5-graal` where that is installed next to `25.0.5.0.3-graal`, which is a different download (Oracle ships `25.0.5`, `25.0.5.0.2` and `25.0.5.0.3` as three files), and otherwise the newest installed release of 25: a project pinned to `25.0.5.0+3-graal` moves to a newer GraalVM as soon as one is installed. See [sdkmanrc.md](sdkmanrc.md#sdkmans-spellings) ([#124](https://github.com/version-fox/vfox-java/pull/124)). ## 0.6.4 (2026-11-03) diff --git a/docs/development.md b/docs/development.md index a03f51f..d500528 100644 --- a/docs/development.md +++ b/docs/development.md @@ -53,7 +53,7 @@ A few contracts that cost time to find: Installed names are `[-][-fx]`, with no short name for OpenJDK, Foojay's `distribution_version` in place of `java_version` for Mandrel and Liberica NIK, and GraalVM's own version for `graal` and `graalce` ([versions.md](versions.md#installed-names)). `lib/distribution_version.lua` reads a spec into a version, a distribution and the JavaFX flag, in either order (`21-tem`, `tem-21`). `lib/installed_version.lua` turns a version the user typed into an installed name: the name itself first. A bare major then takes the newest installed release of it, and any other version takes the release itself or its newest build. `PreUse` stops there. `ParseLegacyFile` goes one step further and falls back to the newest installed release of the major. Both leave out Oracle GraalVM's feature releases when they take the newest release of a major, unless nothing else of it is installed (`bare_major_skips`, see below). -SDKMAN spells some things differently (`jbr`, `21.0.12.fx-zulu`, `21.0.12-fx+1.1-librca`, `28.0.0+ea.19-open`), and `plugin_spelling` in `hooks/parse_legacy_file.lua` rewrites them into the plugin's before parsing. For the distributions SDKMAN no longer lists, `sdkman_flavours` there turns the virtual machine or JDK in SDKMAN's version into the short name (`22.3.3.r17-grl` is `22.3.3-grl17`). For Mandrel and Liberica NIK (`sdkman_jdks`) the JDK is dropped (`25.0.4.r25-nik` is `25.0.4-nik`). An identifier with the older JDK of a release that comes for two, which `older_jdk` returns, selects nothing (`22.1.r11-mandrel`). `installed_version.unpad` drops the zeros SDKMAN pads releases with (`27.0.0+36` is `27+36`). Where the short names differ from SDKMAN's is in [distributions.md](distributions.md#short-names-and-sdkman). +SDKMAN spells some things differently (`jbr`, `21.0.12.fx-zulu`, `21.0.12-fx+1.1-librca`, `28.0.0+ea.19-open`), and `plugin_spelling` in `hooks/parse_legacy_file.lua` rewrites them into the plugin's before parsing. For the distributions SDKMAN no longer lists, `sdkman_flavours` there turns the virtual machine or JDK in SDKMAN's version into the short name (`22.3.3.r17-grl` is `22.3.3-grl17`). For Mandrel and Liberica NIK (`sdkman_jdks`) the JDK is dropped (`25.0.4.r25-nik` is `25.0.4-nik`). An identifier with the older JDK of a release that comes for two, which `older_jdk` returns, selects nothing (`22.1.r11-mandrel`). `installed_version.unpad` drops the zeros SDKMAN pads releases with (`27.0.0+36` is `27+36`). In the identifiers of Oracle GraalVM and GraalVM Community (`sdkman_graalvm`) the number after the `+` is the fifth number of GraalVM's version and no build, so `ParseLegacyFile` looks for the installed name with a dot before the others (`25.0.5.0+3-graal` is `25.0.5.0.3-graal`). Where the short names differ from SDKMAN's is in [distributions.md](distributions.md#short-names-and-sdkman). ## Foojay @@ -67,7 +67,7 @@ SDKMAN spells some things differently (`jbr`, `21.0.12.fx-zulu`, `21.0.12-fx+1.1 - The package's record (`links.pkg_info_uri`) holds `checksum_type` and either `checksum` or `checksum_uri`. `checksum.lookup` in `lib/checksum.lua` takes the digest of the record first, which also costs no request, and fetches the file only where the record has none. `PreInstall` hands it the function that fetches, which sends a GitHub address through `$VFOX_JAVA_GITHUB_MIRROR`, so the library needs no `http` and the tests need no stub for it. A file that lists other packages only gives none, because the digest of another file would fail an install that is fine: Microsoft's file for its EA build of 11.0.14 for macOS names the GA build. - `Available` lists a name once where Foojay has two records for it. - Foojay marks GraalVM Community's monthly feature releases (`25.1.3` and on) as LTS where it lists them the old way round, as it did Oracle GraalVM's. `is_feature_release` in `lib/distribution_version.lua` recognises them, by the minor number, and `Available` drops the note. It is for `graal` and `graalce` only: Mandrel and Liberica NIK carry GraalVM's older numbers up to 24, whose minor is no feature release (`mandrel` `23.1.12` is LTS), and the JDK's from 25 on. -- For a bare major of Oracle GraalVM (`graal`) only, `PreInstall` skips the feature releases, so the 25.0 line is installed. A major that has nothing but feature releases keeps them. GraalVM Community is not filtered, because its feature releases are what it still ships. `bare_major_skips` in `lib/distribution_version.lua` holds that rule. `PreUse` and `ParseLegacyFile` apply it to the installed versions as well, so that `vfox use` and a `.sdkmanrc` select the build `PreInstall` installs: the newest installed release of the major that is no feature release, else the newest feature release. `ParseLegacyFile` applies it to the fallback for a release that is not installed too, except when the file names a feature release (`25.4.4+1-graal`, as SDKMAN spells one), which takes the newest release of the major as before. +- For a bare major of Oracle GraalVM (`graal`) only, `PreInstall` skips the feature releases, so the 25.0 line is installed. A major that has nothing but feature releases keeps them. GraalVM Community is not filtered, because its feature releases are what it still ships. `bare_major_skips` in `lib/distribution_version.lua` holds that rule. `PreUse` and `ParseLegacyFile` apply it to the installed versions as well, so that `vfox use` and a `.sdkmanrc` select the build `PreInstall` installs: the newest installed release of the major that is no feature release, else the newest feature release. `ParseLegacyFile` applies it to the fallback for a release that is not installed too, except when the file names a feature release (`25.4.4.1+1-graal`, as SDKMAN spells one, or `25.4.4+1-graal`), which takes the newest release of the major as before. - The CPU names are `arm64` to `aarch64`, and on Windows `amd64` to `x64`. `darwin` becomes `macos`. On Linux `ldd --version` decides between glibc and musl. ## Tests diff --git a/docs/e2e.md b/docs/e2e.md index a014b1f..540d242 100644 --- a/docs/e2e.md +++ b/docs/e2e.md @@ -305,6 +305,12 @@ JDK, so `java` can only come from what vfox installs: which is a feature release as soon as one is installed ([#110](https://github.com/version-fox/vfox-java/issues/110)). Each faked build holds a stand-in `java` that only prints its name, as in item 6. + A `.sdkmanrc` holding SDKMAN's identifier of each faked build that has + five numbers (`25.0.5.0.3-graal` is `25.0.5.0+3-graal`, `25.4.4.1.1-graal` + is `25.4.4.1+1-graal`; `GraalVMIdentifiers` in `tests/e2e/common`) must + select that build, not the `25.0.5-graal` next to it or a newer release. + `ParseLegacyFile` took the number after the `+` for a build of the release + ([#124](https://github.com/version-fox/vfox-java/pull/124)). Once the 25.0 line is removed, `vfox use` and the `.sdkmanrc` must both select the newest feature release. 4. On the Temurin rows, which run on every runner, the distributions the diff --git a/docs/sdkmanrc.md b/docs/sdkmanrc.md index 0073138..dc72e8b 100644 --- a/docs/sdkmanrc.md +++ b/docs/sdkmanrc.md @@ -34,13 +34,13 @@ vfox's shell hook reads the file when you enter the directory and selects the JD The plugin matches the identifier against the JDKs that are installed, in this order: -1. An installed name written as it is: `java=21.0.8+9-tem`, `java=28-ea+19`. +1. An installed name written as it is: `java=21.0.8+9-tem`, `java=28-ea+19`. For Oracle GraalVM and GraalVM Community the number after the `+` is the fifth number of the version, so `java=25.0.5.0+3-graal` names `25.0.5.0.3-graal`, see [SDKMAN's spellings](#sdkmans-spellings). 2. The release you named, with its newest installed build: `21.0.8-tem` selects `21.0.8+9-tem`. 3. Failing that, the newest installed release of the same major. `21-tem` goes straight to this step. Step 3 does not check that the release is at least the one named. With only `21.0.8+9-tem` installed, `java=21.0.12-tem` selects it, and so does `java=21.0.3-tem`. A build number that is not installed falls back to the newest installed build of the release (`21.0.8+7-tem` selects `21.0.8+9-tem`). If the major is not installed at all, nothing is selected. -For Oracle GraalVM, step 3 leaves out the monthly feature releases (`25.4.4.1.1-graal`), as `vfox use java@25-graal` does, so `java=25-graal` and `java=25.0.3-graal` select the newest installed build of the 25.0 line. If nothing else of 25 is installed, a feature release is taken. If the file names a feature release (SDKMAN spells one `25.4.4+1-graal`), the newest installed release of 25 is taken. +For Oracle GraalVM, step 3 leaves out the monthly feature releases (`25.4.4.1.1-graal`), as `vfox use java@25-graal` does, so `java=25-graal` and `java=25.0.3-graal` select the newest installed build of the 25.0 line. If nothing else of 25 is installed, a feature release is taken. If the file names a feature release that is not installed (SDKMAN has spelled one `25.4.4.1+1-graal` and `25.4.4+1-graal`), the newest installed release of 25 is taken. It never crosses to another distribution, between a JavaFX build and a plain one, or between an early-access build and a release. @@ -56,6 +56,7 @@ It never crosses to another distribution, between a JavaFX build and a plain one | `21.0.12-fx+1.1-librca` | Liberica with JavaFX (newer spelling) | | `21.0.8+1.1-tem` | Temurin 21.0.8, see below | | `27.0.0+36-librca`, `25.0.1.0+8-open` | `27+36-librca`, `25.0.1+8`: the zeros are dropped | +| `25.0.5.0+3-graal`, `25.4.4.1+1-graalce` | `25.0.5.0.3-graal`, `25.4.4.1.1-graalce`: the number after the `+` is the fifth number of GraalVM's version | | `28.ea.19-open`, `28.0.0+ea.19-open` | the early-access build `28-ea+19` | | `25.0.4.r25-nik`, `25.0.2.r25-mandrel` | `25.0.4-nik`, `25.0.2-mandrel`: `.r` and the JDK after it are dropped | | `11.0.10.hs-adpt`, `11.0.10.j9-adpt` | AdoptOpenJDK with HotSpot, `11.0.10-adpt`, and with OpenJ9, `11.0.10-adptj9` | @@ -66,7 +67,9 @@ The last three rows are SDKMAN's identifiers for distributions it no longer list SDKMAN writes the JDK into some versions of Mandrel and Liberica NIK as well, which the plugin names after the GraalVM version alone, see [distributions.md](distributions.md#behavior-of-mandrel-and-liberica-nik). Of a release that comes for two JDKs, the plugin installs only the build for the newer one, so an identifier with the older one selects nothing: `22.1.r11-mandrel`, `23.0.1.r17-nik`. The older JDK is 11 from 21.3 to 22.3.5 and 17 from 23 to 23.0.1.2. `25.r25-mandrel` has only the major and selects the newest installed Mandrel 25, as `java=25-mandrel` does, while SDKMAN installs 25.0.1.0 for it. -The number after `+` in SDKMAN's newer identifiers (`21.0.8+1.1-tem`) counts SDKMAN's own rebuilds. It is not a build number of the vendor, so the plugin does not look for one and takes the release. Foojay, and so the installed name, has no zero padding, which is why `27.0.0` means the release `27`. A `.0` padding in `sdk list java` is common (`25.0.1.0+8-open`, `21.0.9.0+116386-jbr`), and the plugin reads it as well. +The number after `+` in SDKMAN's newer identifiers is a build number, the vendor's (`25.0.5.0+8-tem` is Temurin's build 8, installed as `25.0.5+8-tem`) or SDKMAN's own count of its rebuilds (`21.0.8+1.1-tem`). The plugin looks for an installed build of that number first and otherwise takes the release. Foojay, and so the installed name, has no zero padding, which is why `27.0.0` means the release `27`. A `.0` padding in `sdk list java` is common (`25.0.1.0+8-open`, `21.0.9.0+116386-jbr`), and the plugin reads it as well. + +Oracle GraalVM and GraalVM Community are the exception. Their versions have five numbers (`25.0.5.0.3`) where SDKMAN's identifiers have four before the `+`, so SDKMAN writes the fifth after it: `25.0.5.0+3-graal` is GraalVM 25.0.5.0.3, and `25.4.4.1+1-graalce` is the feature release 25.4.4.1.1. That number belongs to the release. Oracle ships `25.0.5`, `25.0.5.0.2` and `25.0.5.0.3` as three different files. The plugin looks for the installed name with the dot first, and failing that goes on with steps 2 and 3 as for any release that is not installed. `vfox install` takes the dotted name only (`java@25.0.5.0.3-graal`), not the identifier. Unreleased: release 0.6.4 takes the number for a build of the release `25.0.5`. So it selects `25.0.5-graal` when that is installed next to `25.0.5.0.3-graal`, and a newer release of 25 when that is installed instead. ## Not finding it diff --git a/docs/zh-CN/changes.md b/docs/zh-CN/changes.md index 3c4d97d..98304c7 100644 --- a/docs/zh-CN/changes.md +++ b/docs/zh-CN/changes.md @@ -2,7 +2,11 @@ [中文](changes.md) | [English](../changes.md) -按发布版本列出用户能感受到的变化。GitHub 的 Release 页面列出了对应的 PR。 +按发布版本列出用户能感受到的变化。GitHub 的 Release 页面列出了对应的 PR。写这篇文档时最新的发布版是 0.6.4,`main` 比它多出“未发布”下面的所有内容。想现在就用上这些变化,见 [install-from-source.md](install-from-source.md)。 + +## 未发布 + +- `.sdkmanrc` 里写 SDKMAN 给 Oracle GraalVM 和 GraalVM 社区版的标识符时,会选中它指明的版本。SDKMAN 把这两个发行版版本号的第五位写在 `+` 后面:`java=25.0.5.0+3-graal` 选中 `25.0.5.0.3-graal`,`java=25.4.4.1+1-graalce` 选中 `25.4.4.1.1-graalce`。0.6.4 把这个数字当作 25.0.5 的构建号,找不到这样的名字,于是 `25.0.5-graal` 和 `25.0.5.0.3-graal` 都装着时选中前者,而它们是不同的下载(Oracle 把 `25.0.5`、`25.0.5.0.2` 和 `25.0.5.0.3` 发布成了三个文件);没装 `25.0.5-graal` 时则选 25 里已安装的最新版本:钉在 `25.0.5.0+3-graal` 上的项目,一装了更新的 GraalVM 就会换过去。见 [sdkmanrc.md](sdkmanrc.md#sdkman-的写法)([#124](https://github.com/version-fox/vfox-java/pull/124))。 ## 0.6.4(2026-11-03) diff --git a/docs/zh-CN/development.md b/docs/zh-CN/development.md index fde5aac..ff3a66d 100644 --- a/docs/zh-CN/development.md +++ b/docs/zh-CN/development.md @@ -53,7 +53,7 @@ vfox 加载 `metadata.lua`,命令需要时调用相应的钩子,并向钩子 安装后的版本名是 `[-<简称>][-fx]`,OpenJDK 没有简称,Mandrel 和 Liberica NIK 用 Foojay 的 `distribution_version` 代替 `java_version`,`graal` 和 `graalce` 用 GraalVM 自己的版本号([versions.md](versions.md#安装后的版本名))。`lib/distribution_version.lua` 把一个写法解析成版本、发行版和 JavaFX 标志,两种顺序都接受(`21-tem`、`tem-21`)。`lib/installed_version.lua` 把用户输入的版本变成已安装的版本名:先看这个名字本身。只写大版本号时,取这个大版本里已安装的最新版本;其他写法则取这个版本本身,或它的最新构建。`PreUse` 到此为止。`ParseLegacyFile` 还会再退一步,取同一大版本里已安装的最新版本。这两处取一个大版本里的最新版本时,都会跳过 Oracle GraalVM 的特性版本,除非这个大版本里没有装别的版本(`bare_major_skips`,见下文)。 -SDKMAN 有些写法不同(`jbr`、`21.0.12.fx-zulu`、`21.0.12-fx+1.1-librca`、`28.0.0+ea.19-open`),`hooks/parse_legacy_file.lua` 里的 `plugin_spelling` 会在解析之前把它们改写成插件自己的写法。对 SDKMAN 已经不再提供的发行版,同一文件里的 `sdkman_flavours` 把 SDKMAN 写在版本号里的虚拟机或 JDK 版本换成简称(`22.3.3.r17-grl` 就是 `22.3.3-grl17`)。对 `sdkman_jdks` 里的 Mandrel 和 Liberica NIK,则是去掉 JDK 版本(`25.0.4.r25-nik` 就是 `25.0.4-nik`)。一个版本同时为两个 JDK 发布时,写了较旧 JDK(由 `older_jdk` 给出)的标识符什么都不选中(`22.1.r11-mandrel`)。SDKMAN 给版本补的零由 `installed_version.unpad` 去掉(`27.0.0+36` 就是 `27+36`)。简称与 SDKMAN 不同的地方见 [distributions.md](distributions.md#简称与-sdkman-的不同)。 +SDKMAN 有些写法不同(`jbr`、`21.0.12.fx-zulu`、`21.0.12-fx+1.1-librca`、`28.0.0+ea.19-open`),`hooks/parse_legacy_file.lua` 里的 `plugin_spelling` 会在解析之前把它们改写成插件自己的写法。对 SDKMAN 已经不再提供的发行版,同一文件里的 `sdkman_flavours` 把 SDKMAN 写在版本号里的虚拟机或 JDK 版本换成简称(`22.3.3.r17-grl` 就是 `22.3.3-grl17`)。对 `sdkman_jdks` 里的 Mandrel 和 Liberica NIK,则是去掉 JDK 版本(`25.0.4.r25-nik` 就是 `25.0.4-nik`)。一个版本同时为两个 JDK 发布时,写了较旧 JDK(由 `older_jdk` 给出)的标识符什么都不选中(`22.1.r11-mandrel`)。SDKMAN 给版本补的零由 `installed_version.unpad` 去掉(`27.0.0+36` 就是 `27+36`)。Oracle GraalVM 和 GraalVM 社区版的标识符(`sdkman_graalvm`)里,`+` 后面的数字是 GraalVM 版本号的第五位,不是构建号,所以 `ParseLegacyFile` 先找用点号写的已安装版本名(`25.0.5.0+3-graal` 就是 `25.0.5.0.3-graal`),再找其他的。简称与 SDKMAN 不同的地方见 [distributions.md](distributions.md#简称与-sdkman-的不同)。 ## Foojay @@ -67,7 +67,7 @@ SDKMAN 有些写法不同(`jbr`、`21.0.12.fx-zulu`、`21.0.12-fx+1.1-librca` - 包的记录(`links.pkg_info_uri`)里有 `checksum_type`,以及 `checksum` 或 `checksum_uri`。`lib/checksum.lua` 里的 `checksum.lookup` 优先取记录自带的摘要,这也不用再发请求,只有记录里没有摘要时才去取那个文件。取文件的函数由 `PreInstall` 传给它,GitHub 上的地址会经过 `$VFOX_JAVA_GITHUB_MIRROR`,所以这个库不需要 `http`,测试也不用为它模拟 `http`。只列了别的包的文件不给出摘要,因为别的文件的摘要会让本来没问题的安装失败:Microsoft 为 macOS 上 11.0.14 的 EA 构建发布的文件,里面写的是 GA 构建。 - Foojay 里同一个名字有两条记录时,`Available` 只列一次。 - GraalVM 社区版每月发布的特性版本(`25.1.3` 起),Foojay 按老办法列的那些标成了 LTS,以前 Oracle GraalVM 的也是这样。`lib/distribution_version.lua` 里的 `is_feature_release` 按次版本号识别它们,`Available` 去掉它们的备注。它只适用于 `graal` 和 `graalce`:Mandrel 和 Liberica NIK 在 24 及以前沿用 GraalVM 的旧版本号,次版本号并不表示特性版本(`mandrel` 的 `23.1.12` 就是 LTS),从 25 起和 JDK 的版本号一致。 -- 只有 Oracle GraalVM(`graal`)在只写大版本号时,`PreInstall` 才会跳过特性版本,所以装的是 25.0 系列。一个大版本里只有特性版本时,则保留它们。GraalVM 社区版不做这个过滤,因为特性版本就是它现在发布的全部。这条规则放在 `lib/distribution_version.lua` 的 `bare_major_skips` 里。`PreUse` 和 `ParseLegacyFile` 也用它过滤已安装的版本,这样 `vfox use` 和 `.sdkmanrc` 选中的就是 `PreInstall` 装的那个构建:这个大版本里已安装的、不是特性版本的最新版本,没有的话才取最新的特性版本。没装的版本在 `ParseLegacyFile` 里退到同一大版本的最新版本时,也适用这条规则,除非文件里写的本来就是特性版本(SDKMAN 写作 `25.4.4+1-graal`),这时仍然像以前一样取这个大版本里已安装的最新版本。 +- 只有 Oracle GraalVM(`graal`)在只写大版本号时,`PreInstall` 才会跳过特性版本,所以装的是 25.0 系列。一个大版本里只有特性版本时,则保留它们。GraalVM 社区版不做这个过滤,因为特性版本就是它现在发布的全部。这条规则放在 `lib/distribution_version.lua` 的 `bare_major_skips` 里。`PreUse` 和 `ParseLegacyFile` 也用它过滤已安装的版本,这样 `vfox use` 和 `.sdkmanrc` 选中的就是 `PreInstall` 装的那个构建:这个大版本里已安装的、不是特性版本的最新版本,没有的话才取最新的特性版本。没装的版本在 `ParseLegacyFile` 里退到同一大版本的最新版本时,也适用这条规则,除非文件里写的本来就是特性版本(SDKMAN 写作 `25.4.4.1+1-graal`,或者 `25.4.4+1-graal`),这时仍然像以前一样取这个大版本里已安装的最新版本。 - CPU 名字:`arm64` 改成 `aarch64`,Windows 上 `amd64` 改成 `x64`;`darwin` 改成 `macos`。在 Linux 上,由 `ldd --version` 决定是 glibc 还是 musl。 ## 测试 diff --git a/docs/zh-CN/e2e.md b/docs/zh-CN/e2e.md index f37386b..0260989 100644 --- a/docs/zh-CN/e2e.md +++ b/docs/zh-CN/e2e.md @@ -185,7 +185,7 @@ docker run --rm -v "$PWD:/src" ghcr.io/google/addlicense:v1.2.0 -f .license.tpl 在 `tem` 这几行里,经过一个不存在的镜像安装也必须失败。设成 `VFOX_JAVA_GITHUB_MIRROR=https://invalid.example.invalid` 后,镜像会加在 Temurin 的 GitHub 地址前面,所以 `vfox install` 在下载时失败,错误信息里必须出现 vfox 请求的那个地址:镜像、一个斜杠,再加 GitHub 地址。以前插件不读这个变量,会从 github.com 下载 JDK,安装成功。这一步不下载任何东西,也不运行能正常工作的镜像。 3. 在 `graalce` 这一行里,Oracle GraalVM 只写大版本号的 `25-graal` 应该装 25.0 系列的最新构建(2026-11-03 是 `25.0.5.0.3-graal`),也就是 Oracle 官方 `25/latest` 下载跟的那个系列,而不是列在它前面的某个每月特性版本(比如 `25.4.4.1.1-graal`)。`vfox search java graal` 必须按 GraalVM 自己的版本号列出这些特性版本,25 的其他版本备注要一致,同第 5 条。从 2026 年 10 月起,Foojay 给特性版本标的是 JDK 的版本号,和 25.0 系列共用。插件以前按这个版本号命名,结果搜索里一个特性版本都没有,`25.0.4.1-graal` 也没有 LTS 备注,装上的却是 25.4.4.1.1。搜索列出的 25 的各构建会先被模拟成已安装,这样 `vfox install` 报出的就是 `PreInstall` 选中的那个,而且不会下载任何东西。GA 版本 25 不放进去,因为那样 vfox 会发现 `25-graal` 已安装,根本不会去问 `PreInstall`。在 Linux 上,安装向 Foojay 发的请求还必须和搜索的相同,同第 4 条末尾。 - 装着这些构建时,`vfox use java@25-graal` 和写着 `java=25-graal` 的 `.sdkmanrc` 必须选中 `vfox install` 报出的那个构建。`PreUse` 和 `ParseLegacyFile` 以前选的是 25 里已安装的最新版本,所以一旦装了特性版本,选中的就是它([#110](https://github.com/version-fox/vfox-java/issues/110))。模拟出的每个构建里都放着一个只打印名字的替身 `java`,同第 6 条。把 25.0 系列的构建删掉之后,`vfox use` 和 `.sdkmanrc` 都必须选中最新的特性版本。 + 装着这些构建时,`vfox use java@25-graal` 和写着 `java=25-graal` 的 `.sdkmanrc` 必须选中 `vfox install` 报出的那个构建。`PreUse` 和 `ParseLegacyFile` 以前选的是 25 里已安装的最新版本,所以一旦装了特性版本,选中的就是它([#110](https://github.com/version-fox/vfox-java/issues/110))。模拟出的每个构建里都放着一个只打印名字的替身 `java`,同第 6 条。对模拟出的每个有五位版本号的构建,写着 SDKMAN 给它的标识符的 `.sdkmanrc`(`25.0.5.0.3-graal` 对应 `25.0.5.0+3-graal`,`25.4.4.1.1-graal` 对应 `25.4.4.1+1-graal`;见 `tests/e2e/common` 里的 `GraalVMIdentifiers`)必须选中这个构建,而不是它旁边的 `25.0.5-graal` 或更新的版本。`ParseLegacyFile` 以前把 `+` 后面的数字当作这个版本的构建号([#124](https://github.com/version-fox/vfox-java/pull/124))。把 25.0 系列的构建删掉之后,`vfox use` 和 `.sdkmanrc` 都必须选中最新的特性版本。 4. 在 `tem` 这几行里(这几行在每个 runner 上都会运行),只按名字检查的发行版(`adpt` 到 `semcrt`,即 `tests/e2e/common` 里的 `nameOnly`),只要 Foojay 在这个 runner 上有它的包,都要能用简称找到:`vfox search java <简称>` 能列出它;把它列出的最新版本模拟成已安装后,`vfox install java@<大版本>-<简称>`(`22-grl17`)要报告这个版本已经安装,所以不会下载任何东西。以前没有这些简称时,这两条命令分别报 `Unsupported distribution` 和 `Could not extract a valid distribution`。 同样在这几行里,Mandrel 和 Liberica NIK 要按它们沿用的 GraalVM 版本号来(`tests/e2e/common` 里的 `ownNumbers`;Windows arm64 上两者都没有):`vfox search java mandrel` 要列出 `23.1.12-mandrel`(Liberica NIK 是 `23.1.8-nik`);把它和搜索结果里最新的 23.x 模拟成已安装后,`vfox install java@mandrel-23.1.12` 和 `vfox install java@23-mandrel` 要报告这两个版本已经安装。2026 年 10 月 Foojay 把这个版本号挪到了 `distribution_version`,插件改读它之前,搜索结果每个 Java 大版本只列一个名字,找不到 `23.1.12-mandrel`,`java@23-mandrel` 装上的是为 Java 23 构建的 Mandrel 24.1.2。 diff --git a/docs/zh-CN/sdkmanrc.md b/docs/zh-CN/sdkmanrc.md index 28bb8b5..e2b5613 100644 --- a/docs/zh-CN/sdkmanrc.md +++ b/docs/zh-CN/sdkmanrc.md @@ -34,13 +34,13 @@ vfox 挂载到 Shell 之后,进入目录时会读取这个文件,并选中 插件把标识符与已安装的 JDK 按下面的顺序匹配: -1. 原样写出的已安装版本名:`java=21.0.8+9-tem`、`java=28-ea+19`。 +1. 原样写出的已安装版本名:`java=21.0.8+9-tem`、`java=28-ea+19`。对 Oracle GraalVM 和 GraalVM 社区版,`+` 后面的数字是版本号的第五位,所以 `java=25.0.5.0+3-graal` 指的是 `25.0.5.0.3-graal`,见 [SDKMAN 的写法](#sdkman-的写法)。 2. 你写的那个版本,取它已安装的最新构建:`21.0.8-tem` 选中 `21.0.8+9-tem`。 3. 不行的话,取同一大版本里已安装的最新版本。`21-tem` 直接走这一步。 第 3 步不检查已装的版本是否低于你写的版本。只装了 `21.0.8+9-tem` 时,`java=21.0.12-tem` 会选中它,`java=21.0.3-tem` 也一样。写了没装的构建号,会退到这个版本已安装的最新构建(`21.0.8+7-tem` 选中 `21.0.8+9-tem`)。如果这个大版本根本没装,就什么也不选。 -对 Oracle GraalVM,第 3 步会跳过每月发布的特性版本(`25.4.4.1.1-graal`),和 `vfox use java@25-graal` 一样,所以 `java=25-graal` 和 `java=25.0.3-graal` 选中的是 25.0 系列里已安装的最新构建。如果 25 里没有装别的版本,就选特性版本。如果文件里写的是特性版本(SDKMAN 写作 `25.4.4+1-graal`),选的是 25 里已安装的最新版本。 +对 Oracle GraalVM,第 3 步会跳过每月发布的特性版本(`25.4.4.1.1-graal`),和 `vfox use java@25-graal` 一样,所以 `java=25-graal` 和 `java=25.0.3-graal` 选中的是 25.0 系列里已安装的最新构建。如果 25 里没有装别的版本,就选特性版本。如果文件里写的是没装的特性版本(SDKMAN 写过 `25.4.4.1+1-graal` 和 `25.4.4+1-graal` 两种写法),选的是 25 里已安装的最新版本。 它不会跨发行版,不会在带 JavaFX 和不带 JavaFX 的构建之间串用,也不会在 EA 构建和 GA 版本之间串用。 @@ -56,6 +56,7 @@ vfox 挂载到 Shell 之后,进入目录时会读取这个文件,并选中 | `21.0.12-fx+1.1-librca` | 带 JavaFX 的 Liberica(较新的写法) | | `21.0.8+1.1-tem` | Temurin 21.0.8,见下文 | | `27.0.0+36-librca`、`25.0.1.0+8-open` | `27+36-librca`、`25.0.1+8`:补的零会被去掉 | +| `25.0.5.0+3-graal`、`25.4.4.1+1-graalce` | `25.0.5.0.3-graal`、`25.4.4.1.1-graalce`:`+` 后面的数字是 GraalVM 版本号的第五位 | | `28.ea.19-open`、`28.0.0+ea.19-open` | EA 构建 `28-ea+19` | | `25.0.4.r25-nik`、`25.0.2.r25-mandrel` | `25.0.4-nik`、`25.0.2-mandrel`:`.r` 和后面的 JDK 版本会被去掉 | | `11.0.10.hs-adpt`、`11.0.10.j9-adpt` | AdoptOpenJDK 的 HotSpot 版 `11.0.10-adpt` 和 OpenJ9 版 `11.0.10-adptj9` | @@ -66,7 +67,9 @@ vfox 挂载到 Shell 之后,进入目录时会读取这个文件,并选中 SDKMAN 在一些 Mandrel 和 Liberica NIK 的版本号里也写了 JDK 版本,而插件只按 GraalVM 版本号给它们命名,见 [distributions.md](distributions.md#mandrel-与-liberica-nik-的行为)。一个版本同时为两个 JDK 发布时,插件只装较新 JDK 的构建,所以写了较旧 JDK 的标识符什么都不会选中:`22.1.r11-mandrel`、`23.0.1.r17-nik`。较旧的 JDK,在 21.3 到 22.3.5 是 JDK 11,在 23 到 23.0.1.2 是 JDK 17。`25.r25-mandrel` 只写了大版本号,会选中已安装的最新 Mandrel 25,和 `java=25-mandrel` 一样,而 SDKMAN 按这个标识符装的是 25.0.1.0。 -SDKMAN 新写法里 `+` 后面的数字(`21.0.8+1.1-tem`)是 SDKMAN 自己重新构建的次数,不是厂商的构建号,所以插件不会去找这个构建,而是按版本匹配。Foojay 和安装后的版本名都不补零,所以 `27.0.0` 指的就是 `27`。`sdk list java` 里补一个 `.0` 很常见(`25.0.1.0+8-open`、`21.0.9.0+116386-jbr`),插件同样能读。 +SDKMAN 新写法里 `+` 后面的数字是构建号,可能是厂商的(`25.0.5.0+8-tem` 是 Temurin 的第 8 个构建,安装后叫 `25.0.5+8-tem`),也可能是 SDKMAN 自己重新构建的次数(`21.0.8+1.1-tem`)。插件先找已安装的、带这个构建号的版本,找不到再按版本匹配。Foojay 和安装后的版本名都不补零,所以 `27.0.0` 指的就是 `27`。`sdk list java` 里补一个 `.0` 很常见(`25.0.1.0+8-open`、`21.0.9.0+116386-jbr`),插件同样能读。 + +Oracle GraalVM 和 GraalVM 社区版是例外。它们的版本号有五位(`25.0.5.0.3`),而 SDKMAN 的标识符在 `+` 前只有四位,所以 SDKMAN 把第五位写在 `+` 后面:`25.0.5.0+3-graal` 是 GraalVM 25.0.5.0.3,`25.4.4.1+1-graalce` 是特性版本 25.4.4.1.1。这个数字是版本号的一部分,Oracle 把 `25.0.5`、`25.0.5.0.2` 和 `25.0.5.0.3` 发布成了三个不同的文件。插件先找用点号写的已安装版本名,找不到再像对待任何没装的版本一样走第 2、3 步。`vfox install` 只认用点号写的版本名(`java@25.0.5.0.3-graal`),不认这个标识符。未发布:0.6.4 把这个数字当作 `25.0.5` 的构建号,所以 `25.0.5.0.3-graal` 旁边装着 `25.0.5-graal` 时选中后者;没装 `25.0.5-graal`、却装了更新的 25 时,选中那个更新的。 ## 没有生效怎么办 diff --git a/hooks/parse_legacy_file.lua b/hooks/parse_legacy_file.lua index 415981d..9083547 100644 --- a/hooks/parse_legacy_file.lua +++ b/hooks/parse_legacy_file.lua @@ -36,6 +36,17 @@ local sdkman_jdks = { nik = true, } +--- Oracle GraalVM and GraalVM Community, which the plugin names after +--- GraalVM's own version. It has five numbers where SDKMAN's identifiers have +--- four before the +, so SDKMAN writes the fifth after it: 25.0.5.0+3-graal is +--- the plugin's 25.0.5.0.3-graal, and 25.4.4.1+1-graalce its 25.4.4.1.1-graalce. +--- Oracle's file is graalvm-jdk-25.0.5.0.3, so that number belongs to the +--- release and is no build of the vendor's. +local sdkman_graalvm = { + graal = true, + graalce = true, +} + --- Returns the JDK whose build of a Mandrel or Liberica NIK release the --- plugin does not install, if any. Their releases from 21.3 to 23.0.1.2 come --- for two JDKs, and the plugin installs the build for the newer one, so the @@ -167,14 +178,25 @@ function PLUGIN:ParseLegacyFile(ctx) --- a bare major skips releases (Oracle GraalVM's feature releases), so does --- this step: java=25-graal and java=25.0.3-graal select 25.0.5-graal, --- unless nothing else of the major is installed or the file names a - --- feature release itself (java=25.4.4+1-graal). + --- feature release itself (java=25.4.4.1+1-graal). local skip = distribution_version_parser.bare_major_skips(distributionVersion.distribution) if skip and skip(fullVersion) then skip = nil end local name = version .. build .. suffix + + --- GraalVM's own spelling of the version, as the file names it: the number + --- after the + is the fifth of the release (25.0.5.0+3 is 25.0.5.0.3), a + --- different download than 25.0.5 and 25.0.5.0.2, so it is looked for + --- before the release without it and the newest of the major. + local graalvm_name + local graalvm_release, graalvm_number = fullVersion:match("^(%d[%d.]*)%+(%d+)$") + if sdkman_graalvm[vendor] and graalvm_release then + graalvm_name = installed_version.unpad(graalvm_release .. "." .. graalvm_number) .. suffix + end return { - version = installed[name] and name + version = graalvm_name and installed[graalvm_name] and graalvm_name + or installed[name] and name or not fullVersion:match("^%d+$") and installed_version.release(installed, version, suffix) or installed_version.major(installed, majorVersion, suffix, skip), } diff --git a/tests/e2e/common/common.go b/tests/e2e/common/common.go index eea99da..5d83374 100644 --- a/tests/e2e/common/common.go +++ b/tests/e2e/common/common.go @@ -764,6 +764,29 @@ func FeatureReleases(builds []string) []string { return features } +// graalVMFiveNumbers matches a build named after GraalVM's version with five +// numbers (25.0.5.0.3-graal): the first four, the fifth, and the short name. +var graalVMFiveNumbers = regexp.MustCompile(`^(\d+(?:\.\d+){3})\.(\d+)(-graal(?:ce)?)$`) + +// GraalVMIdentifiers renders SDKMAN's identifier of each of the builds that +// BareMajorBuilds returned with five numbers (25.0.5.0.3-graal, +// 25.4.4.1.1-graal), each with the build a .sdkmanrc holding it must select. +// SDKMAN has four numbers before the + and writes the fifth after it +// (25.0.5.0+3-graal, 25.4.4.1+1-graal): its download of the first is Oracle's +// graalvm-jdk-25.0.5.0.3, a different file than 25.0.5 and 25.0.5.0.2. +// ParseLegacyFile took the number for a build of the release, found no such +// install, and selected the plain 25.0.5 or the newest release of the major +// instead. +func GraalVMIdentifiers(builds []string) []LegacyCase { + var cases []LegacyCase + for _, build := range builds { + if m := graalVMFiveNumbers.FindStringSubmatch(build); m != nil { + cases = append(cases, LegacyCase{Identifier: m[1] + "+" + m[2] + m[3], Selects: build}) + } + } + return cases +} + // nameOnly maps the distributions the suite checks by name only, by short // name, to the runner platforms Foojay lists packages of them for // (2026-10-20). Only Red Hat's Linux x64 builds still download, which the diff --git a/tests/e2e/common/common_test.go b/tests/e2e/common/common_test.go index ea0c9b4..53dc926 100644 --- a/tests/e2e/common/common_test.go +++ b/tests/e2e/common/common_test.go @@ -636,6 +636,33 @@ func TestBareMajorBuilds(t *testing.T) { } } +func TestGraalVMIdentifiers(t *testing.T) { + // The builds `vfox search java graal` lists for 25 on 2026-11-03, + // less the GA 25. + builds := []string{ + "25.4.4.1.1-graal", "25.3.4.1-graal", "25.2.4-graal", "25.1.3-graal", + "25.0.5.0.3-graal", "25.0.5.0.2-graal", "25.0.5-graal", "25.0.4.1.1-graal", "25.0.4.1-graal", + } + // SDKMAN writes the fifth number after the +; the builds with four or + // fewer numbers have nothing to move. + want := []LegacyCase{ + {"25.4.4.1+1-graal", "25.4.4.1.1-graal"}, + {"25.0.5.0+3-graal", "25.0.5.0.3-graal"}, + {"25.0.5.0+2-graal", "25.0.5.0.2-graal"}, + {"25.0.4.1+1-graal", "25.0.4.1.1-graal"}, + } + if got := GraalVMIdentifiers(builds); !slices.Equal(got, want) { + t.Errorf("GraalVMIdentifiers = %q, want %q", got, want) + } + if got := GraalVMIdentifiers([]string{"25.4.4.1.1-graalce"}); !slices.Equal(got, []LegacyCase{{"25.4.4.1+1-graalce", "25.4.4.1.1-graalce"}}) { + t.Errorf("GraalVMIdentifiers(graalce) = %q", got) + } + // Another distribution's version, an early-access build and a build number are no fifth number. + if got := GraalVMIdentifiers([]string{"21.0.12.1+1-tem", "26-ea+13-graal", "25.0.5.0.3-mandrel", "25.0.5.0.3"}); len(got) != 0 { + t.Errorf("GraalVMIdentifiers(others) = %q, want none", got) + } +} + func TestNameOnlyDistributions(t *testing.T) { for platform, want := range map[string][]string{ "linux/amd64": {"adpt", "adptj9", "eliya", "gln", "grl11", "grl16", "grl17", "grl19", "grl8", "ojdkbld", "opnlgc", "rdht", "semcrt"}, diff --git a/tests/e2e/linux/setup.go b/tests/e2e/linux/setup.go index 86630ba..7006380 100644 --- a/tests/e2e/linux/setup.go +++ b/tests/e2e/linux/setup.go @@ -43,8 +43,11 @@ func setupVfox(ctx context.Context, t *testing.T, ctr tc.Container, vfoxVersion "git clone --depth 1 https://github.com/version-fox/vfox %q/src && (cd %q/src && CGO_ENABLED=0 go build -trimpath -o /usr/local/bin/vfox .)", work, work)) } else { - execOK(ctx, t, ctr, - "curl --fail --silent --show-error --location https://raw.githubusercontent.com/version-fox/vfox/main/install.sh | bash") + // A pipeline exits with the status of its last command, so without + // pipefail a download that fails leaves bash an empty script and + // the install passes without vfox, which the next step then misses. + execRetry(ctx, t, ctr, "install vfox", + "set -o pipefail; curl --fail --silent --show-error --location https://raw.githubusercontent.com/version-fox/vfox/main/install.sh | bash") } execOK(ctx, t, ctr, fmt.Sprintf( "(cd /e2e && zip -qr %q/java.zip metadata.lua hooks lib) && vfox add java --source %q/java.zip", @@ -159,6 +162,7 @@ func checkGraalVMBareMajor(ctx context.Context, t *testing.T, ctr tc.Container) require.Containsf(t, common.StripANSI(out), "java@"+want+" is already installed", "vfox install java@%s must take %s, the newest build that is no feature release", spec, want) checkBareMajorSelected(ctx, t, ctr, spec, want, builds) + checkGraalVMIdentifiers(ctx, t, ctr, builds) // Without the 25.0 line, the feature releases are all there is to select. line := slices.DeleteFunc(slices.Clone(builds), func(build string) bool { return slices.Contains(features, build) }) removeInstalls(ctx, t, ctr, line) @@ -168,6 +172,22 @@ func checkGraalVMBareMajor(ctx context.Context, t *testing.T, ctr tc.Container) strings.Join(builds, ", "), features[0], strings.Join(features, ", ")) } +// checkGraalVMIdentifiers proves a .sdkmanrc holding SDKMAN's identifier of a +// build with five numbers (25.0.5.0+3-graal) selects that build among the +// installed ones, which must be faked (see fakeInstalls), and not the plain +// 25.0.5 next to it or a newer release (see common.GraalVMIdentifiers). +func checkGraalVMIdentifiers(ctx context.Context, t *testing.T, ctr tc.Container, builds []string) { + t.Helper() + cases := common.GraalVMIdentifiers(builds) + if len(cases) == 0 { + t.Logf("SKIP no build with five numbers among %s", strings.Join(builds, ", ")) + return + } + for _, c := range cases { + common.CheckSelects(t, legacyRun(ctx, t, ctr, c.Identifier, printJava), c, builds) + } +} + // checkBareMajorSelected proves `vfox use java@` and a .sdkmanrc // holding spec both select want among the installed builds, which must be // faked (see fakeInstalls), and nothing is downloaded. diff --git a/tests/e2e/windows/setup.go b/tests/e2e/windows/setup.go index 2e40a33..63e7c42 100644 --- a/tests/e2e/windows/setup.go +++ b/tests/e2e/windows/setup.go @@ -375,6 +375,7 @@ func checkGraalVMBareMajor(ctx context.Context, t *testing.T, ctr tc.Container, require.Containsf(t, common.StripANSI(out), "java@"+want+" is already installed", "vfox install java@%s must take %s, the newest build that is no feature release", spec, want) checkBareMajorSelected(ctx, t, ctr, box, activation, spec, want, builds) + checkGraalVMIdentifiers(ctx, t, ctr, box, builds) // Without the 25.0 line, the feature releases are all there is to select. line := slices.DeleteFunc(slices.Clone(builds), func(build string) bool { return slices.Contains(features, build) }) removeInstalls(ctx, t, ctr, box, line) @@ -384,6 +385,22 @@ func checkGraalVMBareMajor(ctx context.Context, t *testing.T, ctr tc.Container, strings.Join(builds, ", "), features[0], strings.Join(features, ", ")) } +// checkGraalVMIdentifiers proves a .sdkmanrc holding SDKMAN's identifier of a +// build with five numbers (25.0.5.0+3-graal) selects that build among the +// installed ones, which must be faked (see fakeInstalls), and not the plain +// 25.0.5 next to it or a newer release (see common.GraalVMIdentifiers). +func checkGraalVMIdentifiers(ctx context.Context, t *testing.T, ctr tc.Container, box slotBox, builds []string) { + t.Helper() + cases := common.GraalVMIdentifiers(builds) + if len(cases) == 0 { + t.Logf("SKIP no build with five numbers among %s", strings.Join(builds, ", ")) + return + } + for _, c := range cases { + common.CheckSelects(t, legacyRun(ctx, t, ctr, box, c.Identifier, printJava), c, builds) + } +} + // checkBareMajorSelected proves `vfox use java@` and a .sdkmanrc // holding spec both select want among the installed builds, which must be // faked (see fakeInstalls), and nothing is downloaded. diff --git a/tests/parse_legacy_file_test.lua b/tests/parse_legacy_file_test.lua index fe7ca29..14c7b3a 100644 --- a/tests/parse_legacy_file_test.lua +++ b/tests/parse_legacy_file_test.lua @@ -188,11 +188,34 @@ local cases = { -- Nothing else of the major installed. { "java=25-graal\n", { "25.4.4.1.1-graal", "25.3.4.1-graal" }, "25.4.4.1.1-graal" }, { "java=25.0.3-graal\n", { "25.4.4.1.1-graal" }, "25.4.4.1.1-graal" }, - -- A file that names a feature release (SDKMAN's identifier is 25.4.4+1-graal) - -- takes the newest release of the major, as it did. + -- A file that names a feature release by a name no install has (SDKMAN + -- spelled Oracle's 25.4.4+1-graal before 25.4.4.1+1-graal) takes the + -- newest release of the major, as it did. { "java=25.4.4+1-graal\n", { "25.4.4.1.1-graal", "25.0.4.1-graal" }, "25.4.4.1.1-graal" }, { "java=25.5.5-graal\n", { "25.4.4.1.1-graal", "25.0.4.1-graal" }, "25.4.4.1.1-graal" }, + { "java=25.5.5.1+1-graal\n", { "25.4.4.1.1-graal", "25.0.4.1-graal" }, "25.4.4.1.1-graal" }, { "java=25.4.4.1.1-graal\n", { "25.4.4.1.1-graal", "25.0.4.1-graal" }, "25.4.4.1.1-graal" }, + -- SDKMAN writes the fifth number of GraalVM's own version after the +: + -- 25.0.5.0+3-graal is GraalVM 25.0.5.0.3, whose file is + -- graalvm-jdk-25.0.5.0.3 and no build of 25.0.5, and 25.4.4.1+1-graal is + -- the feature release 25.4.4.1.1. The release a file names is selected + -- while it is installed, not 25.0.5 next to it, the .2 build or a newer one. + { "java=25.0.5.0+3-graal\n", { "25.0.5.0.3-graal", "25.0.5-graal" }, "25.0.5.0.3-graal" }, + { "java=25.0.5.0+3-graal\n", { "25.0.5.0.3-graal", "25.0.5.0.2-graal", "25.0.5-graal" }, "25.0.5.0.3-graal" }, + { "java=25.0.5.0+2-graal\n", { "25.0.5.0.3-graal", "25.0.5.0.2-graal", "25.0.5-graal" }, "25.0.5.0.2-graal" }, + { "java=25.0.5.0+3-graal\n", { "25.0.5.0.3-graal", "25.0.6-graal" }, "25.0.5.0.3-graal" }, + { "java=25.4.4.1+1-graal\n", { "25.4.4.1.1-graal", "25.5.5.1.1-graal", "25.0.5.0.3-graal" }, "25.4.4.1.1-graal" }, + { "java=25.4.4.1+1-graalce\n", { "25.4.4.1.1-graalce", "25.5.5.1.1-graalce" }, "25.4.4.1.1-graalce" }, + -- Not installed, it takes what any release not installed takes: the + -- release without the fifth number, else the newest of the line, or the + -- feature releases where they are all there is. + { "java=25.0.5.0+3-graal\n", { "25.0.5-graal", "25.0.6-graal" }, "25.0.5-graal" }, + { "java=25.0.5.0+3-graal\n", { "25.0.5.0.2-graal", "25.4.4.1.1-graal" }, "25.0.5.0.2-graal" }, + { "java=25.0.5.0+3-graal\n", { "25.4.4.1.1-graal" }, "25.4.4.1.1-graal" }, + -- Never another distribution. For the others the number after the + is + -- the vendor's build, which is looked for in the installed name as before. + { "java=25.0.5.0+3-graal\n", { "25.0.5.0.3-graalce" }, nil }, + { "java=25.0.5.0+8-tem\n", { "25.0.5+8-tem", "25.0.6+7-tem" }, "25.0.5+8-tem" }, -- Other majors and distributions: GraalVM Community's feature releases are -- what it still ships, and a minor above 0 means nothing for Mandrel. { "java=21-graal\n", { "21.0.8-graal", "25.4.4.1.1-graal" }, "21.0.8-graal" },