mirror of https://github.com/sbt/sbt.git
commit
92e60d2b26
|
|
@ -91,9 +91,22 @@ case class Coursier(scope: List[String],
|
|||
def repr(dep: Dependency) =
|
||||
s"${dep.module.organization}:${dep.module.name}:${dep.`type`}:${Some(dep.classifier).filter(_.nonEmpty).map(_+":").mkString}${dep.module.version}"
|
||||
|
||||
val trDeps = res.dependencies.toList.map(repr).sorted
|
||||
val trDeps = res.dependencies.toList.sortBy(repr)
|
||||
|
||||
println("\n" + trDeps.mkString("\n"))
|
||||
println("\n" + trDeps.map(repr).mkString("\n"))
|
||||
|
||||
if (res.conflicts.nonEmpty) {
|
||||
// Needs test
|
||||
println(s"${res.conflicts.size} conflict(s):\n ${res.conflicts.toList.map(repr).sorted.mkString(" \n")}")
|
||||
}
|
||||
|
||||
val errDeps = trDeps.filter(dep => res.errors.contains(dep.module))
|
||||
if (errDeps.nonEmpty) {
|
||||
println(s"${errDeps.size} error(s):")
|
||||
for (dep <- errDeps) {
|
||||
println(s" ${dep.module}:\n ${res.errors(dep.module).mkString("\n").replace("\n", " \n")}")
|
||||
}
|
||||
}
|
||||
|
||||
if (fetch) {
|
||||
println()
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ case class Remote(base: String, logger: Option[Logger] = None) extends Repositor
|
|||
for {
|
||||
xml <- \/.fromEither(eitherXml)
|
||||
_ = logger.foreach(_.other(url, "is XML"))
|
||||
_ <- if (xml.label == "project") \/-(()) else -\/("Project definition not found")
|
||||
_ <- if (xml.label == "project") \/-(()) else -\/(s"Project definition not found (got '${xml.label}')")
|
||||
_ = logger.foreach(_.other(url, "project definition found"))
|
||||
proj <- Xml.project(xml)
|
||||
_ = logger.foreach(_.other(url, "project definition ok"))
|
||||
|
|
|
|||
|
|
@ -30,6 +30,20 @@ package object compatibility {
|
|||
js.Dynamic.newInstance(defn)()
|
||||
}
|
||||
|
||||
lazy val XMLSerializer = {
|
||||
import js.Dynamic.{global => g}
|
||||
import js.DynamicImplicits._
|
||||
|
||||
val defn =
|
||||
if (js.isUndefined(g.XMLSerializer)) g.require("xmldom").XMLSerializer
|
||||
else g.XMLSerializer
|
||||
js.Dynamic.newInstance(defn)()
|
||||
}
|
||||
|
||||
// Can't find these from node
|
||||
val ELEMENT_NODE = 1 // org.scalajs.dom.raw.Node.ELEMENT_NODE
|
||||
val TEXT_NODE = 3 // org.scalajs.dom.raw.Node.TEXT_NODE
|
||||
|
||||
def fromNode(node: org.scalajs.dom.raw.Node): Xml.Node = {
|
||||
|
||||
val node0 = node.asInstanceOf[js.Dynamic]
|
||||
|
|
@ -43,15 +57,19 @@ package object compatibility {
|
|||
.map(l => List.tabulate(l.length)(l.item).map(fromNode))
|
||||
.getOrElse(Nil)
|
||||
|
||||
// `exists` instead of `contains`, for scala 2.10
|
||||
def isText =
|
||||
option[Int](node0.nodeType)
|
||||
.exists(_ == 3) //org.scalajs.dom.raw.Node.TEXT_NODE
|
||||
.exists(_ == TEXT_NODE)
|
||||
def textContent =
|
||||
option(node0.textContent)
|
||||
.getOrElse("")
|
||||
def isElement =
|
||||
option[Int](node0.nodeType)
|
||||
.exists(_ == 1) // org.scalajs.dom.raw.Node.ELEMENT_NODE
|
||||
.exists(_ == ELEMENT_NODE)
|
||||
|
||||
override def toString =
|
||||
XMLSerializer.serializeToString(node).asInstanceOf[String]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -59,10 +77,18 @@ package object compatibility {
|
|||
def xmlParse(s: String): Either[String, Xml.Node] = {
|
||||
val doc = {
|
||||
if (s.isEmpty) None
|
||||
else
|
||||
dynOption(DOMParser.parseFromString(s, "text/xml"))
|
||||
.flatMap(t => dynOption(t.childNodes))
|
||||
.flatMap(l => l.asInstanceOf[js.Array[js.Dynamic]].headOption.flatMap(option[org.scalajs.dom.raw.Node]))
|
||||
else {
|
||||
for {
|
||||
xmlDoc <- dynOption(DOMParser.parseFromString(s, "text/xml"))
|
||||
rootNodes <- dynOption(xmlDoc.childNodes)
|
||||
// From node, rootNodes.head is sometimes just a comment instead of the main root node
|
||||
// (tested with org.ow2.asm:asm-commons in CentralTests)
|
||||
rootNode <- rootNodes.asInstanceOf[js.Array[js.Dynamic]]
|
||||
.flatMap(option[org.scalajs.dom.raw.Node])
|
||||
.dropWhile(_.nodeType != ELEMENT_NODE)
|
||||
.headOption
|
||||
} yield rootNode
|
||||
}
|
||||
}
|
||||
|
||||
Right(doc.fold(Xml.Node.empty)(fromNode))
|
||||
|
|
|
|||
|
|
@ -17,10 +17,7 @@ package object compatibility {
|
|||
def label = node.label
|
||||
def child = node.child.map(fromNode)
|
||||
def isText = node match { case _: scala.xml.Text => true; case _ => false }
|
||||
def textContent = node match {
|
||||
case t: scala.xml.Text => t.data
|
||||
case _ => throw new NoSuchElementException("text of non text node")
|
||||
}
|
||||
def textContent = node.text
|
||||
def isElement = node match { case _: scala.xml.Elem => true; case _ => false }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -350,21 +350,22 @@ object Resolver {
|
|||
// Here, we're substituting properties also in dependencies that come from parents
|
||||
// or dependency management. This may not be the right thing to do.
|
||||
|
||||
val properties = mergeProperties(
|
||||
project.properties,
|
||||
Map(
|
||||
"project.groupId" -> project.module.organization,
|
||||
"project.artifactId" -> project.module.name,
|
||||
"project.version" -> project.module.version
|
||||
)
|
||||
)
|
||||
|
||||
val deps =
|
||||
withExclusions(
|
||||
withProperties(
|
||||
depsWithDependencyManagement(
|
||||
project.dependencies,
|
||||
project.dependencyManagement
|
||||
),
|
||||
mergeProperties(
|
||||
project.properties,
|
||||
Map(
|
||||
"project.groupId" -> project.module.organization,
|
||||
"project.artifactId" -> project.module.name,
|
||||
"project.version" -> project.module.version
|
||||
)
|
||||
)
|
||||
depsWithDependencyManagement(
|
||||
// important: properties have to be applied to both, so that dep mgmt can be matched properly
|
||||
// See the added test with org.ow2.asm:asm-commons:5.0.2
|
||||
withProperties(project.dependencies, properties),
|
||||
withProperties(project.dependencyManagement, properties)
|
||||
),
|
||||
from.exclusions
|
||||
)
|
||||
|
|
|
|||
|
|
@ -41,12 +41,10 @@ object Xml {
|
|||
.toRightDisjunction(s"$description not found")
|
||||
}
|
||||
|
||||
private def property(elem: Node): String \/ (String, String) = {
|
||||
elem.child match {
|
||||
case Seq() => \/-(elem.label -> "")
|
||||
case Seq(Text(t)) => \/-(elem.label -> t)
|
||||
case _ => -\/(s"Can't parse property $elem")
|
||||
}
|
||||
def property(elem: Node): String \/ (String, String) = {
|
||||
// Not matching with Text, which fails on scala-js if the property value has xml comments
|
||||
if (elem.isElement) \/-(elem.label -> elem.textContent)
|
||||
else -\/(s"Can't parse property $elem")
|
||||
}
|
||||
|
||||
// TODO Allow no version in some contexts
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@ object CentralTests extends TestSuite {
|
|||
.runF)
|
||||
|
||||
val res = res0.copy(
|
||||
projectsCache = Map.empty, errors = Map.empty, // No validating these here
|
||||
dependencies = res0.dependencies.filter(dep => dep.scope == Scope.Compile && !dep.optional)
|
||||
projectsCache = Map.empty, errors = Map.empty // No validating these here
|
||||
)
|
||||
|
||||
val expected = Resolution(
|
||||
|
|
@ -34,6 +33,29 @@ object CentralTests extends TestSuite {
|
|||
)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'asm{
|
||||
async {
|
||||
val dep = Dependency(Module("org.ow2.asm", "asm-commons", "5.0.2"))
|
||||
val res0 =
|
||||
await(resolve(Set(dep), fetchFrom(repositories))
|
||||
.runF)
|
||||
|
||||
val res = res0.copy(
|
||||
projectsCache = Map.empty, errors = Map.empty // No validating these here
|
||||
)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(
|
||||
dep.withCompileScope,
|
||||
Dependency(Module("org.ow2.asm", "asm-tree", "5.0.2")).withCompileScope,
|
||||
Dependency(Module("org.ow2.asm", "asm", "5.0.2")).withCompileScope
|
||||
)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,62 @@ object PomParsingTests extends TestSuite {
|
|||
|
||||
assert(result == expected)
|
||||
}
|
||||
'beFineWithCommentsInProperties{
|
||||
import scalaz._, Scalaz._
|
||||
|
||||
val properties =
|
||||
"""
|
||||
| <properties>
|
||||
| <maven.compile.source>1.6</maven.compile.source>
|
||||
| <maven.compile.target>1.6</maven.compile.target>
|
||||
| <commons.componentid>io</commons.componentid>
|
||||
| <commons.rc.version>RC1</commons.rc.version>
|
||||
| <commons.release.version>2.4</commons.release.version>
|
||||
| <commons.release.desc>(requires JDK 1.6+)</commons.release.desc>
|
||||
| <commons.release.2.version>2.2</commons.release.2.version>
|
||||
| <commons.release.2.desc>(requires JDK 1.5+)</commons.release.2.desc>
|
||||
| <commons.jira.id>IO</commons.jira.id>
|
||||
| <commons.jira.pid>12310477</commons.jira.pid>
|
||||
| <commons.osgi.export>
|
||||
| <!-- Explicit list of packages from IO 1.4 -->
|
||||
| org.apache.commons.io;
|
||||
| org.apache.commons.io.comparator;
|
||||
| org.apache.commons.io.filefilter;
|
||||
| org.apache.commons.io.input;
|
||||
| org.apache.commons.io.output;version=1.4.9999;-noimport:=true,
|
||||
| <!-- Same list plus * for new packages -->
|
||||
| org.apache.commons.io;
|
||||
| org.apache.commons.io.comparator;
|
||||
| org.apache.commons.io.filefilter;
|
||||
| org.apache.commons.io.input;
|
||||
| org.apache.commons.io.output;
|
||||
| org.apache.commons.io.*;version=${project.version};-noimport:=true
|
||||
| </commons.osgi.export>
|
||||
| </properties>
|
||||
|
|
||||
""".stripMargin
|
||||
|
||||
val parsed = core.compatibility.xmlParse(properties)
|
||||
assert(parsed.isRight)
|
||||
|
||||
val node = parsed.right.get
|
||||
assert(node.label == "properties")
|
||||
|
||||
val children = node.child.collect{case elem if elem.isElement => elem}
|
||||
val props0 = children.toList.traverseU(Xml.property)
|
||||
|
||||
assert(props0.isRight)
|
||||
|
||||
val props = props0.getOrElse(???).toMap
|
||||
|
||||
assert(props.contains("commons.release.2.desc"))
|
||||
assert(props.contains("commons.osgi.export"))
|
||||
|
||||
assert(props("commons.rc.version") == "RC1")
|
||||
assert(props("commons.release.2.desc") == "(requires JDK 1.5+)")
|
||||
assert(props("commons.osgi.export").contains("org.apache.commons.io.filefilter;"))
|
||||
assert(props("commons.osgi.export").contains("org.apache.commons.io.input;"))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@
|
|||
.customButton {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.popover {
|
||||
max-width: 400px;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -175,6 +175,10 @@ class Backend($: BackendScope[Unit, State]) {
|
|||
}
|
||||
}
|
||||
|
||||
def enablePopover(e: ReactEventI) = {
|
||||
g.$("[data-toggle='popover']").popover()
|
||||
}
|
||||
|
||||
object options {
|
||||
def toggleOptional(e: ReactEventI) = {
|
||||
$.modState(s => s.copy(options = s.options.copy(followOptional = !s.options.followOptional)))
|
||||
|
|
@ -189,8 +193,22 @@ object App {
|
|||
|
||||
lazy val arbor = g.arbor
|
||||
|
||||
val resultDependencies = ReactComponentB[Resolution]("Result")
|
||||
.render{ res =>
|
||||
val resultDependencies = ReactComponentB[(Resolution, Backend)]("Result")
|
||||
.render{ T =>
|
||||
val (res, backend) = T
|
||||
|
||||
def infoLabel(label: String) =
|
||||
<.span(^.`class` := "label label-info", label)
|
||||
def errorLabel(label: String, desc: String) =
|
||||
<.button(^.`type` := "button", ^.`class` := "btn btn-xs btn-danger",
|
||||
Attr("data-trigger") := "focus",
|
||||
Attr("data-toggle") := "popover", Attr("data-placement") := "bottom",
|
||||
Attr("data-content") := desc,
|
||||
^.onClick ==> backend.enablePopover,
|
||||
^.onMouseOver ==> backend.enablePopover,
|
||||
label
|
||||
)
|
||||
|
||||
def depItem(dep: Dependency) =
|
||||
<.tr(
|
||||
^.`class` := (if (res.errors.contains(dep.module)) "danger" else ""),
|
||||
|
|
@ -198,10 +216,11 @@ object App {
|
|||
<.td(dep.module.name),
|
||||
<.td(dep.module.version),
|
||||
<.td(Seq[Seq[TagMod]](
|
||||
if (dep.scope == Scope.Compile) Seq() else Seq(<.span(^.`class` := "label label-info", dep.scope.name)),
|
||||
if (dep.`type`.isEmpty || dep.`type` == "jar") Seq() else Seq(<.span(^.`class` := "label label-info", dep.`type`)),
|
||||
if (dep.classifier.isEmpty) Seq() else Seq(<.span(^.`class` := "label label-info", dep.classifier)),
|
||||
if (dep.optional) Seq(<.span(^.`class` := "label label-info", dep.classifier)) else Seq()
|
||||
if (dep.scope == Scope.Compile) Seq() else Seq(infoLabel(dep.scope.name)),
|
||||
if (dep.`type`.isEmpty || dep.`type` == "jar") Seq() else Seq(infoLabel(dep.`type`)),
|
||||
if (dep.classifier.isEmpty) Seq() else Seq(infoLabel(dep.classifier)),
|
||||
if (dep.optional) Seq(infoLabel("optional")) else Seq(),
|
||||
res.errors.get(dep.module).map(errs => errorLabel("Error", errs.mkString("; "))).toSeq
|
||||
)),
|
||||
<.td(Seq[Seq[TagMod]](
|
||||
res.projectsCache.get(dep.module) match {
|
||||
|
|
@ -244,7 +263,6 @@ object App {
|
|||
<.tbody(
|
||||
sortedDeps.map(depItem)
|
||||
)
|
||||
// <.div(dangerouslySetInnerHtml("<script>$(function () { $('[data-toggle=\"popover\"]').popover() })</script>"))
|
||||
)
|
||||
}
|
||||
.build
|
||||
|
|
@ -406,21 +424,23 @@ object App {
|
|||
}
|
||||
.build
|
||||
|
||||
val resolution = ReactComponentB[Option[Resolution]]("Resolution")
|
||||
.render(resOpt =>
|
||||
val resolution = ReactComponentB[(Option[Resolution], Backend)]("Resolution")
|
||||
.render{ T =>
|
||||
val (resOpt, backend) = T
|
||||
|
||||
resOpt match {
|
||||
case Some(res) =>
|
||||
<.div(
|
||||
<.div(^.`class` := "page-header",
|
||||
<.h1("Resolution")
|
||||
),
|
||||
resultDependencies(res)
|
||||
resultDependencies((res, backend))
|
||||
)
|
||||
|
||||
case None =>
|
||||
<.div()
|
||||
}
|
||||
)
|
||||
}
|
||||
.build
|
||||
|
||||
val initialState = State(Nil, Seq(coursier.repository.mavenCentral), ResolutionOptions(), None, -1, resolving = false, reverseTree = false, log = Nil)
|
||||
|
|
@ -494,7 +514,7 @@ object App {
|
|||
),
|
||||
<.div(^.`class` := "tab-content",
|
||||
<.div(^.role := "tabpanel", ^.`class` := "tab-pane", ^.id := "resolution",
|
||||
resolution(S.resolutionOpt)
|
||||
resolution((S.resolutionOpt, B))
|
||||
),
|
||||
<.div(^.role := "tabpanel", ^.`class` := "tab-pane", ^.id := "log",
|
||||
<.button(^.`type` := "button", ^.`class` := "btn btn-default",
|
||||
|
|
|
|||
Loading…
Reference in New Issue