mirror of https://github.com/sbt/sbt.git
Adapt Zinc to use the new LibraryManagement API
This commit is contained in:
parent
34d0dae6e2
commit
763effd337
|
|
@ -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.
|
||||
* <p>
|
||||
* This method is useful to invoke {@link ZincBridgeProvider#getProvider(File, GlobalLock, ComponentProvider, IvyConfiguration, Logger)}.
|
||||
* <p>
|
||||
* In order to know which arguments to pass, reading the
|
||||
* <a href="http://ant.apache.org/ivy/history/latest-milestone/concept.html">ivy main concepts</a>
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(", ")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue