Separate ComponentManager from Launcher (#1248)

This commit is contained in:
Radosław Waśko 2020-10-30 12:31:31 +01:00 committed by GitHub
parent 36694e2496
commit 35efd8ea55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
157 changed files with 1538 additions and 1150 deletions

View File

@ -178,6 +178,8 @@ lazy val enso = (project in file("."))
runtime,
searcher,
launcher,
`runtime-version-manager`,
`runtime-version-manager-test`,
syntax.jvm,
testkit
)
@ -1131,9 +1133,45 @@ lazy val launcher = project
parallelExecution in Test := false
)
.dependsOn(cli)
.dependsOn(`runtime-version-manager`)
.dependsOn(`version-output`)
.dependsOn(pkg)
.dependsOn(`logging-service`)
.dependsOn(`runtime-version-manager-test` % Test)
lazy val `runtime-version-manager` = project
.in(file("lib/scala/runtime-version-manager"))
.configs(Test)
.settings(
resolvers += Resolver.bintrayRepo("gn0s1s", "releases"),
libraryDependencies ++= Seq(
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion,
"org.typelevel" %% "cats-core" % catsVersion,
"nl.gn0s1s" %% "bump" % bumpVersion,
"org.apache.commons" % "commons-compress" % commonsCompressVersion,
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
akkaHttp,
akkaSLF4J
)
)
.dependsOn(pkg)
.dependsOn(`logging-service`)
.dependsOn(cli)
.dependsOn(`version-output`)
lazy val `runtime-version-manager-test` = project
.in(file("lib/scala/runtime-version-manager-test"))
.configs(Test)
.settings(
libraryDependencies ++= Seq(
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion,
"org.scalatest" %% "scalatest" % scalatestVersion,
"commons-io" % "commons-io" % commonsIoVersion
)
)
.settings(parallelExecution in Test := false)
.dependsOn(`runtime-version-manager`)
.dependsOn(`logging-service`)
val `std-lib-root` = file("distribution/std-lib/")
val `std-lib-polyglot-root` = `std-lib-root` / "Base" / "polyglot" / "java"

View File

