Additional options for Ivy resolvers.

Specify an Ivy resolver with ", descriptorOptional" to make Ivy
descriptor files optional for that repository or with
", skipConsistencyCheck" to disable Ivy consistency checks for
that repository.
This commit is contained in:
William Benton 2013-08-13 16:10:59 -05:00 committed by Mark Harrah
parent e3ee1a9ac4
commit 2a3462ac12
8 changed files with 53 additions and 22 deletions

View File

@ -76,6 +76,7 @@ private object ConvertResolver
case repo: RawRepository => repo.resolver case repo: RawRepository => repo.resolver
} }
} }
private sealed trait DescriptorRequired extends BasicResolver private sealed trait DescriptorRequired extends BasicResolver
{ {
override def getDependency(dd: DependencyDescriptor, data: ResolveData) = override def getDependency(dd: DependencyDescriptor, data: ResolveData) =
@ -122,6 +123,8 @@ private object ConvertResolver
private def initializePatterns(resolver: AbstractPatternsBasedResolver, patterns: Patterns, settings: IvySettings) private def initializePatterns(resolver: AbstractPatternsBasedResolver, patterns: Patterns, settings: IvySettings)
{ {
resolver.setM2compatible(patterns.isMavenCompatible) resolver.setM2compatible(patterns.isMavenCompatible)
resolver.setDescriptor(if (patterns.descriptorOptional) BasicResolver.DESCRIPTOR_OPTIONAL else BasicResolver.DESCRIPTOR_REQUIRED)
resolver.setCheckconsistency(!patterns.skipConsistencyCheck)
patterns.ivyPatterns.foreach(p => resolver.addIvyPattern(settings substitute p)) patterns.ivyPatterns.foreach(p => resolver.addIvyPattern(settings substitute p))
patterns.artifactPatterns.foreach(p => resolver.addArtifactPattern(settings substitute p)) patterns.artifactPatterns.foreach(p => resolver.addArtifactPattern(settings substitute p))
} }

View File

@ -23,20 +23,23 @@ sealed case class MavenRepository(name: String, root: String) extends Resolver
override def toString = name + ": " + root override def toString = name + ": " + root
} }
final class Patterns(val ivyPatterns: Seq[String], val artifactPatterns: Seq[String], val isMavenCompatible: Boolean) final class Patterns(val ivyPatterns: Seq[String], val artifactPatterns: Seq[String], val isMavenCompatible: Boolean, val descriptorOptional: Boolean, val skipConsistencyCheck: Boolean)
{ {
private[sbt] def mavenStyle(): Patterns = Patterns(ivyPatterns, artifactPatterns, true) private[sbt] def mavenStyle(): Patterns = Patterns(ivyPatterns, artifactPatterns, true)
private[sbt] def withIvys(patterns: Seq[String]): Patterns = Patterns(patterns ++ ivyPatterns, artifactPatterns, isMavenCompatible) private[sbt] def withIvys(patterns: Seq[String]): Patterns = Patterns(patterns ++ ivyPatterns, artifactPatterns, isMavenCompatible)
private[sbt] def withArtifacts(patterns: Seq[String]): Patterns = Patterns(ivyPatterns, patterns ++ artifactPatterns, isMavenCompatible) private[sbt] def withArtifacts(patterns: Seq[String]): Patterns = Patterns(ivyPatterns, patterns ++ artifactPatterns, isMavenCompatible)
override def toString = "Patterns(ivyPatterns=%s, artifactPatterns=%s, isMavenCompatible=%s)".format(ivyPatterns, artifactPatterns, isMavenCompatible) override def toString = "Patterns(ivyPatterns=%s, artifactPatterns=%s, isMavenCompatible=%s, descriptorOptional=%s, skipConsistencyCheck=%s)".format(ivyPatterns, artifactPatterns, isMavenCompatible, descriptorOptional, skipConsistencyCheck)
override def equals(obj: Any): Boolean = { override def equals(obj: Any): Boolean = {
obj match { obj match {
case other: Patterns => case other: Patterns =>
ivyPatterns == other.ivyPatterns && artifactPatterns == other.artifactPatterns && isMavenCompatible == other.isMavenCompatible ivyPatterns == other.ivyPatterns && artifactPatterns == other.artifactPatterns && isMavenCompatible == other.isMavenCompatible && descriptorOptional == other.descriptorOptional && skipConsistencyCheck == other.skipConsistencyCheck
case _ => false case _ => false
} }
} }
override def hashCode: Int = (ivyPatterns, artifactPatterns, isMavenCompatible).hashCode override def hashCode: Int = (ivyPatterns, artifactPatterns, isMavenCompatible, descriptorOptional, skipConsistencyCheck).hashCode
@deprecated
def this(ivyPatterns: Seq[String], artifactPatterns: Seq[String], isMavenCompatible: Boolean) = this(ivyPatterns, artifactPatterns, isMavenCompatible, false, false)
} }
object Patterns object Patterns
{ {
@ -44,7 +47,7 @@ object Patterns
def apply(artifactPatterns: String*): Patterns = Patterns(true, artifactPatterns : _*) def apply(artifactPatterns: String*): Patterns = Patterns(true, artifactPatterns : _*)
def apply(isMavenCompatible: Boolean, artifactPatterns: String*): Patterns = Patterns(artifactPatterns, artifactPatterns, isMavenCompatible) def apply(isMavenCompatible: Boolean, artifactPatterns: String*): Patterns = Patterns(artifactPatterns, artifactPatterns, isMavenCompatible)
def apply(ivyPatterns: Seq[String], artifactPatterns: Seq[String], isMavenCompatible: Boolean): Patterns = new Patterns(ivyPatterns, artifactPatterns, isMavenCompatible) def apply(ivyPatterns: Seq[String], artifactPatterns: Seq[String], isMavenCompatible: Boolean, descriptorOptional: Boolean = false, skipConsistencyCheck: Boolean = false): Patterns = new Patterns(ivyPatterns, artifactPatterns, isMavenCompatible, descriptorOptional, skipConsistencyCheck)
} }
object RepositoryHelpers object RepositoryHelpers
{ {

View File

@ -9,4 +9,6 @@ public interface IvyRepository extends Repository
String ivyPattern(); String ivyPattern();
String artifactPattern(); String artifactPattern();
boolean mavenCompatible(); boolean mavenCompatible();
boolean skipConsistencyCheck();
boolean descriptorOptional();
} }

