From 9a49a02e3f458e7c9f87d38224b62b688bbc9b24 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Mon, 18 Nov 2024 23:44:54 +0100 Subject: [PATCH] --jvm tries to find Java executable system-wide. (#11500) Fixes `--jvm` option, given to the native image. This was failing on my machine, because when given `--jvm` option, the runner was trying to find the `java` executable from the distribution manager's runtime (on my system located in `~/.local/share/enso/runtime`) and it used the first runtime found. But the first runtime on my system is JDK 17. The `--jvm` option now tries to: - Find a JDK from the distribution manager that has the same version as the JDK used for building the engine. - If there is not an exact version match, it tries to find a runtime from distribution manager that is *newer*. - If none, fallback to system-wide search - System-wide search tries to find `java` from `$JAVA_HOME` and from `$PATH`. But this is just a fallback. # Important Notes - Added test to Engine CI jobs that pass `--jvm` argument to a native image of engine-runner - ea3af5ffbca6dc439690142251426b4c167bca98 - `runtime-version-manager` sbt project migrated to a JPMS module - `engine-runner` now depends on `runtime-version-manager`. - Removed unnecessary stuff in `runtime-version-manager` dealing with outdated `gu` Graal Updater utility. - Extracted [GraalVersionManager](https://github.com/enso-org/enso/blob/1455b025cb8e5141409ea96b75577e8884265a70/lib/scala/runtime-version-manager/src/main/java/org/enso/runtimeversionmanager/components/GraalVersionManager.java) from [RuntimeVersionManager](https://github.com/enso-org/enso/blob/d2e8994700fd36228f7873f040668013e643190a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeVersionManager.scala) --- build.sbt | 29 ++- build/build/src/engine/context.rs | 21 +- distribution/launcher/THIRD-PARTY/NOTICE | 15 -- .../NOTICES | 11 - .../NOTICES | 1 - .../NOTICES | 7 - .../distribution/DefaultManagers.scala | 7 +- engine/runner/src/main/java/module-info.java | 1 + .../main/java/org/enso/runner/JavaFinder.java | 110 ++++++++++ .../src/main/java/org/enso/runner/Main.java | 19 +- .../DefaultDistributionConfiguration.scala | 16 +- .../TestDistributionConfiguration.scala | 13 +- .../test/NoopComponentUpdater.scala | 20 -- .../test/NoopComponentUpdaterFactory.scala | 15 -- .../test/RuntimeVersionManagerTest.scala | 7 +- .../locking/ConcurrencyTest.scala | 7 +- .../src/main/java/module-info.java | 22 ++ .../components/GraalVersionManager.java | 140 ++++++++++++ .../runtimeversionmanager/package-info.java | 1 - .../runtimeversionmanager/cli/Arguments.scala | 9 - .../components/GraalVMComponent.scala | 11 - .../GraalVMComponentConfiguration.scala | 89 -------- .../components/GraalVMComponentUpdater.scala | 180 ---------------- .../components/GraalVMVersion.scala | 41 +++- .../RuntimeComponentConfiguration.scala | 19 -- .../components/RuntimeComponentUpdater.scala | 19 -- .../RuntimeComponentUpdaterFactory.scala | 30 --- .../components/RuntimeVersionManager.scala | 201 ++---------------- .../UnchainedGraalVMComponentUpdater.scala | 26 --- .../GraalVMComponentConfigurationSpec.scala | 106 --------- .../GraalVMComponentParserSpec.scala | 57 ----- .../components/GraalVMVersionSpec.scala | 40 ++++ .../java/org/enso/semver/VersionsTest.java | 2 + .../java/org/enso/version/BuildVersion.java | 13 ++ project/BuildInfo.scala | 6 + .../copyright-ignore | 8 - .../copyright-keep | 6 - .../copyright-ignore | 6 - .../copyright-keep | 1 - .../copyright-ignore | 2 - .../copyright-keep | 4 - tools/legal-review/launcher/report-state | 4 +- 42 files changed, 453 insertions(+), 889 deletions(-) delete mode 100644 distribution/launcher/THIRD-PARTY/com.typesafe.akka.akka-http-core_2.13-10.2.10/NOTICES delete mode 100644 distribution/launcher/THIRD-PARTY/com.typesafe.akka.akka-http_2.13-10.2.10/NOTICES delete mode 100644 distribution/launcher/THIRD-PARTY/com.typesafe.akka.akka-parsing_2.13-10.2.10/NOTICES create mode 100644 engine/runner/src/main/java/org/enso/runner/JavaFinder.java delete mode 100644 lib/scala/runtime-version-manager-test/src/main/scala/org/enso/runtimeversionmanager/test/NoopComponentUpdater.scala delete mode 100644 lib/scala/runtime-version-manager-test/src/main/scala/org/enso/runtimeversionmanager/test/NoopComponentUpdaterFactory.scala create mode 100644 lib/scala/runtime-version-manager/src/main/java/module-info.java create mode 100644 lib/scala/runtime-version-manager/src/main/java/org/enso/runtimeversionmanager/components/GraalVersionManager.java delete mode 100644 lib/scala/runtime-version-manager/src/main/java/org/enso/runtimeversionmanager/package-info.java delete mode 100644 lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMComponent.scala delete mode 100644 lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMComponentConfiguration.scala delete mode 100644 lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMComponentUpdater.scala delete mode 100644 lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeComponentConfiguration.scala delete mode 100644 lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeComponentUpdater.scala delete mode 100644 lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeComponentUpdaterFactory.scala delete mode 100644 lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/UnchainedGraalVMComponentUpdater.scala delete mode 100644 lib/scala/runtime-version-manager/src/test/scala/org/enso/runtimeversionmanager/components/GraalVMComponentConfigurationSpec.scala delete mode 100644 lib/scala/runtime-version-manager/src/test/scala/org/enso/runtimeversionmanager/components/GraalVMComponentParserSpec.scala create mode 100644 lib/scala/runtime-version-manager/src/test/scala/org/enso/runtimeversionmanager/components/GraalVMVersionSpec.scala delete mode 100644 tools/legal-review/launcher/com.typesafe.akka.akka-http-core_2.13-10.2.10/copyright-ignore delete mode 100644 tools/legal-review/launcher/com.typesafe.akka.akka-http-core_2.13-10.2.10/copyright-keep delete mode 100644 tools/legal-review/launcher/com.typesafe.akka.akka-http_2.13-10.2.10/copyright-ignore delete mode 100644 tools/legal-review/launcher/com.typesafe.akka.akka-http_2.13-10.2.10/copyright-keep delete mode 100644 tools/legal-review/launcher/com.typesafe.akka.akka-parsing_2.13-10.2.10/copyright-ignore delete mode 100644 tools/legal-review/launcher/com.typesafe.akka.akka-parsing_2.13-10.2.10/copyright-keep diff --git a/build.sbt b/build.sbt index 3a3b909918f..17d5a6e7b4f 100644 --- a/build.sbt +++ b/build.sbt @@ -721,6 +721,7 @@ lazy val componentModulesPaths = (`runtime-instrument-runtime-server` / Compile / exportedModuleBin).value, (`runtime-language-arrow` / Compile / exportedModuleBin).value, (`runtime-language-epb` / Compile / exportedModuleBin).value, + (`runtime-version-manager` / Compile / exportedModuleBin).value, (`persistance` / Compile / exportedModuleBin).value, (`cli` / Compile / exportedModuleBin).value, (`json-rpc-server` / Compile / exportedModuleBin).value, @@ -1613,7 +1614,8 @@ lazy val `version-output` = (project in file("lib/scala/version-output")) defaultDevEnsoVersion = defaultDevEnsoVersion, ensoVersion = ensoVersion, scalacVersion = scalacVersion, - graalVersion = graalVersion, + graalVersion = graalMavenPackagesVersion, + javaVersion = graalVersion, currentEdition = currentEdition ) }.taskValue @@ -3525,6 +3527,7 @@ lazy val `engine-runner` = project (`pkg` / Compile / exportedModule).value, (`engine-runner-common` / Compile / exportedModule).value, (`runtime-parser` / Compile / exportedModule).value, + (`runtime-version-manager` / Compile / exportedModule).value, (`version-output` / Compile / exportedModule).value, (`engine-common` / Compile / exportedModule).value, (`polyglot-api` / Compile / exportedModule).value, @@ -3700,6 +3703,7 @@ lazy val `engine-runner` = project .dependsOn(`distribution-manager`) .dependsOn(`edition-updater`) .dependsOn(`runtime-parser`) + .dependsOn(`runtime-version-manager`) .dependsOn(`logging-service`) .dependsOn(`logging-service-logback` % Runtime) .dependsOn(`engine-runner-common`) @@ -4337,15 +4341,34 @@ lazy val `connected-lock-manager-server` = project lazy val `runtime-version-manager` = project .in(file("lib/scala/runtime-version-manager")) + .enablePlugins(JPMSPlugin) .configs(Test) .settings( frgaalJavaCompilerSetting, + scalaModuleDependencySetting, + mixedJavaScalaProjectSetting, resolvers += Resolver.bintrayRepo("gn0s1s", "releases"), libraryDependencies ++= Seq( "com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion, "org.apache.commons" % "commons-compress" % commonsCompressVersion, - "org.scalatest" %% "scalatest" % scalatestVersion % Test, - akkaHttp + "org.scalatest" %% "scalatest" % scalatestVersion % Test + ), + Compile / moduleDependencies ++= Seq( + "org.apache.commons" % "commons-compress" % commonsCompressVersion, + "org.slf4j" % "slf4j-api" % slf4jVersion + ), + Compile / internalModuleDependencies := Seq( + (`cli` / Compile / exportedModule).value, + (`distribution-manager` / Compile / exportedModule).value, + (`downloader` / Compile / exportedModule).value, + (`editions` / Compile / exportedModule).value, + (`edition-updater` / Compile / exportedModule).value, + (`logging-utils` / Compile / exportedModule).value, + (`pkg` / Compile / exportedModule).value, + (`semver` / Compile / exportedModule).value, + (`scala-libs-wrapper` / Compile / exportedModule).value, + (`scala-yaml` / Compile / exportedModule).value, + (`version-output` / Compile / exportedModule).value ) ) .dependsOn(pkg) diff --git a/build/build/src/engine/context.rs b/build/build/src/engine/context.rs index 42328320a7f..8b4b9f65b44 100644 --- a/build/build/src/engine/context.rs +++ b/build/build/src/engine/context.rs @@ -664,6 +664,7 @@ pub async fn runner_sanity_test( .bin .join("enso") .with_executable_extension(); + let test_base = Command::new(&enso) .args(["--run", repo_root.test.join("Base_Tests").as_str()]) .set_env(ENSO_DATA_DIRECTORY, engine_package)? @@ -686,7 +687,25 @@ pub async fn runner_sanity_test( .run_ok() .await; - test_base.and(test_internal_base).and(test_geo) + let all_cmds = test_base.and(test_internal_base).and(test_geo); + + // The following test does not actually run anything, it just checks if the engine + // can accept `--jvm` argument and evaluates something. + if TARGET_OS != OS::Windows { + let test_jvm_arg = Command::new(&enso) + .args([ + "--jvm", + "--run", + repo_root.test.join("Base_Tests").as_str(), + "__NON_EXISTING_TEST__", + ]) + .set_env(ENSO_DATA_DIRECTORY, engine_package)? + .run_ok() + .await; + all_cmds.and(test_jvm_arg) + } else { + all_cmds + } } else { Ok(()) } diff --git a/distribution/launcher/THIRD-PARTY/NOTICE b/distribution/launcher/THIRD-PARTY/NOTICE index 9f5326ae53c..b09d657a906 100644 --- a/distribution/launcher/THIRD-PARTY/NOTICE +++ b/distribution/launcher/THIRD-PARTY/NOTICE @@ -36,21 +36,6 @@ The license file can be found at `licenses/APACHE2.0`. Copyright notices related to this dependency can be found in the directory `com.typesafe.akka.akka-actor_2.13-2.6.20`. -'akka-http-core_2.13', licensed under the Apache-2.0, is distributed with the launcher. -The license file can be found at `licenses/APACHE2.0`. -Copyright notices related to this dependency can be found in the directory `com.typesafe.akka.akka-http-core_2.13-10.2.10`. - - -'akka-http_2.13', licensed under the Apache-2.0, is distributed with the launcher. -The license file can be found at `licenses/APACHE2.0`. -Copyright notices related to this dependency can be found in the directory `com.typesafe.akka.akka-http_2.13-10.2.10`. - - -'akka-parsing_2.13', licensed under the Apache-2.0, is distributed with the launcher. -The license file can be found at `licenses/APACHE2.0`. -Copyright notices related to this dependency can be found in the directory `com.typesafe.akka.akka-parsing_2.13-10.2.10`. - - 'akka-slf4j_2.13', licensed under the Apache-2.0, is distributed with the launcher. The license file can be found at `licenses/APACHE2.0`. Copyright notices related to this dependency can be found in the directory `com.typesafe.akka.akka-slf4j_2.13-2.6.20`. diff --git a/distribution/launcher/THIRD-PARTY/com.typesafe.akka.akka-http-core_2.13-10.2.10/NOTICES b/distribution/launcher/THIRD-PARTY/com.typesafe.akka.akka-http-core_2.13-10.2.10/NOTICES deleted file mode 100644 index 03925592b62..00000000000 --- a/distribution/launcher/THIRD-PARTY/com.typesafe.akka.akka-http-core_2.13-10.2.10/NOTICES +++ /dev/null @@ -1,11 +0,0 @@ -Copyright (C) 2008-2017 Bjoern Hoehrmann - -Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev - -Copyright (C) 2009-2022 Lightbend Inc. - -Copyright 2011 Mark Harrah, Eugene Yokota - -Copyright 2014 Twitter, Inc. - -Copyright 2015 Heiko Seeberger diff --git a/distribution/launcher/THIRD-PARTY/com.typesafe.akka.akka-http_2.13-10.2.10/NOTICES b/distribution/launcher/THIRD-PARTY/com.typesafe.akka.akka-http_2.13-10.2.10/NOTICES deleted file mode 100644 index e25cd2d998b..00000000000 --- a/distribution/launcher/THIRD-PARTY/com.typesafe.akka.akka-http_2.13-10.2.10/NOTICES +++ /dev/null @@ -1 +0,0 @@ -Copyright (C) 2009-2020 Lightbend Inc. diff --git a/distribution/launcher/THIRD-PARTY/com.typesafe.akka.akka-parsing_2.13-10.2.10/NOTICES b/distribution/launcher/THIRD-PARTY/com.typesafe.akka.akka-parsing_2.13-10.2.10/NOTICES deleted file mode 100644 index 055c0b30159..00000000000 --- a/distribution/launcher/THIRD-PARTY/com.typesafe.akka.akka-parsing_2.13-10.2.10/NOTICES +++ /dev/null @@ -1,7 +0,0 @@ -Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev - -Copyright (C) 2009-2022 Lightbend Inc. - -Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (base64 @ miginfocom . com) - -Copyright (c) 2011-13 Miles Sabin diff --git a/engine/launcher/src/main/scala/org/enso/launcher/distribution/DefaultManagers.scala b/engine/launcher/src/main/scala/org/enso/launcher/distribution/DefaultManagers.scala index d23063c813b..8105e3a66d6 100644 --- a/engine/launcher/src/main/scala/org/enso/launcher/distribution/DefaultManagers.scala +++ b/engine/launcher/src/main/scala/org/enso/launcher/distribution/DefaultManagers.scala @@ -39,10 +39,6 @@ object DefaultManagers { lazy val temporaryDirectoryManager = TemporaryDirectoryManager(distributionManager, defaultResourceManager) - /** Default [[RuntimeComponentConfiguration]]. */ - lazy val componentConfig: RuntimeComponentConfiguration = - new GraalVMComponentConfiguration - /** Creates a [[RuntimeVersionManager]] that uses the default distribution. */ def runtimeVersionManager( globalCLIOptions: GlobalCLIOptions, @@ -55,12 +51,11 @@ object DefaultManagers { alwaysInstallMissing ), distributionManager, + new GraalVersionManager(distributionManager, LauncherEnvironment), temporaryDirectoryManager, defaultResourceManager, EngineRepository.defaultEngineReleaseProvider, GraalCEReleaseProvider.default, - componentConfig, - RuntimeComponentUpdaterFactory.Default, InstallerKind.Launcher ) } diff --git a/engine/runner/src/main/java/module-info.java b/engine/runner/src/main/java/module-info.java index dd625d9c59b..493c5af4adf 100644 --- a/engine/runner/src/main/java/module-info.java +++ b/engine/runner/src/main/java/module-info.java @@ -9,6 +9,7 @@ module org.enso.runner { requires org.enso.logging.config; requires org.enso.logging.utils; requires org.enso.runtime.parser; + requires org.enso.runtime.version.manager; requires org.enso.runner.common; requires org.enso.pkg; requires org.enso.polyglot.api; diff --git a/engine/runner/src/main/java/org/enso/runner/JavaFinder.java b/engine/runner/src/main/java/org/enso/runner/JavaFinder.java new file mode 100644 index 00000000000..44b340e762e --- /dev/null +++ b/engine/runner/src/main/java/org/enso/runner/JavaFinder.java @@ -0,0 +1,110 @@ +package org.enso.runner; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Comparator; +import java.util.concurrent.TimeUnit; +import org.enso.distribution.DistributionManager; +import org.enso.distribution.Environment; +import org.enso.runtimeversionmanager.components.GraalRuntime; +import org.enso.runtimeversionmanager.components.GraalVMVersion; +import org.enso.runtimeversionmanager.components.GraalVersionManager; +import org.enso.version.BuildVersion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Utility class that tries to find installed JDK on the system. */ +final class JavaFinder { + private static final Logger logger = LoggerFactory.getLogger(JavaFinder.class); + + private JavaFinder() {} + + /** + * Tries to find {@code java} executable on the system. If a system-wide JDK is not found, tries + * to find it in the {@link DistributionManager distribution} runtimes. + * + * @return null if cannot be found. Otherwise, returns the absolute path to the executable, or + * simply {@code java} if it is on the {@code PATH}. + */ + static String findJavaExecutable() { + var javaInRuntime = findJavaExecutableInDistributionRuntimes(); + if (javaInRuntime != null) { + return javaInRuntime.toAbsolutePath().toString(); + } + logger.warn("No appropriate JDK found in the distribution runtimes. Trying system-wide JDK."); + var javaHome = System.getenv("JAVA_HOME"); + if (javaHome != null) { + var binDir = Path.of(javaHome).resolve("bin"); + Path javaExe; + if (isOnWindows()) { + javaExe = binDir.resolve("java.exe"); + } else { + javaExe = binDir.resolve("java"); + } + if (javaExe.toFile().exists()) { + logger.warn("Found JDK in JAVA_HOME: {}", javaHome); + return javaExe.toAbsolutePath().toString(); + } + } + logger.warn("No JDK found in JAVA_HOME. Trying java on PATH."); + if (isJavaOnPath()) { + var javaExe = isOnWindows() ? "java.exe" : "java"; + logger.warn("Falling back to java on PATH: {}", javaExe); + return javaExe; + } + logger.warn("No JDK found on PATH. Cannot start the runtime."); + return null; + } + + private static boolean isOnWindows() { + return System.getProperty("os.name").equals("windows"); + } + + /** + * Tries to find {@code java} executable in the distribution runtime with the same version that + * was used for building, or a newer one. + * + * @return null if not found. + */ + private static Path findJavaExecutableInDistributionRuntimes() { + var env = new Environment() {}; + var distributionManager = new DistributionManager(env); + var graalVersionManager = new GraalVersionManager(distributionManager, env); + var versionUsedForBuild = + new GraalVMVersion(BuildVersion.graalVersion(), BuildVersion.javaVersion()); + var runtimeWithExactVersionMatch = graalVersionManager.findGraalRuntime(versionUsedForBuild); + if (runtimeWithExactVersionMatch != null) { + return runtimeWithExactVersionMatch.javaExecutable(); + } + // Try to find newer runtime (JDK). + var newerRuntime = + graalVersionManager.getAllRuntimes().stream() + .sorted(Comparator.comparing(GraalRuntime::version)) + .filter(runtime -> runtime.version().compareTo(versionUsedForBuild) > 0) + .findFirst(); + if (newerRuntime.isPresent()) { + logger.warn( + "Found newer JDK [{}] than the one used for build [{}]", + newerRuntime.get().version(), + versionUsedForBuild); + return newerRuntime.get().javaExecutable(); + } + return null; + } + + private static boolean isJavaOnPath() { + try { + ProcessBuilder processBuilder; + if (isOnWindows()) { + processBuilder = new ProcessBuilder("java.exe", "-h"); + } else { + processBuilder = new ProcessBuilder("java", "-h"); + } + Process process = processBuilder.start(); + boolean exitSucc = process.waitFor(5L, TimeUnit.SECONDS); + return exitSucc; + } catch (IOException | InterruptedException e) { + return false; + } + } +} diff --git a/engine/runner/src/main/java/org/enso/runner/Main.java b/engine/runner/src/main/java/org/enso/runner/Main.java index fd99d8486c8..711c4248810 100644 --- a/engine/runner/src/main/java/org/enso/runner/Main.java +++ b/engine/runner/src/main/java/org/enso/runner/Main.java @@ -1339,22 +1339,13 @@ public class Main { println(JVM_OPTION + " option has no effect - already running in JVM " + current); } else { var commandAndArgs = new ArrayList(); - JVM_FOUND: if (jvm == null) { - var env = new Environment() {}; - var dm = new DistributionManager(env); - var paths = dm.paths(); - var files = paths.runtimes().toFile().listFiles(); - if (files != null) { - for (var d : files) { - var java = new File(new File(d, "bin"), "java").getAbsoluteFile(); - if (java.exists()) { - commandAndArgs.add(java.getPath()); - break JVM_FOUND; - } - } + var javaExe = JavaFinder.findJavaExecutable(); + if (javaExe == null) { + println("Cannot find java executable"); + throw exitFail(); } - commandAndArgs.add("java"); + commandAndArgs.add(javaExe); } else { commandAndArgs.add(new File(new File(new File(jvm), "bin"), "java").getAbsolutePath()); } diff --git a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/versionmanagement/DefaultDistributionConfiguration.scala b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/versionmanagement/DefaultDistributionConfiguration.scala index b4fd9c79e0f..59e4b9b7034 100644 --- a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/versionmanagement/DefaultDistributionConfiguration.scala +++ b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/versionmanagement/DefaultDistributionConfiguration.scala @@ -52,12 +52,6 @@ object DefaultDistributionConfiguration lazy val temporaryDirectoryManager = TemporaryDirectoryManager(distributionManager, resourceManager) - lazy val componentConfiguration: RuntimeComponentConfiguration = - new GraalVMComponentConfiguration - - lazy val runtimeComponentUpdaterFactory: RuntimeComponentUpdaterFactory = - RuntimeComponentUpdaterFactory.Default - /** @inheritdoc */ def engineReleaseProvider: ReleaseProvider[EngineRelease] = EngineRepository.defaultEngineReleaseProvider @@ -67,15 +61,15 @@ object DefaultDistributionConfiguration userInterface: RuntimeVersionManagementUserInterface ): RuntimeVersionManager = new RuntimeVersionManager( - environment = this.environment, - userInterface = userInterface, - distributionManager = distributionManager, + environment = this.environment, + userInterface = userInterface, + distributionManager = distributionManager, + graalVersionManager = + new GraalVersionManager(distributionManager, environment), temporaryDirectoryManager = temporaryDirectoryManager, resourceManager = resourceManager, engineReleaseProvider = engineReleaseProvider, runtimeReleaseProvider = GraalCEReleaseProvider.default, - componentConfig = componentConfiguration, - componentUpdaterFactory = runtimeComponentUpdaterFactory, installerKind = InstallerKind.ProjectManager ) diff --git a/lib/scala/project-manager/src/test/scala/org/enso/projectmanager/TestDistributionConfiguration.scala b/lib/scala/project-manager/src/test/scala/org/enso/projectmanager/TestDistributionConfiguration.scala index 5e84b2f0ec4..6d3fdb344df 100644 --- a/lib/scala/project-manager/src/test/scala/org/enso/projectmanager/TestDistributionConfiguration.scala +++ b/lib/scala/project-manager/src/test/scala/org/enso/projectmanager/TestDistributionConfiguration.scala @@ -7,7 +7,7 @@ import org.enso.editions.updater.EditionManager import java.nio.file.Path import org.enso.projectmanager.versionmanagement.DistributionConfiguration import org.enso.runtimeversionmanager.components.{ - GraalVMComponentConfiguration, + GraalVersionManager, InstallerKind, RuntimeVersionManagementUserInterface, RuntimeVersionManager @@ -28,7 +28,6 @@ import org.enso.runtimeversionmanager.releases.{ import org.enso.runtimeversionmanager.runner.{JVMSettings, JavaCommand} import org.enso.runtimeversionmanager.test.{ FakeEnvironment, - NoopComponentUpdaterFactory, TestLocalLockManager } import org.enso.testkit.HasTestDirectory @@ -60,6 +59,9 @@ class TestDistributionConfiguration( lazy val distributionManager = new DistributionManager(environment) + lazy val graalVersionManager = + new GraalVersionManager(distributionManager, environment) + lazy val lockManager = new TestLocalLockManager lazy val resourceManager = new ResourceManager(lockManager) @@ -69,10 +71,6 @@ class TestDistributionConfiguration( lazy val temporaryDirectoryManager = TemporaryDirectoryManager(distributionManager, resourceManager) - lazy val componentConfig = new GraalVMComponentConfiguration - - lazy val componentUpdaterFactory = NoopComponentUpdaterFactory - override def makeRuntimeVersionManager( userInterface: RuntimeVersionManagementUserInterface ): RuntimeVersionManager = new RuntimeVersionManager( @@ -80,11 +78,10 @@ class TestDistributionConfiguration( userInterface = userInterface, distributionManager = distributionManager, temporaryDirectoryManager = temporaryDirectoryManager, + graalVersionManager = graalVersionManager, resourceManager = resourceManager, engineReleaseProvider = engineReleaseProvider, runtimeReleaseProvider = runtimeReleaseProvider, - componentConfig = componentConfig, - componentUpdaterFactory = componentUpdaterFactory, installerKind = InstallerKind.ProjectManager ) diff --git a/lib/scala/runtime-version-manager-test/src/main/scala/org/enso/runtimeversionmanager/test/NoopComponentUpdater.scala b/lib/scala/runtime-version-manager-test/src/main/scala/org/enso/runtimeversionmanager/test/NoopComponentUpdater.scala deleted file mode 100644 index c11f2648df7..00000000000 --- a/lib/scala/runtime-version-manager-test/src/main/scala/org/enso/runtimeversionmanager/test/NoopComponentUpdater.scala +++ /dev/null @@ -1,20 +0,0 @@ -package org.enso.runtimeversionmanager.test - -import org.enso.runtimeversionmanager.components.{ - GraalVMComponent, - RuntimeComponentUpdater -} - -import scala.util.Try - -/** Test component updater that does not do anything. */ -object NoopComponentUpdater extends RuntimeComponentUpdater { - - /** @inheritdoc */ - override def list(): Try[Seq[GraalVMComponent]] = - Try(Seq()) - - /** @inheritdoc */ - override def install(components: Seq[GraalVMComponent]): Try[Unit] = - Try(()) -} diff --git a/lib/scala/runtime-version-manager-test/src/main/scala/org/enso/runtimeversionmanager/test/NoopComponentUpdaterFactory.scala b/lib/scala/runtime-version-manager-test/src/main/scala/org/enso/runtimeversionmanager/test/NoopComponentUpdaterFactory.scala deleted file mode 100644 index fd8cee58d1a..00000000000 --- a/lib/scala/runtime-version-manager-test/src/main/scala/org/enso/runtimeversionmanager/test/NoopComponentUpdaterFactory.scala +++ /dev/null @@ -1,15 +0,0 @@ -package org.enso.runtimeversionmanager.test - -import org.enso.runtimeversionmanager.components.{ - GraalRuntime, - RuntimeComponentUpdater, - RuntimeComponentUpdaterFactory -} - -/** Test factory creating a noop updater. */ -object NoopComponentUpdaterFactory extends RuntimeComponentUpdaterFactory { - - /** @inheritdoc */ - override def build(runtime: GraalRuntime): RuntimeComponentUpdater = - NoopComponentUpdater -} diff --git a/lib/scala/runtime-version-manager-test/src/main/scala/org/enso/runtimeversionmanager/test/RuntimeVersionManagerTest.scala b/lib/scala/runtime-version-manager-test/src/main/scala/org/enso/runtimeversionmanager/test/RuntimeVersionManagerTest.scala index d50b6e70049..0fb469c2bdc 100644 --- a/lib/scala/runtime-version-manager-test/src/main/scala/org/enso/runtimeversionmanager/test/RuntimeVersionManagerTest.scala +++ b/lib/scala/runtime-version-manager-test/src/main/scala/org/enso/runtimeversionmanager/test/RuntimeVersionManagerTest.scala @@ -9,7 +9,7 @@ import org.enso.distribution.{ } import org.enso.pkg.{Config, PackageManager} import org.enso.runtimeversionmanager.components.{ - GraalVMComponentConfiguration, + GraalVersionManager, InstallerKind, RuntimeVersionManagementUserInterface, RuntimeVersionManager @@ -51,22 +51,21 @@ class RuntimeVersionManagerTest ): (DistributionManager, RuntimeVersionManager, Environment) = { val env = fakeInstalledEnvironment(environmentOverrides) val distributionManager = new PortableDistributionManager(env) + val graalVersionManager = new GraalVersionManager(distributionManager, env) val resourceManager = TestLocalResourceManager.create() val temporaryDirectoryManager = TemporaryDirectoryManager(distributionManager, resourceManager) - val componentConfig = new GraalVMComponentConfiguration val runtimeVersionManager = new RuntimeVersionManager( env, userInterface, distributionManager, + graalVersionManager, temporaryDirectoryManager, resourceManager, engineProvider, runtimeProvider, - componentConfig, - NoopComponentUpdaterFactory, installerKind ) diff --git a/lib/scala/runtime-version-manager-test/src/test/scala/org/enso/distribution/locking/ConcurrencyTest.scala b/lib/scala/runtime-version-manager-test/src/test/scala/org/enso/distribution/locking/ConcurrencyTest.scala index aaf01815b0f..895515302fb 100644 --- a/lib/scala/runtime-version-manager-test/src/test/scala/org/enso/distribution/locking/ConcurrencyTest.scala +++ b/lib/scala/runtime-version-manager-test/src/test/scala/org/enso/distribution/locking/ConcurrencyTest.scala @@ -9,8 +9,8 @@ import org.enso.distribution.{ TemporaryDirectoryManager } import org.enso.runtimeversionmanager.components.{ - GraalVMComponentConfiguration, GraalVMVersion, + GraalVersionManager, InstallerKind, Manifest, RuntimeVersionManager @@ -140,19 +140,18 @@ class ConcurrencyTest } } + val graalVersionManager = new GraalVersionManager(distributionManager, env) val temporaryDirectoryManager = TemporaryDirectoryManager(distributionManager, resourceManager) - val componentConfig = new GraalVMComponentConfiguration val componentsManager = new RuntimeVersionManager( env, TestRuntimeVersionManagementUserInterface.default, distributionManager, + graalVersionManager, temporaryDirectoryManager, resourceManager, engineProvider, runtimeProvider, - componentConfig, - NoopComponentUpdaterFactory, InstallerKind.Launcher ) diff --git a/lib/scala/runtime-version-manager/src/main/java/module-info.java b/lib/scala/runtime-version-manager/src/main/java/module-info.java new file mode 100644 index 00000000000..7aee955efa5 --- /dev/null +++ b/lib/scala/runtime-version-manager/src/main/java/module-info.java @@ -0,0 +1,22 @@ +module org.enso.runtime.version.manager { + requires scala.library; + requires org.apache.commons.compress; + requires org.slf4j; + requires org.enso.cli; + requires org.enso.distribution; + requires org.enso.downloader; + requires org.enso.editions; + requires org.enso.editions.updater; + requires org.enso.logging.utils; + requires org.enso.pkg; + requires org.enso.semver; + requires org.enso.scala.yaml; + // For com.typesafe.scalalogging.Logger + requires org.enso.scala.wrapper; + requires org.enso.version.output; + + exports org.enso.runtimeversionmanager; + exports org.enso.runtimeversionmanager.cli; + exports org.enso.runtimeversionmanager.components; + exports org.enso.runtimeversionmanager.runner; +} diff --git a/lib/scala/runtime-version-manager/src/main/java/org/enso/runtimeversionmanager/components/GraalVersionManager.java b/lib/scala/runtime-version-manager/src/main/java/org/enso/runtimeversionmanager/components/GraalVersionManager.java new file mode 100644 index 00000000000..06c385445d6 --- /dev/null +++ b/lib/scala/runtime-version-manager/src/main/java/org/enso/runtimeversionmanager/components/GraalVersionManager.java @@ -0,0 +1,140 @@ +package org.enso.runtimeversionmanager.components; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; +import org.enso.distribution.DistributionManager; +import org.enso.distribution.Environment; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import scala.jdk.javaapi.CollectionConverters; + +/** + * Utility class that finds installed managed runtimes (Graal JDK) from {@link DistributionManager}. + */ +public final class GraalVersionManager { + private final DistributionManager distributionManager; + private final Environment environment; + private static final Logger logger = LoggerFactory.getLogger(GraalVersionManager.class); + + public GraalVersionManager(DistributionManager distributionManager, Environment environment) { + this.distributionManager = distributionManager; + this.environment = environment; + } + + /** + * Get all locally installed runtimes. + * + * @return Possibly empty list. Not null. + */ + public List getAllRuntimes() { + var foundRuntimes = new ArrayList(); + for (var runtimeSearchPath : + CollectionConverters.asJava(distributionManager.paths().runtimeSearchPaths())) { + if (runtimeSearchPath.toFile().isDirectory()) { + var subdirs = runtimeSearchPath.toFile().listFiles(); + assert subdirs != null; + for (var subdir : subdirs) { + var parsedVersion = parseGraalRuntimeVersionString(subdir.getName()); + if (parsedVersion != null) { + var foundRuntime = new GraalRuntime(parsedVersion, subdir.toPath()); + foundRuntime.ensureValid(); + foundRuntimes.add(foundRuntime); + } + } + } else { + logger.warn("Runtime search path `{}` is not a directory", runtimeSearchPath); + } + } + return foundRuntimes; + } + + /** + * Tries to find a GraalVM runtime for the provided engine. + * + *

Returns null if the runtime is missing. + */ + public GraalRuntime findGraalRuntime(Engine engine) { + return findGraalRuntime(engine.manifest().runtimeVersion()); + } + + /** + * Finds an installed GraalVM runtime with the given {@code version}. + * + *

Returns null if that version is not installed. + */ + public GraalRuntime findGraalRuntime(GraalVMVersion version) { + var explicitPathOpt = environment.getEnvPath("ENSO_JVM_PATH"); + if (explicitPathOpt.isDefined()) { + var runtime = new GraalRuntime(version, explicitPathOpt.get()); + runtime.ensureValid(); + logger.debug("Found GraalVM runtime [{}]", runtime); + return runtime; + } + var pathOpt = findGraalRuntimeOnSearchPath(version); + if (pathOpt != null) { + GraalRuntime runtime; + try { + runtime = loadGraalRuntime(pathOpt); + } catch (Exception e) { + throw new UnrecognizedComponentError( + "The runtime " + + version + + "is already installed, but cannot be " + + "loaded due to " + + e.getMessage() + + "." + + "Until the launcher gets an auto-repair " + + "feature, please try reinstalling the runtime by " + + "uninstalling all engines that use it and installing them " + + "again, or manually removing `" + + pathOpt + + "`", + e); + } + logger.debug("Found GraalVM runtime [{}]", runtime); + return runtime; + } + logger.debug("GraalVM runtime [{}] not found", version); + return null; + } + + public GraalRuntime loadGraalRuntime(Path path) throws UnrecognizedComponentError { + logger.debug("Loading Graal runtime [{}]", path); + var name = path.getFileName().toString(); + var version = parseGraalRuntimeVersionString(name); + if (version == null) { + throw new UnrecognizedComponentError("Invalid runtime component name `" + name + "`", null); + } + var runtime = new GraalRuntime(version, path); + runtime.ensureValid(); + return runtime; + } + + private Path findGraalRuntimeOnSearchPath(GraalVMVersion version) { + var name = graalRuntimeNameForVersion(version); + for (var runtimeSearchPath : + CollectionConverters.asJava(distributionManager.paths().runtimeSearchPaths())) { + var path = runtimeSearchPath.resolve(name); + if (path.toFile().exists()) { + return path; + } + } + return null; + } + + private GraalVMVersion parseGraalRuntimeVersionString(String name) { + var pattern = Pattern.compile("graalvm-ce-java(.+)-(.+)"); + var matcher = pattern.matcher(name); + if (matcher.matches()) { + return new GraalVMVersion(matcher.group(2), matcher.group(1)); + } + logger.warn("Unrecognized runtime name `{}`", name); + return null; + } + + private static String graalRuntimeNameForVersion(GraalVMVersion version) { + return "graalvm-ce-java" + version.javaVersion() + "-" + version.graalVersion(); + } +} diff --git a/lib/scala/runtime-version-manager/src/main/java/org/enso/runtimeversionmanager/package-info.java b/lib/scala/runtime-version-manager/src/main/java/org/enso/runtimeversionmanager/package-info.java deleted file mode 100644 index 2b5d1e7f35f..00000000000 --- a/lib/scala/runtime-version-manager/src/main/java/org/enso/runtimeversionmanager/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package org.enso.runtimeversionmanager; diff --git a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/cli/Arguments.scala b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/cli/Arguments.scala index a20026002c1..2be09b79e62 100644 --- a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/cli/Arguments.scala +++ b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/cli/Arguments.scala @@ -1,6 +1,5 @@ package org.enso.runtimeversionmanager.cli -import akka.http.scaladsl.model.{IllegalUriException, Uri} import org.enso.cli.arguments.{Argument, OptsParseError} import org.enso.logger.LoggerUtils @@ -9,14 +8,6 @@ import java.net.URISyntaxException import org.slf4j.event.Level object Arguments { - implicit val uriAkkaArgument: Argument[Uri] = (string: String) => - try { - Right(Uri(string)) - } catch { - case error: IllegalUriException => - Left(OptsParseError(s"`$string` is not a valid Uri: $error.")) - } - implicit val uriArgument: Argument[URI] = (string: String) => try { Right(URI.create(string)) diff --git a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMComponent.scala b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMComponent.scala deleted file mode 100644 index 9fa89490d0b..00000000000 --- a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMComponent.scala +++ /dev/null @@ -1,11 +0,0 @@ -package org.enso.runtimeversionmanager.components - -/** A component of the GraalVM distribution. */ -case class GraalVMComponent(id: String) - -object GraalVMComponent { - - val js: GraalVMComponent = GraalVMComponent("js") - val python: GraalVMComponent = GraalVMComponent("python") - val R: GraalVMComponent = GraalVMComponent("R") -} diff --git a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMComponentConfiguration.scala b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMComponentConfiguration.scala deleted file mode 100644 index dc821a55181..00000000000 --- a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMComponentConfiguration.scala +++ /dev/null @@ -1,89 +0,0 @@ -package org.enso.runtimeversionmanager.components - -import org.enso.cli.OS - -/** Component configuration of the GraalVM distribution. */ -class GraalVMComponentConfiguration extends RuntimeComponentConfiguration { - - import GraalVMComponentConfiguration._ - - /** @inheritdoc */ - override def getRequiredComponents( - version: GraalVMVersion, - os: OS - ): Seq[GraalVMComponent] = { - val optPythonComponent = - if (os.hasPythonSupport) Seq(GraalVMComponent.python) else Seq() - val optRComponent = - if (os.hasRSupport) Seq(GraalVMComponent.R) else Seq() - if (version.isUnchained) { - Seq() - } else { - version.graalVersion match { - case GraalVersions.Major(v) if v >= 23 => - // Since 23.0.0, R is not bundled in the Graal release anymore. - Seq(GraalVMComponent.js) ++ optPythonComponent - case GraalVersions.Major(v) if v >= 22 => - Seq(GraalVMComponent.js) ++ optRComponent ++ optPythonComponent - case GraalVersions.Major(v) - if v > 20 && os.hasSulongSupport && os.hasRSupport => - Seq(GraalVMComponent.R) ++ optPythonComponent - case _ => - Seq() - } - } - } - -} -object GraalVMComponentConfiguration { - - /** OS extensions. */ - implicit private class OSExtensions(os: OS) { - - /** Check if the provided OS supports Sulong runtime. - * - * Sulong is a Graal sub-project, providing an engine for running - * LLVM bitcode on GraalVM. - * - * @return `true` if the OS supports Sulong runtime and `false` otherwise - */ - def hasSulongSupport: Boolean = - os match { - case OS.Linux => true - case OS.MacOS => true - case OS.Windows => false - } - - /** Check if the provided OS supports Python. - * Python is currently not supported in any form on Windows. - * - * @return `true` if the OS supports Python runtime - */ - def hasPythonSupport: Boolean = - os match { - case OS.Windows => false - case _ => true - } - - /** Check if the provided OS supports FastR. - * FastR is currently not supported in any form on Windows. - * - * @return `true` if the OS supports FastR GraalVM component. - */ - def hasRSupport: Boolean = - os match { - case OS.Windows => false - case _ => true - } - } - - private object GraalVersions { - - /** Get the major Graal version number. */ - object Major { - def unapply(version: String): Option[Int] = { - version.takeWhile(_ != '.').toIntOption - } - } - } -} diff --git a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMComponentUpdater.scala b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMComponentUpdater.scala deleted file mode 100644 index 9b781e8a5d7..00000000000 --- a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMComponentUpdater.scala +++ /dev/null @@ -1,180 +0,0 @@ -package org.enso.runtimeversionmanager.components - -import java.nio.file.Path -import com.typesafe.scalalogging.Logger - -import scala.sys.process._ -import scala.util.{Failure, Success, Try} - -/** Module that manages components of the GraalVM distribution. - * - * @param runtime the GraalVM runtime - */ -class GraalVMComponentUpdater(runtime: GraalRuntime) - extends RuntimeComponentUpdater { - - import GraalVMComponentUpdater._ - - private val logger = Logger[GraalVMComponentUpdater] - private val gu = runtime.findExecutable("gu") - - /** Path to the GraalVM's updater. - * - * @return path that will be executed to call the updater - */ - protected def updaterExec: Path = gu - - /** List the installed GraalVM components. - * - * @return the list of installed GraalVM components - */ - override def list(): Try[Seq[GraalVMComponent]] = { - val command = Seq("list", "-v") - - logger.trace("{} {}", gu, Properties(gu)) - logger.debug( - "Executing: JAVA_HOME={} GRAALVM_HOME={} {} {}", - runtime.javaHome, - runtime.javaHome, - gu, - command.mkString(" ") - ) - - val executor = new ExponentialBackoffRetry(5, logger) { - override def cmd: String = "list" - override def executeProcess( - logger: ProcessLogger - ): Try[LazyList[String]] = { - val process = Process( - updaterExec.toAbsolutePath.toString +: command, - Some(runtime.javaHome.toFile), - ("JAVA_HOME", runtime.javaHome), - ("GRAALVM_HOME", runtime.javaHome) - ) - Try(process.lazyLines(logger)) - } - } - executor - .execute() - .map(stdout => if (stdout.isEmpty) Seq() else ListOut.parse(stdout)) - } - - /** Install the provided GraalVM components. - * - * @param components the list of components to install - */ - override def install(components: Seq[GraalVMComponent]): Try[Unit] = { - if (components.nonEmpty) { - val command = "install" +: components.map(_.id) - logger.trace("{} {}", gu, Properties(gu)) - logger.debug( - "Executing: JAVA_HOME={} GRRAALVM_HOME={} {} {}", - runtime.javaHome, - runtime.javaHome, - gu, - command.mkString(" ") - ) - val executor = new ExponentialBackoffRetry(5, logger) { - override def cmd: String = "install" - override def executeProcess( - logger: ProcessLogger - ): Try[LazyList[String]] = { - val process = Process( - updaterExec.toAbsolutePath.toString +: command, - Some(runtime.path.toFile), - ("JAVA_HOME", runtime.javaHome), - ("GRAALVM_HOME", runtime.javaHome) - ) - Try(process.lazyLines(logger)) - } - } - executor.execute().map { stdout => - stdout.foreach(logger.trace(_)) - () - } - } else { - Success(()) - } - } - -} -object GraalVMComponentUpdater { - - abstract class ProcessWithRetries(maxRetries: Int, logger: Logger) { - def executeProcess(logger: ProcessLogger): Try[LazyList[String]] - - def cmd: String - - def execute(): Try[List[String]] = execute(0) - - protected def retryWait(retry: Int): Long - - private def execute(retry: Int): Try[List[String]] = { - val errors = scala.collection.mutable.ListBuffer[String]() - val processLogger = ProcessLogger(err => errors.addOne(err)) - executeProcess(processLogger) match { - case Success(stdout) => - Try(stdout.toList).recoverWith({ - case _ if retry < maxRetries => - try { - Thread.sleep(retryWait(retry)) - } catch { - case _: InterruptedException => - } - execute(retry + 1) - }) - case Failure(exception) if retry < maxRetries => - logger.warn("{} failed: {}. Retrying...", cmd, exception.getMessage) - try { - Thread.sleep(retryWait(retry)) - } catch { - case _: InterruptedException => - } - execute(retry + 1) - case Failure(exception) => - errors.foreach(logger.trace("[stderr] {}", _)) - Failure(exception) - } - } - } - - abstract class ExponentialBackoffRetry(maxRetries: Int, logger: Logger) - extends ProcessWithRetries(maxRetries, logger) { - override def retryWait(retry: Int): Long = { - 200 * 2.toLong ^ retry - } - - } - - implicit private def pathToString(path: Path): String = - path.toAbsolutePath.toString - - /** Debug file properties. */ - private case class Properties(path: Path) { - - private val file = path.toFile - - override def toString: String = - s"{ exists=${file.exists()}, " + - s"executable=${file.canExecute} " + - "}" - } - - /** Parser for the `gu list -v` command output. */ - object ListOut { - - private val ID: String = "ID" - private val separator: Char = ':' - - /** Extract the GraalVM components from the gu output. - * - * @param lines the gu output - * @return the list of GraalVM components. - */ - def parse(lines: Seq[String]): Seq[GraalVMComponent] = - lines - .filter(_.startsWith(ID)) - .map(_.dropWhile(_ != separator).drop(1).trim) - .map(GraalVMComponent(_)) - } -} diff --git a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMVersion.scala b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMVersion.scala index aa97aa65a3c..91e0f2f2597 100644 --- a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMVersion.scala +++ b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/GraalVMVersion.scala @@ -11,7 +11,8 @@ import org.enso.semver.SemVer * Can be specified either as a single integer or as a * semantic version */ -case class GraalVMVersion(graalVersion: String, javaVersion: String) { +case class GraalVMVersion(graalVersion: String, javaVersion: String) + extends Comparable[GraalVMVersion] { require(GraalVMVersion.isCorrectVersionFormat(graalVersion)) require(GraalVMVersion.isCorrectVersionFormat(javaVersion)) @@ -29,15 +30,35 @@ case class GraalVMVersion(graalVersion: String, javaVersion: String) { } } - /** The GraalVM distribution policy changed a lot since GraalVM 23.1.0 for JDK 21. - * Most of the components for the newest GraalVM distributions are distributed as - * artifacts from the Maven central. This mens there is no longer `gu` tool. - * - * @see https://medium.com/graalvm/truffle-unchained-13887b77b62c - * @return true if this version is associated with Truffle unchained. - */ - def isUnchained: Boolean = { - javaMajorVersion >= 21 && graalMajorVersion >= 23 + override def compareTo(other: GraalVMVersion): Int = { + val javaSemVer = SemVer.parse(javaVersion) + val otherJavaSemVer = SemVer.parse(other.javaVersion) + if (javaSemVer.isSuccess && otherJavaSemVer.isSuccess) { + val comp = javaSemVer.get.compareTo(otherJavaSemVer.get) + if (comp != 0) { + return comp + } + } + + val graalSemVer = SemVer.parse(graalVersion) + val otherGraalSemVer = SemVer.parse(other.graalVersion) + if (graalSemVer.isSuccess && otherGraalSemVer.isSuccess) { + val comp = graalSemVer.get.compareTo(otherGraalSemVer.get) + if (comp != 0) { + return comp + } + } + + val javaMajorComp = javaMajorVersion.compareTo(other.javaMajorVersion) + if (javaMajorComp != 0) { + return javaMajorComp + } + val graalMajorComp = graalMajorVersion.compareTo(other.graalMajorVersion) + if (graalMajorComp != 0) { + return graalMajorComp + } + + 0 } } diff --git a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeComponentConfiguration.scala b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeComponentConfiguration.scala deleted file mode 100644 index f57cd56edb5..00000000000 --- a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeComponentConfiguration.scala +++ /dev/null @@ -1,19 +0,0 @@ -package org.enso.runtimeversionmanager.components - -import org.enso.cli.OS - -/** Provides configuration of the runtime components. */ -trait RuntimeComponentConfiguration { - - /** Return the list of components required for the provided version of - * the runtime installed on the provided OS. - * - * @param version the runtime version - * @param os the operating system - * @return the list of required components - */ - def getRequiredComponents( - version: GraalVMVersion, - os: OS - ): Seq[GraalVMComponent] -} diff --git a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeComponentUpdater.scala b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeComponentUpdater.scala deleted file mode 100644 index 2d3636ebf19..00000000000 --- a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeComponentUpdater.scala +++ /dev/null @@ -1,19 +0,0 @@ -package org.enso.runtimeversionmanager.components - -import scala.util.Try - -/** Module that manages components of the runtime distribution. */ -trait RuntimeComponentUpdater { - - /** List the installed runtime components. - * - * @return the list of installed runtime components - */ - def list(): Try[Seq[GraalVMComponent]] - - /** Install the provided runtime components. - * - * @param components the list of components to install - */ - def install(components: Seq[GraalVMComponent]): Try[Unit] -} diff --git a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeComponentUpdaterFactory.scala b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeComponentUpdaterFactory.scala deleted file mode 100644 index 7cfd192f5bc..00000000000 --- a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeComponentUpdaterFactory.scala +++ /dev/null @@ -1,30 +0,0 @@ -package org.enso.runtimeversionmanager.components - -/** The factory that creates a runtime component updater. */ -trait RuntimeComponentUpdaterFactory { - - /** Create a runtime component updater. - * - * @param runtime the GraalVM runtime - * @return new instance of the runtime component updater - */ - def build(runtime: GraalRuntime): RuntimeComponentUpdater -} - -object RuntimeComponentUpdaterFactory { - - /** The default runtime component updater factory creating an instance of - * [[GraalVMComponentUpdater]]. - */ - object Default extends RuntimeComponentUpdaterFactory { - - /** @inheritdoc */ - override def build(runtime: GraalRuntime): RuntimeComponentUpdater = { - if (runtime.version.isUnchained) { - new UnchainedGraalVMComponentUpdater() - } else { - new GraalVMComponentUpdater(runtime) - } - } - } -} diff --git a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeVersionManager.scala b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeVersionManager.scala index 0a2fba84264..134c83c6373 100644 --- a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeVersionManager.scala +++ b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeVersionManager.scala @@ -3,7 +3,6 @@ package org.enso.runtimeversionmanager.components import java.nio.file.{Files, Path, StandardOpenOption} import com.typesafe.scalalogging.Logger import org.enso.semver.SemVer -import org.enso.cli.OS import org.enso.distribution.{ DistributionManager, Environment, @@ -13,7 +12,6 @@ import org.enso.distribution.{ import org.enso.distribution.locking.{LockType, ResourceManager} import org.enso.runtimeversionmanager.CurrentVersion import org.enso.distribution.FileSystem.PathSyntax -import org.enso.logger.masking.MaskedPath import org.enso.downloader.archive.Archive import org.enso.runtimeversionmanager.locking.Resources import org.enso.runtimeversionmanager.releases.ReleaseProvider @@ -32,79 +30,36 @@ import scala.util.{Failure, Success, Try, Using} * @param userInterface a [[RuntimeVersionManagementUserInterface]] instance * that specifies how to handle user interactions * (displaying progress and handling corner cases) - * @param distributionManager the [[DistributionManager]] to use * @param engineReleaseProvider the provider of engine releases * @param runtimeReleaseProvider the provider of runtime releases - * @param componentConfig the runtime component configuration - * @param componentUpdaterFactory the runtime component updater factory */ class RuntimeVersionManager( environment: Environment, userInterface: RuntimeVersionManagementUserInterface, distributionManager: DistributionManager, + graalVersionManager: GraalVersionManager, temporaryDirectoryManager: TemporaryDirectoryManager, resourceManager: ResourceManager, engineReleaseProvider: ReleaseProvider[EngineRelease], runtimeReleaseProvider: GraalVMRuntimeReleaseProvider, - componentConfig: RuntimeComponentConfiguration, - componentUpdaterFactory: RuntimeComponentUpdaterFactory, implicit private val installerKind: InstallerKind ) { private val logger = Logger[RuntimeVersionManager] - private val os = OS.operatingSystem /** Tries to find a GraalVM runtime for the provided engine. * * Returns None if the runtime is missing. */ - def findGraalRuntime(engine: Engine): Option[GraalRuntime] = - findGraalRuntime(engine.manifest.runtimeVersion) + def findGraalRuntime(engine: Engine): Option[GraalRuntime] = { + Option(graalVersionManager.findGraalRuntime(engine)) + } /** Finds an installed GraalVM runtime with the given `version`. * * Returns None if that version is not installed. */ def findGraalRuntime(version: GraalVMVersion): Option[GraalRuntime] = { - val explicitPathOpt = this.environment.getEnvPath("ENSO_JVM_PATH") - val graalRuntimeOpt = explicitPathOpt - .map(path => { - val runtime = GraalRuntime(version, path) - runtime.ensureValid() - runtime - }) - .orElse { - val pathOpt = findGraalRuntimeOnSearchPath(version) - pathOpt.map { path => - // TODO [RW] for now an exception is thrown if the installation is - // corrupted, in #1052 offer to repair the broken installation - loadGraalRuntime(path).recoverWith { case e: Exception => - Failure( - UnrecognizedComponentError( - s"The runtime $version is already installed, but cannot be " + - s"loaded due to $e. Until the launcher gets an auto-repair " + - s"feature, please try reinstalling the runtime by " + - s"uninstalling all engines that use it and installing them " + - s"again, or manually removing `$path`", - e - ) - ) - }.get - } - } - graalRuntimeOpt match { - case Some(graalRuntime) => - logger.debug("Found GraalVM runtime [{}]", graalRuntime) - case None => - logger.debug("GraalVM runtime [{}] not found", version) - } - graalRuntimeOpt - } - - private def findGraalRuntimeOnSearchPath( - version: GraalVMVersion - ): Option[Path] = { - val name = graalRuntimeNameForVersion(version) - firstExisting(distributionManager.paths.runtimeSearchPaths.map(_ / name)) + Option(graalVersionManager.findGraalRuntime(version)); } /** Executes the provided action with a requested engine version. @@ -635,70 +590,13 @@ class RuntimeVersionManager( private def engineNameForVersion(version: SemVer): String = version.toString - /** Returns name of the directory containing the runtime of that version. - */ - private def graalRuntimeNameForVersion(version: GraalVMVersion): String = { - s"graalvm-ce-java${version.javaVersion}-${version.graalVersion}" - } - /** Loads the GraalVM runtime definition. */ private def loadGraalRuntime(path: Path): Try[GraalRuntime] = { - logger.debug("Loading Graal runtime [{}]", path) - val name = path.getFileName.toString - for { - version <- parseGraalRuntimeVersionString(name) - .toRight( - UnrecognizedComponentError(s"Invalid runtime component name `$name`.") - ) - .toTry - runtime = GraalRuntime(version, path) - _ <- runtime.ensureValid() - _ <- installRequiredRuntimeComponents(runtime).recover { - case NonFatal(error) => - val msg = translateError(error) - logger.warn( - "Failed to install required components on the existing [{}]. " + - "Some language features may be unavailable. {}", - runtime, - msg - ) - } - } yield runtime - } - - /** Provide human-readable error messages for OS-specific failures - * @param cause exception thrown when executing the process - * @return human-readable error message - */ - private def translateError(cause: Throwable): String = { - val msg = cause.getMessage - OS.operatingSystem match { - case OS.Linux => msg - case OS.MacOS => msg - case OS.Windows => - if (msg.contains("-1073741515")) { - "Required Microsoft Visual C++ installation is missing" - } else { - msg - } - } - } - - /** Gets the runtime version from its name. - */ - private def parseGraalRuntimeVersionString( - name: String - ): Option[GraalVMVersion] = { - val regex = """graalvm-ce-java(.+)-(.+)""".r - name match { - case regex(javaVersionString, graalVersionString) => - Some(GraalVMVersion(graalVersionString, javaVersionString)) - case _ => - logger.warn( - s"Unrecognized runtime name `$name`" - ) - None + try { + Success(graalVersionManager.loadGraalRuntime(path)) + } catch { + case e: UnrecognizedComponentError => Failure(e) } } @@ -800,26 +698,16 @@ class RuntimeVersionManager( try { logger.debug("Loading temporary runtime [{}]", runtimeTemporaryPath) - val temporaryRuntime = - loadGraalRuntime(runtimeTemporaryPath).recoverWith { error => - Failure( - InstallationError( - "Cannot load the installed runtime. The package may have " + - "been corrupted. Reverting installation", - error - ) + + loadGraalRuntime(runtimeTemporaryPath).recoverWith { error => + Failure( + InstallationError( + "Cannot load the installed runtime. The package may have " + + "been corrupted. Reverting installation", + error ) - }.get - logger.debug("Installing GraalVM components to [{}]", temporaryRuntime) - installRequiredRuntimeComponents(temporaryRuntime).recoverWith { - error => - Failure( - InstallationError( - "fatal: Cannot install the required runtime components", - error - ) - ) - }.get + ) + } val runtimePath = distributionManager.paths.runtimes / runtimeDirectoryName @@ -849,32 +737,6 @@ class RuntimeVersionManager( } } - /** Install components required for the specified runtime on the specified OS. - * - * @param runtime the GraalVM runtime - */ - private def installRequiredRuntimeComponents( - runtime: GraalRuntime - ): Try[Unit] = { - logger.debug("Installing GraalVM components [{}, {}]", runtime, os) - val cu = componentUpdaterFactory.build(runtime) - val requiredComponents = - componentConfig.getRequiredComponents(runtime.version, os) - - if (requiredComponents.isEmpty) Success(()) - else { - for { - installedComponents <- cu.list() - _ = logger.debug( - "Available GraalVM components: [{}]", - installedComponents - ) - missingComponents = requiredComponents.diff(installedComponents) - _ <- cu.install(missingComponents) - } yield () - } - } - private def engineDirectoryNameForVersion(version: SemVer): Path = Path.of(version.toString()) @@ -931,33 +793,6 @@ class RuntimeVersionManager( FileSystem.removeDirectory(temporaryPath) } - /** Logs on trace level all installed engines and runtimes. - * - * NOTE: Useful for debugging but should not be added to production code since it may - * cause unnecessary installations for different engine versions. - */ - def logAvailableComponentsForDebugging(): Unit = logger.whenTraceEnabled { - logger.trace("Discovering available components...") - val engines = for (engine <- listInstalledEngines()) yield { - val runtime = findGraalRuntime(engine) - val runtimeName = runtime - .map(_.toString) - .getOrElse("no runtime found") - val broken = if (engine.isMarkedBroken) " (broken)" else "" - s" - Enso ${engine.version}$broken [runtime: $runtimeName] " + - s"[location: ${MaskedPath(engine.path).applyMasking()}]" - } - - val runtimes = - for (runtime <- listInstalledGraalRuntimes()) - yield s" - $runtime [location: " + - s"${MaskedPath(runtime.path).applyMasking()}]" - - logger.trace( - s"Installed engines (${engines.length}):\n${engines.mkString("\n")}\n\n" + - s"Installed runtimes (${runtimes.length}):\n${runtimes.mkString("\n")}" - ) - } } /* Note [RuntimeVersionManager Concurrency Model] diff --git a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/UnchainedGraalVMComponentUpdater.scala b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/UnchainedGraalVMComponentUpdater.scala deleted file mode 100644 index 271ebf7584e..00000000000 --- a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/UnchainedGraalVMComponentUpdater.scala +++ /dev/null @@ -1,26 +0,0 @@ -package org.enso.runtimeversionmanager.components - -import scala.util.{Success, Try} - -/** A dummy component updater for [[GraalVMVersion.isUnchained unchained]] GraalVM. - * There is no `gu` utility in unchained GraalVM, so this updater does not do anything. - * It only lists the components that are known to be included in the unchained GraalVM. - */ -class UnchainedGraalVMComponentUpdater extends RuntimeComponentUpdater { - - /** There - * - * @return the list of installed runtime components - */ - override def list(): Try[Seq[GraalVMComponent]] = Success(Seq()) - - /** Install the provided runtime components. - * - * @param components the list of components to install - */ - override def install(components: Seq[GraalVMComponent]): Try[Unit] = { - throw new IllegalStateException( - "Cannot install components in unchained GraalVM" - ) - } -} diff --git a/lib/scala/runtime-version-manager/src/test/scala/org/enso/runtimeversionmanager/components/GraalVMComponentConfigurationSpec.scala b/lib/scala/runtime-version-manager/src/test/scala/org/enso/runtimeversionmanager/components/GraalVMComponentConfigurationSpec.scala deleted file mode 100644 index b5a00650fe6..00000000000 --- a/lib/scala/runtime-version-manager/src/test/scala/org/enso/runtimeversionmanager/components/GraalVMComponentConfigurationSpec.scala +++ /dev/null @@ -1,106 +0,0 @@ -package org.enso.runtimeversionmanager.components - -import org.enso.cli.OS -import org.scalatest.matchers.should.Matchers -import org.scalatest.wordspec.AnyWordSpec - -class GraalVMComponentConfigurationSpec extends AnyWordSpec with Matchers { - - "RuntimeComponentConfiguration" should { - - "return required components" in { - val conf = new GraalVMComponentConfiguration - val required = Seq(GraalVMComponent.python, GraalVMComponent.R) - val requiredAbove22 = required ++ Seq(GraalVMComponent.js) - - conf.getRequiredComponents( - GraalVMVersion("21.0.0.2", "11"), - OS.Linux - ) should contain theSameElementsAs required - - conf.getRequiredComponents( - GraalVMVersion("21.0.0.2", "11"), - OS.MacOS - ) should contain theSameElementsAs required - - conf.getRequiredComponents( - GraalVMVersion("21.0.0.2", "11"), - OS.Windows - ) should contain theSameElementsAs Seq() - - conf.getRequiredComponents( - GraalVMVersion("22.0.0.0", "11"), - OS.Linux - ) should contain theSameElementsAs requiredAbove22 - - conf.getRequiredComponents( - GraalVMVersion("22.3.1", "17"), - OS.MacOS - ) should contain theSameElementsAs requiredAbove22 - - conf.getRequiredComponents( - GraalVMVersion("22.3.1", "17"), - OS.Windows - ) should contain theSameElementsAs Seq( - GraalVMComponent.js - ) - - conf.getRequiredComponents( - GraalVMVersion("22.3.1", "17"), - OS.Linux - ) should contain theSameElementsAs Seq( - GraalVMComponent.js, - GraalVMComponent.python, - GraalVMComponent.R - ) - - conf.getRequiredComponents( - GraalVMVersion("20.0.0.0", "11"), - OS.Linux - ) should contain theSameElementsAs Seq() - - conf.getRequiredComponents( - GraalVMVersion("23.0.0", "17.0.7+7.1"), - OS.Linux - ) should contain theSameElementsAs Seq( - GraalVMComponent.js, - GraalVMComponent.python - ) - - conf.getRequiredComponents( - GraalVMVersion("23.0.0", "11"), - OS.Linux - ) should contain theSameElementsAs Seq( - GraalVMComponent.js, - GraalVMComponent.python - ) - - conf.getRequiredComponents( - GraalVMVersion("23.0.0", "17.0.7+7.1"), - OS.Windows - ) should contain theSameElementsAs Seq( - GraalVMComponent.js - ) - } - - "return no required components for Truffle unchained" in { - val conf = new GraalVMComponentConfiguration - val versions = Seq( - GraalVMVersion("23.0.0", "21"), - GraalVMVersion("23.0.1", "21"), - GraalVMVersion("23.0.0", "21.0.1"), - GraalVMVersion("23.0.1", "21.0.1"), - GraalVMVersion("23.0.0", "21.0.1+5.1"), - GraalVMVersion("23.0.1", "21.0.1+5.1"), - GraalVMVersion("23.1.0", "21") - ) - versions.forall(_.isUnchained) shouldBe true - versions.foreach(version => { - conf.getRequiredComponents( - version, - OS.Linux - ) shouldBe empty - }) - } - } -} diff --git a/lib/scala/runtime-version-manager/src/test/scala/org/enso/runtimeversionmanager/components/GraalVMComponentParserSpec.scala b/lib/scala/runtime-version-manager/src/test/scala/org/enso/runtimeversionmanager/components/GraalVMComponentParserSpec.scala deleted file mode 100644 index 52cb4390172..00000000000 --- a/lib/scala/runtime-version-manager/src/test/scala/org/enso/runtimeversionmanager/components/GraalVMComponentParserSpec.scala +++ /dev/null @@ -1,57 +0,0 @@ -package org.enso.runtimeversionmanager.components - -import org.scalatest.matchers.should.Matchers -import org.scalatest.wordspec.AnyWordSpec - -class GraalVMComponentParserSpec extends AnyWordSpec with Matchers { - - "RuntimeComponentUpdater" should { - - "parse list output" in { - val listOut = - """ - |ID : js - |Name : Graal.js - |Version : 21.0.0.2 - |GraalVM : n/a - |Stability: - - |Origin : - | - |ID : graalvm - |Name : GraalVM Core - |Version : 21.0.0.2 - |GraalVM : n/a - |Stability: - - |Origin : - | - |ID : R - |Name : FastR - |Version : 21.0.0.2 - |GraalVM : 21.0.0.2 - |Stability: Experimental - |Origin : https://github.com/oracle/fastr/releases/download/vm-21.0.0.2/r-installable-java11-linux-amd64-21.0.0.2.jar - | - |ID : llvm-toolchain - |Name : LLVM.org toolchain - |Version : 21.0.0.2 - |GraalVM : 21.0.0.2 - |Stability: Supported - |Origin : https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.0.0.2/llvm-toolchain-installable-java11-linux-amd64-21.0.0.2.jar - | - |ID : native-image - |Name : Native Image - |Version : 21.0.0.2 - |GraalVM : 21.0.0.2 - |Stability: Early adopter - |Origin : https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.0.0.2/native-image-installable-svm-java11-linux-amd64-21.0.0.2.jar - |""".stripMargin - - val expectedComponents = - Seq("js", "graalvm", "R", "llvm-toolchain", "native-image") - .map(GraalVMComponent(_)) - val components = - GraalVMComponentUpdater.ListOut.parse(listOut.linesIterator.toSeq) - components shouldEqual expectedComponents - } - } -} diff --git a/lib/scala/runtime-version-manager/src/test/scala/org/enso/runtimeversionmanager/components/GraalVMVersionSpec.scala b/lib/scala/runtime-version-manager/src/test/scala/org/enso/runtimeversionmanager/components/GraalVMVersionSpec.scala new file mode 100644 index 00000000000..dabcc5188b5 --- /dev/null +++ b/lib/scala/runtime-version-manager/src/test/scala/org/enso/runtimeversionmanager/components/GraalVMVersionSpec.scala @@ -0,0 +1,40 @@ +package org.enso.runtimeversionmanager.components + +import org.scalatest.matchers.should.Matchers +import org.scalatest.wordspec.AnyWordSpec + +class GraalVMVersionSpec extends AnyWordSpec with Matchers { + + "GraalVM Version" should { + "greater JDK version is considered newer" in { + val graalVersion = "24.0.0" + val ver1 = GraalVMVersion(graalVersion, "21.0.2") + val ver2 = GraalVMVersion(graalVersion, "17.0.7") + (ver1.compareTo(ver2) > 0) shouldBe true + } + + "If JDK version is same (semver), greater Graal version is newer" in { + val jdkVersion = "21.0.2" + val ver1 = GraalVMVersion("24.0.2", jdkVersion) + val ver2 = GraalVMVersion("24.0.0", jdkVersion) + (ver1.compareTo(ver2) > 0) shouldBe true + } + + "If JDK version is same (non semver), greater Graal version is newer" in { + val jdkVersion = "21" + val ver1 = GraalVMVersion("24.0.2", jdkVersion) + val ver2 = GraalVMVersion("24.0.0", jdkVersion) + (ver1.compareTo(ver2) > 0) shouldBe true + } + + "be correctly ordered" in { + val ver1 = GraalVMVersion("24.0.0", "21.0.2") + val ver2 = GraalVMVersion("23.1.2", "21.0.2") + val ver3 = GraalVMVersion("23.1.0", "21.0.1") + val ver4 = GraalVMVersion("23.0.0", "17.0.7") + val lst = List(ver4, ver2, ver3, ver1) + val sortedList = lst.sortWith((ver1, ver2) => ver1.compareTo(ver2) < 0) + sortedList shouldEqual List(ver4, ver3, ver2, ver1) + } + } +} diff --git a/lib/scala/semver/src/test/java/org/enso/semver/VersionsTest.java b/lib/scala/semver/src/test/java/org/enso/semver/VersionsTest.java index 188ba465e3b..0a865378db5 100644 --- a/lib/scala/semver/src/test/java/org/enso/semver/VersionsTest.java +++ b/lib/scala/semver/src/test/java/org/enso/semver/VersionsTest.java @@ -12,6 +12,8 @@ public class VersionsTest { assertTrue(SemVer.parse("0.1.1").isSuccess()); assertTrue(SemVer.parse("9999.0.0").isSuccess()); assertTrue(SemVer.parse("0.1").isFailure()); + assertTrue(SemVer.parse("21.0.2").isSuccess()); + assertTrue(SemVer.parse("17.0.7").isSuccess()); } @Test diff --git a/lib/scala/version-output/src/main/java/org/enso/version/BuildVersion.java b/lib/scala/version-output/src/main/java/org/enso/version/BuildVersion.java index a5d3b54f3ac..e9261bbcaaf 100644 --- a/lib/scala/version-output/src/main/java/org/enso/version/BuildVersion.java +++ b/lib/scala/version-output/src/main/java/org/enso/version/BuildVersion.java @@ -19,10 +19,23 @@ public class BuildVersion { return GeneratedVersion.scalacVersion(); } + /** + * Version of GraalVM, more specifically, version of the GraalVM and Truffle libraries used to + * build the engine. + */ public static String graalVersion() { return GeneratedVersion.graalVersion(); } + /** + * Version of Java (JDK) used to build the engine. + * + * @return + */ + public static String javaVersion() { + return GeneratedVersion.javaVersion(); + } + public static String currentEdition() { return GeneratedVersion.currentEdition(); } diff --git a/project/BuildInfo.scala b/project/BuildInfo.scala index 44c7fad93f1..4e84c96f1f4 100644 --- a/project/BuildInfo.scala +++ b/project/BuildInfo.scala @@ -18,6 +18,7 @@ object BuildInfo { * @param ensoVersion Enso version * @param scalacVersion Scala compiler version used in the project * @param graalVersion GraalVM version used in the project + * @param javaVersion Java language version used in the project. * @param currentEdition name of the edition associated with the Enso * version; this should be removed once #1831 is * implemented @@ -30,6 +31,7 @@ object BuildInfo { ensoVersion: String, scalacVersion: String, graalVersion: String, + javaVersion: String, currentEdition: String ): Seq[File] = { val gitInfo = getGitInformation(log).getOrElse(fallbackGitInformation) @@ -58,6 +60,10 @@ object BuildInfo { | return "${graalVersion}"; | } | + | static String javaVersion() { + | return "${javaVersion}"; + | } + | | static String currentEdition() { | return "${currentEdition}"; | } diff --git a/tools/legal-review/launcher/com.typesafe.akka.akka-http-core_2.13-10.2.10/copyright-ignore b/tools/legal-review/launcher/com.typesafe.akka.akka-http-core_2.13-10.2.10/copyright-ignore deleted file mode 100644 index ac3adb92c90..00000000000 --- a/tools/legal-review/launcher/com.typesafe.akka.akka-http-core_2.13-10.2.10/copyright-ignore +++ /dev/null @@ -1,8 +0,0 @@ -Copyright (C) 2015-2022 Lightbend Inc. -Copyright (C) 2016-2022 Lightbend Inc. -Copyright (C) 2017-2022 Lightbend Inc. -Copyright (C) 2018-2022 Lightbend Inc. -Copyright (C) 2019-2022 Lightbend Inc. -Copyright (C) 2020-2022 Lightbend Inc. -Copyright (C) 2021-2022 Lightbend Inc. -Copyright 2009-2020 Lightbend Inc. diff --git a/tools/legal-review/launcher/com.typesafe.akka.akka-http-core_2.13-10.2.10/copyright-keep b/tools/legal-review/launcher/com.typesafe.akka.akka-http-core_2.13-10.2.10/copyright-keep deleted file mode 100644 index 86256d61190..00000000000 --- a/tools/legal-review/launcher/com.typesafe.akka.akka-http-core_2.13-10.2.10/copyright-keep +++ /dev/null @@ -1,6 +0,0 @@ -Copyright (C) 2008-2017 Bjoern Hoehrmann -Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev -Copyright (C) 2009-2022 Lightbend Inc. -Copyright 2011 Mark Harrah, Eugene Yokota -Copyright 2014 Twitter, Inc. -Copyright 2015 Heiko Seeberger diff --git a/tools/legal-review/launcher/com.typesafe.akka.akka-http_2.13-10.2.10/copyright-ignore b/tools/legal-review/launcher/com.typesafe.akka.akka-http_2.13-10.2.10/copyright-ignore deleted file mode 100644 index aa3e5cce83b..00000000000 --- a/tools/legal-review/launcher/com.typesafe.akka.akka-http_2.13-10.2.10/copyright-ignore +++ /dev/null @@ -1,6 +0,0 @@ -Copyright (C) 2009-2020 Lightbend Inc. -Copyright (C) 2009-2022 Lightbend Inc. -Copyright (C) 2015-2022 Lightbend Inc. -Copyright (C) 2017-2022 Lightbend Inc. -Copyright (C) 2018-2022 Lightbend Inc. -Copyright (C) 2020-2022 Lightbend Inc. diff --git a/tools/legal-review/launcher/com.typesafe.akka.akka-http_2.13-10.2.10/copyright-keep b/tools/legal-review/launcher/com.typesafe.akka.akka-http_2.13-10.2.10/copyright-keep deleted file mode 100644 index e25cd2d998b..00000000000 --- a/tools/legal-review/launcher/com.typesafe.akka.akka-http_2.13-10.2.10/copyright-keep +++ /dev/null @@ -1 +0,0 @@ -Copyright (C) 2009-2020 Lightbend Inc. diff --git a/tools/legal-review/launcher/com.typesafe.akka.akka-parsing_2.13-10.2.10/copyright-ignore b/tools/legal-review/launcher/com.typesafe.akka.akka-parsing_2.13-10.2.10/copyright-ignore deleted file mode 100644 index 6da40a864fe..00000000000 --- a/tools/legal-review/launcher/com.typesafe.akka.akka-parsing_2.13-10.2.10/copyright-ignore +++ /dev/null @@ -1,2 +0,0 @@ -Copyright (C) 2019-2022 Lightbend Inc. -Copyright (c) 2013-14 Miles Sabin diff --git a/tools/legal-review/launcher/com.typesafe.akka.akka-parsing_2.13-10.2.10/copyright-keep b/tools/legal-review/launcher/com.typesafe.akka.akka-parsing_2.13-10.2.10/copyright-keep deleted file mode 100644 index 141594ba9e2..00000000000 --- a/tools/legal-review/launcher/com.typesafe.akka.akka-parsing_2.13-10.2.10/copyright-keep +++ /dev/null @@ -1,4 +0,0 @@ -Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev -Copyright (C) 2009-2022 Lightbend Inc. -Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (base64 @ miginfocom . com) -Copyright (c) 2011-13 Miles Sabin diff --git a/tools/legal-review/launcher/report-state b/tools/legal-review/launcher/report-state index 2617247d9c3..a02587526a0 100644 --- a/tools/legal-review/launcher/report-state +++ b/tools/legal-review/launcher/report-state @@ -1,3 +1,3 @@ -5BE1C47CDA76AF7E6C42089993BEA2B8DB544C1752AE5D8055BF2B4E713B20EA -E92B79099FF706DC1F50287D428322268954285BD62F19B0A70456E3356AE1D1 +BBB2B5E440C388A022983CB2C0B9B4BA68D04B97FC07E4C8E142952448437BE0 +CA8B1BB2992E828BA958FD6CFC0076B213170FCD454406131407ED0340EC7F2F 0