@ -149,11 +149,11 @@ class names are made up):
"group": "org.enso.launcher.Main",
"message": "Failed to load a configuration file.",
"exception": {
"name": "org.enso.launcher.config.ConfigurationLoaderFailure",
"name": "org.enso.componentmanager.config.ConfigurationLoaderFailure",
"message": "Configuration file does not exist.",
"trace": [
{
"element": "org.enso.launcher.config.ConfigurationLoader.load",
"element": "org.enso.componentmanager.config.ConfigurationLoader.load",
"location": "ConfigurationLoader.scala:123"
},
{

View File

@ -0,0 +1,28 @@
package org.enso.launcher
import org.enso.runtimeversionmanager.components.RuntimeVersionManager
import org.enso.runtimeversionmanager.releases.graalvm.GraalCEReleaseProvider
import org.enso.launcher.cli.{
CLIRuntimeVersionManagementUserInterface,
GlobalCLIOptions
}
import org.enso.launcher.distribution.DefaultManagers._
import org.enso.launcher.releases.EnsoRepository
object DefaultComponentManager {
def make(
globalCLIOptions: GlobalCLIOptions,
alwaysInstallMissing: Boolean
): RuntimeVersionManager =
new RuntimeVersionManager(
new CLIRuntimeVersionManagementUserInterface(
globalCLIOptions,
alwaysInstallMissing
),
distributionManager,
temporaryDirectoryManager,
DefaultResourceManager,
EnsoRepository.defaultEngineReleaseProvider,
GraalCEReleaseProvider
)
}

View File

@ -5,19 +5,23 @@ import java.nio.file.Path
import com.typesafe.scalalogging.Logger
import io.circe.Json
import nl.gn0s1s.bump.SemVer
import org.enso.launcher.cli.{GlobalCLIOptions, LauncherLogging, Main}
import org.enso.launcher.components.ComponentsManager
import org.enso.launcher.components.runner.{
import org.enso.runtimeversionmanager.CurrentVersion
import org.enso.runtimeversionmanager.config.{
DefaultVersion,
GlobalConfigurationManager
}
import org.enso.runtimeversionmanager.runner.{
JVMSettings,
LanguageServerOptions,
Runner,
WhichEngine
}
import org.enso.launcher.config.{DefaultVersion, GlobalConfigurationManager}
import org.enso.launcher.cli.{GlobalCLIOptions, LauncherLogging, Main}
import org.enso.launcher.components.LauncherRunner
import org.enso.launcher.distribution.DefaultManagers._
import org.enso.launcher.distribution.LauncherEnvironment
import org.enso.launcher.installation.DistributionInstaller.BundleAction
import org.enso.launcher.installation.{
DistributionInstaller,
DistributionManager,
DistributionUninstaller
}
import org.enso.launcher.project.ProjectManager
@ -33,16 +37,17 @@ import org.enso.version.{VersionDescription, VersionDescriptionParameter}
case class Launcher(cliOptions: GlobalCLIOptions) {
private val logger = Logger[Launcher]
private lazy val componentsManager = ComponentsManager.default(cliOptions)
private lazy val componentsManager =
DefaultComponentManager.make(cliOptions, alwaysInstallMissing = false)
private lazy val configurationManager =
new GlobalConfigurationManager(componentsManager, DistributionManager)
new GlobalConfigurationManager(componentsManager, distributionManager)
private lazy val projectManager = new ProjectManager(configurationManager)
private lazy val runner =
new Runner(
new LauncherRunner(
projectManager,
configurationManager,
componentsManager,
Environment,
LauncherEnvironment,
LauncherLogging.loggingServiceEndpoint()
)
private lazy val upgrader = LauncherUpgrader.default(cliOptions)
@ -111,7 +116,7 @@ case class Launcher(cliOptions: GlobalCLIOptions) {
/** Prints a list of installed runtimes.
*/
def listRuntimes(): Int = {
for (runtime <- componentsManager.listInstalledRuntimes()) {
for (runtime <- componentsManager.listInstalledGraalRuntimes()) {
val engines = componentsManager.findEnginesUsingRuntime(runtime)
val usedBy = {
val plural =
@ -128,7 +133,7 @@ case class Launcher(cliOptions: GlobalCLIOptions) {
*/
def listSummary(): Int = {
for (engine <- componentsManager.listInstalledEngines()) {
val runtime = componentsManager.findRuntime(engine)
val runtime = componentsManager.findGraalRuntime(engine)
val runtimeName = runtime
.map(_.toString)
.getOrElse("no runtime found for this distribution")
@ -143,11 +148,13 @@ case class Launcher(cliOptions: GlobalCLIOptions) {
* Also installs the required runtime if it wasn't already installed.
*/
def installEngine(version: SemVer): Int = {
val existing = componentsManager.findEngine(version)
val installingComponentManager =
DefaultComponentManager.make(cliOptions, alwaysInstallMissing = true)
val existing = installingComponentManager.findEngine(version)
if (existing.isDefined) {
InfoLogger.info(s"Engine $version is already installed.")
} else {
componentsManager.findOrInstallEngine(version, complain = false)
installingComponentManager.findOrInstallEngine(version)
}
0
}
@ -168,7 +175,7 @@ case class Launcher(cliOptions: GlobalCLIOptions) {
*/
def uninstallEngine(version: SemVer): Int = {
componentsManager.uninstallEngine(version)
DistributionManager.tryCleaningUnusedLockfiles()
distributionManager.tryCleaningUnusedLockfiles()
0
}
@ -261,6 +268,7 @@ case class Launcher(cliOptions: GlobalCLIOptions) {
*/
def runLanguageServer(
options: LanguageServerOptions,
contentRoot: Path,
versionOverride: Option[SemVer],
logLevel: LogLevel,
useSystemJVM: Boolean,
@ -272,6 +280,7 @@ case class Launcher(cliOptions: GlobalCLIOptions) {
runner
.languageServer(
options,
contentRoot,
versionOverride,
logLevel,
additionalArguments
@ -469,7 +478,7 @@ object Launcher {
/** Checks if the launcher is running in portable mode and exits if it is not.
*/
def ensurePortable(): Unit = {
if (!DistributionManager.isRunningPortable) {
if (!distributionManager.isRunningPortable) {
Logger[Launcher].error(
"`--ensure-portable` is set, but the launcher is not running in " +
"portable mode. Terminating."

View File

@ -0,0 +1,74 @@
package org.enso.launcher.cli
import com.typesafe.scalalogging.Logger
import nl.gn0s1s.bump.SemVer
import org.enso.cli.{CLIOutput, ProgressBar, TaskProgress}
import org.enso.runtimeversionmanager.components.{
GraalVMVersion,
RuntimeVersionManagementUserInterface
}
import org.enso.launcher.InfoLogger
/** [[RuntimeVersionManagementUserInterface]] that reports information and progress
* to the command line.
*
* It may ask interactive questions to the user, depending on [[cliOptions]].
*/
class CLIRuntimeVersionManagementUserInterface(
cliOptions: GlobalCLIOptions,
alwaysInstallMissing: Boolean
) extends RuntimeVersionManagementUserInterface {
/** @inheritdoc */
override def trackProgress(task: TaskProgress[_]): Unit =
if (cliOptions.hideProgress) ()
else ProgressBar.waitWithProgress(task)
private val logger = Logger[CLIRuntimeVersionManagementUserInterface]
/** @inheritdoc */
override def shouldInstallBrokenEngine(version: SemVer): Boolean =
if (cliOptions.autoConfirm) {
logger.warn(
s"The engine release $version is marked as broken and it should " +
s"not be used. Since `auto-confirm` is set, the installation will " +
s"continue, but you may want to reconsider changing versions to a " +
s"stable release."
)
true
} else {
logger.warn(
s"The engine release $version is marked as broken and it should " +
s"not be used."
)
CLIOutput.askConfirmation(
"Are you sure you still want to continue installing this version " +
"despite the warning?"
)
}
/** @inheritdoc */
override def shouldInstallMissingEngine(version: SemVer): Boolean = {
def complainAndAsk(): Boolean = {
logger.warn(s"Engine $version is missing.")
cliOptions.autoConfirm || CLIOutput.askConfirmation(
"Do you want to install the missing engine?",
yesDefault = true
)
}
alwaysInstallMissing || complainAndAsk()
}
/** @inheritdoc */
override def shouldInstallMissingRuntime(version: GraalVMVersion): Boolean = {
logger.warn(s"Required runtime $version is missing.")
cliOptions.autoConfirm || CLIOutput.askConfirmation(
"Do you want to install the missing runtime?",
yesDefault = true
)
}
/** @inheritdoc */
override def logInfo(message: => String): Unit = InfoLogger.info(message)
}

View File

@ -7,11 +7,12 @@ import cats.implicits._
import nl.gn0s1s.bump.SemVer
import org.enso.cli.arguments.Opts
import org.enso.cli.arguments.Opts.implicits._
import org.enso.launcher.FileSystem.PathSyntax
import org.enso.launcher.cli.Arguments._
import org.enso.launcher.releases.EnsoRepository
import org.enso.runtimeversionmanager.{CurrentVersion, FileSystem, OS}
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.cli.Arguments._
import org.enso.launcher.distribution.LauncherEnvironment
import org.enso.launcher.upgrade.LauncherUpgrader
import org.enso.launcher.{CurrentVersion, Environment, FileSystem, OS}
import org.enso.launcher.releases.EnsoRepository
/** Implements internal options that the launcher may use when running another
* instance of itself.
@ -209,7 +210,7 @@ object InternalOpts {
}
emulateLocation.foreach { location =>
Environment.internalOverrideExecutableLocation(location)
LauncherEnvironment.internalOverrideExecutableLocation(location)
}
if (waitForAssets) {

View File

@ -10,16 +10,14 @@ import nl.gn0s1s.bump.SemVer
import org.enso.cli._
import org.enso.cli.arguments.Opts.implicits._
import org.enso.cli.arguments._
import org.enso.launcher.Launcher
import org.enso.launcher.cli.Arguments._
import org.enso.launcher.components.runner.LanguageServerOptions
import org.enso.launcher.config.DefaultVersion
import org.enso.runtimeversionmanager.cli.Arguments._
import org.enso.runtimeversionmanager.config.DefaultVersion
import org.enso.runtimeversionmanager.runner.LanguageServerOptions
import org.enso.launcher.distribution.DefaultManagers._
import org.enso.launcher.installation.DistributionInstaller
import org.enso.launcher.installation.DistributionInstaller.BundleAction
import org.enso.launcher.installation.{
DistributionInstaller,
DistributionManager
}
import org.enso.launcher.locking.DefaultResourceManager
import org.enso.launcher.upgrade.LauncherUpgrader
import org.enso.launcher.{cli, Launcher}
import org.enso.loggingservice.LogLevel
/** Defines the CLI commands and options for the program.
@ -225,11 +223,11 @@ object LauncherApplication {
Launcher(config).runLanguageServer(
options = LanguageServerOptions(
rootId = rootId,
path = path,
interface = interface,
rpcPort = rpcPort,
dataPort = dataPort
),
contentRoot = path,
versionOverride = versionOverride,
useSystemJVM = systemJVMOverride,
jvmOpts = jvmOpts,
@ -320,7 +318,7 @@ object LauncherApplication {
) {
val version = Opts.optionalArgument[SemVer]("VERSION")
version map { version => (config: Config) =>
DistributionManager.tryCleaningTemporaryDirectory()
temporaryDirectoryManager.tryCleaningTemporaryDirectory()
version match {
case Some(value) =>
Launcher(config).installEngine(value)
@ -401,7 +399,7 @@ object LauncherApplication {
"unexpected files."
) {
Opts.pure(()) map { (_: Unit) => (config: Config) =>
DistributionManager.tryCleaningTemporaryDirectory()
temporaryDirectoryManager.tryCleaningTemporaryDirectory()
Launcher(config).uninstallDistribution()
}
}
@ -549,7 +547,7 @@ object LauncherApplication {
Launcher.ensurePortable()
}
val globalCLIOptions = GlobalCLIOptions(
val globalCLIOptions = cli.GlobalCLIOptions(
autoConfirm = autoConfirm,
hideProgress = hideProgress,
useJSON = useJSON,
@ -559,6 +557,7 @@ object LauncherApplication {
)
internalOptsCallback(globalCLIOptions)
LauncherUpgrader.setCLIOptions(globalCLIOptions)
LauncherLogging.setup(logLevel, connectLogger, globalCLIOptions)
initializeApp()

View File

@ -2,7 +2,7 @@ package org.enso.launcher.cli
import akka.http.scaladsl.model.Uri
import com.typesafe.scalalogging.Logger
import org.enso.launcher.installation.DistributionManager
import org.enso.launcher.distribution.DefaultManagers
import org.enso.loggingservice.printers.{
FileOutputPrinter,
Printer,
@ -11,11 +11,11 @@ import org.enso.loggingservice.printers.{
}
import org.enso.loggingservice.{LogLevel, LoggerMode, LoggingServiceManager}
import scala.util.control.NonFatal
import scala.util.{Failure, Success}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.DurationInt
import scala.concurrent.{Await, Future, Promise}
import scala.util.control.NonFatal
import scala.util.{Failure, Success}
/** Manages setting up the logging service within the launcher.
*/
@ -115,7 +115,9 @@ object LauncherLogging {
def createPrinters() =
try {
val filePrinter =
FileOutputPrinter.create(DistributionManager.paths.logs)
FileOutputPrinter.create(
DefaultManagers.distributionManager.paths.logs
)
Seq(
stderrPrinter(globalCLIOptions, printExceptionsInStderr),
filePrinter

View File

@ -2,7 +2,7 @@ package org.enso.launcher.cli
import com.typesafe.scalalogging.Logger
import org.enso.cli.CLIOutput
import org.enso.launcher.locking.DefaultResourceManager
import org.enso.launcher.distribution.DefaultManagers
import org.enso.launcher.upgrade.LauncherUpgrader
/** Defines the entry point for the launcher.
@ -56,7 +56,7 @@ object Main {
*/
def exit(exitCode: Int): Nothing = {
LauncherLogging.tearDown()
DefaultResourceManager.releaseMainLock()
DefaultManagers.DefaultResourceManager.releaseMainLock()
sys.exit(exitCode)
}
}

View File

@ -4,7 +4,8 @@ import java.nio.file.{Files, Path}
import org.enso.cli.arguments
import org.enso.cli.arguments.CommandHelp
import org.enso.launcher.{Environment, FileSystem}
import org.enso.runtimeversionmanager.{Environment, FileSystem}
import org.enso.launcher.distribution.LauncherEnvironment
import scala.sys.process._
import scala.util.Try
@ -137,6 +138,6 @@ class PluginManager(env: Environment) extends arguments.PluginManager {
}
/** Default implementation of the [[PluginManager]] using the default
* [[Environment]].
* [[LauncherEnvironment]].
*/
object PluginManager extends PluginManager(Environment)
object PluginManager extends PluginManager(LauncherEnvironment)

View File

@ -0,0 +1,193 @@
package org.enso.launcher.components
import java.nio.file.{Files, Path}
import akka.http.scaladsl.model.Uri
import nl.gn0s1s.bump.SemVer
import org.enso.runtimeversionmanager.Environment
import org.enso.runtimeversionmanager.components.RuntimeVersionManager
import org.enso.runtimeversionmanager.config.GlobalConfigurationManager
import org.enso.runtimeversionmanager.runner.{
LanguageServerOptions,
RunSettings,
Runner,
RunnerError,
WhichEngine
}
import org.enso.launcher.project.ProjectManager
import org.enso.loggingservice.LogLevel
import scala.concurrent.Future
import scala.util.Try
/** Extends the [[Runner]] with launcher specific logic for project discovery.
*/
class LauncherRunner(
projectManager: ProjectManager,
configurationManager: GlobalConfigurationManager,
componentsManager: RuntimeVersionManager,
environment: Environment,
loggerConnection: Future[Option[Uri]]
) extends Runner(
componentsManager,
environment,
loggerConnection
) {
/** Creates [[RunSettings]] for launching the REPL.
*
* See [[org.enso.launcher.Launcher.runRepl]] for more details.
*/
def repl(
projectPath: Option[Path],
versionOverride: Option[SemVer],
logLevel: LogLevel,
additionalArguments: Seq[String]
): Try[RunSettings] =
Try {
val inProject = projectPath match {
case Some(value) =>
Some(projectManager.loadProject(value).get)
case None =>
projectManager.findProject(currentWorkingDirectory).get
}
val version =
versionOverride.getOrElse {
inProject
.map(_.version)
.getOrElse(configurationManager.defaultVersion)
}
val arguments = inProject match {
case Some(project) =>
val projectPackagePath =
project.path.toAbsolutePath.normalize.toString
Seq("--repl", "--in-project", projectPackagePath)
case None =>
Seq("--repl")
}
RunSettings(
version,
arguments ++ Seq("--log-level", logLevel.toString)
++ additionalArguments,
connectLoggerIfAvailable = true
)
}
/** Creates [[RunSettings]] for running Enso projects or scripts.
*
* See [[org.enso.launcher.Launcher.runRun]] for more details.
*/
def run(
path: Option[Path],
versionOverride: Option[SemVer],
logLevel: LogLevel,
additionalArguments: Seq[String]
): Try[RunSettings] =
Try {
val actualPath = path
.getOrElse {
projectManager
.findProject(currentWorkingDirectory)
.get
.getOrElse {
throw RunnerError(
"The current directory is not inside any project. `enso run` " +
"should either get a path to a project or script to run, or " +
"be run inside of a project to run that project."
)
}
.path
}
.toAbsolutePath
.normalize()
if (!Files.exists(actualPath)) {
throw RunnerError(s"$actualPath does not exist")
}
val projectMode = Files.isDirectory(actualPath)
val project =
if (projectMode) Some(projectManager.loadProject(actualPath).get)
else projectManager.findProject(actualPath).get
val version = versionOverride
.orElse(project.map(_.version))
.getOrElse(configurationManager.defaultVersion)
val arguments =
if (projectMode) Seq("--run", actualPath.toString)
else
project match {
case Some(project) =>
Seq(
"--run",
actualPath.toString,
"--in-project",
project.path.toAbsolutePath.normalize().toString
)
case None =>
Seq("--run", actualPath.toString)
}
RunSettings(
version,
arguments ++ Seq("--log-level", logLevel.toString)
++ additionalArguments,
connectLoggerIfAvailable = true
)
}
/** Creates [[RunSettings]] for launching the Language Server.
*
* See [[org.enso.launcher.Launcher.runLanguageServer]] for more details.
*/
def languageServer(
options: LanguageServerOptions,
contentRootPath: Path,
versionOverride: Option[SemVer],
logLevel: LogLevel,
additionalArguments: Seq[String]
): Try[RunSettings] =
for {
project <- projectManager.loadProject(contentRootPath)
runSettings <- startLanguageServer(
options,
project,
versionOverride,
logLevel,
additionalArguments
)
} yield runSettings
/** Creates [[RunSettings]] for querying the currently selected engine
* version.
*
* If the current working directory is inside of a project, the engine
* associated with the project is queried, otherwise the default engine is
* queried.
*
* @param useJSON if set to true, the returned [[RunSettings]] will request
* the version in JSON format, otherwise human readable text
* format will be used
* @return the [[RunSettings]] and a [[WhichEngine]] indicating if the used
* engine was from a project (true) or the default one (false)
*/
def version(useJSON: Boolean): Try[(RunSettings, WhichEngine)] = {
for {
project <- projectManager.findProject(currentWorkingDirectory)
} yield {
val version =
project.map(_.version).getOrElse(configurationManager.defaultVersion)
val arguments =
Seq("--version") ++ (if (useJSON) Seq("--json") else Seq())
val whichEngine =
project match {
case Some(value) => WhichEngine.FromProject(value.name)
case None => WhichEngine.Default
}
(
RunSettings(version, arguments, connectLoggerIfAvailable = false),
whichEngine
)
}
}
}

View File

@ -0,0 +1,33 @@
package org.enso.launcher.distribution
import java.nio.file.Path
import org.enso.runtimeversionmanager.distribution.{
PortableDistributionManager,
TemporaryDirectoryManager
}
import org.enso.runtimeversionmanager.locking.{FileLockManager, ResourceManager}
/** Gathers default managers used in the launcher. */
object DefaultManagers {
/** Default distribution manager that is capable of detecting portable mode.
*/
val distributionManager = new PortableDistributionManager(LauncherEnvironment)
/** Default [[FileLockManager]] storing lock files in a directory defined by
* the distribution manager.
*/
object DefaultFileLockManager extends FileLockManager {
/** @inheritdoc */
override def locksRoot: Path = distributionManager.paths.locks
}
/** Default [[ResourceManager]] using the [[DefaultFileLockManager]]. */
object DefaultResourceManager extends ResourceManager(DefaultFileLockManager)
/** Default [[TemporaryDirectoryManager]]. */
val temporaryDirectoryManager =
new TemporaryDirectoryManager(distributionManager, DefaultResourceManager)
}

View File

@ -0,0 +1,37 @@
package org.enso.launcher.distribution
import java.nio.file.Path
import com.typesafe.scalalogging.Logger
import org.enso.runtimeversionmanager.Environment
/** Default [[Environment]] to use in the launcher.
*
* In non-release mode, it allows internal test scripts to override the
* executable location.
*/
object LauncherEnvironment extends Environment {
/** @inheritdoc */
override def getPathToRunningExecutable: Path =
executablePathOverride.getOrElse(super.getPathToRunningExecutable)
private var executablePathOverride: Option[Path] = None
/** Overrides the return value of [[getPathToRunningExecutable]] with the
* provided path.
*
* Internal method used for testing. It should be called as early as
* possible, before [[getPathToRunningExecutable]] is called.
*/
def internalOverrideExecutableLocation(newLocation: Path): Unit =
if (buildinfo.Info.isRelease) {
throw new IllegalStateException(
"Internal testing function internalOverrideExecutableLocation used " +
"in a release build."
)
} else {
Logger("TEST").debug(s"Overriding location to $newLocation.")
executablePathOverride = Some(newLocation)
}
}

View File

@ -4,16 +4,19 @@ import java.nio.file.{Files, Path}
import com.typesafe.scalalogging.Logger
import org.enso.cli.CLIOutput
import org.enso.launcher.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.config.GlobalConfigurationManager
import org.enso.runtimeversionmanager.distribution.PortableDistributionManager
import org.enso.runtimeversionmanager.locking.ResourceManager
import org.enso.runtimeversionmanager.{FileSystem, OS}
import org.enso.launcher.InfoLogger
import org.enso.launcher.cli.{GlobalCLIOptions, InternalOpts, Main}
import org.enso.launcher.config.GlobalConfigurationManager
import org.enso.launcher.distribution.DefaultManagers
import org.enso.launcher.installation.DistributionInstaller.{
BundleAction,
IgnoreBundles,
MoveBundles
}
import org.enso.launcher.locking.{DefaultResourceManager, ResourceManager}
import org.enso.launcher.{FileSystem, InfoLogger, OS}
import scala.util.control.NonFatal
@ -32,7 +35,7 @@ import scala.util.control.NonFatal
* otherwise explicitly asks the user
*/
class DistributionInstaller(
manager: DistributionManager,
manager: PortableDistributionManager,
resourceManager: ResourceManager,
autoConfirm: Boolean,
removeOldLauncher: Boolean,
@ -411,8 +414,8 @@ object DistributionInstaller {
bundleActionOption: Option[BundleAction]
): DistributionInstaller =
new DistributionInstaller(
DistributionManager,
DefaultResourceManager,
DefaultManagers.distributionManager,
DefaultManagers.DefaultResourceManager,
globalCLIOptions.autoConfirm,
removeOldLauncher = removeOldLauncher,
bundleActionOption = bundleActionOption

View File

@ -5,16 +5,19 @@ import java.nio.file.{Files, Path}
import com.typesafe.scalalogging.Logger
import org.apache.commons.io.FileUtils
import org.enso.cli.CLIOutput
import org.enso.launcher.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.config.GlobalConfigurationManager
import org.enso.runtimeversionmanager.distribution.PortableDistributionManager
import org.enso.runtimeversionmanager.locking.ResourceManager
import org.enso.runtimeversionmanager.{FileSystem, OS}
import org.enso.launcher.InfoLogger
import org.enso.launcher.cli.{
GlobalCLIOptions,
InternalOpts,
LauncherLogging,
Main
}
import org.enso.launcher.config.GlobalConfigurationManager
import org.enso.launcher.locking.{DefaultResourceManager, ResourceManager}
import org.enso.launcher.{FileSystem, InfoLogger, OS}
import org.enso.launcher.distribution.DefaultManagers
import scala.util.control.NonFatal
@ -24,7 +27,7 @@ import scala.util.control.NonFatal
* the distribution that will be uninstalled
*/
class DistributionUninstaller(
manager: DistributionManager,
manager: PortableDistributionManager,
resourceManager: ResourceManager,
globalCLIOptions: GlobalCLIOptions
) {
@ -345,8 +348,8 @@ object DistributionUninstaller {
*/
def default(globalCLIOptions: GlobalCLIOptions): DistributionUninstaller =
new DistributionUninstaller(
DistributionManager,
DefaultResourceManager,
DefaultManagers.distributionManager,
DefaultManagers.DefaultResourceManager,
globalCLIOptions
)
}

View File

@ -1,14 +0,0 @@
package org.enso.launcher.locking
import java.nio.file.Path
import org.enso.launcher.installation.DistributionManager
/** Default [[FileLockManager]] storing lock files in a directory defined by the
* [[DistributionManager]].
*/
object DefaultFileLockManager extends FileLockManager {
/** @inheritdoc
*/
override def locksRoot: Path = DistributionManager.paths.locks
}

View File

@ -1,5 +0,0 @@
package org.enso.launcher.locking
/** Default [[ResourceManager]] using the [[DefaultFileLockManager]].
*/
object DefaultResourceManager extends ResourceManager(DefaultFileLockManager)

View File

@ -2,7 +2,8 @@ package org.enso.launcher.project
import java.nio.file.Path
import org.enso.launcher.config.GlobalConfigurationManager
import org.enso.runtimeversionmanager.config.GlobalConfigurationManager
import org.enso.runtimeversionmanager.runner.Project
import org.enso.pkg.PackageManager
import scala.util.{Failure, Try}

View File

@ -3,16 +3,24 @@ package org.enso.launcher.releases
import java.nio.file.Path
import com.typesafe.scalalogging.Logger
import org.enso.launcher.http.URIBuilder
import org.enso.launcher.releases.engine.{EngineRelease, EngineReleaseProvider}
import org.enso.runtimeversionmanager.http.URIBuilder
import org.enso.runtimeversionmanager.releases.engine.{
EngineRelease,
EngineReleaseProvider
}
import org.enso.runtimeversionmanager.releases.github.GithubReleaseProvider
import org.enso.runtimeversionmanager.releases.testing.FakeReleaseProvider
import org.enso.runtimeversionmanager.releases.{
ReleaseProvider,
SimpleReleaseProvider
}
import org.enso.launcher.distribution.DefaultManagers
import org.enso.launcher.releases.fallback.SimpleReleaseProviderWithFallback
import org.enso.launcher.releases.fallback.staticwebsite.StaticWebsiteFallbackReleaseProvider
import org.enso.launcher.releases.github.GithubReleaseProvider
import org.enso.launcher.releases.launcher.{
LauncherRelease,
LauncherReleaseProvider
}
import org.enso.launcher.releases.testing.FakeReleaseProvider
/** Represents the default Enso repository providing releases for the engine and
* the launcher.
@ -95,6 +103,8 @@ object EnsoRepository {
): SimpleReleaseProvider =
FakeReleaseProvider(
fakeRepositoryRoot,
shouldWaitForAssets = shouldWaitForAssets
lockManagerForAssets =
if (shouldWaitForAssets) Some(DefaultManagers.DefaultFileLockManager)
else None
)
}

View File

@ -1,6 +1,6 @@
package org.enso.launcher.releases.fallback
import org.enso.launcher.releases.SimpleReleaseProvider
import org.enso.runtimeversionmanager.releases.SimpleReleaseProvider
/** A fallback [[SimpleReleaseProvider]].
*

View File

@ -1,6 +1,6 @@
package org.enso.launcher.releases.fallback
import org.enso.launcher.releases.{Release, SimpleReleaseProvider}
import org.enso.runtimeversionmanager.releases.{Release, SimpleReleaseProvider}
import scala.util.{Failure, Try}

View File

@ -3,7 +3,7 @@ package org.enso.launcher.releases.fallback.staticwebsite
import java.nio.file.Path
import org.enso.cli.TaskProgress
import org.enso.launcher.releases.Asset
import org.enso.runtimeversionmanager.releases.Asset
/** An [[Asset]] provided by [[FallbackRelease]].
*

View File

@ -1,6 +1,6 @@
package org.enso.launcher.releases.fallback.staticwebsite
import org.enso.launcher.releases.{Asset, Release}
import org.enso.runtimeversionmanager.releases.{Asset, Release}
/** A [[Release]] provided by the [[FileStorageFallbackReleaseProvider]].
*

View File

@ -1,7 +1,10 @@
package org.enso.launcher.releases.fallback.staticwebsite
import org.enso.launcher.releases.fallback.FallbackReleaseProvider
import org.enso.launcher.releases.{Release, ReleaseProviderException}
import org.enso.runtimeversionmanager.releases.{
Release,
ReleaseProviderException
}
import scala.util.control.NonFatal
import scala.util.{Failure, Success, Try}

View File

@ -3,7 +3,11 @@ package org.enso.launcher.releases.fallback.staticwebsite
import java.nio.file.Path
import org.enso.cli.TaskProgress
import org.enso.launcher.http.{HTTPDownload, HTTPRequestBuilder, URIBuilder}
import org.enso.runtimeversionmanager.http.{
HTTPDownload,
HTTPRequestBuilder,
URIBuilder
}
/** Provides [[FileStorage]] backed by a static HTTPS website.
*

View File

@ -1,7 +1,7 @@
package org.enso.launcher.releases.fallback.staticwebsite
import org.enso.launcher.http.URIBuilder
import org.enso.launcher.releases.Release
import org.enso.runtimeversionmanager.http.URIBuilder
import org.enso.runtimeversionmanager.releases.Release
import org.enso.launcher.releases.fallback.FallbackReleaseProvider
import scala.util.Try

View File

@ -2,7 +2,7 @@ package org.enso.launcher.releases.launcher
import io.circe.{yaml, Decoder}
import nl.gn0s1s.bump.SemVer
import org.enso.launcher.releases.ReleaseProviderException
import org.enso.runtimeversionmanager.releases.ReleaseProviderException
import org.enso.pkg.SemVerJson._
import scala.util.{Failure, Try}

View File

@ -4,7 +4,7 @@ import java.nio.file.Path
import nl.gn0s1s.bump.SemVer
import org.enso.cli.TaskProgress
import org.enso.launcher.CurrentVersion
import org.enso.runtimeversionmanager.CurrentVersion
/** Represents a launcher release.
*/

View File

@ -4,7 +4,7 @@ import java.nio.file.Path
import nl.gn0s1s.bump.SemVer
import org.enso.cli.TaskProgress
import org.enso.launcher.releases.{
import org.enso.runtimeversionmanager.releases.{
EnsoReleaseProvider,
Release,
ReleaseProviderException,

View File

@ -5,20 +5,22 @@ import java.nio.file.{Files, Path}
import com.typesafe.scalalogging.Logger
import nl.gn0s1s.bump.SemVer
import org.enso.cli.CLIOutput
import org.enso.launcher.FileSystem.PathSyntax
import org.enso.launcher.archive.Archive
import org.enso.runtimeversionmanager.{CurrentVersion, FileSystem, OS}
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.archive.Archive
import org.enso.runtimeversionmanager.components.UpgradeRequiredError
import org.enso.runtimeversionmanager.distribution.DistributionManager
import org.enso.launcher.cli.{GlobalCLIOptions, InternalOpts}
import org.enso.launcher.components.LauncherUpgradeRequiredError
import org.enso.launcher.installation.DistributionManager
import org.enso.launcher.locking.{
DefaultResourceManager,
import org.enso.runtimeversionmanager.locking.{
LockType,
Resource,
ResourceManager
}
import org.enso.launcher.releases.launcher.LauncherRelease
import org.enso.launcher.releases.{EnsoRepository, ReleaseProvider}
import org.enso.launcher.{CurrentVersion, FileSystem, InfoLogger, OS}
import org.enso.runtimeversionmanager.releases.ReleaseProvider
import org.enso.launcher.releases.EnsoRepository
import org.enso.launcher.InfoLogger
import org.enso.launcher.distribution.DefaultManagers
import org.enso.logger.LoggerSyntax
import scala.util.Try
@ -374,13 +376,13 @@ object LauncherUpgrader {
): LauncherUpgrader =
new LauncherUpgrader(
globalCLIOptions,
DistributionManager,
DefaultManagers.distributionManager,
EnsoRepository.defaultLauncherReleaseProvider,
DefaultResourceManager,
DefaultManagers.DefaultResourceManager,
originalExecutablePath
)
/** Wraps an action and intercepts the [[LauncherUpgradeRequiredError]]
/** Wraps an action and intercepts the [[UpgradeRequiredError]]
* offering to upgrade the launcher and re-run the command with the newer
* version.
*
@ -389,7 +391,7 @@ object LauncherUpgrader {
* @param action action that is executed and may throw the exception; it
* should return the desired exit code
* @return if `action` succeeds, its exit code is returned; otherwise if the
* [[LauncherUpgradeRequiredError]] is intercepted and an upgrade is
* [[UpgradeRequiredError]] is intercepted and an upgrade is
* performed, the exit code of the command that has been re-executed
* is returned
*/
@ -399,19 +401,27 @@ object LauncherUpgrader {
try {
action
} catch {
case upgradeRequiredError: LauncherUpgradeRequiredError =>
case upgradeRequiredError: UpgradeRequiredError =>
askToUpgrade(upgradeRequiredError, originalArguments)
}
}
private var cachedCLIOptions: Option[GlobalCLIOptions] = None
def setCLIOptions(globalCLIOptions: GlobalCLIOptions): Unit =
cachedCLIOptions = Some(globalCLIOptions)
private def askToUpgrade(
upgradeRequiredError: LauncherUpgradeRequiredError,
upgradeRequiredError: UpgradeRequiredError,
originalArguments: Array[String]
): Int = {
val logger = Logger[LauncherUpgrader].enter("auto-upgrade")
val autoConfirm = upgradeRequiredError.globalCLIOptions.autoConfirm
val logger = Logger[LauncherUpgrader].enter("auto-upgrade")
val globalCLIOptions = cachedCLIOptions.getOrElse(
throw new IllegalStateException(
"Upgrade requested but application was not initialized properly."
)
)
def shouldProceed: Boolean =
if (autoConfirm) {
if (globalCLIOptions.autoConfirm) {
logger.warn(
"A more recent launcher version is required. Since `auto-confirm` " +
"is set, the launcher upgrade will be peformed automatically."
@ -433,7 +443,7 @@ object LauncherUpgrader {
throw upgradeRequiredError
}
val upgrader = default(upgradeRequiredError.globalCLIOptions)
val upgrader = default(globalCLIOptions)
val targetVersion = upgrader.latestVersion().get
val launcherExecutable = upgrader.originalExecutable
try {

View File

@ -1,13 +1,17 @@
package org.enso.launcher
import nl.gn0s1s.bump.SemVer
import org.enso.launcher.components.{ComponentsManager, ComponentsManagerTest}
import org.enso.launcher.config.DefaultVersion.{Exact, LatestInstalled}
import org.enso.launcher.config.GlobalConfigurationManager
import org.enso.runtimeversionmanager.components.RuntimeVersionManager
import org.enso.runtimeversionmanager.config.DefaultVersion.{
Exact,
LatestInstalled
}
import org.enso.runtimeversionmanager.config.GlobalConfigurationManager
import org.enso.runtimeversionmanager.test.RuntimeVersionManagerTest
class DefaultVersionSpec extends ComponentsManagerTest {
class DefaultVersionSpec extends RuntimeVersionManagerTest {
def makeConfigAndComponentsManagers()
: (ComponentsManager, GlobalConfigurationManager) = {
: (RuntimeVersionManager, GlobalConfigurationManager) = {
val (distributionManager, componentsManager, _) = makeManagers()
val configurationManager =
new GlobalConfigurationManager(componentsManager, distributionManager)

View File

@ -5,6 +5,7 @@ import java.lang.{ProcessBuilder => JProcessBuilder}
import java.nio.file.{Files, Path}
import java.util.concurrent.{Semaphore, TimeUnit}
import org.enso.runtimeversionmanager.OS
import org.scalatest.concurrent.{Signaler, TimeLimitedTests}
import org.scalatest.matchers.should.Matchers
import org.scalatest.matchers.{MatchResult, Matcher}

View File

@ -2,10 +2,10 @@ package org.enso.launcher
import java.nio.file.{Files, Path}
import org.enso.runtimeversionmanager.test.WithTemporaryDirectory
import org.scalatest.OptionValues
import scala.jdk.CollectionConverters._
import scala.sys.process._
class PluginManagerSpec

View File

@ -1,92 +0,0 @@
package org.enso.launcher.components
import java.nio.file.Path
import nl.gn0s1s.bump.SemVer
import org.enso.launcher.cli.{ColorMode, GlobalCLIOptions}
import org.enso.launcher.installation.DistributionManager
import org.enso.launcher.locking.TestLocalResourceManager
import org.enso.launcher.releases.engine.EngineReleaseProvider
import org.enso.launcher.releases.runtime.GraalCEReleaseProvider
import org.enso.launcher.releases.testing.FakeReleaseProvider
import org.enso.launcher.{
DropLogs,
Environment,
FakeEnvironment,
WithTemporaryDirectory
}
import org.enso.pkg.{PackageManager, SemVerEnsoVersion}
import org.scalatest.OptionValues
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
class ComponentsManagerTest
extends AnyWordSpec
with Matchers
with OptionValues
with WithTemporaryDirectory
with FakeEnvironment
with DropLogs {
/** Creates the [[DistributionManager]], [[ComponentsManager]] and an
* [[Environment]] for use in the tests.
*
* Should be called separately for each test case, as the components use
* temporary directories which are separate for each test case.
*
* Additional environment variables may be provided that are added to the
* [[Environment]] for the created managers.
*/
def makeManagers(
environmentOverrides: Map[String, String] = Map.empty
): (DistributionManager, ComponentsManager, Environment) = {
val env = fakeInstalledEnvironment(environmentOverrides)
val distributionManager =
new DistributionManager(env, TestLocalResourceManager.create())
val fakeReleasesRoot =
Path.of(
getClass
.getResource("/org/enso/launcher/components/fake-releases")
.toURI
)
val engineProvider = new EngineReleaseProvider(
FakeReleaseProvider(
fakeReleasesRoot.resolve("enso"),
copyIntoArchiveRoot = Seq("manifest.yaml")
)
)
val runtimeProvider = new GraalCEReleaseProvider(
FakeReleaseProvider(fakeReleasesRoot.resolve("graalvm"))
)
val componentsManager = new ComponentsManager(
GlobalCLIOptions(
autoConfirm = true,
hideProgress = true,
useJSON = false,
colorMode = ColorMode.Never
),
distributionManager,
TestLocalResourceManager.create(),
engineProvider,
runtimeProvider
)
(distributionManager, componentsManager, env)
}
/** Returns just the [[ComponentsManager]].
*
* See [[makeManagers]] for details.
*/
def makeComponentsManager(): ComponentsManager = makeManagers()._2
/** Creates a new project using the default package manager.
*/
def newProject(name: String, path: Path, version: SemVer): Unit = {
PackageManager.Default.create(
root = path.toFile,
name = name,
ensoVersion = SemVerEnsoVersion(version)
)
}
}

View File

@ -1,19 +1,23 @@
package org.enso.launcher.components.runner
package org.enso.launcher.components
import java.nio.file.{Files, Path}
import java.util.UUID
import akka.http.scaladsl.model.Uri
import nl.gn0s1s.bump.SemVer
import org.enso.launcher.FileSystem.PathSyntax
import org.enso.launcher.components.ComponentsManagerTest
import org.enso.launcher.config.GlobalConfigurationManager
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.config.GlobalConfigurationManager
import org.enso.runtimeversionmanager.runner._
import org.enso.runtimeversionmanager.test.RuntimeVersionManagerTest
import org.enso.launcher.project.ProjectManager
import org.enso.loggingservice.LogLevel
import scala.concurrent.Future
class RunnerSpec extends ComponentsManagerTest {
/** We test integration of both the underlying [[Runner]] and the
* [[LauncherRunner]] in a single suite.
*/
class LauncherRunnerSpec extends RuntimeVersionManagerTest {
private val defaultEngineVersion = SemVer(0, 0, 0, Some("default"))
private val fakeUri = Uri("ws://test:1234/")
@ -21,7 +25,7 @@ class RunnerSpec extends ComponentsManagerTest {
def makeFakeRunner(
cwdOverride: Option[Path] = None,
extraEnv: Map[String, String] = Map.empty
): Runner = {
): LauncherRunner = {
val (distributionManager, componentsManager, env) = makeManagers(extraEnv)
val configurationManager =
new GlobalConfigurationManager(componentsManager, distributionManager) {
@ -30,7 +34,7 @@ class RunnerSpec extends ComponentsManagerTest {
val projectManager = new ProjectManager(configurationManager)
val cwd = cwdOverride.getOrElse(getTestDirectory)
val runner =
new Runner(
new LauncherRunner(
projectManager,
configurationManager,
componentsManager,
@ -212,7 +216,6 @@ class RunnerSpec extends ComponentsManagerTest {
val options = LanguageServerOptions(
rootId = UUID.randomUUID(),
path = projectPath,
interface = "127.0.0.2",
rpcPort = 1234,
dataPort = 4321
@ -220,6 +223,7 @@ class RunnerSpec extends ComponentsManagerTest {
val runSettings = runner
.languageServer(
options,
contentRootPath = projectPath,
versionOverride = None,
additionalArguments = Seq("additional"),
logLevel = LogLevel.Info
@ -232,7 +236,7 @@ class RunnerSpec extends ComponentsManagerTest {
commandLine should include(s"--rpc-port ${options.rpcPort}")
commandLine should include(s"--data-port ${options.dataPort}")
commandLine should include(s"--root-id ${options.rootId}")
val normalizedPath = options.path.toAbsolutePath.normalize.toString
val normalizedPath = projectPath.toAbsolutePath.normalize.toString
commandLine should include(s"--path $normalizedPath")
runSettings.runnerArguments.lastOption.value shouldEqual "additional"
@ -240,6 +244,7 @@ class RunnerSpec extends ComponentsManagerTest {
runner
.languageServer(
options,
contentRootPath = projectPath,
versionOverride = Some(overridden),
additionalArguments = Seq(),
logLevel = LogLevel.Info

View File

@ -2,7 +2,9 @@ package org.enso.launcher.installation
import java.nio.file.{Files, Path}
import org.enso.launcher.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.{FileSystem, OS}
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.test.WithTemporaryDirectory
import org.enso.launcher._
class InstallerSpec extends NativeTest with WithTemporaryDirectory {

View File

@ -2,8 +2,10 @@ package org.enso.launcher.installation
import java.nio.file.{Files, Path}
import org.enso.launcher.FileSystem.PathSyntax
import org.enso.launcher.{FileSystem, NativeTest, OS, WithTemporaryDirectory}
import org.enso.runtimeversionmanager.{FileSystem, OS}
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.test.WithTemporaryDirectory
import org.enso.launcher.NativeTest
class UninstallerSpec extends NativeTest with WithTemporaryDirectory {
def installedRoot: Path = getTestDirectory / "installed"

View File

@ -1,22 +1,20 @@
package org.enso.launcher.project
import nl.gn0s1s.bump.SemVer
import org.enso.launcher.components.ComponentsManagerTest
import org.enso.launcher.config.GlobalConfigurationManager
import org.enso.launcher.installation.DistributionManager
import org.enso.launcher.locking.TestLocalResourceManager
import org.enso.runtimeversionmanager.config.GlobalConfigurationManager
import org.enso.runtimeversionmanager.distribution.DistributionManager
import org.enso.runtimeversionmanager.test.RuntimeVersionManagerTest
import org.enso.pkg.Contact
import org.scalatest.{Inside, OptionValues}
class ProjectManagerSpec
extends ComponentsManagerTest
extends RuntimeVersionManagerTest
with Inside
with OptionValues {
private val defaultEnsoVersion = SemVer(0, 0, 0, Some("default"))
def makeProjectManager(): (GlobalConfigurationManager, ProjectManager) = {
val env = fakeInstalledEnvironment()
val distributionManager =
new DistributionManager(env, TestLocalResourceManager.create())
val env = fakeInstalledEnvironment()
val distributionManager = new DistributionManager(env)
val fakeConfigurationManager =
new GlobalConfigurationManager(null, distributionManager) {
override def defaultVersion: SemVer = defaultEnsoVersion

View File

@ -2,11 +2,12 @@ package org.enso.launcher.releases.fallback
import java.nio.file.Path
import org.enso.launcher.{FileSystem, TestHelpers}
import org.enso.runtimeversionmanager.FileSystem
import org.enso.launcher.TestHelpers
import org.enso.launcher.releases.fallback.staticwebsite.FileStorageFallbackReleaseProvider
import org.scalatest.{Inside, OptionValues}
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
import org.scalatest.{Inside, OptionValues}
import scala.util.Failure

View File

@ -1,6 +1,10 @@
package org.enso.launcher.releases.fallback
import org.enso.launcher.releases.{Asset, Release, SimpleReleaseProvider}
import org.enso.runtimeversionmanager.releases.{
Asset,
Release,
SimpleReleaseProvider
}
import org.scalatest.TryValues
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

View File

@ -3,7 +3,8 @@ package org.enso.launcher.releases.fallback
import java.nio.file.Path
import org.enso.cli.{TaskProgress, TaskProgressImplementation}
import org.enso.launcher.{FileSystem, TestHelpers}
import org.enso.runtimeversionmanager.FileSystem
import org.enso.launcher.TestHelpers
import org.enso.launcher.releases.fallback.staticwebsite.FileStorage
import scala.util.Try

View File

@ -0,0 +1,13 @@
package org.enso.launcher.upgrade
import java.nio.file.Path
object FakeLauncherReleases {
/** Location of fake launcher releases used for testing upgrades. */
def path: Path = Path.of(
getClass
.getResource("/org/enso/launcher/components/fake-releases/launcher")
.toURI
)
}

View File

@ -4,9 +4,11 @@ import java.nio.file.{Files, Path, StandardCopyOption}
import io.circe.parser
import nl.gn0s1s.bump.SemVer
import org.enso.launcher.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.{FileSystem, OS}
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
import org.enso.launcher._
import org.enso.launcher.locking.{FileLockManager, LockType}
import org.enso.runtimeversionmanager.locking.{FileLockManager, LockType}
import org.enso.runtimeversionmanager.test.WithTemporaryDirectory
import org.scalatest.exceptions.TestFailedException
import org.scalatest.{BeforeAndAfterAll, OptionValues}
@ -20,12 +22,7 @@ class UpgradeSpec
/** Location of the fake releases root.
*/
private val fakeReleaseRoot = Path
.of(
getClass
.getResource("/org/enso/launcher/components/fake-releases")
.toURI
) / "launcher"
private val fakeReleaseRoot = FakeLauncherReleases.path
/** Location of built Rust artifacts.
*/

View File

@ -35,6 +35,11 @@ trait TaskProgress[A] {
if (showProgress) ProgressBar.waitWithProgress(this)
else TaskProgress.waitForTask(this)
/** Waits for the task to finish and returns its value, throwing any
* exceptions that were reported.
*/
def force(): A = TaskProgress.waitForTask(this).get
/** Alters the task by transforming its result with a function `f` that may
* fail.
*

View File

@ -1,4 +1,4 @@
package org.enso.launcher
package org.enso.runtimeversionmanager.test
import org.enso.loggingservice.TestLogger
import org.scalatest.{BeforeAndAfterAll, Suite}

View File

@ -1,7 +1,8 @@
package org.enso.launcher
package org.enso.runtimeversionmanager.test
import java.nio.file.{Files, Path}
import org.enso.launcher.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.{Environment, FileSystem}
/** A test-suite mixin that adds helper functions that create a fake environment
* which points to an Enso installation inside the temporary directory
@ -16,12 +17,15 @@ trait FakeEnvironment { self: WithTemporaryDirectory =>
* portable
*/
def fakeExecutablePath(portable: Boolean = false): Path = {
val fakeBin = getTestDirectory / "bin"
val fakeBin = getTestDirectory.resolve("bin")
Files.createDirectories(fakeBin)
if (portable) {
FileSystem.writeTextFile(getTestDirectory / ".enso.portable", "mark")
FileSystem.writeTextFile(
getTestDirectory.resolve(".enso.portable"),
"mark"
)
}
fakeBin / "enso"
fakeBin.resolve("enso")
}
/** Returns an [[Environment]] instance that overrides the `ENSO_*`
@ -36,10 +40,10 @@ trait FakeEnvironment { self: WithTemporaryDirectory =>
extraOverrides: Map[String, String] = Map.empty
): Environment = {
val executable = fakeExecutablePath()
val dataDir = getTestDirectory / "test_data"
val configDir = getTestDirectory / "test_config"
val binDir = getTestDirectory / "test_bin"
val runDir = getTestDirectory / "test_run"
val dataDir = getTestDirectory.resolve("test_data")
val configDir = getTestDirectory.resolve("test_config")
val binDir = getTestDirectory.resolve("test_bin")
val runDir = getTestDirectory.resolve("test_run")
val env = extraOverrides
.updated("ENSO_DATA_DIRECTORY", dataDir.toString)
.updated("ENSO_CONFIG_DIRECTORY", configDir.toString)

View File

@ -0,0 +1,11 @@
package org.enso.runtimeversionmanager.test
import java.nio.file.Path
object FakeReleases {
/** Location of fake engine and runtime releases used for testing component
* installation.
*/
def path: Path = Path.of(getClass.getResource("fake-releases").toURI)
}

View File

@ -0,0 +1,91 @@
package org.enso.runtimeversionmanager.test
import java.nio.file.Path
import nl.gn0s1s.bump.SemVer
import org.enso.runtimeversionmanager._
import org.enso.runtimeversionmanager.components.{
RuntimeVersionManagementUserInterface,
RuntimeVersionManager
}
import org.enso.runtimeversionmanager.distribution.{
DistributionManager,
PortableDistributionManager,
TemporaryDirectoryManager
}
import org.enso.runtimeversionmanager.releases.engine.EngineReleaseProvider
import org.enso.runtimeversionmanager.releases.graalvm.GraalCEReleaseProvider
import org.enso.runtimeversionmanager.releases.testing.FakeReleaseProvider
import org.enso.pkg.{PackageManager, SemVerEnsoVersion}
import org.scalatest.OptionValues
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
/** Gathers helper methods for testing the [[RuntimeVersionManager]]. */
class RuntimeVersionManagerTest
extends AnyWordSpec
with Matchers
with OptionValues
with WithTemporaryDirectory
with FakeEnvironment
with DropLogs {
/** Creates the [[DistributionManager]], [[RuntimeVersionManager]] and an
* [[Environment]] for use in the tests.
*
* Should be called separately for each test case, as the components use
* temporary directories which are separate for each test case.
*
* Additional environment variables may be provided that are added to the
* [[Environment]] for the created managers.
*/
def makeManagers(
environmentOverrides: Map[String, String] = Map.empty,
userInterface: RuntimeVersionManagementUserInterface =
TestRuntimeVersionManagementUserInterface.default
): (DistributionManager, RuntimeVersionManager, Environment) = {
val env = fakeInstalledEnvironment(environmentOverrides)
val distributionManager = new PortableDistributionManager(env)
val fakeReleasesRoot = FakeReleases.path
val engineProvider = new EngineReleaseProvider(
FakeReleaseProvider(
fakeReleasesRoot.resolve("enso"),
copyIntoArchiveRoot = Seq("manifest.yaml")
)
)
val runtimeProvider = new GraalCEReleaseProvider(
FakeReleaseProvider(fakeReleasesRoot.resolve("graalvm"))
)
val resourceManager = TestLocalResourceManager.create()
val temporaryDirectoryManager =
new TemporaryDirectoryManager(distributionManager, resourceManager)
val runtimeVersionManager = new RuntimeVersionManager(
userInterface,
distributionManager,
temporaryDirectoryManager,
resourceManager,
engineProvider,
runtimeProvider
)
(distributionManager, runtimeVersionManager, env)
}
/** Returns just the [[RuntimeVersionManager]].
*
* See [[makeManagers]] for details.
*/
def makeRuntimeVersionManager(): RuntimeVersionManager = makeManagers()._2
/** Creates a new project using the default package manager.
*/
def newProject(name: String, path: Path, version: SemVer): Unit = {
PackageManager.Default.create(
root = path.toFile,
name = name,
ensoVersion = SemVerEnsoVersion(version)
)
}
}

View File

@ -1,4 +1,4 @@
package org.enso.launcher.locking
package org.enso.runtimeversionmanager.test
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.{
@ -7,6 +7,8 @@ import java.util.concurrent.locks.{
Lock => JLock
}
import org.enso.runtimeversionmanager.locking.{Lock, LockManager, LockType}
/** A [[LockManager]] that creates process-local locks.
*
* The locks are not visible by other processes, so this manager is not useful

View File

@ -1,4 +1,6 @@
package org.enso.launcher.locking
package org.enso.runtimeversionmanager.test
import org.enso.runtimeversionmanager.locking.ResourceManager
object TestLocalResourceManager {

View File

@ -0,0 +1,48 @@
package org.enso.runtimeversionmanager.test
import com.typesafe.scalalogging.Logger
import nl.gn0s1s.bump.SemVer
import org.enso.cli.TaskProgress
import org.enso.runtimeversionmanager.components.{
GraalVMVersion,
RuntimeVersionManagementUserInterface
}
/** [[RuntimeVersionManagementUserInterface]] for usage in testing.
*
* It ensures that there are no interactive actions and unnecessary logging.
*/
class TestRuntimeVersionManagementUserInterface(installBroken: Boolean)
extends RuntimeVersionManagementUserInterface {
private val logger = Logger[TestRuntimeVersionManagementUserInterface]
/** @inheritdoc */
override def trackProgress(task: TaskProgress[_]): Unit = ()
/** @inheritdoc */
override def shouldInstallBrokenEngine(version: SemVer): Boolean = {
wasAskedForBroken = true
installBroken
}
private var wasAskedForBroken: Boolean = false
def wasAskedToInstallBroken: Boolean = wasAskedForBroken
/** @inheritdoc */
override def shouldInstallMissingEngine(version: SemVer): Boolean = true
/** @inheritdoc */
override def shouldInstallMissingRuntime(version: GraalVMVersion): Boolean =
true
/** @inheritdoc */
override def logInfo(message: => String): Unit = logger.debug(message)
}
object TestRuntimeVersionManagementUserInterface {
/** Creates a default [[TestRuntimeVersionManagementUserInterface]]. */
def default: TestRuntimeVersionManagementUserInterface =
new TestRuntimeVersionManagementUserInterface(installBroken = false)
}

View File

@ -1,8 +1,9 @@
package org.enso.launcher.locking
package org.enso.runtimeversionmanager.test
import java.util.concurrent.{Semaphore, TimeUnit}
import org.scalatest.exceptions.TestFailedException
import scala.jdk.CollectionConverters._
/** A helper class that can be used to synchronize actions between multiple

View File

@ -1,7 +1,7 @@
package org.enso.launcher
package org.enso.runtimeversionmanager.test
import java.nio.file.{Files, Path}
import java.io.{File, IOException}
import java.nio.file.{Files, Path}
import org.apache.commons.io.FileUtils
import org.scalatest.{BeforeAndAfterEach, Suite}

View File

@ -1,15 +1,19 @@
package org.enso.launcher.components
package org.enso.runtimeversionmanager.components
import nl.gn0s1s.bump.SemVer
import org.enso.launcher.config.GlobalConfigurationManager
import org.enso.loggingservice.{LogLevel, TestLogger}
import org.enso.runtimeversionmanager.components
import org.enso.runtimeversionmanager.config.GlobalConfigurationManager
import org.enso.runtimeversionmanager.test.{
RuntimeVersionManagerTest,
TestRuntimeVersionManagementUserInterface
}
class ComponentsManagerSpec extends ComponentsManagerTest {
class RuntimeVersionManagerSpec extends RuntimeVersionManagerTest {
"ComponentsManager" should {
"ComponentManager" should {
"find the latest engine version in semver ordering " +
"(skipping broken releases)" in {
val componentsManager = makeComponentsManager()
val componentsManager = makeRuntimeVersionManager()
componentsManager.fetchLatestEngineVersion() shouldEqual SemVer(0, 0, 1)
}
@ -25,8 +29,8 @@ class ComponentsManagerSpec extends ComponentsManagerTest {
"Engine should be installed in the engines directory."
)
val runtime = componentsManager.findRuntime(engine)
runtime.value.version shouldEqual RuntimeVersion(SemVer(2, 0, 0), "11")
val runtime = componentsManager.findGraalRuntime(engine)
runtime.value.version shouldEqual GraalVMVersion(SemVer(2, 0, 0), "11")
assert(
runtime.value.path.startsWith(distributionManager.paths.runtimes),
"Engine should be installed in the engines directory."
@ -34,41 +38,38 @@ class ComponentsManagerSpec extends ComponentsManagerTest {
}
"list installed engines and runtimes" in {
val componentsManager = makeComponentsManager()
val componentsManager = makeRuntimeVersionManager()
val engineVersions =
Set(SemVer(0, 0, 0), SemVer(0, 0, 1), SemVer(0, 0, 1, Some("pre")))
val runtimeVersions =
Set(
RuntimeVersion(SemVer(1, 0, 0), "11"),
RuntimeVersion(SemVer(2, 0, 0), "11")
components.GraalVMVersion(SemVer(1, 0, 0), "11"),
components.GraalVMVersion(SemVer(2, 0, 0), "11")
)
engineVersions.map(
componentsManager.findOrInstallEngine(_, complain = false)
)
engineVersions.map(componentsManager.findOrInstallEngine)
componentsManager
.listInstalledEngines()
.map(_.version)
.toSet shouldEqual engineVersions
componentsManager
.listInstalledRuntimes()
.listInstalledGraalRuntimes()
.map(_.version)
.toSet shouldEqual runtimeVersions
val runtime2 =
componentsManager
.findRuntime(RuntimeVersion(SemVer(2, 0, 0), "11"))
.findGraalRuntime(components.GraalVMVersion(SemVer(2, 0, 0), "11"))
.value
componentsManager.findEnginesUsingRuntime(runtime2) should have length 2
}
"preserve the broken mark when installing a broken release" in {
val componentsManager = makeComponentsManager()
val brokenVersion = SemVer(0, 999, 0, Some("marked-broken"))
componentsManager.findOrInstallEngine(
brokenVersion,
complain = false
)
val componentsManager = makeManagers(userInterface =
new TestRuntimeVersionManagementUserInterface(installBroken = true)
)._2
val brokenVersion = SemVer(0, 999, 0, Some("marked-broken"))
componentsManager.findOrInstallEngine(brokenVersion)
assert(
componentsManager.findEngine(brokenVersion).value.isMarkedBroken,
@ -78,7 +79,10 @@ class ComponentsManagerSpec extends ComponentsManagerTest {
}
"skip broken releases when finding latest installed version" in {
val (distributionManager, componentsManager, _) = makeManagers()
val (distributionManager, componentsManager, _) =
makeManagers(userInterface =
new TestRuntimeVersionManagementUserInterface(installBroken = true)
)
val configurationManager =
new GlobalConfigurationManager(componentsManager, distributionManager)
@ -91,30 +95,27 @@ class ComponentsManagerSpec extends ComponentsManagerTest {
}
"issue a warning when a broken release is requested" in {
val componentsManager = makeComponentsManager()
val userInterface =
new TestRuntimeVersionManagementUserInterface(installBroken = true)
val componentsManager = makeManagers(userInterface = userInterface)._2
val brokenVersion = SemVer(0, 999, 0, Some("marked-broken"))
val logs = TestLogger.gatherLogs {
componentsManager.findOrInstallEngine(brokenVersion, complain = false)
}
val warnings = logs.filter(_.logLevel == LogLevel.Warning)
warnings should have size 1
val expectedWarning = warnings.head.message
expectedWarning should include("is marked as broken")
expectedWarning should include("consider changing")
componentsManager.findOrInstallEngine(brokenVersion)
assert(
userInterface.wasAskedToInstallBroken,
"User interface should have been queried if broken versions are allowed."
)
componentsManager.findEngine(brokenVersion).value
}
"uninstall the runtime iff it is not used by any engines" in {
val componentsManager = makeComponentsManager()
val componentsManager = makeRuntimeVersionManager()
val engineVersions =
Seq(SemVer(0, 0, 0), SemVer(0, 0, 1), SemVer(0, 0, 1, Some("pre")))
engineVersions.map(
componentsManager.findOrInstallEngine(_, complain = false)
)
engineVersions.map(componentsManager.findOrInstallEngine)
componentsManager.listInstalledEngines() should have length 3
componentsManager.listInstalledRuntimes() should have length 2
componentsManager.listInstalledGraalRuntimes() should have length 2
// remove the engine that shares the runtime with another one
val version1 = SemVer(0, 0, 1, Some("pre"))
@ -122,7 +123,7 @@ class ComponentsManagerSpec extends ComponentsManagerTest {
val engines1 = componentsManager.listInstalledEngines()
engines1 should have length 2
engines1.map(_.version) should not contain version1
componentsManager.listInstalledRuntimes() should have length 2
componentsManager.listInstalledGraalRuntimes() should have length 2
// remove the second engine that shared the runtime
val version2 = SemVer(0, 0, 1)
@ -130,9 +131,9 @@ class ComponentsManagerSpec extends ComponentsManagerTest {
val engines2 = componentsManager.listInstalledEngines()
engines2 should have length 1
engines2.map(_.version) should not contain version2
val runtimes2 = componentsManager.listInstalledRuntimes()
val runtimes2 = componentsManager.listInstalledGraalRuntimes()
runtimes2 should have length 1
runtimes2.map(_.version).head shouldEqual RuntimeVersion(
runtimes2.map(_.version).head shouldEqual components.GraalVMVersion(
SemVer(1, 0, 0),
"11"
)
@ -140,7 +141,7 @@ class ComponentsManagerSpec extends ComponentsManagerTest {
// remove the last engine
componentsManager.uninstallEngine(SemVer(0, 0, 0))
componentsManager.listInstalledEngines() should have length 0
componentsManager.listInstalledRuntimes() should have length 0
componentsManager.listInstalledGraalRuntimes() should have length 0
}
}
}

View File

@ -1,10 +1,13 @@
package org.enso.launcher.config
package org.enso.runtimeversionmanager.config
import io.circe.Json
import nl.gn0s1s.bump.SemVer
import org.enso.launcher.{DropLogs, FakeEnvironment, WithTemporaryDirectory}
import org.enso.launcher.installation.DistributionManager
import org.enso.launcher.locking.TestLocalResourceManager
import org.enso.runtimeversionmanager.distribution.DistributionManager
import org.enso.runtimeversionmanager.test.{
DropLogs,
FakeEnvironment,
WithTemporaryDirectory
}
import org.scalatest.OptionValues
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
@ -17,9 +20,8 @@ class GlobalConfigurationManagerSpec
with OptionValues
with DropLogs {
def makeConfigManager(): GlobalConfigurationManager = {
val env = fakeInstalledEnvironment()
val distributionManager =
new DistributionManager(env, TestLocalResourceManager.create())
val env = fakeInstalledEnvironment()
val distributionManager = new DistributionManager(env)
new GlobalConfigurationManager(null, distributionManager) {
override def defaultVersion: SemVer = SemVer(0, 0, 0)
}

View File

@ -1,12 +1,15 @@
package org.enso.launcher.installation
package org.enso.runtimeversionmanager.distributuion
import java.nio.file.Path
import org.enso.launcher.FileSystem.PathSyntax
import org.enso.launcher.locking.TestLocalResourceManager
import org.enso.launcher.{
import org.enso.runtimeversionmanager.Environment
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
import org.enso.runtimeversionmanager.distribution.{
DistributionManager,
PortableDistributionManager
}
import org.enso.runtimeversionmanager.test.{
DropLogs,
Environment,
FakeEnvironment,
WithTemporaryDirectory
}
@ -27,11 +30,7 @@ class DistributionManagerSpec
override def getPathToRunningExecutable: Path = executable
}
val distributionManager =
new DistributionManager(
fakeEnvironment,
TestLocalResourceManager.create()
)
val distributionManager = new PortableDistributionManager(fakeEnvironment)
distributionManager.isRunningPortable shouldEqual true
distributionManager.paths.dataRoot shouldEqual getTestDirectory
distributionManager.paths.config shouldEqual getTestDirectory / "config"
@ -46,11 +45,7 @@ class DistributionManagerSpec
override def getPathToRunningExecutable: Path = executable
}
val distributionManager =
new DistributionManager(
fakeEnvironment,
TestLocalResourceManager.create()
)
val distributionManager = new PortableDistributionManager(fakeEnvironment)
distributionManager.isRunningPortable shouldEqual false
}
@ -61,10 +56,7 @@ class DistributionManagerSpec
val binDir = getTestDirectory / "test_bin"
val distributionManager =
new DistributionManager(
fakeInstalledEnvironment(),
TestLocalResourceManager.create()
)
new DistributionManager(fakeInstalledEnvironment())
distributionManager.paths.dataRoot shouldEqual dataDir
distributionManager.paths.config shouldEqual configDir
distributionManager.LocallyInstalledDirectories.binDirectory shouldEqual

View File

@ -1,23 +1,27 @@
package org.enso.launcher.locking
package org.enso.runtimeversionmanager.locking
import java.nio.file.{Files, Path}
import nl.gn0s1s.bump.SemVer
import org.enso.cli.TaskProgress
import org.enso.launcher.FileSystem.PathSyntax
import org.enso.launcher.cli.{ColorMode, GlobalCLIOptions}
import org.enso.launcher.components.{ComponentsManager, RuntimeVersion}
import org.enso.launcher.installation.DistributionManager
import org.enso.launcher.releases.engine.{EngineRelease, EngineReleaseProvider}
import org.enso.launcher.releases.runtime.GraalCEReleaseProvider
import org.enso.launcher.releases.testing.FakeReleaseProvider
import org.enso.launcher.{
components,
DropLogs,
FakeEnvironment,
FileSystem,
WithTemporaryDirectory
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
import org.enso.runtimeversionmanager._
import org.enso.runtimeversionmanager.components.{
GraalVMVersion,
Manifest,
RuntimeVersionManager
}
import org.enso.runtimeversionmanager.distribution.{
DistributionManager,
TemporaryDirectoryManager
}
import org.enso.runtimeversionmanager.releases.engine.{
EngineRelease,
EngineReleaseProvider
}
import org.enso.runtimeversionmanager.releases.graalvm.GraalCEReleaseProvider
import org.enso.runtimeversionmanager.releases.testing.FakeReleaseProvider
import org.enso.runtimeversionmanager.test._
import org.scalatest.BeforeAndAfterEach
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
@ -37,7 +41,7 @@ class ConcurrencyTest
callback: String => Unit
) extends EngineRelease {
override def version: SemVer = originalRelease.version
override def manifest: components.Manifest =
override def manifest: Manifest =
originalRelease.manifest
override def isBroken: Boolean = originalRelease.isBroken
override def packageFileName: String =
@ -69,18 +73,18 @@ class ConcurrencyTest
def makeNewResourceManager(): ResourceManager =
new ResourceManager(lockManager)
/** Creates a [[DistributionManager]] and [[ComponentsManager]] that can be
/** Creates a [[DistributionManager]] and [[RuntimeVersionManager]] that can be
* used in a test.
*
* @param releaseCallback called when a release asset is fetched
* @param lockWaitsCallback called when a lock with the given name is not
* acquired immediately
* @return a tuple of [[DistributionManager]] and [[ComponentsManager]]
* @return a tuple of [[DistributionManager]] and [[RuntimeVersionManager]]
*/
def makeManagers(
releaseCallback: String => Unit,
lockWaitsCallback: String => Unit
): (DistributionManager, ComponentsManager) = {
): (DistributionManager, RuntimeVersionManager, TemporaryDirectoryManager) = {
val env = fakeInstalledEnvironment()
val resourceManager = new ResourceManager(lockManager) {
override def withResource[R](
@ -98,13 +102,8 @@ class ConcurrencyTest
}
}
val distributionManager = new DistributionManager(env, resourceManager)
val fakeReleasesRoot =
Path.of(
getClass
.getResource("/org/enso/launcher/components/fake-releases")
.toURI
)
val distributionManager = new DistributionManager(env)
val fakeReleasesRoot = FakeReleases.path
val engineProvider = new EngineReleaseProvider(
FakeReleaseProvider(
fakeReleasesRoot.resolve("enso"),
@ -118,7 +117,7 @@ class ConcurrencyTest
FakeReleaseProvider(fakeReleasesRoot.resolve("graalvm"))
) {
override def downloadPackage(
version: RuntimeVersion,
version: GraalVMVersion,
destination: Path
): TaskProgress[Unit] = {
releaseCallback(packageFileName(version))
@ -126,29 +125,27 @@ class ConcurrencyTest
}
}
val componentsManager = new ComponentsManager(
GlobalCLIOptions(
autoConfirm = true,
hideProgress = true,
useJSON = false,
colorMode = ColorMode.Never
),
val temporaryDirectoryManager =
new TemporaryDirectoryManager(distributionManager, resourceManager)
val componentsManager = new RuntimeVersionManager(
TestRuntimeVersionManagementUserInterface.default,
distributionManager,
temporaryDirectoryManager,
resourceManager,
engineProvider,
runtimeProvider
)
(distributionManager, componentsManager)
(distributionManager, componentsManager, temporaryDirectoryManager)
}
/** Helper function, acts as [[makeManagers]] but returns only the
* [[ComponentsManager]].
* [[RuntimeVersionManager]].
*/
def makeComponentsManager(
releaseCallback: String => Unit,
lockWaitsCallback: String => Unit
): ComponentsManager =
): RuntimeVersionManager =
makeManagers(
releaseCallback = releaseCallback,
lockWaitsCallback = lockWaitsCallback
@ -182,7 +179,7 @@ class ConcurrencyTest
FileSystem.writeTextFile(garbage, "Garbage")
sync.startThread("t1") {
val (distributionManager, componentsManager) = makeManagers(
val (_, componentsManager, temporaryDirectoryManager) = makeManagers(
releaseCallback = { asset =>
if (asset.startsWith("graalvm-")) {
sync.signal("t1-downloads-runtime")
@ -195,14 +192,14 @@ class ConcurrencyTest
)
)
distributionManager.tryCleaningTemporaryDirectory()
componentsManager.findOrInstallEngine(engine1, complain = false)
temporaryDirectoryManager.tryCleaningTemporaryDirectory()
componentsManager.findOrInstallEngine(engine1)
}
sync.waitFor("t1-downloads-runtime")
sync.startThread("t2") {
val (distributionManager, componentsManager) = makeManagers(
val (_, componentsManager, temporaryDirectoryManager) = makeManagers(
releaseCallback = { asset =>
if (asset.startsWith("graalvm-")) {
throw new IllegalStateException(
@ -219,8 +216,8 @@ class ConcurrencyTest
}
)
distributionManager.tryCleaningTemporaryDirectory()
componentsManager.findOrInstallEngine(engine2, complain = false)
temporaryDirectoryManager.tryCleaningTemporaryDirectory()
componentsManager.findOrInstallEngine(engine2)
}
sync.join()
@ -257,7 +254,7 @@ class ConcurrencyTest
)
)
componentsManager.findOrInstallEngine(engineVersion, complain = false)
componentsManager.findOrInstallEngine(engineVersion)
}
sync.waitFor("t1-downloads-engine")

View File

@ -1,8 +1,8 @@
package org.enso.launcher
package org.enso.runtimeversionmanager
import buildinfo.Info
import nl.gn0s1s.bump.SemVer
import com.typesafe.scalalogging.Logger
import nl.gn0s1s.bump.SemVer
/** Helper object that allows to get the current launcher version.
*

View File

@ -1,4 +1,4 @@
package org.enso.launcher
package org.enso.runtimeversionmanager
import java.io.File
import java.nio.file.Path
@ -127,50 +127,18 @@ trait Environment {
*
* It is intended for usage in native binary builds, where it returns the
* path to the binary executable that is running. When running on the JVM,
* returns a path to the root of the classpath for the `org.enso.launcher`
* package or a built JAR.
* returns a path to the root of the classpath for the
* `org.enso.componentmanager` package or a built JAR.
*/
def getPathToRunningExecutable: Path
}
/** The default [[Environment]] implementation.
*/
object Environment extends Environment {
/** @inheritdoc
*/
override def getPathToRunningExecutable: Path =
executablePathOverride.getOrElse(executablePath)
private def executablePath: Path =
try {
val codeSource =
this.getClass.getProtectionDomain.getCodeSource
Path.of(codeSource.getLocation.toURI).toAbsolutePath
} catch {
case e: Exception =>
throw new IllegalStateException(
"Cannot locate the path of the launched executable",
e
)
}
private var executablePathOverride: Option[Path] = None
/** Overrides the return value of [[getPathToRunningExecutable]] with the
* provided path.
*
* Internal method used for testing. It should be called as early as
* possible, before [[getPathToRunningExecutable]] is called.
*/
def internalOverrideExecutableLocation(newLocation: Path): Unit =
if (buildinfo.Info.isRelease)
def getPathToRunningExecutable: Path = try {
val codeSource =
this.getClass.getProtectionDomain.getCodeSource
Path.of(codeSource.getLocation.toURI).toAbsolutePath
} catch {
case e: Exception =>
throw new IllegalStateException(
"Internal testing function internalOverrideExecutableLocation used " +
"in a release build."
"Cannot locate the path of the launched executable",
e
)
else {
Logger("TEST").debug(s"Overriding location to $newLocation.")
executablePathOverride = Some(newLocation)
}
}
}

View File

@ -1,21 +1,20 @@
package org.enso.launcher
package org.enso.runtimeversionmanager
import java.io.PrintWriter
import java.nio.file.attribute.{PosixFilePermission, PosixFilePermissions}
import java.nio.file.attribute.PosixFilePermissions
import java.nio.file.{
DirectoryNotEmptyException,
Files,
Path,
StandardCopyOption
}
import java.util
import com.typesafe.scalalogging.Logger
import org.apache.commons.io.FileUtils
import scala.collection.Factory
import scala.jdk.StreamConverters._
import scala.util.Using
import com.typesafe.scalalogging.Logger
/** Gathers some helper methods that are used for interaction with the
* filesystem.
@ -73,50 +72,6 @@ object FileSystem {
}
}
/** Parses POSIX file permissions stored in a binary format into a set of Java
* enumerations corresponding to these permissions.
*/
def decodePOSIXPermissions(mode: Int): java.util.Set[PosixFilePermission] = {
val res =
util.EnumSet.noneOf[PosixFilePermission](classOf[PosixFilePermission])
val others = mode & 7
val group = (mode >> 3) & 7
val owner = (mode >> 6) & 7
if ((owner & 4) != 0) {
res.add(PosixFilePermission.OWNER_READ)
}
if ((owner & 2) != 0) {
res.add(PosixFilePermission.OWNER_WRITE)
}
if ((owner & 1) != 0) {
res.add(PosixFilePermission.OWNER_EXECUTE)
}
if ((group & 4) != 0) {
res.add(PosixFilePermission.GROUP_READ)
}
if ((group & 2) != 0) {
res.add(PosixFilePermission.GROUP_WRITE)
}
if ((group & 1) != 0) {
res.add(PosixFilePermission.GROUP_EXECUTE)
}
if ((others & 4) != 0) {
res.add(PosixFilePermission.OTHERS_READ)
}
if ((others & 2) != 0) {
res.add(PosixFilePermission.OTHERS_WRITE)
}
if ((others & 1) != 0) {
res.add(PosixFilePermission.OTHERS_EXECUTE)
}
res
}
/** Runs the `action` with a parameter representing a temporary directory
* created for it.
*

View File

@ -1,4 +1,4 @@
package org.enso.launcher
package org.enso.runtimeversionmanager
import com.typesafe.scalalogging.Logger
import io.circe.{Decoder, DecodingFailure}

View File

@ -1,4 +1,4 @@
package org.enso.launcher.archive
package org.enso.runtimeversionmanager.archive
import java.io.BufferedInputStream
import java.nio.file.{Files, Path}
@ -19,9 +19,12 @@ import org.apache.commons.compress.archivers.zip.{
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream
import org.apache.commons.io.IOUtils
import org.enso.cli.{TaskProgress, TaskProgressImplementation}
import org.enso.launcher.archive.internal.{ArchiveIterator, BaseRenamer}
import org.enso.launcher.internal.ReadProgress
import org.enso.launcher.{FileSystem, OS}
import org.enso.runtimeversionmanager.OS
import org.enso.runtimeversionmanager.archive.internal.{
ArchiveIterator,
BaseRenamer
}
import org.enso.runtimeversionmanager.internal.ReadProgress
import scala.util.{Try, Using}
@ -190,7 +193,7 @@ object Archive {
if (OS.isUNIX) {
getMode(entry) match {
case Some(mode) =>
val permissions = FileSystem.decodePOSIXPermissions(mode)
val permissions = POSIXPermissions.decode(mode)
Files.setPosixFilePermissions(
destinationPath,
permissions

View File

@ -1,4 +1,4 @@
package org.enso.launcher.archive
package org.enso.runtimeversionmanager.archive
import java.nio.file.Path

View File

@ -1,4 +1,4 @@
package org.enso.launcher.archive
package org.enso.runtimeversionmanager.archive
import java.nio.file.Path

View File

@ -1,9 +1,9 @@
package org.enso.launcher.archive
package org.enso.runtimeversionmanager.archive
import java.io.FileInputStream
import java.nio.file.{Files, Path}
import org.enso.launcher.internal.ProgressInputStream
import org.enso.runtimeversionmanager.internal.ProgressInputStream
/** A helper that allows to create a [[ProgressInputStream]] for a file located
* at the given path.

Some files were not shown because too many files have changed in this diff Show More