mirror of https://github.com/sbt/sbt.git
refactor: Unify to dependency-tree
**Problem**
While sbt-dependency-graph is useful, not just for the basic ASCII graph,
but for DOT file generation etc, it adds a large number of settings and
tasks for combination of formats and actions to the point that
we actually disable most of them by default.
**Solution*
I've had an idea for a while that dependencyTree can be implemented
as a inputTask that accepts its own subcommands and options,
and this implements that.
For example, to open the browser that hosts a DOT file, now you can write
dependencyTree dot --browse
This commit is contained in:
parent
09b9a97437
commit
61fe604519
|
|
@ -157,7 +157,7 @@ jobs:
|
|||
if: ${{ matrix.jobtype == 3 }}
|
||||
shell: bash
|
||||
run: |
|
||||
# ./sbt -v "dependencyTreeProj/publishLocal; scripted dependency-graph/*"
|
||||
./sbt -v --client "scripted dependency-graph/*"
|
||||
./sbt -v --client "scripted dependency-management/* project-load/* project-matrix/* java/* run/*"
|
||||
# ./sbt -v --client "scripted plugins/*"
|
||||
# ./sbt -v --client "scripted nio/*"
|
||||
|
|
|
|||
14
build.sbt
14
build.sbt
|
|
@ -628,19 +628,6 @@ lazy val scriptedSbtProj = (project in file("scripted-sbt"))
|
|||
.dependsOn(lmCore)
|
||||
.configure(addSbtIO, addSbtCompilerInterface)
|
||||
|
||||
lazy val dependencyTreeProj = (project in file("dependency-tree"))
|
||||
.dependsOn(sbtProj)
|
||||
.settings(
|
||||
sbtPlugin := true,
|
||||
baseSettings,
|
||||
name := "sbt-dependency-tree",
|
||||
pluginCrossBuild / sbtVersion := version.value,
|
||||
publishMavenStyle := true,
|
||||
sbtPluginPublishLegacyMavenStyle := false,
|
||||
// mimaSettings,
|
||||
mimaPreviousArtifacts := Set.empty,
|
||||
)
|
||||
|
||||
lazy val remoteCacheProj = (project in file("sbt-remote-cache"))
|
||||
.dependsOn(sbtProj)
|
||||
.settings(
|
||||
|
|
@ -1212,7 +1199,6 @@ def allProjects =
|
|||
stdTaskProj,
|
||||
runProj,
|
||||
scriptedSbtProj,
|
||||
dependencyTreeProj,
|
||||
protocolProj,
|
||||
actionsProj,
|
||||
commandProj,
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2023, Scala center
|
||||
* Copyright 2011 - 2022, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt
|
||||
package plugins
|
||||
|
||||
import scala.annotation.nowarn
|
||||
|
||||
object DependencyTreePlugin extends AutoPlugin {
|
||||
object autoImport extends DependencyTreeKeys
|
||||
override def trigger = AllRequirements
|
||||
override def requires = MiniDependencyTreePlugin
|
||||
|
||||
@nowarn
|
||||
val configurations = Vector(Compile, Test, Runtime, Provided, Optional)
|
||||
|
||||
// MiniDependencyTreePlugin provides baseBasicReportingSettings for Compile and Test
|
||||
override lazy val projectSettings: Seq[Def.Setting[?]] =
|
||||
configurations.diff(Vector(Compile, Test)).flatMap { config =>
|
||||
inConfig(config)(DependencyTreeSettings.baseBasicReportingSettings)
|
||||
} ++
|
||||
configurations.flatMap { config =>
|
||||
inConfig(config)(DependencyTreeSettings.baseFullReportingSettings)
|
||||
}
|
||||
}
|
||||
|
|
@ -4442,16 +4442,6 @@ trait BuildExtra extends BuildCommon with DefExtra {
|
|||
Seq(compose(onLoad, add), compose(onUnload, remove))
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Dependency tree plugin.
|
||||
*/
|
||||
def addDependencyTreePlugin: Setting[Seq[ModuleID]] =
|
||||
libraryDependencies += sbtPluginExtra(
|
||||
ModuleID("org.scala-sbt", "sbt-dependency-tree", sbtVersion.value),
|
||||
sbtBinaryVersion.value,
|
||||
scalaBinaryVersion.value
|
||||
)
|
||||
|
||||
/**
|
||||
* Adds Maven resolver plugin.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ object PluginDiscovery:
|
|||
"sbt.plugins.SemanticdbPlugin" -> sbt.plugins.SemanticdbPlugin,
|
||||
"sbt.plugins.JUnitXmlReportPlugin" -> sbt.plugins.JUnitXmlReportPlugin,
|
||||
"sbt.plugins.Giter8TemplatePlugin" -> sbt.plugins.Giter8TemplatePlugin,
|
||||
"sbt.plugins.MiniDependencyTreePlugin" -> sbt.plugins.MiniDependencyTreePlugin,
|
||||
"sbt.plugins.DependencyTreePlugin" -> sbt.plugins.DependencyTreePlugin,
|
||||
)
|
||||
val detectedAutoPlugins = discover[AutoPlugin](AutoPlugins)
|
||||
val allAutoPlugins = (defaultAutoPlugins ++ detectedAutoPlugins.modules) map { (name, value) =>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ import sbt.io.IO
|
|||
|
||||
object DagreHTML {
|
||||
def createLink(dotGraph: String, targetDirectory: File): URI = {
|
||||
val graphHTML = createFile(dotGraph, targetDirectory)
|
||||
new URI(graphHTML.toURI.toString)
|
||||
}
|
||||
|
||||
def createFile(dotGraph: String, targetDirectory: File): File = {
|
||||
targetDirectory.mkdirs()
|
||||
val graphHTML = new File(targetDirectory, "graph.html")
|
||||
TreeView.saveResource("graph.html", graphHTML)
|
||||
|
|
@ -33,7 +38,6 @@ object DagreHTML {
|
|||
s"""data = "$graphString";""",
|
||||
IO.utf8
|
||||
)
|
||||
|
||||
new URI(graphHTML.toURI.toString)
|
||||
graphHTML
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,23 +11,25 @@ package internal
|
|||
package graph
|
||||
package rendering
|
||||
|
||||
import scala.xml.XML
|
||||
import java.io.StringWriter
|
||||
import scala.xml.{ Elem, XML }
|
||||
|
||||
object GraphML {
|
||||
def saveAsGraphML(graph: ModuleGraph, outputFile: String): Unit = {
|
||||
object GraphML:
|
||||
def graphML(graph: ModuleGraph): Elem =
|
||||
val nodesXml =
|
||||
for (n <- graph.nodes)
|
||||
yield <node id={n.id.idString}><data key="d0">
|
||||
<y:ShapeNode>
|
||||
<y:NodeLabel>{n.id.idString}</y:NodeLabel>
|
||||
</y:ShapeNode>
|
||||
</data></node>
|
||||
for n <- graph.nodes
|
||||
yield <node id={n.id.idString}>
|
||||
<data key="d0">
|
||||
<y:ShapeNode>
|
||||
<y:NodeLabel>{n.id.idString}</y:NodeLabel>
|
||||
</y:ShapeNode>
|
||||
</data></node>
|
||||
|
||||
val edgesXml =
|
||||
for (e <- graph.edges)
|
||||
yield <edge source={e._1.idString} target={e._2.idString}/>
|
||||
for e <- graph.edges
|
||||
yield <edge source={e._1.idString} target={e._2.idString}/>
|
||||
|
||||
val xml =
|
||||
val r =
|
||||
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
||||
<key for="node" id="d0" yfiles.type="nodegraphics"/>
|
||||
<graph id="Graph" edgedefault="undirected">
|
||||
|
|
@ -35,7 +37,13 @@ object GraphML {
|
|||
{edgesXml}
|
||||
</graph>
|
||||
</graphml>
|
||||
r
|
||||
|
||||
XML.save(outputFile, xml)
|
||||
}
|
||||
}
|
||||
def graphMLAsString(graph: ModuleGraph): String =
|
||||
val w = StringWriter()
|
||||
XML.write(w, graphML(graph), "UTF-8", false, None.orNull)
|
||||
w.toString()
|
||||
|
||||
def saveAsGraphML(graph: ModuleGraph, outputFile: String): Unit =
|
||||
XML.save(outputFile, graphML(graph))
|
||||
end GraphML
|
||||
|
|
|
|||
|
|
@ -28,12 +28,17 @@ object TreeView {
|
|||
}
|
||||
|
||||
def createLink(graphJson: String, targetDirectory: File): URI = {
|
||||
val graphHTML = createFile(graphJson, targetDirectory)
|
||||
new URI(graphHTML.toURI.toString)
|
||||
}
|
||||
|
||||
def createFile(graphJson: String, targetDirectory: File): File = {
|
||||
targetDirectory.mkdirs()
|
||||
val graphHTML = new File(targetDirectory, "tree.html")
|
||||
saveResource("tree.html", graphHTML)
|
||||
IO.write(new File(targetDirectory, "tree.json"), graphJson, IO.utf8)
|
||||
IO.write(new File(targetDirectory, "tree.data.js"), s"tree_data = $graphJson;", IO.utf8)
|
||||
new URI(graphHTML.toURI.toString)
|
||||
graphHTML
|
||||
}
|
||||
|
||||
private[rendering] def processSubtree(
|
||||
|
|
|
|||
|
|
@ -9,39 +9,15 @@
|
|||
package sbt
|
||||
package plugins
|
||||
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
import sbt.internal.graph.*
|
||||
import sbt.Def.*
|
||||
import sbt.librarymanagement.{ ModuleID, UpdateReport }
|
||||
|
||||
trait MiniDependencyTreeKeys {
|
||||
abstract class DependencyTreeKeys:
|
||||
val dependencyTree = inputKey[String]("Displays dependencies in ascii tree and other formats")
|
||||
val dependencyTreeIncludeScalaLibrary = settingKey[Boolean](
|
||||
"Specifies if scala dependency should be included in dependencyTree output"
|
||||
)
|
||||
val dependencyTree = taskKey[Unit]("Prints an ascii tree of all the dependencies to the console")
|
||||
val asString = taskKey[String]("Provides the string value for the task it is scoped for")
|
||||
// val printToConsole = TaskKey[Unit]("printToConsole", "Prints the tasks value to the console")
|
||||
val toFile = inputKey[File]("Writes the task value to the given file")
|
||||
|
||||
// internal
|
||||
private[sbt] val dependencyTreeIgnoreMissingUpdate =
|
||||
taskKey[UpdateReport]("update used for dependencyTree task")
|
||||
private[sbt] val dependencyTreeModuleGraphStore =
|
||||
taskKey[ModuleGraph]("The stored module-graph from the last run")
|
||||
val whatDependsOn = inputKey[String]("Shows information about what depends on the given module")
|
||||
private[sbt] val dependencyTreeCrossProjectId = settingKey[ModuleID]("")
|
||||
}
|
||||
|
||||
object MiniDependencyTreeKeys extends MiniDependencyTreeKeys
|
||||
|
||||
abstract class DependencyTreeKeys {
|
||||
val dependencyGraphMLFile =
|
||||
settingKey[File]("The location the graphml file should be generated at")
|
||||
val dependencyGraphML =
|
||||
taskKey[File]("Creates a graphml file containing the dependency-graph for a project")
|
||||
val dependencyDotFile =
|
||||
settingKey[File]("The location the dot file should be generated at")
|
||||
val dependencyDotNodeColors = settingKey[Boolean](
|
||||
"The boxes of nodes are painted with colors. Otherwise they're black."
|
||||
)
|
||||
|
|
@ -51,41 +27,18 @@ abstract class DependencyTreeKeys {
|
|||
val dependencyDotHeader = settingKey[String](
|
||||
"The header of the dot file. (e.g. to set your preferred node shapes)"
|
||||
)
|
||||
val dependencyDot = taskKey[File](
|
||||
"Creates a dot file containing the dependency-graph for a project"
|
||||
)
|
||||
val dependencyDotString = taskKey[String](
|
||||
"Creates a String containing the dependency-graph for a project in dot format"
|
||||
)
|
||||
val dependencyBrowseGraphTarget = settingKey[File](
|
||||
"The location dependency browse graph files should be put."
|
||||
)
|
||||
val dependencyBrowseGraphHTML = taskKey[URI](
|
||||
"Creates an HTML page that can be used to view the graph."
|
||||
)
|
||||
val dependencyBrowseGraph = taskKey[URI](
|
||||
"Opens an HTML page that can be used to view the graph."
|
||||
)
|
||||
val dependencyBrowseTreeTarget = settingKey[File](
|
||||
"The location dependency browse tree files should be put."
|
||||
)
|
||||
val dependencyBrowseTreeHTML = taskKey[URI](
|
||||
"Creates an HTML page that can be used to view the dependency tree"
|
||||
)
|
||||
val dependencyBrowseTree = taskKey[URI](
|
||||
"Opens an HTML page that can be used to view the dependency tree"
|
||||
)
|
||||
|
||||
// internal
|
||||
private[sbt] val dependencyTreeIgnoreMissingUpdate =
|
||||
taskKey[UpdateReport]("update used for dependencyTree task")
|
||||
private[sbt] val dependencyTreeModuleGraphStore =
|
||||
taskKey[ModuleGraph]("The stored module-graph from the last run")
|
||||
val whatDependsOn = inputKey[String]("Shows information about what depends on the given module")
|
||||
private[sbt] val dependencyTreeCrossProjectId = settingKey[ModuleID]("")
|
||||
|
||||
// 0 was added to avoid conflict with sbt-dependency-tree
|
||||
private[sbt] val dependencyTreeModuleGraph0 =
|
||||
taskKey[ModuleGraph]("The dependency graph for a project")
|
||||
|
||||
val dependencyList =
|
||||
taskKey[Unit]("Prints a list of all dependencies to the console")
|
||||
val dependencyStats =
|
||||
taskKey[Unit]("Prints statistics for all dependencies to the console")
|
||||
val dependencyLicenseInfo = taskKey[Unit](
|
||||
"Aggregates and shows information about the licenses of dependencies"
|
||||
)
|
||||
}
|
||||
end DependencyTreeKeys
|
||||
|
||||
object DependencyTreeKeys extends DependencyTreeKeys
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2023, Scala center
|
||||
* Copyright 2011 - 2022, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt
|
||||
package plugins
|
||||
|
||||
import sbt.PluginTrigger.AllRequirements
|
||||
import sbt.ProjectExtra.*
|
||||
import sbt.librarymanagement.Configurations.{ Compile, Test }
|
||||
|
||||
object DependencyTreePlugin extends AutoPlugin {
|
||||
object autoImport extends DependencyTreeKeys
|
||||
|
||||
private val defaultDependencyDotHeader =
|
||||
"""|digraph "dependency-graph" {
|
||||
| graph[rankdir="LR"; splines=polyline]
|
||||
| edge [
|
||||
| arrowtail="none"
|
||||
| ]""".stripMargin
|
||||
|
||||
private val defaultDependencyDotNodeLabel =
|
||||
(organization: String, name: String, version: String) =>
|
||||
s"""${organization}<BR/><B>${name}</B><BR/>${version}"""
|
||||
|
||||
import autoImport.*
|
||||
override def trigger: PluginTrigger = AllRequirements
|
||||
override def globalSettings: Seq[Def.Setting[?]] = Seq(
|
||||
dependencyTreeIncludeScalaLibrary :== false,
|
||||
dependencyDotNodeColors :== true,
|
||||
dependencyDotHeader := defaultDependencyDotHeader,
|
||||
dependencyDotNodeLabel := defaultDependencyDotNodeLabel,
|
||||
)
|
||||
override lazy val projectSettings: Seq[Def.Setting[?]] =
|
||||
DependencyTreeSettings.coreSettings ++
|
||||
inConfig(Compile)(DependencyTreeSettings.baseSettings) ++
|
||||
inConfig(Test)(DependencyTreeSettings.baseSettings)
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ package sbt
|
|||
package plugins
|
||||
|
||||
import java.io.File
|
||||
import java.util.Locale
|
||||
|
||||
import sbt.Def.*
|
||||
import sbt.Keys.*
|
||||
|
|
@ -19,15 +20,88 @@ import sbt.internal.graph.backend.SbtUpdateReport
|
|||
import sbt.internal.graph.rendering.{ DagreHTML, TreeView }
|
||||
import sbt.internal.librarymanagement.*
|
||||
import sbt.internal.util.complete.{ Parser, Parsers }
|
||||
import sbt.internal.util.complete.DefaultParsers.*
|
||||
import sbt.io.IO
|
||||
import sbt.io.syntax.*
|
||||
import sbt.librarymanagement.*
|
||||
import sbt.util.Logger
|
||||
import scala.Console
|
||||
|
||||
object DependencyTreeSettings {
|
||||
private[sbt] object DependencyTreeSettings:
|
||||
import sjsonnew.BasicJsonProtocol.*
|
||||
import MiniDependencyTreeKeys.*
|
||||
import DependencyTreeKeys.*
|
||||
|
||||
enum Arg:
|
||||
case Help
|
||||
case Quiet
|
||||
case Format(format: Fmt)
|
||||
case Out(out: String)
|
||||
case Browse
|
||||
|
||||
enum Fmt:
|
||||
case Tree
|
||||
case List
|
||||
case Stats
|
||||
case Json
|
||||
case Graph
|
||||
case HtmlGraph
|
||||
case Html
|
||||
case Xml
|
||||
|
||||
// Parser for the supported formats
|
||||
lazy val FmtParser: Parser[Fmt] =
|
||||
(("tree" ^^^ Fmt.Tree)
|
||||
| ("list" ^^^ Fmt.List)
|
||||
| ("stats" ^^^ Fmt.Stats)
|
||||
| ("json" ^^^ Fmt.Json)
|
||||
| ("dot" ^^^ Fmt.Graph)
|
||||
| ("graph" ^^^ Fmt.Graph)
|
||||
| ("html-graph" ^^^ Fmt.HtmlGraph)
|
||||
| ("html" ^^^ Fmt.Html)
|
||||
| ("xml" ^^^ Fmt.Xml))
|
||||
|
||||
lazy val ArgParser: Parser[Arg] =
|
||||
Space ~> (("help" ^^^ Arg.Help)
|
||||
| ("--help" ^^^ Arg.Help)
|
||||
| FmtParser.map(fmt => Arg.Format(fmt)))
|
||||
|
||||
lazy val ArgOptionParser: Parser[Arg] =
|
||||
Space ~> (("--quiet" ^^^ Arg.Quiet)
|
||||
| ("--browse" ^^^ Arg.Browse)
|
||||
| ("--out" ~> Space ~> StringBasic)
|
||||
.map(Arg.Out(_))
|
||||
.examples("--out /tmp/deps.txt"))
|
||||
|
||||
// You can have zero-or-one format and options afterwards
|
||||
lazy val ArgsParser: Parser[Seq[Arg]] =
|
||||
(ArgParser.? ~ ArgOptionParser.*).map:
|
||||
case (a, opts) => a.toList ::: opts.toList
|
||||
|
||||
def usageText: String =
|
||||
s"""dependencyTree task displays the dependency graph.
|
||||
|
||||
USAGE
|
||||
dependencyTree [subcommand] [options]
|
||||
|
||||
SUBCOMMAND
|
||||
tree Prints ascii tree (default)
|
||||
list Prints list of all dependencies
|
||||
graph Prints GraphViz DOT file
|
||||
dot Same as graph
|
||||
html Creates HTML page
|
||||
html-graph Creates HTML page with GraphViz DOT file
|
||||
json Prints JSON
|
||||
xml Prints GraphML
|
||||
stats Prints statistics for all dependencies
|
||||
help Prints this help
|
||||
|
||||
OPTIONS
|
||||
--quiet Returns the output as task value, replacing asString
|
||||
--out <file> Writes the output to the specified file;
|
||||
The file extension will influence the default subcommand
|
||||
--browse Opens the browser when combined with graph or html subcommand
|
||||
"""
|
||||
|
||||
/**
|
||||
* Core settings needed for any graphing tasks.
|
||||
*/
|
||||
|
|
@ -59,10 +133,10 @@ object DependencyTreeSettings {
|
|||
)
|
||||
|
||||
/**
|
||||
* MiniDependencyTreePlugin includes these settings for Compile and Test scopes
|
||||
* DependencyTreePlugin includes these settings for Compile and Test scopes
|
||||
* to provide dependencyTree task.
|
||||
*/
|
||||
lazy val baseBasicReportingSettings: Seq[Def.Setting[?]] =
|
||||
lazy val baseSettings: Seq[Def.Setting[?]] =
|
||||
Seq(
|
||||
dependencyTreeCrossProjectId := CrossVersion(scalaVersion.value, scalaBinaryVersion.value)(
|
||||
projectID.value
|
||||
|
|
@ -82,57 +156,81 @@ object DependencyTreeSettings {
|
|||
.storeAs(dependencyTreeModuleGraphStore)
|
||||
.triggeredBy(dependencyTreeModuleGraph0)
|
||||
.value,
|
||||
) ++ {
|
||||
renderingTaskSettings(dependencyTree) :+ {
|
||||
dependencyTree / asString := {
|
||||
rendering.AsciiTree.asciiTree(dependencyTreeModuleGraph0.value, asciiGraphWidth.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the maximum strength settings for DependencyTreePlugin.
|
||||
*/
|
||||
lazy val baseFullReportingSettings: Seq[Def.Setting[?]] =
|
||||
Seq(
|
||||
// browse
|
||||
dependencyBrowseGraphTarget := { target.value / "browse-dependency-graph" },
|
||||
dependencyBrowseGraphHTML := browseGraphHTMLTask.value,
|
||||
dependencyBrowseGraph := openBrowser(dependencyBrowseGraphHTML).value,
|
||||
dependencyBrowseTreeTarget := { target.value / "browse-dependency-tree" },
|
||||
dependencyBrowseTreeHTML := browseTreeHTMLTask.value,
|
||||
dependencyBrowseTree := openBrowser(dependencyBrowseTreeHTML).value,
|
||||
// dot support
|
||||
dependencyDotFile := {
|
||||
val config = configuration.value
|
||||
target.value / s"dependencies-${config.toString}.dot"
|
||||
},
|
||||
dependencyDot / asString := Def.uncached(
|
||||
rendering.DOT.dotGraph(
|
||||
dependencyTreeModuleGraph0.value,
|
||||
dependencyDotHeader.value,
|
||||
dependencyDotNodeLabel.value,
|
||||
rendering.DOT.HTMLLabelRendering.AngleBrackets,
|
||||
dependencyDotNodeColors.value
|
||||
)
|
||||
),
|
||||
dependencyDot := writeToFile(dependencyDot / asString, dependencyDotFile).value,
|
||||
dependencyDotHeader :=
|
||||
"""|digraph "dependency-graph" {
|
||||
| graph[rankdir="LR"; splines=polyline]
|
||||
| edge [
|
||||
| arrowtail="none"
|
||||
| ]""".stripMargin,
|
||||
dependencyDotNodeColors := true,
|
||||
dependencyDotNodeLabel := { (organization: String, name: String, version: String) =>
|
||||
s"""${organization}<BR/><B>${name}</B><BR/>${version}"""
|
||||
},
|
||||
// GraphML support
|
||||
dependencyGraphMLFile := {
|
||||
val config = configuration.value
|
||||
target.value / s"dependencies-${config.toString}.graphml"
|
||||
},
|
||||
dependencyGraphML := dependencyGraphMLTask.value,
|
||||
dependencyTree := (Def.inputTaskDyn {
|
||||
val s = streams.value
|
||||
val args = ArgsParser.parsed.toList
|
||||
val isHelp = args.contains(Arg.Help)
|
||||
val isQuiet = args.contains(Arg.Quiet)
|
||||
val isBrowse = args.contains(Arg.Browse)
|
||||
if isHelp then Def.task { s.log.info(usageText); "" }
|
||||
else
|
||||
val formatOpt = (args
|
||||
.collect { case Arg.Format(fmt) => fmt })
|
||||
.reverse
|
||||
.headOption
|
||||
val outFileNameOpt = (args
|
||||
.collect { case Arg.Out(out) => out })
|
||||
.reverse
|
||||
.headOption
|
||||
val outFileOpt = outFileNameOpt.map(new File(_))
|
||||
val format = (formatOpt, outFileNameOpt) match
|
||||
case (None, Some(out)) if out.endsWith(".dot") => Fmt.Graph
|
||||
case (None, Some(out)) if out.endsWith(".html") => Fmt.Html
|
||||
case (None, Some(out)) if out.endsWith(".xml") => Fmt.Xml
|
||||
case (None, Some(out)) if out.endsWith(".json") => Fmt.Json
|
||||
case (Some(Fmt.Graph), Some(out)) if out.endsWith(".html") => Fmt.HtmlGraph
|
||||
case (Some(Fmt.Graph), _) if isBrowse => Fmt.HtmlGraph
|
||||
case (Some(fmt), _) => fmt
|
||||
case _ => Fmt.Tree
|
||||
val config = configuration.value.name
|
||||
val targetDir = target.value / config / format.toString.toLowerCase(Locale.ENGLISH)
|
||||
format match
|
||||
case Fmt.Tree | Fmt.List | Fmt.Stats =>
|
||||
Def.task {
|
||||
val graph = dependencyTreeModuleGraph0.value
|
||||
val output = format match
|
||||
case Fmt.List => rendering.FlatList.render(_.id.idString)(graph)
|
||||
case Fmt.Stats => rendering.Statistics.renderModuleStatsList(graph)
|
||||
case _ => rendering.AsciiTree.asciiTree(graph, asciiGraphWidth.value)
|
||||
handleOutput(output, outFileOpt, isQuiet, s.log)
|
||||
}
|
||||
case Fmt.Json =>
|
||||
Def.task {
|
||||
val graph = dependencyTreeModuleGraph0.value
|
||||
val output = TreeView.createJson(graph)
|
||||
handleOutput(output, outFileOpt, isQuiet, s.log)
|
||||
}
|
||||
case Fmt.Xml =>
|
||||
Def.task {
|
||||
val graph = dependencyTreeModuleGraph0.value
|
||||
val output = rendering.GraphML.graphMLAsString(graph)
|
||||
handleOutput(output, outFileOpt, isQuiet, s.log)
|
||||
}
|
||||
case Fmt.Html =>
|
||||
Def.task {
|
||||
val graph = dependencyTreeModuleGraph0.value
|
||||
val renderedTree = TreeView.createJson(graph)
|
||||
val outputFile = TreeView.createFile(renderedTree, targetDir)
|
||||
if isBrowse then openBrowser(outputFile.toURI)
|
||||
outputFile.getAbsolutePath
|
||||
}
|
||||
case Fmt.Graph | Fmt.HtmlGraph =>
|
||||
Def.task {
|
||||
val graph = dependencyTreeModuleGraph0.value
|
||||
val output = rendering.DOT.dotGraph(
|
||||
graph,
|
||||
dependencyDotHeader.value,
|
||||
dependencyDotNodeLabel.value,
|
||||
rendering.DOT.HTMLLabelRendering.AngleBrackets,
|
||||
dependencyDotNodeColors.value
|
||||
)
|
||||
if format == Fmt.Graph then handleOutput(output, outFileOpt, isQuiet, s.log)
|
||||
else
|
||||
val outputFile = DagreHTML.createFile(output, targetDir)
|
||||
if isBrowse then openBrowser(outputFile.toURI)
|
||||
outputFile.getAbsolutePath
|
||||
}
|
||||
}).evaluated,
|
||||
whatDependsOn := {
|
||||
val ArtifactPattern(org, name, versionFilter) = artifactPatternParser.parsed
|
||||
val graph = dependencyTreeModuleGraph0.value
|
||||
|
|
@ -155,112 +253,32 @@ object DependencyTreeSettings {
|
|||
}
|
||||
output
|
||||
},
|
||||
) ++
|
||||
renderingAlternatives.flatMap { (key, renderer) => renderingTaskSettings(key, renderer) }
|
||||
|
||||
def renderingAlternatives: Seq[(TaskKey[Unit], ModuleGraph => String)] =
|
||||
Seq(
|
||||
dependencyList -> rendering.FlatList.render(_.id.idString),
|
||||
dependencyStats -> rendering.Statistics.renderModuleStatsList,
|
||||
dependencyLicenseInfo -> rendering.LicenseInfo.render
|
||||
)
|
||||
|
||||
def renderingTaskSettings(key: TaskKey[Unit], renderer: ModuleGraph => String): Seq[Setting[?]] =
|
||||
renderingTaskSettings(key) :+ {
|
||||
key / asString := renderer(dependencyTreeModuleGraph0.value)
|
||||
}
|
||||
private def handleOutput(
|
||||
content: String,
|
||||
outputFileOpt: Option[File],
|
||||
isQuiet: Boolean,
|
||||
log: Logger,
|
||||
): String =
|
||||
outputFileOpt match
|
||||
case Some(output) =>
|
||||
IO.write(output, content, IO.utf8)
|
||||
if !isQuiet then log.info(s"wrote dependencies to $output")
|
||||
output.toString
|
||||
case None =>
|
||||
if isQuiet then content
|
||||
else
|
||||
Console.out.println(content); ""
|
||||
|
||||
def renderingTaskSettings(key: TaskKey[Unit]): Seq[Setting[?]] =
|
||||
Seq(
|
||||
key := {
|
||||
val s = streams.value
|
||||
val str = (key / asString).value
|
||||
synchronized {
|
||||
s.log.info(str)
|
||||
}
|
||||
},
|
||||
(key / toFile) := {
|
||||
val (targetFile, force) = targetFileAndForceParser.parsed
|
||||
writeToFile(key.key.label, (key / asString).value, targetFile, force, streams.value)
|
||||
},
|
||||
)
|
||||
|
||||
def dependencyGraphMLTask =
|
||||
Def.task {
|
||||
val resultFile = dependencyGraphMLFile.value
|
||||
val graph = dependencyTreeModuleGraph0.value
|
||||
rendering.GraphML.saveAsGraphML(graph, resultFile.getAbsolutePath)
|
||||
streams.value.log.info(s"Wrote dependency graph to '${resultFile}'")
|
||||
resultFile
|
||||
}
|
||||
|
||||
def browseGraphHTMLTask =
|
||||
Def.task {
|
||||
val graph = dependencyTreeModuleGraph0.value
|
||||
val dotGraph = rendering.DOT.dotGraph(
|
||||
graph,
|
||||
dependencyDotHeader.value,
|
||||
dependencyDotNodeLabel.value,
|
||||
rendering.DOT.HTMLLabelRendering.AngleBrackets,
|
||||
dependencyDotNodeColors.value
|
||||
)
|
||||
val link = DagreHTML.createLink(dotGraph, dependencyBrowseGraphTarget.value)
|
||||
streams.value.log.info(s"HTML graph written to $link")
|
||||
link
|
||||
}
|
||||
|
||||
def browseTreeHTMLTask =
|
||||
Def.task {
|
||||
val graph = dependencyTreeModuleGraph0.value
|
||||
val renderedTree = TreeView.createJson(graph)
|
||||
val link = TreeView.createLink(renderedTree, dependencyBrowseTreeTarget.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
|
||||
IO.write(outFile, dataTask.value, IO.utf8)
|
||||
|
||||
streams.value.log.info(s"Wrote dependency graph to '${outFile}'")
|
||||
outFile
|
||||
}
|
||||
|
||||
def writeToFile(
|
||||
what: String,
|
||||
data: String,
|
||||
targetFile: File,
|
||||
force: Boolean,
|
||||
streams: TaskStreams
|
||||
): File =
|
||||
if (targetFile.exists && !force)
|
||||
throw new RuntimeException(
|
||||
s"Target file for $what already exists at ${targetFile.getAbsolutePath}. Use '-f' to override"
|
||||
)
|
||||
else {
|
||||
IO.write(targetFile, data, IO.utf8)
|
||||
|
||||
streams.log.info(s"Wrote $what to '$targetFile'")
|
||||
targetFile
|
||||
}
|
||||
|
||||
def absoluteReportPath = (file: File) => file.getAbsolutePath
|
||||
|
||||
def openBrowser(uriKey: TaskKey[URI]) =
|
||||
Def.task {
|
||||
val uri = uriKey.value
|
||||
streams.value.log.info(s"Opening ${uri} in browser...")
|
||||
val desktop = java.awt.Desktop.getDesktop
|
||||
desktop.synchronized {
|
||||
desktop.browse(uri)
|
||||
}
|
||||
uri
|
||||
def openBrowser(uri: URI): Unit =
|
||||
val desktop = java.awt.Desktop.getDesktop
|
||||
desktop.synchronized {
|
||||
desktop.browse(uri)
|
||||
}
|
||||
|
||||
case class ArtifactPattern(organization: String, name: String, version: Option[String])
|
||||
|
||||
import sbt.internal.util.complete.DefaultParsers.*
|
||||
val artifactPatternParser: Def.Initialize[State => Parser[ArtifactPattern]] =
|
||||
Keys.resolvedScoped { ctx => (state: State) =>
|
||||
val graph =
|
||||
|
|
@ -320,4 +338,4 @@ object DependencyTreeSettings {
|
|||
case _ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
end DependencyTreeSettings
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2023, Scala center
|
||||
* Copyright 2011 - 2022, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt
|
||||
package plugins
|
||||
|
||||
import sbt.PluginTrigger.AllRequirements
|
||||
import sbt.ProjectExtra.*
|
||||
import sbt.librarymanagement.Configurations.{ Compile, Test }
|
||||
|
||||
object MiniDependencyTreePlugin extends AutoPlugin {
|
||||
object autoImport extends MiniDependencyTreeKeys
|
||||
|
||||
import autoImport.*
|
||||
override def trigger: PluginTrigger = AllRequirements
|
||||
override def globalSettings: Seq[Def.Setting[?]] = Seq(
|
||||
dependencyTreeIncludeScalaLibrary := false
|
||||
)
|
||||
override lazy val projectSettings: Seq[Def.Setting[?]] =
|
||||
DependencyTreeSettings.coreSettings ++
|
||||
inConfig(Compile)(DependencyTreeSettings.baseBasicReportingSettings) ++
|
||||
inConfig(Test)(DependencyTreeSettings.baseBasicReportingSettings)
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2023, Scala center
|
||||
* Copyright 2011 - 2022, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt
|
||||
package plugins
|
||||
|
||||
import sbt.internal.util.complete.Parser
|
||||
import DependencyTreeSettings.{ Arg, ArgsParser, Fmt, FmtParser }
|
||||
|
||||
object DependencyTreeTest extends verify.BasicTestSuite:
|
||||
test("Parse args") {
|
||||
assert(parseArgs(List("help")) == List(Arg.Help))
|
||||
assert(parseArgs(List("--help")) == List(Arg.Help))
|
||||
assert(parseArgs(List("--quiet")) == List(Arg.Quiet))
|
||||
assert(parseArgs(List("tree")) == List(Arg.Format(Fmt.Tree)))
|
||||
assert(parseArgs(List("--out", "/tmp/deps.txt")) == List(Arg.Out("/tmp/deps.txt")))
|
||||
assert(parseArgs(List("--browse")) == List(Arg.Browse))
|
||||
}
|
||||
|
||||
test("Parse format") {
|
||||
assert(parseFormat("tree") == Fmt.Tree)
|
||||
assert(parseFormat("list") == Fmt.List)
|
||||
assert(parseFormat("stats") == Fmt.Stats)
|
||||
assert(parseFormat("json") == Fmt.Json)
|
||||
assert(parseFormat("html") == Fmt.Html)
|
||||
assert(parseFormat("graph") == Fmt.Graph)
|
||||
}
|
||||
|
||||
def parseArgs(args: List[String]): Seq[Arg] =
|
||||
Parser.parse(" " + args.mkString(" "), ArgsParser) match
|
||||
case Right(args) => args
|
||||
case Left(err) => sys.error(err)
|
||||
|
||||
def parseFormat(fmt: String): Fmt =
|
||||
Parser.parse(fmt, FmtParser) match
|
||||
case Right(x) => x
|
||||
case Left(err) => sys.error(err)
|
||||
end DependencyTreeTest
|
||||
|
|
@ -5,11 +5,13 @@ name := "asciiGraphWidthSpecs"
|
|||
|
||||
lazy val whenIsDefault = (project in file("when-is-default"))
|
||||
.settings(
|
||||
name := "whenisdefault",
|
||||
libraryDependencies += "org.typelevel" %% "cats-effect" % "3.1.0",
|
||||
check := checkTask.value
|
||||
)
|
||||
lazy val whenIs20 = (project in file("when-is-20"))
|
||||
.settings(
|
||||
name := "whenis20",
|
||||
asciiGraphWidth := 20,
|
||||
libraryDependencies += "org.typelevel" %% "cats-effect" % "3.1.0",
|
||||
check := checkTask.value
|
||||
|
|
@ -19,6 +21,11 @@ lazy val check = taskKey[Unit]("check")
|
|||
lazy val checkTask = Def.task {
|
||||
val context = thisProject.value
|
||||
val expected = IO.read(file(s"${context.base}/expected.txt"))
|
||||
val actual = (Compile / dependencyTree / asString).value
|
||||
require(actual == expected, s"${context.id} is failed.")
|
||||
val actual = (Compile / dependencyTree).toTask(" --quiet").value
|
||||
require(actual == expected, s"""${context.id} failed
|
||||
|
||||
actual: $actual
|
||||
|
||||
expected: $expected
|
||||
""")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
addDependencyTreePlugin
|
||||
// addDependencyTreePlugin
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ updateOptions := updateOptions.value.withCachedResolution(true)
|
|||
|
||||
TaskKey[Unit]("check") := {
|
||||
val report = (Test / updateFull).value
|
||||
val graph = (Test / dependencyTree / asString).value
|
||||
val graph = (Test / dependencyTree).toTask(" --quiet").value
|
||||
|
||||
def sanitize(str: String): String = str.split('\n').drop(1).mkString("\n")
|
||||
val expectedGraph =
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
ThisBuild / scalaVersion := "2.12.20"
|
||||
|
||||
name := "foo"
|
||||
libraryDependencies ++= Seq(
|
||||
"org.slf4j" % "slf4j-api" % "1.7.2",
|
||||
"ch.qos.logback" % "logback-classic" % "1.0.7"
|
||||
|
|
@ -8,8 +9,11 @@ csrMavenDependencyOverride := false
|
|||
|
||||
TaskKey[Unit]("check") := {
|
||||
val report = updateFull.value
|
||||
val graph = (Test / dependencyTree / asString).value
|
||||
def sanitize(str: String): String = str.split('\n').drop(1).map(_.trim).mkString("\n")
|
||||
val graph = (Test / dependencyTree).toTask(" --quiet").value
|
||||
def sanitize(str: String): String = str.linesIterator.toList
|
||||
.drop(1)
|
||||
.map(_.trim)
|
||||
.mkString("\n")
|
||||
|
||||
/*
|
||||
Started to return:
|
||||
|
|
@ -31,8 +35,8 @@ default:sbt_8ae1da13_2.12:0.1.0-SNAPSHOT [S]
|
|||
| |
|
||||
| +-org.slf4j:slf4j-api:1.7.2
|
||||
| """.stripMargin
|
||||
IO.writeLines(file("/tmp/blib"), sanitize(graph).split("\n"))
|
||||
IO.writeLines(file("/tmp/blub"), sanitize(expectedGraph).split("\n"))
|
||||
// IO.writeLines(file("/tmp/blib"), sanitize(graph).split("\n"))
|
||||
// IO.writeLines(file("/tmp/blub"), sanitize(expectedGraph).split("\n"))
|
||||
require(sanitize(graph) == sanitize(expectedGraph), "Graph for report %s was '\n%s' but should have been '\n%s'" format (report, sanitize(graph), sanitize(expectedGraph)))
|
||||
()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ version := "0.1"
|
|||
name := "blubber"
|
||||
libraryDependencies += "org.typelevel" %% "cats-effect" % "2.2.0"
|
||||
TaskKey[Unit]("check") := {
|
||||
val candidates = "tree list stats licenses".split(' ').map(_.trim)
|
||||
val candidates = "tree list stats".split(' ').map(_.trim)
|
||||
candidates.foreach { c =>
|
||||
val expected = new File(s"expected/$c.txt")
|
||||
val actual = new File(s"target/$c.txt")
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
> dependencyTree --out target/tree.txt
|
||||
> dependencyTree list --out target/list.txt
|
||||
> dependencyTree stats --out target/stats.txt
|
||||
# > dependencyLicenseInfo/toFile target/licenses.txt
|
||||
> check
|
||||
|
|
@ -5,7 +5,7 @@ libraryDependencies +=
|
|||
|
||||
TaskKey[Unit]("check") := {
|
||||
val report = updateFull.value
|
||||
val graph = (Test / dependencyTree / asString).value
|
||||
val graph = (Test / dependencyTree).toTask(" --quiet").value
|
||||
|
||||
def sanitize(str: String): String = str.split('\n').drop(1).mkString("\n")
|
||||
val expectedGraph =
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ lazy val test_project = project
|
|||
.dependsOn(justADependencyProject, justATransitiveDependencyProject)
|
||||
.settings(
|
||||
TaskKey[Unit]("check") := {
|
||||
val dotFile = (dependencyDot in Compile).value
|
||||
val graph = (Compile / dependencyTree).toTask(" dot --quiet").value
|
||||
val expectedGraph =
|
||||
"""digraph "dependency-graph" {
|
||||
| graph[rankdir="LR"; splines=polyline]
|
||||
|
|
@ -23,7 +23,7 @@ lazy val test_project = project
|
|||
| ]
|
||||
| "justadependencyproject:justadependencyproject_2.9.2:0.1-SNAPSHOT"[shape=box label=<justadependencyproject<BR/><B>justadependencyproject_2.9.2</B><BR/>0.1-SNAPSHOT> style="" penwidth="5" color="#B6E316"]
|
||||
| "justatransitivedependencyproject:justatransitivedependencyproject_2.9.2:0.1-SNAPSHOT"[shape=box label=<justatransitivedependencyproject<BR/><B>justatransitivedependencyproject_2.9.2</B><BR/>0.1-SNAPSHOT> style="" penwidth="5" color="#0E92BE"]
|
||||
| "justatransitivedependencyendpointproject:justatransitivedependencyendpointproject_2.9.2:0.1-SNAPSHOT"[shape=box label=<justatransitivedependencyendpointproject<BR/><B>justatransitivedependencyendpointproject_2.9.2</B><BR/>0.1-SNAPSHOT> style="" penwidth="5" color="#9EAD1B"]
|
||||
| "justatransitivedependencyendpointproject:justatransitivedependencyendpointproject_2.9.2:0.1-SNAPSHOT"[shape=box label=<justatransitivedependencyendpointproject<BR/><B>justatransitivedependencyendpointproject_2.9.2</B><BR/>0.1-SNAPSHOT> style="" penwidth="5" color="#A1168F"]
|
||||
| "test_project:test_project_2.9.2:0.1-SNAPSHOT"[shape=box label=<test_project<BR/><B>test_project_2.9.2</B><BR/>0.1-SNAPSHOT> style="" penwidth="5" color="#C37661"]
|
||||
| "justatransitivedependencyproject:justatransitivedependencyproject_2.9.2:0.1-SNAPSHOT" -> "justatransitivedependencyendpointproject:justatransitivedependencyendpointproject_2.9.2:0.1-SNAPSHOT"
|
||||
| "test_project:test_project_2.9.2:0.1-SNAPSHOT" -> "justadependencyproject:justadependencyproject_2.9.2:0.1-SNAPSHOT"
|
||||
|
|
@ -31,8 +31,7 @@ lazy val test_project = project
|
|||
|}
|
||||
""".stripMargin
|
||||
|
||||
val graph: String = scala.io.Source.fromFile(dotFile.getAbsolutePath).mkString
|
||||
val errors = compareByLine(graph, expectedGraph)
|
||||
val errors = compareByLine(graph.trim, expectedGraph.trim)
|
||||
require(errors.isEmpty, errors.mkString("\n"))
|
||||
()
|
||||
}
|
||||
|
|
@ -40,7 +39,7 @@ lazy val test_project = project
|
|||
|
||||
def compareByLine(got: String, expected: String): Seq[String] = {
|
||||
val errors = ListBuffer[String]()
|
||||
got.split("\n").zip(expected.split("\n").toSeq).zipWithIndex.foreach {
|
||||
got.linesIterator.toList.sorted.zip(expected.linesIterator.toList.sorted).zipWithIndex.foreach {
|
||||
case ((got_line: String, expected_line: String), i: Int) =>
|
||||
if (got_line != expected_line) {
|
||||
errors.append("""not matching lines at line %s
|
||||
|
|
@ -49,5 +48,5 @@ def compareByLine(got: String, expected: String): Seq[String] = {
|
|||
|""".stripMargin.format(i, expected_line, got_line))
|
||||
}
|
||||
}
|
||||
errors
|
||||
errors.toList
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
addDependencyTreePlugin
|
||||
|
|
@ -14,7 +14,7 @@ lazy val test_project = project
|
|||
.dependsOn(justADependencyProject, justATransitiveDependencyProject)
|
||||
.settings(
|
||||
TaskKey[Unit]("check") := {
|
||||
val htmlFile = (dependencyBrowseGraphHTML in Compile).value
|
||||
val htmlFile = (Compile / dependencyTree).toTask(" html-graph").value
|
||||
val expectedHtml =
|
||||
"""<!doctype html>
|
||||
|
|
||||
|
|
@ -60,11 +60,10 @@ lazy val test_project = project
|
|||
|<script>
|
||||
| d3.select("#graph").graphviz().renderDot(decodeURIComponent(data));
|
||||
|</script>
|
||||
|
|
||||
""".stripMargin
|
||||
|
||||
val html: String = scala.io.Source.fromFile(htmlFile).mkString
|
||||
val errors = compareByLine(html, expectedHtml)
|
||||
val errors = compareByLine(html.trim, expectedHtml.trim)
|
||||
require(errors.isEmpty, errors.mkString("\n"))
|
||||
()
|
||||
}
|
||||
|
|
@ -72,7 +71,7 @@ lazy val test_project = project
|
|||
|
||||
def compareByLine(got: String, expected: String): Seq[String] = {
|
||||
val errors = ListBuffer[String]()
|
||||
got.split("\n").zip(expected.split("\n").toSeq).zipWithIndex.foreach {
|
||||
got.linesIterator.toList.zip(expected.linesIterator.toList).zipWithIndex.foreach {
|
||||
case ((got_line: String, expected_line: String), i: Int) =>
|
||||
if (got_line != expected_line) {
|
||||
errors.append("""not matching lines at line %s
|
||||
|
|
@ -81,5 +80,5 @@ def compareByLine(got: String, expected: String): Seq[String] = {
|
|||
|""".stripMargin.format(i, expected_line, got_line))
|
||||
}
|
||||
}
|
||||
errors
|
||||
errors.toList
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
addDependencyTreePlugin
|
||||
|
|
@ -1 +0,0 @@
|
|||
addDependencyTreePlugin
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
> dependencyTree/toFile target/tree.txt
|
||||
> dependencyList/toFile target/list.txt
|
||||
> dependencyStats/toFile target/stats.txt
|
||||
> dependencyLicenseInfo/toFile target/licenses.txt
|
||||
> check
|
||||
|
|
@ -11,26 +11,26 @@ libraryDependencies ++= Seq(
|
|||
val check = TaskKey[Unit]("check")
|
||||
|
||||
check := {
|
||||
def sanitize(str: String): String = str.split('\n').map(_.trim).mkString("\n")
|
||||
def sanitize(str: String): String = str.linesIterator.toList.map(_.trim).mkString("\n")
|
||||
def checkOutput(output: String, expected: String): Unit =
|
||||
require(sanitize(expected) == sanitize(output), s"Tree should have been [\n${sanitize(expected)}\n] but was [\n${sanitize(output)}\n]")
|
||||
require(sanitize(expected) == sanitize(output),
|
||||
s"Tree should have been [\n${expected}\n] but was [\n${output}\n]")
|
||||
|
||||
val withVersion =
|
||||
(Compile / whatDependsOn)
|
||||
.toTask(" org.typelevel cats-core_2.13 2.6.0")
|
||||
.value
|
||||
val expectedGraphWithVersion = {
|
||||
val expectedGraphWithVersion =
|
||||
"""org.typelevel:cats-core_2.13:2.6.0 [S]
|
||||
|+-org.typelevel:cats-effect-kernel_2.13:3.1.0 [S]
|
||||
|+-org.typelevel:cats-effect-std_2.13:3.1.0 [S]
|
||||
|| +-org.typelevel:cats-effect_2.13:3.1.0 [S]
|
||||
|| +-whatdependson:whatdependson_2.13:0.1.0-SNAPSHOT [S]
|
||||
||
|
||||
|+-org.typelevel:cats-effect_2.13:3.1.0 [S]
|
||||
|+-whatdependson:whatdependson_2.13:0.1.0-SNAPSHOT [S]""".stripMargin
|
||||
}
|
||||
| +-org.typelevel:cats-effect-kernel_2.13:3.1.0 [S]
|
||||
| +-org.typelevel:cats-effect-std_2.13:3.1.0 [S]
|
||||
| | +-org.typelevel:cats-effect_2.13:3.1.0 [S]
|
||||
| | +-whatdependson:whatdependson_2.13:0.1.0-SNAPSHOT [S]
|
||||
| |
|
||||
| +-org.typelevel:cats-effect_2.13:3.1.0 [S]
|
||||
| +-whatdependson:whatdependson_2.13:0.1.0-SNAPSHOT [S]""".stripMargin
|
||||
|
||||
checkOutput(withVersion.trim, expectedGraphWithVersion.trim)
|
||||
checkOutput(withVersion.trim, expectedGraphWithVersion)
|
||||
|
||||
val withoutVersion =
|
||||
(Compile / whatDependsOn)
|
||||
|
|
|
|||
Loading…
Reference in New Issue