project/CurrentEnvironment.scala (76 lines of code) (raw):

import sbt.File import sbt.io.syntax.fileToRichFile object CurrentEnvironment { val OsName: String = System.getProperty("os.name").toLowerCase val UserHome: File = new File(System.getProperty("user.home")).getCanonicalFile.ensuring(_.exists()) val WorkingDir: File = new File(".").getCanonicalFile val CurrentJavaHome: File = new File(System.getProperty("java.home")) val CurrentJavaExecutablePath: String = (CurrentJavaHome / "bin/java").getCanonicalPath private val PossibleJvmLocations: Seq[File] = if (OsName.contains("mac")) Seq( new File("/Library/Java/JavaVirtualMachines"), new File(s"${UserHome.getPath}/Library/Java/JavaVirtualMachines") ) else if (OsName.contains("linux")) Seq( new File("/usr/lib/jvm"), new File("/usr/java") ) else if (OsName.contains("win")) Seq( new File("C:\\Program Files\\Java"), new File("C:\\Program Files (x86)\\Java") ) else throw new UnsupportedOperationException("Unknown operating system.") val JavaOldHome: File = findJvmInstallation("1.8") .orElse(findJvmInstallation("11")) .getOrElse { throw new IllegalStateException(s"Java 1.8 or 11 not found in default locations:\n${PossibleJvmLocations.mkString("\n")}") } val JavaOldExecutablePath: String = (JavaOldHome / "bin/java").getCanonicalPath val SbtGlobalRoot: File = new File(UserHome, ".sbt-structure-global").getCanonicalFile println( s"""java home : $CurrentJavaHome |java old home : $JavaOldHome |sbt global root : $SbtGlobalRoot |see sbt-launcher logs in $SbtGlobalRoot/boot/update.log""".stripMargin ) //TODO: replace with sbt.Keys.discoveredJavaHomes once this PR is merged and published // https://github.com/sbt/sbt/pull/8032 private def findJvmInstallation(javaVersion: String): Option[File] = { val jvmFolder = PossibleJvmLocations .flatMap { folder => val dirs = Option(folder.listFiles()).getOrElse(Array.empty).filter(_.isDirectory) dirs.filter(_.getName.contains(javaVersion)) } .headOption .map { root => if (OsName.contains("mac")) root / "/Contents/Home" else root } jvmFolder.filter(_.exists()) } lazy val getIvyHomeVmOptionForTeamcity: Seq[String] = if (CurrentEnvironment.isRunningOnTeamcity) { val ivyHomeResult = CurrentEnvironment.detectIvyHomeOnTeamcity ivyHomeResult.fold( error => { System.err.println(s"Failed to detect Ivy cache directory on TeamCity: $error") Nil }, dir => { println(s"Ivy cache directory on TeamCity: $dir") Seq(s"-Dsbt.ivy.home=$dir") } ) } else Nil private def isRunningOnTeamcity: Boolean = System.getenv("TEAMCITY_VERSION") != null /** * Sbt runner on teamcity uses a different ivy cache directory. * Unfortunately, it's hardcoded and is not published via TC parameters, so we can't read it here * * @see jetbrains.buildServer.sbt.SbtRunnerBuildService#getVMProperties * @see jetbrains.buildServer.sbt.IvyCacheProvider#IvyCacheProvider */ private def detectIvyHomeOnTeamcity: Either[String, File] = { val TeamcityAgentHomeDirProperty = "agent.home.dir" for { tcHome <- Option(System.getProperty(TeamcityAgentHomeDirProperty)).toRight(s"Undefined property: $TeamcityAgentHomeDirProperty") ivyHomeDirFile = new File(tcHome, "system/sbt_ivy") ivyHomeDir <- Option(ivyHomeDirFile).filter(_.exists()).toRight(s"Ivy cache directory doesn't exist: $ivyHomeDirFile") } yield ivyHomeDir } }