From 7f808721715857b6f9503dd2e65e710ed762e3ed Mon Sep 17 00:00:00 2001 From: Josh Suereth Date: Thu, 26 Mar 2015 16:09:29 -0400 Subject: [PATCH 1/2] Fixes #1921. * Add version range query (if needed) before resolving artifact in Aether. * Ensure detected version is used after having a version range query. --- ivy/src/main/scala/sbt/MakePom.scala | 96 +++++++++++++++------------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/ivy/src/main/scala/sbt/MakePom.scala b/ivy/src/main/scala/sbt/MakePom.scala index 072a1a055..d0e1a2741 100644 --- a/ivy/src/main/scala/sbt/MakePom.scala +++ b/ivy/src/main/scala/sbt/MakePom.scala @@ -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) { } - /** 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 = { From 07731e68f51005b91d1f0bebe369ab2fe28847d2 Mon Sep 17 00:00:00 2001 From: Josh Suereth Date: Fri, 27 Mar 2015 07:51:37 -0400 Subject: [PATCH 2/2] Fix unit test for makepom. --- ivy/src/test/scala/MakePomSpec.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ivy/src/test/scala/MakePomSpec.scala b/ivy/src/test/scala/MakePomSpec.scala index 3310ed62b..68ede8bc8 100644 --- a/ivy/src/test/scala/MakePomSpec.scala +++ b/ivy/src/test/scala/MakePomSpec.scala @@ -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