Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions docs/e2e.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<version>.fx-<distribution>`, 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
Expand Down
53 changes: 36 additions & 17 deletions hooks/parse_legacy_file.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand All @@ -50,6 +70,19 @@ function PLUGIN:ParseLegacyFile(ctx)

local majorVersion = strings.split(version, ".")[1]

--- Installed versions end in -<vendor> (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
Expand All @@ -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

Expand Down
15 changes: 12 additions & 3 deletions tests/e2e/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -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: "<version>-<distribution>", without the build number.
// LegacyIdentifier renders the SDKMAN identifier a .sdkmanrc holds for a
// release: "<version>-<distribution>", without the build number, in SDKMAN's
// spelling: JetBrains is "jbr" and JavaFX builds are
// "<version>.fx-<distribution>" (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 "<long-name>-<version>[-fx]" of an
Expand Down
3 changes: 2 additions & 1 deletion tests/e2e/common/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
13 changes: 4 additions & 9 deletions tests/e2e/linux/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 <version>.fx-<distribution>, 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 <version>.fx-<distribution>")
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",
Expand Down
14 changes: 4 additions & 10 deletions tests/e2e/windows/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
// <version>.fx-<distribution>, 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 <version>.fx-<distribution>")
return
}
const dir = `C:\e2e-legacy-sdkmanrc`
identifier := common.LegacyIdentifier(distribution, version)
execOK(ctx, t, ctr, fmt.Sprintf(
Expand Down
19 changes: 16 additions & 3 deletions tests/parse_legacy_file_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
Expand All @@ -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
Expand Down
3 changes: 0 additions & 3 deletions tests/support.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading