From 17b75453b59ffea4ad279d606d86093434e4893a Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 21 Sep 2020 21:43:16 -0400 Subject: [PATCH] In-source sbt-dependency-graph Ref https://github.com/sbt/sbt-dependency-graph/issues/178 This in-sources sbt-dependency-graph. --- .travis.yml | 2 +- .../scala/sbt/internal/util/Terminal.scala | 4 + main/src/main/scala/sbt/Defaults.scala | 2 +- .../scala/sbt/internal/PluginDiscovery.scala | 1 + .../scala/sbt/internal/SettingGraph.scala | 48 ++- .../internal/graph/DependencyGraphKeys.scala | 95 +++++ .../internal/graph/GraphTransformations.scala | 58 +++ .../internal/graph/backend/IvyReport.scala | 67 ++++ .../graph/backend/SbtUpdateReport.scala | 54 +++ .../main/scala/sbt/internal/graph/model.scala | 105 ++++++ .../scala/sbt/internal/graph/package.scala | 14 + .../internal/graph/rendering/AsciiTree.scala | 42 +++ .../sbt/internal}/graph/rendering/DOT.scala | 58 +-- .../internal/graph/rendering/DagreHTML.scala | 38 ++ .../internal/graph/rendering/FlatList.scala | 20 ++ .../internal/graph/rendering/GraphML.scala | 40 +++ .../graph/rendering/LicenseInfo.scala | 26 ++ .../internal/graph/rendering/Statistics.scala | 80 +++++ .../internal/graph/rendering/TreeView.scala | 80 +++++ .../sbt/plugins/DependencyGraphPlugin.scala | 329 ++++++++++++++++++ sbt-dependency-graph/CHANGELOG.md | 149 -------- sbt-dependency-graph/LICENSE | 201 ----------- sbt-dependency-graph/NOTICE | 26 -- sbt-dependency-graph/PUBLISHING | 12 - sbt-dependency-graph/README.md | 97 ------ sbt-dependency-graph/build.sbt | 30 -- sbt-dependency-graph/project.sbt | 9 - .../project/ScalariformSupport.scala | 20 -- sbt-dependency-graph/project/build.properties | 1 - sbt-dependency-graph/project/pgp.sbt | 1 - sbt-dependency-graph/project/plugins.sbt | 4 - sbt-dependency-graph/publish.sbt | 31 -- .../src/main/resources/graph.html | 115 ------ .../src/main/resources/tree.html | 49 --- .../sbt/graph/ModuleGraphProtocolCompat.scala | 3 - .../sbt/graph/rendering/AsciiGraph.scala | 59 ---- .../DependencyGraphSbtCompat.scala | 15 - .../sbt/graph/ModuleGraphProtocolCompat.scala | 25 -- .../sbt/graph/rendering/AsciiGraph.scala | 22 -- .../DependencyGraphSbtCompat.scala | 6 - .../sbt/graph/DependencyGraphKeys.scala | 113 ------ .../sbt/graph/DependencyGraphPlugin.scala | 28 -- .../sbt/graph/DependencyGraphSettings.scala | 279 --------------- .../sbt/graph/GraphTransformations.scala | 58 --- .../net/virtualvoid/sbt/graph/Main.scala | 35 -- .../sbt/graph/backend/IvyReport.scala | 61 ---- .../sbt/graph/backend/SbtUpdateReport.scala | 56 --- .../net/virtualvoid/sbt/graph/model.scala | 79 ----- .../net/virtualvoid/sbt/graph/package.scala | 22 -- .../sbt/graph/rendering/AsciiTree.scala | 39 --- .../sbt/graph/rendering/DagreHTML.scala | 40 --- .../sbt/graph/rendering/FlatList.scala | 28 -- .../sbt/graph/rendering/GraphML.scala | 48 --- .../sbt/graph/rendering/LicenseInfo.scala | 12 - .../sbt/graph/rendering/Statistics.scala | 71 ---- .../sbt/graph/rendering/TreeView.scala | 42 --- .../sbt/graph/util/AsciiTreeLayout.scala | 62 ---- .../sbt/graph/util/ConsoleUtils.scala | 27 -- .../virtualvoid/sbt/graph/util/IOUtil.scala | 55 --- .../scala/sbt/dependencygraph/SbtAccess.scala | 29 -- .../cachedResolution/project/plugins.sbt | 1 - .../ignoreScalaLibrary/project/plugins.sbt | 1 - .../intervalRangedVersions/build.sbt | 25 -- .../project/plugins.sbt | 1 - .../sbt-test/sbt-dependency-graph/plugins.sbt | 1 - .../showMissingUpdates/project/plugins.sbt | 1 - .../showMissingUpdates/test | 1 - .../testDotFileGeneration/build.sbt | 68 ---- .../testDotFileGeneration/project/plugins.sbt | 1 - .../testDotFileGeneration/test | 2 - .../toFileSubTask/expected/licenses.txt | 9 - .../toFileSubTask/expected/list.txt | 4 - .../toFileSubTask/expected/stats.txt | 12 - .../toFileSubTask/expected/tree.txt | 6 - .../toFileSubTask/project/plugins.sbt | 1 - .../sbt-dependency-graph/toFileSubTask/test | 5 - .../project/plugins.sbt | 1 - .../whatDependsOn/project/plugins.sbt | 1 - .../sbt/graph/util/AsciiTreeLayoutSpecs.scala | 94 ----- .../cachedResolution/build.sbt | 4 +- .../dependency-graph}/cachedResolution/test | 0 .../ignoreScalaLibrary/build.sbt | 4 +- .../dependency-graph}/ignoreScalaLibrary/test | 0 .../showMissingUpdates/build.sbt | 4 +- .../showMissingUpdates/disabled | 0 .../testDotFileGeneration/build.sbt | 53 +++ .../testDotFileGeneration/test | 1 + .../dependency-graph}/toFileSubTask/build.sbt | 15 +- .../toFileSubTask/expected/licenses.txt | 9 + .../toFileSubTask/expected/list.txt | 4 + .../toFileSubTask/expected/stats.txt | 12 + .../toFileSubTask/expected/tree.txt | 5 + .../dependency-graph/toFileSubTask/test | 5 + .../build.sbt | 2 + .../test | 0 .../dependency-graph}/whatDependsOn/build.sbt | 28 +- .../dependency-graph}/whatDependsOn/test | 0 97 files changed, 1235 insertions(+), 2368 deletions(-) create mode 100644 main/src/main/scala/sbt/internal/graph/DependencyGraphKeys.scala create mode 100644 main/src/main/scala/sbt/internal/graph/GraphTransformations.scala create mode 100644 main/src/main/scala/sbt/internal/graph/backend/IvyReport.scala create mode 100644 main/src/main/scala/sbt/internal/graph/backend/SbtUpdateReport.scala create mode 100644 main/src/main/scala/sbt/internal/graph/model.scala create mode 100644 main/src/main/scala/sbt/internal/graph/package.scala create mode 100644 main/src/main/scala/sbt/internal/graph/rendering/AsciiTree.scala rename {sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt => main/src/main/scala/sbt/internal}/graph/rendering/DOT.scala (54%) create mode 100644 main/src/main/scala/sbt/internal/graph/rendering/DagreHTML.scala create mode 100644 main/src/main/scala/sbt/internal/graph/rendering/FlatList.scala create mode 100644 main/src/main/scala/sbt/internal/graph/rendering/GraphML.scala create mode 100644 main/src/main/scala/sbt/internal/graph/rendering/LicenseInfo.scala create mode 100644 main/src/main/scala/sbt/internal/graph/rendering/Statistics.scala create mode 100644 main/src/main/scala/sbt/internal/graph/rendering/TreeView.scala create mode 100644 main/src/main/scala/sbt/plugins/DependencyGraphPlugin.scala delete mode 100644 sbt-dependency-graph/CHANGELOG.md delete mode 100644 sbt-dependency-graph/LICENSE delete mode 100644 sbt-dependency-graph/NOTICE delete mode 100644 sbt-dependency-graph/PUBLISHING delete mode 100644 sbt-dependency-graph/README.md delete mode 100644 sbt-dependency-graph/build.sbt delete mode 100644 sbt-dependency-graph/project.sbt delete mode 100644 sbt-dependency-graph/project/ScalariformSupport.scala delete mode 100644 sbt-dependency-graph/project/build.properties delete mode 100644 sbt-dependency-graph/project/pgp.sbt delete mode 100644 sbt-dependency-graph/project/plugins.sbt delete mode 100644 sbt-dependency-graph/publish.sbt delete mode 100644 sbt-dependency-graph/src/main/resources/graph.html delete mode 100644 sbt-dependency-graph/src/main/resources/tree.html delete mode 100644 sbt-dependency-graph/src/main/scala-sbt-0.13/net/virtualvoid/sbt/graph/ModuleGraphProtocolCompat.scala delete mode 100644 sbt-dependency-graph/src/main/scala-sbt-0.13/net/virtualvoid/sbt/graph/rendering/AsciiGraph.scala delete mode 100644 sbt-dependency-graph/src/main/scala-sbt-0.13/sbt/dependencygraph/DependencyGraphSbtCompat.scala delete mode 100644 sbt-dependency-graph/src/main/scala-sbt-1.0/net/virtualvoid/sbt/graph/ModuleGraphProtocolCompat.scala delete mode 100644 sbt-dependency-graph/src/main/scala-sbt-1.0/net/virtualvoid/sbt/graph/rendering/AsciiGraph.scala delete mode 100644 sbt-dependency-graph/src/main/scala-sbt-1.0/sbt/dependencygraph/DependencyGraphSbtCompat.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala delete mode 100755 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphPlugin.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/GraphTransformations.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/Main.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/backend/IvyReport.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/backend/SbtUpdateReport.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/model.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/package.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/AsciiTree.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/DagreHTML.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/FlatList.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/GraphML.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/LicenseInfo.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/Statistics.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/TreeView.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayout.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/util/ConsoleUtils.scala delete mode 100644 sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/util/IOUtil.scala delete mode 100644 sbt-dependency-graph/src/main/scala/sbt/dependencygraph/SbtAccess.scala delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/cachedResolution/project/plugins.sbt delete mode 120000 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/ignoreScalaLibrary/project/plugins.sbt delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/intervalRangedVersions/build.sbt delete mode 120000 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/intervalRangedVersions/project/plugins.sbt delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/plugins.sbt delete mode 120000 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/showMissingUpdates/project/plugins.sbt delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/showMissingUpdates/test delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/testDotFileGeneration/build.sbt delete mode 120000 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/testDotFileGeneration/project/plugins.sbt delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/testDotFileGeneration/test delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/licenses.txt delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/list.txt delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/stats.txt delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/tree.txt delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/project/plugins.sbt delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/test delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn-without-previous-initialization/project/plugins.sbt delete mode 100644 sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn/project/plugins.sbt delete mode 100644 sbt-dependency-graph/src/test/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayoutSpecs.scala rename {sbt-dependency-graph/src/sbt-test/sbt-dependency-graph => sbt/src/sbt-test/dependency-graph}/cachedResolution/build.sbt (85%) rename {sbt-dependency-graph/src/sbt-test/sbt-dependency-graph => sbt/src/sbt-test/dependency-graph}/cachedResolution/test (100%) rename {sbt-dependency-graph/src/sbt-test/sbt-dependency-graph => sbt/src/sbt-test/dependency-graph}/ignoreScalaLibrary/build.sbt (91%) rename {sbt-dependency-graph/src/sbt-test/sbt-dependency-graph => sbt/src/sbt-test/dependency-graph}/ignoreScalaLibrary/test (100%) rename {sbt-dependency-graph/src/sbt-test/sbt-dependency-graph => sbt/src/sbt-test/dependency-graph}/showMissingUpdates/build.sbt (86%) rename sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/intervalRangedVersions/test => sbt/src/sbt-test/dependency-graph/showMissingUpdates/disabled (100%) create mode 100644 sbt/src/sbt-test/dependency-graph/testDotFileGeneration/build.sbt create mode 100644 sbt/src/sbt-test/dependency-graph/testDotFileGeneration/test rename {sbt-dependency-graph/src/sbt-test/sbt-dependency-graph => sbt/src/sbt-test/dependency-graph}/toFileSubTask/build.sbt (73%) create mode 100644 sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/licenses.txt create mode 100644 sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/list.txt create mode 100644 sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/stats.txt create mode 100644 sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/tree.txt create mode 100644 sbt/src/sbt-test/dependency-graph/toFileSubTask/test rename {sbt-dependency-graph/src/sbt-test/sbt-dependency-graph => sbt/src/sbt-test/dependency-graph}/whatDependsOn-without-previous-initialization/build.sbt (98%) rename {sbt-dependency-graph/src/sbt-test/sbt-dependency-graph => sbt/src/sbt-test/dependency-graph}/whatDependsOn-without-previous-initialization/test (100%) rename {sbt-dependency-graph/src/sbt-test/sbt-dependency-graph => sbt/src/sbt-test/dependency-graph}/whatDependsOn/build.sbt (58%) rename {sbt-dependency-graph/src/sbt-test/sbt-dependency-graph => sbt/src/sbt-test/dependency-graph}/whatDependsOn/test (100%) diff --git a/.travis.yml b/.travis.yml index e17c5bb7f..c0a6784d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ env: matrix: - SBT_CMD="mimaReportBinaryIssues ; javafmtCheck ; Test / javafmtCheck; scalafmtCheckAll ; scalafmtSbtCheck; serverTestProj/scalafmtCheckAll; headerCheck ;test:headerCheck ;whitesourceOnPush ;test:compile; publishLocal; test; serverTestProj/test; doc; $UTIL_TESTS; ++$SCALA_213; $UTIL_TESTS" - SBT_CMD="scripted actions/* apiinfo/* compiler-project/* ivy-deps-management/* reporter/* tests/* watch/* classloader-cache/* package/*" - - SBT_CMD="scripted dependency-management/* plugins/* project-load/* java/* run/* nio/*" + - SBT_CMD="scripted dependency-graph/* dependency-management/* plugins/* project-load/* java/* run/* nio/*" - SBT_CMD="repoOverrideTest:scripted dependency-management/*; scripted source-dependencies/* project/*" matrix: diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala b/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala index 2855423f8..14bff4939 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala @@ -308,6 +308,10 @@ object Terminal { private[this] lazy val isColorEnabledProp: Option[Boolean] = sys.props.get("sbt.color").orElse(sys.props.get("sbt.colour")).flatMap(parseLogOption) + private[sbt] def red(str: String, doRed: Boolean): String = + if (formatEnabledInEnv && doRed) Console.RED + str + Console.RESET + else str + /** * * @param isServer toggles whether or not this is a server of client process diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 64adc35a5..5e1022128 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -880,7 +880,7 @@ object Defaults extends BuildCommon { Seq( initialCommands :== "", cleanupCommands :== "", - asciiGraphWidth :== 40 + asciiGraphWidth :== 80 ) ) diff --git a/main/src/main/scala/sbt/internal/PluginDiscovery.scala b/main/src/main/scala/sbt/internal/PluginDiscovery.scala index 62d481cac..3f6a9f450 100644 --- a/main/src/main/scala/sbt/internal/PluginDiscovery.scala +++ b/main/src/main/scala/sbt/internal/PluginDiscovery.scala @@ -52,6 +52,7 @@ object PluginDiscovery { "sbt.plugins.SemanticdbPlugin" -> sbt.plugins.SemanticdbPlugin, "sbt.plugins.JUnitXmlReportPlugin" -> sbt.plugins.JUnitXmlReportPlugin, "sbt.plugins.Giter8TemplatePlugin" -> sbt.plugins.Giter8TemplatePlugin, + "sbt.plugins.DependencyGraphPlugin" -> sbt.plugins.DependencyGraphPlugin, ) val detectedAutoPlugins = discover[AutoPlugin](AutoPlugins) val allAutoPlugins = (defaultAutoPlugins ++ detectedAutoPlugins.modules) map { diff --git a/main/src/main/scala/sbt/internal/SettingGraph.scala b/main/src/main/scala/sbt/internal/SettingGraph.scala index be9f83f9d..fdf5f30ec 100644 --- a/main/src/main/scala/sbt/internal/SettingGraph.scala +++ b/main/src/main/scala/sbt/internal/SettingGraph.scala @@ -81,8 +81,12 @@ object Graph { // [info] | +-baz // [info] | // [info] +-quux - def toAscii[A](top: A, children: A => Seq[A], display: A => String, defaultWidth: Int): String = { - val maxColumn = math.max(Terminal.get.getWidth, defaultWidth) - 8 + def toAscii[A]( + top: A, + children: A => Seq[A], + display: A => String, + maxColumn: Int + ): String = { val twoSpaces = " " + " " // prevent accidentally being converted into a tab def limitLine(s: String): String = if (s.length > maxColumn) s.slice(0, maxColumn - 2) + ".." @@ -96,21 +100,33 @@ object Graph { }) + s.slice(at + 1, s.length) else s - def toAsciiLines(node: A, level: Int): (String, Vector[String]) = { - val line = limitLine((twoSpaces * level) + (if (level == 0) "" else "+-") + display(node)) - val cs = Vector(children(node): _*) - val childLines = cs map { toAsciiLines(_, level + 1) } - val withBar = childLines.zipWithIndex flatMap { - case ((line, withBar), pos) if pos < (cs.size - 1) => - (line +: withBar) map { insertBar(_, 2 * (level + 1)) } - case ((line, withBar), _) if withBar.lastOption.getOrElse(line).trim != "" => - (line +: withBar) ++ Vector(twoSpaces * (level + 1)) - case ((line, withBar), _) => line +: withBar + def toAsciiLines(node: A, level: Int, parents: Set[A]): Vector[String] = + if (parents contains node) // cycle + Vector(limitLine((twoSpaces * level) + "#-" + display(node) + " (cycle)")) + else { + val line = limitLine((twoSpaces * level) + (if (level == 0) "" else "+-") + display(node)) + val cs = Vector(children(node): _*) + val childLines = cs map { + toAsciiLines(_, level + 1, parents + node) + } + val withBar = childLines.zipWithIndex flatMap { + case (lines, pos) if pos < (cs.size - 1) => + lines map { + insertBar(_, 2 * (level + 1)) + } + case (lines, pos) => + if (lines.last.trim != "") lines ++ Vector(twoSpaces * (level + 1)) + else lines + } + line +: withBar } - (line, withBar) - } - val (line, withBar) = toAsciiLines(top, 0) - (line +: withBar).mkString("\n") + toAsciiLines(top, 0, Set.empty).mkString("\n") + } + + def defaultColumnSize: Int = { + val termWidth = Terminal.console.getWidth + if (termWidth > 20) termWidth - 8 + else 80 // ignore termWidth } } diff --git a/main/src/main/scala/sbt/internal/graph/DependencyGraphKeys.scala b/main/src/main/scala/sbt/internal/graph/DependencyGraphKeys.scala new file mode 100644 index 000000000..a02ae6a87 --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/DependencyGraphKeys.scala @@ -0,0 +1,95 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package graph + +import java.io.File +import java.net.URI +import sbt.BuildSyntax._ +import sbt.librarymanagement.{ ModuleID, UpdateReport } + +trait DependencyGraphKeys { + 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") + + val dependencyTreeIncludeScalaLibrary = settingKey[Boolean]( + "Specifies if scala dependency should be included in dependencyTree output" + ) + + 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 dependencyDotNodeLabel = settingKey[(String, String, String) => String]( + "Returns a formated string of a dependency. Takes organization, name and version as parameters" + ) + 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" + ) + val moduleGraph = taskKey[ModuleGraph]("The dependency graph for a project") + val moduleGraphIvyReport = taskKey[ModuleGraph]( + "The dependency graph for a project as generated from an Ivy Report XML" + ) + val moduleGraphSbt = taskKey[ModuleGraph]( + "The dependency graph for a project as generated from SBT data structures." + ) + val dependencyGraph = inputKey[Unit]("Prints the ascii graph to the console") + val dependencyTree = taskKey[Unit]("Prints an ascii tree of all the dependencies to the console") + 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 ivyReportFunction = taskKey[String => File]( + "A function which returns the file containing the ivy report from the ivy cache for a given configuration" + ) + val ivyReport = taskKey[File]( + "A task which returns the location of the ivy report file for a given configuration (default `compile`)." + ) + val dependencyLicenseInfo = taskKey[Unit]( + "Aggregates and shows information about the licenses of dependencies" + ) + + // internal + private[sbt] val ignoreMissingUpdate = + TaskKey[UpdateReport]("dependencyUpdate", "sbt-dependency-graph version of update") + private[sbt] val moduleGraphStore = + TaskKey[ModuleGraph]("module-graph-store", "The stored module-graph from the last run") + val whatDependsOn = + InputKey[String]("what-depends-on", "Shows information about what depends on the given module") + private[sbt] val crossProjectId = SettingKey[ModuleID]("dependency-graph-cross-project-id") +} + +object DependencyGraphKeys extends DependencyGraphKeys diff --git a/main/src/main/scala/sbt/internal/graph/GraphTransformations.scala b/main/src/main/scala/sbt/internal/graph/GraphTransformations.scala new file mode 100644 index 000000000..c7385383d --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/GraphTransformations.scala @@ -0,0 +1,58 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package graph + +object GraphTransformations { + def reverseGraphStartingAt(graph: ModuleGraph, root: GraphModuleId): ModuleGraph = { + val deps = graph.reverseDependencyMap + + def visit( + module: GraphModuleId, + visited: Set[GraphModuleId] + ): Seq[(GraphModuleId, GraphModuleId)] = + if (visited(module)) + Nil + else + deps.get(module) match { + case Some(deps) => + deps.flatMap { to => + (module, to.id) +: visit(to.id, visited + module) + } + case None => Nil + } + + val edges = visit(root, Set.empty) + val nodes = + edges + .foldLeft(Set.empty[GraphModuleId])((set, edge) => set + edge._1 + edge._2) + .map(graph.module) + ModuleGraph(nodes.toSeq, edges) + } + + def ignoreScalaLibrary(scalaVersion: String, graph: ModuleGraph): ModuleGraph = { + def isScalaLibrary(m: Module) = isScalaLibraryId(m.id) + def isScalaLibraryId(id: GraphModuleId) = + id.organization == "org.scala-lang" && id.name == "scala-library" + + def dependsOnScalaLibrary(m: Module): Boolean = + graph.dependencyMap(m.id).exists(isScalaLibrary) + + def addScalaLibraryAnnotation(m: Module): Module = { + if (dependsOnScalaLibrary(m)) + m.copy(extraInfo = m.extraInfo + " [S]") + else + m + } + + val newNodes = graph.nodes.map(addScalaLibraryAnnotation).filterNot(isScalaLibrary) + val newEdges = graph.edges.filterNot(e => isScalaLibraryId(e._2)) + ModuleGraph(newNodes, newEdges) + } +} diff --git a/main/src/main/scala/sbt/internal/graph/backend/IvyReport.scala b/main/src/main/scala/sbt/internal/graph/backend/IvyReport.scala new file mode 100644 index 000000000..99270b939 --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/backend/IvyReport.scala @@ -0,0 +1,67 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package graph +package backend + +import scala.xml.{ NodeSeq, Document, Node } +import scala.xml.parsing.ConstructingParser + +object IvyReport { + def fromReportFile(ivyReportFile: String): ModuleGraph = + fromReportXML(loadXML(ivyReportFile)) + + def fromReportXML(doc: Document): ModuleGraph = { + def edgesForModule(id: GraphModuleId, revision: NodeSeq): Seq[Edge] = + for { + caller ← revision \ "caller" + callerModule = moduleIdFromElement(caller, caller.attribute("callerrev").get.text) + } yield (moduleIdFromElement(caller, caller.attribute("callerrev").get.text), id) + + val moduleEdges: Seq[(Module, Seq[Edge])] = for { + mod ← doc \ "dependencies" \ "module" + revision ← mod \ "revision" + rev = revision.attribute("name").get.text + moduleId = moduleIdFromElement(mod, rev) + module = Module( + moduleId, + (revision \ "license").headOption.flatMap(_.attribute("name")).map(_.text), + evictedByVersion = + (revision \ "evicted-by").headOption.flatMap(_.attribute("rev").map(_.text)), + error = revision.attribute("error").map(_.text) + ) + } yield (module, edgesForModule(moduleId, revision)) + + val (nodes, edges) = moduleEdges.unzip + + val info = (doc \ "info").head + def infoAttr(name: String): String = + info + .attribute(name) + .getOrElse(throw new IllegalArgumentException("Missing attribute " + name)) + .text + val rootModule = Module( + GraphModuleId(infoAttr("organization"), infoAttr("module"), infoAttr("revision")) + ) + + ModuleGraph(rootModule +: nodes, edges.flatten) + } + + private def moduleIdFromElement(element: Node, version: String): GraphModuleId = + GraphModuleId( + element.attribute("organization").get.text, + element.attribute("name").get.text, + version + ) + + private def loadXML(ivyReportFile: String) = + ConstructingParser + .fromSource(scala.io.Source.fromFile(ivyReportFile), preserveWS = false) + .document() +} diff --git a/main/src/main/scala/sbt/internal/graph/backend/SbtUpdateReport.scala b/main/src/main/scala/sbt/internal/graph/backend/SbtUpdateReport.scala new file mode 100644 index 000000000..5db194c8e --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/backend/SbtUpdateReport.scala @@ -0,0 +1,54 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package graph +package backend + +import scala.language.implicitConversions +import scala.language.reflectiveCalls +import sbt.librarymanagement.{ ModuleID, ModuleReport, ConfigurationReport } + +object SbtUpdateReport { + type OrganizationArtifactReport = { + def modules: Seq[ModuleReport] + } + + def fromConfigurationReport(report: ConfigurationReport, rootInfo: ModuleID): ModuleGraph = { + implicit def id(sbtId: ModuleID): GraphModuleId = + GraphModuleId(sbtId.organization, sbtId.name, sbtId.revision) + + def moduleEdges(orgArt: OrganizationArtifactReport): Seq[(Module, Seq[Edge])] = { + val chosenVersion = orgArt.modules.find(!_.evicted).map(_.module.revision) + orgArt.modules.map(moduleEdge(chosenVersion)) + } + + def moduleEdge(chosenVersion: Option[String])(report: ModuleReport): (Module, Seq[Edge]) = { + val evictedByVersion = if (report.evicted) chosenVersion else None + val jarFile = report.artifacts + .find(_._1.`type` == "jar") + .orElse(report.artifacts.find(_._1.extension == "jar")) + .map(_._2) + ( + Module( + id = report.module, + license = report.licenses.headOption.map(_._1), + evictedByVersion = evictedByVersion, + jarFile = jarFile, + error = report.problem + ), + report.callers.map(caller => Edge(caller.caller, report.module)) + ) + } + + val (nodes, edges) = report.details.flatMap(moduleEdges).unzip + val root = Module(rootInfo) + + ModuleGraph(root +: nodes, edges.flatten) + } +} diff --git a/main/src/main/scala/sbt/internal/graph/model.scala b/main/src/main/scala/sbt/internal/graph/model.scala new file mode 100644 index 000000000..f4d4676a1 --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/model.scala @@ -0,0 +1,105 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package graph + +import java.io.File +import sjsonnew._ +import scala.collection.mutable.{ HashMap, MultiMap, Set } + +private[sbt] case class GraphModuleId(organization: String, name: String, version: String) { + def idString: String = organization + ":" + name + ":" + version +} + +private[sbt] object GraphModuleId { + import sjsonnew.BasicJsonProtocol.StringJsonFormat + implicit val graphModuleIdIso = LList.iso[GraphModuleId, String :*: String :*: String :*: LNil]( + { m: GraphModuleId => + ("organization", m.organization) :*: ("name", m.name) :*: ("version", m.version) :*: LNil + }, { + case (_, organization) :*: (_, name) :*: (_, version) :*: LNil => + GraphModuleId(organization, name, version) + } + ) +} + +private[sbt] case class Module( + id: GraphModuleId, + license: Option[String] = None, + extraInfo: String = "", + evictedByVersion: Option[String] = None, + jarFile: Option[File] = None, + error: Option[String] = None +) { + def hadError: Boolean = error.isDefined + def isUsed: Boolean = !isEvicted + def isEvicted: Boolean = evictedByVersion.isDefined +} + +private[sbt] object Module { + import sjsonnew.BasicJsonProtocol._ + implicit val moduleIso = LList.iso[Module, GraphModuleId :*: Option[String] :*: String :*: Option[ + String + ] :*: Option[File] :*: Option[String] :*: LNil]( + { m: Module => + ("id", m.id) :*: ("license", m.license) :*: ("extraInfo", m.extraInfo) :*: + ("evictedByVersion", m.evictedByVersion) :*: ( + "jarFile", + m.jarFile + ) :*: ("error", m.error) :*: LNil + }, { + case (_, id) :*: (_, license) :*: (_, extraInfo) :*: (_, evictedByVersion) :*: (_, jarFile) :*: ( + _, + error + ) :*: LNil => + Module(id, license, extraInfo, evictedByVersion, jarFile, error) + } + ) +} + +private[sbt] case class ModuleGraph(nodes: Seq[Module], edges: Seq[Edge]) { + lazy val modules: Map[GraphModuleId, Module] = + nodes.map(n => (n.id, n)).toMap + + def module(id: GraphModuleId): Module = modules(id) + + lazy val dependencyMap: Map[GraphModuleId, Seq[Module]] = + createMap(identity) + + lazy val reverseDependencyMap: Map[GraphModuleId, Seq[Module]] = + createMap { case (a, b) => (b, a) } + + def createMap( + bindingFor: ((GraphModuleId, GraphModuleId)) => (GraphModuleId, GraphModuleId) + ): Map[GraphModuleId, Seq[Module]] = { + val m = new HashMap[GraphModuleId, Set[Module]] with MultiMap[GraphModuleId, Module] + edges.foreach { entry => + val (f, t) = bindingFor(entry) + m.addBinding(f, module(t)) + } + m.toMap.mapValues(_.toSeq.sortBy(_.id.idString)).withDefaultValue(Nil) + } + + def roots: Seq[Module] = + nodes.filter(n => !edges.exists(_._2 == n.id)).sortBy(_.id.idString) +} + +private[sbt] object ModuleGraph { + val empty = ModuleGraph(Seq.empty, Seq.empty) + + import BasicJsonProtocol._ + implicit val moduleGraphIso = LList.iso[ModuleGraph, Vector[Module] :*: Vector[Edge] :*: LNil]( + { g: ModuleGraph => + ("nodes", g.nodes.toVector) :*: ("edges", g.edges.toVector) :*: LNil + }, { + case (_, nodes: Vector[Module]) :*: (_, edges: Vector[Edge]) :*: LNil => + ModuleGraph(nodes, edges) + } + ) +} diff --git a/main/src/main/scala/sbt/internal/graph/package.scala b/main/src/main/scala/sbt/internal/graph/package.scala new file mode 100644 index 000000000..f1fac27a6 --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/package.scala @@ -0,0 +1,14 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal + +package object graph { + type Edge = (GraphModuleId, GraphModuleId) + def Edge(from: GraphModuleId, to: GraphModuleId): Edge = from -> to +} diff --git a/main/src/main/scala/sbt/internal/graph/rendering/AsciiTree.scala b/main/src/main/scala/sbt/internal/graph/rendering/AsciiTree.scala new file mode 100644 index 000000000..33f37513a --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/rendering/AsciiTree.scala @@ -0,0 +1,42 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package graph +package rendering + +import sbt.internal.util.Terminal.red + +object AsciiTree { + def asciiTree(graph: ModuleGraph): String = { + val deps = graph.dependencyMap + + // there should only be one root node (the project itself) + val roots = graph.roots + roots + .map { root => + Graph + .toAscii[Module]( + root, + node => deps.getOrElse(node.id, Seq.empty[Module]), + displayModule, + Graph.defaultColumnSize + ) + } + .mkString("\n") + } + + def displayModule(module: Module): String = + red( + module.id.idString + + module.extraInfo + + module.error.map(" (error: " + _ + ")").getOrElse("") + + module.evictedByVersion.map(_ formatted " (evicted by: %s)").getOrElse(""), + module.hadError + ) +} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/DOT.scala b/main/src/main/scala/sbt/internal/graph/rendering/DOT.scala similarity index 54% rename from sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/DOT.scala rename to main/src/main/scala/sbt/internal/graph/rendering/DOT.scala index dd63bacb3..6c984f1ca 100644 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/DOT.scala +++ b/main/src/main/scala/sbt/internal/graph/rendering/DOT.scala @@ -1,38 +1,33 @@ /* - * 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. + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) */ -package net.virtualvoid.sbt.graph +package sbt +package internal +package graph package rendering object DOT { val EvictedStyle = "stroke-dasharray: 5,5" def dotGraph( - graph: ModuleGraph, - dotHead: String, - nodeFormation: (String, String, String) ⇒ String, - labelRendering: HTMLLabelRendering): String = { + graph: ModuleGraph, + dotHead: String, + nodeFormation: (String, String, String) => String, + labelRendering: HTMLLabelRendering + ): String = { val nodes = { for (n ← graph.nodes) yield { val style = if (n.isEvicted) EvictedStyle else "" - val label = nodeFormation(n.id.organisation, n.id.name, n.id.version) + val label = nodeFormation(n.id.organization, n.id.name, n.id.version) """ "%s"[%s style="%s"]""".format( n.id.idString, labelRendering.renderLabel(label), - style) + style + ) } }.mkString("\n") @@ -41,23 +36,31 @@ object DOT { // add extra edges from evicted to evicted-by module val evictedByEdges: Seq[Edge] = - graph.nodes.filter(_.isEvicted).map(m ⇒ Edge(m.id, m.id.copy(version = m.evictedByVersion.get))) + graph.nodes + .filter(_.isEvicted) + .map(m => Edge(m.id, m.id.copy(version = m.evictedByVersion.get))) // remove edges to new evicted-by module which is now replaced by a chain // dependend -> [evicted] -> dependee val evictionTargetEdges = - graph.edges.filter(targetWasEvicted).map { - case (from, evicted) ⇒ (from, evicted.copy(version = graph.module(evicted).evictedByVersion.get)) - }.toSet + graph.edges + .filter(targetWasEvicted) + .map { + case (from, evicted) => + (from, evicted.copy(version = graph.module(evicted).evictedByVersion.get)) + } + .toSet val filteredEdges = graph.edges - .filterNot(e ⇒ originWasEvicted(e) || evictionTargetEdges(e)) ++ evictedByEdges + .filterNot(e => originWasEvicted(e) || evictionTargetEdges(e)) ++ evictedByEdges val edges = { for (e ← filteredEdges) yield { - val extra = if (graph.module(e._1).isEvicted) - s""" [label="Evicted By" style="$EvictedStyle"]""" else "" + val extra = + if (graph.module(e._1).isEvicted) + s""" [label="Evicted By" style="$EvictedStyle"]""" + else "" """ "%s" -> "%s"%s""".format(e._1.idString, e._2.idString, extra) } }.mkString("\n") @@ -68,6 +71,7 @@ object DOT { sealed trait HTMLLabelRendering { def renderLabel(labelText: String): String } + /** * Render HTML labels in Angle brackets as defined at http://graphviz.org/content/node-shapes#html */ diff --git a/main/src/main/scala/sbt/internal/graph/rendering/DagreHTML.scala b/main/src/main/scala/sbt/internal/graph/rendering/DagreHTML.scala new file mode 100644 index 000000000..f00a197d2 --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/rendering/DagreHTML.scala @@ -0,0 +1,38 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package graph +package rendering + +import java.io.File +import java.net.{ URLEncoder, URI } + +import sbt.io.IO + +object DagreHTML { + def createLink(dotGraph: String, targetDirectory: File): URI = { + targetDirectory.mkdirs() + val graphHTML = new File(targetDirectory, "graph.html") + TreeView.saveResource("graph.html", graphHTML) + IO.write(new File(targetDirectory, "dependencies.dot"), dotGraph, IO.utf8) + + val graphString = + URLEncoder + .encode(dotGraph, "utf8") + .replaceAllLiterally("+", "%20") + + IO.write( + new File(targetDirectory, "dependencies.dot.js"), + s"""data = "$graphString";""", + IO.utf8 + ) + + new URI(graphHTML.toURI.toString) + } +} diff --git a/main/src/main/scala/sbt/internal/graph/rendering/FlatList.scala b/main/src/main/scala/sbt/internal/graph/rendering/FlatList.scala new file mode 100644 index 000000000..a0a842408 --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/rendering/FlatList.scala @@ -0,0 +1,20 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package graph +package rendering + +object FlatList { + def render(display: Module => String)(graph: ModuleGraph): String = + graph.modules.values.toSeq.distinct + .filterNot(_.isEvicted) + .sortBy(m => (m.id.organization, m.id.name)) + .map(display) + .mkString("\n") +} diff --git a/main/src/main/scala/sbt/internal/graph/rendering/GraphML.scala b/main/src/main/scala/sbt/internal/graph/rendering/GraphML.scala new file mode 100644 index 000000000..024d3c6bd --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/rendering/GraphML.scala @@ -0,0 +1,40 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package graph +package rendering + +import scala.xml.XML + +object GraphML { + def saveAsGraphML(graph: ModuleGraph, outputFile: String): Unit = { + val nodesXml = + for (n ← graph.nodes) + yield + + {n.id.idString} + + + + val edgesXml = + for (e ← graph.edges) + yield + + val xml = + + + + {nodesXml} + {edgesXml} + + + + XML.save(outputFile, xml) + } +} diff --git a/main/src/main/scala/sbt/internal/graph/rendering/LicenseInfo.scala b/main/src/main/scala/sbt/internal/graph/rendering/LicenseInfo.scala new file mode 100644 index 000000000..27aa44708 --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/rendering/LicenseInfo.scala @@ -0,0 +1,26 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package graph +package rendering + +object LicenseInfo { + def render(graph: ModuleGraph): String = + graph.nodes + .filter(_.isUsed) + .groupBy(_.license) + .toSeq + .sortBy(_._1) + .map { + case (license, modules) => + license.getOrElse("No license specified") + "\n" + + modules.map(_.id.idString formatted "\t %s").mkString("\n") + } + .mkString("\n\n") +} diff --git a/main/src/main/scala/sbt/internal/graph/rendering/Statistics.scala b/main/src/main/scala/sbt/internal/graph/rendering/Statistics.scala new file mode 100644 index 000000000..a52d4d387 --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/rendering/Statistics.scala @@ -0,0 +1,80 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package graph +package rendering + +object Statistics { + def renderModuleStatsList(graph: ModuleGraph): String = { + case class ModuleStats( + id: GraphModuleId, + numDirectDependencies: Int, + numTransitiveDependencies: Int, + selfSize: Option[Long], + transitiveSize: Long, + transitiveDependencyStats: Map[GraphModuleId, ModuleStats] + ) { + def transitiveStatsWithSelf: Map[GraphModuleId, ModuleStats] = + transitiveDependencyStats + (id -> this) + } + + def statsFor(moduleId: GraphModuleId): ModuleStats = { + val directDependencies = graph.dependencyMap(moduleId).filterNot(_.isEvicted).map(_.id) + val dependencyStats = + directDependencies.map(statsFor).flatMap(_.transitiveStatsWithSelf).toMap + val selfSize = graph.module(moduleId).jarFile.filter(_.exists).map(_.length) + val numDirectDependencies = directDependencies.size + val numTransitiveDependencies = dependencyStats.size + val transitiveSize = selfSize.getOrElse(0L) + dependencyStats + .map(_._2.selfSize.getOrElse(0L)) + .sum + + ModuleStats( + moduleId, + numDirectDependencies, + numTransitiveDependencies, + selfSize, + transitiveSize, + dependencyStats + ) + } + + def format(stats: ModuleStats): String = { + import stats._ + def mb(bytes: Long): Double = bytes.toDouble / 1000000 + val selfSize = + stats.selfSize match { + case Some(size) => f"${mb(size)}%7.3f" + case None => "-------" + } + f"${mb(transitiveSize)}%7.3f MB $selfSize MB $numTransitiveDependencies%4d $numDirectDependencies%4d ${id.idString}%s" + } + + val allStats = + graph.roots + .flatMap(r => statsFor(r.id).transitiveStatsWithSelf) + .toMap + .values + .toSeq + .sortBy(s => (-s.transitiveSize, -s.numTransitiveDependencies)) + + val header = " TotSize JarSize #TDe #Dep Module\n" + + header + + allStats.map(format).mkString("\n") + + """ + | + |Columns are + | - Jar-Size including dependencies + | - Jar-Size + | - Number of transitive dependencies + | - Number of direct dependencies + | - ModuleID""".stripMargin + } +} diff --git a/main/src/main/scala/sbt/internal/graph/rendering/TreeView.scala b/main/src/main/scala/sbt/internal/graph/rendering/TreeView.scala new file mode 100644 index 000000000..2bba9f20f --- /dev/null +++ b/main/src/main/scala/sbt/internal/graph/rendering/TreeView.scala @@ -0,0 +1,80 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package graph +package rendering + +import java.io.{ OutputStream, InputStream, FileOutputStream, File } +import java.net.URI + +import graph.{ Module, ModuleGraph } +import sbt.io.IO + +import scala.annotation.tailrec +import scala.util.parsing.json.{ JSONArray, JSONObject } +import com.github.ghik.silencer.silent + +@silent 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") + 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) + } + + 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))) + } + + def saveResource(resourcePath: String, to: File): Unit = { + val is = getClass.getClassLoader.getResourceAsStream(resourcePath) + require(is ne null, s"Couldn't load '$resourcePath' from classpath.") + + val fos = new FileOutputStream(to) + try copy(is, fos) + finally { + is.close() + fos.close() + } + } + + def copy(from: InputStream, to: OutputStream): Unit = { + val buffer = new Array[Byte](65536) + + @tailrec def rec(): Unit = { + val read = from.read(buffer) + if (read > 0) { + to.write(buffer, 0, read) + rec() + } else if (read == 0) + throw new IllegalStateException("InputStream.read returned 0") + } + rec() + } +} diff --git a/main/src/main/scala/sbt/plugins/DependencyGraphPlugin.scala b/main/src/main/scala/sbt/plugins/DependencyGraphPlugin.scala new file mode 100644 index 000000000..dd546e5ab --- /dev/null +++ b/main/src/main/scala/sbt/plugins/DependencyGraphPlugin.scala @@ -0,0 +1,329 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package plugins + +import java.io.File + +import sbt.Def._ +import sbt.Keys._ +import sbt.SlashSyntax0._ +import sbt.PluginTrigger.AllRequirements +import sbt.Project._ +import sbt.internal.graph._ +import sbt.internal.graph.backend.{ IvyReport, SbtUpdateReport } +import sbt.internal.graph.rendering.{ DagreHTML, TreeView } +import sbt.internal.librarymanagement._ +import sbt.internal.util.complete.{ Parser, Parsers } +import sbt.io.IO +import sbt.io.syntax._ +import sbt.librarymanagement._ +import sbt.librarymanagement.ivy.InlineIvyConfiguration +import sbt.librarymanagement.Configurations.{ + Compile, + IntegrationTest, + Optional, + Provided, + Runtime, + Test +} +// import Keys._ + +object DependencyGraphPlugin extends AutoPlugin { + import sjsonnew.BasicJsonProtocol._ + + object autoImport extends DependencyGraphKeys + + import autoImport._ + override def trigger: PluginTrigger = AllRequirements + override def globalSettings: Seq[Def.Setting[_]] = Seq( + dependencyTreeIncludeScalaLibrary := false + ) + override def projectSettings: Seq[Def.Setting[_]] = graphSettings + def graphSettings = baseSettings ++ reportSettings + + def baseSettings = + Seq( + ivyReportFunction := ivyReportFunctionTask.value, + // disable the cached resolution engine (exposing a scoped `ivyModule` used directly by `updateTask`), as it + // generates artificial module descriptors which are internal to sbt, making it hard to reconstruct the + // dependency tree + ignoreMissingUpdate / updateOptions := updateOptions.value.withCachedResolution(false), + ignoreMissingUpdate / ivyConfiguration := { + // inTask will make sure the new definition will pick up `updateOptions in ignoreMissingUpdate` + inTask(ignoreMissingUpdate, Classpaths.mkIvyConfiguration).value + }, + ignoreMissingUpdate / ivyModule := { + // concatenating & inlining ivySbt & ivyModule default task implementations, as `SbtAccess.inTask` does + // NOT correctly force the scope when applied to `TaskKey.toTask` instances (as opposed to raw + // implementations like `Classpaths.mkIvyConfiguration` or `Classpaths.updateTask`) + val is = new IvySbt((ivyConfiguration in ignoreMissingUpdate).value) + new is.Module(moduleSettings.value) + }, + // don't fail on missing dependencies + ignoreMissingUpdate / updateConfiguration := updateConfiguration.value.withMissingOk(true), + ignoreMissingUpdate := { + // inTask will make sure the new definition will pick up `ivyModule/updateConfiguration in ignoreMissingUpdate` + inTask(ignoreMissingUpdate, Classpaths.updateTask).value + }, + ) + + def reportSettings = + Seq(Compile, Test, IntegrationTest, Runtime, Provided, Optional).flatMap(ivyReportForConfig) + + val renderingAlternatives: Seq[(TaskKey[Unit], ModuleGraph => String)] = + Seq( + dependencyTree -> rendering.AsciiTree.asciiTree _, + dependencyList -> rendering.FlatList.render(_.id.idString), + dependencyStats -> rendering.Statistics.renderModuleStatsList _, + dependencyLicenseInfo -> rendering.LicenseInfo.render _ + ) + + def ivyReportForConfig(config: Configuration) = + inConfig(config)( + Seq( + ivyReport := { + Def + .task { + ivyReportFunction.value.apply(config.toString) + } + .dependsOn(ignoreMissingUpdate) + }.value, + crossProjectId := CrossVersion(scalaVersion.value, scalaBinaryVersion.value)( + projectID.value + ), + moduleGraphSbt := + ignoreMissingUpdate.value + .configuration(configuration.value) + .map(report => SbtUpdateReport.fromConfigurationReport(report, crossProjectId.value)) + .getOrElse(ModuleGraph.empty), + moduleGraphIvyReport := IvyReport.fromReportFile(absoluteReportPath(ivyReport.value)), + moduleGraph := { + sbtVersion.value match { + case Version(0, 13, x, _) if x >= 6 => moduleGraphSbt.value + case Version(1, _, _, _) => moduleGraphSbt.value + } + }, + moduleGraph := { + // FIXME: remove busywork + val sv = scalaVersion.value + val moduleGraph = DependencyGraphKeys.moduleGraph.value + if (dependencyTreeIncludeScalaLibrary.value) moduleGraph + else GraphTransformations.ignoreScalaLibrary(sv, moduleGraph) + }, + moduleGraphStore := (moduleGraph storeAs moduleGraphStore triggeredBy moduleGraph).value, + // 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 := { target.value / "dependencies-%s.dot".format(config.toString) }, + dependencyDot / asString := rendering.DOT.dotGraph( + moduleGraph.value, + dependencyDotHeader.value, + dependencyDotNodeLabel.value, + rendering.DOT.AngleBrackets + ), + dependencyDot := writeToFile(dependencyDot / asString, dependencyDotFile).value, + dependencyDotHeader := + """|digraph "dependency-graph" { + | graph[rankdir="LR"] + | edge [ + | arrowtail="none" + | ]""".stripMargin, + dependencyDotNodeLabel := { (organization: String, name: String, version: String) => + """%s
%s
%s""".format(organization, name, version) + }, + // GraphML support + dependencyGraphMLFile := { + target.value / "dependencies-%s.graphml".format(config.toString) + }, + dependencyGraphML := dependencyGraphMLTask.value, + whatDependsOn := { + val ArtifactPattern(org, name, versionFilter) = artifactPatternParser.parsed + val graph = moduleGraph.value + val modules = + versionFilter match { + case Some(version) => GraphModuleId(org, name, version) :: Nil + case None => + graph.nodes.filter(m => m.id.organization == org && m.id.name == name).map(_.id) + } + val output = + modules + .map { module => + rendering.AsciiTree + .asciiTree(GraphTransformations.reverseGraphStartingAt(graph, module)) + } + .mkString("\n") + + streams.value.log.info(output) + output + }, + ) ++ + renderingAlternatives.flatMap((renderingTaskSettings _).tupled) + ) + + def renderingTaskSettings(key: TaskKey[Unit], renderer: ModuleGraph => String): Seq[Setting[_]] = + Seq( + key := { + val s = streams.value + val str = (key / asString).value + s.log.info(str) + }, + key / asString := renderer(moduleGraph.value), + key / toFile := { + val (targetFile, force) = targetFileAndForceParser.parsed + writeToFile(key.key.label, (asString in key).value, targetFile, force, streams.value) + }, + ) + + def ivyReportFunctionTask = Def.task { + val ivyConfig = Keys.ivyConfiguration.value.asInstanceOf[InlineIvyConfiguration] + val projectID = Keys.projectID.value + val ivyModule = Keys.ivyModule.value + + (config: String) => { + val org = projectID.organization + val name = crossName(ivyModule) + new File(ivyConfig.resolutionCacheDir.get, s"reports/$org-$name-$config.xml") + } + } + + def dependencyGraphMLTask = + Def.task { + val resultFile = dependencyGraphMLFile.value + rendering.GraphML.saveAsGraphML(moduleGraph.value, resultFile.getAbsolutePath) + streams.value.log.info("Wrote dependency graph to '%s'" format resultFile) + resultFile + } + + def browseGraphHTMLTask = + Def.task { + val dotGraph = rendering.DOT.dotGraph( + moduleGraph.value, + dependencyDotHeader.value, + dependencyDotNodeLabel.value, + rendering.DOT.LabelTypeHtml + ) + val link = DagreHTML.createLink(dotGraph, target.value) + streams.value.log.info(s"HTML graph written to $link") + 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 + IO.write(outFile, dataTask.value, IO.utf8) + + streams.value.log.info("Wrote dependency graph to '%s'" format 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("Opening in browser...") + java.awt.Desktop.getDesktop.browse(uri) + 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 = Defaults.loadFromContext(moduleGraphStore, ctx, state) getOrElse ModuleGraph( + Nil, + Nil + ) + + graph.nodes + .map(_.id) + .groupBy(m => (m.organization, m.name)) + .map { + case ((org, name), modules) => + val versionParsers: Seq[Parser[Option[String]]] = + modules.map { id => + token(Space ~> id.version).? + } + + (Space ~> token(org) ~ token(Space ~> name) ~ oneOf(versionParsers)).map { + case ((org, name), version) => ArtifactPattern(org, name, version) + } + } + .reduceOption(_ | _) + .getOrElse { + // If the moduleGraphStore couldn't be loaded because no dependency tree command was run before, we should still provide a parser for the command. + ((Space ~> token(StringBasic, "")) ~ (Space ~> token( + StringBasic, + "" + )) ~ (Space ~> token(StringBasic, "")).?).map { + case ((org, mod), version) => + ArtifactPattern(org, mod, version) + } + } + } + val shouldForceParser: Parser[Boolean] = + (Space ~> (Parser.literal("-f") | "--force")).?.map(_.isDefined) + + val targetFileAndForceParser: Parser[(File, Boolean)] = + Parsers.fileParser(new File(".")) ~ shouldForceParser + + // This is to support 0.13.8's InlineConfigurationWithExcludes while not forcing 0.13.8 + type HasModule = { + val module: ModuleID + } + def crossName(ivyModule: IvySbt#Module) = + ivyModule.moduleSettings match { + case ic: ModuleDescriptorConfiguration => ic.module.name + case _ => + throw new IllegalStateException( + "sbt-dependency-graph plugin currently only supports ModuleDescriptorConfiguration of ivy settings (the default in sbt)" + ) + } + + val VersionPattern = """(\d+)\.(\d+)\.(\d+)(?:-(.*))?""".r + object Version { + def unapply(str: String): Option[(Int, Int, Int, Option[String])] = str match { + case VersionPattern(major, minor, fix, appendix) => + Some((major.toInt, minor.toInt, fix.toInt, Option(appendix))) + case _ => None + } + } +} diff --git a/sbt-dependency-graph/CHANGELOG.md b/sbt-dependency-graph/CHANGELOG.md deleted file mode 100644 index 02eb5e41b..000000000 --- a/sbt-dependency-graph/CHANGELOG.md +++ /dev/null @@ -1,149 +0,0 @@ -# Changelog - -## Unreleased - * [#184](https://github.com/jrudolph/sbt-dependency-graph/pull/184): Fix regression in 0.10.0-RC1 for recent sbt versions when - `cachedResolution` (with coursier turned off). Thanks [@bjaglin](https://github.com/bjaglin) for the report and the fix. - -## Version 0.10.0-RC1 (2019-07-24) - * [#136](https://github.com/jrudolph/sbt-dependency-graph/pull/136): Added `dependencyBrowseTree` to open a searchable dependency tree in the browser. - Thanks, [@pcejrowski](https://github.com/pcejrowski) for contributing this feature. - * [#163](https://github.com/jrudolph/sbt-dependency-graph/pull/163): Remove some usage of internal sbt APIs, this allows to run sbt-dependency-graph with sbt 1.3.0 - but results are not entirely correct. - * [#165](https://github.com/jrudolph/sbt-dependency-graph/pull/165): For common operations introduce `asString`, `printToConsole`, and `toFile` subtasks - -## Version 0.9.2 (2018-08-26) - * [#159](https://github.com/jrudolph/sbt-dependency-graph/pull/159): Fixed regression in `whatDependsOn` where task parser failed when no other sbt-dependency-graph task was called before - -## Version 0.9.1 (2018-07-17) - - * [#110](https://github.com/jrudolph/sbt-dependency-graph/issues/110): `whatDependsOn` can now be called without specifying a version. Thanks, @chikei for the initial implementation. - * [#150](https://github.com/jrudolph/sbt-dependency-graph/issues/150): `ivyReport` now reports correct path again even for older sbt versions (< 0.13.16) - -## Version 0.9.0 (2017-10-25) - -This version (finally!) adds support for sbt 1.0. *sbt-dependency-graph* depends on a lot of internals from sbt to do its -work which is why it was quite an effort to do the migration. Thanks [@MasseGuillaume](https://github.com/MasseGuillaume) from Scala Center, -[@2m](https://github.com/2m), and [@xuwei-k](https://github.com/xuwei-k) for helping out with the effort. - -The plugin is cross-built for sbt 0.13 (and will continued to be for while). The `dependencyGraph` task is currently not -supported on sbt 1.0. Use `dependencyBrowseGraph`, instead. - -## Version 0.8.2 (2016-02-01) - -This is a maintenance release [fixing](https://github.com/jrudolph/sbt-dependency-graph/issues/89) `dependencyBrowseGraph` -in the latest Chrome versions. Thanks [@chtefi](https://github.com/chtefi)! - -## Version 0.8.1 (2016-01-08) - -This is a maintenance release fixing a regression in 0.8.0 and adding two small features. - -All changes: - - * [#84](https://github.com/jrudolph/sbt-dependency-graph/issues/84): Fix regression of DOT label rendering introduced in 0.8.0. - * [#83](https://github.com/jrudolph/sbt-dependency-graph/issues/83): Added new task `dependencyStats` which prints a - simple table of jar sizes for all your dependencies. Handy if you want to know why your assembled jar gets so big. - * [#85](https://github.com/jrudolph/sbt-dependency-graph/issues/85): Added new task `dependencyList` which prints a - flat, deduplicated list of all the transitive dependencies. - -## Version 0.8.0 (2015-11-26) - -sbt-dependency-graph is finally an AutoPlugin and can now show the dependency graph in the browser directly. - -### New features - - - (experimental) open dependency graph directly in the browser with `dependencyBrowseGraph` ([#29](https://github.com/jrudolph/sbt-dependency-graph/issues/29)) - ![dependencyBrowseGraph in action](https://gist.githubusercontent.com/jrudolph/941754bcf67a0fafe495/raw/7d80d766feb7af6ba2a69494e1f3ceb1fd40d4da/Screenshot%2520from%25202015-11-26%252014:18:19.png) - - - this plugin is finally an sbt AutoPlugin and it is automatically enabled - ([#51](https://github.com/jrudolph/sbt-dependency-graph/issues/51)) - -**Note: To update from 0.7.x remove the `net.virtualvoid.sbt.graph.Plugin.graphSettings` line from your configurations.** - -### Other changes - - - a new backend was implemented which accesses the in-memory dependency data structures of sbt directly. The plugin doesn't - require accessing the ivy report XML any more (the old backend can still be wired in for comparisons if needed) which - should have solved the race condition and the dreaded `FileNotFoundException` ([#39](https://github.com/jrudolph/sbt-dependency-graph/issues/39)) - in multi-module projects. The new backend is only used for sbt >= 0.13.6. - - code was restructured which touched a lot of the classes but didn't change the function or syntax of settings and tasks. - - fixed [#77](https://github.com/jrudolph/sbt-dependency-graph/issues/77) - - -## Version 0.7.5 (2015-03-30) - -This is a maintenance release adding support for sbt 0.13.8. - -All changes: - - * [#67](https://github.com/jrudolph/sbt-dependency-graph/issues/67): Added support for sbt 0.13.8. Thanks - [@eed3si9n](https://github.com/eed3si9n) for the fix. - * [#37](https://github.com/jrudolph/sbt-dependency-graph/issues/37): Don't fail with StringIndexOutOfBoundsException - for deep trees. - * [#44](https://github.com/jrudolph/sbt-dependency-graph/issues/44): Only match scala lib by org/name. - Thanks [@2beaucoup](https://github.com/2beaucoup) for the fix. - -## Version 0.7.4 (2013-06-26) - -This is a maintenance release fixing an exception when generating graphs without a terminal [#32](https://github.com/jrudolph/sbt-dependency-graph/issues/32). - -## Version 0.7.3 (2013-04-28) - -This is a maintenance release. Following issues have been fixed: - - * [#27](https://github.com/jrudolph/sbt-dependency-graph/issues/27): A dependency configured with - a version range was not properly associated with its dependant. - * [#30](https://github.com/jrudolph/sbt-dependency-graph/issues/30) & [#31](https://github.com/jrudolph/sbt-dependency-graph/issues/31): - Make it work again with sbt 0.12.3. The path of the dependency resolution file changed in sbt 0.12.3. - Thanks [ebowman](https://github.com/ebowman) for the fix. - -## Version 0.7.2 (2013-03-02) - -This is a maintenance release. Following issues have been fixed: - - * [#27](https://github.com/jrudolph/sbt-dependency-graph/issues/27): A dependency configured with - a version range was not properly associated with its dependant. - - -## Version 0.7.1 - -New features in this version: - - * `dependency-license-info`: show dependencies grouped by declared license - * `dependency-dot`: create dot file from dependency graph. Contributed by - [berleon](https://github.com/berleon). - -## Version 0.7.0 (2012-10-24) - -New features in this version: - - * `dependency-graph` now renders a real graph. Thanks go to [Matt Russell](https://github.com/mdr/) for - this added awesomeness. - * The tree output from previous versions is now available with `dependency-tree`. - * New task `what-depends-on` showing reverse dependency tree for a selected module (incl. tab-completion for modules) - * Don't fail in cases of a missing dependency. Show errors directly in the output. - * Show info about evicted versions. - * By default, exclude scala-library dependency and append `[S]` to the artifact name instead. Set - `filter-scala-library` to `false` to disable this feature. - * Works with sbt 0.12.1. The ivy report files were moved to a new location making an update necessary. - - -## Version 0.6.0 (2012-05-23) - -New features in this version: - - * `dependency-graph` task now prints the dependency graph to the console - (contributed by @gseitz) - * `dependency-graph-ml` contains now the old functionality of `dependency-graph` - which generates a `.graphml` file. Nodes now contain the dependency version as well (contributed by @gseitz). - * The output filename of `dependency-graph-ml` has been changed to include the configuration name. It is now - configurable using the `dependency-graph-ml-file` setting. - * The common `scalaVersion in update` idiom to support Scala 2.9.1 libraries in a - Scala 2.9.2 broke the plugin in 0.5.2, because it wouldn't find the ivy report xml file - any more. This was fixed. - * All tasks are scoped by configuration. - -## Version 0.5.2 (2012-02-13) - -## Version 0.5.1 (2011-11-18) - -## Version 0.5 (2011-11-15) \ No newline at end of file diff --git a/sbt-dependency-graph/LICENSE b/sbt-dependency-graph/LICENSE deleted file mode 100644 index f49a4e16e..000000000 --- a/sbt-dependency-graph/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. \ No newline at end of file diff --git a/sbt-dependency-graph/NOTICE b/sbt-dependency-graph/NOTICE deleted file mode 100644 index 282e7e8e5..000000000 --- a/sbt-dependency-graph/NOTICE +++ /dev/null @@ -1,26 +0,0 @@ -AsciiTreeLayout.scala is copied from sbt and is distributed under the following license: - -Copyright (c) 2008, 2009, 2010 Steven Blundy, Josh Cough, Mark Harrah, Stuart Roebuck, Tony Sloane, Vesa Vilhonen, Jason Zaugg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/sbt-dependency-graph/PUBLISHING b/sbt-dependency-graph/PUBLISHING deleted file mode 100644 index 1f728acbf..000000000 --- a/sbt-dependency-graph/PUBLISHING +++ /dev/null @@ -1,12 +0,0 @@ -Before publishing: - - * create entry in CHANGELOG - * update version in README - - * run `;^ clean; ^ test:compile; ^ test; ^ scripted; ^publishSigned` - - * test staged version in sonatype - * release from sonatype - -After publishing: - * push master and tags diff --git a/sbt-dependency-graph/README.md b/sbt-dependency-graph/README.md deleted file mode 100644 index e2b07689f..000000000 --- a/sbt-dependency-graph/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# sbt-dependency-graph - -[![Join the chat at https://gitter.im/jrudolph/sbt-dependency-graph](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jrudolph/sbt-dependency-graph?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -Visualize your project's dependencies. - -**Note: Under sbt >= 1.3.x some features might currently not work as expected or not at all (like `dependencyLicenses`).** - -## Usage Instructions - -sbt-dependency-graph is an informational tool rather than one that changes your build, so you will more than likely wish to -install it as a [global plugin] so that you can use it in any SBT project without the need to explicitly add it to each one. To do -this, add the plugin dependency to `~/.sbt/0.13/plugins/plugins.sbt` for sbt 0.13 or `~/.sbt/1.0/plugins/plugins.sbt` for sbt 1.0: - -```scala -addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.10.0-RC1") -``` - -To add the plugin only to a single project, put this line into `project/plugins.sbt` of your project, instead. - -The plugin currently supports sbt versions >= 0.13.10 and sbt 1.0.x. For versions supporting older versions of sbt see -the notes of version [0.8.2](https://github.com/jrudolph/sbt-dependency-graph/tree/v0.8.2#compatibility-notes). - -## Main Tasks - - * `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). - * `dependencyBrowseTree`: Opens a browser window with a visualization of the dependency tree (courtesy of jstree). - * `dependencyList`: Shows a flat list of all transitive dependencies on the sbt console (sorted by organization and name) - * `whatDependsOn ?`: Find out what depends on an artifact. Shows a reverse dependency - tree for the selected module. The `` argument is optional. - * `dependencyLicenseInfo`: show dependencies grouped by declared license - * `dependencyStats`: Shows a table with each module a row with (transitive) Jar sizes and number of dependencies - * `dependencyGraphMl`: Generates a `.graphml` file with the project's dependencies to `target/dependencies-.graphml`. - Use e.g. [yEd](http://www.yworks.com/en/products_yed_about.html) to format the graph to your needs. - * `dependencyDot`: Generates a .dot file with the project's dependencies to `target/dependencies-.dot`. - Use [graphviz](http://www.graphviz.org/) to render it to your preferred graphic format. - * `dependencyGraph`: Shows an ASCII graph of the project's dependencies on the sbt console (only supported on sbt 0.13) - * `ivyReport`: Lets ivy generate the resolution report for you project. Use - `show ivyReport` for the filename of the generated report - -The following tasks also support the `toFile` subtask to save the contents to a file: - - * `dependencyTree` - * `dependencyList` - * `dependencyStats` - * `dependencyLicenseInfo` - -The `toFile` subtask has the following syntax: - -``` -:::toFile [-f|--force] -``` - -Use `-f` to force overwriting an existing file. - -E.g. `test:dependencyStats::toFile target/depstats.txt` will write the output of the `dependencyStats` in the `test` -configuration to the file `target/depstats.txt` but would not overwrite an existing file. - -All tasks can be scoped to a configuration to get the report for a specific configuration. `test:dependencyGraph`, -for example, prints the dependencies in the `test` configuration. If you don't specify any configuration, `compile` is -assumed as usual. - -Note: If you want to run tasks with parameters from outside the sbt shell, make sure to put the whole task invocation in -quotes, e.g. `sbt "whatDependsOn "`. - -## Configuration settings - - * `filterScalaLibrary`: Defines if the scala library should be excluded from the output of the dependency-* functions. - If `true`, instead of showing the dependency `"[S]"` is appended to the artifact name. Set to `false` if - you want the scala-library dependency to appear in the output. (default: true) - * `dependencyGraphMLFile`: a setting which allows configuring the output path of `dependency-graph-ml`. - * `dependencyDotFile`: a setting which allows configuring the output path of `dependency-dot`. - * `dependencyDotHeader`: a setting to customize the header of the dot file (e.g. to set your preferred node shapes). - * `dependencyDotNodeLabel`: defines the format of a node label - (default set to `[organisation]
[name]
[version]`) - -E.g. in `build.sbt` you can change configuration settings like this: - -```scala -filterScalaLibrary := false // include scala library in output - -dependencyDotFile := file("dependencies.dot") //render dot file to `./dependencies.dot` -``` - -## Known issues - - * [#19]: There's an unfixed bug with graph generation for particular layouts. Workaround: - Use `dependency-tree` instead of `dependency-graph`. - -## License - -Published under the [Apache License 2.0](http://en.wikipedia.org/wiki/Apache_license). - -[global plugin]: http://www.scala-sbt.org/0.13/tutorial/Using-Plugins.html#Global+plugins -[global build configuration]: http://www.scala-sbt.org/0.13/docs/Global-Settings.html -[#19]: https://github.com/jrudolph/sbt-dependency-graph/issues/19 diff --git a/sbt-dependency-graph/build.sbt b/sbt-dependency-graph/build.sbt deleted file mode 100644 index 27799adea..000000000 --- a/sbt-dependency-graph/build.sbt +++ /dev/null @@ -1,30 +0,0 @@ -enablePlugins(ScriptedPlugin) - -scriptedLaunchOpts += s"-Dproject.version=${version.value}" - -libraryDependencies ++= { - if ((sbtVersion in pluginCrossBuild).value startsWith "0.13") - Seq("com.github.mdr" %% "ascii-graphs" % "0.0.3") - else - Nil -} - - -libraryDependencies += "org.specs2" %% "specs2-core" % "3.10.0" % Test - -libraryDependencies += Defaults.sbtPluginExtra( - "com.dwijnand" % "sbt-compat" % "1.2.6", - (sbtBinaryVersion in pluginCrossBuild).value, - (scalaBinaryVersion in update).value -) - -crossSbtVersions := Seq("1.2.7", "0.13.18") - -scalacOptions ++= Seq( - "-deprecation", - "-encoding", "UTF-8", - "-feature", - "-unchecked" -) - -ScalariformSupport.formatSettings diff --git a/sbt-dependency-graph/project.sbt b/sbt-dependency-graph/project.sbt deleted file mode 100644 index 8d6305446..000000000 --- a/sbt-dependency-graph/project.sbt +++ /dev/null @@ -1,9 +0,0 @@ -sbtPlugin := true - -name := "sbt-dependency-graph" - -organization := "net.virtual-void" - -homepage := Some(url("http://github.com/jrudolph/sbt-dependency-graph")) - -licenses in GlobalScope += "Apache License 2.0" -> url("https://github.com/jrudolph/sbt-dependency-graph/raw/master/LICENSE") diff --git a/sbt-dependency-graph/project/ScalariformSupport.scala b/sbt-dependency-graph/project/ScalariformSupport.scala deleted file mode 100644 index 665a9e6fe..000000000 --- a/sbt-dependency-graph/project/ScalariformSupport.scala +++ /dev/null @@ -1,20 +0,0 @@ -import sbt._ - -import com.typesafe.sbt.SbtScalariform -import com.typesafe.sbt.SbtScalariform.ScalariformKeys - -object ScalariformSupport { - lazy val formatSettings = SbtScalariform.scalariformSettings ++ Seq( - ScalariformKeys.preferences in Compile := formattingPreferences, - ScalariformKeys.preferences in Test := formattingPreferences - ) - - import scalariform.formatter.preferences._ - def formattingPreferences = - FormattingPreferences() - .setPreference(RewriteArrowSymbols, true) - .setPreference(AlignParameters, true) - .setPreference(AlignSingleLineCaseStatements, true) - .setPreference(DoubleIndentClassDeclaration, true) - -} diff --git a/sbt-dependency-graph/project/build.properties b/sbt-dependency-graph/project/build.properties deleted file mode 100644 index 72f902892..000000000 --- a/sbt-dependency-graph/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version=1.2.7 diff --git a/sbt-dependency-graph/project/pgp.sbt b/sbt-dependency-graph/project/pgp.sbt deleted file mode 100644 index 2efcc4b69..000000000 --- a/sbt-dependency-graph/project/pgp.sbt +++ /dev/null @@ -1 +0,0 @@ -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0") diff --git a/sbt-dependency-graph/project/plugins.sbt b/sbt-dependency-graph/project/plugins.sbt deleted file mode 100644 index cb24a862c..000000000 --- a/sbt-dependency-graph/project/plugins.sbt +++ /dev/null @@ -1,4 +0,0 @@ -libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value - -addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2") -addSbtPlugin("com.dwijnand" % "sbt-dynver" % "2.0.0") diff --git a/sbt-dependency-graph/publish.sbt b/sbt-dependency-graph/publish.sbt deleted file mode 100644 index efef315bc..000000000 --- a/sbt-dependency-graph/publish.sbt +++ /dev/null @@ -1,31 +0,0 @@ -publishTo := { - val nexus = "https://oss.sonatype.org/" - Some { - if (version.value.trim.contains("+")) "snapshots" at nexus + "content/repositories/snapshots" - else "releases" at nexus + "service/local/staging/deploy/maven2" - } -} - -publishMavenStyle := true - -publishArtifact in Test := false - -pomIncludeRepository := { _ => false } - -scmInfo := Some( - ScmInfo( - browseUrl = url("https://github.com/jrudolph/sbt-dependency-graph"), - connection = "scm:git:git@github.com:jrudolph/sbt-dependency-graph.git" - ) -) - -developers := List( - Developer( - "jrudolph", - "Johannes Rudolph", - "johannes.rudolph@gmail.com", - url("https://virtual-void.net") - ) -) - -useGpg := true diff --git a/sbt-dependency-graph/src/main/resources/graph.html b/sbt-dependency-graph/src/main/resources/graph.html deleted file mode 100644 index 4ea8baba6..000000000 --- a/sbt-dependency-graph/src/main/resources/graph.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - -Dependency Graph - - - - - - - - - - - - - - - - - - - diff --git a/sbt-dependency-graph/src/main/resources/tree.html b/sbt-dependency-graph/src/main/resources/tree.html deleted file mode 100644 index 909a9b82e..000000000 --- a/sbt-dependency-graph/src/main/resources/tree.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - dependencyBrowseTree - - - - - - - - - - - -

Dependencies

-Search: -
- - - - \ No newline at end of file diff --git a/sbt-dependency-graph/src/main/scala-sbt-0.13/net/virtualvoid/sbt/graph/ModuleGraphProtocolCompat.scala b/sbt-dependency-graph/src/main/scala-sbt-0.13/net/virtualvoid/sbt/graph/ModuleGraphProtocolCompat.scala deleted file mode 100644 index d28f20d8b..000000000 --- a/sbt-dependency-graph/src/main/scala-sbt-0.13/net/virtualvoid/sbt/graph/ModuleGraphProtocolCompat.scala +++ /dev/null @@ -1,3 +0,0 @@ -package net.virtualvoid.sbt.graph - -trait ModuleGraphProtocolCompat diff --git a/sbt-dependency-graph/src/main/scala-sbt-0.13/net/virtualvoid/sbt/graph/rendering/AsciiGraph.scala b/sbt-dependency-graph/src/main/scala-sbt-0.13/net/virtualvoid/sbt/graph/rendering/AsciiGraph.scala deleted file mode 100644 index f1c83ec18..000000000 --- a/sbt-dependency-graph/src/main/scala-sbt-0.13/net/virtualvoid/sbt/graph/rendering/AsciiGraph.scala +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 com.github.mdr.ascii.layout._ -import net.virtualvoid.sbt.graph.DependencyGraphKeys._ -import sbt.Keys._ - -object AsciiGraph { - def asciiGraph(graph: ModuleGraph): String = - Layouter.renderGraph(buildAsciiGraph(graph)) - - private def buildAsciiGraph(moduleGraph: ModuleGraph): Graph[String] = { - def renderVertex(module: Module): String = - module.id.name + module.extraInfo + "\n" + - module.id.organisation + "\n" + - module.id.version + - module.error.map("\nerror: " + _).getOrElse("") + - module.evictedByVersion.map(_ formatted "\nevicted by: %s").getOrElse("") - - val vertices = moduleGraph.nodes.map(renderVertex).toList - val edges = moduleGraph.edges.toList.map { case (from, to) ⇒ (renderVertex(moduleGraph.module(from)), renderVertex(moduleGraph.module(to))) } - Graph(vertices, edges) - } - - def asciiGraphSetttings = Seq[sbt.Def.Setting[_]]( - DependencyGraphKeys.asciiGraph := asciiGraph(moduleGraph.value), - dependencyGraph := { - val force = DependencyGraphSettings.shouldForceParser.parsed - val log = streams.value.log - if (force || moduleGraph.value.nodes.size < 15) { - log.info(rendering.AsciiGraph.asciiGraph(moduleGraph.value)) - log.info("\n\n") - log.info("Note: The old tree layout is still available by using `dependency-tree`") - } - - log.info(rendering.AsciiTree.asciiTree(moduleGraph.value)) - - if (!force) { - log.info("\n") - log.info("Note: The graph was estimated to be too big to display (> 15 nodes). Use `sbt 'dependency-graph --force'` (with the single quotes) to force graph display.") - } - }) -} diff --git a/sbt-dependency-graph/src/main/scala-sbt-0.13/sbt/dependencygraph/DependencyGraphSbtCompat.scala b/sbt-dependency-graph/src/main/scala-sbt-0.13/sbt/dependencygraph/DependencyGraphSbtCompat.scala deleted file mode 100644 index 5aa6bacc6..000000000 --- a/sbt-dependency-graph/src/main/scala-sbt-0.13/sbt/dependencygraph/DependencyGraphSbtCompat.scala +++ /dev/null @@ -1,15 +0,0 @@ -package sbt -package dependencygraph - -import scala.language.implicitConversions - -object DependencyGraphSbtCompat { - object Implicits { - implicit def convertConfig(config: sbt.Configuration): String = config.toString - - implicit class RichUpdateConfiguration(val updateConfig: UpdateConfiguration) extends AnyVal { - def withMissingOk(missingOk: Boolean): UpdateConfiguration = - updateConfig.copy(missingOk = missingOk) - } - } -} diff --git a/sbt-dependency-graph/src/main/scala-sbt-1.0/net/virtualvoid/sbt/graph/ModuleGraphProtocolCompat.scala b/sbt-dependency-graph/src/main/scala-sbt-1.0/net/virtualvoid/sbt/graph/ModuleGraphProtocolCompat.scala deleted file mode 100644 index 1fb08ccc7..000000000 --- a/sbt-dependency-graph/src/main/scala-sbt-1.0/net/virtualvoid/sbt/graph/ModuleGraphProtocolCompat.scala +++ /dev/null @@ -1,25 +0,0 @@ -package net.virtualvoid.sbt.graph - -import java.io.{ ByteArrayInputStream, ByteArrayOutputStream, File } -import java.util.Base64 - -import sbinary.{ Format, JavaInput, JavaOutput } -import sjsonnew.{ Builder, Unbuilder } - -trait ModuleGraphProtocolCompat { - implicit def sjsonNewAndShinyTransformAndTranspileAdapterFactoryModuleImplementation[T](implicit format: Format[T]): sjsonnew.JsonFormat[T] = - new sjsonnew.JsonFormat[T] { - // note, how this is simpler to write than to learn any sjonnew protocol syntax - def write[J](obj: T, builder: Builder[J]): Unit = { - val baos = new ByteArrayOutputStream() - format.writes(new JavaOutput(baos), obj) - val str = Base64.getEncoder.encodeToString(baos.toByteArray) - builder.writeString(str) - } - def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): T = { - val str = unbuilder.readString(jsOpt.get) - val bais = new ByteArrayInputStream(Base64.getDecoder.decode(str)) - format.reads(new JavaInput(bais)) - } - } -} diff --git a/sbt-dependency-graph/src/main/scala-sbt-1.0/net/virtualvoid/sbt/graph/rendering/AsciiGraph.scala b/sbt-dependency-graph/src/main/scala-sbt-1.0/net/virtualvoid/sbt/graph/rendering/AsciiGraph.scala deleted file mode 100644 index b9e187a3b..000000000 --- a/sbt-dependency-graph/src/main/scala-sbt-1.0/net/virtualvoid/sbt/graph/rendering/AsciiGraph.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2017 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 - -object AsciiGraph { - def asciiGraphSetttings = Seq.empty[sbt.Def.Setting[_]] -} \ No newline at end of file diff --git a/sbt-dependency-graph/src/main/scala-sbt-1.0/sbt/dependencygraph/DependencyGraphSbtCompat.scala b/sbt-dependency-graph/src/main/scala-sbt-1.0/sbt/dependencygraph/DependencyGraphSbtCompat.scala deleted file mode 100644 index ea196cb8f..000000000 --- a/sbt-dependency-graph/src/main/scala-sbt-1.0/sbt/dependencygraph/DependencyGraphSbtCompat.scala +++ /dev/null @@ -1,6 +0,0 @@ -package sbt -package dependencygraph - -object DependencyGraphSbtCompat { - object Implicits -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala deleted file mode 100644 index 2abdd156d..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2014 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 - -import sbt._ - -trait DependencyGraphKeys { - val asString = TaskKey[String]("asString", "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]("toFile", "Writes the task value to the given file") - - val dependencyGraphMLFile = SettingKey[File]( - "dependency-graph-ml-file", - "The location the graphml file should be generated at") - val dependencyGraphML = TaskKey[File]( - "dependency-graph-ml", - "Creates a graphml file containing the dependency-graph for a project") - val dependencyDotFile = SettingKey[File]( - "dependency-dot-file", - "The location the dot file should be generated at") - val dependencyDotNodeLabel = SettingKey[(String, String, String) ⇒ String]( - "dependency-dot-node-label", - "Returns a formated string of a dependency. Takes organisation, name and version as parameters") - val dependencyDotHeader = SettingKey[String]( - "dependency-dot-header", - "The header of the dot file. (e.g. to set your preferred node shapes)") - val dependencyDot = TaskKey[File]( - "dependency-dot", - "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 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") - val moduleGraphIvyReport = TaskKey[ModuleGraph]( - "module-graph-ivy-report", - "The dependency graph for a project as generated from an Ivy Report XML") - val moduleGraphSbt = TaskKey[ModuleGraph]( - "module-graph-sbt", - "The dependency graph for a project as generated from SBT data structures.") - val asciiGraph = TaskKey[String]( - "dependency-graph-string", - "Returns a string containing the ascii representation of the dependency graph for a project") - val dependencyGraph = InputKey[Unit]( - "dependency-graph", - "Prints the ascii graph to the console") - val asciiTree = TaskKey[String]( - "dependency-tree-string", - "Returns a string containing an ascii tree representation of the dependency graph for a project") - val dependencyTree = TaskKey[Unit]( - "dependency-tree", - "Prints an ascii tree of all the dependencies to the console") - val dependencyList = TaskKey[Unit]( - "dependency-list", - "Prints a list of all dependencies to the console") - val dependencyStats = TaskKey[Unit]( - "dependency-stats", - "Prints statistics for all dependencies to the console") - val ivyReportFunction = TaskKey[String ⇒ File]( - "ivy-report-function", - "A function which returns the file containing the ivy report from the ivy cache for a given configuration") - val ivyReport = TaskKey[File]( - "ivy-report", - "A task which returns the location of the ivy report file for a given configuration (default `compile`).") - val filterScalaLibrary = SettingKey[Boolean]( - "filter-scala-library", - "Specifies if scala dependency should be filtered in dependency-* output") - - val licenseInfo = TaskKey[Unit]( - "dependency-license-info", - "Aggregates and shows information about the licenses of dependencies") - - // internal - private[graph] val ignoreMissingUpdate = TaskKey[UpdateReport]("dependencyUpdate", "sbt-dependency-graph version of update") - private[graph] val moduleGraphStore = TaskKey[ModuleGraph]("module-graph-store", "The stored module-graph from the last run") - val whatDependsOn = InputKey[String]("what-depends-on", "Shows information about what depends on the given module") - private[graph] val crossProjectId = SettingKey[ModuleID]("dependency-graph-cross-project-id") -} - -object DependencyGraphKeys extends DependencyGraphKeys diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphPlugin.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphPlugin.scala deleted file mode 100755 index 31f36d729..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphPlugin.scala +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, 2012 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 - -import sbt._ -import Keys._ - -object DependencyGraphPlugin extends AutoPlugin { - object autoImport extends DependencyGraphKeys - - override def projectSettings: Seq[Def.Setting[_]] = DependencyGraphSettings.graphSettings - - override def trigger: PluginTrigger = AllRequirements -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala deleted file mode 100644 index bec65daf6..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 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 - -import scala.language.reflectiveCalls -import sbt._ -import Keys._ -import sbt.complete.Parser -import net.virtualvoid.sbt.graph.backend.{ IvyReport, SbtUpdateReport } -import net.virtualvoid.sbt.graph.rendering.{ AsciiGraph, DagreHTML, TreeView } -import net.virtualvoid.sbt.graph.util.IOUtil -import internal.librarymanagement._ -import librarymanagement._ -import sbt.dependencygraph.SbtAccess -import sbt.dependencygraph.DependencyGraphSbtCompat.Implicits._ -import sbt.complete.Parsers - -object DependencyGraphSettings { - import DependencyGraphKeys._ - import ModuleGraphProtocol._ - - def graphSettings = baseSettings ++ reportSettings - - def baseSettings = Seq( - ivyReportFunction := ivyReportFunctionTask.value, - - // disable the cached resolution engine (exposing a scoped `ivyModule` used directly by `updateTask`), as it - // generates artificial module descriptors which are internal to sbt, making it hard to reconstruct the - // dependency tree - updateOptions in ignoreMissingUpdate := updateOptions.value.withCachedResolution(false), - ivyConfiguration in ignoreMissingUpdate := - // inTask will make sure the new definition will pick up `updateOptions in ignoreMissingUpdate` - SbtAccess.inTask(ignoreMissingUpdate, Classpaths.mkIvyConfiguration).value, - ivyModule in ignoreMissingUpdate := { - // concatenating & inlining ivySbt & ivyModule default task implementations, as `SbtAccess.inTask` does - // NOT correctly force the scope when applied to `TaskKey.toTask` instances (as opposed to raw - // implementations like `Classpaths.mkIvyConfiguration` or `Classpaths.updateTask`) - val is = new IvySbt((ivyConfiguration in ignoreMissingUpdate).value) - new is.Module(moduleSettings.value) - }, - - // don't fail on missing dependencies - updateConfiguration in ignoreMissingUpdate := updateConfiguration.value.withMissingOk(true), - - ignoreMissingUpdate := - // inTask will make sure the new definition will pick up `ivyModule/updateConfiguration in ignoreMissingUpdate` - SbtAccess.inTask(ignoreMissingUpdate, Classpaths.updateTask).value, - - filterScalaLibrary in Global := true) - - def reportSettings = - Seq(Compile, Test, IntegrationTest, Runtime, Provided, Optional).flatMap(ivyReportForConfig) - - val renderingAlternatives: Seq[(TaskKey[Unit], ModuleGraph ⇒ String)] = - Seq( - dependencyTree -> rendering.AsciiTree.asciiTree _, - dependencyList -> rendering.FlatList.render(_.id.idString), - dependencyStats -> rendering.Statistics.renderModuleStatsList _, - licenseInfo -> rendering.LicenseInfo.render _) - - def ivyReportForConfig(config: Configuration) = inConfig(config)( - Seq( - ivyReport := { Def.task { ivyReportFunction.value.apply(config.toString) } dependsOn (ignoreMissingUpdate) }.value, - crossProjectId := sbt.CrossVersion(scalaVersion.value, scalaBinaryVersion.value)(projectID.value), - moduleGraphSbt := - ignoreMissingUpdate.value.configuration(configuration.value).map(report ⇒ SbtUpdateReport.fromConfigurationReport(report, crossProjectId.value)).getOrElse(ModuleGraph.empty), - moduleGraphIvyReport := IvyReport.fromReportFile(absoluteReportPath(ivyReport.value)), - moduleGraph := { - sbtVersion.value match { - case Version(0, 13, x, _) if x >= 6 ⇒ moduleGraphSbt.value - case Version(1, _, _, _) ⇒ moduleGraphSbt.value - } - }, - moduleGraph := { - // FIXME: remove busywork - val scalaVersion = Keys.scalaVersion.value - val moduleGraph = DependencyGraphKeys.moduleGraph.value - - if (filterScalaLibrary.value) GraphTransformations.ignoreScalaLibrary(scalaVersion, moduleGraph) - else moduleGraph - }, - moduleGraphStore := (moduleGraph storeAs moduleGraphStore triggeredBy moduleGraph).value, - - // 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 := { target.value / "dependencies-%s.dot".format(config.toString) }, - dependencyDotString := rendering.DOT.dotGraph(moduleGraph.value, dependencyDotHeader.value, dependencyDotNodeLabel.value, rendering.DOT.AngleBrackets), - dependencyDot := writeToFile(dependencyDotString, dependencyDotFile).value, - dependencyDotHeader := - """|digraph "dependency-graph" { - | graph[rankdir="LR"] - | edge [ - | arrowtail="none" - | ]""".stripMargin, - dependencyDotNodeLabel := { (organisation: String, name: String, version: String) ⇒ - """%s
%s
%s""".format(organisation, name, version) - }, - - // GraphML support - dependencyGraphMLFile := { target.value / "dependencies-%s.graphml".format(config.toString) }, - dependencyGraphML := dependencyGraphMLTask.value, - - whatDependsOn := { - val ArtifactPattern(org, name, versionFilter) = artifactPatternParser.parsed - val graph = moduleGraph.value - val modules = - versionFilter match { - case Some(version) ⇒ ModuleId(org, name, version) :: Nil - case None ⇒ graph.nodes.filter(m ⇒ m.id.organisation == org && m.id.name == name).map(_.id) - } - val output = - modules - .map { module ⇒ - rendering.AsciiTree.asciiTree(GraphTransformations.reverseGraphStartingAt(graph, module)) - } - .mkString("\n") - - streams.value.log.info(output) - output - }, - // deprecated settings - asciiTree := (asString in dependencyTree).value) ++ - renderingAlternatives.flatMap((renderingTaskSettings _).tupled) ++ - AsciiGraph.asciiGraphSetttings) - - def renderingTaskSettings(key: TaskKey[Unit], renderer: ModuleGraph ⇒ String): Seq[Setting[_]] = - Seq( - asString in key := renderer(moduleGraph.value), - printToConsole in key := streams.value.log.info((asString in key).value), - toFile in key := { - val (targetFile, force) = targetFileAndForceParser.parsed - writeToFile(key.key.label, (asString in key).value, targetFile, force, streams.value) - }, - key := (printToConsole in key).value) - - def ivyReportFunctionTask = Def.task { - val ivyConfig = Keys.ivyConfiguration.value.asInstanceOf[InlineIvyConfiguration] - val projectID = Keys.projectID.value - val ivyModule = Keys.ivyModule.value - - (config: String) ⇒ { - val org = projectID.organization - val name = crossName(ivyModule) - new File(ivyConfig.resolutionCacheDir.get, s"reports/$org-$name-$config.xml") - } - } - - def dependencyGraphMLTask = - Def.task { - val resultFile = dependencyGraphMLFile.value - rendering.GraphML.saveAsGraphML(moduleGraph.value, resultFile.getAbsolutePath) - streams.value.log.info("Wrote dependency graph to '%s'" format resultFile) - resultFile - } - - def browseGraphHTMLTask = - Def.task { - val dotGraph = rendering.DOT.dotGraph(moduleGraph.value, dependencyDotHeader.value, dependencyDotNodeLabel.value, rendering.DOT.LabelTypeHtml) - val link = DagreHTML.createLink(dotGraph, target.value) - streams.value.log.info(s"HTML graph written to $link") - 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 - IOUtil.writeToFile(dataTask.value, outFile) - - streams.value.log.info("Wrote dependency graph to '%s'" format 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 { - IOUtil.writeToFile(data, targetFile) - - 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("Opening in browser...") - java.awt.Desktop.getDesktop.browse(uri) - uri - } - - case class ArtifactPattern( - organisation: String, - name: String, - version: Option[String]) - - import sbt.complete.DefaultParsers._ - val artifactPatternParser: Def.Initialize[State ⇒ Parser[ArtifactPattern]] = - resolvedScoped { ctx ⇒ (state: State) ⇒ - val graph = loadFromContext(moduleGraphStore, ctx, state) getOrElse ModuleGraph(Nil, Nil) - - graph.nodes - .map(_.id) - .groupBy(m ⇒ (m.organisation, m.name)) - .map { - case ((org, name), modules) ⇒ - val versionParsers: Seq[Parser[Option[String]]] = - modules.map { id ⇒ - token(Space ~> id.version).? - } - - (Space ~> token(org) ~ token(Space ~> name) ~ oneOf(versionParsers)).map { - case ((org, name), version) ⇒ ArtifactPattern(org, name, version) - } - } - .reduceOption(_ | _).getOrElse { - // If the moduleGraphStore couldn't be loaded because no dependency tree command was run before, we should still provide a parser for the command. - ((Space ~> token(StringBasic, "")) ~ (Space ~> token(StringBasic, "")) ~ (Space ~> token(StringBasic, "")).?).map { - case ((org, mod), version) ⇒ - ArtifactPattern(org, mod, version) - } - } - } - val shouldForceParser: Parser[Boolean] = (Space ~> (Parser.literal("-f") | "--force")).?.map(_.isDefined) - - val targetFileAndForceParser: Parser[(File, Boolean)] = - Parsers.fileParser(new File(".")) ~ shouldForceParser - - // This is to support 0.13.8's InlineConfigurationWithExcludes while not forcing 0.13.8 - type HasModule = { - val module: ModuleID - } - def crossName(ivyModule: IvySbt#Module) = - ivyModule.moduleSettings match { - case ic: InlineConfiguration ⇒ ic.module.name - case hm: HasModule @unchecked if hm.getClass.getName == "sbt.InlineConfigurationWithExcludes" ⇒ hm.module.name - case _ ⇒ - throw new IllegalStateException("sbt-dependency-graph plugin currently only supports InlineConfiguration of ivy settings (the default in sbt)") - } - - val VersionPattern = """(\d+)\.(\d+)\.(\d+)(?:-(.*))?""".r - object Version { - def unapply(str: String): Option[(Int, Int, Int, Option[String])] = str match { - case VersionPattern(major, minor, fix, appendix) ⇒ Some((major.toInt, minor.toInt, fix.toInt, Option(appendix))) - case _ ⇒ None - } - } -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/GraphTransformations.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/GraphTransformations.scala deleted file mode 100644 index c5c4e8a21..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/GraphTransformations.scala +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2011, 2012 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 - -object GraphTransformations { - def reverseGraphStartingAt(graph: ModuleGraph, root: ModuleId): ModuleGraph = { - val deps = graph.reverseDependencyMap - - def visit(module: ModuleId, visited: Set[ModuleId]): Seq[(ModuleId, ModuleId)] = - if (visited(module)) - Nil - else - deps.get(module) match { - case Some(deps) ⇒ - deps.flatMap { to ⇒ - (module, to.id) +: visit(to.id, visited + module) - } - case None ⇒ Nil - } - - val edges = visit(root, Set.empty) - val nodes = edges.foldLeft(Set.empty[ModuleId])((set, edge) ⇒ set + edge._1 + edge._2).map(graph.module) - ModuleGraph(nodes.toSeq, edges) - } - - def ignoreScalaLibrary(scalaVersion: String, graph: ModuleGraph): ModuleGraph = { - def isScalaLibrary(m: Module) = isScalaLibraryId(m.id) - def isScalaLibraryId(id: ModuleId) = id.organisation == "org.scala-lang" && id.name == "scala-library" - - def dependsOnScalaLibrary(m: Module): Boolean = - graph.dependencyMap(m.id).exists(isScalaLibrary) - - def addScalaLibraryAnnotation(m: Module): Module = { - if (dependsOnScalaLibrary(m)) - m.copy(extraInfo = m.extraInfo + " [S]") - else - m - } - - val newNodes = graph.nodes.map(addScalaLibraryAnnotation).filterNot(isScalaLibrary) - val newEdges = graph.edges.filterNot(e ⇒ isScalaLibraryId(e._2)) - ModuleGraph(newNodes, newEdges) - } -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/Main.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/Main.scala deleted file mode 100644 index fb51d60b7..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/Main.scala +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 - -import java.io.File - -import net.virtualvoid.sbt.graph.backend.IvyReport - -object Main extends App { - def die(msg: String): Nothing = { - println(msg) - sys.exit(1) - } - def usage: String = - "Usage: " - - val reportFile = args.lift(0).filter(f ⇒ new File(f).exists).getOrElse(die(usage)) - val outputFile = args.lift(1).getOrElse(die(usage)) - val graph = IvyReport.fromReportFile(reportFile) - rendering.GraphML.saveAsGraphML(graph, outputFile) -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/backend/IvyReport.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/backend/IvyReport.scala deleted file mode 100644 index 426a68a3e..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/backend/IvyReport.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 backend - -import scala.xml.{ NodeSeq, Document, Node } -import scala.xml.parsing.ConstructingParser - -object IvyReport { - def fromReportFile(ivyReportFile: String): ModuleGraph = - fromReportXML(loadXML(ivyReportFile)) - - def fromReportXML(doc: Document): ModuleGraph = { - def edgesForModule(id: ModuleId, revision: NodeSeq): Seq[Edge] = - for { - caller ← revision \ "caller" - callerModule = moduleIdFromElement(caller, caller.attribute("callerrev").get.text) - } yield (moduleIdFromElement(caller, caller.attribute("callerrev").get.text), id) - - val moduleEdges: Seq[(Module, Seq[Edge])] = for { - mod ← doc \ "dependencies" \ "module" - revision ← mod \ "revision" - rev = revision.attribute("name").get.text - moduleId = moduleIdFromElement(mod, rev) - module = Module( - moduleId, - (revision \ "license").headOption.flatMap(_.attribute("name")).map(_.text), - evictedByVersion = (revision \ "evicted-by").headOption.flatMap(_.attribute("rev").map(_.text)), - error = revision.attribute("error").map(_.text)) - } yield (module, edgesForModule(moduleId, revision)) - - val (nodes, edges) = moduleEdges.unzip - - val info = (doc \ "info").head - def infoAttr(name: String): String = - info.attribute(name).getOrElse(throw new IllegalArgumentException("Missing attribute " + name)).text - val rootModule = Module(ModuleId(infoAttr("organisation"), infoAttr("module"), infoAttr("revision"))) - - ModuleGraph(rootModule +: nodes, edges.flatten) - } - - private def moduleIdFromElement(element: Node, version: String): ModuleId = - ModuleId(element.attribute("organisation").get.text, element.attribute("name").get.text, version) - - private def loadXML(ivyReportFile: String) = - ConstructingParser.fromSource(io.Source.fromFile(ivyReportFile), preserveWS = false).document() -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/backend/SbtUpdateReport.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/backend/SbtUpdateReport.scala deleted file mode 100644 index 44a4c6cec..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/backend/SbtUpdateReport.scala +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 backend - -import scala.language.implicitConversions -import scala.language.reflectiveCalls - -import sbt._ - -object SbtUpdateReport { - type OrganizationArtifactReport = { - def modules: Seq[ModuleReport] - } - - def fromConfigurationReport(report: ConfigurationReport, rootInfo: sbt.ModuleID): ModuleGraph = { - implicit def id(sbtId: sbt.ModuleID): ModuleId = ModuleId(sbtId.organization, sbtId.name, sbtId.revision) - - def moduleEdges(orgArt: OrganizationArtifactReport): Seq[(Module, Seq[Edge])] = { - val chosenVersion = orgArt.modules.find(!_.evicted).map(_.module.revision) - orgArt.modules.map(moduleEdge(chosenVersion)) - } - - def moduleEdge(chosenVersion: Option[String])(report: ModuleReport): (Module, Seq[Edge]) = { - val evictedByVersion = if (report.evicted) chosenVersion else None - val jarFile = report.artifacts.find(_._1.`type` == "jar").orElse(report.artifacts.find(_._1.extension == "jar")).map(_._2) - ( - Module( - id = report.module, - license = report.licenses.headOption.map(_._1), - evictedByVersion = evictedByVersion, - jarFile = jarFile, - error = report.problem), - report.callers.map(caller ⇒ Edge(caller.caller, report.module))) - } - - val (nodes, edges) = report.details.flatMap(moduleEdges).unzip - val root = Module(rootInfo) - - ModuleGraph(root +: nodes, edges.flatten) - } -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/model.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/model.scala deleted file mode 100644 index cbfc43294..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/model.scala +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 - -import java.io.File - -import sbinary.Format - -import scala.collection.mutable.{ HashMap, MultiMap, Set } - -case class ModuleId( - organisation: String, - name: String, - version: String) { - def idString: String = organisation + ":" + name + ":" + version -} -case class Module( - id: ModuleId, - license: Option[String] = None, - extraInfo: String = "", - evictedByVersion: Option[String] = None, - jarFile: Option[File] = None, - error: Option[String] = None) { - def hadError: Boolean = error.isDefined - def isUsed: Boolean = !isEvicted - def isEvicted: Boolean = evictedByVersion.isDefined -} - -object ModuleGraph { - val empty = ModuleGraph(Seq.empty, Seq.empty) -} - -case class ModuleGraph(nodes: Seq[Module], edges: Seq[Edge]) { - lazy val modules: Map[ModuleId, Module] = - nodes.map(n ⇒ (n.id, n)).toMap - - def module(id: ModuleId): Module = modules(id) - - lazy val dependencyMap: Map[ModuleId, Seq[Module]] = - createMap(identity) - - lazy val reverseDependencyMap: Map[ModuleId, Seq[Module]] = - createMap { case (a, b) ⇒ (b, a) } - - def createMap(bindingFor: ((ModuleId, ModuleId)) ⇒ (ModuleId, ModuleId)): Map[ModuleId, Seq[Module]] = { - val m = new HashMap[ModuleId, Set[Module]] with MultiMap[ModuleId, Module] - edges.foreach { entry ⇒ - val (f, t) = bindingFor(entry) - m.addBinding(f, module(t)) - } - m.toMap.mapValues(_.toSeq.sortBy(_.id.idString)).withDefaultValue(Nil) - } - - def roots: Seq[Module] = - nodes.filter(n ⇒ !edges.exists(_._2 == n.id)).sortBy(_.id.idString) -} - -object ModuleGraphProtocol extends ModuleGraphProtocolCompat { - import sbinary.DefaultProtocol._ - - implicit def seqFormat[T: Format]: Format[Seq[T]] = wrap[Seq[T], List[T]](_.toList, _.toSeq) - implicit val ModuleIdFormat: Format[ModuleId] = asProduct3(ModuleId)(ModuleId.unapply(_).get) - implicit val ModuleFormat: Format[Module] = asProduct6(Module)(Module.unapply(_).get) - implicit val ModuleGraphFormat: Format[ModuleGraph] = asProduct2(ModuleGraph.apply _)(ModuleGraph.unapply(_).get) -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/package.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/package.scala deleted file mode 100644 index 41921bcfa..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/package.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 - -package object graph { - type Edge = (ModuleId, ModuleId) - def Edge(from: ModuleId, to: ModuleId): Edge = from -> to -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/AsciiTree.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/AsciiTree.scala deleted file mode 100644 index c2670e6a2..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/AsciiTree.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 util.AsciiTreeLayout -import util.ConsoleUtils._ - -object AsciiTree { - def asciiTree(graph: ModuleGraph): String = { - val deps = graph.dependencyMap - - // there should only be one root node (the project itself) - val roots = graph.roots - roots.map { root ⇒ - AsciiTreeLayout.toAscii[Module](root, node ⇒ deps.getOrElse(node.id, Seq.empty[Module]), displayModule) - }.mkString("\n") - } - - def displayModule(module: Module): String = - red(module.id.idString + - module.extraInfo + - module.error.map(" (error: " + _ + ")").getOrElse("") + - module.evictedByVersion.map(_ formatted " (evicted by: %s)").getOrElse(""), module.hadError) -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/DagreHTML.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/DagreHTML.scala deleted file mode 100644 index 3064ef502..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/DagreHTML.scala +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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) - } -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/FlatList.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/FlatList.scala deleted file mode 100644 index 95f0676d6..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/FlatList.scala +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2016 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 - -object FlatList { - def render(display: Module ⇒ String)(graph: ModuleGraph): String = - graph.modules.values.toSeq - .distinct - .filterNot(_.isEvicted) - .sortBy(m ⇒ (m.id.organisation, m.id.name)) - .map(display) - .mkString("\n") -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/GraphML.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/GraphML.scala deleted file mode 100644 index e1681fdad..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/GraphML.scala +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.rendering - -import net.virtualvoid.sbt.graph.ModuleGraph - -import scala.xml.XML - -object GraphML { - def saveAsGraphML(graph: ModuleGraph, outputFile: String): Unit = { - val nodesXml = - for (n ← graph.nodes) - yield - - { n.id.idString } - - - - val edgesXml = - for (e ← graph.edges) - yield - - val xml = - - - - { nodesXml } - { edgesXml } - - - - XML.save(outputFile, xml) - } -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/LicenseInfo.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/LicenseInfo.scala deleted file mode 100644 index cb97d3f0e..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/LicenseInfo.scala +++ /dev/null @@ -1,12 +0,0 @@ -package net.virtualvoid.sbt.graph.rendering - -import net.virtualvoid.sbt.graph.ModuleGraph - -object LicenseInfo { - def render(graph: ModuleGraph): String = - graph.nodes.filter(_.isUsed).groupBy(_.license).toSeq.sortBy(_._1).map { - case (license, modules) ⇒ - license.getOrElse("No license specified") + "\n" + - modules.map(_.id.idString formatted "\t %s").mkString("\n") - }.mkString("\n\n") -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/Statistics.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/Statistics.scala deleted file mode 100644 index a9d10fdba..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/Statistics.scala +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2016 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 - -object Statistics { - def renderModuleStatsList(graph: ModuleGraph): String = { - case class ModuleStats( - id: ModuleId, - numDirectDependencies: Int, - numTransitiveDependencies: Int, - selfSize: Option[Long], - transitiveSize: Long, - transitiveDependencyStats: Map[ModuleId, ModuleStats]) { - def transitiveStatsWithSelf: Map[ModuleId, ModuleStats] = transitiveDependencyStats + (id -> this) - } - - def statsFor(moduleId: ModuleId): ModuleStats = { - val directDependencies = graph.dependencyMap(moduleId).filterNot(_.isEvicted).map(_.id) - val dependencyStats = directDependencies.map(statsFor).flatMap(_.transitiveStatsWithSelf).toMap - val selfSize = graph.module(moduleId).jarFile.filter(_.exists).map(_.length) - val numDirectDependencies = directDependencies.size - val numTransitiveDependencies = dependencyStats.size - val transitiveSize = selfSize.getOrElse(0L) + dependencyStats.map(_._2.selfSize.getOrElse(0L)).sum - - ModuleStats(moduleId, numDirectDependencies, numTransitiveDependencies, selfSize, transitiveSize, dependencyStats) - } - - def format(stats: ModuleStats): String = { - import stats._ - def mb(bytes: Long): Double = bytes.toDouble / 1000000 - val selfSize = - stats.selfSize match { - case Some(size) ⇒ f"${mb(size)}%7.3f" - case None ⇒ "-------" - } - f"${mb(transitiveSize)}%7.3f MB $selfSize MB $numTransitiveDependencies%4d $numDirectDependencies%4d ${id.idString}%s" - } - - val allStats = - graph.roots.flatMap(r ⇒ statsFor(r.id).transitiveStatsWithSelf).toMap.values.toSeq - .sortBy(s ⇒ (-s.transitiveSize, -s.numTransitiveDependencies)) - - val header = " TotSize JarSize #TDe #Dep Module\n" - - header + - allStats.map(format).mkString("\n") + - """ - | - |Columns are - | - Jar-Size including dependencies - | - Jar-Size - | - Number of transitive dependencies - | - Number of direct dependencies - | - ModuleID""".stripMargin - } -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/TreeView.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/TreeView.scala deleted file mode 100644 index 582202def..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/rendering/TreeView.scala +++ /dev/null @@ -1,42 +0,0 @@ -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))) - } -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayout.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayout.scala deleted file mode 100644 index 746dab6df..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayout.scala +++ /dev/null @@ -1,62 +0,0 @@ -/* sbt -- Simple Build Tool - * Copyright 2011 Mark Harrah, Eugene Yokota - * - * Copied from sbt 0.12 source code - */ -package net.virtualvoid.sbt.graph.util - -import sbt.dependencygraph.SbtAccess - -object AsciiTreeLayout { - // [info] foo - // [info] +-bar - // [info] | +-baz - // [info] | - // [info] +-quux - def toAscii[A]( - top: A, - children: A ⇒ Seq[A], - display: A ⇒ String, - maxColumn: Int = defaultColumnSize): String = { - val twoSpaces = " " + " " // prevent accidentally being converted into a tab - def limitLine(s: String): String = - if (s.length > maxColumn) s.slice(0, maxColumn - 2) + ".." - else s - def insertBar(s: String, at: Int): String = - if (at < s.length) - s.slice(0, at) + - (s(at).toString match { - case " " ⇒ "|" - case x ⇒ x - }) + - s.slice(at + 1, s.length) - else s - def toAsciiLines(node: A, level: Int, parents: Set[A]): Vector[String] = - if (parents contains node) // cycle - Vector(limitLine((twoSpaces * level) + "#-" + display(node) + " (cycle)")) - else { - val line = limitLine((twoSpaces * level) + (if (level == 0) "" else "+-") + display(node)) - val cs = Vector(children(node): _*) - val childLines = cs map { - toAsciiLines(_, level + 1, parents + node) - } - val withBar = childLines.zipWithIndex flatMap { - case (lines, pos) if pos < (cs.size - 1) ⇒ lines map { - insertBar(_, 2 * (level + 1)) - } - case (lines, pos) ⇒ - if (lines.last.trim != "") lines ++ Vector(twoSpaces * (level + 1)) - else lines - } - line +: withBar - } - - toAsciiLines(top, 0, Set.empty).mkString("\n") - } - - def defaultColumnSize: Int = { - val termWidth = SbtAccess.getTerminalWidth - if (termWidth > 20) termWidth - 8 - else 80 // ignore termWidth - } -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/util/ConsoleUtils.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/util/ConsoleUtils.scala deleted file mode 100644 index ceba7da65..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/util/ConsoleUtils.scala +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.util - -import sbt.ConsoleLogger - -object ConsoleUtils { - def red(str: String, doRed: Boolean): String = - if (ConsoleLogger.formatEnabled && doRed) - Console.RED + str + Console.RESET - else - str -} diff --git a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/util/IOUtil.scala b/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/util/IOUtil.scala deleted file mode 100644 index c9b8ebbf5..000000000 --- a/sbt-dependency-graph/src/main/scala/net/virtualvoid/sbt/graph/util/IOUtil.scala +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.util - -import java.io.{ OutputStream, InputStream, FileOutputStream, File } -import java.nio.charset.Charset - -import scala.annotation.tailrec - -object IOUtil { - val utf8 = Charset.forName("utf8") - - def writeToFile(string: String, file: File): Unit = - sbt.IO.write(file, string, utf8) - - def saveResource(resourcePath: String, to: File): Unit = { - val is = getClass.getClassLoader.getResourceAsStream(resourcePath) - require(is ne null, s"Couldn't load '$resourcePath' from classpath.") - - val fos = new FileOutputStream(to) - try copy(is, fos) - finally { - is.close() - fos.close() - } - } - - def copy(from: InputStream, to: OutputStream): Unit = { - val buffer = new Array[Byte](65536) - - @tailrec def rec(): Unit = { - val read = from.read(buffer) - if (read > 0) { - to.write(buffer, 0, read) - rec() - } else if (read == 0) - throw new IllegalStateException("InputStream.read returned 0") - } - rec() - } -} diff --git a/sbt-dependency-graph/src/main/scala/sbt/dependencygraph/SbtAccess.scala b/sbt-dependency-graph/src/main/scala/sbt/dependencygraph/SbtAccess.scala deleted file mode 100644 index d1f4e596e..000000000 --- a/sbt-dependency-graph/src/main/scala/sbt/dependencygraph/SbtAccess.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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 sbt -package dependencygraph - -import Def._ - -/** Accessors to private[sbt] symbols. */ -object SbtAccess { - val unmanagedScalaInstanceOnly = Defaults.unmanagedScalaInstanceOnly - - def getTerminalWidth: Int = sbt.internal.util.JLine.usingTerminal(_.getWidth) - - def inTask[T](t: Scoped, i: Initialize[T]): Initialize[T] = _root_.sbt.inTask(t, i) -} diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/cachedResolution/project/plugins.sbt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/cachedResolution/project/plugins.sbt deleted file mode 100644 index 6fdebb6d6..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/cachedResolution/project/plugins.sbt +++ /dev/null @@ -1 +0,0 @@ -addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % sys.props("project.version")) diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/ignoreScalaLibrary/project/plugins.sbt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/ignoreScalaLibrary/project/plugins.sbt deleted file mode 120000 index 0caf1de77..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/ignoreScalaLibrary/project/plugins.sbt +++ /dev/null @@ -1 +0,0 @@ -../../plugins.sbt \ No newline at end of file diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/intervalRangedVersions/build.sbt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/intervalRangedVersions/build.sbt deleted file mode 100644 index b417c9e3b..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/intervalRangedVersions/build.sbt +++ /dev/null @@ -1,25 +0,0 @@ -scalaVersion := "2.9.1" - -resolvers += "typesafe maven" at "https://repo.typesafe.com/typesafe/maven-releases/" - -libraryDependencies ++= Seq( - "com.codahale" % "jerkson_2.9.1" % "0.5.0" -) - -TaskKey[Unit]("check") := { - val report = (ivyReport in Test).value - val graph = (asciiTree in Test).value - - def sanitize(str: String): String = str.split('\n').drop(1).map(_.trim).mkString("\n") - val expectedGraph = - """default:default-dbc48d_2.9.2:0.1-SNAPSHOT [S] - | +-com.codahale:jerkson_2.9.1:0.5.0 [S] - | +-org.codehaus.jackson:jackson-core-asl:1.9.11 - | +-org.codehaus.jackson:jackson-mapper-asl:1.9.11 - | +-org.codehaus.jackson:jackson-core-asl:1.9.11 - | """.stripMargin - 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))) - () -} diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/intervalRangedVersions/project/plugins.sbt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/intervalRangedVersions/project/plugins.sbt deleted file mode 120000 index 0caf1de77..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/intervalRangedVersions/project/plugins.sbt +++ /dev/null @@ -1 +0,0 @@ -../../plugins.sbt \ No newline at end of file diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/plugins.sbt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/plugins.sbt deleted file mode 100644 index 6fdebb6d6..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/plugins.sbt +++ /dev/null @@ -1 +0,0 @@ -addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % sys.props("project.version")) diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/showMissingUpdates/project/plugins.sbt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/showMissingUpdates/project/plugins.sbt deleted file mode 120000 index 0caf1de77..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/showMissingUpdates/project/plugins.sbt +++ /dev/null @@ -1 +0,0 @@ -../../plugins.sbt \ No newline at end of file diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/showMissingUpdates/test b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/showMissingUpdates/test deleted file mode 100644 index a5912a391..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/showMissingUpdates/test +++ /dev/null @@ -1 +0,0 @@ -> check \ No newline at end of file diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/testDotFileGeneration/build.sbt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/testDotFileGeneration/build.sbt deleted file mode 100644 index bb8469447..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/testDotFileGeneration/build.sbt +++ /dev/null @@ -1,68 +0,0 @@ -import collection.mutable.ListBuffer - -import net.virtualvoid.sbt.graph.DependencyGraphKeys.dependencyDot - -import scala.collection.mutable.ListBuffer - -def defaultSettings = - Seq( - scalaVersion := "2.9.2", - version := "0.1-SNAPSHOT" - ) - -lazy val justATransiviteDependencyEndpointProject = - Project("just-a-transitive-dependency-endpoint", file("a")) - .settings(defaultSettings: _*) - -lazy val justATransitiveDependencyProject = - Project("just-a-transitive-dependency", file("b")) - .settings(defaultSettings: _*) - .dependsOn(justATransiviteDependencyEndpointProject) - -lazy val justADependencyProject = - Project("just-a-dependency", file("c")) - .settings(defaultSettings: _*) - -lazy val test_project = - Project("test-dot-file-generation", file("d")) - .settings(defaultSettings: _*) - .settings( - TaskKey[Unit]("check") := { - val dotFile = (dependencyDot in Compile).value - val expectedGraph = - """digraph "dependency-graph" { - | graph[rankdir="LR"] - | edge [ - | arrowtail="none" - | ] - | "test-dot-file-generation:test-dot-file-generation_2.9.2:0.1-SNAPSHOT"[label=test-dot-file-generation_2.9.2
0.1-SNAPSHOT> style=""] - | "just-a-transitive-dependency:just-a-transitive-dependency_2.9.2:0.1-SNAPSHOT"[label=just-a-transitive-dependency_2.9.2
0.1-SNAPSHOT> style=""] - | "just-a-transitive-dependency-endpoint:just-a-transitive-dependency-endpoint_2.9.2:0.1-SNAPSHOT"[label=just-a-transitive-dependency-endpoint_2.9.2
0.1-SNAPSHOT> style=""] - | "just-a-dependency:just-a-dependency_2.9.2:0.1-SNAPSHOT"[label=just-a-dependency_2.9.2
0.1-SNAPSHOT> style=""] - | "test-dot-file-generation:test-dot-file-generation_2.9.2:0.1-SNAPSHOT" -> "just-a-transitive-dependency:just-a-transitive-dependency_2.9.2:0.1-SNAPSHOT" - | "just-a-transitive-dependency:just-a-transitive-dependency_2.9.2:0.1-SNAPSHOT" -> "just-a-transitive-dependency-endpoint:just-a-transitive-dependency-endpoint_2.9.2:0.1-SNAPSHOT" - | "test-dot-file-generation:test-dot-file-generation_2.9.2:0.1-SNAPSHOT" -> "just-a-dependency:just-a-dependency_2.9.2:0.1-SNAPSHOT" - |} - """.stripMargin - - val graph : String = scala.io.Source.fromFile(dotFile.getAbsolutePath).mkString - val errors = compareByLine(graph, expectedGraph) - require(errors.isEmpty , errors.mkString("\n")) - () - } - ) - .dependsOn(justADependencyProject, justATransitiveDependencyProject) - -def compareByLine(got : String, expected : String) : Seq[String] = { - val errors = ListBuffer[String]() - got.split("\n").zip(expected.split("\n").toSeq).zipWithIndex.foreach { case((got_line : String, expected_line : String), i : Int) => - if(got_line != expected_line) { - errors.append( - """not matching lines at line %s - |expected: %s - |got: %s - |""".stripMargin.format(i,expected_line, got_line)) - } - } - errors -} \ No newline at end of file diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/testDotFileGeneration/project/plugins.sbt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/testDotFileGeneration/project/plugins.sbt deleted file mode 120000 index 0caf1de77..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/testDotFileGeneration/project/plugins.sbt +++ /dev/null @@ -1 +0,0 @@ -../../plugins.sbt \ No newline at end of file diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/testDotFileGeneration/test b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/testDotFileGeneration/test deleted file mode 100644 index f9fa19e83..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/testDotFileGeneration/test +++ /dev/null @@ -1,2 +0,0 @@ -> project test-dot-file-generation -> check diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/licenses.txt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/licenses.txt deleted file mode 100644 index 826ed0153..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/licenses.txt +++ /dev/null @@ -1,9 +0,0 @@ -No license specified - org.example:blubber_2.12:0.1 - -The Apache Software License, Version 2.0 - org.codehaus.jackson:jackson-mapper-asl:1.9.11 - org.codehaus.jackson:jackson-core-asl:1.9.11 - -The MIT License - com.codahale:jerkson_2.9.1:0.5.0 \ No newline at end of file diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/list.txt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/list.txt deleted file mode 100644 index 4bf401868..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/list.txt +++ /dev/null @@ -1,4 +0,0 @@ -com.codahale:jerkson_2.9.1:0.5.0 -org.codehaus.jackson:jackson-core-asl:1.9.11 -org.codehaus.jackson:jackson-mapper-asl:1.9.11 -org.example:blubber_2.12:0.1 \ No newline at end of file diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/stats.txt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/stats.txt deleted file mode 100644 index 6a76e3522..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/stats.txt +++ /dev/null @@ -1,12 +0,0 @@ - TotSize JarSize #TDe #Dep Module - 1.754 MB ------- MB 3 1 org.example:blubber_2.12:0.1 - 1.754 MB 0.741 MB 2 2 com.codahale:jerkson_2.9.1:0.5.0 - 1.013 MB 0.780 MB 1 1 org.codehaus.jackson:jackson-mapper-asl:1.9.11 - 0.232 MB 0.232 MB 0 0 org.codehaus.jackson:jackson-core-asl:1.9.11 - -Columns are - - Jar-Size including dependencies - - Jar-Size - - Number of transitive dependencies - - Number of direct dependencies - - ModuleID \ No newline at end of file diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/tree.txt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/tree.txt deleted file mode 100644 index 5b1f1aa5e..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/expected/tree.txt +++ /dev/null @@ -1,6 +0,0 @@ -org.example:blubber_2.12:0.1 [S] - +-com.codahale:jerkson_2.9.1:0.5.0 [S] - +-org.codehaus.jackson:jackson-core-asl:1.9.11 - +-org.codehaus.jackson:jackson-mapper-asl:1.9.11 - +-org.codehaus.jackson:jackson-core-asl:1.9.11 - \ No newline at end of file diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/project/plugins.sbt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/project/plugins.sbt deleted file mode 100644 index 6fdebb6d6..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/project/plugins.sbt +++ /dev/null @@ -1 +0,0 @@ -addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % sys.props("project.version")) diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/test b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/test deleted file mode 100644 index 83d872e3e..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/test +++ /dev/null @@ -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 diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn-without-previous-initialization/project/plugins.sbt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn-without-previous-initialization/project/plugins.sbt deleted file mode 100644 index 6fdebb6d6..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn-without-previous-initialization/project/plugins.sbt +++ /dev/null @@ -1 +0,0 @@ -addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % sys.props("project.version")) diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn/project/plugins.sbt b/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn/project/plugins.sbt deleted file mode 100644 index 6fdebb6d6..000000000 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn/project/plugins.sbt +++ /dev/null @@ -1 +0,0 @@ -addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % sys.props("project.version")) diff --git a/sbt-dependency-graph/src/test/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayoutSpecs.scala b/sbt-dependency-graph/src/test/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayoutSpecs.scala deleted file mode 100644 index 097b7adf6..000000000 --- a/sbt-dependency-graph/src/test/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayoutSpecs.scala +++ /dev/null @@ -1,94 +0,0 @@ -package net.virtualvoid.sbt.graph.util - -import org.specs2.mutable.Specification - -class AsciiTreeLayoutSpecs extends Specification { - sealed trait Tree - case class Branch(left: Tree, right: Tree) extends Tree - case class Leaf(i: Int) extends Tree - - def children(t: Tree): Seq[Tree] = t match { - case Branch(left, right) ⇒ Seq(left, right) - case _: Leaf ⇒ Nil - } - def display(t: Tree): String = t match { - case Branch(left, right) ⇒ "Branch" - case Leaf(value) ⇒ value.toString * value - } - - "Graph" should { - "layout simple graphs" in { - val simple = Branch(Branch(Leaf(1), Leaf(2)), Leaf(3)) - AsciiTreeLayout.toAscii(simple, children, display, 20) === - """Branch - | +-Branch - | | +-1 - | | +-22 - | |\u0020 - | +-333 - | """.stripMargin - } - "add separator lines where applicable" in { - val simple = Branch(Branch(Leaf(1), Branch(Leaf(2), Leaf(3))), Leaf(4)) - AsciiTreeLayout.toAscii(simple, children, display, 20) === - """Branch - | +-Branch - | | +-1 - | | +-Branch - | | +-22 - | | +-333 - | |\u0020\u0020\u0020 - | +-4444 - | """.stripMargin - } - "layout deep graphs" in { - val simple = Branch(Branch(Branch(Branch(Branch(Branch(Leaf(1), Leaf(1)), Leaf(1)), Leaf(1)), Leaf(2)), Leaf(3)), Leaf(4)) - AsciiTreeLayout.toAscii(simple, children, display, 10) === - """Branch - | +-Branch - | | +-Br.. - | | | +-.. - | | | | .. - | | | | .. - | | | | .. - | | | | .. - | | | | | |\u0020 - | | | | .. - | | | | |\u0020 - | | | | .. - | | | |\u0020 - | | | +-22 - | | |\u0020 - | | +-333 - | |\u0020 - | +-4444 - | """.stripMargin - } - "cut off cycles" in { - AsciiTreeLayout.toAscii[Int](1, Map( - 1 -> Seq(2, 3, 4), - 2 -> Seq(4, 5), - 3 -> Seq(), - 4 -> Seq(3), - 5 -> Seq(1, 4, 6, 7), - 6 -> Seq(), - 7 -> Seq()), _.toString).trim === - """1 - | +-2 - | | +-4 - | | | +-3 - | | |\u0020 - | | +-5 - | | #-1 (cycle) - | | +-4 - | | | +-3 - | | |\u0020 - | | +-6 - | | +-7 - | |\u0020\u0020\u0020 - | +-3 - | +-4 - | +-3""".stripMargin.trim - } - } -} diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/cachedResolution/build.sbt b/sbt/src/sbt-test/dependency-graph/cachedResolution/build.sbt similarity index 85% rename from sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/cachedResolution/build.sbt rename to sbt/src/sbt-test/dependency-graph/cachedResolution/build.sbt index e9aef9b55..82144c4a0 100644 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/cachedResolution/build.sbt +++ b/sbt/src/sbt-test/dependency-graph/cachedResolution/build.sbt @@ -4,8 +4,8 @@ libraryDependencies += "org.slf4j" % "slf4j-api" % "1.7.28" updateOptions := updateOptions.value.withCachedResolution(true) TaskKey[Unit]("check") := { - val report = (ivyReport in Test).value - val graph = (asciiTree in Test).value + val report = (Test / ivyReport).value + val graph = (Test / dependencyTree / asString).value def sanitize(str: String): String = str.split('\n').drop(1).mkString("\n") val expectedGraph = diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/cachedResolution/test b/sbt/src/sbt-test/dependency-graph/cachedResolution/test similarity index 100% rename from sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/cachedResolution/test rename to sbt/src/sbt-test/dependency-graph/cachedResolution/test diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/ignoreScalaLibrary/build.sbt b/sbt/src/sbt-test/dependency-graph/ignoreScalaLibrary/build.sbt similarity index 91% rename from sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/ignoreScalaLibrary/build.sbt rename to sbt/src/sbt-test/dependency-graph/ignoreScalaLibrary/build.sbt index 1d004c5b6..7e9f4cce2 100644 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/ignoreScalaLibrary/build.sbt +++ b/sbt/src/sbt-test/dependency-graph/ignoreScalaLibrary/build.sbt @@ -6,8 +6,8 @@ libraryDependencies ++= Seq( ) TaskKey[Unit]("check") := { - val report = (ivyReport in Test).value - val graph = (asciiTree in Test).value + 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 expectedGraph = """default:default-e95e05_2.9.2:0.1-SNAPSHOT [S] diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/ignoreScalaLibrary/test b/sbt/src/sbt-test/dependency-graph/ignoreScalaLibrary/test similarity index 100% rename from sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/ignoreScalaLibrary/test rename to sbt/src/sbt-test/dependency-graph/ignoreScalaLibrary/test diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/showMissingUpdates/build.sbt b/sbt/src/sbt-test/dependency-graph/showMissingUpdates/build.sbt similarity index 86% rename from sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/showMissingUpdates/build.sbt rename to sbt/src/sbt-test/dependency-graph/showMissingUpdates/build.sbt index da6ad1a2a..192ecb0a9 100644 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/showMissingUpdates/build.sbt +++ b/sbt/src/sbt-test/dependency-graph/showMissingUpdates/build.sbt @@ -4,8 +4,8 @@ libraryDependencies += "at.blub" % "blib" % "1.2.3" % "test" TaskKey[Unit]("check") := { - val report = (ivyReport in Test).value - val graph = (asciiTree in Test).value + val report = updateFull.value + val graph = (Test / dependencyTree / asString).value def sanitize(str: String): String = str.split('\n').drop(1).mkString("\n") val expectedGraph = diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/intervalRangedVersions/test b/sbt/src/sbt-test/dependency-graph/showMissingUpdates/disabled similarity index 100% rename from sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/intervalRangedVersions/test rename to sbt/src/sbt-test/dependency-graph/showMissingUpdates/disabled diff --git a/sbt/src/sbt-test/dependency-graph/testDotFileGeneration/build.sbt b/sbt/src/sbt-test/dependency-graph/testDotFileGeneration/build.sbt new file mode 100644 index 000000000..313bcc9d7 --- /dev/null +++ b/sbt/src/sbt-test/dependency-graph/testDotFileGeneration/build.sbt @@ -0,0 +1,53 @@ +import scala.collection.mutable.ListBuffer + +ThisBuild / scalaVersion := "2.9.2" +ThisBuild / version := "0.1-SNAPSHOT" + +lazy val justATransiviteDependencyEndpointProject = project + +lazy val justATransitiveDependencyProject = project + .dependsOn(justATransiviteDependencyEndpointProject) + +lazy val justADependencyProject = project + +lazy val test_project = project + .dependsOn(justADependencyProject, justATransitiveDependencyProject) + .settings( + TaskKey[Unit]("check") := { + val dotFile = (dependencyDot in Compile).value + val expectedGraph = + """digraph "dependency-graph" { + | graph[rankdir="LR"] + | edge [ + | arrowtail="none" + | ] + | "test_project:test_project_2.9.2:0.1-SNAPSHOT"[label=test_project_2.9.2
0.1-SNAPSHOT> style=""] + | "justatransitivedependencyproject:justatransitivedependencyproject_2.9.2:0.1-SNAPSHOT"[label=justatransitivedependencyproject_2.9.2
0.1-SNAPSHOT> style=""] + | "justatransivitedependencyendpointproject:justatransivitedependencyendpointproject_2.9.2:0.1-SNAPSHOT"[label=justatransivitedependencyendpointproject_2.9.2
0.1-SNAPSHOT> style=""] + | "justadependencyproject:justadependencyproject_2.9.2:0.1-SNAPSHOT"[label=justadependencyproject_2.9.2
0.1-SNAPSHOT> style=""] + | "test_project:test_project_2.9.2:0.1-SNAPSHOT" -> "justatransitivedependencyproject:justatransitivedependencyproject_2.9.2:0.1-SNAPSHOT" + | "justatransitivedependencyproject:justatransitivedependencyproject_2.9.2:0.1-SNAPSHOT" -> "justatransivitedependencyendpointproject:justatransivitedependencyendpointproject_2.9.2:0.1-SNAPSHOT" + | "test_project:test_project_2.9.2:0.1-SNAPSHOT" -> "justadependencyproject:justadependencyproject_2.9.2:0.1-SNAPSHOT" + |} + """.stripMargin + + val graph : String = scala.io.Source.fromFile(dotFile.getAbsolutePath).mkString + val errors = compareByLine(graph, expectedGraph) + require(errors.isEmpty , errors.mkString("\n")) + () + } + ) + +def compareByLine(got : String, expected : String) : Seq[String] = { + val errors = ListBuffer[String]() + got.split("\n").zip(expected.split("\n").toSeq).zipWithIndex.foreach { case((got_line : String, expected_line : String), i : Int) => + if(got_line != expected_line) { + errors.append( + """not matching lines at line %s + |expected: %s + |got: %s + |""".stripMargin.format(i,expected_line, got_line)) + } + } + errors +} \ No newline at end of file diff --git a/sbt/src/sbt-test/dependency-graph/testDotFileGeneration/test b/sbt/src/sbt-test/dependency-graph/testDotFileGeneration/test new file mode 100644 index 000000000..cc5aac014 --- /dev/null +++ b/sbt/src/sbt-test/dependency-graph/testDotFileGeneration/test @@ -0,0 +1 @@ +> test_project/check diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/build.sbt b/sbt/src/sbt-test/dependency-graph/toFileSubTask/build.sbt similarity index 73% rename from sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/build.sbt rename to sbt/src/sbt-test/dependency-graph/toFileSubTask/build.sbt index d34ee89e9..6b66e7321 100644 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/toFileSubTask/build.sbt +++ b/sbt/src/sbt-test/dependency-graph/toFileSubTask/build.sbt @@ -1,15 +1,10 @@ -scalaVersion := "2.12.6" - -organization := "org.example" +// ThisBuild / useCoursier := false +ThisBuild / scalaVersion := "2.12.6" +ThisBuild / organization := "org.example" +ThisBuild / version := "0.1" name := "blubber" - -version := "0.1" - -libraryDependencies ++= Seq( - "com.codahale" % "jerkson_2.9.1" % "0.5.0" -) - +libraryDependencies += "org.typelevel" %% "cats-effect" % "2.2.0" TaskKey[Unit]("check") := { val candidates = "tree list stats licenses".split(' ').map(_.trim) candidates.foreach { c => diff --git a/sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/licenses.txt b/sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/licenses.txt new file mode 100644 index 000000000..012b770f5 --- /dev/null +++ b/sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/licenses.txt @@ -0,0 +1,9 @@ +No license specified + org.example:blubber_2.12:0.1 + +Apache-2.0 + org.typelevel:cats-effect_2.12:2.2.0 + +MIT + org.typelevel:cats-kernel_2.12:2.2.0 + org.typelevel:cats-core_2.12:2.2.0 \ No newline at end of file diff --git a/sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/list.txt b/sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/list.txt new file mode 100644 index 000000000..1a356d64b --- /dev/null +++ b/sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/list.txt @@ -0,0 +1,4 @@ +org.example:blubber_2.12:0.1 +org.typelevel:cats-core_2.12:2.2.0 +org.typelevel:cats-effect_2.12:2.2.0 +org.typelevel:cats-kernel_2.12:2.2.0 \ No newline at end of file diff --git a/sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/stats.txt b/sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/stats.txt new file mode 100644 index 000000000..3f3c415f0 --- /dev/null +++ b/sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/stats.txt @@ -0,0 +1,12 @@ + TotSize JarSize #TDe #Dep Module + 11.177 MB ------- MB 3 1 org.example:blubber_2.12:0.1 + 11.177 MB 1.185 MB 2 1 org.typelevel:cats-effect_2.12:2.2.0 + 9.992 MB 5.034 MB 1 1 org.typelevel:cats-core_2.12:2.2.0 + 4.958 MB 4.958 MB 0 0 org.typelevel:cats-kernel_2.12:2.2.0 + +Columns are + - Jar-Size including dependencies + - Jar-Size + - Number of transitive dependencies + - Number of direct dependencies + - ModuleID \ No newline at end of file diff --git a/sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/tree.txt b/sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/tree.txt new file mode 100644 index 000000000..d639a0acb --- /dev/null +++ b/sbt/src/sbt-test/dependency-graph/toFileSubTask/expected/tree.txt @@ -0,0 +1,5 @@ +org.example:blubber_2.12:0.1 [S] + +-org.typelevel:cats-effect_2.12:2.2.0 [S] + +-org.typelevel:cats-core_2.12:2.2.0 [S] + +-org.typelevel:cats-kernel_2.12:2.2.0 [S] + \ No newline at end of file diff --git a/sbt/src/sbt-test/dependency-graph/toFileSubTask/test b/sbt/src/sbt-test/dependency-graph/toFileSubTask/test new file mode 100644 index 000000000..b905a41b8 --- /dev/null +++ b/sbt/src/sbt-test/dependency-graph/toFileSubTask/test @@ -0,0 +1,5 @@ +> dependencyTree/toFile target/tree.txt +> dependencyList/toFile target/list.txt +> dependencyStats/toFile target/stats.txt +> dependencyLicenseInfo/toFile target/licenses.txt +> check diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn-without-previous-initialization/build.sbt b/sbt/src/sbt-test/dependency-graph/whatDependsOn-without-previous-initialization/build.sbt similarity index 98% rename from sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn-without-previous-initialization/build.sbt rename to sbt/src/sbt-test/dependency-graph/whatDependsOn-without-previous-initialization/build.sbt index 92bb3b2dd..0586054cd 100644 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn-without-previous-initialization/build.sbt +++ b/sbt/src/sbt-test/dependency-graph/whatDependsOn-without-previous-initialization/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + version := "0.1.0-SNAPSHOT" organization := "default" diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn-without-previous-initialization/test b/sbt/src/sbt-test/dependency-graph/whatDependsOn-without-previous-initialization/test similarity index 100% rename from sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn-without-previous-initialization/test rename to sbt/src/sbt-test/dependency-graph/whatDependsOn-without-previous-initialization/test diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn/build.sbt b/sbt/src/sbt-test/dependency-graph/whatDependsOn/build.sbt similarity index 58% rename from sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn/build.sbt rename to sbt/src/sbt-test/dependency-graph/whatDependsOn/build.sbt index 19c9108a1..8b3a0d5e1 100644 --- a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn/build.sbt +++ b/sbt/src/sbt-test/dependency-graph/whatDependsOn/build.sbt @@ -1,6 +1,7 @@ -version := "0.1.0-SNAPSHOT" +ThisBuild / version := "0.1.0-SNAPSHOT" +ThisBuild / scalaVersion := "2.9.1" -scalaVersion := "2.9.1" +name := "whatDependsOn" resolvers += "typesafe maven" at "https://repo.typesafe.com/typesafe/maven-releases/" @@ -18,18 +19,18 @@ check := { val withVersion = (whatDependsOn in Compile) - .toTask(" org.codehaus.jackson jackson-core-asl 1.9.11") + .toTask(" org.codehaus.jackson jackson-core-asl 1.9.10") .value val expectedGraphWithVersion = - """org.codehaus.jackson:jackson-core-asl:1.9.11 + """org.codehaus.jackson:jackson-core-asl:1.9.10 | +-com.codahale:jerkson_2.9.1:0.5.0 [S] - | | +-default:whatdependson_2.9.1:0.1.0-SNAPSHOT [S] + | | +-whatdependson:whatdependson_2.9.1:0.1.0-SNAPSHOT [S] | | - | +-org.codehaus.jackson:jackson-mapper-asl:1.9.11 + | +-org.codehaus.jackson:jackson-mapper-asl:1.9.10 | +-com.codahale:jerkson_2.9.1:0.5.0 [S] - | | +-default:whatdependson_2.9.1:0.1.0-SNAPSHOT [S] + | | +-whatdependson:whatdependson_2.9.1:0.1.0-SNAPSHOT [S] | | - | +-default:whatdependson_2.9.1:0.1.0-SNAPSHOT [S] + | +-whatdependson:whatdependson_2.9.1:0.1.0-SNAPSHOT [S] | """.stripMargin checkOutput(withVersion, expectedGraphWithVersion) @@ -39,14 +40,15 @@ check := { .toTask(" org.codehaus.jackson jackson-mapper-asl") .value val expectedGraphWithoutVersion = - """org.codehaus.jackson:jackson-mapper-asl:1.9.11 + """org.codehaus.jackson:jackson-mapper-asl:1.9.10 | +-com.codahale:jerkson_2.9.1:0.5.0 [S] - | | +-default:whatdependson_2.9.1:0.1.0-SNAPSHOT [S] + | | +-whatdependson:whatdependson_2.9.1:0.1.0-SNAPSHOT [S] | | - | +-default:whatdependson_2.9.1:0.1.0-SNAPSHOT [S] + | +-whatdependson:whatdependson_2.9.1:0.1.0-SNAPSHOT [S] | - |org.codehaus.jackson:jackson-mapper-asl:1.9.10 (evicted by: 1.9.11) - | +-default:whatdependson_2.9.1:0.1.0-SNAPSHOT [S] + |org.codehaus.jackson:jackson-mapper-asl:[1.9.0,2.0.0) (evicted by: 1.9.10) + | +-com.codahale:jerkson_2.9.1:0.5.0 [S] + | +-whatdependson:whatdependson_2.9.1:0.1.0-SNAPSHOT [S] | """.stripMargin checkOutput(withoutVersion, expectedGraphWithoutVersion) } diff --git a/sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn/test b/sbt/src/sbt-test/dependency-graph/whatDependsOn/test similarity index 100% rename from sbt-dependency-graph/src/sbt-test/sbt-dependency-graph/whatDependsOn/test rename to sbt/src/sbt-test/dependency-graph/whatDependsOn/test