View File

@ -183,20 +183,22 @@ class ConfigurationParser
import Repository.{Ivy, Maven, Predefined} import Repository.{Ivy, Maven, Predefined}
val BootOnly = "bootOnly" val BootOnly = "bootOnly"
val MvnComp = "mavenCompatible" val MvnComp = "mavenCompatible"
val OptSet = Set(BootOnly, MvnComp) val DescriptorOptional = "descriptorOptional"
val DontCheckConsistency = "skipConsistencyCheck"
val OptSet = Set(BootOnly, MvnComp, DescriptorOptional, DontCheckConsistency)
m.toList.map { m.toList.map {
case (key, None) => Predefined(key) case (key, None) => Predefined(key)
case (key, Some(BootOnly)) => Predefined(key, true) case (key, Some(BootOnly)) => Predefined(key, true)
case (key, Some(value)) => case (key, Some(value)) =>
val r = trim(substituteVariables(value).split(",",6)) val r = trim(substituteVariables(value).split(",",7))
val url = try { new URL(r(0)) } catch { case e: MalformedURLException => error("Invalid URL specified for '" + key + "': " + e.getMessage) } val url = try { new URL(r(0)) } catch { case e: MalformedURLException => error("Invalid URL specified for '" + key + "': " + e.getMessage) }
val (optionPart, patterns) = r.tail.partition (OptSet.contains(_)) val (optionPart, patterns) = r.tail.partition (OptSet.contains(_))
val options = (optionPart.contains(BootOnly), optionPart.contains(MvnComp)) val options = (optionPart.contains(BootOnly), optionPart.contains(MvnComp), optionPart.contains(DescriptorOptional), optionPart.contains(DontCheckConsistency))
(patterns, options) match { (patterns, options) match {
case (both :: Nil, (bo, mc)) => Ivy(key, url, both, both, mavenCompatible=mc, bootOnly=bo) case (both :: Nil, (bo, mc, dso, cc)) => Ivy(key, url, both, both, mavenCompatible=mc, bootOnly=bo, descriptorOptional=dso, skipConsistencyCheck=cc)
case (ivy :: art :: Nil, (bo, mc)) => Ivy(key, url, ivy, art, mavenCompatible=mc, bootOnly=bo) case (ivy :: art :: Nil, (bo, mc, dso, cc)) => Ivy(key, url, ivy, art, mavenCompatible=mc, bootOnly=bo, descriptorOptional=dso, skipConsistencyCheck=cc)
case (Nil, (true, false)) => Maven(key, url, bootOnly=true) case (Nil, (true, false, false, cc)) => Maven(key, url, bootOnly=true)
case (Nil, (false, false)) => Maven(key, url) case (Nil, (false, false, false, false)) => Maven(key, url)
case _ => error("Could not parse %s: %s".format(key, value)) case _ => error("Could not parse %s: %s".format(key, value))
} }
} }

View File

@ -98,7 +98,7 @@ object Repository
def bootOnly: Boolean def bootOnly: Boolean
} }
final case class Maven(id: String, url: URL, bootOnly: Boolean = false) extends xsbti.MavenRepository with Repository final case class Maven(id: String, url: URL, bootOnly: Boolean = false) extends xsbti.MavenRepository with Repository
final case class Ivy(id: String, url: URL, ivyPattern: String, artifactPattern: String, mavenCompatible: Boolean, bootOnly: Boolean = false) extends xsbti.IvyRepository with Repository final case class Ivy(id: String, url: URL, ivyPattern: String, artifactPattern: String, mavenCompatible: Boolean, bootOnly: Boolean = false, descriptorOptional: Boolean = false, skipConsistencyCheck: Boolean = false) extends xsbti.IvyRepository with Repository
final case class Predefined(id: xsbti.Predefined, bootOnly: Boolean = false) extends xsbti.PredefinedRepository with Repository final case class Predefined(id: xsbti.Predefined, bootOnly: Boolean = false) extends xsbti.PredefinedRepository with Repository
object Predefined { object Predefined {
def apply(s: String): Predefined = new Predefined(xsbti.Predefined.toValue(s), false) def apply(s: String): Predefined = new Predefined(xsbti.Predefined.toValue(s), false)

View File

@ -261,7 +261,7 @@ final class Update(config: UpdateConfiguration)
newDefault.setName("redefined-public") newDefault.setName("redefined-public")
if(repositories.isEmpty) error("No repositories defined.") if(repositories.isEmpty) error("No repositories defined.")
for(repo <- repositories if includeRepo(repo)) for(repo <- repositories if includeRepo(repo))
newDefault.add(initializeBasic(toIvyRepository(settings, repo))) newDefault.add(toIvyRepository(settings, repo))
configureCache(settings) configureCache(settings)
settings.addResolver(newDefault) settings.addResolver(newDefault)
settings.setDefaultResolver(newDefault.getName) settings.setDefaultResolver(newDefault.getName)
@ -310,7 +310,7 @@ final class Update(config: UpdateConfiguration)
repo match repo match
{ {
case m: xsbti.MavenRepository => mavenResolver(m.id, m.url.toString) case m: xsbti.MavenRepository => mavenResolver(m.id, m.url.toString)
case i: xsbti.IvyRepository => urlResolver(i.id, i.url.toString, i.ivyPattern, i.artifactPattern, i.mavenCompatible) case i: xsbti.IvyRepository => urlResolver(i.id, i.url.toString, i.ivyPattern, i.artifactPattern, i.mavenCompatible, i.descriptorOptional, i.skipConsistencyCheck)
case p: xsbti.PredefinedRepository => p.id match { case p: xsbti.PredefinedRepository => p.id match {
case Local => localResolver(settings.getDefaultIvyUserDir.getAbsolutePath) case Local => localResolver(settings.getDefaultIvyUserDir.getAbsolutePath)
case MavenLocal => mavenLocal case MavenLocal => mavenLocal
@ -329,13 +329,15 @@ final class Update(config: UpdateConfiguration)
} }
} }
/** Uses the pattern defined in BuildConfiguration to download sbt from Google code.*/ /** Uses the pattern defined in BuildConfiguration to download sbt from Google code.*/
private def urlResolver(id: String, base: String, ivyPattern: String, artifactPattern: String, mavenCompatible: Boolean) = private def urlResolver(id: String, base: String, ivyPattern: String, artifactPattern: String, mavenCompatible: Boolean, descriptorOptional: Boolean, skipConsistencyCheck: Boolean) =
{ {
val resolver = new URLResolver val resolver = new URLResolver
resolver.setName(id) resolver.setName(id)
resolver.addIvyPattern(adjustPattern(base, ivyPattern)) resolver.addIvyPattern(adjustPattern(base, ivyPattern))
resolver.addArtifactPattern(adjustPattern(base, artifactPattern)) resolver.addArtifactPattern(adjustPattern(base, artifactPattern))
resolver.setM2compatible(mavenCompatible) resolver.setM2compatible(mavenCompatible)
resolver.setDescriptor(if (descriptorOptional) BasicResolver.DESCRIPTOR_OPTIONAL else BasicResolver.DESCRIPTOR_REQUIRED)
resolver.setCheckconsistency(!skipConsistencyCheck)
resolver resolver
} }
private def adjustPattern(base: String, pattern: String): String = private def adjustPattern(base: String, pattern: String): String =
@ -385,11 +387,6 @@ final class Update(config: UpdateConfiguration)
else else
mavenResolver("Sonatype Snapshots Repository", "https://oss.sonatype.org/content/repositories/snapshots") mavenResolver("Sonatype Snapshots Repository", "https://oss.sonatype.org/content/repositories/snapshots")
} }
private def initializeBasic(resolver: BasicResolver) =
{
resolver.setDescriptor(BasicResolver.DESCRIPTOR_REQUIRED)
resolver
}
/** Logs the given message to a file and to the console. */ /** Logs the given message to a file and to the console. */
private def log(msg: String) = private def log(msg: String) =

View File

@ -53,6 +53,22 @@ object ConfigurationParserTest extends Specification
| id: http://repo1.maven.org, [orgPath], [artPath]""".stripMargin, | id: http://repo1.maven.org, [orgPath], [artPath]""".stripMargin,
Repository.Ivy("id", new URL("http://repo1.maven.org"), "[orgPath]", "[artPath]", false, false)) Repository.Ivy("id", new URL("http://repo1.maven.org"), "[orgPath]", "[artPath]", false, false))
repoFileContains("""|[repositories]
| id: http://repo1.maven.org, [orgPath], [artPath], descriptorOptional""".stripMargin,
Repository.Ivy("id", new URL("http://repo1.maven.org"), "[orgPath]", "[artPath]", false, false, true, false))
repoFileContains("""|[repositories]
| id: http://repo1.maven.org, [orgPath], [artPath], descriptorOptional, skipConsistencyCheck""".stripMargin,
Repository.Ivy("id", new URL("http://repo1.maven.org"), "[orgPath]", "[artPath]", false, false, true, true))
repoFileContains("""|[repositories]
| id: http://repo1.maven.org, [orgPath], [artPath], skipConsistencyCheck, descriptorOptional""".stripMargin,
Repository.Ivy("id", new URL("http://repo1.maven.org"), "[orgPath]", "[artPath]", false, false, true, true))
repoFileContains("""|[repositories]
| id: http://repo1.maven.org, [orgPath], [artPath], skipConsistencyCheck, descriptorOptional, mavenCompatible, bootOnly""".stripMargin,
Repository.Ivy("id", new URL("http://repo1.maven.org"), "[orgPath]", "[artPath]", true, true, true, true))
repoFileContains("""|[repositories] repoFileContains("""|[repositories]
| id: http://repo1.maven.org, [orgPath], [artPath], bootOnly""".stripMargin, | id: http://repo1.maven.org, [orgPath], [artPath], bootOnly""".stripMargin,
Repository.Ivy("id", new URL("http://repo1.maven.org"), "[orgPath]", "[artPath]", false, true)) Repository.Ivy("id", new URL("http://repo1.maven.org"), "[orgPath]", "[artPath]", false, true))

View File

@ -1462,13 +1462,21 @@ object Classpaths
try { ivyRepo.mavenCompatible } try { ivyRepo.mavenCompatible }
catch { case _: NoSuchMethodError => false } catch { case _: NoSuchMethodError => false }
private[this] def skipConsistencyCheck(ivyRepo: xsbti.IvyRepository): Boolean =
try { ivyRepo.skipConsistencyCheck }
catch { case _: NoSuchMethodError => false }
private[this] def descriptorOptional(ivyRepo: xsbti.IvyRepository): Boolean =
try { ivyRepo.descriptorOptional }
catch { case _: NoSuchMethodError => false }
private[this] def bootRepository(repo: xsbti.Repository): Resolver = private[this] def bootRepository(repo: xsbti.Repository): Resolver =
{ {
import xsbti.Predefined import xsbti.Predefined
repo match repo match
{ {
case m: xsbti.MavenRepository => MavenRepository(m.id, m.url.toString) case m: xsbti.MavenRepository => MavenRepository(m.id, m.url.toString)
case i: xsbti.IvyRepository => Resolver.url(i.id, i.url)(Patterns(i.ivyPattern :: Nil, i.artifactPattern :: Nil, mavenCompatible(i))) case i: xsbti.IvyRepository => Resolver.url(i.id, i.url)(Patterns(i.ivyPattern :: Nil, i.artifactPattern :: Nil, mavenCompatible(i), descriptorOptional(i), skipConsistencyCheck(i)))
case p: xsbti.PredefinedRepository => p.id match { case p: xsbti.PredefinedRepository => p.id match {
case Predefined.Local => Resolver.defaultLocal case Predefined.Local => Resolver.defaultLocal
case Predefined.MavenLocal => Resolver.mavenLocal case Predefined.MavenLocal => Resolver.mavenLocal