diff --git a/docs/e2e.md b/docs/e2e.md index e9988cd..568fae9 100644 --- a/docs/e2e.md +++ b/docs/e2e.md @@ -73,11 +73,11 @@ JDK, so `java` can only come from what vfox installs: a SKIP when absent): `Available` lists zip packages and reaches tar.gz ones only when a distribution has no zip at all, so JetBrains Runtime 21.0.5 installs but is not listed. -4. Before any `vfox use`, a `.sdkmanrc` holding the SDKMAN-style identifier - (`java=21.0.8-tem`) selects the JDK through `ParseLegacyFile`. On Windows - the file is written with CRLF line endings. JavaFX builds skip this probe: - SDKMAN spells them `.fx-`, which the legacy parser - does not resolve. +4. Before any `vfox use`, a `.sdkmanrc` holding the SDKMAN identifier + without the build number selects the JDK through `ParseLegacyFile`: + `java=21.0.8-tem`, `java=21.0.5-jbr` (SDKMAN's name for JetBrains) or + `java=25.0.4.fx-librca` (its spelling of JavaFX builds). On Windows the + file is written with CRLF line endings. 5. After `vfox use --global`, the JDK on `PATH` reports the requested `java.version`, the runner's `os.arch` (`amd64` / `aarch64`, which also catches an x64 JDK emulated on Windows ARM64) and the distribution's diff --git a/hooks/parse_legacy_file.lua b/hooks/parse_legacy_file.lua index 9783ff9..a12856d 100644 --- a/hooks/parse_legacy_file.lua +++ b/hooks/parse_legacy_file.lua @@ -16,6 +16,26 @@ local strings = require("vfox.strings") local distribution_version_parser = require("distribution_version") +--- Rewrites an SDKMAN identifier in the plugin's spelling, which parse_version +--- reads. SDKMAN calls JetBrains jbr (the plugin's jb) and puts fx in the +--- version of JavaFX builds: 21.0.12.fx-zulu, or 21.0.12-fx+1.1-librca in its +--- semverish identifiers (the plugin's 21.0.12-zulu-fx, 21.0.12+1.1-librca-fx). +--- Any other spelling, the plugin's own included, is returned unchanged. +local function plugin_spelling(identifier) + local version, distribution = identifier:match("^(.+)%-([^-]+)$") + if not version then + return identifier + end + if distribution == "jbr" then + distribution = "jb" + end + local release, build = version:match("^(%d[%d.]*)[.-]fx(.*)$") + if release then + return release .. build .. "-" .. distribution .. "-fx" + end + return version .. "-" .. distribution +end + function PLUGIN:ParseLegacyFile(ctx) local filepath = ctx.filepath @@ -25,7 +45,7 @@ function PLUGIN:ParseLegacyFile(ctx) for line in io.lines(filepath) do if strings.has_prefix(line, "java=") then - javaVersion = strings.trim_prefix(line, "java=") + javaVersion = plugin_spelling(strings.trim_prefix(line, "java=")) break end end @@ -50,6 +70,19 @@ function PLUGIN:ParseLegacyFile(ctx) local majorVersion = strings.split(version, ".")[1] + --- Installed versions end in - (OpenJDK's in nothing), then -fx for + --- JavaFX builds: 21.0.8+9-tem, 21.0.12+7-zulu-fx, 25.0.2+10. + local suffix = (vendor == "open" and "" or "-" .. vendor) .. (distributionVersion.javafx_bundled and "-fx" or "") + + --- Whether installed version v is of this distribution and JavaFX flavour, + --- with a Java version starting with prefix. + local function matches(v, prefix) + local java_version = v:sub(1, #v - #suffix) + return java_version .. suffix == v + and (vendor ~= "open" or not strings.contains(java_version, "-")) + and strings.has_prefix(java_version, prefix) + end + --- Get the list of versions of the current plugin installed --- (a plain call: vfox 1.x rejects the extra ctx argument of ctx:...). local targetVersion @@ -61,32 +94,18 @@ function PLUGIN:ParseLegacyFile(ctx) break end - if vendor == "open" and not strings.contains(v, "-") and strings.has_prefix(v, version) then + if matches(v, version) then targetVersion = v break end - - if strings.has_suffix(v, "-" .. vendor) then - if strings.has_prefix(v, version) then - targetVersion = v - break - end - end end if not targetVersion then for _, v in ipairs(versions) do - if vendor == "open" and not strings.contains(v, "-") and strings.has_prefix(v, majorVersion .. ".") then + if matches(v, majorVersion .. ".") then targetVersion = v break end - - if strings.has_suffix(v, "-" .. vendor) then - if strings.has_prefix(v, majorVersion .. ".") then - targetVersion = v - break - end - end end end diff --git a/tests/e2e/common/common.go b/tests/e2e/common/common.go index fa9870e..d939e03 100644 --- a/tests/e2e/common/common.go +++ b/tests/e2e/common/common.go @@ -254,10 +254,19 @@ func Major(version string) string { return strings.SplitN(version, ".", 2)[0] } -// LegacyIdentifier renders the SDKMAN-style identifier a .sdkmanrc holds for -// a release: "-", without the build number. +// LegacyIdentifier renders the SDKMAN identifier a .sdkmanrc holds for a +// release: "-", without the build number, in SDKMAN's +// spelling: JetBrains is "jbr" and JavaFX builds are +// ".fx-" (21.0.5-jbr, 25.0.4.fx-librca). func LegacyIdentifier(distribution, version string) string { - return version + "-" + Base(distribution) + name := Base(distribution) + if name == "jb" { + name = "jbr" + } + if JavaFX(distribution) { + version += ".fx" + } + return version + "-" + name } // Alias renders the asdf-style spelling "-[-fx]" of an diff --git a/tests/e2e/common/common_test.go b/tests/e2e/common/common_test.go index 725f2fe..b7a7296 100644 --- a/tests/e2e/common/common_test.go +++ b/tests/e2e/common/common_test.go @@ -187,7 +187,8 @@ func TestSpecs(t *testing.T) { for _, c := range []struct{ dist, version, spec, missing, legacy string }{ {"open", "25.0.2", "25.0.2", "25.0.99", "25.0.2-open"}, {"tem", "21.0.8", "21.0.8-tem", "21.0.99-tem", "21.0.8-tem"}, - {"librca-fx", "25.0.4", "25.0.4-librca-fx", "25.0.99-librca-fx", "25.0.4-librca"}, + {"librca-fx", "25.0.4", "25.0.4-librca-fx", "25.0.99-librca-fx", "25.0.4.fx-librca"}, + {"jb", "21.0.5", "21.0.5-jb", "21.0.99-jb", "21.0.5-jbr"}, } { if got := Spec(c.dist, c.version); got != c.spec { t.Errorf("Spec(%s, %s) = %q, want %q", c.dist, c.version, got, c.spec) diff --git a/tests/e2e/linux/verify.go b/tests/e2e/linux/verify.go index dcb35fa..1b4e2b4 100644 --- a/tests/e2e/linux/verify.go +++ b/tests/e2e/linux/verify.go @@ -51,17 +51,12 @@ func verifySearch(ctx context.Context, t *testing.T, ctr tc.Container, distribut } // verifyLegacyFile proves ParseLegacyFile selects the installed JDK from a -// .sdkmanrc (PLUGIN.legacyFilenames) holding the SDKMAN-style identifier -// without the build number (e.g. java=21.0.8-tem). It runs before any -// `vfox use`, so java can only come from the legacy file. JavaFX builds are -// skipped: SDKMAN spells them .fx-, which -// hooks/parse_legacy_file.lua does not resolve. +// .sdkmanrc (PLUGIN.legacyFilenames) holding the SDKMAN identifier without +// the build number (e.g. java=21.0.8-tem, java=21.0.5-jbr, +// java=25.0.4.fx-librca). It runs before any `vfox use`, so java can only +// come from the legacy file. func verifyLegacyFile(ctx context.Context, t *testing.T, ctr tc.Container, distribution, version, arch string) { t.Helper() - if common.JavaFX(distribution) { - t.Logf("SKIP .sdkmanrc probe: SDKMAN spells JavaFX builds .fx-") - return - } const dir = "/tmp/e2e-legacy-sdkmanrc" identifier := common.LegacyIdentifier(distribution, version) execOK(ctx, t, ctr, fmt.Sprintf("mkdir --parents %s && printf 'java=%%s\\n' %s > %s/.sdkmanrc", diff --git a/tests/e2e/windows/verify.go b/tests/e2e/windows/verify.go index ad5b843..1ea6490 100644 --- a/tests/e2e/windows/verify.go +++ b/tests/e2e/windows/verify.go @@ -62,18 +62,12 @@ func verifySearch(ctx context.Context, t *testing.T, ctr tc.Container, box slotB } // verifyLegacyFile proves ParseLegacyFile selects the installed JDK from a -// .sdkmanrc (PLUGIN.legacyFilenames) holding the SDKMAN-style identifier -// without the build number (e.g. java=21.0.8-tem), written by Set-Content -// with Windows line endings. It runs before any `vfox use`, so java can only -// come from the legacy file. JavaFX builds are skipped: SDKMAN spells them -// .fx-, which hooks/parse_legacy_file.lua does not -// resolve. +// .sdkmanrc (PLUGIN.legacyFilenames) holding the SDKMAN identifier without +// the build number (e.g. java=21.0.8-tem, java=21.0.5-jbr, +// java=25.0.4.fx-librca), written by Set-Content with Windows line endings. +// It runs before any `vfox use`, so java can only come from the legacy file. func verifyLegacyFile(ctx context.Context, t *testing.T, ctr tc.Container, box slotBox, distribution, version, arch string) { t.Helper() - if common.JavaFX(distribution) { - t.Logf("SKIP .sdkmanrc probe: SDKMAN spells JavaFX builds .fx-") - return - } const dir = `C:\e2e-legacy-sdkmanrc` identifier := common.LegacyIdentifier(distribution, version) execOK(ctx, t, ctr, fmt.Sprintf( diff --git a/tests/parse_legacy_file_test.lua b/tests/parse_legacy_file_test.lua index 1a8ebfe..60e5029 100644 --- a/tests/parse_legacy_file_test.lua +++ b/tests/parse_legacy_file_test.lua @@ -38,6 +38,9 @@ local function parse(content, installed) return result.version end +-- The JDKs installed in vfox-java#71. +local jb_and_zulu_fx = { "21.0.5+79248-jb", "21.0.12+7-zulu-fx" } + local cases = { -- SDKMAN identifiers carry no build number. { "java=21.0.8-tem\n", { "21.0.8+9-zulu", "21.0.8+9-tem" }, "21.0.8+9-tem" }, @@ -47,9 +50,19 @@ local cases = { { "java=21.0.1-tem\n", { "21.0.8+9-tem" }, "21.0.8+9-tem" }, -- Windows line endings, as Set-Content writes them. { "java=21.0.8-tem\r\nmaven=3.9.9\r\n", { "21.0.8+9-tem" }, "21.0.8+9-tem" }, - -- Identifiers the plugin does not know (SDKMAN's JetBrains is jbr) or no - -- java line at all select nothing. - { "java=21.0.5-jbr\n", { "21.0.5+79248-jb" }, nil }, + -- SDKMAN's JetBrains is jbr and its JavaFX builds are 21.0.12.fx-zulu or, + -- semverish, 21.0.12-fx+1.1-librca; the plugin's own spellings work too. + { "java=21.0.5-jb\n", jb_and_zulu_fx, "21.0.5+79248-jb" }, + { "java=21.0.5-jbr\n", jb_and_zulu_fx, "21.0.5+79248-jb" }, + { "java=21.0.12.fx-zulu\n", jb_and_zulu_fx, "21.0.12+7-zulu-fx" }, + { "java=21.0.12-zulu-fx\n", jb_and_zulu_fx, "21.0.12+7-zulu-fx" }, + { "java=21.0.12-fx+1.1-librca\n", { "21.0.12+10-librca", "21.0.12+10-librca-fx" }, "21.0.12+10-librca-fx" }, + -- Never a JavaFX build for one without JavaFX, nor the other way round. + { "java=21.0.12-zulu\n", { "21.0.12+7-zulu-fx", "21.0.12+7-zulu" }, "21.0.12+7-zulu" }, + { "java=21.0.12-zulu\n", jb_and_zulu_fx, nil }, + { "java=21.0.12.fx-zulu\n", { "21.0.12+7-zulu" }, nil }, + { "java=21.0.8.fx-zulu\n", { "21.0.12+7-zulu", "21.0.12+7-zulu-fx" }, "21.0.12+7-zulu-fx" }, + -- No java line at all selects nothing. { "maven=3.9.9\n", { "21.0.8+9-tem" }, nil }, } for _, case in ipairs(cases) do diff --git a/tests/support.lua b/tests/support.lua index 830dc12..fedee23 100644 --- a/tests/support.lua +++ b/tests/support.lua @@ -32,9 +32,6 @@ package.preload["vfox.strings"] = function() end end, has_prefix = has_prefix, - has_suffix = function(value, suffix) - return suffix == "" or value:sub(-#suffix) == suffix - end, trim_prefix = function(value, prefix) return has_prefix(value, prefix) and value:sub(#prefix + 1) or value end,