mirror of https://github.com/sbt/sbt.git
Merge pull request #136 from pcejrowski/master
Added dependencyBrowseTreeHTML and dependencyBrowseTree tasks
This commit is contained in:
commit
83d3e3a5df
|
|
@ -21,6 +21,7 @@ the notes of version [0.8.2](https://github.com/jrudolph/sbt-dependency-graph/tr
|
|||
|
||||
## Main Tasks
|
||||
|
||||
* `dependencyBrowseTree`: Opens a browser window with a visualization of the dependency tree (courtesy of jstree).
|
||||
* `dependencyTree`: Shows an ASCII tree representation of the project's dependencies
|
||||
* `dependencyBrowseGraph`: Opens a browser window with a visualization of the dependency graph (courtesy of graphlib-dot + dagre-d3).
|
||||
* `dependencyList`: Shows a flat list of all transitive dependencies on the sbt console (sorted by organization and name)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>dependencyBrowseTree</title>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
|
||||
<script src="tree.data.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css"/>
|
||||
|
||||
<style>
|
||||
#input-field {
|
||||
display: inline;
|
||||
}
|
||||
#tree_div {
|
||||
font-family: monospace
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Dependencies</h1>
|
||||
Search: <input type="search" id="input-field" value="">
|
||||
<div id="tree_div" class="jstree-no-icons"></div>
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
$('#tree_div').jstree({
|
||||
"plugins": ["search", "sort"],
|
||||
"core": {
|
||||
"data": tree_data
|
||||
}
|
||||
});
|
||||
var to = false;
|
||||
$('#input-field').keyup(function() {
|
||||
if (to) {
|
||||
clearTimeout(to);
|
||||
}
|
||||
to = setTimeout(function() {
|
||||
var v = $('#input-field').val();
|
||||
$('#tree_div').jstree(true).search(v);
|
||||
}, 250);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -49,6 +49,15 @@ trait DependencyGraphKeys {
|
|||
val dependencyBrowseGraph = TaskKey[URI](
|
||||
"dependency-browse-graph",
|
||||
"Opens an HTML page that can be used to view the graph.")
|
||||
val dependencyBrowseTreeTarget = SettingKey[File](
|
||||
"dependency-browse-tree-target",
|
||||
"The location dependency browse tree files should be put.")
|
||||
val dependencyBrowseTreeHTML = TaskKey[URI](
|
||||
"dependency-browse-tree-html",
|
||||
"Creates an HTML page that can be used to view the dependency tree")
|
||||
val dependencyBrowseTree = TaskKey[URI](
|
||||
"dependency-browse-tree",
|
||||
"Opens an HTML page that can be used to view the dependency tree")
|
||||
val moduleGraph = TaskKey[ModuleGraph](
|
||||
"module-graph",
|
||||
"The dependency graph for a project")
|
||||
|
|
@ -97,4 +106,4 @@ trait DependencyGraphKeys {
|
|||
private[graph] val crossProjectId = SettingKey[ModuleID]("dependency-graph-cross-project-id")
|
||||
}
|
||||
|
||||
object DependencyGraphKeys extends DependencyGraphKeys
|
||||
object DependencyGraphKeys extends DependencyGraphKeys
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import sbt._
|
|||
import Keys._
|
||||
import sbt.complete.Parser
|
||||
import net.virtualvoid.sbt.graph.backend.{ IvyReport, SbtUpdateReport }
|
||||
import net.virtualvoid.sbt.graph.rendering.{ AsciiGraph, DagreHTML }
|
||||
import net.virtualvoid.sbt.graph.rendering.{ AsciiGraph, DagreHTML, TreeView }
|
||||
import net.virtualvoid.sbt.graph.util.IOUtil
|
||||
import internal.librarymanagement._
|
||||
import librarymanagement._
|
||||
|
|
@ -74,12 +74,10 @@ object DependencyGraphSettings {
|
|||
dependencyDot := writeToFile(dependencyDotString, dependencyDotFile).value,
|
||||
dependencyBrowseGraphTarget := { target.value / "browse-dependency-graph" },
|
||||
dependencyBrowseGraphHTML := browseGraphHTMLTask.value,
|
||||
dependencyBrowseGraph := {
|
||||
val uri = dependencyBrowseGraphHTML.value
|
||||
streams.value.log.info("Opening in browser...")
|
||||
java.awt.Desktop.getDesktop.browse(uri)
|
||||
uri
|
||||
},
|
||||
dependencyBrowseGraph := openBrowser(dependencyBrowseGraphHTML).value,
|
||||
dependencyBrowseTreeTarget := { target.value / "browse-dependency-tree" },
|
||||
dependencyBrowseTreeHTML := browseTreeHTMLTask.value,
|
||||
dependencyBrowseTree := openBrowser(dependencyBrowseTreeHTML).value,
|
||||
dependencyList := printFromGraph(rendering.FlatList.render(_, _.id.idString)).value,
|
||||
dependencyStats := printFromGraph(rendering.Statistics.renderModuleStatsList).value,
|
||||
dependencyDotHeader :=
|
||||
|
|
@ -139,6 +137,14 @@ object DependencyGraphSettings {
|
|||
link
|
||||
}
|
||||
|
||||
def browseTreeHTMLTask =
|
||||
Def.task {
|
||||
val renderedTree = TreeView.createJson(moduleGraph.value)
|
||||
val link = TreeView.createLink(renderedTree, target.value)
|
||||
streams.value.log.info(s"HTML tree written to $link")
|
||||
link
|
||||
}
|
||||
|
||||
def writeToFile(dataTask: TaskKey[String], fileTask: SettingKey[File]) =
|
||||
Def.task {
|
||||
val outFile = fileTask.value
|
||||
|
|
@ -156,6 +162,14 @@ object DependencyGraphSettings {
|
|||
def printFromGraph(f: ModuleGraph ⇒ String) =
|
||||
Def.task { streams.value.log.info(f(moduleGraph.value)) }
|
||||
|
||||
def openBrowser(uriKey: TaskKey[URI]) =
|
||||
Def.task {
|
||||
val uri = uriKey.value
|
||||
streams.value.log.info("Opening in browser...")
|
||||
java.awt.Desktop.getDesktop.browse(uri)
|
||||
uri
|
||||
}
|
||||
|
||||
def showLicenseInfo(graph: ModuleGraph, streams: TaskStreams): Unit = {
|
||||
val output =
|
||||
graph.nodes.filter(_.isUsed).groupBy(_.license).toSeq.sortBy(_._1).map {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
package net.virtualvoid.sbt.graph.rendering
|
||||
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
|
||||
import net.virtualvoid.sbt.graph.util.IOUtil
|
||||
import net.virtualvoid.sbt.graph.{ Module, ModuleGraph }
|
||||
|
||||
import scala.util.parsing.json.{ JSONArray, JSONObject }
|
||||
|
||||
object TreeView {
|
||||
def createJson(graph: ModuleGraph): String = {
|
||||
val trees = graph.roots
|
||||
.map(module ⇒ processSubtree(graph, module))
|
||||
.toList
|
||||
JSONArray(trees).toString
|
||||
}
|
||||
|
||||
def createLink(graphJson: String, targetDirectory: File): URI = {
|
||||
targetDirectory.mkdirs()
|
||||
val graphHTML = new File(targetDirectory, "tree.html")
|
||||
IOUtil.saveResource("tree.html", graphHTML)
|
||||
IOUtil.writeToFile(graphJson, new File(targetDirectory, "tree.json"))
|
||||
IOUtil.writeToFile(s"tree_data = $graphJson;", new File(targetDirectory, "tree.data.js"))
|
||||
new URI(graphHTML.toURI.toString)
|
||||
}
|
||||
|
||||
private def processSubtree(graph: ModuleGraph, module: Module): JSONObject = {
|
||||
val children = graph.dependencyMap
|
||||
.getOrElse(module.id, List())
|
||||
.map(module ⇒ processSubtree(graph, module))
|
||||
.toList
|
||||
moduleAsJson(module, children)
|
||||
}
|
||||
|
||||
private def moduleAsJson(module: Module, children: List[JSONObject]): JSONObject = {
|
||||
val eviction = module.evictedByVersion.map(version ⇒ s" (evicted by $version)").getOrElse("")
|
||||
val error = module.error.map(err ⇒ s" (errors: $err)").getOrElse("")
|
||||
val text = module.id.idString + eviction + error
|
||||
JSONObject(Map("text" -> text, "children" -> JSONArray(children)))
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue