mirror of https://github.com/sbt/sbt.git
Merge pull request #1944 from sbt/wip/fix-aether-range-query
Wip/fix aether range query
This commit is contained in:
commit
289162a301
|
|
@ -21,8 +21,61 @@ 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
|
||||
object MakePom {
|
||||
/** True if the revision is an ivy-range, not a complete revision. */
|
||||
def isDependencyVersionRange(revision: String): Boolean = {
|
||||
(revision endsWith "+") ||
|
||||
(revision contains "[") ||
|
||||
(revision contains "]") ||
|
||||
(revision contains "(") ||
|
||||
(revision contains ")")
|
||||
}
|
||||
|
||||
/** Converts Ivy revision ranges to that of Maven POM */
|
||||
def makeDependencyVersion(revision: String): String = {
|
||||
def plusRange(s: String, shift: Int = 0) = {
|
||||
def pow(i: Int): Int = if (i > 0) 10 * pow(i - 1) else 1
|
||||
val (prefixVersion, lastVersion) = (s + "0" * shift).reverse.split("\\.", 2) match {
|
||||
case Array(revLast, revRest) =>
|
||||
(revRest.reverse + ".", revLast.reverse)
|
||||
case Array(revLast) => ("", revLast.reverse)
|
||||
}
|
||||
val lastVersionInt = lastVersion.toInt
|
||||
s"[${prefixVersion}${lastVersion},${prefixVersion}${lastVersionInt + pow(shift)})"
|
||||
}
|
||||
val startSym = Set(']', '[', '(')
|
||||
val stopSym = Set(']', '[', ')')
|
||||
val DotPlusPattern = """(.+)\.\+""".r
|
||||
val DotNumPlusPattern = """(.+)\.(\d+)\+""".r
|
||||
val NumPlusPattern = """(\d+)\+""".r
|
||||
val maxDigit = 5
|
||||
try {
|
||||
revision match {
|
||||
case "+" => "[0,)"
|
||||
case DotPlusPattern(base) => plusRange(base)
|
||||
// This is a heuristic. Maven just doesn't support Ivy's notions of 1+, so
|
||||
// we assume version ranges never go beyond 5 siginificant digits.
|
||||
case NumPlusPattern(tail) => (0 until maxDigit).map(plusRange(tail, _)).mkString(",")
|
||||
case DotNumPlusPattern(base, tail) => (0 until maxDigit).map(plusRange(base + "." + tail, _)).mkString(",")
|
||||
case rev if rev endsWith "+" => sys.error(s"dynamic revision '$rev' cannot be translated to POM")
|
||||
case rev if startSym(rev(0)) && stopSym(rev(rev.length - 1)) =>
|
||||
val start = rev(0)
|
||||
val stop = rev(rev.length - 1)
|
||||
val mid = rev.substring(1, rev.length - 1)
|
||||
(if (start == ']') "(" else start) + mid + (if (stop == '[') ")" else stop)
|
||||
case _ => revision
|
||||
}
|
||||
} catch {
|
||||
case e: NumberFormatException =>
|
||||
// TODO - if the version doesn't meet our expectations, maybe we just issue a hard
|
||||
// error instead of softly ignoring the attempt to rewrite.
|
||||
//sys.error(s"Could not fix version [$revision] into maven style version")
|
||||
revision
|
||||
}
|
||||
}
|
||||
}
|
||||
class MakePom(val log: Logger) {
|
||||
import MakePom._
|
||||
@deprecated("Use `write(Ivy, ModuleDescriptor, ModuleInfo, Option[Iterable[Configuration]], Set[String], NodeSeq, XNode => XNode, MavenRepository => Boolean, Boolean, File)` instead", "0.11.2")
|
||||
def write(ivy: Ivy, module: ModuleDescriptor, moduleInfo: ModuleInfo, configurations: Option[Iterable[Configuration]], extra: NodeSeq, process: XNode => XNode, filterRepositories: MavenRepository => Boolean, allRepositories: Boolean, output: File): Unit =
|
||||
write(ivy, module, moduleInfo: ModuleInfo, configurations: Option[Iterable[Configuration]], Set(Artifact.DefaultType), extra, process, filterRepositories, allRepositories, output)
|
||||
|
|
@ -218,49 +271,6 @@ class MakePom(val log: Logger) {
|
|||
</dependency>
|
||||
}
|
||||
|
||||
/** Converts Ivy revision ranges to that of Maven POM */
|
||||
def makeDependencyVersion(revision: String): String = {
|
||||
def plusRange(s: String, shift: Int = 0) = {
|
||||
def pow(i: Int): Int = if (i > 0) 10 * pow(i - 1) else 1
|
||||
val (prefixVersion, lastVersion) = (s + "0" * shift).reverse.split("\\.", 2) match {
|
||||
case Array(revLast, revRest) =>
|
||||
(revRest.reverse + ".", revLast.reverse)
|
||||
case Array(revLast) => ("", revLast.reverse)
|
||||
}
|
||||
val lastVersionInt = lastVersion.toInt
|
||||
s"[${prefixVersion}${lastVersion},${prefixVersion}${lastVersionInt + pow(shift)})"
|
||||
}
|
||||
val startSym = Set(']', '[', '(')
|
||||
val stopSym = Set(']', '[', ')')
|
||||
val DotPlusPattern = """(.+)\.\+""".r
|
||||
val DotNumPlusPattern = """(.+)\.(\d+)\+""".r
|
||||
val NumPlusPattern = """(\d+)\+""".r
|
||||
val maxDigit = 5
|
||||
try {
|
||||
revision match {
|
||||
case "+" => "[0,)"
|
||||
case DotPlusPattern(base) => plusRange(base)
|
||||
// This is a heuristic. Maven just doesn't support Ivy's notions of 1+, so
|
||||
// we assume version ranges never go beyond 5 siginificant digits.
|
||||
case NumPlusPattern(tail) => (0 until maxDigit).map(plusRange(tail, _)).mkString(",")
|
||||
case DotNumPlusPattern(base, tail) => (0 until maxDigit).map(plusRange(base + "." + tail, _)).mkString(",")
|
||||
case rev if rev endsWith "+" => sys.error(s"dynamic revision '$rev' cannot be translated to POM")
|
||||
case rev if startSym(rev(0)) && stopSym(rev(rev.length - 1)) =>
|
||||
val start = rev(0)
|
||||
val stop = rev(rev.length - 1)
|
||||
val mid = rev.substring(1, rev.length - 1)
|
||||
(if (start == ']') "(" else start) + mid + (if (stop == '[') ")" else stop)
|
||||
case _ => revision
|
||||
}
|
||||
} catch {
|
||||
case e: NumberFormatException =>
|
||||
// TODO - if the version doesn't meet our expectations, maybe we just issue a hard
|
||||
// error instead of softly ignoring the attempt to rewrite.
|
||||
//sys.error(s"Could not fix version [$revision] into maven style version")
|
||||
revision
|
||||
}
|
||||
}
|
||||
|
||||
@deprecated("No longer used and will be removed.", "0.12.1")
|
||||
def classifier(dependency: DependencyDescriptor, includeTypes: Set[String]): NodeSeq =
|
||||
{
|
||||
|
|
|
|||
|
|
@ -61,10 +61,10 @@ class MakePomSpec extends Specification {
|
|||
|
||||
val mp = new MakePom(ConsoleLogger())
|
||||
def convertTo(s: String, expected: String) =
|
||||
mp.makeDependencyVersion(s) must_== expected
|
||||
MakePom.makeDependencyVersion(s) must_== expected
|
||||
def beParsedAsError(s: String) =
|
||||
try {
|
||||
mp.makeDependencyVersion(s)
|
||||
MakePom.makeDependencyVersion(s)
|
||||
failure
|
||||
} catch {
|
||||
case e: Throwable => success
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ import org.eclipse.aether.metadata.{ DefaultMetadata, Metadata }
|
|||
import org.eclipse.aether.resolution.{
|
||||
ArtifactDescriptorRequest => AetherDescriptorRequest,
|
||||
ArtifactRequest => AetherArtifactRequest,
|
||||
MetadataRequest => AetherMetadataRequest
|
||||
MetadataRequest => AetherMetadataRequest,
|
||||
VersionRequest => AetherVersionRequest,
|
||||
VersionRangeRequest => AetherVersionRangeRequest
|
||||
}
|
||||
import sbt.ivyint.CustomMavenResolver
|
||||
|
||||
|
|
@ -29,6 +31,8 @@ class MavenCacheRepositoryResolver(val repo: MavenCache, settings: IvySettings)
|
|||
protected def setRepository(request: AetherMetadataRequest): AetherMetadataRequest = request
|
||||
protected def addRepositories(request: AetherDescriptorRequest): AetherDescriptorRequest = request
|
||||
protected def addRepositories(request: AetherArtifactRequest): AetherArtifactRequest = request
|
||||
protected def addRepositories(request: AetherVersionRequest): AetherVersionRequest = request
|
||||
protected def addRepositories(request: AetherVersionRangeRequest): AetherVersionRangeRequest = request
|
||||
protected def publishArtifacts(artifacts: Seq[AetherArtifact]): Unit = {
|
||||
val request = new AetherInstallRequest()
|
||||
artifacts foreach request.addArtifact
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ import org.eclipse.aether.resolution.{
|
|||
ArtifactDescriptorRequest => AetherDescriptorRequest,
|
||||
ArtifactDescriptorResult => AetherDescriptorResult,
|
||||
ArtifactRequest => AetherArtifactRequest,
|
||||
MetadataRequest => AetherMetadataRequest
|
||||
MetadataRequest => AetherMetadataRequest,
|
||||
VersionRequest => AetherVersionRequest,
|
||||
VersionRangeRequest => AetherVersionRangeRequest
|
||||
}
|
||||
import sbt.ivyint.CustomRemoteMavenResolver
|
||||
import scala.collection.JavaConverters._
|
||||
|
|
@ -43,6 +45,11 @@ class MavenRemoteRepositoryResolver(val repo: MavenRepository, settings: IvySett
|
|||
if (isUseCacheOnly) request else request.addRepository(aetherRepository)
|
||||
protected def addRepositories(request: AetherArtifactRequest): AetherArtifactRequest =
|
||||
if (isUseCacheOnly) request else request.addRepository(aetherRepository)
|
||||
protected def addRepositories(request: AetherVersionRequest): AetherVersionRequest =
|
||||
if (isUseCacheOnly) request else request.addRepository(aetherRepository)
|
||||
protected def addRepositories(request: AetherVersionRangeRequest): AetherVersionRangeRequest =
|
||||
if (isUseCacheOnly) request else request.addRepository(aetherRepository)
|
||||
|
||||
/** Actually publishes aether artifacts. */
|
||||
protected def publishArtifacts(artifacts: Seq[AetherArtifact]): Unit = {
|
||||
val request = new AetherDeployRequest()
|
||||
|
|
|
|||
|
|
@ -20,7 +20,15 @@ import org.eclipse.aether.artifact.{ DefaultArtifact => AetherArtifact }
|
|||
import org.eclipse.aether.deployment.{ DeployRequest => AetherDeployRequest }
|
||||
import org.eclipse.aether.installation.{ InstallRequest => AetherInstallRequest }
|
||||
import org.eclipse.aether.metadata.{ DefaultMetadata, Metadata }
|
||||
import org.eclipse.aether.resolution.{ ArtifactDescriptorRequest => AetherDescriptorRequest, ArtifactDescriptorResult => AetherDescriptorResult, ArtifactRequest => AetherArtifactRequest, ArtifactResolutionException, MetadataRequest => AetherMetadataRequest }
|
||||
import org.eclipse.aether.resolution.{
|
||||
ArtifactDescriptorRequest => AetherDescriptorRequest,
|
||||
ArtifactDescriptorResult => AetherDescriptorResult,
|
||||
ArtifactRequest => AetherArtifactRequest,
|
||||
ArtifactResolutionException,
|
||||
MetadataRequest => AetherMetadataRequest,
|
||||
VersionRequest => AetherVersionRequest,
|
||||
VersionRangeRequest => AetherVersionRangeRequest
|
||||
}
|
||||
import org.eclipse.aether.{ RepositorySystem, RepositorySystemSession }
|
||||
import sbt.ivyint.{ CustomMavenResolver, CustomRemoteMavenResolver }
|
||||
import sbt.mavenint.MavenRepositoryResolver.JarPackaging
|
||||
|
|
@ -67,6 +75,8 @@ abstract class MavenRepositoryResolver(settings: IvySettings) extends AbstractRe
|
|||
/** Inject necessary repositories into a descriptor request. */
|
||||
protected def addRepositories(request: AetherDescriptorRequest): AetherDescriptorRequest
|
||||
protected def addRepositories(request: AetherArtifactRequest): AetherArtifactRequest
|
||||
protected def addRepositories(request: AetherVersionRequest): AetherVersionRequest
|
||||
protected def addRepositories(request: AetherVersionRangeRequest): AetherVersionRangeRequest
|
||||
|
||||
/** Actually publishes aether artifacts. */
|
||||
protected def publishArtifacts(artifacts: Seq[AetherArtifact]): Unit
|
||||
|
|
@ -105,29 +115,49 @@ abstract class MavenRepositoryResolver(settings: IvySettings) extends AbstractRe
|
|||
override def getDependency(dd: DependencyDescriptor, rd: ResolveData): ResolvedModuleRevision = {
|
||||
val context = IvyContext.pushNewCopyContext
|
||||
try {
|
||||
val drid: ModuleRevisionId =
|
||||
if (sbt.MakePom.isDependencyVersionRange(dd.getDependencyRevisionId.getRevision)) {
|
||||
Message.debug(s"Got a dynamic revision, attempting to convert to real revision: ${dd.getDependencyRevisionId}")
|
||||
val revision = sbt.MakePom.makeDependencyVersion(dd.getDependencyRevisionId.getRevision)
|
||||
// TODO - Alter revision id to be maven-friendly first.
|
||||
val coords =
|
||||
s"${dd.getDependencyRevisionId.getOrganisation}:${aetherArtifactIdFromMrid(dd.getDependencyRevisionId)}:${revision}"
|
||||
//val coords = aetherCoordsFromMrid(dd.getDependencyRevisionId)
|
||||
Message.debug(s"Aether about to resolve version for [$coords]...")
|
||||
val versionRequest = addRepositories(new AetherVersionRangeRequest().setArtifact(new AetherArtifact(coords, getArtifactProperties(dd.getDependencyRevisionId))))
|
||||
val result = system.resolveVersionRange(session, versionRequest)
|
||||
Message.debug(s"Version result = $result, from $getName")
|
||||
if (result.getVersions.isEmpty) throw new MavenResolutionException(s"Did not find any versions for $dd")
|
||||
ModuleRevisionId.newInstance(
|
||||
dd.getDependencyRevisionId.getOrganisation,
|
||||
dd.getDependencyRevisionId.getName,
|
||||
result.getHighestVersion.toString,
|
||||
dd.getExtraAttributes)
|
||||
} else dd.getDependencyRevisionId
|
||||
|
||||
// TODO - Check to see if we're asking for latest.* version, and if so, we should run a latest version query
|
||||
// first and use that result to return the metadata/final module.
|
||||
Message.debug(s"Requesting conf [${dd.getModuleConfigurations.mkString(",")}] from Aether module ${dd.getDependencyRevisionId} in resolver ${getName}")
|
||||
Message.debug(s"Requesting conf [${dd.getModuleConfigurations.mkString(",")}] from Aether module ${drid} in resolver ${getName}")
|
||||
val request = new AetherDescriptorRequest()
|
||||
val coords = aetherCoordsFromMrid(dd.getDependencyRevisionId)
|
||||
val coords = aetherCoordsFromMrid(drid)
|
||||
Message.debug(s"Aether about to resolve [$coords]...")
|
||||
request.setArtifact(new AetherArtifact(coords, getArtifactProperties(dd.getDependencyRevisionId)))
|
||||
request.setArtifact(new AetherArtifact(coords, getArtifactProperties(drid)))
|
||||
addRepositories(request)
|
||||
val result = system.readArtifactDescriptor(session, request)
|
||||
val packaging = getPackagingFromPomProperties(result.getProperties)
|
||||
Message.debug(s"Aether resolved ${dd.getDependencyId} w/ packaging ${packaging}")
|
||||
|
||||
// TODO - better pub date if we have no metadata.
|
||||
val lastModifiedTime = getPublicationTime(dd.getDependencyRevisionId) getOrElse 0L
|
||||
val lastModifiedTime = getPublicationTime(drid) getOrElse 0L
|
||||
|
||||
// Construct a new Ivy module descriptor
|
||||
val desc: ModuleDescriptor = {
|
||||
// TODO - Better detection of snapshot and handling latest.integration/latest.snapshot
|
||||
val status =
|
||||
if (dd.getDependencyRevisionId.getRevision.endsWith("-SNAPSHOT")) "integration"
|
||||
if (drid.getRevision.endsWith("-SNAPSHOT")) "integration"
|
||||
else "release"
|
||||
val md =
|
||||
new DefaultModuleDescriptor(dd.getDependencyRevisionId, status, null /* pubDate */ , false)
|
||||
new DefaultModuleDescriptor(drid, status, null /* pubDate */ , false)
|
||||
//DefaultModuleDescriptor.newDefaultInstance(dd.getDependencyRevisionId)
|
||||
// Here we add the standard configurations
|
||||
for (config <- PomModuleDescriptorBuilder.MAVEN2_CONFIGURATIONS) {
|
||||
|
|
@ -136,7 +166,8 @@ abstract class MavenRepositoryResolver(settings: IvySettings) extends AbstractRe
|
|||
|
||||
// Here we look into the artifacts specified from the dependency descriptor *and* those that are defaulted,
|
||||
// and append them to the appropriate configurations.
|
||||
addArtifactsFromPom(dd, packaging, md, lastModifiedTime)
|
||||
// TODO - Feed correct revision down here
|
||||
addArtifactsFromPom(drid, dd, packaging, md, lastModifiedTime)
|
||||
// Here we add dependencies.
|
||||
addDependenciesFromAether(result, md)
|
||||
// Here we use pom.xml Dependency management section to create Ivy dependency mediators.
|
||||
|
|
@ -157,7 +188,7 @@ abstract class MavenRepositoryResolver(settings: IvySettings) extends AbstractRe
|
|||
}
|
||||
|
||||
// Here we need to pretend we downloaded the pom.xml file
|
||||
val pom = DefaultArtifact.newPomArtifact(dd.getDependencyRevisionId, new java.util.Date(lastModifiedTime))
|
||||
val pom = DefaultArtifact.newPomArtifact(drid, new java.util.Date(lastModifiedTime))
|
||||
val madr = new MetadataArtifactDownloadReport(pom)
|
||||
madr.setSearched(true)
|
||||
madr.setDownloadStatus(DownloadStatus.SUCCESSFUL) // TODO - Figure this things out for this report.
|
||||
|
|
@ -223,13 +254,13 @@ abstract class MavenRepositoryResolver(settings: IvySettings) extends AbstractRe
|
|||
}
|
||||
|
||||
/** Determines which artifacts are associated with this maven module and appends them to the descriptor. */
|
||||
def addArtifactsFromPom(dd: DependencyDescriptor, packaging: String, md: DefaultModuleDescriptor, lastModifiedTime: Long): Unit = {
|
||||
def addArtifactsFromPom(drid: ModuleRevisionId, dd: DependencyDescriptor, packaging: String, md: DefaultModuleDescriptor, lastModifiedTime: Long): Unit = {
|
||||
Message.debug(s"Calculating artifacts for ${dd.getDependencyId} w/ packaging $packaging")
|
||||
// Here we add in additional artifact requests, which ALLWAYS have to be explicit since
|
||||
// Maven/Aether doesn't include all known artifacts in a pom.xml
|
||||
// TODO - This does not appear to be working correctly.
|
||||
if (dd.getAllDependencyArtifacts.isEmpty) {
|
||||
val artifactId = s"${dd.getDependencyId.getName}-${dd.getDependencyRevisionId.getRevision}"
|
||||
if (dd.getAllDependencyArtifacts.isEmpty) {
|
||||
val artifactId = s"${drid.getName}-${drid.getRevision}"
|
||||
// Add the artifacts we know about the module
|
||||
packaging match {
|
||||
case "pom" =>
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ import org.apache.ivy.plugins.repository.Resource
|
|||
import org.apache.ivy.plugins.repository.url.URLResource
|
||||
import org.apache.ivy.util.Message
|
||||
import org.apache.ivy.util.url.URLHandlerRegistry
|
||||
import org.apache.maven.repository.internal.{ MavenRepositorySystemUtils, SbtArtifactDescriptorReader, SnapshotMetadataGeneratorFactory, VersionsMetadataGeneratorFactory }
|
||||
import org.apache.maven.repository.internal.{ MavenRepositorySystemUtils, SbtArtifactDescriptorReader, SnapshotMetadataGeneratorFactory, VersionsMetadataGeneratorFactory, DefaultVersionResolver }
|
||||
import org.eclipse.aether.{ RepositorySystem, RepositorySystemSession }
|
||||
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory
|
||||
import org.eclipse.aether.impl.{ ArtifactDescriptorReader, DefaultServiceLocator, MetadataGeneratorFactory }
|
||||
import org.eclipse.aether.impl.{ ArtifactDescriptorReader, DefaultServiceLocator, MetadataGeneratorFactory, VersionResolver }
|
||||
import org.eclipse.aether.repository.{ LocalRepository, RemoteRepository }
|
||||
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory
|
||||
import org.eclipse.aether.spi.connector.layout.RepositoryLayoutFactory
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
organization := "com.test"
|
||||
name := "maven-version-range-bug"
|
||||
version := "1.0.0-SNAPSHOT"
|
||||
scalaVersion := "2.11.6"
|
||||
libraryDependencies += "com.amazonaws" % "aws-java-sdk" % "1.7.8.1"
|
||||
|
|
@ -0,0 +1 @@
|
|||
> update
|
||||
Loading…
Reference in New Issue