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
}
}
private sealed trait DescriptorRequired extends BasicResolver
{
override def getDependency(dd: DependencyDescriptor, data: ResolveData) =
@ -122,6 +123,8 @@ private object ConvertResolver
private def initializePatterns(resolver: AbstractPatternsBasedResolver, patterns: Patterns, settings: IvySettings)
{
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.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
}
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 withIvys(patterns: Seq[String]): Patterns = Patterns(patterns ++ ivyPatterns, 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 = {
obj match {
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
}
}
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
{
@ -44,7 +47,7 @@ object Patterns
def apply(artifactPatterns: String*): Patterns = Patterns(true, artifactPatterns : _*)
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
{

View File

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

View File

@ -183,20 +183,22 @@ class ConfigurationParser
import Repository.{Ivy, Maven, Predefined}
val BootOnly = "bootOnly"
val MvnComp = "mavenCompatible"
val OptSet = Set(BootOnly, MvnComp)
val DescriptorOptional = "descriptorOptional"
val DontCheckConsistency = "skipConsistencyCheck"
val OptSet = Set(BootOnly, MvnComp, DescriptorOptional, DontCheckConsistency)
m.toList.map {
case (key, None) => Predefined(key)
case (key, Some(BootOnly)) => Predefined(key, true)
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 (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 {
case (both :: Nil, (bo, mc)) => Ivy(key, url, both, both, mavenCompatible=mc, bootOnly=bo)
case (ivy :: art :: Nil, (bo, mc)) => Ivy(key, url, ivy, art, mavenCompatible=mc, bootOnly=bo)
case (Nil, (true, false)) => Maven(key, url, bootOnly=true)
case (Nil, (false, false)) => Maven(key, url)
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, dso, cc)) => Ivy(key, url, ivy, art, mavenCompatible=mc, bootOnly=bo, descriptorOptional=dso, skipConsistencyCheck=cc)
case (Nil, (true, false, false, cc)) => Maven(key, url, bootOnly=true)
case (Nil, (false, false, false, false)) => Maven(key, url)
case _ => error("Could not parse %s: %s".format(key, value))
}
}

View File

@ -98,7 +98,7 @@ object Repository
def bootOnly: Boolean
}
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
object Predefined {
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")
if(repositories.isEmpty) error("No repositories defined.")
for(repo <- repositories if includeRepo(repo))
newDefault.add(initializeBasic(toIvyRepository(settings, repo)))
newDefault.add(toIvyRepository(settings, repo))
configureCache(settings)
settings.addResolver(newDefault)
settings.setDefaultResolver(newDefault.getName)
@ -310,7 +310,7 @@ final class Update(config: UpdateConfiguration)
repo match
{
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 Local => localResolver(settings.getDefaultIvyUserDir.getAbsolutePath)
case MavenLocal => mavenLocal
@ -329,13 +329,15 @@ final class Update(config: UpdateConfiguration)
}
}
/** 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
resolver.setName(id)
resolver.addIvyPattern(adjustPattern(base, ivyPattern))
resolver.addArtifactPattern(adjustPattern(base, artifactPattern))
resolver.setM2compatible(mavenCompatible)
resolver.setDescriptor(if (descriptorOptional) BasicResolver.DESCRIPTOR_OPTIONAL else BasicResolver.DESCRIPTOR_REQUIRED)
resolver.setCheckconsistency(!skipConsistencyCheck)
resolver
}
private def adjustPattern(base: String, pattern: String): String =
@ -385,11 +387,6 @@ final class Update(config: UpdateConfiguration)
else
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. */
private def log(msg: String) =

View File

@ -53,6 +53,22 @@ object ConfigurationParserTest extends Specification
| id: http://repo1.maven.org, [orgPath], [artPath]""".stripMargin,
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]
| id: http://repo1.maven.org, [orgPath], [artPath], bootOnly""".stripMargin,
Repository.Ivy("id", new URL("http://repo1.maven.org"), "[orgPath]", "[artPath]", false, true))

View File

@ -1462,13 +1462,21 @@ object Classpaths
try { ivyRepo.mavenCompatible }
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 =
{
import xsbti.Predefined
repo match
{
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 Predefined.Local => Resolver.defaultLocal
case Predefined.MavenLocal => Resolver.mavenLocal