Skip to content

Commit 8dcdd20

Browse files
authored
fix: ask for a version when only a distribution, such as java@tem, is given (#99)
1 parent 8021721 commit 8dcdd20

15 files changed

Lines changed: 156 additions & 5 deletions

‎docs/e2e.md‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,12 @@ JDK, so `java` can only come from what vfox installs:
6363
registered from this checkout. On Windows, the runner builds `main` once,
6464
while the `latest` combinations run, and the `main` containers start from
6565
the e2e image plus that `vfox.exe`.
66-
2. A release no distribution has published (`<major>.0.99`) fails to install,
66+
2. A distribution without a version, alone or after an empty one
67+
(`java@tem`, `java@-tem`), fails both `vfox install` and `vfox use` with
68+
an error asking for one. The hooks stopped with a Lua error on the first,
69+
while `PreInstall` sent the empty version to Foojay, which lists every
70+
release, and installed the newest one.
71+
A release no distribution has published (`<major>.0.99`) fails to install,
6772
with `PreInstall` naming the platform it searched (`linux/amd64`,
6873
`windows/arm64`, ...), so the Foojay lookup is checked to target the
6974
runner. So does a build of the pinned release that was never published

‎hooks/parse_legacy_file.lua‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ function PLUGIN:ParseLegacyFile(ctx)
8383
if not distributionVersion then
8484
return {}
8585
end
86+
--- A distribution alone (java=tem) selects nothing, as vfox use rejects it.
8687
local fullVersion = distributionVersion.version
88+
if not fullVersion then
89+
return {}
90+
end
8791
local vendor = distributionVersion.distribution.short_name
8892
if not vendor then
8993
return {}

‎hooks/pre_install.lua‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ function PLUGIN:PreInstall(ctx)
3030
if not distribution_version then
3131
error("Could not extract a valid distribution: " .. ctx.version)
3232
end
33+
if not distribution_version.version then
34+
error(distribution_version_parser.missing_version_error(ctx.version, distribution_version))
35+
end
3336
if loongnix.supported() or loongnix.is_distribution(distribution_version.distribution.name) then
3437
return loongnix.pre_install(distribution_version)
3538
end

‎hooks/pre_use.lua‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ function PLUGIN:PreUse(ctx)
2929
end
3030

3131
if distribution_version then
32+
if not distribution_version.version then
33+
error(distribution_version_parser.missing_version_error(input_version, distribution_version))
34+
end
3235
-- OpenJDK versions are installed without a distribution suffix, so
3336
-- 25.0.2+10-open and openjdk-25.0.2+10 both name 25.0.2+10.
3437
local suffix = distribution_version.javafx_bundled and "-fx" or ""

‎lib/distribution_version.lua‎

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,15 @@ function distribution_version.parse_version(arg)
130130
end
131131
end
132132

133-
-- Convert version format for Foojay API
134-
version = distribution_version.convert_version_for_api(version)
133+
-- A distribution alone (tem, zulu-fx), or after an empty version (-tem,
134+
-- temurin-), names no version: leave it nil for the hooks to reject.
135+
if version == "" then
136+
version = nil
137+
end
138+
if version then
139+
-- Convert version format for Foojay API
140+
version = distribution_version.convert_version_for_api(version)
141+
end
135142

136143
return {
137144
version = version,
@@ -140,4 +147,21 @@ function distribution_version.parse_version(arg)
140147
}
141148
end
142149

150+
--- Returns the error for a user-input version that parse_version read
151+
--- without a version, such as tem: it names no JDK to install or use.
152+
--- @param arg string User-input version
153+
--- @param parsed table What parse_version returned for arg
154+
--- @return string Error message
155+
function distribution_version.missing_version_error(arg, parsed)
156+
local short_name = parsed.distribution.short_name
157+
return "No version in "
158+
.. arg
159+
.. "; add one, such as 21-"
160+
.. short_name
161+
.. (parsed.javafx_bundled and "-fx" or "")
162+
.. ". Please check available versions with 'vfox search java "
163+
.. short_name
164+
.. "'"
165+
end
166+
143167
return distribution_version

‎tests/e2e/common/common.go‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,16 @@ func MissingBuildSpec(distribution, version string) string {
260260
return Spec(distribution, version+"+99")
261261
}
262262

263+
// VersionlessSpecs renders the distribution without a version, alone and
264+
// after an empty one ("tem" and "-tem", "librca-fx" and "-librca-fx", "open"
265+
// and "-open" for OpenJDK). PreInstall and PreUse must reject both, asking
266+
// for a version: they failed with a Lua error on the first (vfox-java#98),
267+
// while PreInstall sent the empty version to Foojay, which lists every
268+
// release, and installed the newest one.
269+
func VersionlessSpecs(distribution string) []string {
270+
return []string{distribution, "-" + distribution}
271+
}
272+
263273
// Decoy renders the installed name of another release whose version starts
264274
// with the pinned one (<version>0+1, e.g. 21.0.80+1-tem). vfox lists the
265275
// installed versions sorted as strings, descending, so it comes before the

‎tests/e2e/common/common_test.go‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,21 @@ func TestSpecs(t *testing.T) {
209209
}
210210
}
211211

