From 6b774286d1835b243bcdacf9ea149b32d4e193ad Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Wed, 18 Apr 2012 08:07:53 -0400 Subject: [PATCH 01/90] reorganize compilation modules --- compile/ivy/ComponentCompiler.scala | 92 +++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 compile/ivy/ComponentCompiler.scala diff --git a/compile/ivy/ComponentCompiler.scala b/compile/ivy/ComponentCompiler.scala new file mode 100644 index 000000000..e4431c127 --- /dev/null +++ b/compile/ivy/ComponentCompiler.scala @@ -0,0 +1,92 @@ +/* sbt -- Simple Build Tool + * Copyright 2009, 2010 Mark Harrah + */ +package sbt +package compiler + +import java.io.File + +object ComponentCompiler +{ + val xsbtiID = "xsbti" + val srcExtension = "-src" + val binSeparator = "-bin_" + val compilerInterfaceID = "compiler-interface" + val compilerInterfaceSrcID = compilerInterfaceID + srcExtension + val javaVersion = System.getProperty("java.class.version") + + def interfaceProvider(manager: ComponentManager): CompilerInterfaceProvider = new CompilerInterfaceProvider + { + def apply(scalaInstance: ScalaInstance, log: Logger): File = + { + // this is the instance used to compile the interface component + val componentCompiler = new ComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager) + log.debug("Getting " + compilerInterfaceID + " from component compiler for Scala " + scalaInstance.version) + componentCompiler(compilerInterfaceID) + } + } +} +/** This class provides source components compiled with the provided RawCompiler. +* The compiled classes are cached using the provided component manager according +* to the actualVersion field of the RawCompiler.*/ +class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) +{ + import ComponentCompiler._ + import sbt.IO.{copy, createDirectory, zip, jars, unzip, withTemporaryDirectory} + def apply(id: String): File = + try { getPrecompiled(id) } + catch { case _: InvalidComponent => getLocallyCompiled(id) } + + /** Gets the precompiled (distributed with sbt) component with the given 'id' + * If the component has not been precompiled, this throws InvalidComponent. */ + def getPrecompiled(id: String): File = manager.file( binaryID(id, false) )(IfMissing.Fail) + /** Get the locally compiled component with the given 'id' or compiles it if it has not been compiled yet. + * If the component does not exist, this throws InvalidComponent. */ + def getLocallyCompiled(id: String): File = + { + val binID = binaryID(id, true) + manager.file(binID)( new IfMissing.Define(true, compileAndInstall(id, binID)) ) + } + def clearCache(id: String): Unit = manager.clearCache(binaryID(id, true)) + protected def binaryID(id: String, withJavaVersion: Boolean) = + { + val base = id + binSeparator + compiler.scalaInstance.actualVersion + if(withJavaVersion) base + "__" + javaVersion else base + } + protected def compileAndInstall(id: String, binID: String) + { + val srcID = id + srcExtension + withTemporaryDirectory { binaryDirectory => + val targetJar = new File(binaryDirectory, id + ".jar") + compileSources(manager.files(srcID)(IfMissing.Fail), targetJar, id) + manager.define(binID, Seq(targetJar)) + } + } + /** Extract sources from source jars, compile them with the xsbti interfaces on the classpath, and package the compiled classes and + * any resources from the source jars into a final jar.*/ + private def compileSources(sourceJars: Iterable[File], targetJar: File, id: String) + { + val isSource = (f: File) => isSourceName(f.getName) + def keepIfSource(files: Set[File]): Set[File] = if(files.exists(isSource)) files else Set() + + withTemporaryDirectory { dir => + val extractedSources = (Set[File]() /: sourceJars) { (extracted, sourceJar)=> extracted ++ keepIfSource(unzip(sourceJar, dir)) } + val (sourceFiles, resources) = extractedSources.partition(isSource) + withTemporaryDirectory { outputDirectory => + val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail) + manager.log.info("'" + id + "' not yet compiled for Scala " + compiler.scalaInstance.actualVersion + ". Compiling...") + val start = System.currentTimeMillis + try + { + compiler(sourceFiles.toSeq, xsbtiJars.toSeq ++ sourceJars, outputDirectory, "-nowarn" :: Nil) + manager.log.info(" Compilation completed in " + (System.currentTimeMillis - start) / 1000.0 + " s") + } + catch { case e: xsbti.CompileFailed => throw new CompileFailed(e.arguments, "Error compiling sbt component '" + id + "'") } + import sbt.Path._ + copy(resources x rebase(dir, outputDirectory)) + zip((outputDirectory ***) x_! relativeTo(outputDirectory), targetJar) + } + } + } + private def isSourceName(name: String): Boolean = name.endsWith(".scala") || name.endsWith(".java") +} \ No newline at end of file From 8869378573fdd439756cc8ecc06ae37d9ee186ec Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Wed, 18 Apr 2012 16:01:45 -0400 Subject: [PATCH 02/90] implement embedded interface --- compile/ivy/ComponentCompiler.scala | 35 ++++------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/compile/ivy/ComponentCompiler.scala b/compile/ivy/ComponentCompiler.scala index e4431c127..f4732aabf 100644 --- a/compile/ivy/ComponentCompiler.scala +++ b/compile/ivy/ComponentCompiler.scala @@ -17,7 +17,7 @@ object ComponentCompiler def interfaceProvider(manager: ComponentManager): CompilerInterfaceProvider = new CompilerInterfaceProvider { - def apply(scalaInstance: ScalaInstance, log: Logger): File = + def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { // this is the instance used to compile the interface component val componentCompiler = new ComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager) @@ -32,7 +32,6 @@ object ComponentCompiler class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) { import ComponentCompiler._ - import sbt.IO.{copy, createDirectory, zip, jars, unzip, withTemporaryDirectory} def apply(id: String): File = try { getPrecompiled(id) } catch { case _: InvalidComponent => getLocallyCompiled(id) } @@ -56,37 +55,11 @@ class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) protected def compileAndInstall(id: String, binID: String) { val srcID = id + srcExtension - withTemporaryDirectory { binaryDirectory => + IO.withTemporaryDirectory { binaryDirectory => val targetJar = new File(binaryDirectory, id + ".jar") - compileSources(manager.files(srcID)(IfMissing.Fail), targetJar, id) + val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail) + AnalyzingCompiler.compileSources(manager.files(srcID)(IfMissing.Fail), targetJar, xsbtiJars, id, compiler, manager.log) manager.define(binID, Seq(targetJar)) } } - /** Extract sources from source jars, compile them with the xsbti interfaces on the classpath, and package the compiled classes and - * any resources from the source jars into a final jar.*/ - private def compileSources(sourceJars: Iterable[File], targetJar: File, id: String) - { - val isSource = (f: File) => isSourceName(f.getName) - def keepIfSource(files: Set[File]): Set[File] = if(files.exists(isSource)) files else Set() - - withTemporaryDirectory { dir => - val extractedSources = (Set[File]() /: sourceJars) { (extracted, sourceJar)=> extracted ++ keepIfSource(unzip(sourceJar, dir)) } - val (sourceFiles, resources) = extractedSources.partition(isSource) - withTemporaryDirectory { outputDirectory => - val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail) - manager.log.info("'" + id + "' not yet compiled for Scala " + compiler.scalaInstance.actualVersion + ". Compiling...") - val start = System.currentTimeMillis - try - { - compiler(sourceFiles.toSeq, xsbtiJars.toSeq ++ sourceJars, outputDirectory, "-nowarn" :: Nil) - manager.log.info(" Compilation completed in " + (System.currentTimeMillis - start) / 1000.0 + " s") - } - catch { case e: xsbti.CompileFailed => throw new CompileFailed(e.arguments, "Error compiling sbt component '" + id + "'") } - import sbt.Path._ - copy(resources x rebase(dir, outputDirectory)) - zip((outputDirectory ***) x_! relativeTo(outputDirectory), targetJar) - } - } - } - private def isSourceName(name: String): Boolean = name.endsWith(".scala") || name.endsWith(".java") } \ No newline at end of file From 62fcc2a9b31e0b7ba7d32fff93b51ad821dd9dbd Mon Sep 17 00:00:00 2001 From: Grzegorz Kossakowski Date: Fri, 7 Dec 2012 10:27:08 -0800 Subject: [PATCH 03/90] Follow source layout convention supported by Eclipse. Moved source files so directory structure follow package structure. That makes it possible to use Scala Eclipse plugin with sbt's source code. --- .../ivy/{ => src/main/scala/sbt/compiler}/ComponentCompiler.scala | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename compile/ivy/{ => src/main/scala/sbt/compiler}/ComponentCompiler.scala (100%) diff --git a/compile/ivy/ComponentCompiler.scala b/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala similarity index 100% rename from compile/ivy/ComponentCompiler.scala rename to compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala From 2b526e6aa7511baec459c5434e6d31515b8db091 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 1 May 2014 12:50:07 -0400 Subject: [PATCH 04/90] added scalariform --- .../sbt/compiler/ComponentCompiler.scala | 108 +++++++++--------- 1 file changed, 55 insertions(+), 53 deletions(-) diff --git a/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index f4732aabf..24d4f0530 100644 --- a/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -6,60 +6,62 @@ package compiler import java.io.File -object ComponentCompiler -{ - val xsbtiID = "xsbti" - val srcExtension = "-src" - val binSeparator = "-bin_" - val compilerInterfaceID = "compiler-interface" - val compilerInterfaceSrcID = compilerInterfaceID + srcExtension - val javaVersion = System.getProperty("java.class.version") +object ComponentCompiler { + val xsbtiID = "xsbti" + val srcExtension = "-src" + val binSeparator = "-bin_" + val compilerInterfaceID = "compiler-interface" + val compilerInterfaceSrcID = compilerInterfaceID + srcExtension + val javaVersion = System.getProperty("java.class.version") - def interfaceProvider(manager: ComponentManager): CompilerInterfaceProvider = new CompilerInterfaceProvider - { - def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = - { - // this is the instance used to compile the interface component - val componentCompiler = new ComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager) - log.debug("Getting " + compilerInterfaceID + " from component compiler for Scala " + scalaInstance.version) - componentCompiler(compilerInterfaceID) - } - } + def interfaceProvider(manager: ComponentManager): CompilerInterfaceProvider = new CompilerInterfaceProvider { + def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = + { + // this is the instance used to compile the interface component + val componentCompiler = new ComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager) + log.debug("Getting " + compilerInterfaceID + " from component compiler for Scala " + scalaInstance.version) + componentCompiler(compilerInterfaceID) + } + } } -/** This class provides source components compiled with the provided RawCompiler. -* The compiled classes are cached using the provided component manager according -* to the actualVersion field of the RawCompiler.*/ -class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) -{ - import ComponentCompiler._ - def apply(id: String): File = - try { getPrecompiled(id) } - catch { case _: InvalidComponent => getLocallyCompiled(id) } +/** + * This class provides source components compiled with the provided RawCompiler. + * The compiled classes are cached using the provided component manager according + * to the actualVersion field of the RawCompiler. + */ +class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) { + import ComponentCompiler._ + def apply(id: String): File = + try { getPrecompiled(id) } + catch { case _: InvalidComponent => getLocallyCompiled(id) } - /** Gets the precompiled (distributed with sbt) component with the given 'id' - * If the component has not been precompiled, this throws InvalidComponent. */ - def getPrecompiled(id: String): File = manager.file( binaryID(id, false) )(IfMissing.Fail) - /** Get the locally compiled component with the given 'id' or compiles it if it has not been compiled yet. - * If the component does not exist, this throws InvalidComponent. */ - def getLocallyCompiled(id: String): File = - { - val binID = binaryID(id, true) - manager.file(binID)( new IfMissing.Define(true, compileAndInstall(id, binID)) ) - } - def clearCache(id: String): Unit = manager.clearCache(binaryID(id, true)) - protected def binaryID(id: String, withJavaVersion: Boolean) = - { - val base = id + binSeparator + compiler.scalaInstance.actualVersion - if(withJavaVersion) base + "__" + javaVersion else base - } - protected def compileAndInstall(id: String, binID: String) - { - val srcID = id + srcExtension - IO.withTemporaryDirectory { binaryDirectory => - val targetJar = new File(binaryDirectory, id + ".jar") - val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail) - AnalyzingCompiler.compileSources(manager.files(srcID)(IfMissing.Fail), targetJar, xsbtiJars, id, compiler, manager.log) - manager.define(binID, Seq(targetJar)) - } - } + /** + * Gets the precompiled (distributed with sbt) component with the given 'id' + * If the component has not been precompiled, this throws InvalidComponent. + */ + def getPrecompiled(id: String): File = manager.file(binaryID(id, false))(IfMissing.Fail) + /** + * Get the locally compiled component with the given 'id' or compiles it if it has not been compiled yet. + * If the component does not exist, this throws InvalidComponent. + */ + def getLocallyCompiled(id: String): File = + { + val binID = binaryID(id, true) + manager.file(binID)(new IfMissing.Define(true, compileAndInstall(id, binID))) + } + def clearCache(id: String): Unit = manager.clearCache(binaryID(id, true)) + protected def binaryID(id: String, withJavaVersion: Boolean) = + { + val base = id + binSeparator + compiler.scalaInstance.actualVersion + if (withJavaVersion) base + "__" + javaVersion else base + } + protected def compileAndInstall(id: String, binID: String) { + val srcID = id + srcExtension + IO.withTemporaryDirectory { binaryDirectory => + val targetJar = new File(binaryDirectory, id + ".jar") + val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail) + AnalyzingCompiler.compileSources(manager.files(srcID)(IfMissing.Fail), targetJar, xsbtiJars, id, compiler, manager.log) + manager.define(binID, Seq(targetJar)) + } + } } \ No newline at end of file From c4eb6705886a7462668e3a1647386557df299f8d Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Wed, 15 Jul 2015 10:01:11 +0200 Subject: [PATCH 05/90] Find most specific version of compiler interface sources This commit introduces a mechanism that allows sbt to find the most specific version of the compiler interface sources that exists using Ivy. For instance, when asked for a compiler interface for Scala 2.11.8-M2, sbt will look for sources for: - 2.11.8-M2 ; - 2.11.8 ; - 2.11 ; - the default sources. This commit also modifies the build definition by removing the precompiled projects and configuring the compiler-interface project so that it publishes its source artifacts in a Maven-friendly format. --- .../sbt/compiler/ComponentCompiler.scala | 143 +++++++++++++++++- 1 file changed, 142 insertions(+), 1 deletion(-) diff --git a/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index 24d4f0530..3192e42c6 100644 --- a/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -5,6 +5,7 @@ package sbt package compiler import java.io.File +import scala.util.Try object ComponentCompiler { val xsbtiID = "xsbti" @@ -14,6 +15,7 @@ object ComponentCompiler { val compilerInterfaceSrcID = compilerInterfaceID + srcExtension val javaVersion = System.getProperty("java.class.version") + @deprecated("Use `interfaceProvider(ComponentManager, IvyConfiguration)`.", "0.13.10") def interfaceProvider(manager: ComponentManager): CompilerInterfaceProvider = new CompilerInterfaceProvider { def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { @@ -23,12 +25,23 @@ object ComponentCompiler { componentCompiler(compilerInterfaceID) } } + + def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration): CompilerInterfaceProvider = new CompilerInterfaceProvider { + def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = + { + // this is the instance used to compile the interface component + val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager, ivyConfiguration, log) + log.debug("Getting " + compilerInterfaceID + " from component compiler for Scala " + scalaInstance.version) + componentCompiler(compilerInterfaceID) + } + } } /** * This class provides source components compiled with the provided RawCompiler. * The compiled classes are cached using the provided component manager according * to the actualVersion field of the RawCompiler. */ +@deprecated("Replaced by IvyComponentCompiler.", "0.13.10") class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) { import ComponentCompiler._ def apply(id: String): File = @@ -64,4 +77,132 @@ class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) { manager.define(binID, Seq(targetJar)) } } -} \ No newline at end of file +} + +/** + * Component compiler which is able to find the most specific version available of + * the compiler interface sources using Ivy. + * The compiled classes are cached using the provided component manager according + * to the actualVersion field of the RawCompiler. + */ +private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, log: Logger) { + import ComponentCompiler._ + + private val sbtOrgTemp = JsonUtil.sbtOrgTemp + private val modulePrefixTemp = "temp-module-" + private val ivySbt: IvySbt = new IvySbt(ivyConfiguration) + private val sbtVersion = ComponentManager.version + + def apply(id: String): File = { + val binID = binaryID(id) + manager.file(binID)(new IfMissing.Define(true, compileAndInstall(id, binID))) + } + + private def binaryID(id: String): String = { + val base = id + binSeparator + compiler.scalaInstance.actualVersion + base + "__" + javaVersion + } + + private def compileAndInstall(id: String, binID: String): Unit = { + def interfaceSources(moduleVersions: Vector[VersionNumber]): Iterable[File] = + moduleVersions match { + case Vector() => + def getAndDefineDefaultSources() = + update(getModule(id))(_.getName endsWith "-sources.jar") map { sourcesJar => + manager.define(id, sourcesJar) + sourcesJar + } getOrElse (throw new InvalidComponent(s"Couldn't retrieve default sources: module '$id'")) + + log.debug(s"Fetching default sources: module '$id'") + manager.files(id)(new IfMissing.Fallback(getAndDefineDefaultSources())) + + case version +: rest => + val moduleName = s"${id}_$version" + def getAndDefineVersionSpecificSources() = + update(getModule(moduleName))(_.getName endsWith "-sources.jar") map { sourcesJar => + manager.define(moduleName, sourcesJar) + sourcesJar + } getOrElse interfaceSources(rest) + + log.debug(s"Fetching version-specific sources: module '$moduleName'") + manager.files(moduleName)(new IfMissing.Fallback(getAndDefineVersionSpecificSources())) + } + IO.withTemporaryDirectory { binaryDirectory => + + val targetJar = new File(binaryDirectory, s"$binID.jar") + val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail) + + val sourceModuleVersions = VersionNumber(compiler.scalaInstance.actualVersion).cascadingVersions + AnalyzingCompiler.compileSources(interfaceSources(sourceModuleVersions), targetJar, xsbtiJars, id, compiler, log) + + manager.define(binID, Seq(targetJar)) + + } + } + + /** + * Returns a dummy module that depends on "org.scala-sbt" % `id` % `sbtVersion`. + * Note: Sbt's implementation of Ivy requires us to do this, because only the dependencies + * of the specified module will be downloaded. + */ + private def getModule(id: String): ivySbt.Module = { + val sha1 = Hash.toHex(Hash(id)) + val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, sbtVersion, Some("component")) + val moduleID = ModuleID(xsbti.ArtifactInfo.SbtOrganization, id, sbtVersion, Some("component")).sources() + getModule(dummyID, Seq(moduleID)) + } + + private def getModule(moduleID: ModuleID, deps: Seq[ModuleID], uo: UpdateOptions = UpdateOptions()): ivySbt.Module = { + val moduleSetting = InlineConfiguration( + module = moduleID, + moduleInfo = ModuleInfo(moduleID.name), + dependencies = deps, + configurations = Seq(Configurations.Component), + ivyScala = None) + + new ivySbt.Module(moduleSetting) + } + + private def dependenciesNames(module: ivySbt.Module): String = module.moduleSettings match { + // `module` is a dummy module, we will only fetch its dependencies. + case ic: InlineConfiguration => + ic.dependencies map { + case mID: ModuleID => + import mID._ + s"$organization % $name % $revision" + } mkString ", " + case _ => + s"unknown" + } + + private def update(module: ivySbt.Module)(predicate: File => Boolean): Option[Seq[File]] = { + + val retrieveDirectory = new File(ivyConfiguration.baseDirectory, "component") + val retrieveConfiguration = new RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false) + val updateConfiguration = new UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly) + + log.info(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.") + IvyActions.updateEither(module, updateConfiguration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, log) match { + case Left(unresolvedWarning) => + log.debug("Couldn't retrieve module ${dependenciesNames(module)}.") + None + + case Right(updateReport) => + val allFiles = + for { + conf <- updateReport.configurations + m <- conf.modules + (_, f) <- m.artifacts + } yield f + + log.debug(s"Files retrieved for ${dependenciesNames(module)}:") + log.debug(allFiles mkString ", ") + + allFiles filter predicate match { + case Seq() => None + case files => Some(files) + } + + } + } +} From 25dde24edaf4ac80409c56d46b20ea36ec30acad Mon Sep 17 00:00:00 2001 From: Pierre DAL-PRA Date: Mon, 3 Aug 2015 23:13:59 +0200 Subject: [PATCH 06/90] Replace procedure syntax by explicit Unit annotation --- compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index 3192e42c6..f203c58ca 100644 --- a/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -68,7 +68,7 @@ class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) { val base = id + binSeparator + compiler.scalaInstance.actualVersion if (withJavaVersion) base + "__" + javaVersion else base } - protected def compileAndInstall(id: String, binID: String) { + protected def compileAndInstall(id: String, binID: String): Unit = { val srcID = id + srcExtension IO.withTemporaryDirectory { binaryDirectory => val targetJar = new File(binaryDirectory, id + ".jar") From 71e037ea4e37765e313bc86c7c800aa7291062e3 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 4 Aug 2015 18:06:04 -0400 Subject: [PATCH 07/90] moved subprojects around --- .../src/main/scala/sbt/compiler/ComponentCompiler.scala | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {compile/ivy => internal/compile-ivy}/src/main/scala/sbt/compiler/ComponentCompiler.scala (100%) diff --git a/compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala similarity index 100% rename from compile/ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala rename to internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala From 392b91c21fe3e70f483773d20d8c14ad97f4da86 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Mon, 31 Aug 2015 03:43:29 +0200 Subject: [PATCH 08/90] Update to sbt/io 1.0.0-M1, fix dependencies --- .../src/main/scala/sbt/compiler/ComponentCompiler.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index f203c58ca..8b45096c5 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -6,6 +6,7 @@ package compiler import java.io.File import scala.util.Try +import sbt.io.{ Hash, IO } object ComponentCompiler { val xsbtiID = "xsbti" From e2ddae8d98a2b858a7217b71c320144a04a66f6f Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Tue, 1 Sep 2015 15:34:41 +0200 Subject: [PATCH 09/90] Add recommended compiler flags, suppress a lot of warnings --- .../src/main/scala/sbt/compiler/ComponentCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index 8b45096c5..0bb3779c0 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -185,7 +185,7 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com log.info(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.") IvyActions.updateEither(module, updateConfiguration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, log) match { case Left(unresolvedWarning) => - log.debug("Couldn't retrieve module ${dependenciesNames(module)}.") + log.debug(s"Couldn't retrieve module ${dependenciesNames(module)}.") None case Right(updateReport) => From aec1e5fd52ad3880f28885a3c63834e250b7098b Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Wed, 2 Sep 2015 16:33:52 +0200 Subject: [PATCH 10/90] Fix error in migration to sbt/io --- .../src/main/scala/sbt/compiler/ComponentCompiler.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index 0bb3779c0..5ba9a2d93 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -92,6 +92,7 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com private val sbtOrgTemp = JsonUtil.sbtOrgTemp private val modulePrefixTemp = "temp-module-" private val ivySbt: IvySbt = new IvySbt(ivyConfiguration) + // TODO: The actual sbt version may be different from the component manager's version private val sbtVersion = ComponentManager.version def apply(id: String): File = { @@ -149,7 +150,7 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com private def getModule(id: String): ivySbt.Module = { val sha1 = Hash.toHex(Hash(id)) val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, sbtVersion, Some("component")) - val moduleID = ModuleID(xsbti.ArtifactInfo.SbtOrganization, id, sbtVersion, Some("component")).sources() + val moduleID = ModuleID(xsbti.ArtifactInfo.SbtOrganization + ".incrementalcompiler", id, sbtVersion, Some("component")).sources() getModule(dummyID, Seq(moduleID)) } From ee0f73addbd13062c6a46efe89656f766c479d6e Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Thu, 27 Aug 2015 09:02:46 +0200 Subject: [PATCH 11/90] Hide Ivy logs in compiler-interface sources retrieval Because in most cases there aren't version-specific sources, we expect the retrieval to fail a number of times before succeeding. This generates a lot of noise in sbt's log, so the logs will now be shown if and only all the versions fail. --- .../scala/sbt/compiler/ComponentCompiler.scala | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index 5ba9a2d93..ee7e64e50 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -94,6 +94,7 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com private val ivySbt: IvySbt = new IvySbt(ivyConfiguration) // TODO: The actual sbt version may be different from the component manager's version private val sbtVersion = ComponentManager.version + private val buffered = new BufferedLogger(FullLogger(log)) def apply(id: String): File = { val binID = binaryID(id) @@ -115,7 +116,7 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com sourcesJar } getOrElse (throw new InvalidComponent(s"Couldn't retrieve default sources: module '$id'")) - log.debug(s"Fetching default sources: module '$id'") + buffered.debug(s"Fetching default sources: module '$id'") manager.files(id)(new IfMissing.Fallback(getAndDefineDefaultSources())) case version +: rest => @@ -126,7 +127,7 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com sourcesJar } getOrElse interfaceSources(rest) - log.debug(s"Fetching version-specific sources: module '$moduleName'") + buffered.debug(s"Fetching version-specific sources: module '$moduleName'") manager.files(moduleName)(new IfMissing.Fallback(getAndDefineVersionSpecificSources())) } IO.withTemporaryDirectory { binaryDirectory => @@ -135,7 +136,8 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail) val sourceModuleVersions = VersionNumber(compiler.scalaInstance.actualVersion).cascadingVersions - AnalyzingCompiler.compileSources(interfaceSources(sourceModuleVersions), targetJar, xsbtiJars, id, compiler, log) + val sources = buffered bufferQuietly interfaceSources(sourceModuleVersions) + AnalyzingCompiler.compileSources(sources, targetJar, xsbtiJars, id, compiler, log) manager.define(binID, Seq(targetJar)) @@ -183,10 +185,10 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com val retrieveConfiguration = new RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false) val updateConfiguration = new UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly) - log.info(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.") - IvyActions.updateEither(module, updateConfiguration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, log) match { + buffered.info(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.") + IvyActions.updateEither(module, updateConfiguration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, buffered) match { case Left(unresolvedWarning) => - log.debug(s"Couldn't retrieve module ${dependenciesNames(module)}.") + buffered.debug(s"Couldn't retrieve module ${dependenciesNames(module)}.") None case Right(updateReport) => @@ -197,8 +199,8 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com (_, f) <- m.artifacts } yield f - log.debug(s"Files retrieved for ${dependenciesNames(module)}:") - log.debug(allFiles mkString ", ") + buffered.debug(s"Files retrieved for ${dependenciesNames(module)}:") + buffered.debug(allFiles mkString ", ") allFiles filter predicate match { case Seq() => None From 00101022e1e7d42f63179808edef51beac76dbe6 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Thu, 27 Aug 2015 09:03:49 +0200 Subject: [PATCH 12/90] Download compiler interface sources in boot directory --- .../main/scala/sbt/compiler/ComponentCompiler.scala | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index ee7e64e50..cf3cc9891 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -16,7 +16,7 @@ object ComponentCompiler { val compilerInterfaceSrcID = compilerInterfaceID + srcExtension val javaVersion = System.getProperty("java.class.version") - @deprecated("Use `interfaceProvider(ComponentManager, IvyConfiguration)`.", "0.13.10") + @deprecated("Use `interfaceProvider(ComponentManager, IvyConfiguration, File)`.", "0.13.10") def interfaceProvider(manager: ComponentManager): CompilerInterfaceProvider = new CompilerInterfaceProvider { def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { @@ -27,11 +27,11 @@ object ComponentCompiler { } } - def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration): CompilerInterfaceProvider = new CompilerInterfaceProvider { + def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration, bootDirectory: File): CompilerInterfaceProvider = new CompilerInterfaceProvider { def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { // this is the instance used to compile the interface component - val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager, ivyConfiguration, log) + val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager, ivyConfiguration, bootDirectory, log) log.debug("Getting " + compilerInterfaceID + " from component compiler for Scala " + scalaInstance.version) componentCompiler(compilerInterfaceID) } @@ -86,15 +86,17 @@ class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) { * The compiled classes are cached using the provided component manager according * to the actualVersion field of the RawCompiler. */ -private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, log: Logger) { +private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, bootDirectory: File, log: Logger) { import ComponentCompiler._ + private val incrementalCompilerOrg = xsbti.ArtifactInfo.SbtOrganization + ".incrementalcompiler" private val sbtOrgTemp = JsonUtil.sbtOrgTemp private val modulePrefixTemp = "temp-module-" private val ivySbt: IvySbt = new IvySbt(ivyConfiguration) // TODO: The actual sbt version may be different from the component manager's version private val sbtVersion = ComponentManager.version private val buffered = new BufferedLogger(FullLogger(log)) + private val retrieveDirectory = new File(s"$bootDirectory/scala-${compiler.scalaInstance.version}/$incrementalCompilerOrg/sbt/$sbtVersion/compiler-interface-srcs") def apply(id: String): File = { val binID = binaryID(id) @@ -181,7 +183,6 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com private def update(module: ivySbt.Module)(predicate: File => Boolean): Option[Seq[File]] = { - val retrieveDirectory = new File(ivyConfiguration.baseDirectory, "component") val retrieveConfiguration = new RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false) val updateConfiguration = new UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly) From f87fe3fb161fb30ea92c4fae0ec5739fa0ecc3f7 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Tue, 8 Sep 2015 09:55:26 +0200 Subject: [PATCH 13/90] Update sbt modules, migrate to scalatest - Update sbt/util to 1.0.0-M3 - Update sbt/librarymanagement to 1.0.0-M2 Also, migrate the tests from specs2 to scalatest. --- .../src/main/scala/sbt/compiler/ComponentCompiler.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index 5ba9a2d93..789203f53 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -7,6 +7,9 @@ package compiler import java.io.File import scala.util.Try import sbt.io.{ Hash, IO } +import sbt.internal.librarymanagement._ +import sbt.librarymanagement.{ Configurations, ModuleID, ModuleInfo, Resolver, UpdateOptions, VersionNumber } +import sbt.util.Logger object ComponentCompiler { val xsbtiID = "xsbti" From 90f3b7eb9e096e788bfe25eab4171c948d66a9dd Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 8 Sep 2015 17:06:24 -0400 Subject: [PATCH 14/90] Fixes build --- .../src/main/scala/sbt/compiler/ComponentCompiler.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index 5200ca24d..c8d01524c 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -10,6 +10,7 @@ import sbt.io.{ Hash, IO } import sbt.internal.librarymanagement._ import sbt.librarymanagement.{ Configurations, ModuleID, ModuleInfo, Resolver, UpdateOptions, VersionNumber } import sbt.util.Logger +import sbt.internal.util.{ BufferedLogger, FullLogger } object ComponentCompiler { val xsbtiID = "xsbti" From 4f0b1071dfb6dc54b907c637184b2e4032764984 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Wed, 9 Sep 2015 16:45:01 +0200 Subject: [PATCH 15/90] Retrieve version of compiler interface from properties file Previously we used the version of the component manager. However, these two versions do not need to be in sync, which would make us try to retrieve the wrong version of the compiler interface sources. --- .../scala/sbt/compiler/ComponentCompiler.scala | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index c8d01524c..a2dced311 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -40,6 +40,13 @@ object ComponentCompiler { componentCompiler(compilerInterfaceID) } } + + lazy val incrementalVersion = { + val properties = new java.util.Properties + val propertiesStream = getClass.getResource("/incrementalcompiler.version.properties").openStream + try { properties.load(propertiesStream) } finally { propertiesStream.close() } + properties.getProperty("version") + } } /** * This class provides source components compiled with the provided RawCompiler. @@ -97,10 +104,8 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com private val sbtOrgTemp = JsonUtil.sbtOrgTemp private val modulePrefixTemp = "temp-module-" private val ivySbt: IvySbt = new IvySbt(ivyConfiguration) - // TODO: The actual sbt version may be different from the component manager's version - private val sbtVersion = ComponentManager.version private val buffered = new BufferedLogger(FullLogger(log)) - private val retrieveDirectory = new File(s"$bootDirectory/scala-${compiler.scalaInstance.version}/$incrementalCompilerOrg/sbt/$sbtVersion/compiler-interface-srcs") + private val retrieveDirectory = new File(s"$bootDirectory/scala-${compiler.scalaInstance.version}/$incrementalCompilerOrg/sbt/$incrementalVersion/compiler-interface-srcs") def apply(id: String): File = { val binID = binaryID(id) @@ -151,14 +156,14 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com } /** - * Returns a dummy module that depends on "org.scala-sbt" % `id` % `sbtVersion`. + * Returns a dummy module that depends on "org.scala-sbt" % `id` % `incrementalVersion`. * Note: Sbt's implementation of Ivy requires us to do this, because only the dependencies * of the specified module will be downloaded. */ private def getModule(id: String): ivySbt.Module = { val sha1 = Hash.toHex(Hash(id)) - val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, sbtVersion, Some("component")) - val moduleID = ModuleID(xsbti.ArtifactInfo.SbtOrganization + ".incrementalcompiler", id, sbtVersion, Some("component")).sources() + val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, incrementalVersion, Some("component")) + val moduleID = ModuleID(xsbti.ArtifactInfo.SbtOrganization + ".incrementalcompiler", id, incrementalVersion, Some("component")).sources() getModule(dummyID, Seq(moduleID)) } From d110e6937b1a58e6093e9a6be96e51f4efbc7f4e Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 11 Sep 2015 10:12:02 +0200 Subject: [PATCH 16/90] Specify the compiler bridge module in a setting In order to restore reproducibility of builds, we no longer cascade over the possibly available versions of the compiler bridge sources (a specific version of the bridge sources may not be available one day, but exist on the next day), but rather let the build definition configure which module to use. Fixes sbt/sbt#2196 --- .../sbt/compiler/ComponentCompiler.scala | 71 +++++++------------ 1 file changed, 25 insertions(+), 46 deletions(-) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index a2dced311..057da6bd9 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -31,13 +31,13 @@ object ComponentCompiler { } } - def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration, bootDirectory: File): CompilerInterfaceProvider = new CompilerInterfaceProvider { + def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID, bootDirectory: File): CompilerInterfaceProvider = new CompilerInterfaceProvider { def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { // this is the instance used to compile the interface component - val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager, ivyConfiguration, bootDirectory, log) - log.debug("Getting " + compilerInterfaceID + " from component compiler for Scala " + scalaInstance.version) - componentCompiler(compilerInterfaceID) + val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager, ivyConfiguration, sourcesModule, bootDirectory, log) + log.debug("Getting " + sourcesModule + " from component compiler for Scala " + scalaInstance.version) + componentCompiler() } } @@ -92,12 +92,12 @@ class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) { } /** - * Component compiler which is able to find the most specific version available of - * the compiler interface sources using Ivy. + * Component compiler which is able to to retrieve the compiler bridge sources + * `sourceModule` using Ivy. * The compiled classes are cached using the provided component manager according * to the actualVersion field of the RawCompiler. */ -private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, bootDirectory: File, log: Logger) { +private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID, bootDirectory: File, log: Logger) { import ComponentCompiler._ private val incrementalCompilerOrg = xsbti.ArtifactInfo.SbtOrganization + ".incrementalcompiler" @@ -105,11 +105,11 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com private val modulePrefixTemp = "temp-module-" private val ivySbt: IvySbt = new IvySbt(ivyConfiguration) private val buffered = new BufferedLogger(FullLogger(log)) - private val retrieveDirectory = new File(s"$bootDirectory/scala-${compiler.scalaInstance.version}/$incrementalCompilerOrg/sbt/$incrementalVersion/compiler-interface-srcs") + private val retrieveDirectory = new File(s"$bootDirectory/scala-${compiler.scalaInstance.version}/$incrementalCompilerOrg/sbt/$incrementalVersion/compiler-interface-srcs/${sourcesModule.name}/${sourcesModule.revision}") - def apply(id: String): File = { - val binID = binaryID(id) - manager.file(binID)(new IfMissing.Define(true, compileAndInstall(id, binID))) + def apply(): File = { + val binID = binaryID(sourcesModule.name) + manager.file(binID)(new IfMissing.Define(true, compileAndInstall(binID))) } private def binaryID(id: String): String = { @@ -117,53 +117,32 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com base + "__" + javaVersion } - private def compileAndInstall(id: String, binID: String): Unit = { - def interfaceSources(moduleVersions: Vector[VersionNumber]): Iterable[File] = - moduleVersions match { - case Vector() => - def getAndDefineDefaultSources() = - update(getModule(id))(_.getName endsWith "-sources.jar") map { sourcesJar => - manager.define(id, sourcesJar) - sourcesJar - } getOrElse (throw new InvalidComponent(s"Couldn't retrieve default sources: module '$id'")) - - buffered.debug(s"Fetching default sources: module '$id'") - manager.files(id)(new IfMissing.Fallback(getAndDefineDefaultSources())) - - case version +: rest => - val moduleName = s"${id}_$version" - def getAndDefineVersionSpecificSources() = - update(getModule(moduleName))(_.getName endsWith "-sources.jar") map { sourcesJar => - manager.define(moduleName, sourcesJar) - sourcesJar - } getOrElse interfaceSources(rest) - - buffered.debug(s"Fetching version-specific sources: module '$moduleName'") - manager.files(moduleName)(new IfMissing.Fallback(getAndDefineVersionSpecificSources())) - } + private def compileAndInstall(binID: String): Unit = IO.withTemporaryDirectory { binaryDirectory => val targetJar = new File(binaryDirectory, s"$binID.jar") val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail) - val sourceModuleVersions = VersionNumber(compiler.scalaInstance.actualVersion).cascadingVersions - val sources = buffered bufferQuietly interfaceSources(sourceModuleVersions) - AnalyzingCompiler.compileSources(sources, targetJar, xsbtiJars, id, compiler, log) - - manager.define(binID, Seq(targetJar)) + buffered bufferQuietly { + (update(getModule(sourcesModule))(_.getName endsWith "-sources.jar")) match { + case Some(sources) => + AnalyzingCompiler.compileSources(sources, targetJar, xsbtiJars, sourcesModule.name, compiler, log) + manager.define(binID, Seq(targetJar)) + case None => + throw new InvalidComponent(s"Couldn't retrieve source module: $sourcesModule") + } + } } - } /** - * Returns a dummy module that depends on "org.scala-sbt" % `id` % `incrementalVersion`. + * Returns a dummy module that depends on `moduleID`. * Note: Sbt's implementation of Ivy requires us to do this, because only the dependencies * of the specified module will be downloaded. */ - private def getModule(id: String): ivySbt.Module = { - val sha1 = Hash.toHex(Hash(id)) - val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, incrementalVersion, Some("component")) - val moduleID = ModuleID(xsbti.ArtifactInfo.SbtOrganization + ".incrementalcompiler", id, incrementalVersion, Some("component")).sources() + private def getModule(moduleID: ModuleID): ivySbt.Module = { + val sha1 = Hash.toHex(Hash(moduleID.name)) + val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, moduleID.revision, moduleID.configurations) getModule(dummyID, Seq(moduleID)) } From f86b8163e8e52097bf191e34851b17a0893bf2c6 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 11 Sep 2015 10:20:05 +0200 Subject: [PATCH 17/90] Retrieve compiler bridge sources in temp directory Note that they won't be downloaded again, because the component compiler will look for a previously-compiled version of the compiler bridge before trying to fetch the sources again. If they've already been downlaoded, then they have been compiled and a compiled version of the compiler bridge already exists. --- .../sbt/compiler/ComponentCompiler.scala | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index 057da6bd9..e8e63b002 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -31,11 +31,11 @@ object ComponentCompiler { } } - def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID, bootDirectory: File): CompilerInterfaceProvider = new CompilerInterfaceProvider { + def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID): CompilerInterfaceProvider = new CompilerInterfaceProvider { def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { // this is the instance used to compile the interface component - val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager, ivyConfiguration, sourcesModule, bootDirectory, log) + val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager, ivyConfiguration, sourcesModule, log) log.debug("Getting " + sourcesModule + " from component compiler for Scala " + scalaInstance.version) componentCompiler() } @@ -97,7 +97,7 @@ class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) { * The compiled classes are cached using the provided component manager according * to the actualVersion field of the RawCompiler. */ -private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID, bootDirectory: File, log: Logger) { +private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID, log: Logger) { import ComponentCompiler._ private val incrementalCompilerOrg = xsbti.ArtifactInfo.SbtOrganization + ".incrementalcompiler" @@ -105,7 +105,6 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com private val modulePrefixTemp = "temp-module-" private val ivySbt: IvySbt = new IvySbt(ivyConfiguration) private val buffered = new BufferedLogger(FullLogger(log)) - private val retrieveDirectory = new File(s"$bootDirectory/scala-${compiler.scalaInstance.version}/$incrementalCompilerOrg/sbt/$incrementalVersion/compiler-interface-srcs/${sourcesModule.name}/${sourcesModule.revision}") def apply(): File = { val binID = binaryID(sourcesModule.name) @@ -124,14 +123,18 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail) buffered bufferQuietly { - (update(getModule(sourcesModule))(_.getName endsWith "-sources.jar")) match { - case Some(sources) => - AnalyzingCompiler.compileSources(sources, targetJar, xsbtiJars, sourcesModule.name, compiler, log) - manager.define(binID, Seq(targetJar)) - case None => - throw new InvalidComponent(s"Couldn't retrieve source module: $sourcesModule") + IO.withTemporaryDirectory { retrieveDirectory => + (update(getModule(sourcesModule), retrieveDirectory)(_.getName endsWith "-sources.jar")) match { + case Some(sources) => + AnalyzingCompiler.compileSources(sources, targetJar, xsbtiJars, sourcesModule.name, compiler, log) + manager.define(binID, Seq(targetJar)) + + case None => + throw new InvalidComponent(s"Couldn't retrieve source module: $sourcesModule") + } } + } } @@ -169,7 +172,7 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com s"unknown" } - private def update(module: ivySbt.Module)(predicate: File => Boolean): Option[Seq[File]] = { + private def update(module: ivySbt.Module, retrieveDirectory: File)(predicate: File => Boolean): Option[Seq[File]] = { val retrieveConfiguration = new RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false) val updateConfiguration = new UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly) From c74eae096f1b7d86e55acef431b915f59802e6b1 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 11 Sep 2015 10:21:45 +0200 Subject: [PATCH 18/90] Rename binary form of compiler bridge This will avoid all clashes between modules that may have the same name as other components of sbt, or two different compiler bridges that would happen to have the same name. --- .../src/main/scala/sbt/compiler/ComponentCompiler.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index e8e63b002..4f7e9fabe 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -107,7 +107,8 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com private val buffered = new BufferedLogger(FullLogger(log)) def apply(): File = { - val binID = binaryID(sourcesModule.name) + // binID is of the form "org.example-compilerbridge-1.0.0-bin_2.11.7__50.0" + val binID = binaryID(s"${sourcesModule.organization}-${sourcesModule.name}-${sourcesModule.revision}") manager.file(binID)(new IfMissing.Define(true, compileAndInstall(binID))) } From 0cc451b8b225080a1793bffbfe63afce77523be0 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 11 Sep 2015 10:22:33 +0200 Subject: [PATCH 19/90] Fix deprecation message --- .../src/main/scala/sbt/compiler/ComponentCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index 4f7e9fabe..ec36c4416 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -20,7 +20,7 @@ object ComponentCompiler { val compilerInterfaceSrcID = compilerInterfaceID + srcExtension val javaVersion = System.getProperty("java.class.version") - @deprecated("Use `interfaceProvider(ComponentManager, IvyConfiguration, File)`.", "0.13.10") + @deprecated("Use `interfaceProvider(ComponentManager, IvyConfiguration, ModuleID)`.", "0.13.10") def interfaceProvider(manager: ComponentManager): CompilerInterfaceProvider = new CompilerInterfaceProvider { def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { From ce915b23ba762dad04aeb6868802f179f6124419 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 11 Sep 2015 13:53:51 +0200 Subject: [PATCH 20/90] Retrieve java compiler interfaces using Ivy Previously the component compiler depended on a `componentID` added to some interfaces to be able to compile the compiler interface. sbt's launcher placed artifacts marked with this `componentID` in a special directory that was then used by the ComponentCompiler to be able to compile the compiler interface. This commit modifies the ComponentCompiler so that it does not expect these components to be already present in some directory, but instead downloads it using Ivy when required. --- .../sbt/compiler/ComponentCompiler.scala | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala index ec36c4416..e6ed305c9 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -101,6 +101,8 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com import ComponentCompiler._ private val incrementalCompilerOrg = xsbti.ArtifactInfo.SbtOrganization + ".incrementalcompiler" + private val xsbtiInterfaceModuleName = "interface" + private val xsbtiInterfaceID = s"interface-$incrementalVersion" private val sbtOrgTemp = JsonUtil.sbtOrgTemp private val modulePrefixTemp = "temp-module-" private val ivySbt: IvySbt = new IvySbt(ivyConfiguration) @@ -121,7 +123,7 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com IO.withTemporaryDirectory { binaryDirectory => val targetJar = new File(binaryDirectory, s"$binID.jar") - val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail) + val xsbtiJars = manager.files(xsbtiInterfaceID)(new IfMissing.Define(true, getXsbtiInterface())) buffered bufferQuietly { @@ -139,6 +141,23 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com } } + private def getXsbtiInterface(): Unit = + buffered bufferQuietly { + + IO withTemporaryDirectory { retrieveDirectory => + val module = ModuleID(incrementalCompilerOrg, xsbtiInterfaceModuleName, incrementalVersion, Some("component")) + val jarName = s"$xsbtiInterfaceModuleName-$incrementalVersion.jar" + (update(getModule(module), retrieveDirectory)(_.getName == jarName)) match { + case Some(interface) => + manager.define(xsbtiInterfaceID, interface) + + case None => + throw new InvalidComponent(s"Couldn't retrieve xsbti interface module: $xsbtiInterfaceModuleName") + } + } + + } + /** * Returns a dummy module that depends on `moduleID`. * Note: Sbt's implementation of Ivy requires us to do this, because only the dependencies From f26f95fe6a77112788b25307095184cdce6401bb Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 13 Sep 2015 01:13:42 -0400 Subject: [PATCH 21/90] Reorganize subprojects around --- .../sbt/compiler/ComponentCompiler.scala | 61 +------------------ 1 file changed, 3 insertions(+), 58 deletions(-) rename internal/{compile-ivy => compiler-ivy-integration}/src/main/scala/sbt/compiler/ComponentCompiler.scala (70%) diff --git a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala similarity index 70% rename from internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala rename to internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala index e6ed305c9..5f3f78413 100644 --- a/internal/compile-ivy/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -12,25 +12,12 @@ import sbt.librarymanagement.{ Configurations, ModuleID, ModuleInfo, Resolver, U import sbt.util.Logger import sbt.internal.util.{ BufferedLogger, FullLogger } -object ComponentCompiler { - val xsbtiID = "xsbti" - val srcExtension = "-src" +private[sbt] object ComponentCompiler { + // val xsbtiID = "xsbti" + // val srcExtension = "-src" val binSeparator = "-bin_" - val compilerInterfaceID = "compiler-interface" - val compilerInterfaceSrcID = compilerInterfaceID + srcExtension val javaVersion = System.getProperty("java.class.version") - @deprecated("Use `interfaceProvider(ComponentManager, IvyConfiguration, ModuleID)`.", "0.13.10") - def interfaceProvider(manager: ComponentManager): CompilerInterfaceProvider = new CompilerInterfaceProvider { - def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = - { - // this is the instance used to compile the interface component - val componentCompiler = new ComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager) - log.debug("Getting " + compilerInterfaceID + " from component compiler for Scala " + scalaInstance.version) - componentCompiler(compilerInterfaceID) - } - } - def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID): CompilerInterfaceProvider = new CompilerInterfaceProvider { def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { @@ -48,48 +35,6 @@ object ComponentCompiler { properties.getProperty("version") } } -/** - * This class provides source components compiled with the provided RawCompiler. - * The compiled classes are cached using the provided component manager according - * to the actualVersion field of the RawCompiler. - */ -@deprecated("Replaced by IvyComponentCompiler.", "0.13.10") -class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) { - import ComponentCompiler._ - def apply(id: String): File = - try { getPrecompiled(id) } - catch { case _: InvalidComponent => getLocallyCompiled(id) } - - /** - * Gets the precompiled (distributed with sbt) component with the given 'id' - * If the component has not been precompiled, this throws InvalidComponent. - */ - def getPrecompiled(id: String): File = manager.file(binaryID(id, false))(IfMissing.Fail) - /** - * Get the locally compiled component with the given 'id' or compiles it if it has not been compiled yet. - * If the component does not exist, this throws InvalidComponent. - */ - def getLocallyCompiled(id: String): File = - { - val binID = binaryID(id, true) - manager.file(binID)(new IfMissing.Define(true, compileAndInstall(id, binID))) - } - def clearCache(id: String): Unit = manager.clearCache(binaryID(id, true)) - protected def binaryID(id: String, withJavaVersion: Boolean) = - { - val base = id + binSeparator + compiler.scalaInstance.actualVersion - if (withJavaVersion) base + "__" + javaVersion else base - } - protected def compileAndInstall(id: String, binID: String): Unit = { - val srcID = id + srcExtension - IO.withTemporaryDirectory { binaryDirectory => - val targetJar = new File(binaryDirectory, id + ".jar") - val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail) - AnalyzingCompiler.compileSources(manager.files(srcID)(IfMissing.Fail), targetJar, xsbtiJars, id, compiler, manager.log) - manager.define(binID, Seq(targetJar)) - } - } -} /** * Component compiler which is able to to retrieve the compiler bridge sources From 0df130fbe2d5cd26aa51ea764b1d7078026a2e88 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 14 Sep 2015 01:22:52 -0400 Subject: [PATCH 22/90] New scalariform --- .../src/main/scala/sbt/compiler/ComponentCompiler.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala index 5f3f78413..d2c630ef5 100644 --- a/internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -120,7 +120,8 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com moduleInfo = ModuleInfo(moduleID.name), dependencies = deps, configurations = Seq(Configurations.Component), - ivyScala = None) + ivyScala = None + ) new ivySbt.Module(moduleSetting) } From 785c639805cdd63afd6cefefdbe65acf79a929d6 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 14 Sep 2015 22:04:19 -0400 Subject: [PATCH 23/90] Fix the hardcoded ModuleID to compiler-interface --- .../src/main/scala/sbt/compiler/ComponentCompiler.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala index d2c630ef5..4db853066 100644 --- a/internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala @@ -45,8 +45,8 @@ private[sbt] object ComponentCompiler { private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID, log: Logger) { import ComponentCompiler._ - private val incrementalCompilerOrg = xsbti.ArtifactInfo.SbtOrganization + ".incrementalcompiler" - private val xsbtiInterfaceModuleName = "interface" + private val sbtOrg = xsbti.ArtifactInfo.SbtOrganization + private val xsbtiInterfaceModuleName = "compiler-interface" private val xsbtiInterfaceID = s"interface-$incrementalVersion" private val sbtOrgTemp = JsonUtil.sbtOrgTemp private val modulePrefixTemp = "temp-module-" @@ -90,7 +90,7 @@ private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: Com buffered bufferQuietly { IO withTemporaryDirectory { retrieveDirectory => - val module = ModuleID(incrementalCompilerOrg, xsbtiInterfaceModuleName, incrementalVersion, Some("component")) + val module = ModuleID(sbtOrg, xsbtiInterfaceModuleName, incrementalVersion, Some("component")) val jarName = s"$xsbtiInterfaceModuleName-$incrementalVersion.jar" (update(getModule(module), retrieveDirectory)(_.getName == jarName)) match { case Some(interface) => From f2ee845280dff09f07256657d558508da04354be Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Wed, 16 Sep 2015 00:36:00 -0400 Subject: [PATCH 24/90] Move things around further. --- .../src/main/scala/sbt/internal/inc}/ComponentCompiler.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) rename internal/{compiler-ivy-integration/src/main/scala/sbt/compiler => incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc}/ComponentCompiler.scala (97%) diff --git a/internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala b/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala similarity index 97% rename from internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala rename to internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index 4db853066..81acc448f 100644 --- a/internal/compiler-ivy-integration/src/main/scala/sbt/compiler/ComponentCompiler.scala +++ b/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -2,7 +2,8 @@ * Copyright 2009, 2010 Mark Harrah */ package sbt -package compiler +package internal +package inc import java.io.File import scala.util.Try @@ -42,7 +43,7 @@ private[sbt] object ComponentCompiler { * The compiled classes are cached using the provided component manager according * to the actualVersion field of the RawCompiler. */ -private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID, log: Logger) { +private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID, log: Logger) { import ComponentCompiler._ private val sbtOrg = xsbti.ArtifactInfo.SbtOrganization From c62f8f4683c09133056486eb414929bd17245a94 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Mon, 16 Nov 2015 22:44:58 +0100 Subject: [PATCH 25/90] Put `util-interface` on classpath when compiling compiler bridge Also, write tests to make sure that we remain able to compile the compiler bridge for different versions of Scala. Fixes sbt/incrementalcompiler#32 --- .../sbt/internal/inc/ComponentCompiler.scala | 42 ++----- .../inc/BridgeProviderSpecification.scala | 106 ++++++++++++++++++ .../inc/IvyComponentCompilerSpec.scala | 37 ++++++ 3 files changed, 155 insertions(+), 30 deletions(-) create mode 100644 internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala create mode 100644 internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala diff --git a/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index 81acc448f..9846e2d2a 100644 --- a/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ b/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -47,8 +47,8 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen import ComponentCompiler._ private val sbtOrg = xsbti.ArtifactInfo.SbtOrganization - private val xsbtiInterfaceModuleName = "compiler-interface" - private val xsbtiInterfaceID = s"interface-$incrementalVersion" + // private val xsbtiInterfaceModuleName = "compiler-interface" + // private val xsbtiInterfaceID = s"interface-$incrementalVersion" private val sbtOrgTemp = JsonUtil.sbtOrgTemp private val modulePrefixTemp = "temp-module-" private val ivySbt: IvySbt = new IvySbt(ivyConfiguration) @@ -69,41 +69,26 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen IO.withTemporaryDirectory { binaryDirectory => val targetJar = new File(binaryDirectory, s"$binID.jar") - val xsbtiJars = manager.files(xsbtiInterfaceID)(new IfMissing.Define(true, getXsbtiInterface())) buffered bufferQuietly { IO.withTemporaryDirectory { retrieveDirectory => - (update(getModule(sourcesModule), retrieveDirectory)(_.getName endsWith "-sources.jar")) match { - case Some(sources) => + + update(getModule(sourcesModule), retrieveDirectory) match { + case Seq() => + throw new InvalidComponent(s"Couldn't retrieve source module: $sourcesModule") + + case allArtifacts => + val (sources, xsbtiJars) = allArtifacts partition (_.getName endsWith "-sources.jar") AnalyzingCompiler.compileSources(sources, targetJar, xsbtiJars, sourcesModule.name, compiler, log) manager.define(binID, Seq(targetJar)) - case None => - throw new InvalidComponent(s"Couldn't retrieve source module: $sourcesModule") } } } } - private def getXsbtiInterface(): Unit = - buffered bufferQuietly { - - IO withTemporaryDirectory { retrieveDirectory => - val module = ModuleID(sbtOrg, xsbtiInterfaceModuleName, incrementalVersion, Some("component")) - val jarName = s"$xsbtiInterfaceModuleName-$incrementalVersion.jar" - (update(getModule(module), retrieveDirectory)(_.getName == jarName)) match { - case Some(interface) => - manager.define(xsbtiInterfaceID, interface) - - case None => - throw new InvalidComponent(s"Couldn't retrieve xsbti interface module: $xsbtiInterfaceModuleName") - } - } - - } - /** * Returns a dummy module that depends on `moduleID`. * Note: Sbt's implementation of Ivy requires us to do this, because only the dependencies @@ -139,7 +124,7 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen s"unknown" } - private def update(module: ivySbt.Module, retrieveDirectory: File)(predicate: File => Boolean): Option[Seq[File]] = { + private def update(module: ivySbt.Module, retrieveDirectory: File): Seq[File] = { val retrieveConfiguration = new RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false) val updateConfiguration = new UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly) @@ -148,7 +133,7 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen IvyActions.updateEither(module, updateConfiguration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, buffered) match { case Left(unresolvedWarning) => buffered.debug(s"Couldn't retrieve module ${dependenciesNames(module)}.") - None + Nil case Right(updateReport) => val allFiles = @@ -161,10 +146,7 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen buffered.debug(s"Files retrieved for ${dependenciesNames(module)}:") buffered.debug(allFiles mkString ", ") - allFiles filter predicate match { - case Seq() => None - case files => Some(files) - } + allFiles } } diff --git a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala new file mode 100644 index 000000000..f31478b9e --- /dev/null +++ b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -0,0 +1,106 @@ +package sbt.internal.inc + +import java.io.File +import java.net.URLClassLoader +import java.util.Properties +import java.util.concurrent.Callable + +import sbt.internal.inc.classpath.ClasspathUtilities +import sbt.internal.librarymanagement.{ ComponentManager, IvySbt, BaseIvySpecification } +import sbt.io.IO +import sbt.io.Path._ +import sbt.librarymanagement.{ ModuleID, UpdateOptions, Resolver } +import sbt.util.Logger +import xsbti.{ ComponentProvider, GlobalLock } + +abstract class BridgeProviderSpecification extends BaseIvySpecification { + + override def resolvers: Seq[Resolver] = Seq(Resolver.mavenLocal, Resolver.jcenterRepo) + val ivyConfiguration = mkIvyConfiguration(UpdateOptions()) + val ivySbt = new IvySbt(ivyConfiguration) + + val home = new File(sys.props("user.home")) + val ivyCache = home / ".ivy2" / "cache" + + def getCompilerBridge(tempDir: File, log: Logger, scalaVersion: String): File = { + val instance = scalaInstanceFromFile(scalaVersion) + val bridgeId = compilerBridgeId(scalaVersion) + val sourceModule = ModuleID(xsbti.ArtifactInfo.SbtOrganization, bridgeId, ComponentCompiler.incrementalVersion, Some("component")).sources() + + val raw = new RawCompiler(instance, ClasspathOptions.auto, log) + val manager = new ComponentManager(lock, provider(tempDir), None, log) + val componentCompiler = new IvyComponentCompiler(raw, manager, ivyConfiguration, sourceModule, log) + + val bridge = componentCompiler.apply() + val target = tempDir / s"target-bridge-$scalaVersion.jar" + IO.copyFile(bridge, target) + target + } + + def scalaInstanceFromFile(scalaVersion: String): ScalaInstance = + scalaInstance( + ivyCache / "org.scala-lang" / "scala-compiler" / "jars" / s"scala-compiler-$scalaVersion.jar", + ivyCache / "org.scala-lang" / "scala-library" / "jars" / s"scala-library-$scalaVersion.jar", + Seq(ivyCache / "org.scala-lang" / "scala-reflect" / "jars" / s"scala-reflect-$scalaVersion.jar") + ) + + def scalaInstance(scalaCompiler: File, scalaLibrary: File, scalaExtra: Seq[File]): ScalaInstance = { + val loader = scalaLoader(scalaLibrary +: scalaCompiler +: scalaExtra) + val version = scalaVersion(loader) + val allJars = (scalaLibrary +: scalaCompiler +: scalaExtra).toArray + new ScalaInstance(version.getOrElse("unknown"), loader, scalaLibrary, scalaCompiler, allJars, version) + } + + def compilerBridgeId(scalaVersion: String) = + scalaVersion match { + case sc if sc startsWith "2.11" => "compiler-bridge_2.11" + case _ => "compiler-bridge_2.10" + } + + def scalaLoader(jars: Seq[File]) = new URLClassLoader(sbt.io.Path.toURLs(jars), ClasspathUtilities.rootLoader) + def scalaVersion(scalaLoader: ClassLoader): Option[String] = + propertyFromResource("compiler.properties", "version.number", scalaLoader) + + /** + * Get a property from a properties file resource in the classloader. + */ + def propertyFromResource(resource: String, property: String, classLoader: ClassLoader): Option[String] = { + val props = propertiesFromResource(resource, classLoader) + Option(props.getProperty(property)) + } + + /** + * Get all properties from a properties file resource in the classloader. + */ + def propertiesFromResource(resource: String, classLoader: ClassLoader): Properties = { + val props = new Properties + val stream = classLoader.getResourceAsStream(resource) + try { props.load(stream) } + catch { case _: Exception => } + finally { if (stream ne null) stream.close() } + props + } + + private val lock: GlobalLock = new GlobalLock { + override def apply[T](file: File, callable: Callable[T]): T = callable.call() + } + + private def provider(targetDir: File): ComponentProvider = new ComponentProvider { + + override def lockFile(): File = targetDir / "lock" + + override def defineComponent(componentID: String, files: Array[File]): Unit = + files foreach { f => IO.copyFile(f, targetDir / componentID / f.getName) } + + override def addToComponent(componentID: String, files: Array[File]): Boolean = { + defineComponent(componentID, files) + true + } + + override def component(componentID: String): Array[File] = + IO.listFiles(targetDir / componentID) + + override def componentLocation(id: String): File = throw new UnsupportedOperationException + } + +} diff --git a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala new file mode 100644 index 000000000..0043a083b --- /dev/null +++ b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala @@ -0,0 +1,37 @@ +package sbt.internal.inc + +import sbt.io.IO +import sbt.util.Logger + +class IvyComponentCompilerSpec extends BridgeProviderSpecification { + + val scala282 = "2.8.2" + val scala292 = "2.9.2" + val scala210 = "2.10.5" + val scala211 = "2.11.7" + + "IvyComponentCompiler" should "compile the bridge for Scala 2.8" in pendingUntilFixed { + IO.withTemporaryDirectory { tempDir => + getCompilerBridge(tempDir, Logger.Null, scala282) should exist + } + } + + it should "compile the bridge for Scala 2.9" in pendingUntilFixed { + IO.withTemporaryDirectory { tempDir => + getCompilerBridge(tempDir, Logger.Null, scala292) should exist + } + } + + it should "compile the bridge for Scala 2.10" in pendingUntilFixed { + IO.withTemporaryDirectory { tempDir => + getCompilerBridge(tempDir, Logger.Null, scala210) should exist + } + } + + it should "compile the bridge for Scala 2.11" in { + IO.withTemporaryDirectory { tempDir => + getCompilerBridge(tempDir, Logger.Null, scala211) should exist + } + } + +} From 5dd2b1f16a5317bf81485ee077747de3da657861 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Mon, 23 Nov 2015 11:54:13 +0100 Subject: [PATCH 26/90] Fix tests that fetch and build the compiler bridge. --- .../inc/BridgeProviderSpecification.scala | 52 +++++++++++++------ .../inc/IvyComponentCompilerSpec.scala | 8 +-- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index f31478b9e..80a426611 100644 --- a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -6,43 +6,61 @@ import java.util.Properties import java.util.concurrent.Callable import sbt.internal.inc.classpath.ClasspathUtilities -import sbt.internal.librarymanagement.{ ComponentManager, IvySbt, BaseIvySpecification } +import sbt.internal.librarymanagement.{ JsonUtil, ComponentManager, BaseIvySpecification } import sbt.io.IO import sbt.io.Path._ import sbt.librarymanagement.{ ModuleID, UpdateOptions, Resolver } import sbt.util.Logger import xsbti.{ ComponentProvider, GlobalLock } +/** + * Base class for test suites that must be able to fetch and compile the compiler bridge. + */ abstract class BridgeProviderSpecification extends BaseIvySpecification { - override def resolvers: Seq[Resolver] = Seq(Resolver.mavenLocal, Resolver.jcenterRepo) - val ivyConfiguration = mkIvyConfiguration(UpdateOptions()) - val ivySbt = new IvySbt(ivyConfiguration) + override def resolvers: Seq[Resolver] = super.resolvers ++ Seq(Resolver.mavenLocal, Resolver.jcenterRepo) + private val ivyConfiguration = mkIvyConfiguration(UpdateOptions()) - val home = new File(sys.props("user.home")) - val ivyCache = home / ".ivy2" / "cache" - - def getCompilerBridge(tempDir: File, log: Logger, scalaVersion: String): File = { - val instance = scalaInstanceFromFile(scalaVersion) + def getCompilerBridge(targetDir: File, log: Logger, scalaVersion: String): File = { + val instance = scalaInstance(scalaVersion) val bridgeId = compilerBridgeId(scalaVersion) val sourceModule = ModuleID(xsbti.ArtifactInfo.SbtOrganization, bridgeId, ComponentCompiler.incrementalVersion, Some("component")).sources() val raw = new RawCompiler(instance, ClasspathOptions.auto, log) - val manager = new ComponentManager(lock, provider(tempDir), None, log) + val manager = new ComponentManager(lock, provider(targetDir), None, log) val componentCompiler = new IvyComponentCompiler(raw, manager, ivyConfiguration, sourceModule, log) val bridge = componentCompiler.apply() - val target = tempDir / s"target-bridge-$scalaVersion.jar" + val target = targetDir / s"target-bridge-$scalaVersion.jar" IO.copyFile(bridge, target) target } - def scalaInstanceFromFile(scalaVersion: String): ScalaInstance = - scalaInstance( - ivyCache / "org.scala-lang" / "scala-compiler" / "jars" / s"scala-compiler-$scalaVersion.jar", - ivyCache / "org.scala-lang" / "scala-library" / "jars" / s"scala-library-$scalaVersion.jar", - Seq(ivyCache / "org.scala-lang" / "scala-reflect" / "jars" / s"scala-reflect-$scalaVersion.jar") - ) + def scalaInstance(scalaVersion: String): ScalaInstance = { + val scalaModule = { + val dummyModule = ModuleID(JsonUtil.sbtOrgTemp, "tmp-scala-" + scalaVersion, scalaVersion, Some("compile")) + val scalaLibrary = ModuleID(xsbti.ArtifactInfo.ScalaOrganization, xsbti.ArtifactInfo.ScalaLibraryID, scalaVersion, Some("compile")) + val scalaCompiler = ModuleID(xsbti.ArtifactInfo.ScalaOrganization, xsbti.ArtifactInfo.ScalaCompilerID, scalaVersion, Some("compile")) + + module(dummyModule, Seq(scalaLibrary, scalaCompiler), None) + } + + val allArtifacts = + for { + conf <- ivyUpdate(scalaModule).configurations + m <- conf.modules + (_, f) <- m.artifacts + } yield f + + def isCompiler(f: File) = f.getName startsWith "scala-compiler-" + def isLibrary(f: File) = f.getName startsWith "scala-library-" + + val scalaCompilerJar = allArtifacts find isCompiler getOrElse (throw new RuntimeException("Not found: scala-compiler")) + val scalaLibraryJar = allArtifacts find isLibrary getOrElse (throw new RuntimeException("Not found: scala-library")) + val others = allArtifacts filterNot (a => isCompiler(a) || isLibrary(a)) + + scalaInstance(scalaCompilerJar, scalaLibraryJar, others) + } def scalaInstance(scalaCompiler: File, scalaLibrary: File, scalaExtra: Seq[File]): ScalaInstance = { val loader = scalaLoader(scalaLibrary +: scalaCompiler +: scalaExtra) diff --git a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala index 0043a083b..661f7598f 100644 --- a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala +++ b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala @@ -1,7 +1,7 @@ package sbt.internal.inc import sbt.io.IO -import sbt.util.Logger +import sbt.util.{ Level, Logger } class IvyComponentCompilerSpec extends BridgeProviderSpecification { @@ -10,19 +10,19 @@ class IvyComponentCompilerSpec extends BridgeProviderSpecification { val scala210 = "2.10.5" val scala211 = "2.11.7" - "IvyComponentCompiler" should "compile the bridge for Scala 2.8" in pendingUntilFixed { + "IvyComponentCompiler" should "compile the bridge for Scala 2.8" in { IO.withTemporaryDirectory { tempDir => getCompilerBridge(tempDir, Logger.Null, scala282) should exist } } - it should "compile the bridge for Scala 2.9" in pendingUntilFixed { + it should "compile the bridge for Scala 2.9" in { IO.withTemporaryDirectory { tempDir => getCompilerBridge(tempDir, Logger.Null, scala292) should exist } } - it should "compile the bridge for Scala 2.10" in pendingUntilFixed { + it should "compile the bridge for Scala 2.10" in { IO.withTemporaryDirectory { tempDir => getCompilerBridge(tempDir, Logger.Null, scala210) should exist } From 85a05ed237df7da044ee0071a21d6453c93a55b3 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Mon, 23 Nov 2015 15:44:23 +0100 Subject: [PATCH 27/90] Fix command and definition of compiler bridge The compiler bridge had a dependency on the scala compiler in the version defined in the build definition. This means that when trying to fetch the compiler bridge for, say, Scala 2.9.2, we would also pull in the Scala compiler 2.10.5. The compiler bridge now has a "provided" dependency on the Scala compiler. --- .../test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala index 661f7598f..38544bbfa 100644 --- a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala +++ b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala @@ -1,7 +1,7 @@ package sbt.internal.inc import sbt.io.IO -import sbt.util.{ Level, Logger } +import sbt.util.Logger class IvyComponentCompilerSpec extends BridgeProviderSpecification { From 17f55850f626ca26bf4ca23f0f6a59bd48cb2ab1 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 22 Dec 2015 00:20:29 -0500 Subject: [PATCH 28/90] Quieter log during scripted --- .../scala/sbt/internal/inc/BridgeProviderSpecification.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 80a426611..d7ef0f410 100644 --- a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -10,13 +10,14 @@ import sbt.internal.librarymanagement.{ JsonUtil, ComponentManager, BaseIvySpeci import sbt.io.IO import sbt.io.Path._ import sbt.librarymanagement.{ ModuleID, UpdateOptions, Resolver } -import sbt.util.Logger +import sbt.util.{ Logger, Level } import xsbti.{ ComponentProvider, GlobalLock } /** * Base class for test suites that must be able to fetch and compile the compiler bridge. */ abstract class BridgeProviderSpecification extends BaseIvySpecification { + log.setLevel(Level.Warn) override def resolvers: Seq[Resolver] = super.resolvers ++ Seq(Resolver.mavenLocal, Resolver.jcenterRepo) private val ivyConfiguration = mkIvyConfiguration(UpdateOptions()) From c2406c06485c81a6444fed366cf2ae686718a616 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 24 Dec 2015 05:36:31 -0500 Subject: [PATCH 29/90] Use real local to retrieve compiler bridge during test. Fixes #36 --- .../sbt/internal/inc/BridgeProviderSpecification.scala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index d7ef0f410..32a8406b0 100644 --- a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -9,7 +9,7 @@ import sbt.internal.inc.classpath.ClasspathUtilities import sbt.internal.librarymanagement.{ JsonUtil, ComponentManager, BaseIvySpecification } import sbt.io.IO import sbt.io.Path._ -import sbt.librarymanagement.{ ModuleID, UpdateOptions, Resolver } +import sbt.librarymanagement.{ ModuleID, UpdateOptions, Resolver, Patterns, FileRepository, DefaultMavenRepository } import sbt.util.{ Logger, Level } import xsbti.{ ComponentProvider, GlobalLock } @@ -19,7 +19,12 @@ import xsbti.{ ComponentProvider, GlobalLock } abstract class BridgeProviderSpecification extends BaseIvySpecification { log.setLevel(Level.Warn) - override def resolvers: Seq[Resolver] = super.resolvers ++ Seq(Resolver.mavenLocal, Resolver.jcenterRepo) + def realLocal: Resolver = + { + val pList = s"$${user.home}/.ivy2/local/${Resolver.localBasePattern}" :: Nil + FileRepository("local", Resolver.defaultFileConfiguration, Patterns(pList, pList, false)) + } + override def resolvers: Seq[Resolver] = Seq(realLocal, DefaultMavenRepository) private val ivyConfiguration = mkIvyConfiguration(UpdateOptions()) def getCompilerBridge(targetDir: File, log: Logger, scalaVersion: String): File = { From 78c76cb7755907e3fe836764b3de6e51b50eade2 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Wed, 24 Feb 2016 00:08:23 -0500 Subject: [PATCH 30/90] librarymanagement 0.1.0-M7 --- .../src/main/scala/sbt/internal/inc/ComponentCompiler.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index 9846e2d2a..ab2b3c0bc 100644 --- a/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ b/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -9,7 +9,7 @@ import java.io.File import scala.util.Try import sbt.io.{ Hash, IO } import sbt.internal.librarymanagement._ -import sbt.librarymanagement.{ Configurations, ModuleID, ModuleInfo, Resolver, UpdateOptions, VersionNumber } +import sbt.librarymanagement.{ Configurations, ModuleID, ModuleInfo, Resolver, UpdateOptions, VersionNumber, ArtifactTypeFilter } import sbt.util.Logger import sbt.internal.util.{ BufferedLogger, FullLogger } @@ -127,7 +127,7 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen private def update(module: ivySbt.Module, retrieveDirectory: File): Seq[File] = { val retrieveConfiguration = new RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false) - val updateConfiguration = new UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly) + val updateConfiguration = new UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly, ArtifactTypeFilter.forbid(Set("src", "doc"))) buffered.info(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.") IvyActions.updateEither(module, updateConfiguration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, buffered) match { From b04faef33fd0b0725898c11c4d84ade03e1e06f4 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Wed, 24 Feb 2016 09:55:22 +0100 Subject: [PATCH 31/90] Fix compiler bridge sources retrieval --- .../src/main/scala/sbt/internal/inc/ComponentCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index ab2b3c0bc..f1aa399a4 100644 --- a/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ b/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -127,7 +127,7 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen private def update(module: ivySbt.Module, retrieveDirectory: File): Seq[File] = { val retrieveConfiguration = new RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false) - val updateConfiguration = new UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly, ArtifactTypeFilter.forbid(Set("src", "doc"))) + val updateConfiguration = new UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly, ArtifactTypeFilter.forbid(Set("doc"))) buffered.info(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.") IvyActions.updateEither(module, updateConfiguration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, buffered) match { From f32ea08a5367f61e1611f431677326ab931c4d27 Mon Sep 17 00:00:00 2001 From: Grzegorz Kossakowski Date: Wed, 16 Mar 2016 20:28:41 +0100 Subject: [PATCH 32/90] Zinc is compatible with Scala 2.10 and 2.11 only The class-based-dependencies branch nuked compatibility with older Scala compiler versions. --- .../internal/inc/IvyComponentCompilerSpec.scala | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala index 38544bbfa..669aa3c77 100644 --- a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala +++ b/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala @@ -5,23 +5,9 @@ import sbt.util.Logger class IvyComponentCompilerSpec extends BridgeProviderSpecification { - val scala282 = "2.8.2" - val scala292 = "2.9.2" val scala210 = "2.10.5" val scala211 = "2.11.7" - "IvyComponentCompiler" should "compile the bridge for Scala 2.8" in { - IO.withTemporaryDirectory { tempDir => - getCompilerBridge(tempDir, Logger.Null, scala282) should exist - } - } - - it should "compile the bridge for Scala 2.9" in { - IO.withTemporaryDirectory { tempDir => - getCompilerBridge(tempDir, Logger.Null, scala292) should exist - } - } - it should "compile the bridge for Scala 2.10" in { IO.withTemporaryDirectory { tempDir => getCompilerBridge(tempDir, Logger.Null, scala210) should exist From aa0a77930a10db67cb39e7172e27165009b67cd4 Mon Sep 17 00:00:00 2001 From: Grzegorz Kossakowski Date: Thu, 31 Mar 2016 00:02:59 +0200 Subject: [PATCH 33/90] Rename incrementalcompiler to zinc Reflect the rename of the repo to zinc in project's structure. --- .../src/main/scala/sbt/internal/inc/ComponentCompiler.scala | 0 .../test/scala/sbt/internal/inc/BridgeProviderSpecification.scala | 0 .../test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename internal/{incrementalcompiler-ivy-integration => zinc-ivy-integration}/src/main/scala/sbt/internal/inc/ComponentCompiler.scala (100%) rename internal/{incrementalcompiler-ivy-integration => zinc-ivy-integration}/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala (100%) rename internal/{incrementalcompiler-ivy-integration => zinc-ivy-integration}/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala (100%) diff --git a/internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala similarity index 100% rename from internal/incrementalcompiler-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala rename to internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala diff --git a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala similarity index 100% rename from internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala rename to internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala diff --git a/internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala similarity index 100% rename from internal/incrementalcompiler-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala rename to internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala From ba398b5b9c22e422f31291231326bbb59e6b5855 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Wed, 4 May 2016 23:13:28 -0400 Subject: [PATCH 34/90] Update dependencies --- .../scala/sbt/internal/inc/BridgeProviderSpecification.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 32a8406b0..e435ea4c7 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -8,7 +8,7 @@ import java.util.concurrent.Callable import sbt.internal.inc.classpath.ClasspathUtilities import sbt.internal.librarymanagement.{ JsonUtil, ComponentManager, BaseIvySpecification } import sbt.io.IO -import sbt.io.Path._ +import sbt.io.syntax._ import sbt.librarymanagement.{ ModuleID, UpdateOptions, Resolver, Patterns, FileRepository, DefaultMavenRepository } import sbt.util.{ Logger, Level } import xsbti.{ ComponentProvider, GlobalLock } From 1ec9fc4b28f310e8741785f1062b539f1892860b Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Wed, 11 May 2016 15:08:08 -0400 Subject: [PATCH 35/90] Don't use other projects' tests --- .../scala/sbt/internal/inc/BridgeProviderSpecification.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index e435ea4c7..74417ae4b 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -6,7 +6,7 @@ import java.util.Properties import java.util.concurrent.Callable import sbt.internal.inc.classpath.ClasspathUtilities -import sbt.internal.librarymanagement.{ JsonUtil, ComponentManager, BaseIvySpecification } +import sbt.internal.librarymanagement.{ JsonUtil, ComponentManager } import sbt.io.IO import sbt.io.syntax._ import sbt.librarymanagement.{ ModuleID, UpdateOptions, Resolver, Patterns, FileRepository, DefaultMavenRepository } From 7799afdef8a26fa9d7e4fd7fc2170453e78ccc85 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Wed, 1 Jun 2016 15:58:20 +0200 Subject: [PATCH 36/90] Generate `ClasspathOptions` with sbt-datatype Also rename the previous object called `ClasspathOptions` to `ClasspathOptionsUtil`. --- .../src/main/scala/sbt/internal/inc/ComponentCompiler.scala | 2 +- .../scala/sbt/internal/inc/BridgeProviderSpecification.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index f1aa399a4..6216c2d1e 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -23,7 +23,7 @@ private[sbt] object ComponentCompiler { def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { // this is the instance used to compile the interface component - val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager, ivyConfiguration, sourcesModule, log) + val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, log), manager, ivyConfiguration, sourcesModule, log) log.debug("Getting " + sourcesModule + " from component compiler for Scala " + scalaInstance.version) componentCompiler() } diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index e435ea4c7..f5b78ad04 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -32,7 +32,7 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { val bridgeId = compilerBridgeId(scalaVersion) val sourceModule = ModuleID(xsbti.ArtifactInfo.SbtOrganization, bridgeId, ComponentCompiler.incrementalVersion, Some("component")).sources() - val raw = new RawCompiler(instance, ClasspathOptions.auto, log) + val raw = new RawCompiler(instance, ClasspathOptionsUtil.auto, log) val manager = new ComponentManager(lock, provider(targetDir), None, log) val componentCompiler = new IvyComponentCompiler(raw, manager, ivyConfiguration, sourceModule, log) From 531ea5f63537c0d98f376bca217eadb3a9ef1946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sch=C3=A4fer?= Date: Thu, 3 Nov 2016 09:27:52 +0100 Subject: [PATCH 37/90] Rename CompilerInterfaceProvider to CompilerBridgeProvider Fix #162 --- .../src/main/scala/sbt/internal/inc/ComponentCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index 6216c2d1e..c88a484a2 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -19,7 +19,7 @@ private[sbt] object ComponentCompiler { val binSeparator = "-bin_" val javaVersion = System.getProperty("java.class.version") - def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID): CompilerInterfaceProvider = new CompilerInterfaceProvider { + def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID): CompilerBridgeProvider = new CompilerBridgeProvider { def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { // this is the instance used to compile the interface component From e4dfbb01749f14ec4a3ebe49559e38d0af9e0c6c Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 17 Nov 2016 16:29:44 +0000 Subject: [PATCH 38/90] Bump TravisCI to 2.11.8, match crossScalaVersions --- .../test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala index 669aa3c77..d6d2d66be 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala @@ -6,7 +6,7 @@ import sbt.util.Logger class IvyComponentCompilerSpec extends BridgeProviderSpecification { val scala210 = "2.10.5" - val scala211 = "2.11.7" + val scala211 = "2.11.8" it should "compile the bridge for Scala 2.10" in { IO.withTemporaryDirectory { tempDir => From b9060c63eeee009fbbca4b556802e0c79ccf7ae0 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 17 Nov 2016 12:49:24 +0000 Subject: [PATCH 39/90] Upgrade to new sbt/librarymanagement --- .../sbt/internal/inc/ComponentCompiler.scala | 28 +++++++++---------- .../inc/BridgeProviderSpecification.scala | 18 ++++++------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index c88a484a2..1c15ff238 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -9,9 +9,9 @@ import java.io.File import scala.util.Try import sbt.io.{ Hash, IO } import sbt.internal.librarymanagement._ -import sbt.librarymanagement.{ Configurations, ModuleID, ModuleInfo, Resolver, UpdateOptions, VersionNumber, ArtifactTypeFilter } +import sbt.librarymanagement.{ Configurations, ModuleID, ModuleInfo, Resolver, UpdateConfiguration, UpdateLogging, UpdateOptions, ArtifactTypeFilter } import sbt.util.Logger -import sbt.internal.util.{ BufferedLogger, FullLogger } +import sbt.internal.util.{ BufferedLogger, CacheStore, FullLogger } private[sbt] object ComponentCompiler { // val xsbtiID = "xsbti" @@ -19,11 +19,11 @@ private[sbt] object ComponentCompiler { val binSeparator = "-bin_" val javaVersion = System.getProperty("java.class.version") - def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID): CompilerBridgeProvider = new CompilerBridgeProvider { + def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration, fileToStore: File => CacheStore, sourcesModule: ModuleID): CompilerBridgeProvider = new CompilerBridgeProvider { def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { // this is the instance used to compile the interface component - val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, log), manager, ivyConfiguration, sourcesModule, log) + val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, log), manager, ivyConfiguration, fileToStore, sourcesModule, log) log.debug("Getting " + sourcesModule + " from component compiler for Scala " + scalaInstance.version) componentCompiler() } @@ -43,7 +43,7 @@ private[sbt] object ComponentCompiler { * The compiled classes are cached using the provided component manager according * to the actualVersion field of the RawCompiler. */ -private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID, log: Logger) { +private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, fileToStore: File => CacheStore, sourcesModule: ModuleID, log: Logger) { import ComponentCompiler._ private val sbtOrg = xsbti.ArtifactInfo.SbtOrganization @@ -51,7 +51,7 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen // private val xsbtiInterfaceID = s"interface-$incrementalVersion" private val sbtOrgTemp = JsonUtil.sbtOrgTemp private val modulePrefixTemp = "temp-module-" - private val ivySbt: IvySbt = new IvySbt(ivyConfiguration) + private val ivySbt: IvySbt = new IvySbt(ivyConfiguration, fileToStore) private val buffered = new BufferedLogger(FullLogger(log)) def apply(): File = { @@ -96,18 +96,18 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen */ private def getModule(moduleID: ModuleID): ivySbt.Module = { val sha1 = Hash.toHex(Hash(moduleID.name)) - val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, moduleID.revision, moduleID.configurations) - getModule(dummyID, Seq(moduleID)) + val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, moduleID.revision).withConfigurations(moduleID.configurations) + getModule(dummyID, Vector(moduleID)) } - private def getModule(moduleID: ModuleID, deps: Seq[ModuleID], uo: UpdateOptions = UpdateOptions()): ivySbt.Module = { + private def getModule(moduleID: ModuleID, deps: Vector[ModuleID], uo: UpdateOptions = UpdateOptions()): ivySbt.Module = { val moduleSetting = InlineConfiguration( + validate = false, + ivyScala = None, module = moduleID, moduleInfo = ModuleInfo(moduleID.name), - dependencies = deps, - configurations = Seq(Configurations.Component), - ivyScala = None - ) + dependencies = deps + ).withConfigurations(Vector(Configurations.Component)) new ivySbt.Module(moduleSetting) } @@ -126,7 +126,7 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen private def update(module: ivySbt.Module, retrieveDirectory: File): Seq[File] = { - val retrieveConfiguration = new RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false) + val retrieveConfiguration = new RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false, None) val updateConfiguration = new UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly, ArtifactTypeFilter.forbid(Set("doc"))) buffered.info(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.") diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 762383a60..8b8987975 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -21,20 +21,20 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { def realLocal: Resolver = { - val pList = s"$${user.home}/.ivy2/local/${Resolver.localBasePattern}" :: Nil - FileRepository("local", Resolver.defaultFileConfiguration, Patterns(pList, pList, false)) + val pList = Vector(s"$${user.home}/.ivy2/local/${Resolver.localBasePattern}") + FileRepository("local", Resolver.defaultFileConfiguration, Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false)) } - override def resolvers: Seq[Resolver] = Seq(realLocal, DefaultMavenRepository) + override def resolvers: Vector[Resolver] = Vector(realLocal, DefaultMavenRepository) private val ivyConfiguration = mkIvyConfiguration(UpdateOptions()) def getCompilerBridge(targetDir: File, log: Logger, scalaVersion: String): File = { val instance = scalaInstance(scalaVersion) val bridgeId = compilerBridgeId(scalaVersion) - val sourceModule = ModuleID(xsbti.ArtifactInfo.SbtOrganization, bridgeId, ComponentCompiler.incrementalVersion, Some("component")).sources() + val sourceModule = ModuleID(xsbti.ArtifactInfo.SbtOrganization, bridgeId, ComponentCompiler.incrementalVersion).withConfigurations(Some("component")).sources() val raw = new RawCompiler(instance, ClasspathOptionsUtil.auto, log) val manager = new ComponentManager(lock, provider(targetDir), None, log) - val componentCompiler = new IvyComponentCompiler(raw, manager, ivyConfiguration, sourceModule, log) + val componentCompiler = new IvyComponentCompiler(raw, manager, ivyConfiguration, fileToStore, sourceModule, log) val bridge = componentCompiler.apply() val target = targetDir / s"target-bridge-$scalaVersion.jar" @@ -44,11 +44,11 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { def scalaInstance(scalaVersion: String): ScalaInstance = { val scalaModule = { - val dummyModule = ModuleID(JsonUtil.sbtOrgTemp, "tmp-scala-" + scalaVersion, scalaVersion, Some("compile")) - val scalaLibrary = ModuleID(xsbti.ArtifactInfo.ScalaOrganization, xsbti.ArtifactInfo.ScalaLibraryID, scalaVersion, Some("compile")) - val scalaCompiler = ModuleID(xsbti.ArtifactInfo.ScalaOrganization, xsbti.ArtifactInfo.ScalaCompilerID, scalaVersion, Some("compile")) + val dummyModule = ModuleID(JsonUtil.sbtOrgTemp, "tmp-scala-" + scalaVersion, scalaVersion).withConfigurations(Some("compile")) + val scalaLibrary = ModuleID(xsbti.ArtifactInfo.ScalaOrganization, xsbti.ArtifactInfo.ScalaLibraryID, scalaVersion).withConfigurations(Some("compile")) + val scalaCompiler = ModuleID(xsbti.ArtifactInfo.ScalaOrganization, xsbti.ArtifactInfo.ScalaCompilerID, scalaVersion).withConfigurations(Some("compile")) - module(dummyModule, Seq(scalaLibrary, scalaCompiler), None) + module(dummyModule, Vector(scalaLibrary, scalaCompiler), None) } val allArtifacts = From 376718f976cf699608a68bf08212537dc652eb20 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 5 Jan 2017 14:07:11 +0000 Subject: [PATCH 40/90] Upgrade to newer modules, migrate to new lm api --- .../src/main/scala/sbt/internal/inc/ComponentCompiler.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index 1c15ff238..4248a6246 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -126,8 +126,8 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen private def update(module: ivySbt.Module, retrieveDirectory: File): Seq[File] = { - val retrieveConfiguration = new RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false, None) - val updateConfiguration = new UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly, ArtifactTypeFilter.forbid(Set("doc"))) + val retrieveConfiguration = RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false, None) + val updateConfiguration = UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly, ArtifactTypeFilter.forbid(Set("doc"))) buffered.info(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.") IvyActions.updateEither(module, updateConfiguration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, buffered) match { From c75a69bbb0214c619b9d536269225661398dae33 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 7 Jan 2017 03:06:14 -0500 Subject: [PATCH 41/90] Cross build to Scala 2.12 --- .../scala/sbt/internal/inc/BridgeProviderSpecification.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 8b8987975..869cb04f1 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -77,8 +77,8 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { def compilerBridgeId(scalaVersion: String) = scalaVersion match { - case sc if sc startsWith "2.11" => "compiler-bridge_2.11" - case _ => "compiler-bridge_2.10" + case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" + case _ => "compiler-bridge_2.12" } def scalaLoader(jars: Seq[File]) = new URLClassLoader(sbt.io.Path.toURLs(jars), ClasspathUtilities.rootLoader) From 818cee0156b04c2bf73d071d6f3b6924a35cce40 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 28 Jan 2017 22:53:01 -0500 Subject: [PATCH 42/90] Migrate ComponentManager from librarymanagement This migrates the `ComponentManager` from librarymanagement, and refactors it to clarify the double caching of the compiler bridge. The main purpose of this refactoring is to fix sbt/sbt#2539. As it stands, becaue Ivy cache directory is being used as the secondary cache of the compiled compiler bridge, it's annoying to work with the compiler bridge. Instead of using "Ivy cache", the new `ZincComponentManager` accepts `secondaryCacheDir: Option[File]`, which during test defaults to `target/zinc-components`. Fixes sbt/sbt#2539 --- .../sbt/internal/inc/ComponentCompiler.scala | 12 +- .../internal/inc/ZincComponentManager.scala | 121 ++++++++++++++++++ .../inc/BridgeProviderSpecification.scala | 11 +- 3 files changed, 134 insertions(+), 10 deletions(-) create mode 100644 internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index 4248a6246..9b2ec6d39 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -6,9 +6,8 @@ package internal package inc import java.io.File -import scala.util.Try import sbt.io.{ Hash, IO } -import sbt.internal.librarymanagement._ +import sbt.internal.librarymanagement.{ IvyConfiguration, JsonUtil, IvySbt, InlineConfiguration, RetrieveConfiguration, IvyActions, UnresolvedWarningConfiguration, LogicalClock } import sbt.librarymanagement.{ Configurations, ModuleID, ModuleInfo, Resolver, UpdateConfiguration, UpdateLogging, UpdateOptions, ArtifactTypeFilter } import sbt.util.Logger import sbt.internal.util.{ BufferedLogger, CacheStore, FullLogger } @@ -19,7 +18,7 @@ private[sbt] object ComponentCompiler { val binSeparator = "-bin_" val javaVersion = System.getProperty("java.class.version") - def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration, fileToStore: File => CacheStore, sourcesModule: ModuleID): CompilerBridgeProvider = new CompilerBridgeProvider { + def interfaceProvider(manager: ZincComponentManager, ivyConfiguration: IvyConfiguration, fileToStore: File => CacheStore, sourcesModule: ModuleID): CompilerBridgeProvider = new CompilerBridgeProvider { def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { // this is the instance used to compile the interface component @@ -43,10 +42,8 @@ private[sbt] object ComponentCompiler { * The compiled classes are cached using the provided component manager according * to the actualVersion field of the RawCompiler. */ -private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, fileToStore: File => CacheStore, sourcesModule: ModuleID, log: Logger) { +private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ZincComponentManager, ivyConfiguration: IvyConfiguration, fileToStore: File => CacheStore, sourcesModule: ModuleID, log: Logger) { import ComponentCompiler._ - - private val sbtOrg = xsbti.ArtifactInfo.SbtOrganization // private val xsbtiInterfaceModuleName = "compiler-interface" // private val xsbtiInterfaceID = s"interface-$incrementalVersion" private val sbtOrgTemp = JsonUtil.sbtOrgTemp @@ -57,7 +54,7 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen def apply(): File = { // binID is of the form "org.example-compilerbridge-1.0.0-bin_2.11.7__50.0" val binID = binaryID(s"${sourcesModule.organization}-${sourcesModule.name}-${sourcesModule.revision}") - manager.file(binID)(new IfMissing.Define(true, compileAndInstall(binID))) + manager.file(binID)(IfMissing.define(true, compileAndInstall(binID))) } private def binaryID(id: String): String = { @@ -82,7 +79,6 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: Componen val (sources, xsbtiJars) = allArtifacts partition (_.getName endsWith "-sources.jar") AnalyzingCompiler.compileSources(sources, targetJar, xsbtiJars, sourcesModule.name, compiler, log) manager.define(binID, Seq(targetJar)) - } } diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala new file mode 100644 index 000000000..61c0cbc41 --- /dev/null +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala @@ -0,0 +1,121 @@ +package sbt +package internal +package inc + +import java.io.File +import java.util.concurrent.Callable +import sbt.util.Logger +import sbt.io.IO + +/** + * A component manager provides access to the pieces of zinc that are distributed as components. + * Compiler bridge is distributed as a source jar so that it can be compiled against a specific + * version of Scala. + * + * The component manager provides services to install and retrieve components to the local filesystem. + * This is used for compiled source jars so that the compilation need not be repeated for other projects on the same + * machine. + */ +class ZincComponentManager(globalLock: xsbti.GlobalLock, provider: xsbti.ComponentProvider, + secondaryCacheDir: Option[File], val log: Logger) { + /** Get all of the files for component 'id', throwing an exception if no files exist for the component. */ + def files(id: String)(ifMissing: IfMissing): Iterable[File] = + { + def fromSecondary = + lockSecondaryCache { + update(id) + getOrElse(createAndCache) + } getOrElse notFound + def getOrElse(orElse: => Iterable[File]): Iterable[File] = + { + val existing = provider.component(id) + if (existing.isEmpty) orElse + else existing + } + def notFound = invalid("Could not find required component '" + id + "'") + def createAndCache = + ifMissing match { + case IfMissing.Fail => notFound + case d: IfMissing.Define => + d.run() // this is expected to have called define. + if (d.useSecondaryCache) { + cacheToSecondaryCache(id) + } + getOrElse(notFound) + } + lockLocalCache { getOrElse(fromSecondary) } + } + /** This is used to lock the local cache in project/boot/. By checking the local cache first, we can avoid grabbing a global lock. */ + private def lockLocalCache[T](action: => T): T = lock(provider.lockFile)(action) + /** This is used to ensure atomic access to components in the global Ivy cache.*/ + private def lockSecondaryCache[T](action: => T): Option[T] = + secondaryCacheDir map { dir => + val lockFile = new File(dir, ".sbt.cache.lock") + lock(lockFile)(action) + } + private def lock[T](file: File)(action: => T): T = globalLock(file, new Callable[T] { def call = action }) + /** Get the file for component 'id', throwing an exception if no files or multiple files exist for the component. */ + def file(id: String)(ifMissing: IfMissing): File = + files(id)(ifMissing).toList match { + case x :: Nil => x + case xs => invalid("Expected single file for component '" + id + "', found: " + xs.mkString(", ")) + } + private def invalid(msg: String) = throw new InvalidComponent(msg) + + def define(id: String, files: Iterable[File]) = lockLocalCache { provider.defineComponent(id, files.toSeq.toArray) } + /** Retrieve the file for component 'id' from the secondary cache. */ + private def update(id: String): Unit = + { + secondaryCacheDir map { dir => + val file = seondaryCacheFile(id, dir) + if (file.exists) { + define(id, Seq(file)) + } + } + () + } + /** Install the files for component 'id' to the secondary cache. */ + private def cacheToSecondaryCache(id: String): Unit = + { + val fromPrimaryCache = file(id)(IfMissing.fail) + secondaryCacheDir match { + case Some(dir) => + val file = seondaryCacheFile(id, dir) + IO.copyFile(fromPrimaryCache, file) + case _ => () + } + () + } + private val sbtOrg = xsbti.ArtifactInfo.SbtOrganization + private def seondaryCacheFile(id: String, dir: File): File = + { + val fileName = id + "-" + ZincComponentManager.stampedVersion + ".jar" + new File(new File(dir, sbtOrg), fileName) + } +} +class InvalidComponent(msg: String, cause: Throwable) extends RuntimeException(msg, cause) { + def this(msg: String) = this(msg, null) +} +sealed trait IfMissing +object IfMissing { + def fail: IfMissing = Fail + /** f is expected to call ZincComponentManager.define. */ + def define(useSecondaryCache: Boolean, f: => Unit): IfMissing = new Define(useSecondaryCache, f) + object Fail extends IfMissing + final class Define(val useSecondaryCache: Boolean, define: => Unit) extends IfMissing { + def run(): Unit = define + } +} +object ZincComponentManager { + lazy val (version, timestamp) = + { + val properties = new java.util.Properties + val propertiesStream = versionResource.openStream + try { properties.load(propertiesStream) } finally { propertiesStream.close() } + (properties.getProperty("version"), properties.getProperty("timestamp")) + } + lazy val stampedVersion = version + "_" + timestamp + + import java.net.URL + private def versionResource: URL = getClass.getResource("/incrementalcompiler.version.properties") +} diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 869cb04f1..323f238d6 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -6,7 +6,7 @@ import java.util.Properties import java.util.concurrent.Callable import sbt.internal.inc.classpath.ClasspathUtilities -import sbt.internal.librarymanagement.{ JsonUtil, ComponentManager } +import sbt.internal.librarymanagement.JsonUtil import sbt.io.IO import sbt.io.syntax._ import sbt.librarymanagement.{ ModuleID, UpdateOptions, Resolver, Patterns, FileRepository, DefaultMavenRepository } @@ -27,13 +27,20 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { override def resolvers: Vector[Resolver] = Vector(realLocal, DefaultMavenRepository) private val ivyConfiguration = mkIvyConfiguration(UpdateOptions()) + def secondaryCacheDirectory: File = + { + val target = file("target").getAbsoluteFile + target / "zinc-components" + } + def secondaryCacheOpt: Option[File] = Some(secondaryCacheDirectory) + def getCompilerBridge(targetDir: File, log: Logger, scalaVersion: String): File = { val instance = scalaInstance(scalaVersion) val bridgeId = compilerBridgeId(scalaVersion) val sourceModule = ModuleID(xsbti.ArtifactInfo.SbtOrganization, bridgeId, ComponentCompiler.incrementalVersion).withConfigurations(Some("component")).sources() val raw = new RawCompiler(instance, ClasspathOptionsUtil.auto, log) - val manager = new ComponentManager(lock, provider(targetDir), None, log) + val manager = new ZincComponentManager(lock, provider(targetDir), secondaryCacheOpt, log) val componentCompiler = new IvyComponentCompiler(raw, manager, ivyConfiguration, fileToStore, sourceModule, log) val bridge = componentCompiler.apply() From b6fc9f95172138cc7741f4b0cec963f8a5f17236 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 7 Feb 2017 15:26:33 -0500 Subject: [PATCH 43/90] Put copyright notice Fixes #222 --- .../main/scala/sbt/internal/inc/ComponentCompiler.scala | 8 ++++++-- .../scala/sbt/internal/inc/ZincComponentManager.scala | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index 9b2ec6d39..4b0d3f61c 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -1,6 +1,10 @@ -/* sbt -- Simple Build Tool - * Copyright 2009, 2010 Mark Harrah +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. */ + package sbt package internal package inc diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala index 61c0cbc41..e0cc8f418 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package internal package inc From ddb9cfd3f99b383101e19ada444d2148a9f0bc33 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 24 Jan 2017 21:17:21 -0500 Subject: [PATCH 44/90] Switch over to using ManagedLogger --- .../scala/sbt/internal/inc/BridgeProviderSpecification.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 323f238d6..170545e8e 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -17,7 +17,7 @@ import xsbti.{ ComponentProvider, GlobalLock } * Base class for test suites that must be able to fetch and compile the compiler bridge. */ abstract class BridgeProviderSpecification extends BaseIvySpecification { - log.setLevel(Level.Warn) + // log.setLevel(Level.Warn) def realLocal: Resolver = { From 5cea7ae09fc20650660650bd339771a388781d52 Mon Sep 17 00:00:00 2001 From: jvican Date: Fri, 24 Feb 2017 17:10:07 +0100 Subject: [PATCH 45/90] Do a first pass on the Zinc internal implementation This commit addresses several concers: * Document better the Zinc internal implementation. * Getting the implementation ready for moving things from internal to public APIs. This will be done in a follow-up commit. * Removing `inputs` and `setups` from the `IncrementalCompilerUtil` as they exist mainly to interface between Scala code and Java code. The reality is that both Java and Scala developers can easily call the constructors by themselves and don't learn more API methods. * Removes unused imports, that emit stupid warnings. * Make code more readable, especifically in the analyzing compilers for both Java and Scala, which was hardly understandable and documented. * Make `AnalyzingJavaCompiler` to extend `JavaCompiler` as `AnalyzingCompiler` does for `ScalaCompiler`. In an upcoming commit, `AnalyzingCompiler` will be renamed into `AnalyzingScalaCompiler` for consistency reasons. * Replace use of `sbt.util.Logger` helpers by `sbt.util.InterfaceUtil`. --- .../scala/sbt/internal/inc/BridgeProviderSpecification.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 170545e8e..35c9fda9b 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -10,7 +10,7 @@ import sbt.internal.librarymanagement.JsonUtil import sbt.io.IO import sbt.io.syntax._ import sbt.librarymanagement.{ ModuleID, UpdateOptions, Resolver, Patterns, FileRepository, DefaultMavenRepository } -import sbt.util.{ Logger, Level } +import sbt.util.Logger import xsbti.{ ComponentProvider, GlobalLock } /** From ef6193e8cf87c6f374807c41d681537c4663f160 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 23 Mar 2017 23:56:42 -0400 Subject: [PATCH 46/90] Adds Hello world for 2.10, 2.11, and 2.12 --- .../scala/sbt/internal/inc/BridgeProviderSpecification.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 35c9fda9b..e28c804e7 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -85,6 +85,7 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { def compilerBridgeId(scalaVersion: String) = scalaVersion match { case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" + case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" case _ => "compiler-bridge_2.12" } From 34da766f2b2452a45c0b87e48901dfaca1b7781e Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 11 Apr 2017 03:08:06 -0400 Subject: [PATCH 47/90] Better error message for bridge resolution The compiler bridge dependency resolution had `missingOk = true` flag on. This would silently succeed even when one of the dependency is missing, and it would randomly fail bridge compilation, which is very confusing. --- .../sbt/internal/inc/ComponentCompiler.scala | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index 4b0d3f61c..e46a8e307 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -11,8 +11,9 @@ package inc import java.io.File import sbt.io.{ Hash, IO } -import sbt.internal.librarymanagement.{ IvyConfiguration, JsonUtil, IvySbt, InlineConfiguration, RetrieveConfiguration, IvyActions, UnresolvedWarningConfiguration, LogicalClock } +import sbt.internal.librarymanagement.{ IvyConfiguration, JsonUtil, IvySbt, InlineConfiguration, RetrieveConfiguration, IvyActions, UnresolvedWarningConfiguration, LogicalClock, UnresolvedWarning } import sbt.librarymanagement.{ Configurations, ModuleID, ModuleInfo, Resolver, UpdateConfiguration, UpdateLogging, UpdateOptions, ArtifactTypeFilter } +import sbt.librarymanagement.syntax._ import sbt.util.Logger import sbt.internal.util.{ BufferedLogger, CacheStore, FullLogger } @@ -76,10 +77,12 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ZincComp IO.withTemporaryDirectory { retrieveDirectory => update(getModule(sourcesModule), retrieveDirectory) match { - case Seq() => - throw new InvalidComponent(s"Couldn't retrieve source module: $sourcesModule") + case Left(uw) => + import sbt.util.ShowLines._ + throw new InvalidComponent(s"Couldn't retrieve source module: $sourcesModule\n" + + uw.lines.mkString("\n")) - case allArtifacts => + case Right(allArtifacts) => val (sources, xsbtiJars) = allArtifacts partition (_.getName endsWith "-sources.jar") AnalyzingCompiler.compileSources(sources, targetJar, xsbtiJars, sourcesModule.name, compiler, log) manager.define(binID, Seq(targetJar)) @@ -124,30 +127,24 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ZincComp s"unknown" } - private def update(module: ivySbt.Module, retrieveDirectory: File): Seq[File] = { - + private def update(module: ivySbt.Module, retrieveDirectory: File): Either[UnresolvedWarning, Vector[File]] = { val retrieveConfiguration = RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false, None) - val updateConfiguration = UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly, ArtifactTypeFilter.forbid(Set("doc"))) + val updateConfiguration = UpdateConfiguration( + Some(retrieveConfiguration), + missingOk = false, UpdateLogging.DownloadOnly, ArtifactTypeFilter.forbid(Set("doc")) + ) buffered.info(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.") IvyActions.updateEither(module, updateConfiguration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, buffered) match { case Left(unresolvedWarning) => buffered.debug(s"Couldn't retrieve module ${dependenciesNames(module)}.") - Nil + Left(unresolvedWarning) case Right(updateReport) => - val allFiles = - for { - conf <- updateReport.configurations - m <- conf.modules - (_, f) <- m.artifacts - } yield f - + val allFiles = updateReport.allFiles buffered.debug(s"Files retrieved for ${dependenciesNames(module)}:") buffered.debug(allFiles mkString ", ") - - allFiles - + Right(allFiles.toVector) } } } From ad7bd2c2d698c2a0cc68f6359511a48f0551e134 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 17 Apr 2017 14:14:58 -0400 Subject: [PATCH 48/90] Bump to util 1.0.0-M22 and 1.0.0-X10 Bumping to the latest librarymanagement. --- .../scala/sbt/internal/inc/ComponentCompiler.scala | 10 +++++----- .../sbt/internal/inc/BridgeProviderSpecification.scala | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index e46a8e307..936bf21b5 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -15,7 +15,7 @@ import sbt.internal.librarymanagement.{ IvyConfiguration, JsonUtil, IvySbt, Inli import sbt.librarymanagement.{ Configurations, ModuleID, ModuleInfo, Resolver, UpdateConfiguration, UpdateLogging, UpdateOptions, ArtifactTypeFilter } import sbt.librarymanagement.syntax._ import sbt.util.Logger -import sbt.internal.util.{ BufferedLogger, CacheStore, FullLogger } +import sbt.internal.util.{ BufferedLogger, FullLogger } private[sbt] object ComponentCompiler { // val xsbtiID = "xsbti" @@ -23,11 +23,11 @@ private[sbt] object ComponentCompiler { val binSeparator = "-bin_" val javaVersion = System.getProperty("java.class.version") - def interfaceProvider(manager: ZincComponentManager, ivyConfiguration: IvyConfiguration, fileToStore: File => CacheStore, sourcesModule: ModuleID): CompilerBridgeProvider = new CompilerBridgeProvider { + def interfaceProvider(manager: ZincComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID): CompilerBridgeProvider = new CompilerBridgeProvider { def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { // this is the instance used to compile the interface component - val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, log), manager, ivyConfiguration, fileToStore, sourcesModule, log) + val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, log), manager, ivyConfiguration, sourcesModule, log) log.debug("Getting " + sourcesModule + " from component compiler for Scala " + scalaInstance.version) componentCompiler() } @@ -47,13 +47,13 @@ private[sbt] object ComponentCompiler { * The compiled classes are cached using the provided component manager according * to the actualVersion field of the RawCompiler. */ -private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ZincComponentManager, ivyConfiguration: IvyConfiguration, fileToStore: File => CacheStore, sourcesModule: ModuleID, log: Logger) { +private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ZincComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID, log: Logger) { import ComponentCompiler._ // private val xsbtiInterfaceModuleName = "compiler-interface" // private val xsbtiInterfaceID = s"interface-$incrementalVersion" private val sbtOrgTemp = JsonUtil.sbtOrgTemp private val modulePrefixTemp = "temp-module-" - private val ivySbt: IvySbt = new IvySbt(ivyConfiguration, fileToStore) + private val ivySbt: IvySbt = new IvySbt(ivyConfiguration) private val buffered = new BufferedLogger(FullLogger(log)) def apply(): File = { diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index e28c804e7..5b20a0eb4 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -41,7 +41,7 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { val raw = new RawCompiler(instance, ClasspathOptionsUtil.auto, log) val manager = new ZincComponentManager(lock, provider(targetDir), secondaryCacheOpt, log) - val componentCompiler = new IvyComponentCompiler(raw, manager, ivyConfiguration, fileToStore, sourceModule, log) + val componentCompiler = new IvyComponentCompiler(raw, manager, ivyConfiguration, sourceModule, log) val bridge = componentCompiler.apply() val target = targetDir / s"target-bridge-$scalaVersion.jar" From 9c1268412a0252040e551d39d7c55b89e1d50b00 Mon Sep 17 00:00:00 2001 From: jvican Date: Wed, 3 May 2017 18:34:51 +0200 Subject: [PATCH 49/90] Reformat zinc with scalafmt The same as https://github.com/sbt/librarymanagement/pull/87/. --- .../sbt/internal/inc/ComponentCompiler.scala | 93 ++++++++++--- .../internal/inc/ZincComponentManager.scala | 130 ++++++++++-------- .../inc/BridgeProviderSpecification.scala | 83 +++++++---- 3 files changed, 197 insertions(+), 109 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala index 936bf21b5..2888cfb14 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala @@ -11,8 +11,27 @@ package inc import java.io.File import sbt.io.{ Hash, IO } -import sbt.internal.librarymanagement.{ IvyConfiguration, JsonUtil, IvySbt, InlineConfiguration, RetrieveConfiguration, IvyActions, UnresolvedWarningConfiguration, LogicalClock, UnresolvedWarning } -import sbt.librarymanagement.{ Configurations, ModuleID, ModuleInfo, Resolver, UpdateConfiguration, UpdateLogging, UpdateOptions, ArtifactTypeFilter } +import sbt.internal.librarymanagement.{ + IvyConfiguration, + JsonUtil, + IvySbt, + InlineConfiguration, + RetrieveConfiguration, + IvyActions, + UnresolvedWarningConfiguration, + LogicalClock, + UnresolvedWarning +} +import sbt.librarymanagement.{ + Configurations, + ModuleID, + ModuleInfo, + Resolver, + UpdateConfiguration, + UpdateLogging, + UpdateOptions, + ArtifactTypeFilter +} import sbt.librarymanagement.syntax._ import sbt.util.Logger import sbt.internal.util.{ BufferedLogger, FullLogger } @@ -23,19 +42,28 @@ private[sbt] object ComponentCompiler { val binSeparator = "-bin_" val javaVersion = System.getProperty("java.class.version") - def interfaceProvider(manager: ZincComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID): CompilerBridgeProvider = new CompilerBridgeProvider { - def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = - { + def interfaceProvider(manager: ZincComponentManager, + ivyConfiguration: IvyConfiguration, + sourcesModule: ModuleID): CompilerBridgeProvider = + new CompilerBridgeProvider { + def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { // this is the instance used to compile the interface component - val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, log), manager, ivyConfiguration, sourcesModule, log) - log.debug("Getting " + sourcesModule + " from component compiler for Scala " + scalaInstance.version) + val componentCompiler = new IvyComponentCompiler( + new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, log), + manager, + ivyConfiguration, + sourcesModule, + log) + log.debug( + "Getting " + sourcesModule + " from component compiler for Scala " + scalaInstance.version) componentCompiler() } - } + } lazy val incrementalVersion = { val properties = new java.util.Properties - val propertiesStream = getClass.getResource("/incrementalcompiler.version.properties").openStream + val propertiesStream = + getClass.getResource("/incrementalcompiler.version.properties").openStream try { properties.load(propertiesStream) } finally { propertiesStream.close() } properties.getProperty("version") } @@ -47,7 +75,11 @@ private[sbt] object ComponentCompiler { * The compiled classes are cached using the provided component manager according * to the actualVersion field of the RawCompiler. */ -private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ZincComponentManager, ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID, log: Logger) { +private[inc] class IvyComponentCompiler(compiler: RawCompiler, + manager: ZincComponentManager, + ivyConfiguration: IvyConfiguration, + sourcesModule: ModuleID, + log: Logger) { import ComponentCompiler._ // private val xsbtiInterfaceModuleName = "compiler-interface" // private val xsbtiInterfaceID = s"interface-$incrementalVersion" @@ -58,7 +90,8 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ZincComp def apply(): File = { // binID is of the form "org.example-compilerbridge-1.0.0-bin_2.11.7__50.0" - val binID = binaryID(s"${sourcesModule.organization}-${sourcesModule.name}-${sourcesModule.revision}") + val binID = binaryID( + s"${sourcesModule.organization}-${sourcesModule.name}-${sourcesModule.revision}") manager.file(binID)(IfMissing.define(true, compileAndInstall(binID))) } @@ -69,22 +102,26 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ZincComp private def compileAndInstall(binID: String): Unit = IO.withTemporaryDirectory { binaryDirectory => - val targetJar = new File(binaryDirectory, s"$binID.jar") buffered bufferQuietly { IO.withTemporaryDirectory { retrieveDirectory => - update(getModule(sourcesModule), retrieveDirectory) match { case Left(uw) => import sbt.util.ShowLines._ - throw new InvalidComponent(s"Couldn't retrieve source module: $sourcesModule\n" + - uw.lines.mkString("\n")) + throw new InvalidComponent( + s"Couldn't retrieve source module: $sourcesModule\n" + + uw.lines.mkString("\n")) case Right(allArtifacts) => val (sources, xsbtiJars) = allArtifacts partition (_.getName endsWith "-sources.jar") - AnalyzingCompiler.compileSources(sources, targetJar, xsbtiJars, sourcesModule.name, compiler, log) + AnalyzingCompiler.compileSources(sources, + targetJar, + xsbtiJars, + sourcesModule.name, + compiler, + log) manager.define(binID, Seq(targetJar)) } } @@ -99,11 +136,14 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ZincComp */ private def getModule(moduleID: ModuleID): ivySbt.Module = { val sha1 = Hash.toHex(Hash(moduleID.name)) - val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, moduleID.revision).withConfigurations(moduleID.configurations) + val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, moduleID.revision) + .withConfigurations(moduleID.configurations) getModule(dummyID, Vector(moduleID)) } - private def getModule(moduleID: ModuleID, deps: Vector[ModuleID], uo: UpdateOptions = UpdateOptions()): ivySbt.Module = { + private def getModule(moduleID: ModuleID, + deps: Vector[ModuleID], + uo: UpdateOptions = UpdateOptions()): ivySbt.Module = { val moduleSetting = InlineConfiguration( validate = false, ivyScala = None, @@ -127,15 +167,24 @@ private[inc] class IvyComponentCompiler(compiler: RawCompiler, manager: ZincComp s"unknown" } - private def update(module: ivySbt.Module, retrieveDirectory: File): Either[UnresolvedWarning, Vector[File]] = { - val retrieveConfiguration = RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false, None) + private def update(module: ivySbt.Module, + retrieveDirectory: File): Either[UnresolvedWarning, Vector[File]] = { + val retrieveConfiguration = + RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false, None) val updateConfiguration = UpdateConfiguration( Some(retrieveConfiguration), - missingOk = false, UpdateLogging.DownloadOnly, ArtifactTypeFilter.forbid(Set("doc")) + missingOk = false, + UpdateLogging.DownloadOnly, + ArtifactTypeFilter.forbid(Set("doc")) ) buffered.info(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.") - IvyActions.updateEither(module, updateConfiguration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, buffered) match { + IvyActions.updateEither(module, + updateConfiguration, + UnresolvedWarningConfiguration(), + LogicalClock.unknown, + None, + buffered) match { case Left(unresolvedWarning) => buffered.debug(s"Couldn't retrieve module ${dependenciesNames(module)}.") Left(unresolvedWarning) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala index e0cc8f418..4bd983159 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala @@ -23,82 +23,89 @@ import sbt.io.IO * This is used for compiled source jars so that the compilation need not be repeated for other projects on the same * machine. */ -class ZincComponentManager(globalLock: xsbti.GlobalLock, provider: xsbti.ComponentProvider, - secondaryCacheDir: Option[File], val log: Logger) { +class ZincComponentManager(globalLock: xsbti.GlobalLock, + provider: xsbti.ComponentProvider, + secondaryCacheDir: Option[File], + val log: Logger) { + /** Get all of the files for component 'id', throwing an exception if no files exist for the component. */ - def files(id: String)(ifMissing: IfMissing): Iterable[File] = - { - def fromSecondary = - lockSecondaryCache { - update(id) - getOrElse(createAndCache) - } getOrElse notFound - def getOrElse(orElse: => Iterable[File]): Iterable[File] = - { - val existing = provider.component(id) - if (existing.isEmpty) orElse - else existing - } - def notFound = invalid("Could not find required component '" + id + "'") - def createAndCache = - ifMissing match { - case IfMissing.Fail => notFound - case d: IfMissing.Define => - d.run() // this is expected to have called define. - if (d.useSecondaryCache) { - cacheToSecondaryCache(id) - } - getOrElse(notFound) - } - lockLocalCache { getOrElse(fromSecondary) } + def files(id: String)(ifMissing: IfMissing): Iterable[File] = { + def fromSecondary = + lockSecondaryCache { + update(id) + getOrElse(createAndCache) + } getOrElse notFound + def getOrElse(orElse: => Iterable[File]): Iterable[File] = { + val existing = provider.component(id) + if (existing.isEmpty) orElse + else existing } + def notFound = invalid("Could not find required component '" + id + "'") + def createAndCache = + ifMissing match { + case IfMissing.Fail => notFound + case d: IfMissing.Define => + d.run() // this is expected to have called define. + if (d.useSecondaryCache) { + cacheToSecondaryCache(id) + } + getOrElse(notFound) + } + lockLocalCache { getOrElse(fromSecondary) } + } + /** This is used to lock the local cache in project/boot/. By checking the local cache first, we can avoid grabbing a global lock. */ private def lockLocalCache[T](action: => T): T = lock(provider.lockFile)(action) + /** This is used to ensure atomic access to components in the global Ivy cache.*/ private def lockSecondaryCache[T](action: => T): Option[T] = secondaryCacheDir map { dir => val lockFile = new File(dir, ".sbt.cache.lock") lock(lockFile)(action) } - private def lock[T](file: File)(action: => T): T = globalLock(file, new Callable[T] { def call = action }) + private def lock[T](file: File)(action: => T): T = + globalLock(file, new Callable[T] { def call = action }) + /** Get the file for component 'id', throwing an exception if no files or multiple files exist for the component. */ def file(id: String)(ifMissing: IfMissing): File = files(id)(ifMissing).toList match { case x :: Nil => x - case xs => invalid("Expected single file for component '" + id + "', found: " + xs.mkString(", ")) + case xs => + invalid("Expected single file for component '" + id + "', found: " + xs.mkString(", ")) } private def invalid(msg: String) = throw new InvalidComponent(msg) - def define(id: String, files: Iterable[File]) = lockLocalCache { provider.defineComponent(id, files.toSeq.toArray) } + def define(id: String, files: Iterable[File]) = lockLocalCache { + provider.defineComponent(id, files.toSeq.toArray) + } + /** Retrieve the file for component 'id' from the secondary cache. */ - private def update(id: String): Unit = - { - secondaryCacheDir map { dir => - val file = seondaryCacheFile(id, dir) - if (file.exists) { - define(id, Seq(file)) - } + private def update(id: String): Unit = { + secondaryCacheDir map { dir => + val file = seondaryCacheFile(id, dir) + if (file.exists) { + define(id, Seq(file)) } - () } + () + } + /** Install the files for component 'id' to the secondary cache. */ - private def cacheToSecondaryCache(id: String): Unit = - { - val fromPrimaryCache = file(id)(IfMissing.fail) - secondaryCacheDir match { - case Some(dir) => - val file = seondaryCacheFile(id, dir) - IO.copyFile(fromPrimaryCache, file) - case _ => () - } - () + private def cacheToSecondaryCache(id: String): Unit = { + val fromPrimaryCache = file(id)(IfMissing.fail) + secondaryCacheDir match { + case Some(dir) => + val file = seondaryCacheFile(id, dir) + IO.copyFile(fromPrimaryCache, file) + case _ => () } + () + } private val sbtOrg = xsbti.ArtifactInfo.SbtOrganization - private def seondaryCacheFile(id: String, dir: File): File = - { - val fileName = id + "-" + ZincComponentManager.stampedVersion + ".jar" - new File(new File(dir, sbtOrg), fileName) - } + private def seondaryCacheFile(id: String, dir: File): File = { + val fileName = id + "-" + ZincComponentManager.stampedVersion + ".jar" + new File(new File(dir, sbtOrg), fileName) + } } class InvalidComponent(msg: String, cause: Throwable) extends RuntimeException(msg, cause) { def this(msg: String) = this(msg, null) @@ -106,6 +113,7 @@ class InvalidComponent(msg: String, cause: Throwable) extends RuntimeException(m sealed trait IfMissing object IfMissing { def fail: IfMissing = Fail + /** f is expected to call ZincComponentManager.define. */ def define(useSecondaryCache: Boolean, f: => Unit): IfMissing = new Define(useSecondaryCache, f) object Fail extends IfMissing @@ -114,15 +122,15 @@ object IfMissing { } } object ZincComponentManager { - lazy val (version, timestamp) = - { - val properties = new java.util.Properties - val propertiesStream = versionResource.openStream - try { properties.load(propertiesStream) } finally { propertiesStream.close() } - (properties.getProperty("version"), properties.getProperty("timestamp")) - } + lazy val (version, timestamp) = { + val properties = new java.util.Properties + val propertiesStream = versionResource.openStream + try { properties.load(propertiesStream) } finally { propertiesStream.close() } + (properties.getProperty("version"), properties.getProperty("timestamp")) + } lazy val stampedVersion = version + "_" + timestamp import java.net.URL - private def versionResource: URL = getClass.getResource("/incrementalcompiler.version.properties") + private def versionResource: URL = + getClass.getResource("/incrementalcompiler.version.properties") } diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 5b20a0eb4..c966a4390 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -9,7 +9,14 @@ import sbt.internal.inc.classpath.ClasspathUtilities import sbt.internal.librarymanagement.JsonUtil import sbt.io.IO import sbt.io.syntax._ -import sbt.librarymanagement.{ ModuleID, UpdateOptions, Resolver, Patterns, FileRepository, DefaultMavenRepository } +import sbt.librarymanagement.{ + ModuleID, + UpdateOptions, + Resolver, + Patterns, + FileRepository, + DefaultMavenRepository +} import sbt.util.Logger import xsbti.{ ComponentProvider, GlobalLock } @@ -19,29 +26,34 @@ import xsbti.{ ComponentProvider, GlobalLock } abstract class BridgeProviderSpecification extends BaseIvySpecification { // log.setLevel(Level.Warn) - def realLocal: Resolver = - { - val pList = Vector(s"$${user.home}/.ivy2/local/${Resolver.localBasePattern}") - FileRepository("local", Resolver.defaultFileConfiguration, Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false)) - } + def realLocal: Resolver = { + val pList = Vector(s"$${user.home}/.ivy2/local/${Resolver.localBasePattern}") + FileRepository( + "local", + Resolver.defaultFileConfiguration, + Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false)) + } override def resolvers: Vector[Resolver] = Vector(realLocal, DefaultMavenRepository) private val ivyConfiguration = mkIvyConfiguration(UpdateOptions()) - def secondaryCacheDirectory: File = - { - val target = file("target").getAbsoluteFile - target / "zinc-components" - } + def secondaryCacheDirectory: File = { + val target = file("target").getAbsoluteFile + target / "zinc-components" + } def secondaryCacheOpt: Option[File] = Some(secondaryCacheDirectory) def getCompilerBridge(targetDir: File, log: Logger, scalaVersion: String): File = { val instance = scalaInstance(scalaVersion) val bridgeId = compilerBridgeId(scalaVersion) - val sourceModule = ModuleID(xsbti.ArtifactInfo.SbtOrganization, bridgeId, ComponentCompiler.incrementalVersion).withConfigurations(Some("component")).sources() + val sourceModule = ModuleID( + xsbti.ArtifactInfo.SbtOrganization, + bridgeId, + ComponentCompiler.incrementalVersion).withConfigurations(Some("component")).sources() val raw = new RawCompiler(instance, ClasspathOptionsUtil.auto, log) val manager = new ZincComponentManager(lock, provider(targetDir), secondaryCacheOpt, log) - val componentCompiler = new IvyComponentCompiler(raw, manager, ivyConfiguration, sourceModule, log) + val componentCompiler = + new IvyComponentCompiler(raw, manager, ivyConfiguration, sourceModule, log) val bridge = componentCompiler.apply() val target = targetDir / s"target-bridge-$scalaVersion.jar" @@ -51,9 +63,14 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { def scalaInstance(scalaVersion: String): ScalaInstance = { val scalaModule = { - val dummyModule = ModuleID(JsonUtil.sbtOrgTemp, "tmp-scala-" + scalaVersion, scalaVersion).withConfigurations(Some("compile")) - val scalaLibrary = ModuleID(xsbti.ArtifactInfo.ScalaOrganization, xsbti.ArtifactInfo.ScalaLibraryID, scalaVersion).withConfigurations(Some("compile")) - val scalaCompiler = ModuleID(xsbti.ArtifactInfo.ScalaOrganization, xsbti.ArtifactInfo.ScalaCompilerID, scalaVersion).withConfigurations(Some("compile")) + val dummyModule = ModuleID(JsonUtil.sbtOrgTemp, "tmp-scala-" + scalaVersion, scalaVersion) + .withConfigurations(Some("compile")) + val scalaLibrary = ModuleID(xsbti.ArtifactInfo.ScalaOrganization, + xsbti.ArtifactInfo.ScalaLibraryID, + scalaVersion).withConfigurations(Some("compile")) + val scalaCompiler = ModuleID(xsbti.ArtifactInfo.ScalaOrganization, + xsbti.ArtifactInfo.ScalaCompilerID, + scalaVersion).withConfigurations(Some("compile")) module(dummyModule, Vector(scalaLibrary, scalaCompiler), None) } @@ -68,18 +85,27 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { def isCompiler(f: File) = f.getName startsWith "scala-compiler-" def isLibrary(f: File) = f.getName startsWith "scala-library-" - val scalaCompilerJar = allArtifacts find isCompiler getOrElse (throw new RuntimeException("Not found: scala-compiler")) - val scalaLibraryJar = allArtifacts find isLibrary getOrElse (throw new RuntimeException("Not found: scala-library")) + val scalaCompilerJar = allArtifacts find isCompiler getOrElse (throw new RuntimeException( + "Not found: scala-compiler")) + val scalaLibraryJar = allArtifacts find isLibrary getOrElse (throw new RuntimeException( + "Not found: scala-library")) val others = allArtifacts filterNot (a => isCompiler(a) || isLibrary(a)) scalaInstance(scalaCompilerJar, scalaLibraryJar, others) } - def scalaInstance(scalaCompiler: File, scalaLibrary: File, scalaExtra: Seq[File]): ScalaInstance = { + def scalaInstance(scalaCompiler: File, + scalaLibrary: File, + scalaExtra: Seq[File]): ScalaInstance = { val loader = scalaLoader(scalaLibrary +: scalaCompiler +: scalaExtra) val version = scalaVersion(loader) val allJars = (scalaLibrary +: scalaCompiler +: scalaExtra).toArray - new ScalaInstance(version.getOrElse("unknown"), loader, scalaLibrary, scalaCompiler, allJars, version) + new ScalaInstance(version.getOrElse("unknown"), + loader, + scalaLibrary, + scalaCompiler, + allJars, + version) } def compilerBridgeId(scalaVersion: String) = @@ -89,14 +115,17 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { case _ => "compiler-bridge_2.12" } - def scalaLoader(jars: Seq[File]) = new URLClassLoader(sbt.io.Path.toURLs(jars), ClasspathUtilities.rootLoader) + def scalaLoader(jars: Seq[File]) = + new URLClassLoader(sbt.io.Path.toURLs(jars), ClasspathUtilities.rootLoader) def scalaVersion(scalaLoader: ClassLoader): Option[String] = propertyFromResource("compiler.properties", "version.number", scalaLoader) /** * Get a property from a properties file resource in the classloader. */ - def propertyFromResource(resource: String, property: String, classLoader: ClassLoader): Option[String] = { + def propertyFromResource(resource: String, + property: String, + classLoader: ClassLoader): Option[String] = { val props = propertiesFromResource(resource, classLoader) Option(props.getProperty(property)) } @@ -107,9 +136,9 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { def propertiesFromResource(resource: String, classLoader: ClassLoader): Properties = { val props = new Properties val stream = classLoader.getResourceAsStream(resource) - try { props.load(stream) } - catch { case _: Exception => } - finally { if (stream ne null) stream.close() } + try { props.load(stream) } catch { case _: Exception => } finally { + if (stream ne null) stream.close() + } props } @@ -122,7 +151,9 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { override def lockFile(): File = targetDir / "lock" override def defineComponent(componentID: String, files: Array[File]): Unit = - files foreach { f => IO.copyFile(f, targetDir / componentID / f.getName) } + files foreach { f => + IO.copyFile(f, targetDir / componentID / f.getName) + } override def addToComponent(componentID: String, files: Array[File]): Boolean = { defineComponent(componentID, files) From 3f1cce379ffc342db669441f5ec8a2374cb466f8 Mon Sep 17 00:00:00 2001 From: jvican Date: Thu, 18 May 2017 17:32:04 +0200 Subject: [PATCH 50/90] Add `CompilerBridgeProvider` interface and misc. * Add interface for the provider. * Rename `IvyComponentCompiler` to `ZincComponentCompiler`. * Split `ZincComponentCompiler` and `ZincComponentManager`. * Define `IfMissing` and `InvalidComponent` into independent files. * Rename variables and internal API to be clearer. --- .../sbt/internal/inc/ComponentCompiler.scala | 199 ---------------- .../scala/sbt/internal/inc/IfMissing.scala | 14 ++ .../sbt/internal/inc/InvalidComponent.scala | 5 + .../sbt/internal/inc/ResourceLoader.scala | 13 ++ .../internal/inc/ZincComponentCompiler.scala | 218 ++++++++++++++++++ .../internal/inc/ZincComponentManager.scala | 61 +++-- .../inc/BridgeProviderSpecification.scala | 6 +- ....scala => ZincComponentCompilerSpec.scala} | 2 +- 8 files changed, 281 insertions(+), 237 deletions(-) delete mode 100644 internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala create mode 100644 internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/IfMissing.scala create mode 100644 internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/InvalidComponent.scala create mode 100644 internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala create mode 100644 internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala rename internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/{IvyComponentCompilerSpec.scala => ZincComponentCompilerSpec.scala} (87%) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala deleted file mode 100644 index 2888cfb14..000000000 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ComponentCompiler.scala +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Zinc - The incremental compiler for Scala. - * Copyright 2011 - 2017, Lightbend, Inc. - * Copyright 2008 - 2010, Mark Harrah - * This software is released under the terms written in LICENSE. - */ - -package sbt -package internal -package inc - -import java.io.File -import sbt.io.{ Hash, IO } -import sbt.internal.librarymanagement.{ - IvyConfiguration, - JsonUtil, - IvySbt, - InlineConfiguration, - RetrieveConfiguration, - IvyActions, - UnresolvedWarningConfiguration, - LogicalClock, - UnresolvedWarning -} -import sbt.librarymanagement.{ - Configurations, - ModuleID, - ModuleInfo, - Resolver, - UpdateConfiguration, - UpdateLogging, - UpdateOptions, - ArtifactTypeFilter -} -import sbt.librarymanagement.syntax._ -import sbt.util.Logger -import sbt.internal.util.{ BufferedLogger, FullLogger } - -private[sbt] object ComponentCompiler { - // val xsbtiID = "xsbti" - // val srcExtension = "-src" - val binSeparator = "-bin_" - val javaVersion = System.getProperty("java.class.version") - - def interfaceProvider(manager: ZincComponentManager, - ivyConfiguration: IvyConfiguration, - sourcesModule: ModuleID): CompilerBridgeProvider = - new CompilerBridgeProvider { - def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File = { - // this is the instance used to compile the interface component - val componentCompiler = new IvyComponentCompiler( - new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, log), - manager, - ivyConfiguration, - sourcesModule, - log) - log.debug( - "Getting " + sourcesModule + " from component compiler for Scala " + scalaInstance.version) - componentCompiler() - } - } - - lazy val incrementalVersion = { - val properties = new java.util.Properties - val propertiesStream = - getClass.getResource("/incrementalcompiler.version.properties").openStream - try { properties.load(propertiesStream) } finally { propertiesStream.close() } - properties.getProperty("version") - } -} - -/** - * Component compiler which is able to to retrieve the compiler bridge sources - * `sourceModule` using Ivy. - * The compiled classes are cached using the provided component manager according - * to the actualVersion field of the RawCompiler. - */ -private[inc] class IvyComponentCompiler(compiler: RawCompiler, - manager: ZincComponentManager, - ivyConfiguration: IvyConfiguration, - sourcesModule: ModuleID, - log: Logger) { - import ComponentCompiler._ - // private val xsbtiInterfaceModuleName = "compiler-interface" - // private val xsbtiInterfaceID = s"interface-$incrementalVersion" - private val sbtOrgTemp = JsonUtil.sbtOrgTemp - private val modulePrefixTemp = "temp-module-" - private val ivySbt: IvySbt = new IvySbt(ivyConfiguration) - private val buffered = new BufferedLogger(FullLogger(log)) - - def apply(): File = { - // binID is of the form "org.example-compilerbridge-1.0.0-bin_2.11.7__50.0" - val binID = binaryID( - s"${sourcesModule.organization}-${sourcesModule.name}-${sourcesModule.revision}") - manager.file(binID)(IfMissing.define(true, compileAndInstall(binID))) - } - - private def binaryID(id: String): String = { - val base = id + binSeparator + compiler.scalaInstance.actualVersion - base + "__" + javaVersion - } - - private def compileAndInstall(binID: String): Unit = - IO.withTemporaryDirectory { binaryDirectory => - val targetJar = new File(binaryDirectory, s"$binID.jar") - - buffered bufferQuietly { - - IO.withTemporaryDirectory { retrieveDirectory => - update(getModule(sourcesModule), retrieveDirectory) match { - case Left(uw) => - import sbt.util.ShowLines._ - throw new InvalidComponent( - s"Couldn't retrieve source module: $sourcesModule\n" + - uw.lines.mkString("\n")) - - case Right(allArtifacts) => - val (sources, xsbtiJars) = allArtifacts partition (_.getName endsWith "-sources.jar") - AnalyzingCompiler.compileSources(sources, - targetJar, - xsbtiJars, - sourcesModule.name, - compiler, - log) - manager.define(binID, Seq(targetJar)) - } - } - - } - } - - /** - * Returns a dummy module that depends on `moduleID`. - * Note: Sbt's implementation of Ivy requires us to do this, because only the dependencies - * of the specified module will be downloaded. - */ - private def getModule(moduleID: ModuleID): ivySbt.Module = { - val sha1 = Hash.toHex(Hash(moduleID.name)) - val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, moduleID.revision) - .withConfigurations(moduleID.configurations) - getModule(dummyID, Vector(moduleID)) - } - - private def getModule(moduleID: ModuleID, - deps: Vector[ModuleID], - uo: UpdateOptions = UpdateOptions()): ivySbt.Module = { - val moduleSetting = InlineConfiguration( - validate = false, - ivyScala = None, - module = moduleID, - moduleInfo = ModuleInfo(moduleID.name), - dependencies = deps - ).withConfigurations(Vector(Configurations.Component)) - - new ivySbt.Module(moduleSetting) - } - - private def dependenciesNames(module: ivySbt.Module): String = module.moduleSettings match { - // `module` is a dummy module, we will only fetch its dependencies. - case ic: InlineConfiguration => - ic.dependencies map { - case mID: ModuleID => - import mID._ - s"$organization % $name % $revision" - } mkString ", " - case _ => - s"unknown" - } - - private def update(module: ivySbt.Module, - retrieveDirectory: File): Either[UnresolvedWarning, Vector[File]] = { - val retrieveConfiguration = - RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false, None) - val updateConfiguration = UpdateConfiguration( - Some(retrieveConfiguration), - missingOk = false, - UpdateLogging.DownloadOnly, - ArtifactTypeFilter.forbid(Set("doc")) - ) - - buffered.info(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.") - IvyActions.updateEither(module, - updateConfiguration, - UnresolvedWarningConfiguration(), - LogicalClock.unknown, - None, - buffered) match { - case Left(unresolvedWarning) => - buffered.debug(s"Couldn't retrieve module ${dependenciesNames(module)}.") - Left(unresolvedWarning) - - case Right(updateReport) => - val allFiles = updateReport.allFiles - buffered.debug(s"Files retrieved for ${dependenciesNames(module)}:") - buffered.debug(allFiles mkString ", ") - Right(allFiles.toVector) - } - } -} diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/IfMissing.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/IfMissing.scala new file mode 100644 index 000000000..1e640ed0d --- /dev/null +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/IfMissing.scala @@ -0,0 +1,14 @@ +package sbt.internal.inc + +sealed trait IfMissing + +object IfMissing { + def fail: IfMissing = Fail + + /** f is expected to call ZincComponentManager.define. */ + def define(useSecondaryCache: Boolean, f: => Unit): IfMissing = new Define(useSecondaryCache, f) + object Fail extends IfMissing + final class Define(val useSecondaryCache: Boolean, define: => Unit) extends IfMissing { + def run(): Unit = define + } +} \ No newline at end of file diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/InvalidComponent.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/InvalidComponent.scala new file mode 100644 index 000000000..c1e011bc6 --- /dev/null +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/InvalidComponent.scala @@ -0,0 +1,5 @@ +package sbt.internal.inc + +class InvalidComponent(msg: String, cause: Throwable) extends RuntimeException(msg, cause) { + def this(msg: String) = this(msg, null) +} diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala new file mode 100644 index 000000000..db2758743 --- /dev/null +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala @@ -0,0 +1,13 @@ +package sbt.internal.inc + +import java.util.Properties + +/** Defines utilities to load Java properties from the JVM. */ +private[inc] object ResourceLoader { + def getPropertiesFor(resource: String, classLoader: ClassLoader): Properties = { + val properties = new java.util.Properties + val propertiesStream = getClass.getResource(resource).openStream + try { properties.load(propertiesStream) } finally { propertiesStream.close() } + properties + } +} diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala new file mode 100644 index 000000000..fc23e1ad7 --- /dev/null +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -0,0 +1,218 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + +package sbt +package internal +package inc + +import java.io.File + +import sbt.io.{ Hash, IO } +import sbt.internal.librarymanagement.{ + InlineConfiguration, + IvyActions, + IvyConfiguration, + IvySbt, + JsonUtil, + LogicalClock, + RetrieveConfiguration, + UnresolvedWarning, + UnresolvedWarningConfiguration +} +import sbt.librarymanagement.{ + ArtifactTypeFilter, + Configurations, + ModuleID, + ModuleInfo, + Resolver, + UpdateConfiguration, + UpdateLogging, + UpdateOptions +} +import sbt.librarymanagement.syntax._ +import sbt.util.{ InterfaceUtil, Logger } +import xsbti.compile.CompilerBridgeProvider + +private[sbt] object ZincComponentCompiler { + final val binSeparator = "-bin_" + final val javaClassVersion = System.getProperty("java.class.version") + + private[inc] final val sbtOrgTemp = JsonUtil.sbtOrgTemp + private[inc] final val modulePrefixTemp = "temp-module-" + + private final val ZincVersionPropertyFile = "/incrementalcompiler.version.properties" + private final val ZincVersionProperty = "version" + final lazy val incrementalVersion: String = { + val cl = this.getClass.getClassLoader + ResourceLoader.getPropertiesFor(ZincVersionPropertyFile, cl).getProperty(ZincVersionProperty) + } + + private class ZincCompilerBridgeProvider(manager: ZincComponentManager, + ivyConfiguration: IvyConfiguration, + bridgeModule: ModuleID) + extends CompilerBridgeProvider { + + override def getBridgeSources(scalaInstance: xsbti.compile.ScalaInstance, + logger: xsbti.Logger): File = { + val autoClasspath = ClasspathOptionsUtil.auto + val bridgeCompiler = new RawCompiler(scalaInstance, autoClasspath, logger) + val ivyComponent = + new ZincComponentCompiler(bridgeCompiler, manager, ivyConfiguration, bridgeModule, logger) + logger.debug(InterfaceUtil.f0(s"Getting $bridgeModule for Scala ${scalaInstance.version}")) + ivyComponent.getCompiledBridgeJar + } + } + + def interfaceProvider(manager: ZincComponentManager, + ivyConfiguration: IvyConfiguration, + sourcesModule: ModuleID): CompilerBridgeProvider = + new ZincCompilerBridgeProvider(manager, ivyConfiguration, sourcesModule) + +} + +/** + * Component compiler which is able to to retrieve the compiler bridge sources + * `sourceModule` using Ivy. + * The compiled classes are cached using the provided component manager according + * to the actualVersion field of the RawCompiler. + */ +private[inc] class ZincComponentCompiler( + compiler: RawCompiler, + manager: ZincComponentManager, + ivyConfiguration: IvyConfiguration, + bridgeSources: ModuleID, + log: Logger +) { + import sbt.internal.util.{ BufferedLogger, FullLogger } + private final val ivySbt: IvySbt = new IvySbt(ivyConfiguration) + private final val buffered = new BufferedLogger(FullLogger(log)) + + def getCompiledBridgeJar: File = { + val jarBinaryName = createBridgeSourcesID(bridgeSources) + manager.file(jarBinaryName)(IfMissing.define(true, compileAndInstall(jarBinaryName))) + } + + /** + * Returns the id for the compiler interface component. + * + * The ID contains the following parts: + * - The organization, name and revision. + * - The bin separator to make clear the jar represents binaries. + * - The Scala version for which the compiler interface is meant to. + * - The JVM class version. + * + * Example: "org.scala-sbt-compiler-bridge-1.0.0-bin_2.11.7__50.0". + * + * @param sources The moduleID representing the compiler bridge sources. + * @return The complete jar identifier for the bridge sources. + */ + private def createBridgeSourcesID(sources: ModuleID): String = { + import ZincComponentCompiler.{ binSeparator, javaClassVersion } + val id = s"${sources.organization}-${sources.name}-${sources.revision}" + val scalaVersion = compiler.scalaInstance.actualVersion() + s"$id$binSeparator${scalaVersion}__$javaClassVersion" + } + + /** + * Resolves the compiler bridge sources, compiles them and installs the sbt component + * in the local filesystem to make sure that it's reused the next time is required. + * + * @param compilerBridgeId The identifier for the compiler bridge sources. + */ + private def compileAndInstall(compilerBridgeId: String): Unit = { + import UnresolvedWarning.unresolvedWarningLines + val ivyModuleForBridge = wrapDependencyInModule(bridgeSources) + IO.withTemporaryDirectory { binaryDirectory => + val target = new File(binaryDirectory, s"$compilerBridgeId.jar") + buffered bufferQuietly { + IO.withTemporaryDirectory { retrieveDirectory => + update(ivyModuleForBridge, retrieveDirectory) match { + case Left(uw) => + val mod = bridgeSources.toString + val unresolvedLines = unresolvedWarningLines.showLines(uw) + val unretrievedMessage = s"The compiler bridge sources $mod could not be retrieved." + throw new InvalidComponent(s"$unresolvedLines\n$unresolvedLines") + + case Right(allArtifacts) => + val (srcs, xsbtiJars) = allArtifacts.partition(_.getName.endsWith("-sources.jar")) + val toCompileID = bridgeSources.name + AnalyzingCompiler.compileSources(srcs, target, xsbtiJars, toCompileID, compiler, log) + manager.define(compilerBridgeId, Seq(target)) + } + } + + } + } + } + + /** + * Returns an ivy module that will wrap and download a given `moduleID`. + * + * @param moduleID The `moduleID` that needs to be wrapped in a dummy module to be downloaded. + */ + private def wrapDependencyInModule(moduleID: ModuleID): ivySbt.Module = { + def getModule(moduleID: ModuleID, deps: Vector[ModuleID], uo: UpdateOptions): ivySbt.Module = { + val moduleInfo = ModuleInfo(moduleID.name) + val componentIvySettings = InlineConfiguration( + validate = false, + ivyScala = None, + module = moduleID, + moduleInfo = moduleInfo, + dependencies = deps + ).withConfigurations(Vector(Configurations.Component)) + new ivySbt.Module(componentIvySettings) + } + + import ZincComponentCompiler.{ sbtOrgTemp, modulePrefixTemp } + val sha1 = Hash.toHex(Hash(moduleID.name)) + val dummyID = ModuleID(sbtOrgTemp, s"$modulePrefixTemp$sha1", moduleID.revision) + .withConfigurations(moduleID.configurations) + val defaultUpdateOptions = UpdateOptions() + getModule(dummyID, Vector(moduleID), defaultUpdateOptions) + } + + // The implementation of this method is linked to `wrapDependencyInModule` + private def prettyPrintDependency(module: ivySbt.Module): String = { + module.moduleSettings match { + case ic: InlineConfiguration => + // Pretty print the module as `ModuleIDExtra.toStringImpl` does. + val dependency = + ic.dependencies.map(m => s"${m.organization}:${m.name}:${m.revision}").headOption + dependency.getOrElse(sys.error("Fatal: more than one dependency in dummy bridge module.")) + case _ => sys.error("Fatal: configuration to download was not inline.") + } + } + + private final val warningConf = UnresolvedWarningConfiguration() + private final val defaultRetrievePattern = Resolver.defaultRetrievePattern + private def defaultUpdateConfiguration(retrieveDirectory: File): UpdateConfiguration = { + val retrieve = RetrieveConfiguration(retrieveDirectory, defaultRetrievePattern, false, None) + val logLevel = UpdateLogging.DownloadOnly + val noDocs = ArtifactTypeFilter.forbid(Set("doc")) + UpdateConfiguration(Some(retrieve), missingOk = false, logLevel, noDocs) + } + + private def update(module: ivySbt.Module, + retrieveDirectory: File): Either[UnresolvedWarning, Vector[File]] = { + import IvyActions.updateEither + val updateConfiguration = defaultUpdateConfiguration(retrieveDirectory) + val dependencies = prettyPrintDependency(module) + buffered.info(s"Attempting to fetch $dependencies. This operation may fail.") + val clockForCache = LogicalClock.unknown + updateEither(module, updateConfiguration, warningConf, clockForCache, None, buffered) match { + case Left(unresolvedWarning) => + buffered.debug(s"Couldn't retrieve module ${prettyPrintDependency(module)}.") + Left(unresolvedWarning) + + case Right(updateReport) => + val allFiles = updateReport.allFiles + buffered.debug(s"Files retrieved for ${prettyPrintDependency(module)}:") + buffered.debug(allFiles mkString ", ") + Right(allFiles) + } + } +} diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala index 4bd983159..5af4baa6e 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala @@ -30,18 +30,14 @@ class ZincComponentManager(globalLock: xsbti.GlobalLock, /** Get all of the files for component 'id', throwing an exception if no files exist for the component. */ def files(id: String)(ifMissing: IfMissing): Iterable[File] = { - def fromSecondary = - lockSecondaryCache { - update(id) - getOrElse(createAndCache) - } getOrElse notFound + def notFound = invalid("Could not find required component '" + id + "'") def getOrElse(orElse: => Iterable[File]): Iterable[File] = { val existing = provider.component(id) if (existing.isEmpty) orElse else existing } - def notFound = invalid("Could not find required component '" + id + "'") - def createAndCache = + + def createAndCache = { ifMissing match { case IfMissing.Fail => notFound case d: IfMissing.Define => @@ -51,9 +47,31 @@ class ZincComponentManager(globalLock: xsbti.GlobalLock, } getOrElse(notFound) } - lockLocalCache { getOrElse(fromSecondary) } + } + + def fromSecondary: Iterable[File] = { + lockSecondaryCache { + update(id) + getOrElse(createAndCache) + }.getOrElse(notFound) + } + + lockLocalCache(getOrElse(fromSecondary)) } + /** Get the file for component 'id', throwing an exception if no files or multiple files exist for the component. */ + def file(id: String)(ifMissing: IfMissing): File = { + files(id)(ifMissing).toList match { + case x :: Nil => x + case xs => + invalid("Expected single file for component '" + id + "', found: " + xs.mkString(", ")) + } + } + + /** Associate a component id to a series of jars. */ + def define(id: String, files: Iterable[File]): Unit = + lockLocalCache(provider.defineComponent(id, files.toSeq.toArray)) + /** This is used to lock the local cache in project/boot/. By checking the local cache first, we can avoid grabbing a global lock. */ private def lockLocalCache[T](action: => T): T = lock(provider.lockFile)(action) @@ -66,28 +84,16 @@ class ZincComponentManager(globalLock: xsbti.GlobalLock, private def lock[T](file: File)(action: => T): T = globalLock(file, new Callable[T] { def call = action }) - /** Get the file for component 'id', throwing an exception if no files or multiple files exist for the component. */ - def file(id: String)(ifMissing: IfMissing): File = - files(id)(ifMissing).toList match { - case x :: Nil => x - case xs => - invalid("Expected single file for component '" + id + "', found: " + xs.mkString(", ")) - } private def invalid(msg: String) = throw new InvalidComponent(msg) - def define(id: String, files: Iterable[File]) = lockLocalCache { - provider.defineComponent(id, files.toSeq.toArray) - } - /** Retrieve the file for component 'id' from the secondary cache. */ private def update(id: String): Unit = { - secondaryCacheDir map { dir => + secondaryCacheDir foreach { dir => val file = seondaryCacheFile(id, dir) if (file.exists) { define(id, Seq(file)) } } - () } /** Install the files for component 'id' to the secondary cache. */ @@ -107,20 +113,7 @@ class ZincComponentManager(globalLock: xsbti.GlobalLock, new File(new File(dir, sbtOrg), fileName) } } -class InvalidComponent(msg: String, cause: Throwable) extends RuntimeException(msg, cause) { - def this(msg: String) = this(msg, null) -} -sealed trait IfMissing -object IfMissing { - def fail: IfMissing = Fail - /** f is expected to call ZincComponentManager.define. */ - def define(useSecondaryCache: Boolean, f: => Unit): IfMissing = new Define(useSecondaryCache, f) - object Fail extends IfMissing - final class Define(val useSecondaryCache: Boolean, define: => Unit) extends IfMissing { - def run(): Unit = define - } -} object ZincComponentManager { lazy val (version, timestamp) = { val properties = new java.util.Properties diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index c966a4390..d09045b87 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -48,14 +48,14 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { val sourceModule = ModuleID( xsbti.ArtifactInfo.SbtOrganization, bridgeId, - ComponentCompiler.incrementalVersion).withConfigurations(Some("component")).sources() + ZincComponentCompiler.incrementalVersion).withConfigurations(Some("component")).sources() val raw = new RawCompiler(instance, ClasspathOptionsUtil.auto, log) val manager = new ZincComponentManager(lock, provider(targetDir), secondaryCacheOpt, log) val componentCompiler = - new IvyComponentCompiler(raw, manager, ivyConfiguration, sourceModule, log) + new ZincComponentCompiler(raw, manager, ivyConfiguration, sourceModule, log) - val bridge = componentCompiler.apply() + val bridge = componentCompiler.getCompiledBridgeJar val target = targetDir / s"target-bridge-$scalaVersion.jar" IO.copyFile(bridge, target) target diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala similarity index 87% rename from internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala rename to internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala index d6d2d66be..ad403ffdc 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyComponentCompilerSpec.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala @@ -3,7 +3,7 @@ package sbt.internal.inc import sbt.io.IO import sbt.util.Logger -class IvyComponentCompilerSpec extends BridgeProviderSpecification { +class ZincComponentCompilerSpec extends BridgeProviderSpecification { val scala210 = "2.10.5" val scala211 = "2.11.8" From e756f07aedfbe2a849e282e33fa4b8de0a20f624 Mon Sep 17 00:00:00 2001 From: jvican Date: Thu, 18 May 2017 18:06:25 +0200 Subject: [PATCH 51/90] Add headers to files that don't have them --- .../src/main/scala/sbt/internal/inc/IfMissing.scala | 7 +++++++ .../src/main/scala/sbt/internal/inc/InvalidComponent.scala | 7 +++++++ .../src/main/scala/sbt/internal/inc/ResourceLoader.scala | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/IfMissing.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/IfMissing.scala index 1e640ed0d..1f176270a 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/IfMissing.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/IfMissing.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.internal.inc sealed trait IfMissing diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/InvalidComponent.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/InvalidComponent.scala index c1e011bc6..df0505abc 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/InvalidComponent.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/InvalidComponent.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.internal.inc class InvalidComponent(msg: String, cause: Throwable) extends RuntimeException(msg, cause) { diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala index db2758743..4399747dc 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.internal.inc import java.util.Properties From 8d9d007d3c4e49b8d6ff9d73dbc8ad15d839d045 Mon Sep 17 00:00:00 2001 From: jvican Date: Thu, 18 May 2017 18:08:52 +0200 Subject: [PATCH 52/90] Rename `getCompilerSources` to `getCompiledBridge` Previous name was incorrect, we actually return the compiled bridge. --- .../main/scala/sbt/internal/inc/ZincComponentCompiler.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index fc23e1ad7..7ccd25d4f 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -56,8 +56,8 @@ private[sbt] object ZincComponentCompiler { bridgeModule: ModuleID) extends CompilerBridgeProvider { - override def getBridgeSources(scalaInstance: xsbti.compile.ScalaInstance, - logger: xsbti.Logger): File = { + override def getCompiledBridge(scalaInstance: xsbti.compile.ScalaInstance, + logger: xsbti.Logger): File = { val autoClasspath = ClasspathOptionsUtil.auto val bridgeCompiler = new RawCompiler(scalaInstance, autoClasspath, logger) val ivyComponent = From d48f65a8a75640e50182c2d5698d066c3e4a47b6 Mon Sep 17 00:00:00 2001 From: jvican Date: Thu, 18 May 2017 18:26:45 +0200 Subject: [PATCH 53/90] Fix oversight in InvalidComponent message --- .../src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 7ccd25d4f..70ea5da24 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -135,7 +135,7 @@ private[inc] class ZincComponentCompiler( val mod = bridgeSources.toString val unresolvedLines = unresolvedWarningLines.showLines(uw) val unretrievedMessage = s"The compiler bridge sources $mod could not be retrieved." - throw new InvalidComponent(s"$unresolvedLines\n$unresolvedLines") + throw new InvalidComponent(s"$unretrievedMessage\n$unresolvedLines") case Right(allArtifacts) => val (srcs, xsbtiJars) = allArtifacts.partition(_.getName.endsWith("-sources.jar")) From 62a5037d23d7ba798eac978a1bf8f1e6da9e1b10 Mon Sep 17 00:00:00 2001 From: jvican Date: Fri, 19 May 2017 14:42:43 +0200 Subject: [PATCH 54/90] Add `getScalaInstance` to `CompilerBridgeProvider` --- .../main/scala/sbt/internal/inc/Errors.scala | 23 +++ .../sbt/internal/inc/InvalidComponent.scala | 12 -- .../sbt/internal/inc/ResourceLoader.scala | 9 + .../internal/inc/ZincComponentCompiler.scala | 167 ++++++++++++------ 4 files changed, 142 insertions(+), 69 deletions(-) create mode 100644 internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/Errors.scala delete mode 100644 internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/InvalidComponent.scala diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/Errors.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/Errors.scala new file mode 100644 index 000000000..c3c5e8a7f --- /dev/null +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/Errors.scala @@ -0,0 +1,23 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + +package sbt.internal.inc + +class InvalidComponent(msg: String, cause: Throwable) extends RuntimeException(msg, cause) { + def this(msg: String) = this(msg, null) +} + +final class MissingScalaJar(msg: String, cause: Throwable) extends RuntimeException(msg, cause) { + def this(msg: String) = this(msg, null) +} + +object MissingScalaJar { + def missingTemplate(missing: String): String = + s"The $missing could not be found in your cache nor downloaded from the Internet." + def compiler: MissingScalaJar = new MissingScalaJar(missingTemplate("Scala compiler")) + def library: MissingScalaJar = new MissingScalaJar(missingTemplate("Scala library")) +} diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/InvalidComponent.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/InvalidComponent.scala deleted file mode 100644 index df0505abc..000000000 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/InvalidComponent.scala +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Zinc - The incremental compiler for Scala. - * Copyright 2011 - 2017, Lightbend, Inc. - * Copyright 2008 - 2010, Mark Harrah - * This software is released under the terms written in LICENSE. - */ - -package sbt.internal.inc - -class InvalidComponent(msg: String, cause: Throwable) extends RuntimeException(msg, cause) { - def this(msg: String) = this(msg, null) -} diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala index 4399747dc..78e05b6c2 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala @@ -17,4 +17,13 @@ private[inc] object ResourceLoader { try { properties.load(propertiesStream) } finally { propertiesStream.close() } properties } + + def getSafePropertiesFor(resource: String, classLoader: ClassLoader): Properties = { + val properties = new Properties + val propertiesStream = classLoader.getResourceAsStream(resource) + try { properties.load(propertiesStream) } catch { case _: Exception => } finally { + if (propertiesStream ne null) propertiesStream.close() + } + properties + } } diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 70ea5da24..bb266260f 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -11,32 +11,17 @@ package inc import java.io.File +import sbt.internal.inc.classpath.ClasspathUtilities import sbt.io.{ Hash, IO } -import sbt.internal.librarymanagement.{ - InlineConfiguration, - IvyActions, - IvyConfiguration, - IvySbt, - JsonUtil, - LogicalClock, - RetrieveConfiguration, - UnresolvedWarning, - UnresolvedWarningConfiguration -} -import sbt.librarymanagement.{ - ArtifactTypeFilter, - Configurations, - ModuleID, - ModuleInfo, - Resolver, - UpdateConfiguration, - UpdateLogging, - UpdateOptions -} +import sbt.internal.librarymanagement._ +import sbt.internal.util.FullLogger +import sbt.librarymanagement._ import sbt.librarymanagement.syntax._ import sbt.util.{ InterfaceUtil, Logger } import xsbti.compile.CompilerBridgeProvider +import scala.reflect.internal.util.ScalaClassLoader.URLClassLoader + private[sbt] object ZincComponentCompiler { final val binSeparator = "-bin_" final val javaClassVersion = System.getProperty("java.class.version") @@ -59,11 +44,60 @@ private[sbt] object ZincComponentCompiler { override def getCompiledBridge(scalaInstance: xsbti.compile.ScalaInstance, logger: xsbti.Logger): File = { val autoClasspath = ClasspathOptionsUtil.auto - val bridgeCompiler = new RawCompiler(scalaInstance, autoClasspath, logger) - val ivyComponent = - new ZincComponentCompiler(bridgeCompiler, manager, ivyConfiguration, bridgeModule, logger) + val raw = new RawCompiler(scalaInstance, autoClasspath, logger) + val zinc = new ZincComponentCompiler(raw, manager, ivyConfiguration, bridgeModule, logger) logger.debug(InterfaceUtil.f0(s"Getting $bridgeModule for Scala ${scalaInstance.version}")) - ivyComponent.getCompiledBridgeJar + zinc.getCompiledBridgeJar + } + + private final case class ScalaArtifacts(compiler: File, library: File, others: Vector[File]) + + private def getScalaArtifacts(scalaVersion: String, logger: xsbti.Logger): ScalaArtifacts = { + def isPrefixedWith(artifact: File, prefix: String) = artifact.getName.startsWith(prefix) + + import xsbti.ArtifactInfo._ + import Configurations.Compile + import UnresolvedWarning.unresolvedWarningLines + val fullLogger = new FullLogger(logger) + val CompileConf = Some(Compile.name) + val dummyModule = ModuleID(JsonUtil.sbtOrgTemp, s"tmp-scala-$scalaVersion", scalaVersion) + val scalaLibrary = ModuleID(ScalaOrganization, ScalaLibraryID, scalaVersion) + val scalaCompiler = ModuleID(ScalaOrganization, ScalaCompilerID, scalaVersion) + val dependencies = Vector(scalaLibrary, scalaCompiler).map(_.withConfigurations(CompileConf)) + val wrapper = dummyModule.withConfigurations(CompileConf) + val ivySbt: IvySbt = new IvySbt(ivyConfiguration) + val ivyModule = ZincIvyActions.getModule(ivySbt, wrapper, dependencies) + IO.withTemporaryDirectory { retrieveDirectory => + ZincIvyActions.update(ivyModule, retrieveDirectory, fullLogger) match { + case Left(uw) => + val unresolvedLines = unresolvedWarningLines.showLines(uw) + val unretrievedMessage = s"The Scala compiler and library could not be retrieved." + throw new InvalidComponent(s"$unretrievedMessage\n$unresolvedLines") + case Right(allArtifacts) => + val isScalaCompiler = (f: File) => isPrefixedWith(f, "scala-compiler-") + val isScalaLibrary = (f: File) => isPrefixedWith(f, "scala-library-") + val maybeScalaCompiler = allArtifacts.find(isScalaCompiler) + val maybeScalaLibrary = allArtifacts.find(isScalaLibrary) + val others = allArtifacts.filterNot(a => isScalaCompiler(a) || isScalaLibrary(a)) + val scalaCompiler = maybeScalaCompiler.getOrElse(throw MissingScalaJar.compiler) + val scalaLibrary = maybeScalaLibrary.getOrElse(throw MissingScalaJar.library) + ScalaArtifacts(scalaCompiler, scalaLibrary, others) + } + } + } + + override def getScalaInstance(scalaVersion: String, + logger: xsbti.Logger): xsbti.compile.ScalaInstance = { + import sbt.io.Path.toURLs + val scalaArtifacts = getScalaArtifacts(scalaVersion, logger) + val scalaCompiler = scalaArtifacts.compiler + val scalaLibrary = scalaArtifacts.library + val jarsToLoad = (scalaCompiler +: scalaLibrary +: scalaArtifacts.others).toArray + val loader = new URLClassLoader(toURLs(jarsToLoad), ClasspathUtilities.rootLoader) + val properties = ResourceLoader.getSafePropertiesFor("compiler.properties", loader) + val loaderVersion = Option(properties.getProperty("version.number")) + val scalaV = loaderVersion.getOrElse("unknown") + new ScalaInstance(scalaV, loader, scalaLibrary, scalaCompiler, jarsToLoad, loaderVersion) } } @@ -117,6 +151,19 @@ private[inc] class ZincComponentCompiler( s"$id$binSeparator${scalaVersion}__$javaClassVersion" } + /** + * Returns an ivy module that will wrap and download a given `moduleID`. + * + * @param moduleID The `moduleID` that needs to be wrapped in a dummy module to be downloaded. + */ + private[inc] def wrapDependencyInModule(moduleID: ModuleID): IvySbt#Module = { + import ZincComponentCompiler.{ sbtOrgTemp, modulePrefixTemp } + val sha1 = Hash.toHex(Hash(moduleID.name)) + val dummyID = ModuleID(sbtOrgTemp, s"$modulePrefixTemp$sha1", moduleID.revision) + .withConfigurations(moduleID.configurations) + ZincIvyActions.getModule(ivySbt, dummyID, Vector(moduleID)) + } + /** * Resolves the compiler bridge sources, compiles them and installs the sbt component * in the local filesystem to make sure that it's reused the next time is required. @@ -130,7 +177,7 @@ private[inc] class ZincComponentCompiler( val target = new File(binaryDirectory, s"$compilerBridgeId.jar") buffered bufferQuietly { IO.withTemporaryDirectory { retrieveDirectory => - update(ivyModuleForBridge, retrieveDirectory) match { + ZincIvyActions.update(ivyModuleForBridge, retrieveDirectory, buffered) match { case Left(uw) => val mod = bridgeSources.toString val unresolvedLines = unresolvedWarningLines.showLines(uw) @@ -149,34 +196,39 @@ private[inc] class ZincComponentCompiler( } } - /** - * Returns an ivy module that will wrap and download a given `moduleID`. - * - * @param moduleID The `moduleID` that needs to be wrapped in a dummy module to be downloaded. - */ - private def wrapDependencyInModule(moduleID: ModuleID): ivySbt.Module = { - def getModule(moduleID: ModuleID, deps: Vector[ModuleID], uo: UpdateOptions): ivySbt.Module = { - val moduleInfo = ModuleInfo(moduleID.name) - val componentIvySettings = InlineConfiguration( - validate = false, - ivyScala = None, - module = moduleID, - moduleInfo = moduleInfo, - dependencies = deps - ).withConfigurations(Vector(Configurations.Component)) - new ivySbt.Module(componentIvySettings) - } +} - import ZincComponentCompiler.{ sbtOrgTemp, modulePrefixTemp } - val sha1 = Hash.toHex(Hash(moduleID.name)) - val dummyID = ModuleID(sbtOrgTemp, s"$modulePrefixTemp$sha1", moduleID.revision) - .withConfigurations(moduleID.configurations) - val defaultUpdateOptions = UpdateOptions() - getModule(dummyID, Vector(moduleID), defaultUpdateOptions) +object ZincIvyActions { + type IvyModule = IvySbt#Module + + /** Define the default configurations for a Zinc module wrapper. */ + private final val DefaultConfigurations: Vector[Configuration] = + Vector(Configurations.Component, Configurations.Compile) + private final val DefaultUpdateOptions = UpdateOptions() + + /** + * Create a module from its dummy wrapper and its dependencies. + * + * @param wrapper The ModuleID wrapper that will download the dependencies. + * @param deps The dependencies to be downloaded. + * @return A fully-fledged ivy module to be used for [[IvyActions]]. + */ + private[inc] def getModule(ivySbt: IvySbt, + wrapper: ModuleID, + deps: Vector[ModuleID]): IvyModule = { + val moduleInfo = ModuleInfo(wrapper.name) + val componentIvySettings = InlineConfiguration( + validate = false, + ivyScala = None, + module = wrapper, + moduleInfo = moduleInfo, + dependencies = deps + ).withConfigurations(DefaultConfigurations) + new ivySbt.Module(componentIvySettings) } // The implementation of this method is linked to `wrapDependencyInModule` - private def prettyPrintDependency(module: ivySbt.Module): String = { + private def prettyPrintDependency(module: IvyModule): String = { module.moduleSettings match { case ic: InlineConfiguration => // Pretty print the module as `ModuleIDExtra.toStringImpl` does. @@ -196,22 +248,23 @@ private[inc] class ZincComponentCompiler( UpdateConfiguration(Some(retrieve), missingOk = false, logLevel, noDocs) } - private def update(module: ivySbt.Module, - retrieveDirectory: File): Either[UnresolvedWarning, Vector[File]] = { + private[inc] def update(module: IvyModule, + retrieveDirectory: File, + logger: Logger): Either[UnresolvedWarning, Vector[File]] = { import IvyActions.updateEither val updateConfiguration = defaultUpdateConfiguration(retrieveDirectory) val dependencies = prettyPrintDependency(module) - buffered.info(s"Attempting to fetch $dependencies. This operation may fail.") + logger.info(s"Attempting to fetch $dependencies. This operation may fail.") val clockForCache = LogicalClock.unknown - updateEither(module, updateConfiguration, warningConf, clockForCache, None, buffered) match { + updateEither(module, updateConfiguration, warningConf, clockForCache, None, logger) match { case Left(unresolvedWarning) => - buffered.debug(s"Couldn't retrieve module ${prettyPrintDependency(module)}.") + logger.debug(s"Couldn't retrieve module ${prettyPrintDependency(module)}.") Left(unresolvedWarning) case Right(updateReport) => val allFiles = updateReport.allFiles - buffered.debug(s"Files retrieved for ${prettyPrintDependency(module)}:") - buffered.debug(allFiles mkString ", ") + logger.debug(s"Files retrieved for ${prettyPrintDependency(module)}:") + logger.debug(allFiles mkString ", ") Right(allFiles) } } From ae40c096e3b65adcc1c448dd8132321436a6ff94 Mon Sep 17 00:00:00 2001 From: jvican Date: Fri, 19 May 2017 15:43:19 +0200 Subject: [PATCH 55/90] Remove custom `getScalaInstance` and use default --- .../inc/BridgeProviderSpecification.scala | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index d09045b87..71c29a794 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -10,14 +10,15 @@ import sbt.internal.librarymanagement.JsonUtil import sbt.io.IO import sbt.io.syntax._ import sbt.librarymanagement.{ - ModuleID, - UpdateOptions, - Resolver, - Patterns, + DefaultMavenRepository, FileRepository, - DefaultMavenRepository + ModuleID, + Patterns, + Resolver, + UpdateOptions } import sbt.util.Logger +import xsbti.compile.CompilerBridgeProvider import xsbti.{ ComponentProvider, GlobalLock } /** @@ -42,20 +43,29 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { } def secondaryCacheOpt: Option[File] = Some(secondaryCacheDirectory) - def getCompilerBridge(targetDir: File, log: Logger, scalaVersion: String): File = { - val instance = scalaInstance(scalaVersion) + def compilerBridgeId(scalaVersion: String) = { + scalaVersion match { + case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" + case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" + case _ => "compiler-bridge_2.12" + } + } + + def getZincProvider(targetDir: File, scalaVersion: String, log: Logger): CompilerBridgeProvider = { + import xsbti.ArtifactInfo.SbtOrganization + import ZincComponentCompiler.incrementalVersion val bridgeId = compilerBridgeId(scalaVersion) - val sourceModule = ModuleID( - xsbti.ArtifactInfo.SbtOrganization, - bridgeId, - ZincComponentCompiler.incrementalVersion).withConfigurations(Some("component")).sources() + val sourceModule = ModuleID(SbtOrganization, bridgeId, incrementalVersion) + .withConfigurations(Some("component")) + .sources() + val manager = new ZincComponentManager(lock, compProvider(targetDir), secondaryCacheOpt, log) + ZincComponentCompiler.interfaceProvider(manager, ivyConfiguration, sourceModule) + } - val raw = new RawCompiler(instance, ClasspathOptionsUtil.auto, log) - val manager = new ZincComponentManager(lock, provider(targetDir), secondaryCacheOpt, log) - val componentCompiler = - new ZincComponentCompiler(raw, manager, ivyConfiguration, sourceModule, log) - - val bridge = componentCompiler.getCompiledBridgeJar + def getCompilerBridge(targetDir: File, log: Logger, scalaVersion: String): File = { + val provider = getZincProvider(targetDir, scalaVersion, log) + val scalaInstance = provider.getScalaInstance(scalaVersion, log) + val bridge = provider.getCompiledBridge(scalaInstance, log) val target = targetDir / s"target-bridge-$scalaVersion.jar" IO.copyFile(bridge, target) target @@ -108,13 +118,6 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { version) } - def compilerBridgeId(scalaVersion: String) = - scalaVersion match { - case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" - case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" - case _ => "compiler-bridge_2.12" - } - def scalaLoader(jars: Seq[File]) = new URLClassLoader(sbt.io.Path.toURLs(jars), ClasspathUtilities.rootLoader) def scalaVersion(scalaLoader: ClassLoader): Option[String] = @@ -146,7 +149,7 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { override def apply[T](file: File, callable: Callable[T]): T = callable.call() } - private def provider(targetDir: File): ComponentProvider = new ComponentProvider { + private def compProvider(targetDir: File): ComponentProvider = new ComponentProvider { override def lockFile(): File = targetDir / "lock" From f4c38c8355fabdba9f5e536581e9d0b7a1090341 Mon Sep 17 00:00:00 2001 From: jvican Date: Fri, 19 May 2017 20:19:25 +0200 Subject: [PATCH 56/90] Test `getScalaInstance` & `getCompiledBridge` * Remove unused code in `BridgeProviderSpecification` and test the real code in the default provider. * Don't use temporary directory to download the Scala jars, retrive them in a directory specified by the user. * Use `java.net.ClassLoader` instead of `ScalaClassLoader`. * Use the `ScalaInstance` interface, not the implementation. Remove any reference to the implementation. --- .../internal/inc/ZincComponentCompiler.scala | 118 ++++++++++------ .../inc/BridgeProviderSpecification.scala | 126 +++--------------- 2 files changed, 91 insertions(+), 153 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index bb266260f..dccea7f80 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -10,6 +10,7 @@ package internal package inc import java.io.File +import java.net.URLClassLoader import sbt.internal.inc.classpath.ClasspathUtilities import sbt.io.{ Hash, IO } @@ -20,8 +21,6 @@ import sbt.librarymanagement.syntax._ import sbt.util.{ InterfaceUtil, Logger } import xsbti.compile.CompilerBridgeProvider -import scala.reflect.internal.util.ScalaClassLoader.URLClassLoader - private[sbt] object ZincComponentCompiler { final val binSeparator = "-bin_" final val javaClassVersion = System.getProperty("java.class.version") @@ -31,23 +30,57 @@ private[sbt] object ZincComponentCompiler { private final val ZincVersionPropertyFile = "/incrementalcompiler.version.properties" private final val ZincVersionProperty = "version" - final lazy val incrementalVersion: String = { + private final lazy val incrementalVersion: String = { val cl = this.getClass.getClassLoader ResourceLoader.getPropertiesFor(ZincVersionPropertyFile, cl).getProperty(ZincVersionProperty) } - private class ZincCompilerBridgeProvider(manager: ZincComponentManager, - ivyConfiguration: IvyConfiguration, - bridgeModule: ModuleID) - extends CompilerBridgeProvider { + /** Defines the internal implementation of a bridge provider. */ + private class ZincCompilerBridgeProvider( + manager: ZincComponentManager, + ivyConfiguration: IvyConfiguration, + scalaJarsTarget: File + ) extends CompilerBridgeProvider { + + private val CompileConf = Some(Configurations.Compile.name) + private def getDefaultBridgeModule(scalaVersion: String): ModuleID = { + def compilerBridgeId(scalaVersion: String) = { + // Defaults to bridge for 2.12 for Scala versions bigger than 2.12.x + scalaVersion match { + case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" + case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" + case _ => "compiler-bridge_2.12" + } + } + + import xsbti.ArtifactInfo.SbtOrganization + val bridgeId = compilerBridgeId(scalaVersion) + ModuleID(SbtOrganization, bridgeId, incrementalVersion) + .withConfigurations(CompileConf) + .sources() + } + + /** + * Defines a richer interface for Scala users that want to pass in an explicit module id. + * + * Note that this method cannot be defined in [[CompilerBridgeProvider]] because [[ModuleID]] + * is a Scala-defined class to which the compiler bridge cannot depend on. + */ + def getCompiledBridge(bridgeSources: ModuleID, + scalaInstance: xsbti.compile.ScalaInstance, + logger: xsbti.Logger): File = { + val autoClasspath = ClasspathOptionsUtil.auto + val raw = new RawCompiler(scalaInstance, autoClasspath, logger) + val zinc = new ZincComponentCompiler(raw, manager, ivyConfiguration, bridgeSources, logger) + logger.debug(InterfaceUtil.f0(s"Getting $bridgeSources for Scala ${scalaInstance.version}")) + zinc.getCompiledBridgeJar + } override def getCompiledBridge(scalaInstance: xsbti.compile.ScalaInstance, logger: xsbti.Logger): File = { - val autoClasspath = ClasspathOptionsUtil.auto - val raw = new RawCompiler(scalaInstance, autoClasspath, logger) - val zinc = new ZincComponentCompiler(raw, manager, ivyConfiguration, bridgeModule, logger) - logger.debug(InterfaceUtil.f0(s"Getting $bridgeModule for Scala ${scalaInstance.version}")) - zinc.getCompiledBridgeJar + val scalaVersion = scalaInstance.actualVersion() + val bridgeSources = getDefaultBridgeModule(scalaVersion) + getCompiledBridge(bridgeSources, scalaInstance, logger) } private final case class ScalaArtifacts(compiler: File, library: File, others: Vector[File]) @@ -56,10 +89,9 @@ private[sbt] object ZincComponentCompiler { def isPrefixedWith(artifact: File, prefix: String) = artifact.getName.startsWith(prefix) import xsbti.ArtifactInfo._ - import Configurations.Compile import UnresolvedWarning.unresolvedWarningLines val fullLogger = new FullLogger(logger) - val CompileConf = Some(Compile.name) + val CompileConf = Some(Configurations.Compile.name) val dummyModule = ModuleID(JsonUtil.sbtOrgTemp, s"tmp-scala-$scalaVersion", scalaVersion) val scalaLibrary = ModuleID(ScalaOrganization, ScalaLibraryID, scalaVersion) val scalaCompiler = ModuleID(ScalaOrganization, ScalaCompilerID, scalaVersion) @@ -67,22 +99,20 @@ private[sbt] object ZincComponentCompiler { val wrapper = dummyModule.withConfigurations(CompileConf) val ivySbt: IvySbt = new IvySbt(ivyConfiguration) val ivyModule = ZincIvyActions.getModule(ivySbt, wrapper, dependencies) - IO.withTemporaryDirectory { retrieveDirectory => - ZincIvyActions.update(ivyModule, retrieveDirectory, fullLogger) match { - case Left(uw) => - val unresolvedLines = unresolvedWarningLines.showLines(uw) - val unretrievedMessage = s"The Scala compiler and library could not be retrieved." - throw new InvalidComponent(s"$unretrievedMessage\n$unresolvedLines") - case Right(allArtifacts) => - val isScalaCompiler = (f: File) => isPrefixedWith(f, "scala-compiler-") - val isScalaLibrary = (f: File) => isPrefixedWith(f, "scala-library-") - val maybeScalaCompiler = allArtifacts.find(isScalaCompiler) - val maybeScalaLibrary = allArtifacts.find(isScalaLibrary) - val others = allArtifacts.filterNot(a => isScalaCompiler(a) || isScalaLibrary(a)) - val scalaCompiler = maybeScalaCompiler.getOrElse(throw MissingScalaJar.compiler) - val scalaLibrary = maybeScalaLibrary.getOrElse(throw MissingScalaJar.library) - ScalaArtifacts(scalaCompiler, scalaLibrary, others) - } + ZincIvyActions.update(ivyModule, scalaJarsTarget, noSource = true, fullLogger) match { + case Left(uw) => + val unresolvedLines = unresolvedWarningLines.showLines(uw) + val unretrievedMessage = s"The Scala compiler and library could not be retrieved." + throw new InvalidComponent(s"$unretrievedMessage\n$unresolvedLines") + case Right(allArtifacts) => + val isScalaCompiler = (f: File) => isPrefixedWith(f, "scala-compiler-") + val isScalaLibrary = (f: File) => isPrefixedWith(f, "scala-library-") + val maybeScalaCompiler = allArtifacts.find(isScalaCompiler) + val maybeScalaLibrary = allArtifacts.find(isScalaLibrary) + val others = allArtifacts.filterNot(a => isScalaCompiler(a) || isScalaLibrary(a)) + val scalaCompiler = maybeScalaCompiler.getOrElse(throw MissingScalaJar.compiler) + val scalaLibrary = maybeScalaLibrary.getOrElse(throw MissingScalaJar.library) + ScalaArtifacts(scalaCompiler, scalaLibrary, others) } } @@ -93,6 +123,7 @@ private[sbt] object ZincComponentCompiler { val scalaCompiler = scalaArtifacts.compiler val scalaLibrary = scalaArtifacts.library val jarsToLoad = (scalaCompiler +: scalaLibrary +: scalaArtifacts.others).toArray + assert(jarsToLoad.forall(_.exists), "One or more jar(s) in the Scala instance do not exist.") val loader = new URLClassLoader(toURLs(jarsToLoad), ClasspathUtilities.rootLoader) val properties = ResourceLoader.getSafePropertiesFor("compiler.properties", loader) val loaderVersion = Option(properties.getProperty("version.number")) @@ -103,8 +134,8 @@ private[sbt] object ZincComponentCompiler { def interfaceProvider(manager: ZincComponentManager, ivyConfiguration: IvyConfiguration, - sourcesModule: ModuleID): CompilerBridgeProvider = - new ZincCompilerBridgeProvider(manager, ivyConfiguration, sourcesModule) + scalaJarsTarget: File): CompilerBridgeProvider = + new ZincCompilerBridgeProvider(manager, ivyConfiguration, scalaJarsTarget) } @@ -177,7 +208,7 @@ private[inc] class ZincComponentCompiler( val target = new File(binaryDirectory, s"$compilerBridgeId.jar") buffered bufferQuietly { IO.withTemporaryDirectory { retrieveDirectory => - ZincIvyActions.update(ivyModuleForBridge, retrieveDirectory, buffered) match { + ZincIvyActions.update(ivyModuleForBridge, retrieveDirectory, false, buffered) match { case Left(uw) => val mod = bridgeSources.toString val unresolvedLines = unresolvedWarningLines.showLines(uw) @@ -232,33 +263,34 @@ object ZincIvyActions { module.moduleSettings match { case ic: InlineConfiguration => // Pretty print the module as `ModuleIDExtra.toStringImpl` does. - val dependency = - ic.dependencies.map(m => s"${m.organization}:${m.name}:${m.revision}").headOption - dependency.getOrElse(sys.error("Fatal: more than one dependency in dummy bridge module.")) + ic.dependencies.map(m => s"${m.organization}:${m.name}:${m.revision}").mkString(", ") case _ => sys.error("Fatal: configuration to download was not inline.") } } private final val warningConf = UnresolvedWarningConfiguration() private final val defaultRetrievePattern = Resolver.defaultRetrievePattern - private def defaultUpdateConfiguration(retrieveDirectory: File): UpdateConfiguration = { - val retrieve = RetrieveConfiguration(retrieveDirectory, defaultRetrievePattern, false, None) + private def defaultUpdateConfiguration(targetDir: File, noSource: Boolean): UpdateConfiguration = { + val retrieve = RetrieveConfiguration(targetDir, defaultRetrievePattern, false, None) val logLevel = UpdateLogging.DownloadOnly - val noDocs = ArtifactTypeFilter.forbid(Set("doc")) - UpdateConfiguration(Some(retrieve), missingOk = false, logLevel, noDocs) + val defaultExcluded = Set("doc") + val finalExcluded = if (noSource) defaultExcluded + "src" else defaultExcluded + val artifactFilter = ArtifactTypeFilter.forbid(finalExcluded) + UpdateConfiguration(Some(retrieve), missingOk = false, logLevel, artifactFilter) } private[inc] def update(module: IvyModule, retrieveDirectory: File, + noSource: Boolean = false, logger: Logger): Either[UnresolvedWarning, Vector[File]] = { import IvyActions.updateEither - val updateConfiguration = defaultUpdateConfiguration(retrieveDirectory) + val updateConfiguration = defaultUpdateConfiguration(retrieveDirectory, noSource) val dependencies = prettyPrintDependency(module) - logger.info(s"Attempting to fetch $dependencies. This operation may fail.") + logger.info(s"Attempting to fetch $dependencies.") val clockForCache = LogicalClock.unknown updateEither(module, updateConfiguration, warningConf, clockForCache, None, logger) match { case Left(unresolvedWarning) => - logger.debug(s"Couldn't retrieve module ${prettyPrintDependency(module)}.") + logger.debug(s"Couldn't retrieve module(s) ${prettyPrintDependency(module)}.") Left(unresolvedWarning) case Right(updateReport) => diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 71c29a794..580b30b81 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -1,18 +1,13 @@ package sbt.internal.inc import java.io.File -import java.net.URLClassLoader -import java.util.Properties import java.util.concurrent.Callable -import sbt.internal.inc.classpath.ClasspathUtilities -import sbt.internal.librarymanagement.JsonUtil import sbt.io.IO import sbt.io.syntax._ import sbt.librarymanagement.{ DefaultMavenRepository, FileRepository, - ModuleID, Patterns, Resolver, UpdateOptions @@ -25,8 +20,6 @@ import xsbti.{ ComponentProvider, GlobalLock } * Base class for test suites that must be able to fetch and compile the compiler bridge. */ abstract class BridgeProviderSpecification extends BaseIvySpecification { - // log.setLevel(Level.Warn) - def realLocal: Resolver = { val pList = Vector(s"$${user.home}/.ivy2/local/${Resolver.localBasePattern}") FileRepository( @@ -34,6 +27,7 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { Resolver.defaultFileConfiguration, Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false)) } + override def resolvers: Vector[Resolver] = Vector(realLocal, DefaultMavenRepository) private val ivyConfiguration = mkIvyConfiguration(UpdateOptions()) @@ -41,29 +35,15 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { val target = file("target").getAbsoluteFile target / "zinc-components" } - def secondaryCacheOpt: Option[File] = Some(secondaryCacheDirectory) - def compilerBridgeId(scalaVersion: String) = { - scalaVersion match { - case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" - case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" - case _ => "compiler-bridge_2.12" - } - } - - def getZincProvider(targetDir: File, scalaVersion: String, log: Logger): CompilerBridgeProvider = { - import xsbti.ArtifactInfo.SbtOrganization - import ZincComponentCompiler.incrementalVersion - val bridgeId = compilerBridgeId(scalaVersion) - val sourceModule = ModuleID(SbtOrganization, bridgeId, incrementalVersion) - .withConfigurations(Some("component")) - .sources() - val manager = new ZincComponentManager(lock, compProvider(targetDir), secondaryCacheOpt, log) - ZincComponentCompiler.interfaceProvider(manager, ivyConfiguration, sourceModule) + def getZincProvider(targetDir: File, log: Logger): CompilerBridgeProvider = { + val secondaryCache = Some(secondaryCacheDirectory) + val manager = new ZincComponentManager(lock, compProvider(targetDir), secondaryCache, log) + ZincComponentCompiler.interfaceProvider(manager, ivyConfiguration, currentManaged) } def getCompilerBridge(targetDir: File, log: Logger, scalaVersion: String): File = { - val provider = getZincProvider(targetDir, scalaVersion, log) + val provider = getZincProvider(targetDir, log) val scalaInstance = provider.getScalaInstance(scalaVersion, log) val bridge = provider.getCompiledBridge(scalaInstance, log) val target = targetDir / s"target-bridge-$scalaVersion.jar" @@ -71,78 +51,11 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { target } - def scalaInstance(scalaVersion: String): ScalaInstance = { - val scalaModule = { - val dummyModule = ModuleID(JsonUtil.sbtOrgTemp, "tmp-scala-" + scalaVersion, scalaVersion) - .withConfigurations(Some("compile")) - val scalaLibrary = ModuleID(xsbti.ArtifactInfo.ScalaOrganization, - xsbti.ArtifactInfo.ScalaLibraryID, - scalaVersion).withConfigurations(Some("compile")) - val scalaCompiler = ModuleID(xsbti.ArtifactInfo.ScalaOrganization, - xsbti.ArtifactInfo.ScalaCompilerID, - scalaVersion).withConfigurations(Some("compile")) - - module(dummyModule, Vector(scalaLibrary, scalaCompiler), None) - } - - val allArtifacts = - for { - conf <- ivyUpdate(scalaModule).configurations - m <- conf.modules - (_, f) <- m.artifacts - } yield f - - def isCompiler(f: File) = f.getName startsWith "scala-compiler-" - def isLibrary(f: File) = f.getName startsWith "scala-library-" - - val scalaCompilerJar = allArtifacts find isCompiler getOrElse (throw new RuntimeException( - "Not found: scala-compiler")) - val scalaLibraryJar = allArtifacts find isLibrary getOrElse (throw new RuntimeException( - "Not found: scala-library")) - val others = allArtifacts filterNot (a => isCompiler(a) || isLibrary(a)) - - scalaInstance(scalaCompilerJar, scalaLibraryJar, others) - } - - def scalaInstance(scalaCompiler: File, - scalaLibrary: File, - scalaExtra: Seq[File]): ScalaInstance = { - val loader = scalaLoader(scalaLibrary +: scalaCompiler +: scalaExtra) - val version = scalaVersion(loader) - val allJars = (scalaLibrary +: scalaCompiler +: scalaExtra).toArray - new ScalaInstance(version.getOrElse("unknown"), - loader, - scalaLibrary, - scalaCompiler, - allJars, - version) - } - - def scalaLoader(jars: Seq[File]) = - new URLClassLoader(sbt.io.Path.toURLs(jars), ClasspathUtilities.rootLoader) - def scalaVersion(scalaLoader: ClassLoader): Option[String] = - propertyFromResource("compiler.properties", "version.number", scalaLoader) - - /** - * Get a property from a properties file resource in the classloader. - */ - def propertyFromResource(resource: String, - property: String, - classLoader: ClassLoader): Option[String] = { - val props = propertiesFromResource(resource, classLoader) - Option(props.getProperty(property)) - } - - /** - * Get all properties from a properties file resource in the classloader. - */ - def propertiesFromResource(resource: String, classLoader: ClassLoader): Properties = { - val props = new Properties - val stream = classLoader.getResourceAsStream(resource) - try { props.load(stream) } catch { case _: Exception => } finally { - if (stream ne null) stream.close() - } - props + def scalaInstance(scalaVersion: String, + targetDir: File, + logger: Logger): xsbti.compile.ScalaInstance = { + val provider = getZincProvider(targetDir, logger) + provider.getScalaInstance(scalaVersion, logger) } private val lock: GlobalLock = new GlobalLock { @@ -150,23 +63,16 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { } private def compProvider(targetDir: File): ComponentProvider = new ComponentProvider { - override def lockFile(): File = targetDir / "lock" - + override def componentLocation(id: String): File = + throw new UnsupportedOperationException + override def component(componentID: String): Array[File] = + IO.listFiles(targetDir / componentID) override def defineComponent(componentID: String, files: Array[File]): Unit = - files foreach { f => - IO.copyFile(f, targetDir / componentID / f.getName) - } - + files.foreach(f => IO.copyFile(f, targetDir / componentID / f.getName)) override def addToComponent(componentID: String, files: Array[File]): Boolean = { defineComponent(componentID, files) true } - - override def component(componentID: String): Array[File] = - IO.listFiles(targetDir / componentID) - - override def componentLocation(id: String): File = throw new UnsupportedOperationException } - } From 47415e7deff4a5a1719bfff9d7b43bc6ba50ffaa Mon Sep 17 00:00:00 2001 From: jvican Date: Fri, 19 May 2017 20:32:03 +0200 Subject: [PATCH 57/90] Compile bridge for 2.12.x and other Scala versions This commit makes sure that we always check that we compile against the latest two versions in Scala 2.10, Scala 2.11 and Scala 2.12. This commit also removes the null loggers and uses normal loggers to check what the output of the bridge provider is. This output is important and the rationale to do this is that it should be visible for us in order to detect cases where there's a regression or the output is modified in some way. Output is short anyway. --- .../inc/ZincComponentCompilerSpec.scala | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala index ad403ffdc..cbba8021b 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala @@ -1,23 +1,29 @@ package sbt.internal.inc +import sbt.internal.util.ConsoleLogger import sbt.io.IO -import sbt.util.Logger class ZincComponentCompilerSpec extends BridgeProviderSpecification { + val scala2105 = "2.10.5" + val scala2106 = "2.10.6" + val scala2118 = "2.11.8" + val scala21111 = "2.11.11" + val scala2121 = "2.12.1" + val scala2122 = "2.12.2" - val scala210 = "2.10.5" - val scala211 = "2.11.8" - - it should "compile the bridge for Scala 2.10" in { - IO.withTemporaryDirectory { tempDir => - getCompilerBridge(tempDir, Logger.Null, scala210) should exist - } + val logger = ConsoleLogger() + it should "compile the bridge for Scala 2.10.5 and 2.10.6" in { + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2105) should exist) + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2106) should exist) } - it should "compile the bridge for Scala 2.11" in { - IO.withTemporaryDirectory { tempDir => - getCompilerBridge(tempDir, Logger.Null, scala211) should exist - } + it should "compile the bridge for Scala 2.11.8 and 2.11.11" in { + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2118) should exist) + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala21111) should exist) } + it should "compile the bridge for Scala 2.12.2" in { + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2121) should exist) + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2122) should exist) + } } From d794ead617b479dd4853af911d8f49bd74575f7b Mon Sep 17 00:00:00 2001 From: jvican Date: Fri, 19 May 2017 20:54:24 +0200 Subject: [PATCH 58/90] Fix error when showing unresolved warning lines --- .../main/scala/sbt/internal/inc/ZincComponentCompiler.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index dccea7f80..00dd2519b 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -101,7 +101,7 @@ private[sbt] object ZincComponentCompiler { val ivyModule = ZincIvyActions.getModule(ivySbt, wrapper, dependencies) ZincIvyActions.update(ivyModule, scalaJarsTarget, noSource = true, fullLogger) match { case Left(uw) => - val unresolvedLines = unresolvedWarningLines.showLines(uw) + val unresolvedLines = unresolvedWarningLines.showLines(uw).mkString("\n") val unretrievedMessage = s"The Scala compiler and library could not be retrieved." throw new InvalidComponent(s"$unretrievedMessage\n$unresolvedLines") case Right(allArtifacts) => @@ -211,7 +211,7 @@ private[inc] class ZincComponentCompiler( ZincIvyActions.update(ivyModuleForBridge, retrieveDirectory, false, buffered) match { case Left(uw) => val mod = bridgeSources.toString - val unresolvedLines = unresolvedWarningLines.showLines(uw) + val unresolvedLines = unresolvedWarningLines.showLines(uw).mkString("\n") val unretrievedMessage = s"The compiler bridge sources $mod could not be retrieved." throw new InvalidComponent(s"$unretrievedMessage\n$unresolvedLines") From c228ce8817959d074e3d57c54224e195ac68d30e Mon Sep 17 00:00:00 2001 From: jvican Date: Sat, 20 May 2017 01:19:22 +0200 Subject: [PATCH 59/90] Add Java API for Zinc Ivy integration * Adds a method to fetch the default implementation of the compiler provider. * Adds a method to get a default `IvyConfiguration` from a small number of parameters. The public API is implemented in Java to ensure binary compatibility no matter what happens to the internal Scala implementations. It also makes it easier for Java users to use the API and avoid importing MODULE$'s and Scala generated class files.' --- .../main/java/sbt/inc/ZincBridgeProvider.java | 53 +++++++++++++++++++ .../internal/inc/ZincComponentCompiler.scala | 25 +++++++++ .../internal/inc/ZincComponentManager.scala | 6 ++- 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java diff --git a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java new file mode 100644 index 000000000..60a9920e8 --- /dev/null +++ b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java @@ -0,0 +1,53 @@ +package sbt.inc; + +import sbt.internal.inc.ZincComponentCompiler$; +import sbt.internal.inc.ZincComponentManager; +import sbt.internal.librarymanagement.IvyConfiguration; +import sbt.librarymanagement.Resolver; +import scala.None$; +import xsbti.ComponentProvider; +import xsbti.GlobalLock; +import xsbti.Logger; +import xsbti.compile.CompilerBridgeProvider; + +import java.io.File; + +public final class ZincBridgeProvider { + /** + * Get the default ivy configuration to retrieve compiler components. + *

+ * This method is useful to invoke {@link ZincBridgeProvider#getProvider(File, GlobalLock, ComponentProvider, IvyConfiguration, Logger)}. + *

+ * In order to know which arguments to pass, reading the + * ivy main concepts + * may be useful. + * + * @param baseDirectory The base directory for ivy. + * @param ivyHome The home for ivy. + * @param resolvers The resolvers to be used (usually local and Maven). + * @return A default ivy configuration ready for fetching Zinc compiler components. + */ + public static IvyConfiguration getDefaultConfiguration(File baseDirectory, File ivyHome, Resolver[] resolvers, Logger logger) { + return ZincComponentCompiler$.MODULE$.getDefaultConfiguration(baseDirectory, ivyHome, resolvers, logger); + } + + /** + * Get a compiler bridge provider that allows the user to fetch Scala and a compiled bridge. + * + * @param scalaJarsTarget The place where the downloaded Scala jars should be placed. + * @param lock The lock file used internally by Ivy to synchronize the dependency resolution. + * @param componentProvider A provider capable of retrieving existing components or installing + * new ones. The component provider manages compiled bridge sources. + * @param ivyConfiguration The ivy configuration used internally by the provider. + * @param logger The logger. + * @return A compiler bridge provider capable of fetching scala jars and the compiler bridge. + */ + public static CompilerBridgeProvider getProvider(File scalaJarsTarget, + GlobalLock lock, + ComponentProvider componentProvider, + IvyConfiguration ivyConfiguration, + Logger logger) { + ZincComponentManager manager = new ZincComponentManager(lock, componentProvider, None$.empty(), logger); + return ZincComponentCompiler$.MODULE$.interfaceProvider(manager, ivyConfiguration, scalaJarsTarget); + } +} diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 00dd2519b..20f91b5ba 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -137,6 +137,31 @@ private[sbt] object ZincComponentCompiler { scalaJarsTarget: File): CompilerBridgeProvider = new ZincCompilerBridgeProvider(manager, ivyConfiguration, scalaJarsTarget) + def getDefaultConfiguration(baseDirectory: File, + ivyHome: File, + resolvers0: Array[Resolver], + log: xsbti.Logger): IvyConfiguration = { + import sbt.io.syntax._ + val empty = Vector.empty + val checksums = empty + val otherResolvers = empty + val resolvers = resolvers0.toVector + val updateOptions = UpdateOptions() + val paths = IvyPaths(baseDirectory, Some(ivyHome)) + val resolutionCache = Some(ivyHome / "resolution-cache") + val chainResolver = ChainedResolver("zinc-chain", resolvers) + val moduleConfs = Vector(ModuleConfiguration("*", chainResolver)) + new InlineIvyConfiguration(paths, + resolvers, + otherResolvers, + moduleConfs, + false, + None, + checksums, + resolutionCache, + updateOptions, + log) + } } /** diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala index 5af4baa6e..0db0011a3 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentManager.scala @@ -11,7 +11,8 @@ package inc import java.io.File import java.util.concurrent.Callable -import sbt.util.Logger + +import sbt.internal.util.FullLogger import sbt.io.IO /** @@ -26,7 +27,8 @@ import sbt.io.IO class ZincComponentManager(globalLock: xsbti.GlobalLock, provider: xsbti.ComponentProvider, secondaryCacheDir: Option[File], - val log: Logger) { + log0: xsbti.Logger) { + val log = new FullLogger(log0) /** Get all of the files for component 'id', throwing an exception if no files exist for the component. */ def files(id: String)(ifMissing: IfMissing): Iterable[File] = { From 025c4cef9a5874dee9ed91b4f0ca4ba714011f5a Mon Sep 17 00:00:00 2001 From: jvican Date: Sat, 20 May 2017 01:41:21 +0200 Subject: [PATCH 60/90] Add public method to get a local ivy resolver --- .../main/java/sbt/inc/ZincBridgeProvider.java | 23 +++++++++++++++---- .../internal/inc/ZincComponentCompiler.scala | 8 +++++++ .../inc/BridgeProviderSpecification.scala | 11 ++------- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java index 60a9920e8..985861793 100644 --- a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java +++ b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java @@ -4,6 +4,7 @@ import sbt.internal.inc.ZincComponentCompiler$; import sbt.internal.inc.ZincComponentManager; import sbt.internal.librarymanagement.IvyConfiguration; import sbt.librarymanagement.Resolver; +import sbt.librarymanagement.ResolversSyntax; import scala.None$; import xsbti.ComponentProvider; import xsbti.GlobalLock; @@ -13,6 +14,18 @@ import xsbti.compile.CompilerBridgeProvider; import java.io.File; public final class ZincBridgeProvider { + /** + * Returns an ivy resolver to resolve dependencies locally in the default `.ivy2/local`. + *

+ * For those users interested in using Internet resolvers like Maven Central, you can + * instantiate them via {@link ResolversSyntax#DefaultMavenRepository()} et al. + * + * @return A local ivy resolver. + */ + public static Resolver getLocalResolver() { + return ZincComponentCompiler$.MODULE$.LocalResolver(); + } + /** * Get the default ivy configuration to retrieve compiler components. *

@@ -25,6 +38,8 @@ public final class ZincBridgeProvider { * @param baseDirectory The base directory for ivy. * @param ivyHome The home for ivy. * @param resolvers The resolvers to be used (usually local and Maven). + * See {@link ZincBridgeProvider#getProvider(File, GlobalLock, ComponentProvider, IvyConfiguration, Logger)} + * and {@link ResolversSyntax}. * @return A default ivy configuration ready for fetching Zinc compiler components. */ public static IvyConfiguration getDefaultConfiguration(File baseDirectory, File ivyHome, Resolver[] resolvers, Logger logger) { @@ -43,10 +58,10 @@ public final class ZincBridgeProvider { * @return A compiler bridge provider capable of fetching scala jars and the compiler bridge. */ public static CompilerBridgeProvider getProvider(File scalaJarsTarget, - GlobalLock lock, - ComponentProvider componentProvider, - IvyConfiguration ivyConfiguration, - Logger logger) { + GlobalLock lock, + ComponentProvider componentProvider, + IvyConfiguration ivyConfiguration, + Logger logger) { ZincComponentManager manager = new ZincComponentManager(lock, componentProvider, None$.empty(), logger); return ZincComponentCompiler$.MODULE$.interfaceProvider(manager, ivyConfiguration, scalaJarsTarget); } diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 20f91b5ba..1eb777de5 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -137,6 +137,14 @@ private[sbt] object ZincComponentCompiler { scalaJarsTarget: File): CompilerBridgeProvider = new ZincCompilerBridgeProvider(manager, ivyConfiguration, scalaJarsTarget) + private final val LocalIvy = s"$${user.home}/.ivy2/local/${Resolver.localBasePattern}" + final val LocalResolver: Resolver = { + val toUse = Vector(LocalIvy) + val ivyPatterns = Patterns().withIsMavenCompatible(false) + val finalPatterns = ivyPatterns.withIvyPatterns(toUse).withArtifactPatterns(toUse) + FileRepository("local", Resolver.defaultFileConfiguration, finalPatterns) + } + def getDefaultConfiguration(baseDirectory: File, ivyHome: File, resolvers0: Array[Resolver], diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 580b30b81..72bfc8859 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -20,15 +20,8 @@ import xsbti.{ ComponentProvider, GlobalLock } * Base class for test suites that must be able to fetch and compile the compiler bridge. */ abstract class BridgeProviderSpecification extends BaseIvySpecification { - def realLocal: Resolver = { - val pList = Vector(s"$${user.home}/.ivy2/local/${Resolver.localBasePattern}") - FileRepository( - "local", - Resolver.defaultFileConfiguration, - Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false)) - } - - override def resolvers: Vector[Resolver] = Vector(realLocal, DefaultMavenRepository) + override def resolvers: Vector[Resolver] = + Vector(ZincComponentCompiler.LocalResolver, DefaultMavenRepository) private val ivyConfiguration = mkIvyConfiguration(UpdateOptions()) def secondaryCacheDirectory: File = { From aa3527996fe1ef2cc44ef3205600b306125693a8 Mon Sep 17 00:00:00 2001 From: jvican Date: Sat, 20 May 2017 01:56:34 +0200 Subject: [PATCH 61/90] Add public method to get no-op global lock --- .../main/java/sbt/inc/ZincBridgeProvider.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java index 985861793..f68ff596c 100644 --- a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java +++ b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java @@ -12,6 +12,7 @@ import xsbti.Logger; import xsbti.compile.CompilerBridgeProvider; import java.io.File; +import java.util.concurrent.Callable; public final class ZincBridgeProvider { /** @@ -46,6 +47,44 @@ public final class ZincBridgeProvider { return ZincComponentCompiler$.MODULE$.getDefaultConfiguration(baseDirectory, ivyHome, resolvers, logger); } + /** + * Cast a CheckedException as an unchecked one. + * + * @param throwable to cast + * @param the type of the Throwable + * @return this method will never return a Throwable instance, it will just throw it. + * @throws T the throwable as an unchecked throwable + */ + @SuppressWarnings("unchecked") + private static RuntimeException rethrow(Throwable throwable) throws T { + throw (T) throwable; // rely on vacuous cast + } + + + /** + * Defines a global lock that does nothing but calling the callable to synchronize + * across threads. The lock file is used to resolve and download dependencies via ivy. + *

+ * This operation is necesary to invoke {@link ZincBridgeProvider#getProvider(File, GlobalLock, ComponentProvider, IvyConfiguration, Logger)}. + * + * @return A default global lock. + */ + public static GlobalLock getDefaultLock() { + return new GlobalLock() { + @Override + public T apply(File lockFile, Callable run) { + T value = null; + try { + value = run.call(); + } catch (Exception e) { + // Rethrow runtime exception because apply does not define throwing Exception + rethrow(e); + } + return value; + } + }; + } + /** * Get a compiler bridge provider that allows the user to fetch Scala and a compiled bridge. * From 6d012abaf99244cc24e1c21ccf569e47a191aa55 Mon Sep 17 00:00:00 2001 From: jvican Date: Sat, 20 May 2017 02:04:23 +0200 Subject: [PATCH 62/90] Remove verbose Java global lock implementation --- .../main/java/sbt/inc/ZincBridgeProvider.java | 28 +------------------ .../internal/inc/ZincComponentCompiler.scala | 6 ++++ 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java index f68ff596c..01d023296 100644 --- a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java +++ b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java @@ -47,20 +47,6 @@ public final class ZincBridgeProvider { return ZincComponentCompiler$.MODULE$.getDefaultConfiguration(baseDirectory, ivyHome, resolvers, logger); } - /** - * Cast a CheckedException as an unchecked one. - * - * @param throwable to cast - * @param the type of the Throwable - * @return this method will never return a Throwable instance, it will just throw it. - * @throws T the throwable as an unchecked throwable - */ - @SuppressWarnings("unchecked") - private static RuntimeException rethrow(Throwable throwable) throws T { - throw (T) throwable; // rely on vacuous cast - } - - /** * Defines a global lock that does nothing but calling the callable to synchronize * across threads. The lock file is used to resolve and download dependencies via ivy. @@ -70,19 +56,7 @@ public final class ZincBridgeProvider { * @return A default global lock. */ public static GlobalLock getDefaultLock() { - return new GlobalLock() { - @Override - public T apply(File lockFile, Callable run) { - T value = null; - try { - value = run.call(); - } catch (Exception e) { - // Rethrow runtime exception because apply does not define throwing Exception - rethrow(e); - } - return value; - } - }; + return ZincComponentCompiler$.MODULE$.getDefaultLock(); } /** diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 1eb777de5..61d75a672 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -11,6 +11,7 @@ package inc import java.io.File import java.net.URLClassLoader +import java.util.concurrent.Callable import sbt.internal.inc.classpath.ClasspathUtilities import sbt.io.{ Hash, IO } @@ -19,6 +20,7 @@ import sbt.internal.util.FullLogger import sbt.librarymanagement._ import sbt.librarymanagement.syntax._ import sbt.util.{ InterfaceUtil, Logger } +import xsbti.GlobalLock import xsbti.compile.CompilerBridgeProvider private[sbt] object ZincComponentCompiler { @@ -145,6 +147,10 @@ private[sbt] object ZincComponentCompiler { FileRepository("local", Resolver.defaultFileConfiguration, finalPatterns) } + def getDefaultLock: GlobalLock = new GlobalLock { + override def apply[T](file: File, callable: Callable[T]): T = callable.call() + } + def getDefaultConfiguration(baseDirectory: File, ivyHome: File, resolvers0: Array[Resolver], From 4d0f06a2eed35c84f16da9e50d4d7e32f19dae6b Mon Sep 17 00:00:00 2001 From: jvican Date: Sat, 20 May 2017 02:26:05 +0200 Subject: [PATCH 63/90] Add public method to get default component provider Expose default component provider through a static method in `ZincCompilerBridge`. This method is necessary to invoke the bridge. Removes the previous global lock and component provider implementations in `BridgeProviderSpecification`. --- .../main/java/sbt/inc/ZincBridgeProvider.java | 17 +++++++++++++- .../internal/inc/ZincComponentCompiler.scala | 23 ++++++++++++++++++- .../inc/BridgeProviderSpecification.scala | 22 +++--------------- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java index 01d023296..809028f76 100644 --- a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java +++ b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java @@ -48,7 +48,7 @@ public final class ZincBridgeProvider { } /** - * Defines a global lock that does nothing but calling the callable to synchronize + * Returns a global lock that does nothing but calling the callable to synchronize * across threads. The lock file is used to resolve and download dependencies via ivy. *

* This operation is necesary to invoke {@link ZincBridgeProvider#getProvider(File, GlobalLock, ComponentProvider, IvyConfiguration, Logger)}. @@ -59,6 +59,21 @@ public final class ZincBridgeProvider { return ZincComponentCompiler$.MODULE$.getDefaultLock(); } + /** + * Returns a default component provider that retrieves and installs component managers + * (like the compiled bridge sources) under a given target directory. + *

+ * This is the most simplistic implementation of a component provider. If you need more + * advanced feature, like management of component via proxies (for companies) or access to + * other servers, you need to implement your own component provider. + * + * @param componentsRoot The directory in which components will be installed and retrieved. + * @return A default component provider. + */ + public static ComponentProvider getDefaultComponentProvider(File componentsRoot) { + return ZincComponentCompiler$.MODULE$.getDefaultComponentProvider(componentsRoot); + } + /** * Get a compiler bridge provider that allows the user to fetch Scala and a compiled bridge. * diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 61d75a672..95214b0f2 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -20,7 +20,7 @@ import sbt.internal.util.FullLogger import sbt.librarymanagement._ import sbt.librarymanagement.syntax._ import sbt.util.{ InterfaceUtil, Logger } -import xsbti.GlobalLock +import xsbti.{ ComponentProvider, GlobalLock } import xsbti.compile.CompilerBridgeProvider private[sbt] object ZincComponentCompiler { @@ -151,6 +151,27 @@ private[sbt] object ZincComponentCompiler { override def apply[T](file: File, callable: Callable[T]): T = callable.call() } + /** Defines a default component provider that manages the component in a given directory. */ + private final class DefaultComponentProvider(targetDir: File) extends ComponentProvider { + import sbt.io.syntax._ + private val LockFile = targetDir / "lock" + override def lockFile(): File = LockFile + override def componentLocation(id: String): File = targetDir / id + override def component(componentID: String): Array[File] = + IO.listFiles(targetDir / componentID) + override def defineComponent(componentID: String, files: Array[File]): Unit = + files.foreach(f => IO.copyFile(f, targetDir / componentID / f.getName)) + override def addToComponent(componentID: String, files: Array[File]): Boolean = { + defineComponent(componentID, files) + true + } + } + + def getDefaultComponentProvider(targetDir: File): ComponentProvider = { + require(targetDir.isDirectory) + new DefaultComponentProvider(targetDir) + } + def getDefaultConfiguration(baseDirectory: File, ivyHome: File, resolvers0: Array[Resolver], diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 72bfc8859..e655a1ef3 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -30,8 +30,10 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { } def getZincProvider(targetDir: File, log: Logger): CompilerBridgeProvider = { + val lock = ZincComponentCompiler.getDefaultLock val secondaryCache = Some(secondaryCacheDirectory) - val manager = new ZincComponentManager(lock, compProvider(targetDir), secondaryCache, log) + val componentProvider = ZincComponentCompiler.getDefaultComponentProvider(targetDir) + val manager = new ZincComponentManager(lock, componentProvider, secondaryCache, log) ZincComponentCompiler.interfaceProvider(manager, ivyConfiguration, currentManaged) } @@ -50,22 +52,4 @@ abstract class BridgeProviderSpecification extends BaseIvySpecification { val provider = getZincProvider(targetDir, logger) provider.getScalaInstance(scalaVersion, logger) } - - private val lock: GlobalLock = new GlobalLock { - override def apply[T](file: File, callable: Callable[T]): T = callable.call() - } - - private def compProvider(targetDir: File): ComponentProvider = new ComponentProvider { - override def lockFile(): File = targetDir / "lock" - override def componentLocation(id: String): File = - throw new UnsupportedOperationException - override def component(componentID: String): Array[File] = - IO.listFiles(targetDir / componentID) - override def defineComponent(componentID: String, files: Array[File]): Unit = - files.foreach(f => IO.copyFile(f, targetDir / componentID / f.getName)) - override def addToComponent(componentID: String, files: Array[File]): Boolean = { - defineComponent(componentID, files) - true - } - } } From 96f7e0886490d2794200d2f10fbe18ee424f3d9b Mon Sep 17 00:00:00 2001 From: jvican Date: Sat, 20 May 2017 02:37:16 +0200 Subject: [PATCH 64/90] Remove the use of `BaseIvySpecification` This is the proof that we're now testing the Zinc public API because we're resolving with the ivy options and resolution specified in the default compiler bridge provider. --- .../internal/inc/BridgeProviderSpecification.scala | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index e655a1ef3..2d6e1748e 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -18,11 +18,17 @@ import xsbti.{ ComponentProvider, GlobalLock } /** * Base class for test suites that must be able to fetch and compile the compiler bridge. + * + * This is a very good example on how to instantiate the compiler bridge provider. */ -abstract class BridgeProviderSpecification extends BaseIvySpecification { - override def resolvers: Vector[Resolver] = - Vector(ZincComponentCompiler.LocalResolver, DefaultMavenRepository) - private val ivyConfiguration = mkIvyConfiguration(UpdateOptions()) +abstract class BridgeProviderSpecification extends UnitSpec { + def currentBase: File = new File(".") + def currentTarget: File = currentBase / "target" / "ivyhome" + def currentManaged: File = currentBase / "target" / "lib_managed" + + val resolvers = Array(ZincComponentCompiler.LocalResolver, DefaultMavenRepository) + private val ivyConfiguration = + ZincComponentCompiler.getDefaultConfiguration(currentBase, currentTarget, resolvers, log) def secondaryCacheDirectory: File = { val target = file("target").getAbsoluteFile From c8560c6b4e6cae4579f348dd465bc2c96f34849b Mon Sep 17 00:00:00 2001 From: jvican Date: Mon, 22 May 2017 15:42:59 +0200 Subject: [PATCH 65/90] Add `ZincCompilerUtil` to get the Scalac compiler * Move `IncrementalCompilerUtil` to `ZincCompilerUtil`. * Change `IncrementalCompilerUtil` to an interface with static methods. * Remove bug in which ScalaInstance implementation was leaking to the public API. --- .../src/main/java/sbt/inc/ZincBridgeProvider.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java index 809028f76..97ec691aa 100644 --- a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java +++ b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java @@ -1,5 +1,6 @@ package sbt.inc; +import sbt.internal.inc.ZincComponentCompiler; import sbt.internal.inc.ZincComponentCompiler$; import sbt.internal.inc.ZincComponentManager; import sbt.internal.librarymanagement.IvyConfiguration; @@ -24,7 +25,7 @@ public final class ZincBridgeProvider { * @return A local ivy resolver. */ public static Resolver getLocalResolver() { - return ZincComponentCompiler$.MODULE$.LocalResolver(); + return ZincComponentCompiler.LocalResolver(); } /** @@ -44,7 +45,7 @@ public final class ZincBridgeProvider { * @return A default ivy configuration ready for fetching Zinc compiler components. */ public static IvyConfiguration getDefaultConfiguration(File baseDirectory, File ivyHome, Resolver[] resolvers, Logger logger) { - return ZincComponentCompiler$.MODULE$.getDefaultConfiguration(baseDirectory, ivyHome, resolvers, logger); + return ZincComponentCompiler.getDefaultConfiguration(baseDirectory, ivyHome, resolvers, logger); } /** @@ -56,7 +57,7 @@ public final class ZincBridgeProvider { * @return A default global lock. */ public static GlobalLock getDefaultLock() { - return ZincComponentCompiler$.MODULE$.getDefaultLock(); + return ZincComponentCompiler.getDefaultLock(); } /** @@ -71,7 +72,7 @@ public final class ZincBridgeProvider { * @return A default component provider. */ public static ComponentProvider getDefaultComponentProvider(File componentsRoot) { - return ZincComponentCompiler$.MODULE$.getDefaultComponentProvider(componentsRoot); + return ZincComponentCompiler.getDefaultComponentProvider(componentsRoot); } /** @@ -91,6 +92,6 @@ public final class ZincBridgeProvider { IvyConfiguration ivyConfiguration, Logger logger) { ZincComponentManager manager = new ZincComponentManager(lock, componentProvider, None$.empty(), logger); - return ZincComponentCompiler$.MODULE$.interfaceProvider(manager, ivyConfiguration, scalaJarsTarget); + return ZincComponentCompiler.interfaceProvider(manager, ivyConfiguration, scalaJarsTarget); } } From e071577d6a5b01d9ee445cee87f89032f47c5ce1 Mon Sep 17 00:00:00 2001 From: jvican Date: Mon, 22 May 2017 15:54:20 +0200 Subject: [PATCH 66/90] Hide Zinc Compilation implementation Before, we had made this public in `sbt.inc`, but this is not necessary anymore. --- .../src/main/java/sbt/inc/ZincBridgeProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java index 97ec691aa..5f715c45a 100644 --- a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java +++ b/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java @@ -15,7 +15,7 @@ import xsbti.compile.CompilerBridgeProvider; import java.io.File; import java.util.concurrent.Callable; -public final class ZincBridgeProvider { +public interface ZincBridgeProvider { /** * Returns an ivy resolver to resolve dependencies locally in the default `.ivy2/local`. *

From 19ddb6f2a2e8204a71b448b3c41f4c190259bef4 Mon Sep 17 00:00:00 2001 From: jvican Date: Mon, 22 May 2017 16:07:53 +0200 Subject: [PATCH 67/90] Move ZincBridgeProvider to `xsbti.compile` Before, we were using `sbt.inc`. As we have settled to define all the interfaces in the `xsbti.compile` namespaces, it's not worth it to force users remember other locations for the interfaces forwarding the default implementations in Scala. --- .../java/{sbt/inc => xsbti/compile}/ZincBridgeProvider.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) rename internal/zinc-ivy-integration/src/main/java/{sbt/inc => xsbti/compile}/ZincBridgeProvider.java (96%) diff --git a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java b/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java similarity index 96% rename from internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java rename to internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java index 5f715c45a..a64730262 100644 --- a/internal/zinc-ivy-integration/src/main/java/sbt/inc/ZincBridgeProvider.java +++ b/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java @@ -1,7 +1,6 @@ -package sbt.inc; +package xsbti.compile; import sbt.internal.inc.ZincComponentCompiler; -import sbt.internal.inc.ZincComponentCompiler$; import sbt.internal.inc.ZincComponentManager; import sbt.internal.librarymanagement.IvyConfiguration; import sbt.librarymanagement.Resolver; @@ -10,10 +9,8 @@ import scala.None$; import xsbti.ComponentProvider; import xsbti.GlobalLock; import xsbti.Logger; -import xsbti.compile.CompilerBridgeProvider; import java.io.File; -import java.util.concurrent.Callable; public interface ZincBridgeProvider { /** From 66c34d180ea832a6bd058101d7c872a55136e856 Mon Sep 17 00:00:00 2001 From: jvican Date: Mon, 22 May 2017 17:00:29 +0200 Subject: [PATCH 68/90] Move `ClasspathOptionsUtil` to the Java public API Move the previous Scala implementation to Java as static methods. --- .../src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 95214b0f2..aac0945f4 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -21,7 +21,7 @@ import sbt.librarymanagement._ import sbt.librarymanagement.syntax._ import sbt.util.{ InterfaceUtil, Logger } import xsbti.{ ComponentProvider, GlobalLock } -import xsbti.compile.CompilerBridgeProvider +import xsbti.compile.{ ClasspathOptionsUtil, CompilerBridgeProvider } private[sbt] object ZincComponentCompiler { final val binSeparator = "-bin_" From 551c5d9aa4f1983613d3ea6ded3ab9cfd678b3ff Mon Sep 17 00:00:00 2001 From: jvican Date: Mon, 22 May 2017 17:02:32 +0200 Subject: [PATCH 69/90] Add headers to files missing it --- .../src/main/java/xsbti/compile/ZincBridgeProvider.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java b/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java index a64730262..1560a0e44 100644 --- a/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java +++ b/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package xsbti.compile; import sbt.internal.inc.ZincComponentCompiler; From 11fa775ef85458fd39f93d16bdd53a25496502d2 Mon Sep 17 00:00:00 2001 From: jvican Date: Fri, 26 May 2017 15:32:29 +0200 Subject: [PATCH 70/90] Rename `getXXX` by `fetchXXX` As suggested by Eugene. --- .../scala/sbt/internal/inc/ZincComponentCompiler.scala | 8 ++++---- .../sbt/internal/inc/BridgeProviderSpecification.scala | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index aac0945f4..ae43d3eb5 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -78,8 +78,8 @@ private[sbt] object ZincComponentCompiler { zinc.getCompiledBridgeJar } - override def getCompiledBridge(scalaInstance: xsbti.compile.ScalaInstance, - logger: xsbti.Logger): File = { + override def fetchCompiledBridge(scalaInstance: xsbti.compile.ScalaInstance, + logger: xsbti.Logger): File = { val scalaVersion = scalaInstance.actualVersion() val bridgeSources = getDefaultBridgeModule(scalaVersion) getCompiledBridge(bridgeSources, scalaInstance, logger) @@ -118,8 +118,8 @@ private[sbt] object ZincComponentCompiler { } } - override def getScalaInstance(scalaVersion: String, - logger: xsbti.Logger): xsbti.compile.ScalaInstance = { + override def fetchScalaInstance(scalaVersion: String, + logger: xsbti.Logger): xsbti.compile.ScalaInstance = { import sbt.io.Path.toURLs val scalaArtifacts = getScalaArtifacts(scalaVersion, logger) val scalaCompiler = scalaArtifacts.compiler diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 2d6e1748e..6eebed1cf 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -45,8 +45,8 @@ abstract class BridgeProviderSpecification extends UnitSpec { def getCompilerBridge(targetDir: File, log: Logger, scalaVersion: String): File = { val provider = getZincProvider(targetDir, log) - val scalaInstance = provider.getScalaInstance(scalaVersion, log) - val bridge = provider.getCompiledBridge(scalaInstance, log) + val scalaInstance = provider.fetchScalaInstance(scalaVersion, log) + val bridge = provider.fetchCompiledBridge(scalaInstance, log) val target = targetDir / s"target-bridge-$scalaVersion.jar" IO.copyFile(bridge, target) target @@ -56,6 +56,6 @@ abstract class BridgeProviderSpecification extends UnitSpec { targetDir: File, logger: Logger): xsbti.compile.ScalaInstance = { val provider = getZincProvider(targetDir, logger) - provider.getScalaInstance(scalaVersion, logger) + provider.fetchScalaInstance(scalaVersion, logger) } } From 9e28e0bfd65876fcf0878fad5e67107c233c853a Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 27 May 2017 17:42:16 -0400 Subject: [PATCH 71/90] Bump all the modules --- .../internal/inc/ZincComponentCompiler.scala | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index ae43d3eb5..0bff2a21a 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -177,25 +177,20 @@ private[sbt] object ZincComponentCompiler { resolvers0: Array[Resolver], log: xsbti.Logger): IvyConfiguration = { import sbt.io.syntax._ - val empty = Vector.empty - val checksums = empty - val otherResolvers = empty val resolvers = resolvers0.toVector - val updateOptions = UpdateOptions() - val paths = IvyPaths(baseDirectory, Some(ivyHome)) - val resolutionCache = Some(ivyHome / "resolution-cache") val chainResolver = ChainedResolver("zinc-chain", resolvers) - val moduleConfs = Vector(ModuleConfiguration("*", chainResolver)) - new InlineIvyConfiguration(paths, - resolvers, - otherResolvers, - moduleConfs, - false, - None, - checksums, - resolutionCache, - updateOptions, - log) + new InlineIvyConfiguration( + paths = IvyPaths(baseDirectory, Some(ivyHome)), + resolvers = resolvers, + otherResolvers = Vector.empty, + moduleConfigurations = Vector(ModuleConfiguration("*", chainResolver)), + lock = None, + checksums = Vector.empty, + managedChecksums = false, + resolutionCacheDir = Some(ivyHome / "resolution-cache"), + updateOptions = UpdateOptions(), + log = log + ) } } @@ -336,7 +331,12 @@ object ZincIvyActions { val defaultExcluded = Set("doc") val finalExcluded = if (noSource) defaultExcluded + "src" else defaultExcluded val artifactFilter = ArtifactTypeFilter.forbid(finalExcluded) - UpdateConfiguration(Some(retrieve), missingOk = false, logLevel, artifactFilter) + UpdateConfiguration(retrieve = Some(retrieve), + missingOk = false, + logging = logLevel, + artifactFilter = artifactFilter, + offline = false, + frozen = false) } private[inc] def update(module: IvyModule, From c95396b02096ba270a8cfdf199af2da3d6d68461 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 29 May 2017 05:05:10 -0400 Subject: [PATCH 72/90] Add scalaCompiler variant that accepts ModuleID --- .../internal/inc/ZincComponentCompiler.scala | 65 +++++++++++-------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 0bff2a21a..ebf9c84e6 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -32,57 +32,57 @@ private[sbt] object ZincComponentCompiler { private final val ZincVersionPropertyFile = "/incrementalcompiler.version.properties" private final val ZincVersionProperty = "version" - private final lazy val incrementalVersion: String = { + private[sbt] final lazy val incrementalVersion: String = { val cl = this.getClass.getClassLoader ResourceLoader.getPropertiesFor(ZincVersionPropertyFile, cl).getProperty(ZincVersionProperty) } + private val CompileConf = Some(Configurations.Compile.name) + private[sbt] def getDefaultBridgeModule(scalaVersion: String): ModuleID = { + def compilerBridgeId(scalaVersion: String) = { + // Defaults to bridge for 2.12 for Scala versions bigger than 2.12.x + scalaVersion match { + case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" + case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" + case _ => "compiler-bridge_2.12" + } + } + import xsbti.ArtifactInfo.SbtOrganization + val bridgeId = compilerBridgeId(scalaVersion) + ModuleID(SbtOrganization, bridgeId, incrementalVersion) + .withConfigurations(CompileConf) + .sources() + } + /** Defines the internal implementation of a bridge provider. */ private class ZincCompilerBridgeProvider( + userProvidedBridgeSources: Option[ModuleID], manager: ZincComponentManager, ivyConfiguration: IvyConfiguration, scalaJarsTarget: File ) extends CompilerBridgeProvider { - private val CompileConf = Some(Configurations.Compile.name) - private def getDefaultBridgeModule(scalaVersion: String): ModuleID = { - def compilerBridgeId(scalaVersion: String) = { - // Defaults to bridge for 2.12 for Scala versions bigger than 2.12.x - scalaVersion match { - case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" - case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" - case _ => "compiler-bridge_2.12" - } - } - - import xsbti.ArtifactInfo.SbtOrganization - val bridgeId = compilerBridgeId(scalaVersion) - ModuleID(SbtOrganization, bridgeId, incrementalVersion) - .withConfigurations(CompileConf) - .sources() - } - /** * Defines a richer interface for Scala users that want to pass in an explicit module id. * * Note that this method cannot be defined in [[CompilerBridgeProvider]] because [[ModuleID]] * is a Scala-defined class to which the compiler bridge cannot depend on. */ - def getCompiledBridge(bridgeSources: ModuleID, - scalaInstance: xsbti.compile.ScalaInstance, - logger: xsbti.Logger): File = { + def compiledBridge(bridgeSources: ModuleID, + scalaInstance: xsbti.compile.ScalaInstance, + logger: xsbti.Logger): File = { val autoClasspath = ClasspathOptionsUtil.auto val raw = new RawCompiler(scalaInstance, autoClasspath, logger) val zinc = new ZincComponentCompiler(raw, manager, ivyConfiguration, bridgeSources, logger) logger.debug(InterfaceUtil.f0(s"Getting $bridgeSources for Scala ${scalaInstance.version}")) - zinc.getCompiledBridgeJar + zinc.compiledBridgeJar } override def fetchCompiledBridge(scalaInstance: xsbti.compile.ScalaInstance, logger: xsbti.Logger): File = { val scalaVersion = scalaInstance.actualVersion() - val bridgeSources = getDefaultBridgeModule(scalaVersion) - getCompiledBridge(bridgeSources, scalaInstance, logger) + val bridgeSources = userProvidedBridgeSources getOrElse getDefaultBridgeModule(scalaVersion) + compiledBridge(bridgeSources, scalaInstance, logger) } private final case class ScalaArtifacts(compiler: File, library: File, others: Vector[File]) @@ -134,10 +134,20 @@ private[sbt] object ZincComponentCompiler { } } + // Used by ZincUtil. + def interfaceProvider(compilerBridgeSource: ModuleID, + manager: ZincComponentManager, + ivyConfiguration: IvyConfiguration, + scalaJarsTarget: File): CompilerBridgeProvider = + new ZincCompilerBridgeProvider(Some(compilerBridgeSource), + manager, + ivyConfiguration, + scalaJarsTarget) + def interfaceProvider(manager: ZincComponentManager, ivyConfiguration: IvyConfiguration, scalaJarsTarget: File): CompilerBridgeProvider = - new ZincCompilerBridgeProvider(manager, ivyConfiguration, scalaJarsTarget) + new ZincCompilerBridgeProvider(None, manager, ivyConfiguration, scalaJarsTarget) private final val LocalIvy = s"$${user.home}/.ivy2/local/${Resolver.localBasePattern}" final val LocalResolver: Resolver = { @@ -211,7 +221,7 @@ private[inc] class ZincComponentCompiler( private final val ivySbt: IvySbt = new IvySbt(ivyConfiguration) private final val buffered = new BufferedLogger(FullLogger(log)) - def getCompiledBridgeJar: File = { + def compiledBridgeJar: File = { val jarBinaryName = createBridgeSourcesID(bridgeSources) manager.file(jarBinaryName)(IfMissing.define(true, compileAndInstall(jarBinaryName))) } @@ -290,7 +300,6 @@ object ZincIvyActions { /** Define the default configurations for a Zinc module wrapper. */ private final val DefaultConfigurations: Vector[Configuration] = Vector(Configurations.Component, Configurations.Compile) - private final val DefaultUpdateOptions = UpdateOptions() /** * Create a module from its dummy wrapper and its dependencies. From 34d0dae6e20a6f0c409c97aaa9dfdc17aab7cf87 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 3 Jul 2017 14:53:56 -0400 Subject: [PATCH 73/90] Fix ScalaFmt wiring --- .../src/main/scala/sbt/internal/inc/IfMissing.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/IfMissing.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/IfMissing.scala index 1f176270a..1936799a0 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/IfMissing.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/IfMissing.scala @@ -18,4 +18,4 @@ object IfMissing { final class Define(val useSecondaryCache: Boolean, define: => Unit) extends IfMissing { def run(): Unit = define } -} \ No newline at end of file +} From 763effd337c4952ceef21e4084f157b6b3319593 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Thu, 6 Jul 2017 15:35:34 +0200 Subject: [PATCH 74/90] Adapt Zinc to use the new LibraryManagement API --- .../xsbti/compile/ZincBridgeProvider.java | 28 +-- .../internal/inc/ZincComponentCompiler.scala | 160 +++++++----------- .../inc/BridgeProviderSpecification.scala | 34 +++- 3 files changed, 92 insertions(+), 130 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java b/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java index 1560a0e44..ca3f43d2a 100644 --- a/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java +++ b/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java @@ -9,7 +9,7 @@ package xsbti.compile; import sbt.internal.inc.ZincComponentCompiler; import sbt.internal.inc.ZincComponentManager; -import sbt.internal.librarymanagement.IvyConfiguration; +import sbt.librarymanagement.LibraryManagement; import sbt.librarymanagement.Resolver; import sbt.librarymanagement.ResolversSyntax; import scala.None$; @@ -32,26 +32,6 @@ public interface ZincBridgeProvider { return ZincComponentCompiler.LocalResolver(); } - /** - * Get the default ivy configuration to retrieve compiler components. - *

- * This method is useful to invoke {@link ZincBridgeProvider#getProvider(File, GlobalLock, ComponentProvider, IvyConfiguration, Logger)}. - *

- * In order to know which arguments to pass, reading the - * ivy main concepts - * may be useful. - * - * @param baseDirectory The base directory for ivy. - * @param ivyHome The home for ivy. - * @param resolvers The resolvers to be used (usually local and Maven). - * See {@link ZincBridgeProvider#getProvider(File, GlobalLock, ComponentProvider, IvyConfiguration, Logger)} - * and {@link ResolversSyntax}. - * @return A default ivy configuration ready for fetching Zinc compiler components. - */ - public static IvyConfiguration getDefaultConfiguration(File baseDirectory, File ivyHome, Resolver[] resolvers, Logger logger) { - return ZincComponentCompiler.getDefaultConfiguration(baseDirectory, ivyHome, resolvers, logger); - } - /** * Returns a global lock that does nothing but calling the callable to synchronize * across threads. The lock file is used to resolve and download dependencies via ivy. @@ -86,16 +66,16 @@ public interface ZincBridgeProvider { * @param lock The lock file used internally by Ivy to synchronize the dependency resolution. * @param componentProvider A provider capable of retrieving existing components or installing * new ones. The component provider manages compiled bridge sources. - * @param ivyConfiguration The ivy configuration used internally by the provider. + * @param libraryManagement The library management module to use to retrieve the bridge. * @param logger The logger. * @return A compiler bridge provider capable of fetching scala jars and the compiler bridge. */ public static CompilerBridgeProvider getProvider(File scalaJarsTarget, GlobalLock lock, ComponentProvider componentProvider, - IvyConfiguration ivyConfiguration, + LibraryManagement libraryManagement, Logger logger) { ZincComponentManager manager = new ZincComponentManager(lock, componentProvider, None$.empty(), logger); - return ZincComponentCompiler.interfaceProvider(manager, ivyConfiguration, scalaJarsTarget); + return ZincComponentCompiler.interfaceProvider(manager, libraryManagement, scalaJarsTarget); } } diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index ebf9c84e6..2fe33d748 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -58,7 +58,7 @@ private[sbt] object ZincComponentCompiler { private class ZincCompilerBridgeProvider( userProvidedBridgeSources: Option[ModuleID], manager: ZincComponentManager, - ivyConfiguration: IvyConfiguration, + libraryManagement: LibraryManagement, scalaJarsTarget: File ) extends CompilerBridgeProvider { @@ -73,7 +73,7 @@ private[sbt] object ZincComponentCompiler { logger: xsbti.Logger): File = { val autoClasspath = ClasspathOptionsUtil.auto val raw = new RawCompiler(scalaInstance, autoClasspath, logger) - val zinc = new ZincComponentCompiler(raw, manager, ivyConfiguration, bridgeSources, logger) + val zinc = new ZincComponentCompiler(raw, manager, libraryManagement, bridgeSources, logger) logger.debug(InterfaceUtil.f0(s"Getting $bridgeSources for Scala ${scalaInstance.version}")) zinc.compiledBridgeJar } @@ -99,9 +99,16 @@ private[sbt] object ZincComponentCompiler { val scalaCompiler = ModuleID(ScalaOrganization, ScalaCompilerID, scalaVersion) val dependencies = Vector(scalaLibrary, scalaCompiler).map(_.withConfigurations(CompileConf)) val wrapper = dummyModule.withConfigurations(CompileConf) - val ivySbt: IvySbt = new IvySbt(ivyConfiguration) - val ivyModule = ZincIvyActions.getModule(ivySbt, wrapper, dependencies) - ZincIvyActions.update(ivyModule, scalaJarsTarget, noSource = true, fullLogger) match { + val moduleDescriptor = + libraryManagement.moduleDescriptor(wrapper, + dependencies, + None, + ZincLMHelper.DefaultConfigurations) + ZincLMHelper.update(libraryManagement, + moduleDescriptor, + scalaJarsTarget, + noSource = true, + fullLogger) match { case Left(uw) => val unresolvedLines = unresolvedWarningLines.showLines(uw).mkString("\n") val unretrievedMessage = s"The Scala compiler and library could not be retrieved." @@ -137,17 +144,17 @@ private[sbt] object ZincComponentCompiler { // Used by ZincUtil. def interfaceProvider(compilerBridgeSource: ModuleID, manager: ZincComponentManager, - ivyConfiguration: IvyConfiguration, + libraryManagement: LibraryManagement, scalaJarsTarget: File): CompilerBridgeProvider = new ZincCompilerBridgeProvider(Some(compilerBridgeSource), manager, - ivyConfiguration, + libraryManagement, scalaJarsTarget) def interfaceProvider(manager: ZincComponentManager, - ivyConfiguration: IvyConfiguration, + libraryManagement: LibraryManagement, scalaJarsTarget: File): CompilerBridgeProvider = - new ZincCompilerBridgeProvider(None, manager, ivyConfiguration, scalaJarsTarget) + new ZincCompilerBridgeProvider(None, manager, libraryManagement, scalaJarsTarget) private final val LocalIvy = s"$${user.home}/.ivy2/local/${Resolver.localBasePattern}" final val LocalResolver: Resolver = { @@ -182,43 +189,22 @@ private[sbt] object ZincComponentCompiler { new DefaultComponentProvider(targetDir) } - def getDefaultConfiguration(baseDirectory: File, - ivyHome: File, - resolvers0: Array[Resolver], - log: xsbti.Logger): IvyConfiguration = { - import sbt.io.syntax._ - val resolvers = resolvers0.toVector - val chainResolver = ChainedResolver("zinc-chain", resolvers) - new InlineIvyConfiguration( - paths = IvyPaths(baseDirectory, Some(ivyHome)), - resolvers = resolvers, - otherResolvers = Vector.empty, - moduleConfigurations = Vector(ModuleConfiguration("*", chainResolver)), - lock = None, - checksums = Vector.empty, - managedChecksums = false, - resolutionCacheDir = Some(ivyHome / "resolution-cache"), - updateOptions = UpdateOptions(), - log = log - ) - } } /** * Component compiler which is able to to retrieve the compiler bridge sources - * `sourceModule` using Ivy. + * `sourceModule` using a `LibraryManagement` instance. * The compiled classes are cached using the provided component manager according * to the actualVersion field of the RawCompiler. */ private[inc] class ZincComponentCompiler( compiler: RawCompiler, manager: ZincComponentManager, - ivyConfiguration: IvyConfiguration, + libraryManagement: LibraryManagement, bridgeSources: ModuleID, log: Logger ) { import sbt.internal.util.{ BufferedLogger, FullLogger } - private final val ivySbt: IvySbt = new IvySbt(ivyConfiguration) private final val buffered = new BufferedLogger(FullLogger(log)) def compiledBridgeJar: File = { @@ -247,19 +233,6 @@ private[inc] class ZincComponentCompiler( s"$id$binSeparator${scalaVersion}__$javaClassVersion" } - /** - * Returns an ivy module that will wrap and download a given `moduleID`. - * - * @param moduleID The `moduleID` that needs to be wrapped in a dummy module to be downloaded. - */ - private[inc] def wrapDependencyInModule(moduleID: ModuleID): IvySbt#Module = { - import ZincComponentCompiler.{ sbtOrgTemp, modulePrefixTemp } - val sha1 = Hash.toHex(Hash(moduleID.name)) - val dummyID = ModuleID(sbtOrgTemp, s"$modulePrefixTemp$sha1", moduleID.revision) - .withConfigurations(moduleID.configurations) - ZincIvyActions.getModule(ivySbt, dummyID, Vector(moduleID)) - } - /** * Resolves the compiler bridge sources, compiles them and installs the sbt component * in the local filesystem to make sure that it's reused the next time is required. @@ -268,12 +241,17 @@ private[inc] class ZincComponentCompiler( */ private def compileAndInstall(compilerBridgeId: String): Unit = { import UnresolvedWarning.unresolvedWarningLines - val ivyModuleForBridge = wrapDependencyInModule(bridgeSources) + val moduleForBridge = + libraryManagement.wrapDependencyInModule(bridgeSources) IO.withTemporaryDirectory { binaryDirectory => val target = new File(binaryDirectory, s"$compilerBridgeId.jar") buffered bufferQuietly { IO.withTemporaryDirectory { retrieveDirectory => - ZincIvyActions.update(ivyModuleForBridge, retrieveDirectory, false, buffered) match { + ZincLMHelper.update(libraryManagement, + moduleForBridge, + retrieveDirectory, + false, + buffered) match { case Left(uw) => val mod = bridgeSources.toString val unresolvedLines = unresolvedWarningLines.showLines(uw).mkString("\n") @@ -294,70 +272,23 @@ private[inc] class ZincComponentCompiler( } -object ZincIvyActions { - type IvyModule = IvySbt#Module - - /** Define the default configurations for a Zinc module wrapper. */ - private final val DefaultConfigurations: Vector[Configuration] = - Vector(Configurations.Component, Configurations.Compile) - - /** - * Create a module from its dummy wrapper and its dependencies. - * - * @param wrapper The ModuleID wrapper that will download the dependencies. - * @param deps The dependencies to be downloaded. - * @return A fully-fledged ivy module to be used for [[IvyActions]]. - */ - private[inc] def getModule(ivySbt: IvySbt, - wrapper: ModuleID, - deps: Vector[ModuleID]): IvyModule = { - val moduleInfo = ModuleInfo(wrapper.name) - val componentIvySettings = InlineConfiguration( - validate = false, - ivyScala = None, - module = wrapper, - moduleInfo = moduleInfo, - dependencies = deps - ).withConfigurations(DefaultConfigurations) - new ivySbt.Module(componentIvySettings) - } - - // The implementation of this method is linked to `wrapDependencyInModule` - private def prettyPrintDependency(module: IvyModule): String = { - module.moduleSettings match { - case ic: InlineConfiguration => - // Pretty print the module as `ModuleIDExtra.toStringImpl` does. - ic.dependencies.map(m => s"${m.organization}:${m.name}:${m.revision}").mkString(", ") - case _ => sys.error("Fatal: configuration to download was not inline.") - } - } +private object ZincLMHelper { private final val warningConf = UnresolvedWarningConfiguration() private final val defaultRetrievePattern = Resolver.defaultRetrievePattern - private def defaultUpdateConfiguration(targetDir: File, noSource: Boolean): UpdateConfiguration = { - val retrieve = RetrieveConfiguration(targetDir, defaultRetrievePattern, false, None) - val logLevel = UpdateLogging.DownloadOnly - val defaultExcluded = Set("doc") - val finalExcluded = if (noSource) defaultExcluded + "src" else defaultExcluded - val artifactFilter = ArtifactTypeFilter.forbid(finalExcluded) - UpdateConfiguration(retrieve = Some(retrieve), - missingOk = false, - logging = logLevel, - artifactFilter = artifactFilter, - offline = false, - frozen = false) - } + private[inc] final val DefaultConfigurations: Vector[Configuration] = + Vector(Configurations.Component, Configurations.Compile) - private[inc] def update(module: IvyModule, + private[inc] def update(libraryManagement: LibraryManagement, + module: ModuleDescriptor, retrieveDirectory: File, noSource: Boolean = false, logger: Logger): Either[UnresolvedWarning, Vector[File]] = { - import IvyActions.updateEither val updateConfiguration = defaultUpdateConfiguration(retrieveDirectory, noSource) val dependencies = prettyPrintDependency(module) logger.info(s"Attempting to fetch $dependencies.") val clockForCache = LogicalClock.unknown - updateEither(module, updateConfiguration, warningConf, clockForCache, None, logger) match { + libraryManagement.update(module, updateConfiguration, warningConf, logger) match { case Left(unresolvedWarning) => logger.debug(s"Couldn't retrieve module(s) ${prettyPrintDependency(module)}.") Left(unresolvedWarning) @@ -369,4 +300,33 @@ object ZincIvyActions { Right(allFiles) } } + + private def defaultUpdateConfiguration(targetDir: File, noSource: Boolean): UpdateConfiguration = { + val retrieve = + RetrieveConfiguration(Some(targetDir), Some(defaultRetrievePattern), Some(false), None) + val logLevel = UpdateLogging.DownloadOnly + val defaultExcluded = Set("doc") + val finalExcluded = if (noSource) defaultExcluded + "src" else defaultExcluded + val artifactFilter = ArtifactTypeFilter.forbid(finalExcluded) + UpdateConfiguration( + retrieveManaged = Some(retrieve), + missingOk = Some(false), + logging = Some(logLevel), + logicalClock = None, + metadataDirectory = None, + artifactFilter = Some(artifactFilter), + offline = Some(false), + frozen = Some(false) + ) + } + + private def prettyPrintDependency(module: ModuleDescriptor): String = { + module.directDependencies + .map { m => + // Pretty print the module as `ModuleIDExtra.toStringImpl` does. + s"${m.organization}:${m.name}:${m.revision}" + } + .mkString(", ") + } + } diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 6eebed1cf..3527bccda 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -1,20 +1,20 @@ package sbt.internal.inc import java.io.File -import java.util.concurrent.Callable import sbt.io.IO import sbt.io.syntax._ import sbt.librarymanagement.{ DefaultMavenRepository, - FileRepository, - Patterns, + ChainedResolver, + IvyLibraryManagement, + ModuleConfiguration, Resolver, UpdateOptions } +import sbt.internal.librarymanagement.{ InlineIvyConfiguration, IvyPaths } import sbt.util.Logger import xsbti.compile.CompilerBridgeProvider -import xsbti.{ ComponentProvider, GlobalLock } /** * Base class for test suites that must be able to fetch and compile the compiler bridge. @@ -28,7 +28,7 @@ abstract class BridgeProviderSpecification extends UnitSpec { val resolvers = Array(ZincComponentCompiler.LocalResolver, DefaultMavenRepository) private val ivyConfiguration = - ZincComponentCompiler.getDefaultConfiguration(currentBase, currentTarget, resolvers, log) + getDefaultConfiguration(currentBase, currentTarget, resolvers, log) def secondaryCacheDirectory: File = { val target = file("target").getAbsoluteFile @@ -40,7 +40,8 @@ abstract class BridgeProviderSpecification extends UnitSpec { val secondaryCache = Some(secondaryCacheDirectory) val componentProvider = ZincComponentCompiler.getDefaultComponentProvider(targetDir) val manager = new ZincComponentManager(lock, componentProvider, secondaryCache, log) - ZincComponentCompiler.interfaceProvider(manager, ivyConfiguration, currentManaged) + val libraryManagement = new IvyLibraryManagement(ivyConfiguration) + ZincComponentCompiler.interfaceProvider(manager, libraryManagement, currentManaged) } def getCompilerBridge(targetDir: File, log: Logger, scalaVersion: String): File = { @@ -58,4 +59,25 @@ abstract class BridgeProviderSpecification extends UnitSpec { val provider = getZincProvider(targetDir, logger) provider.fetchScalaInstance(scalaVersion, logger) } + + private def getDefaultConfiguration(baseDirectory: File, + ivyHome: File, + resolvers0: Array[Resolver], + log: xsbti.Logger): InlineIvyConfiguration = { + import sbt.io.syntax._ + val resolvers = resolvers0.toVector + val chainResolver = ChainedResolver("zinc-chain", resolvers) + new InlineIvyConfiguration( + paths = IvyPaths(baseDirectory, Some(ivyHome)), + resolvers = resolvers, + otherResolvers = Vector.empty, + moduleConfigurations = Vector(ModuleConfiguration("*", chainResolver)), + lock = None, + checksums = Vector.empty, + managedChecksums = false, + resolutionCacheDir = Some(ivyHome / "resolution-cache"), + updateOptions = UpdateOptions(), + log = log + ) + } } From f69ba0ea6893876a3ee1aa3201d7369c963a627c Mon Sep 17 00:00:00 2001 From: jvican Date: Fri, 14 Jul 2017 16:33:13 +0200 Subject: [PATCH 75/90] Remove any reference to `F0` and `F1` Syncs up with https://github.com/sbt/util/pull/84. --- .../main/scala/sbt/internal/inc/ZincComponentCompiler.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index ebf9c84e6..5ebb2b96c 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -71,10 +71,11 @@ private[sbt] object ZincComponentCompiler { def compiledBridge(bridgeSources: ModuleID, scalaInstance: xsbti.compile.ScalaInstance, logger: xsbti.Logger): File = { + import InterfaceUtil.{ toSupplier => f0 } val autoClasspath = ClasspathOptionsUtil.auto val raw = new RawCompiler(scalaInstance, autoClasspath, logger) val zinc = new ZincComponentCompiler(raw, manager, ivyConfiguration, bridgeSources, logger) - logger.debug(InterfaceUtil.f0(s"Getting $bridgeSources for Scala ${scalaInstance.version}")) + logger.debug(f0(s"Getting $bridgeSources for Scala ${scalaInstance.version}")) zinc.compiledBridgeJar } From 57d25161dcd4613884324da38847eee8b38c92bc Mon Sep 17 00:00:00 2001 From: jvican Date: Wed, 26 Jul 2017 10:48:10 +0200 Subject: [PATCH 76/90] Use Scala 2.12.3 We have to look into the reason why the shaded version of the compiler plugin reports the following error and halts the build: ``` protoc-jar: executing: [/tmp/protocjar2818613521400194680/bin/protoc.exe, --plugin=protoc-gen-scala=/tmp/protocbridge4921434211196915044, --scala_out=grpc:/data/rw/code/scala/zinc/internal/zinc-persist/target/scala-2.12/src_managed/main, -I/data/rw/code/scala/zinc/internal/zinc-persist/src/main/protobuf, -I/data/rw/code/scala/zinc/internal/zinc-persist/target/protobuf_external, /data/rw/code/scala/zinc/internal/zinc-persist/src/main/protobuf/schema.proto] java.lang.AbstractMethodError: Method scalapb/ScalaPbCodeGenerator$.run(Lcom/google/protobuf/compiler/PluginProtos$CodeGeneratorRequest;)Lcom/google/protobuf/compiler/PluginProtos$CodeGeneratorResponse; is abstract at scalapb.ScalaPbCodeGenerator$.run(ScalaPbCodeGenerator.scala) at protocbridge.frontend.PluginFrontend$.$anonfun$runWithBytes$1(PluginFrontend.scala:56) at scala.util.Try$.apply(Try.scala:209) at protocbridge.frontend.PluginFrontend$.runWithBytes(PluginFrontend.scala:54) at protocbridge.frontend.PluginFrontend$.runWithInputStream(PluginFrontend.scala:67) at protocbridge.frontend.PosixPluginFrontend$.$anonfun$prepare$1(PosixPluginFrontend.scala:25) at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12) at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:653) at scala.util.Success.$anonfun$map$1(Try.scala:251) at scala.util.Success.map(Try.scala:209) at scala.concurrent.Future.$anonfun$map$1(Future.scala:287) at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:29) at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:29) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:60) at scala.concurrent.impl.ExecutionContextImpl$AdaptedForkJoinTask.exec(ExecutionContextImpl.scala:140) at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056) at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692) at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157) ``` --- .../test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala index cbba8021b..3fbd1a24f 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala @@ -10,6 +10,7 @@ class ZincComponentCompilerSpec extends BridgeProviderSpecification { val scala21111 = "2.11.11" val scala2121 = "2.12.1" val scala2122 = "2.12.2" + val scala2123 = "2.12.3" val logger = ConsoleLogger() it should "compile the bridge for Scala 2.10.5 and 2.10.6" in { @@ -25,5 +26,6 @@ class ZincComponentCompilerSpec extends BridgeProviderSpecification { it should "compile the bridge for Scala 2.12.2" in { IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2121) should exist) IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2122) should exist) + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2123) should exist) } } From 1c1ba43ed1fd505e111ed9684a4b94ed65c6eac0 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 22 Aug 2017 16:05:24 +0100 Subject: [PATCH 77/90] Add back, re-configure & re-enable Scalafmt --- .../main/scala/sbt/internal/inc/ZincComponentCompiler.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 9a0977581..e14e591de 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -304,7 +304,10 @@ private object ZincLMHelper { } } - private def defaultUpdateConfiguration(targetDir: File, noSource: Boolean): UpdateConfiguration = { + private def defaultUpdateConfiguration( + targetDir: File, + noSource: Boolean + ): UpdateConfiguration = { val retrieve = RetrieveConfiguration() .withRetrieveDirectory(targetDir) .withOutputPattern(defaultRetrievePattern) From bd1a38be544be6371310e43a9061ca1ea8ad866c Mon Sep 17 00:00:00 2001 From: Allan Timothy Leong Date: Sun, 22 Oct 2017 16:05:38 +0800 Subject: [PATCH 78/90] Remove unused imports + variables --- .../main/scala/sbt/internal/inc/ZincComponentCompiler.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index e14e591de..1c665172c 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -14,7 +14,7 @@ import java.net.URLClassLoader import java.util.concurrent.Callable import sbt.internal.inc.classpath.ClasspathUtilities -import sbt.io.{ Hash, IO } +import sbt.io.IO import sbt.internal.librarymanagement._ import sbt.internal.util.FullLogger import sbt.librarymanagement._ @@ -290,7 +290,6 @@ private object ZincLMHelper { val updateConfiguration = defaultUpdateConfiguration(retrieveDirectory, noSource) val dependencies = prettyPrintDependency(module) logger.info(s"Attempting to fetch $dependencies.") - val clockForCache = LogicalClock.unknown dependencyResolution.update(module, updateConfiguration, warningConf, logger) match { case Left(unresolvedWarning) => logger.debug(s"Couldn't retrieve module(s) ${prettyPrintDependency(module)}.") From 282b0f7f517372aa3f03b4e353884698c0eb06c9 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Wed, 15 Nov 2017 23:37:09 -0500 Subject: [PATCH 79/90] Split compiler bridge tests to another subproject Splitting compiler bridge tests to another subproject because while the bridge itself can be compiled with just compiler-interface, util-interface, and Scala Compiler as dependencies, the testing introduces more (such as IO). This creates problem for new Scala versions where IO or test libraries do not exist yet (e.g. Scala 2.13.0-M2). This also removes the Mima test due to the lack of 2.13 bridge for Zinc 1.0.0. Compiler bridge just needs to compile itself against the interface and Scala compiler, so there's no need to run Mima test. --- .../scala/sbt/internal/inc/ZincComponentCompiler.scala | 9 ++++++--- .../sbt/internal/inc/ZincComponentCompilerSpec.scala | 5 +++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index e14e591de..f64360a5f 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -42,9 +42,12 @@ private[sbt] object ZincComponentCompiler { def compilerBridgeId(scalaVersion: String) = { // Defaults to bridge for 2.12 for Scala versions bigger than 2.12.x scalaVersion match { - case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" - case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" - case _ => "compiler-bridge_2.12" + case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" + case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" + case sc if (sc startsWith "2.12.") => "compiler-bridge_2.12" + case sc if (sc startsWith "2.13.0-M") => "compiler-bridge_2.13.0-M2" + case sc if (sc startsWith "2.13.0-RC") => "compiler-bridge_2.13.0-M2" + case _ => "compiler-bridge_2.13" } } import xsbti.ArtifactInfo.SbtOrganization diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala index 3fbd1a24f..f3245c1ea 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala @@ -11,6 +11,7 @@ class ZincComponentCompilerSpec extends BridgeProviderSpecification { val scala2121 = "2.12.1" val scala2122 = "2.12.2" val scala2123 = "2.12.3" + val scala2130M2 = "2.13.0-M2" val logger = ConsoleLogger() it should "compile the bridge for Scala 2.10.5 and 2.10.6" in { @@ -28,4 +29,8 @@ class ZincComponentCompilerSpec extends BridgeProviderSpecification { IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2122) should exist) IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2123) should exist) } + + it should "compile the bridge for Scala 2.13.0-M2" in { + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2130M2) should exist) + } } From 8c1e062fd1ad791be186f162c1de9bd960b937bc Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 28 Nov 2017 15:32:02 +0000 Subject: [PATCH 80/90] Support scala 2.13.0-pre-* & 2.13.0-M1 Fixes sbt/sbt#3771 Fixes sbt/zinc#460 --- .../sbt/internal/inc/ZincComponentCompiler.scala | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index f64360a5f..33a9e7fd7 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -40,14 +40,15 @@ private[sbt] object ZincComponentCompiler { private val CompileConf = Some(Configurations.Compile.name) private[sbt] def getDefaultBridgeModule(scalaVersion: String): ModuleID = { def compilerBridgeId(scalaVersion: String) = { - // Defaults to bridge for 2.12 for Scala versions bigger than 2.12.x scalaVersion match { - case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" - case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" - case sc if (sc startsWith "2.12.") => "compiler-bridge_2.12" - case sc if (sc startsWith "2.13.0-M") => "compiler-bridge_2.13.0-M2" - case sc if (sc startsWith "2.13.0-RC") => "compiler-bridge_2.13.0-M2" - case _ => "compiler-bridge_2.13" + case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" + case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" + case sc if (sc startsWith "2.12.") => "compiler-bridge_2.12" + case "2.13.0-M1" => "compiler-bridge_2.12" + case sc if (sc startsWith "2.13.0-pre-") => "compiler-bridge_2.13.0-M2" + case sc if (sc startsWith "2.13.0-M") => "compiler-bridge_2.13.0-M2" + case sc if (sc startsWith "2.13.0-RC") => "compiler-bridge_2.13.0-M2" + case _ => "compiler-bridge_2.13" } } import xsbti.ArtifactInfo.SbtOrganization From 9c53ad39052a1d9c335d183606ee80e0b3f6498c Mon Sep 17 00:00:00 2001 From: exoego Date: Wed, 21 Feb 2018 21:24:46 +0900 Subject: [PATCH 81/90] Drop "final" modifier from private case classes, to prevent false positive. Refer https://issues.scala-lang.org/browse/SI-4440 --- .../src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 234a9c3a9..2caced237 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -91,7 +91,7 @@ private[sbt] object ZincComponentCompiler { compiledBridge(bridgeSources, scalaInstance, logger) } - private final case class ScalaArtifacts(compiler: File, library: File, others: Vector[File]) + private case class ScalaArtifacts(compiler: File, library: File, others: Vector[File]) private def getScalaArtifacts(scalaVersion: String, logger: xsbti.Logger): ScalaArtifacts = { def isPrefixedWith(artifact: File, prefix: String) = artifact.getName.startsWith(prefix) From 862ae293ba6ba16ab8fd06db057ae496703f64da Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 2 Mar 2018 00:42:00 -0500 Subject: [PATCH 82/90] include only scala-library into the boot classpath during run Fixes https://github.com/sbt/sbt/issues/3405 Ref https://github.com/scala/scala-xml/issues/195 sbt's `run` is emulated using a classloader trick that includes ScalaInstance as the parent classloader under the classpath. The problem is the ScalaInstance classloader currently contains both compiler, library, and their transitive JARs: ```scala res0: Array[java.io.File] = Array(scala-library.jar, scala-compiler.jar, jline.jar, scala-reflect.jar, scala-xml_2.12.jar) ``` This could have been causing various issues, but most recently it showed up as wrong version of scala-xml getting prioritized over what's passed by the user. 1. new field loaderLibraryOnly is added to xsbti.ScalaInstance. 2. it is initialized to the library loader if the launcher creates it, otherwise create layered loader here. This aims to isolate the library loader, and retain the perf. --- .../sbt/internal/inc/ZincComponentCompiler.scala | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 234a9c3a9..f51672038 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -140,11 +140,19 @@ private[sbt] object ZincComponentCompiler { val scalaLibrary = scalaArtifacts.library val jarsToLoad = (scalaCompiler +: scalaLibrary +: scalaArtifacts.others).toArray assert(jarsToLoad.forall(_.exists), "One or more jar(s) in the Scala instance do not exist.") - val loader = new URLClassLoader(toURLs(jarsToLoad), ClasspathUtilities.rootLoader) + val loaderLibraryOnly = ClasspathUtilities.toLoader(Vector(scalaLibrary)) + val loader = ClasspathUtilities.toLoader(jarsToLoad.toVector filterNot { _ == scalaLibrary }, + loaderLibraryOnly) val properties = ResourceLoader.getSafePropertiesFor("compiler.properties", loader) val loaderVersion = Option(properties.getProperty("version.number")) val scalaV = loaderVersion.getOrElse("unknown") - new ScalaInstance(scalaV, loader, scalaLibrary, scalaCompiler, jarsToLoad, loaderVersion) + new ScalaInstance(scalaV, + loader, + loaderLibraryOnly, + scalaLibrary, + scalaCompiler, + jarsToLoad, + loaderVersion) } } From f1951ce7250dfb15287478d0090b34d44162dce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Wawrzyk?= Date: Mon, 4 Jun 2018 14:04:36 +0200 Subject: [PATCH 83/90] Got rid of multiple warnigns --- .../src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index dff8387d9..69963e12b 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -10,7 +10,6 @@ package internal package inc import java.io.File -import java.net.URLClassLoader import java.util.concurrent.Callable import sbt.internal.inc.classpath.ClasspathUtilities @@ -134,7 +133,6 @@ private[sbt] object ZincComponentCompiler { override def fetchScalaInstance(scalaVersion: String, logger: xsbti.Logger): xsbti.compile.ScalaInstance = { - import sbt.io.Path.toURLs val scalaArtifacts = getScalaArtifacts(scalaVersion, logger) val scalaCompiler = scalaArtifacts.compiler val scalaLibrary = scalaArtifacts.library From 4a04764f2077bc1d54620f966fcc631fefd7b389 Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Wed, 8 Aug 2018 16:34:45 +0900 Subject: [PATCH 84/90] Fix the several typos detected by github.com/client9/misspell --- .../src/main/java/xsbti/compile/ZincBridgeProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java b/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java index 0a1e8e77e..abf3be3d6 100644 --- a/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java +++ b/internal/zinc-ivy-integration/src/main/java/xsbti/compile/ZincBridgeProvider.java @@ -35,7 +35,7 @@ public interface ZincBridgeProvider { * Returns a global lock that does nothing but calling the callable to synchronize * across threads. The lock file is used to resolve and download dependencies via ivy. *

- * This operation is necesary to invoke {@link ZincBridgeProvider#getProvider(File, GlobalLock, ComponentProvider, IvyConfiguration, Logger)}. + * This operation is necessary to invoke {@link ZincBridgeProvider#getProvider(File, GlobalLock, ComponentProvider, IvyConfiguration, Logger)}. * * @return A default global lock. */ From d30556f19e7494366e52df9b7fb6d3cd1961ad0d Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 12 Oct 2018 05:22:39 -0400 Subject: [PATCH 85/90] Refactor compiler bridge unit test This refactors the compiler bridge unit test to use the normal Zinc facility, namely AnalyzingCompiler that's built on Scala 2.12, but is capable of driving the compiler bridge built on non-2.12. This allows us to run the unit tests without any additional dependencies published for Scala 2.13.0-M5. --- .../main/scala/sbt/internal/inc/ZincComponentCompiler.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 69963e12b..9fab72636 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -44,9 +44,9 @@ private[sbt] object ZincComponentCompiler { case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" case sc if (sc startsWith "2.12.") => "compiler-bridge_2.12" case "2.13.0-M1" => "compiler-bridge_2.12" - case sc if (sc startsWith "2.13.0-pre-") => "compiler-bridge_2.13.0-M2" - case sc if (sc startsWith "2.13.0-M") => "compiler-bridge_2.13.0-M2" - case sc if (sc startsWith "2.13.0-RC") => "compiler-bridge_2.13.0-M2" + case sc if (sc startsWith "2.13.0-pre-") => "compiler-bridge_2.13.0-M5" + case sc if (sc startsWith "2.13.0-M") => "compiler-bridge_2.13.0-M5" + case sc if (sc startsWith "2.13.0-RC") => "compiler-bridge_2.13.0-M5" case _ => "compiler-bridge_2.13" } } From c61773af032eb16d9bf511f0ec0f90189152e3ba Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 14 Feb 2019 01:33:23 -0500 Subject: [PATCH 86/90] Skip Scala 2.10 and Scala 2.11 components for JDK 11 Scala 2.10 and Scala 2.11 do not support JDK 11. --- .../internal/inc/ZincComponentCompilerSpec.scala | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala index f3245c1ea..2073da404 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala @@ -12,16 +12,21 @@ class ZincComponentCompilerSpec extends BridgeProviderSpecification { val scala2122 = "2.12.2" val scala2123 = "2.12.3" val scala2130M2 = "2.13.0-M2" + def isJava8: Boolean = sys.props("java.specification.version") == "1.8" val logger = ConsoleLogger() it should "compile the bridge for Scala 2.10.5 and 2.10.6" in { - IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2105) should exist) - IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2106) should exist) + if (isJava8) { + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2105) should exist) + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2106) should exist) + } else () } it should "compile the bridge for Scala 2.11.8 and 2.11.11" in { - IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2118) should exist) - IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala21111) should exist) + if (isJava8) { + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2118) should exist) + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala21111) should exist) + } else () } it should "compile the bridge for Scala 2.12.2" in { From 146afdf8cde7bb1c13c5d7a3e0b2eb8638a98436 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 12 Apr 2019 10:17:21 +0100 Subject: [PATCH 87/90] Break the dependency on LM, and thus Ivy This patch breaks the dependency that Zinc had on sbt's Library Management (LM) library abstraction (sbt/librarymanagement) and thus, transitively, on Ivy. The reason Zinc depends on LM in the first place is to dynamically download the compiler bridge sources JAR, which it then compiles in order to bridge from binary-compatible Zinc to the never-binary-stable (and most of the time source-compatible) compiler API. From my research (that is, using GitHub Search) the only user of this feature is sbt, with all other integrations (e.g. pants, bloop, mill) providing the compiler bridge sources JAR directly (an alternative API entry point). Therefore the dependency on LM and that integration code could be untangled from Zinc and moved into sbt. That would also give an opportunity to move the code in LM (back) into sbt, which I also think would be a good idea. For now this patch leaves that integration code in the already existing `zinc-ivy-integration` module, but which is now no longer a dependency of any other module of Zinc, specifically it is no longer a dependency of the `zinc` and `zincScripted` modules. I think, though, zinc-ivy-integration should remain in the zinc repo, as a part of the build, being tested in CI, until it's been moved (back) into sbt. I'd be happy to take care of both the remaining move and removal tasks. In order to allow removing LM, Ivy and zinc-ivy-integration as transitive dependencies of Zinc, this patch has to make a breaking change to the `ZincUtil` object in the zinc module. Despite it being defined in the `sbt.internal.inc` package (i.e. not declared as public API) ZincUtil is in fact a used (Scala) API of Zinc (usages discovered via GitHub Search). Therefore I chose to leave the object in the zinc module and only drop from the object the two methods that directly depend on LM's API. Specifically (1) the `getDefaultBridgeModule` method and (2) the `scalaCompiler` overload that depends on LM were removed. These methods now live in a new `ZincLmUtil` object in zinc-ivy-integration, which sbt can switch to using. In terms of risk, from my research (GitHub Search) the only users of those methods are sbt and bloop. I need to confirm but I think bloop will be able to manage this breaking change (it looks it might be just fallback usage? TBC). For sbt we don't actual support using new Zinc with old sbt, so sbt can also just update its usage on its next release. Any other usage risks being broken but given it's internal, non-public API I think it's fair game. The remaining changes are in the testing so that zinc-ivy-integration's test suite continues to test its download-and-compile behaviour, while the rest of Zinc switches to using the prebuilt compiler bridges, reusing and generalising some pre-existing zincScripted code (as well as re-wiring some modules) so it can be used by zinc's tests too. --- .../scala/sbt/internal/inc/ZincLmUtil.scala | 49 +++++++++++++++++++ ...a => IvyBridgeProviderSpecification.scala} | 19 +------ .../inc/ZincComponentCompilerSpec.scala | 2 +- 3 files changed, 51 insertions(+), 19 deletions(-) create mode 100644 internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincLmUtil.scala rename internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/{BridgeProviderSpecification.scala => IvyBridgeProviderSpecification.scala} (75%) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincLmUtil.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincLmUtil.scala new file mode 100644 index 000000000..4c3e915d2 --- /dev/null +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincLmUtil.scala @@ -0,0 +1,49 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + +package sbt.internal.inc + +import java.io.File +import java.net.URLClassLoader + +import sbt.librarymanagement.{ DependencyResolution, ModuleID } +import sbt.internal.inc.classpath.ClassLoaderCache +import xsbti._ +import xsbti.compile._ + +object ZincLmUtil { + import xsbti.compile.ScalaInstance + + /** + * Instantiate a Scala compiler that is instrumented to analyze dependencies. + * This Scala compiler is useful to create your own instance of incremental + * compilation. + */ + def scalaCompiler( + scalaInstance: ScalaInstance, + classpathOptions: ClasspathOptions, + globalLock: GlobalLock, + componentProvider: ComponentProvider, + secondaryCacheDir: Option[File], + dependencyResolution: DependencyResolution, + compilerBridgeSource: ModuleID, + scalaJarsTarget: File, + log: Logger + ): AnalyzingCompiler = { + val compilerBridgeProvider = ZincComponentCompiler.interfaceProvider( + compilerBridgeSource, + new ZincComponentManager(globalLock, componentProvider, secondaryCacheDir, log), + dependencyResolution, + scalaJarsTarget, + ) + val loader = Some(new ClassLoaderCache(new URLClassLoader(new Array(0)))) + new AnalyzingCompiler(scalaInstance, compilerBridgeProvider, classpathOptions, _ => (), loader) + } + + def getDefaultBridgeModule(scalaVersion: String): ModuleID = + ZincComponentCompiler.getDefaultBridgeModule(scalaVersion) +} diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyBridgeProviderSpecification.scala similarity index 75% rename from internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala rename to internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyBridgeProviderSpecification.scala index abd2485a4..283b3f0c7 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyBridgeProviderSpecification.scala @@ -2,7 +2,6 @@ package sbt.internal.inc import java.io.File -import sbt.io.IO import sbt.io.syntax._ import sbt.librarymanagement._ import sbt.librarymanagement.ivy._ @@ -14,7 +13,7 @@ import xsbti.compile.CompilerBridgeProvider * * This is a very good example on how to instantiate the compiler bridge provider. */ -abstract class BridgeProviderSpecification extends UnitSpec { +abstract class IvyBridgeProviderSpecification extends UnitSpec with AbstractBridgeProviderTestkit { def currentBase: File = new File(".") def currentTarget: File = currentBase / "target" / "ivyhome" def currentManaged: File = currentBase / "target" / "lib_managed" @@ -37,22 +36,6 @@ abstract class BridgeProviderSpecification extends UnitSpec { ZincComponentCompiler.interfaceProvider(manager, dependencyResolution, currentManaged) } - def getCompilerBridge(targetDir: File, log: Logger, scalaVersion: String): File = { - val provider = getZincProvider(targetDir, log) - val scalaInstance = provider.fetchScalaInstance(scalaVersion, log) - val bridge = provider.fetchCompiledBridge(scalaInstance, log) - val target = targetDir / s"target-bridge-$scalaVersion.jar" - IO.copyFile(bridge, target) - target - } - - def scalaInstance(scalaVersion: String, - targetDir: File, - logger: Logger): xsbti.compile.ScalaInstance = { - val provider = getZincProvider(targetDir, logger) - provider.fetchScalaInstance(scalaVersion, logger) - } - private def getDefaultConfiguration(baseDirectory: File, ivyHome: File, resolvers0: Array[Resolver], diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala index 2073da404..c6df524bb 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala @@ -3,7 +3,7 @@ package sbt.internal.inc import sbt.internal.util.ConsoleLogger import sbt.io.IO -class ZincComponentCompilerSpec extends BridgeProviderSpecification { +class ZincComponentCompilerSpec extends IvyBridgeProviderSpecification { val scala2105 = "2.10.5" val scala2106 = "2.10.6" val scala2118 = "2.11.8" From 9c16938c6a9dc48b00b22aa9fa44f113e7dd8694 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 4 Apr 2019 11:03:56 -0400 Subject: [PATCH 88/90] bump Scala bridge to use 2.13.0-RC1 We are fairly certain we can maintain source-compatibility of compiler bridge from 2.13.0-RC to 2.13.x. See also https://github.com/sbt/zinc/issues/78 :) --- .../sbt/internal/inc/ZincComponentCompiler.scala | 14 ++++++-------- .../internal/inc/ZincComponentCompilerSpec.scala | 6 +++--- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 9fab72636..b8cc94c26 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -40,14 +40,12 @@ private[sbt] object ZincComponentCompiler { private[sbt] def getDefaultBridgeModule(scalaVersion: String): ModuleID = { def compilerBridgeId(scalaVersion: String) = { scalaVersion match { - case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" - case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" - case sc if (sc startsWith "2.12.") => "compiler-bridge_2.12" - case "2.13.0-M1" => "compiler-bridge_2.12" - case sc if (sc startsWith "2.13.0-pre-") => "compiler-bridge_2.13.0-M5" - case sc if (sc startsWith "2.13.0-M") => "compiler-bridge_2.13.0-M5" - case sc if (sc startsWith "2.13.0-RC") => "compiler-bridge_2.13.0-M5" - case _ => "compiler-bridge_2.13" + case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10" + case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" + case sc if (sc startsWith "2.12.") => "compiler-bridge_2.12" + case "2.13.0-M1" => "compiler-bridge_2.12" + case sc if (sc startsWith "2.13.") => "compiler-bridge_2.13.0-RC1" + case _ => "compiler-bridge_2.13.0-RC1" } } import xsbti.ArtifactInfo.SbtOrganization diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala index c6df524bb..75e04d8ff 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala @@ -11,7 +11,7 @@ class ZincComponentCompilerSpec extends IvyBridgeProviderSpecification { val scala2121 = "2.12.1" val scala2122 = "2.12.2" val scala2123 = "2.12.3" - val scala2130M2 = "2.13.0-M2" + val scala2130RC1 = "2.13.0-RC1" def isJava8: Boolean = sys.props("java.specification.version") == "1.8" val logger = ConsoleLogger() @@ -35,7 +35,7 @@ class ZincComponentCompilerSpec extends IvyBridgeProviderSpecification { IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2123) should exist) } - it should "compile the bridge for Scala 2.13.0-M2" in { - IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2130M2) should exist) + it should "compile the bridge for Scala 2.13.0-RC1" in { + IO.withTemporaryDirectory(t => getCompilerBridge(t, logger, scala2130RC1) should exist) } } From 9daae10ad979af1068488f4f39c6688a59bb0711 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 4 Apr 2019 15:17:27 -0400 Subject: [PATCH 89/90] call it compiler-bridge_2.13 --- .../main/scala/sbt/internal/inc/ZincComponentCompiler.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index b8cc94c26..0e1f73024 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -44,8 +44,7 @@ private[sbt] object ZincComponentCompiler { case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11" case sc if (sc startsWith "2.12.") => "compiler-bridge_2.12" case "2.13.0-M1" => "compiler-bridge_2.12" - case sc if (sc startsWith "2.13.") => "compiler-bridge_2.13.0-RC1" - case _ => "compiler-bridge_2.13.0-RC1" + case _ => "compiler-bridge_2.13" } } import xsbti.ArtifactInfo.SbtOrganization From 895c1d39ce67a71897b0150d93b390f5e76ac58a Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Wed, 10 Apr 2019 21:01:18 +0000 Subject: [PATCH 90/90] Add scala-integration resolver --- .../sbt/internal/inc/IvyBridgeProviderSpecification.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyBridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyBridgeProviderSpecification.scala index 283b3f0c7..d0e9c8339 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyBridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/IvyBridgeProviderSpecification.scala @@ -18,7 +18,12 @@ abstract class IvyBridgeProviderSpecification extends UnitSpec with AbstractBrid def currentTarget: File = currentBase / "target" / "ivyhome" def currentManaged: File = currentBase / "target" / "lib_managed" - val resolvers = Array(ZincComponentCompiler.LocalResolver, Resolver.mavenCentral) + val resolvers = Array( + ZincComponentCompiler.LocalResolver, + Resolver.mavenCentral, + MavenRepository("scala-integration", + "https://scala-ci.typesafe.com/artifactory/scala-integration/") + ) private val ivyConfiguration = getDefaultConfiguration(currentBase, currentTarget, resolvers, log)