diff --git a/src/main/resources/graph.html b/src/main/resources/graph.html
new file mode 100644
index 000000000..eae90cff0
--- /dev/null
+++ b/src/main/resources/graph.html
@@ -0,0 +1,126 @@
+
+
+
+
+
+
Dependency Graph
+
+
+
+
+
+
+
+
+
+
+
+
+
+Dependencies
+
+
+
+
+
diff --git a/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala b/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala
index 0dcbb0d15..7356e97a9 100644
--- a/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala
+++ b/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala
@@ -33,6 +33,12 @@ trait DependencyGraphKeys {
"Creates a dot file containing the dependency-graph for a project")
val dependencyDotString = TaskKey[String]("dependency-dot-string",
"Creates a String containing the dependency-graph for a project in dot format")
+ val dependencyBrowseGraphTarget = SettingKey[File]("dependency-browse-graph-target",
+ "The location dependency browse graph files should be put.")
+ val dependencyBrowseGraphHTML = TaskKey[URI]("dependency-browse-graph-html",
+ "Creates an HTML page that can be used to view the graph.")
+ val dependencyBrowseGraph = TaskKey[URI]("dependency-browse-graph",
+ "Opens an HTML page that can be used to view the graph.")
val moduleGraph = TaskKey[ModuleGraph]("module-graph",
"The dependency graph for a project")
val asciiGraph = TaskKey[String]("dependency-graph-string",
diff --git a/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala b/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala
index 29c8fc306..038c3282a 100644
--- a/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala
+++ b/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala
@@ -16,8 +16,6 @@
package net.virtualvoid.sbt.graph
-import net.virtualvoid.sbt.graph.backend.{ IvyReport, SbtUpdateReport }
-import net.virtualvoid.sbt.graph.util.IOUtil
import sbt._
import Keys._
@@ -27,6 +25,10 @@ import sbt.complete.Parser
import org.apache.ivy.core.resolve.ResolveOptions
+import net.virtualvoid.sbt.graph.backend.{ IvyReport, SbtUpdateReport }
+import net.virtualvoid.sbt.graph.rendering.DagreHTML
+import net.virtualvoid.sbt.graph.util.IOUtil
+
object DependencyGraphSettings {
import DependencyGraphKeys._
import ModuleGraphProtocol._
@@ -83,6 +85,13 @@ object DependencyGraphSettings {
dependencyDotFile <<= target / "dependencies-%s.dot".format(config.toString),
dependencyDotString <<= dependencyDotStringTask,
dependencyDot <<= writeToFile(dependencyDotString, dependencyDotFile),
+ dependencyBrowseGraphTarget <<= target / "browse-dependency-graph",
+ dependencyBrowseGraphHTML <<= browseGraphHTMLTask,
+ dependencyBrowseGraph <<= (dependencyBrowseGraphHTML, streams).map { (uri, streams) ⇒
+ streams.log.info("Opening in browser...")
+ java.awt.Desktop.getDesktop.browse(uri)
+ uri
+ },
dependencyDotHeader := """digraph "dependency-graph" {
| graph[rankdir="LR"]
| edge [
@@ -118,6 +127,13 @@ object DependencyGraphSettings {
(graph, dotHead, nodeLabel) ⇒ rendering.DOT.dotGraph(graph, dotHead, nodeLabel)
}
+ def browseGraphHTMLTask =
+ (dependencyDotString, dependencyBrowseGraphTarget, streams).map { (graph, target, streams) ⇒
+ val link = DagreHTML.createLink(graph, target)
+ streams.log.info(s"HTML graph written to $link")
+ link
+ }
+
def writeToFile(dataTask: TaskKey[String], fileTask: SettingKey[File]) =
(dataTask, fileTask, streams).map { (data, outFile, streams) ⇒
IOUtil.writeToFile(data, outFile)
diff --git a/src/main/scala/net/virtualvoid/sbt/graph/model.scala b/src/main/scala/net/virtualvoid/sbt/graph/model.scala
index f4b51cfcb..e833d34ab 100644
--- a/src/main/scala/net/virtualvoid/sbt/graph/model.scala
+++ b/src/main/scala/net/virtualvoid/sbt/graph/model.scala
@@ -29,7 +29,8 @@ case class Module(id: ModuleId,
evictedByVersion: Option[String] = None,
error: Option[String] = None) {
def hadError: Boolean = error.isDefined
- def isUsed: Boolean = !evictedByVersion.isDefined
+ def isUsed: Boolean = !isEvicted
+ def isEvicted: Boolean = evictedByVersion.isDefined
}
case class ModuleGraph(nodes: Seq[Module], edges: Seq[Edge]) {
diff --git a/src/main/scala/net/virtualvoid/sbt/graph/rendering/DagreHTML.scala b/src/main/scala/net/virtualvoid/sbt/graph/rendering/DagreHTML.scala
new file mode 100644
index 000000000..3064ef502
--- /dev/null
+++ b/src/main/scala/net/virtualvoid/sbt/graph/rendering/DagreHTML.scala
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 Johannes Rudolph
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.virtualvoid.sbt.graph
+package rendering
+
+import java.io.File
+import java.net.{ URLEncoder, URI }
+
+import net.virtualvoid.sbt.graph.util.IOUtil
+
+object DagreHTML {
+ def createLink(dotGraph: String, targetDirectory: File): URI = {
+ targetDirectory.mkdirs()
+ val graphHTML = new File(targetDirectory, "graph.html")
+ IOUtil.saveResource("graph.html", graphHTML)
+ IOUtil.writeToFile(dotGraph, new File(targetDirectory, "dependencies.dot"))
+
+ val graphString =
+ URLEncoder.encode(dotGraph, "utf8")
+ .replaceAllLiterally("+", "%20")
+
+ IOUtil.writeToFile(s"""data = "$graphString";""", new File(targetDirectory, "dependencies.dot.js"))
+
+ new URI(graphHTML.toURI.toString)
+ }
+}