All Downloads are FREE. Search and download functionalities are using the official Maven repository.

coursier.cli.setup.MaybeInstallJvm.scala Maven / Gradle / Ivy

There is a newer version: 2.1.13
Show newest version
package coursier.cli.setup

import java.io.File

import coursier.cache.Cache
import coursier.env.{EnvironmentUpdate, ProfileUpdater, WindowsEnvVarUpdater}
import coursier.jvm.{JvmCacheLogger, JavaHome}
import coursier.util.Task
import dataclass.data

@data class MaybeInstallJvm(
  coursierCache: Cache[Task],
  envVarUpdaterOpt: Option[Either[WindowsEnvVarUpdater, ProfileUpdater]],
  javaHome: JavaHome,
  confirm: Confirm,
  defaultId: String
) extends SetupStep {

  import MaybeInstallJvm.headerComment

  import MaybeSetupPath.dirStr

  def banner: String =
    "Checking if a JVM is installed"

  def task: Task[Unit] =
    for {
      initialIdJavaHomeOpt <- javaHome.getWithRetainedIdIfInstalled(defaultId)

      idJavaHomeOpt <- initialIdJavaHomeOpt match {
        case Some((id, javaHome0)) =>
          System.err.println(s"Found a JVM installed under $javaHome0.") // Task.delay(…)
          Task.point(Some(id -> javaHome0))
        case None =>
          confirm.confirm("No JVM found, should we try to install one?", default = true).flatMap {
            case false =>
              Task.point(None)
            case true =>
              javaHome.getWithRetainedId(defaultId).map(Some(_))
          }
      }

      envUpdate = idJavaHomeOpt match {
        case Some((id, javaHome0)) =>
          javaHome.environmentFor(id, javaHome0)
        case None =>
          EnvironmentUpdate.empty
      }

      updatedSomething <- {

        envVarUpdaterOpt match {
          case None =>
            Task.delay {
              println(envUpdate.script)
              false
            }
          case Some(Left(windowsEnvVarUpdater)) =>
            if (envUpdate.isEmpty) Task.point(false)
            else {
              val msg = s"Should we update the " +
                (envUpdate.set.map(_._1) ++ envUpdate.pathLikeAppends.map(_._1)).mkString(", ") +
                " environment variable(s)?"
              confirm.confirm(msg, default = true)
                .flatMap {
                  case false => Task.point(false)
                  case true =>
                    Task.delay {
                      windowsEnvVarUpdater.applyUpdate(envUpdate)
                    }
                }
            }
          case Some(Right(profileUpdater)) =>
            lazy val profileFiles = profileUpdater.profileFiles() // Task.delay(…)
            if (envUpdate.isEmpty || profileFiles.isEmpty /* just in case, should not happen */)
              Task.point(false)
            else {
              val profileFilesStr = profileFiles.map(_.toString.replaceAllLiterally(sys.props("user.home"), "~"))
              confirm.confirm(s"Should we update ${profileFilesStr.mkString(", ")}?", default = true).flatMap {
                case false => Task.point(false)
                case true =>
                  Task.delay {
                    profileUpdater.applyUpdate(envUpdate, headerComment)
                  }
              }
            }
        }
      }

      _ <- {
        if (updatedSomething)
          Task.delay {
            val messageStart =
              if (envVarUpdaterOpt.exists(_.isLeft))
                "Some global environment variables were updated."
              else
                "Some shell configuration files were updated."

            val message =
              messageStart + " It is recommended to close this terminal once " +
                "the setup command is done, and open a new one " +
                "for the changes to be taken into account."

            System.err.println(message)
          }
        else
          Task.point(())
      }

    } yield ()

  private def tryRevertEnvVarUpdate(
    envUpdate: EnvironmentUpdate,
    id: String
  ): Task[Unit] = {

    // FIXME Some duplication with MaybeSetupPath.revert

    val revertedTask = envVarUpdaterOpt match {
      case None =>
        Task.point(false)
      case Some(Left(windowsEnvVarUpdater)) =>
        Task.delay {
          windowsEnvVarUpdater.tryRevertUpdate(envUpdate)
        }
      case Some(Right(profileUpdater)) =>
        val profileFilesStr = profileUpdater.profileFiles().map(dirStr)
        Task.delay {
          profileUpdater.tryRevertUpdate(headerComment)
        }
    }

    val profileFilesOpt = envVarUpdaterOpt.flatMap {
      case Left(windowsEnvVarUpdater) =>
        None
      case Right(profileUpdater) =>
        val profileFilesStr = profileUpdater.profileFiles().map(dirStr)
        Some(profileFilesStr)
    }

    revertedTask.flatMap { reverted =>
      val message =
        if (reverted) s"Removed entries of JVM $id" + profileFilesOpt.fold("")(l => s" in ${l.mkString(", ")}")
        else s"JVM $id not setup"

      Task.delay(System.err.println(message))
    }
  }

  def tryRevert: Task[Unit] = {

    val maybeRemoveJvm = javaHome.cache
      .map { jvmCache =>
        val entryOpt = jvmCache.entry(defaultId)
          .unsafeRun()(coursierCache.ec) // meh
          .toOption
        val id = entryOpt.fold(defaultId)(_.id) // replaces version ranges with actual versions in particular
        val dir = jvmCache.directory(id)
        val dirExists = Task.delay(dir.exists())
        val removedOpt = dirExists.flatMap {
          case false =>
            Task.point(Some(false))
          case true =>
            jvmCache.delete(id)
        }

        val envUpdate = javaHome.environmentFor(id, dir)

        for {
          removedOpt0 <- removedOpt
          message = removedOpt0 match {
            case None => s"Could not remove JVM $id in $dir (concurrent operation ongoing)"
            case Some(false) => s"JVM $id was not installed"
            case Some(true) => s"Deleted JVM $id in $dir"
          }
          _ <- Task.delay(System.err.println(message))
          _ <- tryRevertEnvVarUpdate(envUpdate, id)
        } yield ()
      }
      .getOrElse(Task.point(()))

    maybeRemoveJvm
  }

}

object MaybeInstallJvm {

  def headerComment = "JVM installed by coursier"

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy