Skip to content
Open
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
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ plugins {
def allureVersion = '2.29.1'
def aspectJVersion = '1.9.25'
def assertjVersion = '3.24.2'
def devkitmanVersion = '0.3.3'
def devkitmanVersion = '0.4.2'
def junitBomVersion = '5.14.1'
def testcontainersVersion = '2.0.2'
def jlineVersion = '3.30.5'
Expand Down
9 changes: 6 additions & 3 deletions src/it/java/dev/jbang/it/BaseIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,15 @@ public String toStringOf(Object object) {
String javaMajorVersion = System.getenv("_JBANG_TEST_JAVA_VERSION");

if (testJavaHome == null) {
JdkManager jdkMan = JavaUtil.defaultJdkManager(List.of());
// We want to make sure the "multihome" is added for when we run in GH CI
JdkManager jdkMan = JavaUtil.defaultJdkManagerBuilder().provider("multihome").build();
// if env not avail it is null and will use default jdk
// to use same jdk as what tetss run with to make it more
// to use same jdk as what tets run with to make it more
// deterministic.

InstalledJdk jdk = jdkMan.getOrInstallJdk(testJavaMajorVersion + "");
System.err.println("Requested Java version: " + javaMajorVersion);
InstalledJdk jdk = jdkMan.getOrInstallJdk(testJavaMajorVersion > 0 ? testJavaMajorVersion + "" : null);
System.err.println("Using JDK: " + jdk);
testJavaHome = jdk.home().toString();
} else {
if (!Files.exists(Paths.get(testJavaHome))) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/dev/jbang/Cache.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static void clearCache(CacheClass... classes) {
// We're running using a managed JDK on Windows so we can't just delete the
// entire folder!
for (Jdk.InstalledJdk jdk : jdkMan.listInstalledJdks()) {
jdkMan.uninstallJdk(jdk);
jdk.uninstall();
}
}
if (cc == CacheClass.deps) {
Expand Down
6 changes: 0 additions & 6 deletions src/main/java/dev/jbang/cli/BuildMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import picocli.CommandLine;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Option;
import picocli.CommandLine.ParameterException;
import picocli.CommandLine.Spec;

public class BuildMixin {
Expand All @@ -26,11 +25,6 @@ public class BuildMixin {
@CommandLine.Option(names = { "-j",
"--java" }, description = "JDK version to use for running the script.")
void setJavaVersion(String javaVersion) {
if (!javaVersion.matches("\\d+[+]?")) {
throw new ParameterException(spec.commandLine(),
String.format("Invalid version '%s', should be a number optionally followed by a plus sign",
javaVersion));
}
this.javaVersion = javaVersion;
}

Expand Down
151 changes: 120 additions & 31 deletions src/main/java/dev/jbang/cli/Jdk.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ public Integer install(
@CommandLine.Parameters(paramLabel = "existingJdkPath", index = "1", description = "Pre installed JDK path", arity = "0..1") String path)
throws IOException {
JdkManager jdkMan = jdkProvidersMixin.getJdkManager();
dev.jbang.devkitman.Jdk jdk = jdkMan.getInstalledJdk(versionOrId, JdkProvider.Predicates.canUpdate);
dev.jbang.devkitman.Jdk jdk = jdkMan.getInstalledJdk(versionOrId, JdkProvider.Predicates.canInstall);
if (force || jdk == null) {
if (!Util.isNullOrBlankString(path)) {
jdkMan.linkToExistingJdk(Paths.get(path), versionOrId);
} else {
if (jdk == null) {
jdk = jdkMan.getJdk(versionOrId, JdkProvider.Predicates.canUpdate);
jdk = jdkMan.getJdk(versionOrId, JdkProvider.Predicates.canInstall);
if (jdk == null) {
throw new IllegalArgumentException("JDK is not available for installation: " + versionOrId);
}
Expand All @@ -67,30 +67,42 @@ public Integer install(
@CommandLine.Command(name = "list", aliases = "l", description = "Lists installed JDKs.")
public Integer list(
@CommandLine.Option(names = {
"--available" }, description = "Shows versions available for installation") boolean available,
"--available", "-a" }, description = "Shows versions available for installation") boolean available,
@CommandLine.Option(names = {
"--show-details" }, description = "Shows detailed information for each JDK (only when format=text)") boolean details,
"--show-details", "--details",
"-d" }, description = "Shows detailed information for each JDK (only when format=text)") boolean details,
@CommandLine.Option(names = {
"--format" }, description = "Specify output format ('text' or 'json')") FormatMixin.Format format) {
JdkManager jdkMan = jdkProvidersMixin.getJdkManager();
dev.jbang.devkitman.Jdk defaultJdk = jdkMan.getDefaultJdk();
int defMajorVersion = defaultJdk != null ? defaultJdk.majorVersion() : 0;
String defVersion = defaultJdk != null ? defaultJdk.version() : "";
PrintStream out = System.out;
List<? extends dev.jbang.devkitman.Jdk> jdks;
List<JdkOut> jdkOuts;
if (available) {
jdks = jdkMan.listAvailableJdks();
List<dev.jbang.devkitman.Jdk.AvailableJdk> jdks = jdkMan.listAvailableJdks();
jdkOuts = jdks.stream()
.map(jdk -> new JdkOut(jdk.id(), jdk.version(), jdk.provider().name(),
null, null,
details ? jdk.equals(defaultJdk)
: jdk.version().equals(defVersion),
jdk.tags()))
.collect(Collectors.toList());
} else {
jdks = jdkMan.listInstalledJdks();
List<dev.jbang.devkitman.Jdk.InstalledJdk> jdks = jdkMan.listInstalledJdks();
jdkOuts = jdks.stream()
.map(jdk -> new JdkOut(jdk.id(), jdk.version(), jdk.provider().name(),
jdk.home(),
jdk instanceof dev.jbang.devkitman.Jdk.LinkedJdk
? ((dev.jbang.devkitman.Jdk.LinkedJdk) jdk).linked().id()
: null,
details ? jdk.equals(defaultJdk)
: jdk.version().equals(defVersion),
jdk.tags()))
.collect(Collectors.toList());
}
List<JdkOut> jdkOuts = jdks.stream()
.map(jdk -> new JdkOut(jdk.id(), jdk.version(), jdk.provider().name(),
jdk.isInstalled() ? ((dev.jbang.devkitman.Jdk.InstalledJdk) jdk).home() : null,
details ? jdk.equals(defaultJdk)
: jdk.majorVersion() == defMajorVersion))
.collect(Collectors.toList());
if (!details) {
// Only keep a list of unique major versions
Set<JdkOut> uniqueJdks = new TreeSet<>(Comparator.comparingInt(j -> j.version));
// Only keep a list of unique versions
Set<JdkOut> uniqueJdks = new TreeSet<>(Comparator.<JdkOut>comparingInt(j -> j.version).reversed());
uniqueJdks.addAll(jdkOuts);
jdkOuts = new ArrayList<>(uniqueJdks);
}
Expand All @@ -106,12 +118,17 @@ public Integer list(
out.print(" ");
out.print(jdk.version);
out.print(" (");
out.print(jdk.fullVersion);
if (details) {
out.print(jdk.fullVersion);
out.print(", " + jdk.providerName + ", " + jdk.id);
if (jdk.javaHomeDir != null) {
out.print(", " + jdk.javaHomeDir);
}
if (!jdk.tags.isEmpty()) {
out.print(", " + jdk.tags);
}
} else {
out.print(available ? jdk.id : jdk.fullVersion);
}
out.print(")");
if (!available) {
Expand All @@ -134,20 +151,43 @@ static class JdkOut implements Comparable<JdkOut> {
String fullVersion;
String providerName;
String javaHomeDir;
String realHomeDir;
String linkedId;
@SerializedName("default")
Boolean isDefault;
Set<String> tags;

public JdkOut(String id, String version, String providerName, Path home, boolean isDefault) {
public JdkOut(String id, String version, String providerName, Path home, String linkedId, boolean isDefault,
Set<String> tags) {
this.id = id;
this.version = JavaUtil.parseJavaVersion(version);
this.fullVersion = version;
this.providerName = providerName;
if (home != null) {
this.javaHomeDir = home.toString();
this.realHomeDir = home.toString();
try {
this.realHomeDir = home.toRealPath().toString();
} catch (IOException e) {
// Ignore
}
}
this.linkedId = linkedId;
if (isDefault) {
this.isDefault = true;
}
this.tags = tags != null ? trimTags(tags) : Collections.emptySet();
}

private Set<String> trimTags(Set<String> tags) {
Set<String> trimmedTags = new HashSet<>();
for (String tag : tags) {
if (!tag.equalsIgnoreCase("ga")
&& !tag.equalsIgnoreCase("jdk")) {
trimmedTags.add(tag.toLowerCase());
}
}
return trimmedTags;
}

@Override
Expand All @@ -162,15 +202,20 @@ public int compareTo(JdkOut o) {

@CommandLine.Command(name = "uninstall", aliases = "u", description = "Uninstalls an existing JDK.")
public Integer uninstall(
@CommandLine.Parameters(paramLabel = "version", index = "0", description = "The version to install", arity = "1") String versionOrId) {
@CommandLine.Parameters(paramLabel = "versionOrId", index = "0", description = "The version to install", arity = "1") String versionOrId) {
JdkManager jdkMan = jdkProvidersMixin.getJdkManager();
// This will first select for JDKs from providers that can actually install JDKs
dev.jbang.devkitman.Jdk.InstalledJdk jdk = jdkMan.getInstalledJdk(versionOrId,
JdkProvider.Predicates.canUpdate);
JdkProvider.Predicates.canInstall);
if (jdk == null) {
throw new ExitException(EXIT_INVALID_INPUT, "JDK " + versionOrId + " is not installed");
// If necessary we select JDKs from providers that can update JDKs
jdk = jdkMan.getInstalledJdk(versionOrId, JdkProvider.Predicates.canUpdate);
if (jdk == null) {
throw new ExitException(EXIT_INVALID_INPUT, "JDK " + versionOrId + " is not installed");
}
}
jdkMan.uninstallJdk(jdk);
Util.infoMsg("Uninstalled JDK:\n " + versionOrId);
jdk.uninstall();
Util.infoMsg("Uninstalled JDK:\n " + jdk.id());
return EXIT_OK;
}

Expand All @@ -193,7 +238,7 @@ public Integer javaEnv(
JdkManager jdkMan = jdkProvidersMixin.getJdkManager();
dev.jbang.devkitman.Jdk jdk = null;
if (versionOrId != null && JavaUtil.isRequestedVersion(versionOrId)) {
jdk = jdkMan.getJdk(versionOrId, JdkProvider.Predicates.canUpdate);
jdk = jdkMan.getJdk(versionOrId, JdkProvider.Predicates.canInstall);
}
if (jdk == null || !jdk.isInstalled()) {
jdk = jdkMan.getOrInstallJdk(versionOrId);
Expand Down Expand Up @@ -273,28 +318,72 @@ public Integer exec(

@CommandLine.Command(name = "default", description = "Sets the default JDK to be used by JBang.")
public Integer defaultJdk(
@CommandLine.Parameters(paramLabel = "version", index = "0", description = "The version of the JDK to select", arity = "0..1") String versionOrId) {
@CommandLine.Parameters(paramLabel = "versionOrId", index = "0", description = "The version of the JDK to select", arity = "0..1") String versionOrId,
@CommandLine.Option(names = {
"--for-version",
"-v" }, description = "Sets the default for the specified major version") boolean forVersion,
@CommandLine.Option(names = {
"--show-details", "--details",
"-d" }, description = "Shows detailed information for each JDK (only when format=text)") boolean details,
@CommandLine.Option(names = {
"--format" }, description = "Specify output format ('text' or 'json')") FormatMixin.Format format) {
JdkManager jdkMan = jdkProvidersMixin.getJdkManager();
if (!jdkMan.hasDefaultProvider()) {
Util.warnMsg("Cannot perform operation, the 'default' provider was not found");
return EXIT_INVALID_INPUT;
}
dev.jbang.devkitman.Jdk.InstalledJdk defjdk = jdkMan.getDefaultJdk();
if (versionOrId != null) {
dev.jbang.devkitman.Jdk.InstalledJdk jdk = jdkMan.getOrInstallJdk(versionOrId);
dev.jbang.devkitman.Jdk.InstalledJdk defjdk = forVersion
? jdkMan.getDefaultJdkForVersion(jdk.majorVersion())
: jdkMan.getDefaultJdk();
if (defjdk == null || (!jdk.equals(defjdk) && !Objects.equals(jdk.home(), defjdk.home()))) {
jdkMan.setDefaultJdk(jdk);
if (forVersion) {
jdkMan.setDefaultJdkForVersion(jdk);
} else {
jdkMan.setDefaultJdk(jdk);
}
} else {
Util.infoMsg("Default JDK already set to " + defjdk.majorVersion());
}
} else {
if (defjdk == null) {
Util.infoMsg("No default JDK set, use 'jbang jdk default <version>' to set one.");
List<dev.jbang.devkitman.Jdk.LinkedJdk> jdks = jdkMan.listDefaultJdks();
List<JdkOut> jdkOuts = jdks.stream()
.map(jdk -> new JdkOut(jdk.id(), jdk.version(), jdk.provider().name(), jdk.home(),
jdk.linked().id(), jdk.id().equals("default"), jdk.tags()))
.collect(Collectors.toList());
PrintStream out = System.out;
if (format == FormatMixin.Format.json) {
Gson parser = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create();
parser.toJson(jdkOuts, out);
} else {
Util.infoMsg("Default JDK is currently set to " + defjdk.majorVersion());
if (!jdkOuts.isEmpty()) {
out.println("Default JDKs:");
jdkOuts.forEach(jdk -> {
out.print(" ");
if (Boolean.TRUE.equals(jdk.isDefault)) {
out.print("*");
} else {
out.print(jdk.version);
}
out.print(" -> ");
out.print(jdk.linkedId);
if (details) {
out.print(" (" + jdk.realHomeDir + ", " + jdk.fullVersion + ", " + jdk.id);
if (!jdk.tags.isEmpty()) {
out.print(", " + jdk.tags);
}
out.print(")");
} else {
out.print(" (" + jdk.fullVersion + ")");
}
out.println();
});
} else {
out.println("No default JDK set, use 'jbang jdk default <version>' to set one.");
}
}
}
return EXIT_OK;
}

}
14 changes: 12 additions & 2 deletions src/main/java/dev/jbang/cli/JdkProvidersMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@
public class JdkProvidersMixin {

@CommandLine.Option(names = {
"--jdk-providers" }, description = "Use the given providers to check for installed JDKs", split = ",", hidden = true)
"--jdk-providers" }, description = "Use the given providers to manage JDKs", split = ",", hidden = true)
List<String> jdkProviders;

@CommandLine.Option(names = {
"--jdk-vendors" }, description = "Use the given vendors/distributions to install new JDKs", split = ",", hidden = true)
List<String> jdkVendors;

private JdkManager jdkMan;

protected JdkManager getJdkManager() {
if (jdkMan == null) {
jdkMan = JavaUtil.defaultJdkManager(jdkProviders);
jdkMan = JavaUtil.defaultJdkManager(jdkProviders, jdkVendors);
}
return jdkMan;
}
Expand All @@ -31,6 +35,12 @@ public List<String> opts() {
opts.add(p);
}
}
if (jdkVendors != null) {
for (String v : jdkVendors) {
opts.add("--jdk-vendors");
opts.add(v);
}
}
return opts;
}
}
Loading
Loading