Added support for extra attributes with Ivy. Use extra(key -> value) on ModuleIDs and Artifacts. To define for a project's ID:

override def projectID = super.projectID extra(key -> value)
To specify in a dependency:
  val dep = normalID extra(key -> value)



git-svn-id: https://simple-build-tool.googlecode.com/svn/trunk@986 d89573ee-9141-11dd-94d4-bdf5e562f29c
This commit is contained in:
dmharrah 2009-09-08 14:01:41 +00:00
parent ed3dbe92d9
commit eaabe0b85f
3 changed files with 45 additions and 17 deletions

View File

@ -279,13 +279,14 @@ trait BasicManagedProject extends ManagedProject with ReflectiveManagedProject w
/** The options provided to the 'update' action. This is by default the options in 'baseUpdateOptions'.
* If 'manager' has any dependencies, resolvers, or inline Ivy XML (which by default happens when inline
* dependency management is used), it is passed as the dependency manager.*/
def updateOptions: Seq[ManagedOption] =
def updateOptions: Seq[ManagedOption] = baseUpdateOptions ++ managerOption
def managerOption: Seq[ManagedOption] =
{
val m = manager
if(m.dependencies.isEmpty && m.resolvers.isEmpty && ivyXML.isEmpty && m.artifacts.isEmpty && m.configurations.isEmpty)
baseUpdateOptions
Nil
else
LibraryManager(m) :: baseUpdateOptions
LibraryManager(m) :: Nil
}
def deliverOptions: Seq[ManagedOption] = updateOptions.filter { case _: CheckScalaVersion => false; case _ => true }
def publishOptions: Seq[ManagedOption] = deliverOptions
@ -347,11 +348,20 @@ trait BasicManagedProject extends ManagedProject with ReflectiveManagedProject w
protected def deliverProjectDependencies: Iterable[ModuleID] =
{
val interDependencies = new scala.collection.mutable.ListBuffer[ModuleID]
dependencies.foreach(dep => dep match { case mp: ManagedProject => interDependencies += mp.projectID; case _ => () })
dependencies.foreach(dep => dep match { case mp: ManagedProject => interDependencies += projectModuleID(mp); case _ => () })
if(filterScalaJars)
interDependencies ++= deliverScalaDependencies
interDependencies.readOnly
}
protected def projectModuleID(mp: ManagedProject) =
{
val base = mp.projectID
val as = mp.artifacts.toSeq.toArray
if(as.size == 1)
base artifacts(as : _*)
else
base artifacts(as.filter(_.`type` != "pom") : _*)
}
protected def deliverScalaDependencies: Iterable[ModuleID] = Nil
protected def makePomAction = makePomTask(pomPath, deliverProjectDependencies, None, updateOptions)
protected def deliverLocalAction = deliverTask(publishLocalConfiguration, deliverOptions)
@ -542,6 +552,7 @@ trait ReflectiveProject extends ReflectiveModules with ReflectiveTasks with Refl
/** This Project subclass is used to contain other projects as dependencies.*/
class ParentProject(val info: ProjectInfo) extends BasicDependencyProject
{
override def managerOption: Seq[ManagedOption] = LibraryManager(new AutoDetectManager(projectID, false)) :: Nil
def dependencies: Iterable[Project] = info.dependencies ++ subProjects.values.toList
/** The directories to which a project writes are listed here and is used
* to check a project and its dependencies for collisions.*/

View File

@ -138,7 +138,7 @@ object ManageDependencies
/** Called to determine dependencies when the dependency manager is SbtManager and no inline dependencies (Scala or XML) are defined
* or if the manager is AutodetectManager. It will try to read from pom.xml first and then ivy.xml if pom.xml is not found. If neither is found,
* Ivy is configured with defaults unless IvyFlags.errorIfNoConfiguration is true, in which case an error is generated.*/
def autodetectDependencies(module: ModuleRevisionId) =
def autodetectDependencies(module: ModuleRevisionId, defaultArtifact: Boolean) =
{
log.debug("Autodetecting dependencies.")
val defaultPOMFile = defaultPOM(paths.projectDirectory).asFile
@ -157,7 +157,8 @@ object ManageDependencies
log.warn("No readable dependency configuration found, using defaults.")
val moduleID = DefaultModuleDescriptor.newDefaultInstance(module)
addMainArtifact(moduleID)
addDefaultArtifact(defaultConf, moduleID)
if(defaultArtifact)
addDefaultArtifact(defaultConf, moduleID)
Right((moduleID, defaultConf))
}
}
@ -183,7 +184,7 @@ object ManageDependencies
{
log.debug("No dependency manager explicitly specified.")
autodetectConfiguration()
autodetectDependencies(toID(adm.module))
autodetectDependencies(toID(adm.module), adm.defaultArtifact)
}
case sm: SbtManager =>
{
@ -196,7 +197,7 @@ object ManageDependencies
configureDefaults(withDefaultResolvers(resolvers))
}
if(autodetect)
autodetectDependencies(toID(module))
autodetectDependencies(toID(module), true)
else
{
val moduleID =
@ -280,7 +281,7 @@ object ManageDependencies
}
}
private def addExtraNamespaces(md: DefaultModuleDescriptor): Unit =
md.getExtraAttributesNamespaces.asInstanceOf[java.util.Map[String,String]].put("m", "m")
md.getExtraAttributesNamespaces.asInstanceOf[java.util.Map[String,String]].put("e", "http://ant.apache.org/ivy/extra")
/** Checks the immediate dependencies of module for dependencies on scala jars and verifies that the version on the
* dependencies matches scalaVersion. */
private def checkDependencies(module: ModuleDescriptor, scalaVersion: String, configurations: Iterable[Configuration]): Option[String] =
@ -538,7 +539,11 @@ object ManageDependencies
}
}
private def extra(artifact: Artifact) =
artifact.classifier.map(c => wrap.Wrappers.javaMap("m:classifier" -> c)).getOrElse(null)
{
val ea = artifact.classifier match { case Some(c) => artifact.extra("e:classifier" -> c); case None => artifact }
javaMap(artifact.extraAttributes)
}
private def javaMap(map: Map[String,String]) = if(map.isEmpty) null else wrap.Wrappers.javaMap(map.toSeq : _*)
private def toURL(file: File) = file.toURI.toURL
/** Adds the ivy.xml main artifact. */
private def addMainArtifact(moduleID: DefaultModuleDescriptor)
@ -574,7 +579,7 @@ object ManageDependencies
private def toID(m: ModuleID) =
{
import m._
ModuleRevisionId.newInstance(organization, name, revision)
ModuleRevisionId.newInstance(organization, name, revision, javaMap(extraAttributes))
}
private def toIvyArtifact(moduleID: ModuleDescriptor, a: Artifact, configurations: Iterable[String]): MDArtifact =
{

View File

@ -12,7 +12,10 @@ import org.apache.ivy.util.url.CredentialsStore
sealed abstract class Manager extends NotNull
/** This explicitly requests auto detection as a dependency manager. It will first check for a 'pom.xml' file and if that does not exist, an 'ivy.xml' file.
* Ivy is configured using the detected file or uses defaults.*/
final class AutoDetectManager(val module: ModuleID) extends Manager
final class AutoDetectManager(val module: ModuleID, val defaultArtifact: Boolean) extends Manager
{
def this(module: ModuleID) = this(module, true)
}
/** This explicitly requests that the Maven pom 'pom' be used to determine dependencies. An Ivy configuration file to use may be specified in
* 'configuration', since Ivy currently cannot extract Maven repositories from a pom file. Otherwise, defaults are used.*/
final class MavenManager(val configuration: Option[Path], val pom: Path) extends Manager
@ -52,16 +55,17 @@ final class SimpleManager private[sbt] (val dependenciesXML: NodeSeq, val autode
explicitConfigurations
}
final case class ModuleID(organization: String, name: String, revision: String, configurations: Option[String], isChanging: Boolean, isTransitive: Boolean, explicitArtifacts: Seq[Artifact]) extends NotNull
final case class ModuleID(organization: String, name: String, revision: String, configurations: Option[String], isChanging: Boolean, isTransitive: Boolean, explicitArtifacts: Seq[Artifact], extraAttributes: Map[String,String]) extends NotNull
{
override def toString = organization + ":" + name + ":" + revision
// () required for chaining
def notTransitive() = intransitive()
def intransitive() = ModuleID(organization, name, revision, configurations, isChanging, false, explicitArtifacts)
def changing() = ModuleID(organization, name, revision, configurations, true, isTransitive, explicitArtifacts)
def intransitive() = ModuleID(organization, name, revision, configurations, isChanging, false, explicitArtifacts, extraAttributes)
def changing() = ModuleID(organization, name, revision, configurations, true, isTransitive, explicitArtifacts, extraAttributes)
def from(url: String) = artifacts(Artifact(name, new URL(url)))
def classifier(c: String) = artifacts(Artifact(name, c))
def artifacts(newArtifacts: Artifact*) = ModuleID(organization, name, revision, configurations, isChanging, isTransitive, newArtifacts ++ explicitArtifacts)
def artifacts(newArtifacts: Artifact*) = ModuleID(organization, name, revision, configurations, isChanging, isTransitive, newArtifacts ++ explicitArtifacts, extraAttributes)
def extra(attributes: (String,String)*) = ModuleID(organization, name, revision, configurations, isChanging, isTransitive, explicitArtifacts, extraAttributes ++ attributes)
}
object ModuleID
{
@ -70,6 +74,8 @@ object ModuleID
ModuleID(organization, name, revision, configurations, false, true)
def apply(organization: String, name: String, revision: String, configurations: Option[String], isChanging: Boolean, isTransitive: Boolean): ModuleID =
ModuleID(organization, name, revision, configurations, isChanging, isTransitive, Nil)
def apply(organization: String, name: String, revision: String, configurations: Option[String], isChanging: Boolean, isTransitive: Boolean, explicitArtifacts: Seq[Artifact]): ModuleID =
ModuleID(organization, name, revision, configurations, isChanging, isTransitive, explicitArtifacts, Map.empty)
}
sealed trait Resolver extends NotNull
{
@ -334,13 +340,19 @@ final case class Configuration(name: String, description: String, isPublic: Bool
override def toString = name
}
final case class Artifact(name: String, `type`: String, extension: String, classifier: Option[String], configurations: Iterable[Configuration], url: Option[URL]) extends NotNull
final case class Artifact(name: String, `type`: String, extension: String, classifier: Option[String], configurations: Iterable[Configuration], url: Option[URL], extraAttributes: Map[String,String]) extends NotNull
{
def extra(attributes: (String,String)*) = Artifact(name, `type`, extension, classifier, configurations, url, extraAttributes ++ attributes)
}
object Artifact
{
def apply(name: String): Artifact = Artifact(name, defaultType, defaultExtension, None, Nil, None)
def apply(name: String, extra: Map[String,String]): Artifact = Artifact(name, defaultType, defaultExtension, None, Nil, None, extra)
def apply(name: String, classifier: String): Artifact = Artifact(name, defaultType, defaultExtension, Some(classifier), Nil, None)
def apply(name: String, `type`: String, extension: String): Artifact = Artifact(name, `type`, extension, None, Nil, None)
def apply(name: String, url: URL): Artifact =Artifact(name, extract(url, defaultType), extract(url, defaultExtension), None, Nil, Some(url))
def apply(name: String, `type`: String, extension: String, classifier: Option[String], configurations: Iterable[Configuration], url: Option[URL]): Artifact =
Artifact(name, `type`, extension, classifier, configurations, url, Map.empty)
val defaultExtension = "jar"
val defaultType = "jar"
private[this] def extract(url: URL, default: String) =