package sbt
import java.util.Collections.emptyMap
import scala.collection.mutable.HashSet
import org.apache.ivy.{core, plugins}
import core.module.descriptor.{DefaultExcludeRule, ExcludeRule}
import core.module.descriptor.{DependencyDescriptor, DefaultModuleDescriptor, ModuleDescriptor, OverrideDependencyDescriptorMediator}
import core.module.id.{ArtifactId,ModuleId, ModuleRevisionId}
import plugins.matcher.ExactPatternMatcher
object ScalaArtifacts
{
import xsbti.ArtifactInfo._
val Organization = ScalaOrganization
val LibraryID = ScalaLibraryID
val CompilerID = ScalaCompilerID
def libraryDependency(version: String): ModuleID = ModuleID(Organization, LibraryID, version)
}
object SbtArtifacts
{
import xsbti.ArtifactInfo._
val Organization = SbtOrganization
}
import ScalaArtifacts._
final case class IvyScala(scalaFullVersion: String, scalaBinaryVersion: String, configurations: Iterable[Configuration], checkExplicit: Boolean, filterImplicit: Boolean, overrideScalaVersion: Boolean)
private object IvyScala
{
def checkModule(module: DefaultModuleDescriptor, conf: String, log: Logger)(check: IvyScala)
{
if(check.checkExplicit)
checkDependencies(module, check.scalaBinaryVersion, check.configurations, log)
if(check.filterImplicit)
excludeScalaJars(module, check.configurations)
if(check.overrideScalaVersion)
overrideScalaVersion(module, check.scalaFullVersion)
}
def overrideScalaVersion(module: DefaultModuleDescriptor, version: String)
{
overrideVersion(module, Organization, LibraryID, version)
overrideVersion(module, Organization, CompilerID, version)
}
def overrideVersion(module: DefaultModuleDescriptor, org: String, name: String, version: String)
{
val id = new ModuleId(org, name)
val over = new OverrideDependencyDescriptorMediator(null, version)
module.addDependencyDescriptorMediator(id, ExactPatternMatcher.INSTANCE, over)
}
private def checkDependencies(module: ModuleDescriptor, scalaBinaryVersion: String, configurations: Iterable[Configuration], log: Logger)
{
val configSet = if(configurations.isEmpty) (c: String) => true else configurationSet(configurations)
def binaryScalaWarning(dep: DependencyDescriptor): Option[String] =
{
val id = dep.getDependencyRevisionId
val depBinaryVersion = CrossVersion.binaryScalaVersion(id.getRevision)
val mismatched = id.getOrganisation == Organization && depBinaryVersion != scalaBinaryVersion && dep.getModuleConfigurations.exists(configSet)
if(mismatched)
Some("Binary version (" + depBinaryVersion + ") for dependency " + id +
"\n\tin " + module.getModuleRevisionId +
" differs from Scala binary version in project (" + scalaBinaryVersion + ").")
else
None
}
module.getDependencies.toList.flatMap(binaryScalaWarning).toSet foreach { (s: String) => log.warn(s) }
}
private def configurationSet(configurations: Iterable[Configuration]) = configurations.map(_.toString).toSet
private def excludeScalaJars(module: DefaultModuleDescriptor, configurations: Iterable[Configuration])
{
val configurationNames =
{
val names = module.getConfigurationsNames
if(configurations.isEmpty)
names
else
{
val configSet = configurationSet(configurations)
configSet.intersect(HashSet(names : _*))
configSet.toArray
}
}
def excludeScalaJar(name: String): Unit =
module.addExcludeRule(excludeRule(Organization, name, configurationNames, "jar"))
excludeScalaJar(LibraryID)
excludeScalaJar(CompilerID)
}
private[sbt] def excludeRule(organization: String, name: String, configurationNames: Iterable[String], excludeTypePattern: String): ExcludeRule =
{
val artifact = new ArtifactId(ModuleId.newInstance(organization, name), "*", excludeTypePattern, "*")
val rule = new DefaultExcludeRule(artifact, ExactPatternMatcher.INSTANCE, emptyMap[AnyRef,AnyRef])
configurationNames.foreach(rule.addConfiguration)
rule
}
}