From f36a5b88d86ab5b90bd9af5a06d92742dc3aca80 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 8 Jan 2015 18:02:59 -0500 Subject: [PATCH] Turn Aether integration into sbt-maven-resolver --- build.sbt | 13 ++++- ivy/src/main/scala/sbt/ConvertResolver.scala | 51 +++++++++---------- ivy/src/main/scala/sbt/Ivy.scala | 3 +- ivy/src/main/scala/sbt/MakePom.scala | 3 +- ivy/src/main/scala/sbt/UpdateOptions.scala | 27 +++++----- .../sbt/ivyint/CustomMavenResolver.scala | 11 ++++ .../scala/sbt/ivyint/SbtChainResolver.scala | 2 +- .../resolver/MavenRepositoryResolver.scala | 7 ++- .../MavenRepositorySystemFactory.scala | 0 .../internal/SbtArtifactDescriptorReader.java | 0 .../internal/SbtExtraProperties.java | 0 .../internal/SbtRepositoryLayout.scala | 0 .../scala/sbt/MavenResolverConverter.scala | 13 +++++ .../sbt/plugins/MavenResolverPlugin.scala | 13 +++++ .../dependency-management/mvn-local/build.sbt | 5 +- .../mvn-local/project/plugin.sbt | 2 + 16 files changed, 101 insertions(+), 49 deletions(-) create mode 100644 ivy/src/main/scala/sbt/ivyint/CustomMavenResolver.scala rename {ivy => sbt-maven-resolver}/src/main/scala/org/apache/ivy/plugins/resolver/MavenRepositoryResolver.scala (99%) rename {ivy => sbt-maven-resolver}/src/main/scala/org/apache/ivy/plugins/resolver/MavenRepositorySystemFactory.scala (100%) rename {ivy => sbt-maven-resolver}/src/main/scala/org/apache/maven/repository/internal/SbtArtifactDescriptorReader.java (100%) rename {ivy => sbt-maven-resolver}/src/main/scala/org/apache/maven/repository/internal/SbtExtraProperties.java (100%) rename {ivy => sbt-maven-resolver}/src/main/scala/org/apache/maven/repository/internal/SbtRepositoryLayout.scala (100%) create mode 100644 sbt-maven-resolver/src/main/scala/sbt/MavenResolverConverter.scala create mode 100644 sbt-maven-resolver/src/main/scala/sbt/plugins/MavenResolverPlugin.scala create mode 100644 sbt/src/sbt-test/dependency-management/mvn-local/project/plugin.sbt diff --git a/build.sbt b/build.sbt index 1faa99e75..e2e301bb5 100644 --- a/build.sbt +++ b/build.sbt @@ -215,7 +215,7 @@ lazy val ivyProj = (project in file("ivy")). settings(baseSettings: _*). settings( name := "Ivy", - libraryDependencies ++= Seq(ivy, jsch, json4sNative, jawnParser, jawnJson4s) ++ aetherLibs, + libraryDependencies ++= Seq(ivy, jsch, json4sNative, jawnParser, jawnJson4s), testExclusive) // Runner for uniform test interface @@ -412,6 +412,15 @@ lazy val sbtProj = (project in sbtPath). normalizedName := "sbt" ) +lazy val mavenResolverPluginProj = (project in file("sbt-maven-resolver")). + dependsOn(sbtProj). + settings(baseSettings: _*). + settings( + name := "sbt-maven-resolver", + libraryDependencies ++= aetherLibs, + sbtPlugin := true + ) + def scriptedTask: Initialize[InputTask[Unit]] = InputTask(scriptedSource(dir => (s: State) => scriptedParser(dir))) { result => (proguard in Proguard, fullClasspath in scriptedSbtProj in Test, scalaInstance in scriptedSbtProj, publishAll, scriptedSource, result) map { (launcher, scriptedSbtClasspath, scriptedSbtInstance, _, sourcePath, args) => @@ -435,7 +444,7 @@ def allProjects = Seq(launchInterfaceProj, launchProj, testSamples, interfacePro compileInterfaceProj, compileIncrementalProj, compilePersistProj, compilerProj, compilerIntegrationProj, compilerIvyProj, scriptedBaseProj, scriptedSbtProj, scriptedPluginProj, - actionsProj, commandProj, mainSettingsProj, mainProj, sbtProj) + actionsProj, commandProj, mainSettingsProj, mainProj, sbtProj, mavenResolverPluginProj) def projectsWithMyProvided = allProjects.map(p => p.copy(configurations = (p.configurations.filter(_ != Provided)) :+ myProvided)) lazy val nonRoots = projectsWithMyProvided.map(p => LocalProject(p.id)) diff --git a/ivy/src/main/scala/sbt/ConvertResolver.scala b/ivy/src/main/scala/sbt/ConvertResolver.scala index 9c7545eb9..26abec09c 100644 --- a/ivy/src/main/scala/sbt/ConvertResolver.scala +++ b/ivy/src/main/scala/sbt/ConvertResolver.scala @@ -19,6 +19,8 @@ import org.apache.ivy.util.{ FileUtil, ChecksumHelper } import org.apache.ivy.core.module.descriptor.{ Artifact => IArtifact } private[sbt] object ConvertResolver { + import UpdateOptions.ResolverConverter + /** * This class contains all the reflective lookups used in the * checksum-friendly URL publishing shim. @@ -94,37 +96,34 @@ private[sbt] object ConvertResolver { } } - private[sbt] val USE_AETHER_PROPERTY = "sbt.use.aether" - private def isUseAetherForResolution(settings: IvySettings): Boolean = - settings.getVariable(USE_AETHER_PROPERTY) == "true" + /** Converts the given sbt resolver into an Ivy resolver. */ + @deprecated("0.13.8", "Use the variant with updateOptions") + def apply(r: Resolver, settings: IvySettings, log: Logger): DependencyResolver = + apply(r, settings, UpdateOptions(), log) - /** Converts the given sbt resolver into an Ivy resolver..*/ - def apply(r: Resolver, settings: IvySettings, log: Logger) = - { + /** Converts the given sbt resolver into an Ivy resolver. */ + def apply(r: Resolver, settings: IvySettings, updateOptions: UpdateOptions, log: Logger): DependencyResolver = + (updateOptions.resolverConverter orElse defaultConvert)((r, settings, log)) + + /** The default implementation of converter. */ + lazy val defaultConvert: ResolverConverter = { + case (r, settings, log) => r match { case repo: MavenRepository => { - if (isUseAetherForResolution(settings)) { - repo match { - case cache: MavenCache => new org.apache.ivy.plugins.resolver.MavenCacheRepositoryResolver(cache, settings) - case _ => new org.apache.ivy.plugins.resolver.MavenRemoteRepositoryResolver(repo, settings) + val pattern = Collections.singletonList(Resolver.resolvePattern(repo.root, Resolver.mavenStyleBasePattern)) + final class PluginCapableResolver extends IBiblioResolver with ChecksumFriendlyURLResolver with DescriptorRequired { + def setPatterns() { + // done this way for access to protected methods. + setArtifactPatterns(pattern) + setIvyPatterns(pattern) } - } else { - val pattern = Collections.singletonList(Resolver.resolvePattern(repo.root, Resolver.mavenStyleBasePattern)) - final class PluginCapableResolver extends IBiblioResolver with ChecksumFriendlyURLResolver with DescriptorRequired { - def setPatterns() { - // done this way for access to protected methods. - setArtifactPatterns(pattern) - setIvyPatterns(pattern) - } - } - val resolver = new PluginCapableResolver - resolver.setRepository(new LocalIfFileRepo) - initializeMavenStyle(resolver, repo.name, repo.root) - resolver.setPatterns() // has to be done after initializeMavenStyle, which calls methods that overwrite the patterns - resolver } - + val resolver = new PluginCapableResolver + resolver.setRepository(new LocalIfFileRepo) + initializeMavenStyle(resolver, repo.name, repo.root) + resolver.setPatterns() // has to be done after initializeMavenStyle, which calls methods that overwrite the patterns + resolver } // TODO: HTTP repository is no longer recommended. #1541 // Remove `JavaNet1Repository` when we bump up the API. @@ -176,7 +175,7 @@ private[sbt] object ConvertResolver { case repo: ChainedResolver => IvySbt.resolverChain(repo.name, repo.resolvers, false, settings, log) case repo: RawRepository => repo.resolver } - } + } private sealed trait DescriptorRequired extends BasicResolver { override def getDependency(dd: DependencyDescriptor, data: ResolveData) = diff --git a/ivy/src/main/scala/sbt/Ivy.scala b/ivy/src/main/scala/sbt/Ivy.scala index d2d0388ee..be86d1131 100644 --- a/ivy/src/main/scala/sbt/Ivy.scala +++ b/ivy/src/main/scala/sbt/Ivy.scala @@ -73,7 +73,6 @@ final class IvySbt(val configuration: IvyConfiguration) { is.setBaseDir(baseDirectory) is.setCircularDependencyStrategy(configuration.updateOptions.circularDependencyLevel.ivyStrategy) CustomPomParser.registerDefault - is.setVariable(ConvertResolver.USE_AETHER_PROPERTY, s"${configuration.updateOptions.aetherResolution}") configuration match { case e: ExternalIvyConfiguration => @@ -289,7 +288,7 @@ private[sbt] object IvySbt { def resolverChain(name: String, resolvers: Seq[Resolver], localOnly: Boolean, settings: IvySettings, log: Logger): DependencyResolver = resolverChain(name, resolvers, localOnly, settings, UpdateOptions(), log) def resolverChain(name: String, resolvers: Seq[Resolver], localOnly: Boolean, settings: IvySettings, updateOptions: UpdateOptions, log: Logger): DependencyResolver = { - def mapResolvers(rs: Seq[Resolver]) = rs.map(r => ConvertResolver(r, settings, log)) + def mapResolvers(rs: Seq[Resolver]) = rs.map(r => ConvertResolver(r, settings, updateOptions, log)) val (projectResolvers, rest) = resolvers.partition(_.name == "inter-project") if (projectResolvers.isEmpty) new ivyint.SbtChainResolver(name, mapResolvers(rest), settings, updateOptions, log) else { diff --git a/ivy/src/main/scala/sbt/MakePom.scala b/ivy/src/main/scala/sbt/MakePom.scala index 13ca70f1b..fc15a3cd9 100644 --- a/ivy/src/main/scala/sbt/MakePom.scala +++ b/ivy/src/main/scala/sbt/MakePom.scala @@ -20,6 +20,7 @@ import org.apache.ivy.Ivy import org.apache.ivy.core.settings.IvySettings import org.apache.ivy.core.module.descriptor.{ DependencyArtifactDescriptor, DependencyDescriptor, License, ModuleDescriptor, ExcludeRule } import org.apache.ivy.plugins.resolver.{ ChainResolver, DependencyResolver, IBiblioResolver } +import ivyint.CustomRemoteMavenResolver class MakePom(val log: Logger) { @deprecated("Use `write(Ivy, ModuleDescriptor, ModuleInfo, Option[Iterable[Configuration]], Set[String], NodeSeq, XNode => XNode, MavenRepository => Boolean, Boolean, File)` instead", "0.11.2") @@ -333,7 +334,7 @@ class MakePom(val log: Logger) { val repositories = if (includeAll) allResolvers(settings) else resolvers(settings.getDefaultResolver) val mavenRepositories = repositories.flatMap { - case m: org.apache.ivy.plugins.resolver.MavenRemoteRepositoryResolver if m.repo.root != DefaultMavenRepository.root => + case m: CustomRemoteMavenResolver if m.repo.root != DefaultMavenRepository.root => MavenRepository(m.repo.name, m.repo.root) :: Nil case m: IBiblioResolver if m.isM2compatible && m.getRoot != DefaultMavenRepository.root => MavenRepository(m.getName, m.getRoot) :: Nil diff --git a/ivy/src/main/scala/sbt/UpdateOptions.scala b/ivy/src/main/scala/sbt/UpdateOptions.scala index e13fed72f..3a710026c 100644 --- a/ivy/src/main/scala/sbt/UpdateOptions.scala +++ b/ivy/src/main/scala/sbt/UpdateOptions.scala @@ -1,6 +1,8 @@ package sbt import java.io.File +import org.apache.ivy.plugins.resolver.DependencyResolver +import org.apache.ivy.core.settings.IvySettings /** * Represents configurable options for update task. @@ -18,13 +20,8 @@ final class UpdateOptions private[sbt] ( val consolidatedResolution: Boolean, /** If set to true, use cached resolution. */ val cachedResolution: Boolean, - /** If set to true, use aether for resolving maven artifacts. */ - val aetherResolution: Boolean) { - - /** Enables Aether for dependency resolution. */ - def withAetherResolution(aetherResolution: Boolean): UpdateOptions = - copy(aetherResolution = aetherResolution) - + /** Extention point for an alternative resolver converter. */ + val resolverConverter: UpdateOptions.ResolverConverter) { def withCircularDependencyLevel(circularDependencyLevel: CircularDependencyLevel): UpdateOptions = copy(circularDependencyLevel = circularDependencyLevel) def withLatestSnapshots(latestSnapshots: Boolean): UpdateOptions = @@ -36,24 +33,28 @@ final class UpdateOptions private[sbt] ( def withCachedResolution(cachedResoluton: Boolean): UpdateOptions = copy(cachedResolution = cachedResoluton, consolidatedResolution = cachedResolution) + /** Extention point for an alternative resolver converter. */ + def withResolverConverter(resolverConverter: UpdateOptions.ResolverConverter): UpdateOptions = + copy(resolverConverter = resolverConverter) private[sbt] def copy( circularDependencyLevel: CircularDependencyLevel = this.circularDependencyLevel, latestSnapshots: Boolean = this.latestSnapshots, consolidatedResolution: Boolean = this.consolidatedResolution, cachedResolution: Boolean = this.cachedResolution, - aetherResolution: Boolean = this.aetherResolution): UpdateOptions = + resolverConverter: UpdateOptions.ResolverConverter = this.resolverConverter): UpdateOptions = new UpdateOptions(circularDependencyLevel, latestSnapshots, consolidatedResolution, cachedResolution, - aetherResolution) + resolverConverter) override def equals(o: Any): Boolean = o match { case o: UpdateOptions => this.circularDependencyLevel == o.circularDependencyLevel && this.latestSnapshots == o.latestSnapshots && - this.cachedResolution == o.cachedResolution + this.cachedResolution == o.cachedResolution && + this.resolverConverter == o.resolverConverter case _ => false } @@ -63,17 +64,19 @@ final class UpdateOptions private[sbt] ( hash = hash * 31 + this.circularDependencyLevel.## hash = hash * 31 + this.latestSnapshots.## hash = hash * 31 + this.cachedResolution.## + hash = hash * 31 + this.resolverConverter.## hash } } object UpdateOptions { + type ResolverConverter = PartialFunction[(Resolver, IvySettings, Logger), DependencyResolver] + def apply(): UpdateOptions = new UpdateOptions( circularDependencyLevel = CircularDependencyLevel.Warn, latestSnapshots = false, consolidatedResolution = false, cachedResolution = false, - // TODO - Disable this before release, but make sure test suite passes with it on. - aetherResolution = true) + resolverConverter = PartialFunction.empty) } diff --git a/ivy/src/main/scala/sbt/ivyint/CustomMavenResolver.scala b/ivy/src/main/scala/sbt/ivyint/CustomMavenResolver.scala new file mode 100644 index 000000000..e3e41148e --- /dev/null +++ b/ivy/src/main/scala/sbt/ivyint/CustomMavenResolver.scala @@ -0,0 +1,11 @@ +package sbt +package ivyint + +import org.apache.ivy.plugins.resolver.DependencyResolver + +// These are placeholder traits for sbt-aether-resolver +trait CustomMavenResolver extends DependencyResolver { +} +trait CustomRemoteMavenResolver extends CustomMavenResolver { + def repo: MavenRepository +} diff --git a/ivy/src/main/scala/sbt/ivyint/SbtChainResolver.scala b/ivy/src/main/scala/sbt/ivyint/SbtChainResolver.scala index 13c2642ec..08c8f00e7 100644 --- a/ivy/src/main/scala/sbt/ivyint/SbtChainResolver.scala +++ b/ivy/src/main/scala/sbt/ivyint/SbtChainResolver.scala @@ -184,7 +184,7 @@ private[sbt] case class SbtChainResolver( val artifactOpt = findFirstArtifactRef(rmr.getDescriptor, dd, data, resolver) artifactOpt match { case None if resolver.getName == "inter-project" => // do nothing - case None if resolver.isInstanceOf[AbstractMavenRepositoryResolver] => + case None if resolver.isInstanceOf[CustomMavenResolver] => // do nothing for now.... // We want to see if the maven caching is sufficient and we do not need to duplicate within the ivy cache... case None => throw new RuntimeException(s"\t${resolver.getName}: no ivy file nor artifact found for $rmr") diff --git a/ivy/src/main/scala/org/apache/ivy/plugins/resolver/MavenRepositoryResolver.scala b/sbt-maven-resolver/src/main/scala/org/apache/ivy/plugins/resolver/MavenRepositoryResolver.scala similarity index 99% rename from ivy/src/main/scala/org/apache/ivy/plugins/resolver/MavenRepositoryResolver.scala rename to sbt-maven-resolver/src/main/scala/org/apache/ivy/plugins/resolver/MavenRepositoryResolver.scala index 6ff019c6a..a5336ad3b 100644 --- a/ivy/src/main/scala/org/apache/ivy/plugins/resolver/MavenRepositoryResolver.scala +++ b/sbt-maven-resolver/src/main/scala/org/apache/ivy/plugins/resolver/MavenRepositoryResolver.scala @@ -30,6 +30,7 @@ import org.eclipse.aether.deployment.{ DeployRequest => AetherDeployRequest } import org.eclipse.aether.installation.{ InstallRequest => AetherInstallRequest } import org.apache.ivy.core.cache.{ ModuleDescriptorWriter, ArtifactOrigin } import sbt.{ MavenCache, MavenRepository } +import sbt.ivyint.{ CustomMavenResolver, CustomRemoteMavenResolver } import scala.collection.JavaConverters._ object MavenRepositoryResolver { @@ -60,7 +61,8 @@ object MavenRepositoryResolver { * Note: This creates its *own* local cache directory for cache metadata. using its name. * */ -class MavenRemoteRepositoryResolver(val repo: MavenRepository, settings: IvySettings) extends AbstractMavenRepositoryResolver(settings) { +class MavenRemoteRepositoryResolver(val repo: MavenRepository, settings: IvySettings) + extends AbstractMavenRepositoryResolver(settings) with CustomRemoteMavenResolver { setName(repo.name) override def toString = s"${repo.name}: ${repo.root}" protected val system = MavenRepositorySystemFactory.newRepositorySystemImpl @@ -136,7 +138,8 @@ class MavenRemoteRepositoryResolver(val repo: MavenRepository, settings: IvySett * * Note: This should never hit somethign remote, as it just looks in the maven cache for things already resolved. */ -class MavenCacheRepositoryResolver(val repo: MavenCache, settings: IvySettings) extends AbstractMavenRepositoryResolver(settings) { +class MavenCacheRepositoryResolver(val repo: MavenCache, settings: IvySettings) + extends AbstractMavenRepositoryResolver(settings) with CustomMavenResolver { setName(repo.name) protected val system = MavenRepositorySystemFactory.newRepositorySystemImpl sbt.IO.createDirectory(repo.rootFile) diff --git a/ivy/src/main/scala/org/apache/ivy/plugins/resolver/MavenRepositorySystemFactory.scala b/sbt-maven-resolver/src/main/scala/org/apache/ivy/plugins/resolver/MavenRepositorySystemFactory.scala similarity index 100% rename from ivy/src/main/scala/org/apache/ivy/plugins/resolver/MavenRepositorySystemFactory.scala rename to sbt-maven-resolver/src/main/scala/org/apache/ivy/plugins/resolver/MavenRepositorySystemFactory.scala diff --git a/ivy/src/main/scala/org/apache/maven/repository/internal/SbtArtifactDescriptorReader.java b/sbt-maven-resolver/src/main/scala/org/apache/maven/repository/internal/SbtArtifactDescriptorReader.java similarity index 100% rename from ivy/src/main/scala/org/apache/maven/repository/internal/SbtArtifactDescriptorReader.java rename to sbt-maven-resolver/src/main/scala/org/apache/maven/repository/internal/SbtArtifactDescriptorReader.java diff --git a/ivy/src/main/scala/org/apache/maven/repository/internal/SbtExtraProperties.java b/sbt-maven-resolver/src/main/scala/org/apache/maven/repository/internal/SbtExtraProperties.java similarity index 100% rename from ivy/src/main/scala/org/apache/maven/repository/internal/SbtExtraProperties.java rename to sbt-maven-resolver/src/main/scala/org/apache/maven/repository/internal/SbtExtraProperties.java diff --git a/ivy/src/main/scala/org/apache/maven/repository/internal/SbtRepositoryLayout.scala b/sbt-maven-resolver/src/main/scala/org/apache/maven/repository/internal/SbtRepositoryLayout.scala similarity index 100% rename from ivy/src/main/scala/org/apache/maven/repository/internal/SbtRepositoryLayout.scala rename to sbt-maven-resolver/src/main/scala/org/apache/maven/repository/internal/SbtRepositoryLayout.scala diff --git a/sbt-maven-resolver/src/main/scala/sbt/MavenResolverConverter.scala b/sbt-maven-resolver/src/main/scala/sbt/MavenResolverConverter.scala new file mode 100644 index 000000000..7f527c813 --- /dev/null +++ b/sbt-maven-resolver/src/main/scala/sbt/MavenResolverConverter.scala @@ -0,0 +1,13 @@ +package sbt + +import UpdateOptions.ResolverConverter +import org.apache.ivy.plugins.resolver.{ MavenCacheRepositoryResolver, MavenRemoteRepositoryResolver } + +object MavenResolverConverter { + val converter: ResolverConverter = { + case (cache: MavenCache, settings, log) => + new MavenCacheRepositoryResolver(cache, settings) + case (repo: MavenRepository, settings, log) => + new MavenRemoteRepositoryResolver(repo, settings) + } +} diff --git a/sbt-maven-resolver/src/main/scala/sbt/plugins/MavenResolverPlugin.scala b/sbt-maven-resolver/src/main/scala/sbt/plugins/MavenResolverPlugin.scala new file mode 100644 index 000000000..df166e568 --- /dev/null +++ b/sbt-maven-resolver/src/main/scala/sbt/plugins/MavenResolverPlugin.scala @@ -0,0 +1,13 @@ +package sbt +package plugins + +import Keys._ + +object MavenResolverPlugin extends AutoPlugin { + override def requires = IvyPlugin + override def trigger = allRequirements + + override lazy val projectSettings: Seq[Setting[_]] = Seq( + updateOptions := updateOptions.value.withResolverConverter(MavenResolverConverter.converter) + ) +} diff --git a/sbt/src/sbt-test/dependency-management/mvn-local/build.sbt b/sbt/src/sbt-test/dependency-management/mvn-local/build.sbt index 65715e00d..10b0d8003 100644 --- a/sbt/src/sbt-test/dependency-management/mvn-local/build.sbt +++ b/sbt/src/sbt-test/dependency-management/mvn-local/build.sbt @@ -14,14 +14,13 @@ lazy val main = project. libraryDependencies += (projectID in library).value, fullResolvers := fullResolvers.value.filterNot(_.name == "inter-project"), // TODO - should this not be needed? - updateOptions := updateOptions.value.withLatestSnapshots(true).withAetherResolution(true) + updateOptions := updateOptions.value.withLatestSnapshots(true) ) lazy val library = project. settings(commonSettings: _*). settings( - uniqueName, - updateOptions := updateOptions.value.withAetherResolution(true) + uniqueName ) def uniqueName = diff --git a/sbt/src/sbt-test/dependency-management/mvn-local/project/plugin.sbt b/sbt/src/sbt-test/dependency-management/mvn-local/project/plugin.sbt new file mode 100644 index 000000000..1ae548913 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/mvn-local/project/plugin.sbt @@ -0,0 +1,2 @@ +libraryDependencies += Defaults.sbtPluginExtra("org.scala-sbt" % "sbt-maven-resolver" % sbtVersion.value, + sbtBinaryVersion.value, scalaBinaryVersion.value)