mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 22:10:15 +03:00
Update the editions/listDefinedLibraries
Endpoint (#1964)
This commit is contained in:
parent
f53744ff53
commit
63819526d7
@ -1330,6 +1330,7 @@ interface LibraryEntry {
|
||||
namespace: String;
|
||||
name: String;
|
||||
version: LibraryVersion;
|
||||
isCached: Boolean;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -14,6 +14,7 @@ import org.enso.languageserver.http.server.BinaryWebSocketServer
|
||||
import org.enso.languageserver.io._
|
||||
import org.enso.languageserver.libraries.{
|
||||
EditionReferenceResolver,
|
||||
LibraryConfig,
|
||||
LocalLibraryManager,
|
||||
ProjectSettingsManager
|
||||
}
|
||||
@ -36,6 +37,9 @@ import org.enso.languageserver.search.SuggestionsHandler
|
||||
import org.enso.languageserver.session.SessionRouter
|
||||
import org.enso.languageserver.text.BufferRegistry
|
||||
import org.enso.languageserver.util.binary.BinaryEncoder
|
||||
import org.enso.librarymanager.LibraryLocations
|
||||
import org.enso.librarymanager.local.DefaultLocalLibraryProvider
|
||||
import org.enso.librarymanager.published.PublishedLibraryCache
|
||||
import org.enso.loggingservice.{JavaLoggingLogHandler, LogLevel}
|
||||
import org.enso.polyglot.{RuntimeOptions, RuntimeServerInfo}
|
||||
import org.enso.searcher.sql.{SqlDatabase, SqlSuggestionsRepo, SqlVersionsRepo}
|
||||
@ -292,24 +296,34 @@ class MainModule(serverConfig: LanguageServerConfig, logLevel: LogLevel) {
|
||||
"local-library-manager"
|
||||
)
|
||||
|
||||
val jsonRpcControllerFactory = new JsonConnectionControllerFactory(
|
||||
mainComponent = initializationComponent,
|
||||
bufferRegistry = bufferRegistry,
|
||||
capabilityRouter = capabilityRouter,
|
||||
fileManager = fileManager,
|
||||
contentRootManager = contentRootManagerActor,
|
||||
contextRegistry = contextRegistry,
|
||||
suggestionsHandler = suggestionsHandler,
|
||||
stdOutController = stdOutController,
|
||||
stdErrController = stdErrController,
|
||||
stdInController = stdInController,
|
||||
runtimeConnector = runtimeConnector,
|
||||
idlenessMonitor = idlenessMonitor,
|
||||
projectSettingsManager = projectSettingsManager,
|
||||
val libraryLocations =
|
||||
LibraryLocations.resolve(distributionManager, Some(languageHome))
|
||||
|
||||
val libraryConfig = LibraryConfig(
|
||||
localLibraryManager = localLibraryManager,
|
||||
editionReferenceResolver = editionReferenceResolver,
|
||||
editionManager = editionManager,
|
||||
config = languageServerConfig
|
||||
localLibraryProvider = DefaultLocalLibraryProvider.make(libraryLocations),
|
||||
publishedLibraryCache =
|
||||
PublishedLibraryCache.makeReadOnlyCache(libraryLocations)
|
||||
)
|
||||
|
||||
val jsonRpcControllerFactory = new JsonConnectionControllerFactory(
|
||||
mainComponent = initializationComponent,
|
||||
bufferRegistry = bufferRegistry,
|
||||
capabilityRouter = capabilityRouter,
|
||||
fileManager = fileManager,
|
||||
contentRootManager = contentRootManagerActor,
|
||||
contextRegistry = contextRegistry,
|
||||
suggestionsHandler = suggestionsHandler,
|
||||
stdOutController = stdOutController,
|
||||
stdErrController = stdErrController,
|
||||
stdInController = stdInController,
|
||||
runtimeConnector = runtimeConnector,
|
||||
idlenessMonitor = idlenessMonitor,
|
||||
projectSettingsManager = projectSettingsManager,
|
||||
libraryConfig = libraryConfig,
|
||||
config = languageServerConfig
|
||||
)
|
||||
log.trace(
|
||||
"Created JSON connection controller factory [{}].",
|
||||
|
@ -0,0 +1,22 @@
|
||||
package org.enso.languageserver.libraries
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import org.enso.editions.updater.EditionManager
|
||||
import org.enso.librarymanager.local.LocalLibraryProvider
|
||||
import org.enso.librarymanager.published.PublishedLibraryCache
|
||||
|
||||
/** Gathers together components needed by library-related Language Server endpoints.
|
||||
*
|
||||
* @param localLibraryManager a reference to the local library manager actor
|
||||
* @param editionReferenceResolver an instance of edition reference resolver
|
||||
* @param editionManager an instance of edition manager
|
||||
* @param localLibraryProvider an instance of local library provider
|
||||
* @param publishedLibraryCache an instance of published library cache
|
||||
*/
|
||||
case class LibraryConfig(
|
||||
localLibraryManager: ActorRef,
|
||||
editionReferenceResolver: EditionReferenceResolver,
|
||||
editionManager: EditionManager,
|
||||
localLibraryProvider: LocalLibraryProvider,
|
||||
publishedLibraryCache: PublishedLibraryCache
|
||||
)
|
@ -10,11 +10,14 @@ import org.enso.editions
|
||||
* @param namespace namespace of the library
|
||||
* @param name name of the library
|
||||
* @param version version of the library
|
||||
* @param isCached indicates whether the library is available in one of local
|
||||
* caches
|
||||
*/
|
||||
case class LibraryEntry(
|
||||
namespace: String,
|
||||
name: String,
|
||||
version: LibraryEntry.LibraryVersion
|
||||
version: LibraryEntry.LibraryVersion,
|
||||
isCached: Boolean
|
||||
)
|
||||
|
||||
object LibraryEntry {
|
||||
|
@ -101,7 +101,12 @@ class LocalLibraryManager(
|
||||
private def listLocalLibraries(): Try[ListLocalLibrariesResponse] = for {
|
||||
libraryNames <- findLocalLibraries()
|
||||
libraryEntries = libraryNames.distinct.map { name =>
|
||||
LibraryEntry(name.namespace, name.name, LibraryEntry.LocalLibraryVersion)
|
||||
LibraryEntry(
|
||||
name.namespace,
|
||||
name.name,
|
||||
LibraryEntry.LocalLibraryVersion,
|
||||
isCached = true
|
||||
)
|
||||
}
|
||||
} yield ListLocalLibrariesResponse(libraryEntries)
|
||||
|
||||
|
@ -2,23 +2,30 @@ package org.enso.languageserver.libraries.handler
|
||||
|
||||
import akka.actor.{Actor, Props}
|
||||
import com.typesafe.scalalogging.LazyLogging
|
||||
import org.enso.editions.LibraryVersion
|
||||
import org.enso.jsonrpc.{Request, ResponseError, ResponseResult}
|
||||
import org.enso.languageserver.filemanager.FileManagerApi.FileSystemError
|
||||
import org.enso.languageserver.libraries.LibraryApi._
|
||||
import org.enso.languageserver.libraries.{
|
||||
EditionReferenceResolver,
|
||||
LibraryEntry
|
||||
}
|
||||
import org.enso.languageserver.libraries.LibraryApi._
|
||||
import org.enso.languageserver.util.UnhandledLogging
|
||||
import org.enso.librarymanager.local.LocalLibraryProvider
|
||||
import org.enso.librarymanager.published.PublishedLibraryCache
|
||||
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
/** A request handler for the `editions/listDefinedLibraries` endpoint.
|
||||
*
|
||||
* @param editionReferenceResolver an [[EditionReferenceResolver]] instance
|
||||
* @param localLibraryProvider a provider of local libraries
|
||||
* @param publishedLibraryCache a cache of published libraries
|
||||
*/
|
||||
class EditionsListDefinedLibrariesHandler(
|
||||
editionReferenceResolver: EditionReferenceResolver
|
||||
editionReferenceResolver: EditionReferenceResolver,
|
||||
localLibraryProvider: LocalLibraryProvider,
|
||||
publishedLibraryCache: PublishedLibraryCache
|
||||
) extends Actor
|
||||
with LazyLogging
|
||||
with UnhandledLogging {
|
||||
@ -31,10 +38,17 @@ class EditionsListDefinedLibrariesHandler(
|
||||
val result = for {
|
||||
edition <- editionReferenceResolver.resolveEdition(reference)
|
||||
} yield edition.getAllDefinedLibraries.toSeq.map { case (name, version) =>
|
||||
val isCached = version match {
|
||||
case LibraryVersion.Local =>
|
||||
localLibraryProvider.findLibrary(name).isDefined
|
||||
case LibraryVersion.Published(version, _) =>
|
||||
publishedLibraryCache.isLibraryCached(name, version)
|
||||
}
|
||||
LibraryEntry(
|
||||
namespace = name.namespace,
|
||||
name = name.name,
|
||||
version = version
|
||||
version = version,
|
||||
isCached = isCached
|
||||
)
|
||||
}
|
||||
|
||||
@ -62,8 +76,18 @@ object EditionsListDefinedLibrariesHandler {
|
||||
* [[EditionsListDefinedLibrariesHandler]].
|
||||
*
|
||||
* @param editionReferenceResolver an [[EditionReferenceResolver]] instance
|
||||
* @param localLibraryProvider a provider of local libraries
|
||||
* @param publishedLibraryCache a cache of published libraries
|
||||
*/
|
||||
def props(editionReferenceResolver: EditionReferenceResolver): Props = Props(
|
||||
new EditionsListDefinedLibrariesHandler(editionReferenceResolver)
|
||||
def props(
|
||||
editionReferenceResolver: EditionReferenceResolver,
|
||||
localLibraryProvider: LocalLibraryProvider,
|
||||
publishedLibraryCache: PublishedLibraryCache
|
||||
): Props = Props(
|
||||
new EditionsListDefinedLibrariesHandler(
|
||||
editionReferenceResolver,
|
||||
localLibraryProvider,
|
||||
publishedLibraryCache
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import akka.util.Timeout
|
||||
import com.typesafe.scalalogging.LazyLogging
|
||||
import org.enso.cli.task.ProgressUnit
|
||||
import org.enso.cli.task.notifications.TaskNotificationApi
|
||||
import org.enso.editions.updater.EditionManager
|
||||
import org.enso.jsonrpc._
|
||||
import org.enso.languageserver.boot.resource.InitializationComponent
|
||||
import org.enso.languageserver.capability.CapabilityApi.{
|
||||
@ -27,8 +26,8 @@ import org.enso.languageserver.filemanager._
|
||||
import org.enso.languageserver.io.InputOutputApi._
|
||||
import org.enso.languageserver.io.OutputKind.{StandardError, StandardOutput}
|
||||
import org.enso.languageserver.io.{InputOutputApi, InputOutputProtocol}
|
||||
import org.enso.languageserver.libraries.EditionReferenceResolver
|
||||
import org.enso.languageserver.libraries.LibraryApi._
|
||||
import org.enso.languageserver.libraries.LibraryConfig
|
||||
import org.enso.languageserver.libraries.handler._
|
||||
import org.enso.languageserver.monitoring.MonitoringApi.{InitialPing, Ping}
|
||||
import org.enso.languageserver.monitoring.MonitoringProtocol
|
||||
@ -89,6 +88,7 @@ import scala.concurrent.duration._
|
||||
* @param suggestionsHandler a reference to the suggestions requests handler
|
||||
* @param idlenessMonitor a reference to the idleness monitor actor
|
||||
* @param projectSettingsManager a reference to the project settings manager
|
||||
* @param libraryConfig configuration of the library ecosystem
|
||||
* @param requestTimeout a request timeout
|
||||
*/
|
||||
class JsonConnectionController(
|
||||
@ -106,9 +106,7 @@ class JsonConnectionController(
|
||||
val runtimeConnector: ActorRef,
|
||||
val idlenessMonitor: ActorRef,
|
||||
val projectSettingsManager: ActorRef,
|
||||
val localLibraryManager: ActorRef,
|
||||
val editionReferenceResolver: EditionReferenceResolver,
|
||||
val editionManager: EditionManager,
|
||||
val libraryConfig: LibraryConfig,
|
||||
val languageServerConfig: Config,
|
||||
requestTimeout: FiniteDuration = 10.seconds
|
||||
) extends Actor
|
||||
@ -495,24 +493,28 @@ class JsonConnectionController(
|
||||
EditionsGetProjectSettings -> EditionsGetProjectSettingsHandler
|
||||
.props(requestTimeout, projectSettingsManager),
|
||||
EditionsListAvailable -> EditionsListAvailableHandler.props(
|
||||
editionManager
|
||||
libraryConfig.editionManager
|
||||
),
|
||||
EditionsListDefinedLibraries -> EditionsListDefinedLibrariesHandler
|
||||
.props(editionReferenceResolver),
|
||||
.props(
|
||||
libraryConfig.editionReferenceResolver,
|
||||
libraryConfig.localLibraryProvider,
|
||||
libraryConfig.publishedLibraryCache
|
||||
),
|
||||
EditionsResolve -> EditionsResolveHandler
|
||||
.props(editionReferenceResolver),
|
||||
.props(libraryConfig.editionReferenceResolver),
|
||||
EditionsSetParentEdition -> EditionsSetParentEditionHandler
|
||||
.props(requestTimeout, projectSettingsManager),
|
||||
EditionsSetLocalLibrariesPreference -> EditionsSetProjectLocalLibrariesPreferenceHandler
|
||||
.props(requestTimeout, projectSettingsManager),
|
||||
LibraryCreate -> LibraryCreateHandler
|
||||
.props(requestTimeout, localLibraryManager),
|
||||
.props(requestTimeout, libraryConfig.localLibraryManager),
|
||||
LibraryListLocal -> LibraryListLocalHandler
|
||||
.props(requestTimeout, localLibraryManager),
|
||||
.props(requestTimeout, libraryConfig.localLibraryManager),
|
||||
LibraryGetMetadata -> LibraryGetMetadataHandler.props(),
|
||||
LibraryPreinstall -> LibraryPreinstallHandler.props(),
|
||||
LibraryPublish -> LibraryPublishHandler
|
||||
.props(requestTimeout, localLibraryManager),
|
||||
.props(requestTimeout, libraryConfig.localLibraryManager),
|
||||
LibrarySetMetadata -> LibrarySetMetadataHandler.props()
|
||||
)
|
||||
}
|
||||
@ -557,6 +559,7 @@ object JsonConnectionController {
|
||||
* @param contentRootManager manages the available content roots
|
||||
* @param contextRegistry a router that dispatches execution context requests
|
||||
* @param suggestionsHandler a reference to the suggestions requests handler
|
||||
* @param libraryConfig configuration of the library ecosystem
|
||||
* @param requestTimeout a request timeout
|
||||
* @return a configuration object
|
||||
*/
|
||||
@ -575,33 +578,29 @@ object JsonConnectionController {
|
||||
runtimeConnector: ActorRef,
|
||||
idlenessMonitor: ActorRef,
|
||||
projectSettingsManager: ActorRef,
|
||||
localLibraryManager: ActorRef,
|
||||
editionReferenceResolver: EditionReferenceResolver,
|
||||
editionManager: EditionManager,
|
||||
libraryConfig: LibraryConfig,
|
||||
languageServerConfig: Config,
|
||||
requestTimeout: FiniteDuration = 10.seconds
|
||||
): Props =
|
||||
Props(
|
||||
new JsonConnectionController(
|
||||
connectionId = connectionId,
|
||||
mainComponent = mainComponent,
|
||||
bufferRegistry = bufferRegistry,
|
||||
capabilityRouter = capabilityRouter,
|
||||
fileManager = fileManager,
|
||||
contentRootManager = contentRootManager,
|
||||
contextRegistry = contextRegistry,
|
||||
suggestionsHandler = suggestionsHandler,
|
||||
stdOutController = stdOutController,
|
||||
stdErrController = stdErrController,
|
||||
stdInController = stdInController,
|
||||
runtimeConnector = runtimeConnector,
|
||||
idlenessMonitor = idlenessMonitor,
|
||||
projectSettingsManager = projectSettingsManager,
|
||||
localLibraryManager = localLibraryManager,
|
||||
editionReferenceResolver = editionReferenceResolver,
|
||||
editionManager = editionManager,
|
||||
languageServerConfig = languageServerConfig,
|
||||
requestTimeout = requestTimeout
|
||||
connectionId = connectionId,
|
||||
mainComponent = mainComponent,
|
||||
bufferRegistry = bufferRegistry,
|
||||
capabilityRouter = capabilityRouter,
|
||||
fileManager = fileManager,
|
||||
contentRootManager = contentRootManager,
|
||||
contextRegistry = contextRegistry,
|
||||
suggestionsHandler = suggestionsHandler,
|
||||
stdOutController = stdOutController,
|
||||
stdErrController = stdErrController,
|
||||
stdInController = stdInController,
|
||||
runtimeConnector = runtimeConnector,
|
||||
idlenessMonitor = idlenessMonitor,
|
||||
projectSettingsManager = projectSettingsManager,
|
||||
libraryConfig = libraryConfig,
|
||||
languageServerConfig = languageServerConfig,
|
||||
requestTimeout = requestTimeout
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
package org.enso.languageserver.protocol.json
|
||||
|
||||
import akka.actor.{ActorRef, ActorSystem}
|
||||
import org.enso.editions.updater.EditionManager
|
||||
import org.enso.jsonrpc.ClientControllerFactory
|
||||
import org.enso.languageserver.boot.resource.InitializationComponent
|
||||
import org.enso.languageserver.data.Config
|
||||
import org.enso.languageserver.libraries.EditionReferenceResolver
|
||||
import org.enso.languageserver.libraries.LibraryConfig
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
@ -15,6 +14,7 @@ import java.util.UUID
|
||||
* @param bufferRegistry the buffer registry actor ref
|
||||
* @param capabilityRouter the capability router actor ref
|
||||
* @param system the actor system
|
||||
* @param libraryConfig configuration of the library ecosystem
|
||||
*/
|
||||
class JsonConnectionControllerFactory(
|
||||
mainComponent: InitializationComponent,
|
||||
@ -30,9 +30,7 @@ class JsonConnectionControllerFactory(
|
||||
runtimeConnector: ActorRef,
|
||||
idlenessMonitor: ActorRef,
|
||||
projectSettingsManager: ActorRef,
|
||||
localLibraryManager: ActorRef,
|
||||
editionReferenceResolver: EditionReferenceResolver,
|
||||
editionManager: EditionManager,
|
||||
libraryConfig: LibraryConfig,
|
||||
config: Config
|
||||
)(implicit system: ActorSystem)
|
||||
extends ClientControllerFactory {
|
||||
@ -45,24 +43,22 @@ class JsonConnectionControllerFactory(
|
||||
override def createClientController(clientId: UUID): ActorRef =
|
||||
system.actorOf(
|
||||
JsonConnectionController.props(
|
||||
connectionId = clientId,
|
||||
mainComponent = mainComponent,
|
||||
bufferRegistry = bufferRegistry,
|
||||
capabilityRouter = capabilityRouter,
|
||||
fileManager = fileManager,
|
||||
contentRootManager = contentRootManager,
|
||||
contextRegistry = contextRegistry,
|
||||
suggestionsHandler = suggestionsHandler,
|
||||
stdOutController = stdOutController,
|
||||
stdErrController = stdErrController,
|
||||
stdInController = stdInController,
|
||||
runtimeConnector = runtimeConnector,
|
||||
idlenessMonitor = idlenessMonitor,
|
||||
projectSettingsManager = projectSettingsManager,
|
||||
localLibraryManager = localLibraryManager,
|
||||
editionReferenceResolver = editionReferenceResolver,
|
||||
editionManager = editionManager,
|
||||
languageServerConfig = config
|
||||
connectionId = clientId,
|
||||
mainComponent = mainComponent,
|
||||
bufferRegistry = bufferRegistry,
|
||||
capabilityRouter = capabilityRouter,
|
||||
fileManager = fileManager,
|
||||
contentRootManager = contentRootManager,
|
||||
contextRegistry = contextRegistry,
|
||||
suggestionsHandler = suggestionsHandler,
|
||||
stdOutController = stdOutController,
|
||||
stdErrController = stdErrController,
|
||||
stdInController = stdInController,
|
||||
runtimeConnector = runtimeConnector,
|
||||
idlenessMonitor = idlenessMonitor,
|
||||
projectSettingsManager = projectSettingsManager,
|
||||
libraryConfig = libraryConfig,
|
||||
languageServerConfig = config
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -7,13 +7,20 @@ import org.scalatest.wordspec.AnyWordSpec
|
||||
class LibraryEntrySerializationSpec extends AnyWordSpec with Matchers {
|
||||
"LibraryEntry" should {
|
||||
"serialize and deserialize to the same thing" in {
|
||||
val entry1 = LibraryEntry("Foo", "Bar", LibraryEntry.LocalLibraryVersion)
|
||||
val entry1 =
|
||||
LibraryEntry(
|
||||
"Foo",
|
||||
"Bar",
|
||||
LibraryEntry.LocalLibraryVersion,
|
||||
isCached = true
|
||||
)
|
||||
entry1.asJson.as[LibraryEntry] shouldEqual Right(entry1)
|
||||
|
||||
val entry2 = LibraryEntry(
|
||||
"Foo",
|
||||
"Bar",
|
||||
LibraryEntry.PublishedLibraryVersion("1.2.3", "https://example.com/")
|
||||
LibraryEntry.PublishedLibraryVersion("1.2.3", "https://example.com/"),
|
||||
isCached = false
|
||||
)
|
||||
entry2.asJson.as[LibraryEntry] shouldEqual Right(entry2)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import io.circe.parser.parse
|
||||
import io.circe.syntax.EncoderOps
|
||||
import org.apache.commons.io.FileUtils
|
||||
import org.enso.distribution.{DistributionManager, LanguageHome}
|
||||
import org.enso.editions.EditionResolver
|
||||
import org.enso.editions.{EditionResolver, Editions}
|
||||
import org.enso.editions.updater.EditionManager
|
||||
import org.enso.jsonrpc.test.JsonRpcServerTestKit
|
||||
import org.enso.jsonrpc.{ClientControllerFactory, Protocol}
|
||||
@ -24,6 +24,7 @@ import org.enso.languageserver.filemanager._
|
||||
import org.enso.languageserver.io._
|
||||
import org.enso.languageserver.libraries.{
|
||||
EditionReferenceResolver,
|
||||
LibraryConfig,
|
||||
LocalLibraryManager,
|
||||
ProjectSettingsManager
|
||||
}
|
||||
@ -37,6 +38,9 @@ import org.enso.languageserver.runtime.{ContextRegistry, RuntimeFailureMapper}
|
||||
import org.enso.languageserver.search.SuggestionsHandler
|
||||
import org.enso.languageserver.session.SessionRouter
|
||||
import org.enso.languageserver.text.BufferRegistry
|
||||
import org.enso.librarymanager.LibraryLocations
|
||||
import org.enso.librarymanager.local.DefaultLocalLibraryProvider
|
||||
import org.enso.librarymanager.published.PublishedLibraryCache
|
||||
import org.enso.pkg.PackageManager
|
||||
import org.enso.polyglot.data.TypeGraph
|
||||
import org.enso.polyglot.runtime.Runtime.Api
|
||||
@ -47,7 +51,7 @@ import org.enso.text.Sha3_224VersionCalculator
|
||||
import org.scalatest.OptionValues
|
||||
|
||||
import java.nio.file
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.{Files, Path}
|
||||
import java.util.UUID
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
@ -221,21 +225,6 @@ class BaseServerTest
|
||||
Api.VerifyModulesIndexResponse(Seq())
|
||||
)
|
||||
|
||||
locally {
|
||||
val dataRoot = getTestDirectory.resolve("test_data")
|
||||
val editions = dataRoot.resolve("editions")
|
||||
Files.createDirectories(editions)
|
||||
val distribution = file.Path.of("distribution")
|
||||
val currentEdition = buildinfo.Info.currentEdition + ".yaml"
|
||||
val dest = editions.resolve(currentEdition)
|
||||
if (Files.notExists(dest)) {
|
||||
Files.copy(
|
||||
distribution.resolve("editions").resolve(currentEdition),
|
||||
dest
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val environment = fakeInstalledEnvironment()
|
||||
val languageHome = LanguageHome.detectFromExecutableLocation(environment)
|
||||
val distributionManager = new DistributionManager(environment)
|
||||
@ -267,35 +256,59 @@ class BaseServerTest
|
||||
)
|
||||
)
|
||||
|
||||
new JsonConnectionControllerFactory(
|
||||
mainComponent = initializationComponent,
|
||||
bufferRegistry = bufferRegistry,
|
||||
capabilityRouter = capabilityRouter,
|
||||
fileManager = fileManager,
|
||||
contentRootManager = contentRootManagerActor,
|
||||
contextRegistry = contextRegistry,
|
||||
suggestionsHandler = suggestionsHandler,
|
||||
stdOutController = stdOutController,
|
||||
stdErrController = stdErrController,
|
||||
stdInController = stdInController,
|
||||
runtimeConnector = runtimeConnectorProbe.ref,
|
||||
idlenessMonitor = idlenessMonitor,
|
||||
projectSettingsManager = projectSettingsManager,
|
||||
val libraryLocations =
|
||||
LibraryLocations.resolve(distributionManager, Some(languageHome))
|
||||
|
||||
val libraryConfig = LibraryConfig(
|
||||
localLibraryManager = localLibraryManager,
|
||||
editionReferenceResolver = editionReferenceResolver,
|
||||
editionManager = editionManager,
|
||||
config = config
|
||||
localLibraryProvider = DefaultLocalLibraryProvider.make(libraryLocations),
|
||||
publishedLibraryCache =
|
||||
PublishedLibraryCache.makeReadOnlyCache(libraryLocations)
|
||||
)
|
||||
|
||||
new JsonConnectionControllerFactory(
|
||||
mainComponent = initializationComponent,
|
||||
bufferRegistry = bufferRegistry,
|
||||
capabilityRouter = capabilityRouter,
|
||||
fileManager = fileManager,
|
||||
contentRootManager = contentRootManagerActor,
|
||||
contextRegistry = contextRegistry,
|
||||
suggestionsHandler = suggestionsHandler,
|
||||
stdOutController = stdOutController,
|
||||
stdErrController = stdErrController,
|
||||
stdInController = stdInController,
|
||||
runtimeConnector = runtimeConnectorProbe.ref,
|
||||
idlenessMonitor = idlenessMonitor,
|
||||
projectSettingsManager = projectSettingsManager,
|
||||
libraryConfig = libraryConfig,
|
||||
config = config
|
||||
)
|
||||
}
|
||||
|
||||
/** As we are testing the language server, we want to imitate the location
|
||||
* context of the runner.jar, while the default implementation of this method
|
||||
* was more suited towards testing the launcher.
|
||||
*/
|
||||
override def fakeExecutablePath(portable: Boolean): Path =
|
||||
Path.of("distribution/component/runner.jar")
|
||||
|
||||
/** Specifies if the `package.yaml` at project root should be auto-created. */
|
||||
protected def initializeProjectPackage: Boolean = true
|
||||
|
||||
/** Allows to customize the edition used by the project.
|
||||
*
|
||||
* Only applicable if [[initializeProjectPackage]] is [[true]].
|
||||
*/
|
||||
protected def customEdition: Option[Editions.RawEdition] = None
|
||||
|
||||
lazy val initPackage: Unit = {
|
||||
if (initializeProjectPackage) {
|
||||
PackageManager.Default.create(
|
||||
config.projectContentRoot.file,
|
||||
name = "TestProject"
|
||||
name = "TestProject",
|
||||
edition = customEdition
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package org.enso.languageserver.websocket.json
|
||||
|
||||
import io.circe.literal._
|
||||
import io.circe.{Json, JsonObject}
|
||||
import nl.gn0s1s.bump.SemVer
|
||||
import org.enso.editions.{Editions, LibraryName}
|
||||
import org.enso.languageserver.libraries.LibraryEntry
|
||||
import org.enso.languageserver.libraries.LibraryEntry.PublishedLibraryVersion
|
||||
import org.enso.librarymanager.published.repository.{
|
||||
@ -12,6 +14,20 @@ import org.enso.librarymanager.published.repository.{
|
||||
import java.nio.file.Files
|
||||
|
||||
class LibrariesTest extends BaseServerTest {
|
||||
override protected def customEdition: Option[Editions.RawEdition] = Some(
|
||||
Editions.Raw.Edition
|
||||
.make(
|
||||
parent = Some(buildinfo.Info.currentEdition),
|
||||
libraries = Seq(
|
||||
Editions.Raw.PublishedLibrary(
|
||||
name = LibraryName("Foo", "Bar"),
|
||||
version = SemVer(1, 2, 3),
|
||||
repository = "main"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
"LocalLibraryManager" should {
|
||||
"create a library project and include it on the list of local projects" in {
|
||||
val client = getInitialisedWsClient()
|
||||
@ -66,7 +82,8 @@ class LibrariesTest extends BaseServerTest {
|
||||
"name": "My_Local_Lib",
|
||||
"version": {
|
||||
"type": "LocalLibraryVersion"
|
||||
}
|
||||
},
|
||||
"isCached": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -254,21 +271,31 @@ class LibrariesTest extends BaseServerTest {
|
||||
}
|
||||
}
|
||||
|
||||
"editions/listDefinedLibraries" should {
|
||||
"include Standard.Base in the list" in {
|
||||
def containsBase(response: Json): Unit = {
|
||||
val result = response.asObject.value("result").value
|
||||
val libs = result.asObject.value("availableLibraries").value
|
||||
val parsed = libs.asArray.value.map(_.as[LibraryEntry])
|
||||
val bases = parsed.collect {
|
||||
case Right(
|
||||
LibraryEntry("Standard", "Base", PublishedLibraryVersion(_, _))
|
||||
) =>
|
||||
()
|
||||
}
|
||||
bases should have size 1
|
||||
}
|
||||
case class PublishedLibrary(
|
||||
namespace: String,
|
||||
name: String,
|
||||
isCached: Boolean
|
||||
)
|
||||
|
||||
def extractPublishedLibraries(response: Json): Seq[PublishedLibrary] = {
|
||||
val result = response.asObject.value("result").value
|
||||
val libs = result.asObject.value("availableLibraries").value
|
||||
val parsed = libs.asArray.value.map(_.as[LibraryEntry])
|
||||
parsed.collect {
|
||||
case Right(
|
||||
LibraryEntry(
|
||||
namespace,
|
||||
name,
|
||||
PublishedLibraryVersion(_, _),
|
||||
isCached
|
||||
)
|
||||
) =>
|
||||
PublishedLibrary(namespace, name, isCached)
|
||||
}
|
||||
}
|
||||
|
||||
"editions/listDefinedLibraries" should {
|
||||
"include expected libraries in the list" in {
|
||||
val client = getInitialisedWsClient()
|
||||
client.send(json"""
|
||||
{ "jsonrpc": "2.0",
|
||||
@ -281,7 +308,14 @@ class LibrariesTest extends BaseServerTest {
|
||||
}
|
||||
}
|
||||
""")
|
||||
containsBase(client.expectSomeJson())
|
||||
val published = extractPublishedLibraries(client.expectSomeJson())
|
||||
|
||||
published should contain(
|
||||
PublishedLibrary("Standard", "Base", isCached = true)
|
||||
)
|
||||
published should contain(
|
||||
PublishedLibrary("Foo", "Bar", isCached = false)
|
||||
)
|
||||
|
||||
val currentEditionName = buildinfo.Info.currentEdition
|
||||
client.send(json"""
|
||||
@ -296,7 +330,9 @@ class LibrariesTest extends BaseServerTest {
|
||||
}
|
||||
}
|
||||
""")
|
||||
containsBase(client.expectSomeJson())
|
||||
extractPublishedLibraries(client.expectSomeJson()) should contain(
|
||||
PublishedLibrary("Standard", "Base", isCached = true)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,7 +344,7 @@ object PackageRepository {
|
||||
val edition = editionManager.resolveEdition(rawEdition).get
|
||||
|
||||
val resolvingLibraryProvider =
|
||||
new DefaultLibraryProvider(
|
||||
DefaultLibraryProvider.make(
|
||||
distributionManager = distributionManager,
|
||||
resourceManager = resourceManager,
|
||||
lockUserInterface = notificationHandler,
|
||||
|
@ -85,6 +85,34 @@ trait Editions {
|
||||
"that will imply it."
|
||||
)
|
||||
}
|
||||
|
||||
object Edition {
|
||||
|
||||
/** Alternative constructor for creating editions.
|
||||
*
|
||||
* Useful for manually created editions.
|
||||
*
|
||||
* @param parent a parent edition (if applicable)
|
||||
* @param engineVersion an engine version; it should be defined if the
|
||||
* edition wants to override the setting from the parent
|
||||
* or if it has no parents
|
||||
* @param repositories a list of repositories directly defined in the
|
||||
* edition (does not include ones defined in the parents)
|
||||
* @param libraries a list of libraries directly defined in the edition
|
||||
* (does not include ones defined in the parents)
|
||||
*/
|
||||
def make(
|
||||
parent: Option[NestedEditionType] = None,
|
||||
engineVersion: Option[SemVer] = None,
|
||||
repositories: Seq[Editions.Repository] = Seq.empty,
|
||||
libraries: Seq[Library] = Seq.empty
|
||||
): Edition = Edition(
|
||||
parent,
|
||||
engineVersion,
|
||||
repositories.map(r => (r.name, r)).toMap,
|
||||
libraries.map(l => (l.name, l)).toMap
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object Editions {
|
||||
|
@ -9,82 +9,34 @@ import org.enso.distribution.{
|
||||
TemporaryDirectoryManager
|
||||
}
|
||||
import org.enso.editions.{Editions, LibraryName, LibraryVersion}
|
||||
import org.enso.librarymanager.local.DefaultLocalLibraryProvider
|
||||
import org.enso.librarymanager.local.{
|
||||
DefaultLocalLibraryProvider,
|
||||
LocalLibraryProvider
|
||||
}
|
||||
import org.enso.librarymanager.published.bundles.LocalReadOnlyRepository
|
||||
import org.enso.librarymanager.published.cache.DownloadingLibraryCache
|
||||
import org.enso.librarymanager.published.{
|
||||
DefaultPublishedLibraryProvider,
|
||||
PublishedLibraryProvider
|
||||
}
|
||||
import org.enso.logger.masking.MaskedPath
|
||||
|
||||
import java.nio.file.Path
|
||||
|
||||
/** A helper class for loading libraries.
|
||||
*
|
||||
* @param distributionManager a distribution manager
|
||||
* @param resourceManager a resource manager
|
||||
* @param lockUserInterface an interface that will handle notifications
|
||||
* about waiting on locks
|
||||
* @param progressReporter an interface that will handle progress
|
||||
* notifications
|
||||
* @param languageHome a language home which may contain bundled libraries
|
||||
* @param edition the edition used in the project
|
||||
* @param preferLocalLibraries project setting whether to use local libraries
|
||||
* @param localLibraryProvider provider of local (unpublished) libraries
|
||||
* @param publishedLibraryProvider provider of published libraries
|
||||
* @param edition the edition used in the project
|
||||
* @param preferLocalLibraries project setting whether to use local
|
||||
* libraries
|
||||
*/
|
||||
class DefaultLibraryProvider(
|
||||
distributionManager: DistributionManager,
|
||||
resourceManager: ResourceManager,
|
||||
lockUserInterface: LockUserInterface,
|
||||
progressReporter: ProgressReporter,
|
||||
languageHome: Option[LanguageHome],
|
||||
class DefaultLibraryProvider private (
|
||||
localLibraryProvider: LocalLibraryProvider,
|
||||
publishedLibraryProvider: PublishedLibraryProvider,
|
||||
edition: Editions.ResolvedEdition,
|
||||
preferLocalLibraries: Boolean
|
||||
) extends ResolvingLibraryProvider {
|
||||
private val logger = Logger[DefaultLibraryProvider]
|
||||
private val localLibrarySearchPaths =
|
||||
distributionManager.paths.localLibrariesSearchPaths.toList
|
||||
private val localLibraryProvider = new DefaultLocalLibraryProvider(
|
||||
localLibrarySearchPaths
|
||||
)
|
||||
|
||||
private val logger = Logger[DefaultLibraryProvider]
|
||||
private val resolver = LibraryResolver(localLibraryProvider)
|
||||
|
||||
private val cacheRoot = distributionManager.paths.cachedLibraries
|
||||
private val primaryCache = new DownloadingLibraryCache(
|
||||
cacheRoot,
|
||||
TemporaryDirectoryManager(distributionManager, resourceManager),
|
||||
resourceManager,
|
||||
lockUserInterface,
|
||||
progressReporter
|
||||
)
|
||||
private val additionalCacheLocations = {
|
||||
val engineBundleRoot = languageHome.map(_.libraries)
|
||||
val locations =
|
||||
engineBundleRoot.toList ++ distributionManager.auxiliaryLibraryCaches()
|
||||
locations.distinct
|
||||
}
|
||||
private val additionalCaches =
|
||||
additionalCacheLocations.map(new LocalReadOnlyRepository(_))
|
||||
|
||||
private val publishedLibraryProvider: PublishedLibraryProvider =
|
||||
new DefaultPublishedLibraryProvider(primaryCache, additionalCaches)
|
||||
|
||||
locally {
|
||||
def mask(path: Path): String = MaskedPath(path).applyMasking()
|
||||
|
||||
logger.trace(
|
||||
s"Local library search paths = ${localLibrarySearchPaths.map(mask)}"
|
||||
)
|
||||
logger.trace(
|
||||
s"Primary library cache = ${mask(cacheRoot)}"
|
||||
)
|
||||
logger.trace(
|
||||
s"Auxiliary (bundled) library caches = " +
|
||||
s"${additionalCacheLocations.map(mask)}"
|
||||
)
|
||||
}
|
||||
|
||||
/** Resolves the library version that should be used based on the
|
||||
* configuration and returns its location on the filesystem.
|
||||
*
|
||||
@ -124,3 +76,51 @@ class DefaultLibraryProvider(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DefaultLibraryProvider {
|
||||
|
||||
/** Creates a [[ResolvingLibraryProvider]] that can download new libraries.
|
||||
*
|
||||
* @param distributionManager a distribution manager
|
||||
* @param resourceManager a resource manager
|
||||
* @param lockUserInterface an interface that will handle notifications
|
||||
* about waiting on locks
|
||||
* @param progressReporter an interface that will handle progress
|
||||
* notifications
|
||||
* @param languageHome a language home which may contain bundled libraries
|
||||
* @param edition the edition used in the project
|
||||
* @param preferLocalLibraries project setting whether to use local libraries
|
||||
*/
|
||||
def make(
|
||||
distributionManager: DistributionManager,
|
||||
resourceManager: ResourceManager,
|
||||
lockUserInterface: LockUserInterface,
|
||||
progressReporter: ProgressReporter,
|
||||
languageHome: Option[LanguageHome],
|
||||
edition: Editions.ResolvedEdition,
|
||||
preferLocalLibraries: Boolean
|
||||
): ResolvingLibraryProvider = {
|
||||
val locations = LibraryLocations.resolve(distributionManager, languageHome)
|
||||
val primaryCache = new DownloadingLibraryCache(
|
||||
locations.primaryCacheRoot,
|
||||
TemporaryDirectoryManager(distributionManager, resourceManager),
|
||||
resourceManager,
|
||||
lockUserInterface,
|
||||
progressReporter
|
||||
)
|
||||
val additionalCaches =
|
||||
locations.additionalCacheRoots.map(new LocalReadOnlyRepository(_))
|
||||
|
||||
val localLibraryProvider =
|
||||
new DefaultLocalLibraryProvider(locations.localLibrarySearchPaths)
|
||||
val publishedLibraryProvider =
|
||||
new DefaultPublishedLibraryProvider(primaryCache, additionalCaches)
|
||||
|
||||
new DefaultLibraryProvider(
|
||||
localLibraryProvider,
|
||||
publishedLibraryProvider,
|
||||
edition,
|
||||
preferLocalLibraries
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
package org.enso.librarymanager
|
||||
|
||||
import com.typesafe.scalalogging.Logger
|
||||
import org.enso.distribution.{DistributionManager, LanguageHome}
|
||||
import org.enso.logger.masking.MaskedPath
|
||||
|
||||
import java.nio.file.Path
|
||||
|
||||
/** Organizes locations which may hold libraries.
|
||||
*
|
||||
* @param localLibrarySearchPaths search paths of local (unpublished) libraries
|
||||
* @param primaryCacheRoot the primary cache, which is the location to which
|
||||
* new libraries will be downloaded
|
||||
* @param additionalCacheRoots additional caches, for example libraries
|
||||
* bundled with an engine release
|
||||
*/
|
||||
case class LibraryLocations(
|
||||
localLibrarySearchPaths: List[Path],
|
||||
primaryCacheRoot: Path,
|
||||
additionalCacheRoots: List[Path]
|
||||
)
|
||||
|
||||
object LibraryLocations {
|
||||
private lazy val logger = Logger[LibraryLocations]
|
||||
|
||||
/** Resolves the [[LibraryLocations]] based on the [[DistributionManager]]
|
||||
* which provides paths to the distribution and an optional [[LanguageHome]]
|
||||
* which can provide paths to libraries bundled with the current language
|
||||
* version.
|
||||
*/
|
||||
def resolve(
|
||||
distributionManager: DistributionManager,
|
||||
languageHome: Option[LanguageHome]
|
||||
): LibraryLocations = {
|
||||
val localLibrarySearchPaths =
|
||||
distributionManager.paths.localLibrariesSearchPaths.toList
|
||||
val cacheRoot = distributionManager.paths.cachedLibraries
|
||||
val additionalCacheLocations = {
|
||||
val engineBundleRoot = languageHome.map(_.libraries)
|
||||
val locations =
|
||||
engineBundleRoot.toList ++ distributionManager.auxiliaryLibraryCaches()
|
||||
locations.distinct
|
||||
}
|
||||
|
||||
def mask(path: Path): String = MaskedPath(path).applyMasking()
|
||||
|
||||
logger.trace(
|
||||
s"Local library search paths = ${localLibrarySearchPaths.map(mask)}"
|
||||
)
|
||||
logger.trace(
|
||||
s"Primary library cache = ${mask(cacheRoot)}"
|
||||
)
|
||||
logger.trace(
|
||||
s"Auxiliary (bundled) library caches = " +
|
||||
s"${additionalCacheLocations.map(mask)}"
|
||||
)
|
||||
|
||||
LibraryLocations(
|
||||
localLibrarySearchPaths = localLibrarySearchPaths,
|
||||
primaryCacheRoot = cacheRoot,
|
||||
additionalCacheRoots = additionalCacheLocations
|
||||
)
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package org.enso.librarymanager.local
|
||||
|
||||
import com.typesafe.scalalogging.Logger
|
||||
import org.enso.editions.LibraryName
|
||||
import org.enso.librarymanager.LibraryLocations
|
||||
import org.enso.logger.masking.MaskedPath
|
||||
|
||||
import java.nio.file.{Files, Path}
|
||||
@ -48,3 +49,12 @@ class DefaultLocalLibraryProvider(searchPaths: List[Path])
|
||||
case Nil => None
|
||||
}
|
||||
}
|
||||
|
||||
object DefaultLocalLibraryProvider {
|
||||
|
||||
/** Creates a [[DefaultLocalLibraryProvider]] from the [[LibraryLocations]]
|
||||
* configuration.
|
||||
*/
|
||||
def make(locations: LibraryLocations): DefaultLocalLibraryProvider =
|
||||
new DefaultLocalLibraryProvider(locations.localLibrarySearchPaths)
|
||||
}
|
||||
|
@ -0,0 +1,58 @@
|
||||
package org.enso.librarymanager.published
|
||||
|
||||
import nl.gn0s1s.bump.SemVer
|
||||
import org.enso.editions.{Editions, LibraryName}
|
||||
import org.enso.librarymanager.LibraryResolutionError
|
||||
import org.enso.librarymanager.published.cache.ReadOnlyLibraryCache
|
||||
|
||||
import java.nio.file.Path
|
||||
import scala.annotation.tailrec
|
||||
import scala.util.Try
|
||||
|
||||
/** A [[PublishedLibraryProvider]] that just provides libraries which are
|
||||
* already available in the cache.
|
||||
*/
|
||||
class CachedLibraryProvider(caches: List[ReadOnlyLibraryCache])
|
||||
extends PublishedLibraryProvider
|
||||
with PublishedLibraryCache {
|
||||
|
||||
@tailrec
|
||||
private def findCachedHelper(
|
||||
libraryName: LibraryName,
|
||||
version: SemVer,
|
||||
caches: List[ReadOnlyLibraryCache]
|
||||
): Option[Path] = caches match {
|
||||
case head :: tail =>
|
||||
head.findCachedLibrary(libraryName, version) match {
|
||||
case Some(found) => Some(found)
|
||||
case None => findCachedHelper(libraryName, version, tail)
|
||||
}
|
||||
case Nil => None
|
||||
}
|
||||
|
||||
/** Looks for the library in the known caches. */
|
||||
final protected def findCached(
|
||||
libraryName: LibraryName,
|
||||
version: SemVer
|
||||
): Option[Path] = findCachedHelper(libraryName, version, caches)
|
||||
|
||||
/** @inheritdoc */
|
||||
override def findLibrary(
|
||||
libraryName: LibraryName,
|
||||
version: SemVer,
|
||||
recommendedRepository: Editions.Repository
|
||||
): Try[Path] =
|
||||
findCached(libraryName, version)
|
||||
.toRight(
|
||||
LibraryResolutionError(
|
||||
s"Library [$libraryName:$version] was not found in the cache."
|
||||
)
|
||||
)
|
||||
.toTry
|
||||
|
||||
/** @inheritdoc */
|
||||
override def isLibraryCached(
|
||||
libraryName: LibraryName,
|
||||
version: SemVer
|
||||
): Boolean = findCached(libraryName, version).isDefined
|
||||
}
|
@ -9,7 +9,6 @@ import org.enso.librarymanager.published.cache.{
|
||||
}
|
||||
|
||||
import java.nio.file.Path
|
||||
import scala.annotation.tailrec
|
||||
import scala.util.{Success, Try}
|
||||
|
||||
/** A default implementation of [[PublishedLibraryProvider]] which uses one
|
||||
@ -19,24 +18,8 @@ import scala.util.{Success, Try}
|
||||
class DefaultPublishedLibraryProvider(
|
||||
primaryCache: LibraryCache,
|
||||
auxiliaryCaches: List[ReadOnlyLibraryCache]
|
||||
) extends PublishedLibraryProvider {
|
||||
) extends CachedLibraryProvider(caches = primaryCache :: auxiliaryCaches) {
|
||||
private val logger = Logger[DefaultPublishedLibraryProvider]
|
||||
private val caches: List[ReadOnlyLibraryCache] =
|
||||
primaryCache :: auxiliaryCaches
|
||||
|
||||
@tailrec
|
||||
private def findCached(
|
||||
libraryName: LibraryName,
|
||||
version: SemVer,
|
||||
caches: List[ReadOnlyLibraryCache]
|
||||
): Option[Path] = caches match {
|
||||
case head :: tail =>
|
||||
head.findCachedLibrary(libraryName, version) match {
|
||||
case Some(found) => Some(found)
|
||||
case None => findCached(libraryName, version, tail)
|
||||
}
|
||||
case Nil => None
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
override def findLibrary(
|
||||
@ -44,7 +27,7 @@ class DefaultPublishedLibraryProvider(
|
||||
version: SemVer,
|
||||
recommendedRepository: Editions.Repository
|
||||
): Try[Path] = {
|
||||
val cached = findCached(libraryName, version, caches)
|
||||
val cached = findCached(libraryName, version)
|
||||
cached.map(Success(_)).getOrElse {
|
||||
logger.trace(
|
||||
s"$libraryName was not found in any caches, it will need to be " +
|
||||
|
@ -0,0 +1,47 @@
|
||||
package org.enso.librarymanager.published
|
||||
|
||||
import nl.gn0s1s.bump.SemVer
|
||||
import org.enso.editions.LibraryName
|
||||
import org.enso.librarymanager.LibraryLocations
|
||||
import org.enso.librarymanager.published.bundles.LocalReadOnlyRepository
|
||||
|
||||
import java.nio.file.Path
|
||||
|
||||
/** An interface that allows to check if a given published library version is
|
||||
* cached.
|
||||
*/
|
||||
trait PublishedLibraryCache {
|
||||
|
||||
/** Checks if the library at the specific version is already available in the
|
||||
* caches.
|
||||
*/
|
||||
def isLibraryCached(libraryName: LibraryName, version: SemVer): Boolean
|
||||
}
|
||||
|
||||
object PublishedLibraryCache {
|
||||
|
||||
/** Creates a read only [[PublishedLibraryCache]] which can be used to check
|
||||
* which libraries are already cached.
|
||||
*/
|
||||
def makeReadOnlyCache(cacheLocations: List[Path]): PublishedLibraryCache =
|
||||
new CachedLibraryProvider(
|
||||
cacheLocations.map(new LocalReadOnlyRepository(_))
|
||||
)
|
||||
|
||||
/** Creates a read only [[PublishedLibraryCache]] which can be used to check
|
||||
* which libraries are already cached.
|
||||
*
|
||||
* This function creates a [[LocalReadOnlyRepository]] at the primary cache
|
||||
* location, which, as described in the documentation of that class, is
|
||||
* usually not recommended. This situation is however an exception - the
|
||||
* [[PublishedLibraryCache]] is only used to check if a library is cached or
|
||||
* not - so even if it responds with 'true' regarding a library that is still
|
||||
* being installed, any actual access of the library (an attempt to load it)
|
||||
* will use a proper synchronized cache instance and so will have to wait
|
||||
* until that installation is complete.
|
||||
*/
|
||||
def makeReadOnlyCache(locations: LibraryLocations): PublishedLibraryCache =
|
||||
makeReadOnlyCache(
|
||||
locations.primaryCacheRoot :: locations.additionalCacheRoots
|
||||
)
|
||||
}
|
@ -19,6 +19,10 @@ import java.nio.file.{Files, Path}
|
||||
* actions). So this class performs no synchronization and in the second case
|
||||
* it is the user's case to not import libraries that are in the middle of
|
||||
* being copied into this repository.
|
||||
*
|
||||
* Usually, this implementation should not be used for the primary cache, as
|
||||
* other processes can concurrently access it, so the access should be
|
||||
* synchronized.
|
||||
*/
|
||||
class LocalReadOnlyRepository(root: Path) extends ReadOnlyLibraryCache {
|
||||
private val logger = Logger[LocalReadOnlyRepository]
|
||||
|
Loading…
Reference in New Issue
Block a user