212+
func TestVersionlessSpecs(t *testing.T) {
213+
for _, c := range []struct {
214+
dist string
215+
want []string
216+
}{
217+
{"open", []string{"open", "-open"}},
218+
{"tem", []string{"tem", "-tem"}},
219+
{"librca-fx", []string{"librca-fx", "-librca-fx"}},
220+
} {
221+
if got := VersionlessSpecs(c.dist); !slices.Equal(got, c.want) {
222+
t.Errorf("VersionlessSpecs(%s) = %q, want %q", c.dist, got, c.want)
223+
}
224+
}
225+
}
226+
212227
func TestPaddedIdentifier(t *testing.T) {
213228
for _, c := range []struct{ dist, version, installed, want string }{
214229
{"open", "25.0.2", "25.0.2+10", "25.0.2.0+10-open"},

‎tests/e2e/linux/e2e_test.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ func runOne(t *testing.T, ctx context.Context, image, platform, arch string, c c
166166
t.Logf("=== vfox %s, java@%s, %s (%s) ===", c.Vfox, common.Spec(c.Distribution, version), platform, machine)
167167

168168
setupVfox(ctx, t, ctr, c.Vfox)
169+
checkVersionlessRejected(ctx, t, ctr, c.Distribution)
169170
checkMissingVersionRejected(ctx, t, ctr, c.Distribution, version, arch)
170171

171172
installed := installJava(ctx, t, ctr, common.Spec(c.Distribution, version))

‎tests/e2e/linux/setup.go‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,26 @@ func setupVfox(ctx context.Context, t *testing.T, ctr tc.Container, vfoxVersion
5151
t.Logf("PASS %s with the local java plugin", strings.TrimSpace(execOK(ctx, t, ctr, "vfox --version")))
5252
}
5353

54+
// checkVersionlessRejected proves a distribution without a version (e.g.
55+
// java@tem, java@-tem, see common.VersionlessSpecs) fails both `vfox
56+
// install` and `vfox use` with an error asking for one. The hooks raise it
57+
// before any Foojay lookup, so nothing is retried.
58+
func checkVersionlessRejected(ctx context.Context, t *testing.T, ctr tc.Container, distribution string) {
59+
t.Helper()
60+
for _, spec := range common.VersionlessSpecs(distribution) {
61+
want := "No version in " + spec + ";"
62+
for _, c := range []struct{ label, script string }{
63+
{"vfox install java@" + spec, "vfox install java@" + spec},
64+
{"vfox use --global java@" + spec, activated("vfox use --global java@" + spec)},
65+
} {
66+
code, out := execRun(ctx, t, ctr, c.script)
67+
require.NotZerof(t, code, "%s must fail\n--- output ---\n%s", c.label, out)
68+
require.Containsf(t, common.StripANSI(out), want, "%s must ask for a version", c.label)
69+
}
70+
t.Logf("PASS java@%s is rejected by vfox install and vfox use", spec)
71+
}
72+
}
73+
5474
// checkMissingVersionRejected proves an unpublished release, and an
5575
// unpublished build of the pinned one, fail loudly instead of installing
5676
// something else: PreInstall finds no Foojay package and names the platform

‎tests/e2e/windows/e2e_test.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,10 @@ func runOne(t *testing.T, ctx context.Context, image, platform, arch string, c c
242242

243243
box := setupSlotEnv(ctx, t, ctr, c.Slug())
244244
setupVfox(ctx, t, ctr, box, c.Vfox)
245+
activation := fetchActivation(ctx, t, ctr, box)
246+
checkVersionlessRejected(ctx, t, ctr, box, activation, c.Distribution)
245247
checkMissingVersionRejected(ctx, t, ctr, box, c.Distribution, version, arch)
246248

247-
activation := fetchActivation(ctx, t, ctr, box)
248249
installed := installJava(ctx, t, ctr, box, common.Spec(c.Distribution, version))
249250
verifySearch(ctx, t, ctr, box, c.Distribution, installed)
250251
// Before any `vfox use`, so java can only come from the legacy file.

0 commit comments

Comments
 (0)