Add support for attributes

This commit is contained in:
Alexandre Archambault 2015-12-30 01:34:37 +01:00
parent a3188a9b8a
commit f52e2ecca4
10 changed files with 69 additions and 29 deletions

View File

@ -158,8 +158,22 @@ class Helper(
}
val moduleVersions = splitDependencies.map{
case Seq(org, name, version) =>
(Module(org, name), version)
case Seq(org, namePart, version) =>
val p = namePart.split(';')
val name = p.head
val splitAttributes = p.tail.map(_.split("=", 2).toSeq).toSeq
val malformedAttributes = splitAttributes.filter(_.length != 2)
if (malformedAttributes.nonEmpty) {
// FIXME Get these for all dependencies at once
Console.err.println(s"Malformed attributes in ${splitDependencies.mkString(":")}")
// :(
sys.exit(255)
}
val attributes = splitAttributes.collect {
case Seq(k, v) => k -> v
}
println(s"-> $org:$name:$attributes")
(Module(org, name, attributes.toMap), version)
}
val deps = moduleVersions.map{case (mod, ver) =>

View File

@ -51,7 +51,7 @@ package object compatibility {
.map(l => List.tabulate(l.length)(l.item).map(fromNode))
.getOrElse(Nil)
def attributes: Seq[(String, String)] = ???
def attributes = ???
// `exists` instead of `contains`, for scala 2.10
def isText =

View File

@ -2,7 +2,7 @@ package coursier.core
import coursier.util.Xml
import scala.xml.{ MetaData, Null }
import scala.xml.{ Attribute, MetaData, Null }
package object compatibility {
@ -19,14 +19,20 @@ package object compatibility {
def fromNode(node: scala.xml.Node): Xml.Node =
new Xml.Node {
lazy val attributes = {
def helper(m: MetaData): Stream[(String, String)] =
def helper(m: MetaData): Stream[(String, String, String)] =
m match {
case Null => Stream.empty
case attr =>
val pre = attr match {
case a: Attribute => Option(node.getNamespace(a.pre)).getOrElse("")
case _ => ""
}
val value = attr.value.collect {
case scala.xml.Text(t) => t
}.mkString("")
(attr.key -> value) #:: helper(m.next)
(pre, attr.key, value) #:: helper(m.next)
}
helper(node.attributes).toVector

View File

@ -8,12 +8,11 @@ package coursier.core
* between them.
*
* Using the same terminology as Ivy.
*
* Ivy attributes would land here, if support for it is added.
*/
case class Module(
organization: String,
name: String
name: String,
attributes: Map[String, String]
) {
def trim: Module = copy(
@ -21,7 +20,14 @@ case class Module(
name = name.trim
)
override def toString = s"$organization:$name"
private def attributesStr = attributes.toSeq
.sortBy { case (k, _) => k }
.map { case (k, v) => s"$k=$v" }
.mkString(";")
override def toString =
s"$organization:$name" +
(if (attributes.nonEmpty) s";$attributesStr" else "")
}
/**

View File

@ -145,23 +145,22 @@ case class IvyRepository(
// list of variables that should be supported.
// Some are missing (branch, conf, originalName).
private def variables(
org: String,
name: String,
module: Module,
version: String,
`type`: String,
artifact: String,
ext: String
) =
Map(
"organization" -> org,
"organisation" -> org,
"orgPath" -> org.replace('.', '/'),
"module" -> name,
"organization" -> module.organization,
"organisation" -> module.organization,
"orgPath" -> module.organization.replace('.', '/'),
"module" -> module.name,
"revision" -> version,
"type" -> `type`,
"artifact" -> artifact,
"ext" -> ext
)
) ++ module.attributes
val source: Artifact.Source = new Artifact.Source {
@ -191,8 +190,7 @@ case class IvyRepository(
val retainedWithUrl = retained.flatMap { p =>
substitute(variables(
dependency.module.organization,
dependency.module.name,
dependency.module,
dependency.version,
p.`type`,
p.name,
@ -225,7 +223,9 @@ case class IvyRepository(
val eitherArtifact: String \/ Artifact =
for {
url <- substitute(variables(module.organization, module.name, version, "ivy", "ivy", "xml"))
url <- substitute(
variables(module, version, "ivy", "ivy", "xml")
)
} yield
Artifact(
url,

View File

@ -7,12 +7,15 @@ import scalaz.{ Node => _, _ }, Scalaz._
object IvyXml {
val attributesNamespace = "http://ant.apache.org/ivy/extra"
private def info(node: Node): String \/ (Module, String) =
for {
org <- node.attribute("organisation")
name <- node.attribute("module")
version <- node.attribute("revision")
} yield (Module(org, name), version)
attr = node.attributesFromNamespace(attributesNamespace)
} yield (Module(org, name, attr.toMap), version)
// FIXME Errors are ignored here
private def configurations(node: Node): Seq[(String, Seq[String])] =
@ -53,8 +56,9 @@ object IvyXml {
(fromConf, toConf) <- rawConf.split(',').toSeq.map(_.split("->", 2)).collect {
case Array(from, to) => from -> to
}
attr = node.attributesFromNamespace(attributesNamespace)
} yield fromConf -> Dependency(
Module(org, name),
Module(org, name, attr.toMap),
version,
toConf,
allConfsExcludes ++ excludes.getOrElse(fromConf, Set.empty),

View File

@ -22,7 +22,7 @@ object Pom {
else e
}
name <- text(node, "artifactId", "Name")
} yield Module(organization, name).trim
} yield Module(organization, name, Map.empty).trim
}
private def readVersion(node: Node) =
@ -307,7 +307,7 @@ object Pom {
.toList
.traverseU(snapshotVersion)
} yield SnapshotVersioning(
Module(organization, name),
Module(organization, name, Map.empty),
version,
latest,
release,

View File

@ -42,8 +42,8 @@ package object coursier {
type Module = core.Module
object Module {
def apply(organization: String, name: String): Module =
core.Module(organization, name)
def apply(organization: String, name: String, attributes: Map[String, String] = Map.empty): Module =
core.Module(organization, name, attributes)
}
type ModuleVersion = (core.Module, String)

View File

@ -7,13 +7,20 @@ object Xml {
/** A representation of an XML node/document, with different implementations on JVM and JS */
trait Node {
def label: String
def attributes: Seq[(String, String)]
/** Namespace / key / value */
def attributes: Seq[(String, String, String)]
def children: Seq[Node]
def isText: Boolean
def textContent: String
def isElement: Boolean
lazy val attributesMap = attributes.toMap
def attributesFromNamespace(namespace: String): Seq[(String, String)] =
attributes.collect {
case (`namespace`, k, v) =>
k -> v
}
lazy val attributesMap = attributes.map { case (_, k, v) => k -> v }.toMap
def attribute(name: String): String \/ String =
attributesMap.get(name) match {
case None => -\/(s"Missing attribute $name")

View File

@ -406,7 +406,10 @@ object App {
}
val sortedDeps = res.minDependencies.toList
.sortBy(dep => coursier.core.Module.unapply(dep.module).get)
.sortBy { dep =>
val (org, name, _) = coursier.core.Module.unapply(dep.module).get
(org, name)
}
<.table(^.`class` := "table",
<.thead(