diff --git a/lib/scala/distribution-manager/src/main/scala/org/enso/distribution/DistributionManager.scala b/lib/scala/distribution-manager/src/main/scala/org/enso/distribution/DistributionManager.scala index 135428c1816b..f7ee44764572 100644 --- a/lib/scala/distribution-manager/src/main/scala/org/enso/distribution/DistributionManager.scala +++ b/lib/scala/distribution-manager/src/main/scala/org/enso/distribution/DistributionManager.scala @@ -422,7 +422,7 @@ class DistributionManager(val env: Environment) { * Should be used in places where not being able to determine the data * directory is not a fatal error. */ - def safeDataDirectory: Option[Path] = + private def safeDataDirectory: Option[Path] = Try(dataDirectory).toOption /** Determines whether a locally installed distribution exists on the diff --git a/lib/scala/distribution-manager/src/main/scala/org/enso/distribution/config/GlobalConfig.scala b/lib/scala/distribution-manager/src/main/scala/org/enso/distribution/config/GlobalConfig.scala index 11784a998451..64e9dd8c84ee 100644 --- a/lib/scala/distribution-manager/src/main/scala/org/enso/distribution/config/GlobalConfig.scala +++ b/lib/scala/distribution-manager/src/main/scala/org/enso/distribution/config/GlobalConfig.scala @@ -3,7 +3,6 @@ package org.enso.distribution.config import io.circe.syntax._ import io.circe.{Decoder, Encoder, Json, JsonObject} import org.enso.distribution.config -import org.enso.pkg.Contact /** Global user configuration. * @@ -26,17 +25,7 @@ case class GlobalConfig( authorEmail: Option[String], editionProviders: Seq[String], original: JsonObject -) { - - /** Returns a [[Contact]] for the default author if at least one of the name - * and email is set. - * - * If both name and email are not set, returns None. - */ - def defaultAuthor: Option[Contact] = - if (authorName.isEmpty && authorEmail.isEmpty) None - else Some(Contact(name = authorName, email = authorEmail)) -} +) object GlobalConfig { private val defaultEditionProviders: Seq[String] = Seq( diff --git a/lib/scala/edition-updater/src/main/scala/org/enso/editions/updater/EditionUpdater.scala b/lib/scala/edition-updater/src/main/scala/org/enso/editions/updater/EditionUpdater.scala index 7f5d2cdf5dca..0350291f9f3a 100644 --- a/lib/scala/edition-updater/src/main/scala/org/enso/editions/updater/EditionUpdater.scala +++ b/lib/scala/edition-updater/src/main/scala/org/enso/editions/updater/EditionUpdater.scala @@ -26,6 +26,23 @@ import scala.util.{Failure, Try} class EditionUpdater(cachePath: Path, sources: Seq[String]) { private lazy val logger = Logger[EditionUpdater] + /** Downloads requested edition from the [[sources]] to the [[cachePath]]. + * + * If there are errors when processing one of the edition sources or + * downloading the editions, the errors are logged as warnings, but other + * sources proceed as normal. + */ + def downloadEdition(name: String): Try[Unit] = Try { + for { + repositoryManifests <- fetchManifests() + (repositoryRoot, manifest) <- repositoryManifests + edition <- manifest.editions + if edition.name == name + } { + downloadEdition(repositoryRoot, edition) + } + } + /** Downloads edition lists from the [[sources]] and downloads any missing * editions to the [[cachePath]]. * @@ -35,23 +52,12 @@ class EditionUpdater(cachePath: Path, sources: Seq[String]) { */ def updateEditions(): Try[Unit] = Try { for { - source <- sources - repositoryRoot <- Try { URIBuilder.fromUri(source) } - .recoverWith { error => - logger.warn(s"Failed to parse the source URI [$source]: $error") - Failure(error) - } - manifest <- downloadEditionRepositoryManifest(repositoryRoot) - .recoverWith { error => - logger.warn(s"Failed to fetch editions from [$source]: $error") - Failure(error) - } - edition <- manifest.editions + repositoryManifests <- fetchManifests() + (repositoryRoot, manifest) <- repositoryManifests + edition <- manifest.editions if !isEditionAlreadyCached(edition) } { - downloadEdition(repositoryRoot, edition).getOrElse { - logger.warn(s"Failed to download edition [$edition] from [$source].") - } + downloadEdition(repositoryRoot, edition) } } @@ -65,7 +71,7 @@ class EditionUpdater(cachePath: Path, sources: Seq[String]) { YamlHelper.parseString[Manifest](response.content).toTry.get } - private def downloadEdition( + private def tryDownloadEdition( repositoryRoot: URIBuilder, editionName: EditionName ): Try[Unit] = Try { @@ -78,6 +84,33 @@ class EditionUpdater(cachePath: Path, sources: Seq[String]) { HTTPDownload.download(request, destinationPath).force() } + private def downloadEdition( + repositoryRoot: URIBuilder, + editionName: EditionName + ): Unit = + tryDownloadEdition(repositoryRoot, editionName).getOrElse { + logger.warn( + s"Failed to download edition [$editionName] from [${repositoryRoot.uri}]." + ) + } + + private def fetchManifests(): Try[Seq[(URIBuilder, Manifest)]] = Try { + for { + source <- sources + repositoryRoot <- Try { URIBuilder.fromUri(source) }.recoverWith { + error => + logger.warn(s"Failed to parse the source URI [$source]: $error") + Failure(error) + }.toOption + manifest <- downloadEditionRepositoryManifest( + repositoryRoot + ).recoverWith { error => + logger.warn(s"Failed to fetch editions from [$source]: $error") + Failure(error) + }.toOption + } yield (repositoryRoot, manifest) + } + private def isEditionAlreadyCached(editionName: EditionName): Boolean = Files.exists(cachePath.resolve(editionName.toFileName)) } diff --git a/lib/scala/edition-updater/src/main/scala/org/enso/editions/updater/UpdatingEditionProvider.scala b/lib/scala/edition-updater/src/main/scala/org/enso/editions/updater/UpdatingEditionProvider.scala index d06a34835aa2..e7e9a2856a94 100644 --- a/lib/scala/edition-updater/src/main/scala/org/enso/editions/updater/UpdatingEditionProvider.scala +++ b/lib/scala/edition-updater/src/main/scala/org/enso/editions/updater/UpdatingEditionProvider.scala @@ -26,23 +26,17 @@ class UpdatingEditionProvider( private val provider = new FileSystemEditionProvider(actualSearchPaths) private val updater = new EditionUpdater(cachePath, sources) - private var wasUpdateTried: Boolean = false - /** @inheritdoc */ override def findEditionForName( name: String - ): Either[EditionLoadingError, Editions.Raw.Edition] = { + ): Either[EditionLoadingError, Editions.Raw.Edition] = provider.findEditionForName(name) match { case Left(EditionNotFound(_)) => - if (!wasUpdateTried) { - wasUpdateTried = true - updater.updateEditions() - provider.findEditionForName(name) - } else Left(EditionNotFound(name)) + updater.downloadEdition(name) + provider.findEditionForName(name) case Left(otherError) => Left(otherError) case Right(value) => Right(value) } - } /** Finds all editions available on the [[searchPaths]]. */ override def findAvailableEditions(): Seq[String] = @@ -52,7 +46,6 @@ class UpdatingEditionProvider( def findAvailableEditions(update: Boolean): Seq[String] = { if (update) { updater.updateEditions() - wasUpdateTried = true } provider.findAvailableEditions()