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 + ) + } }