mirror of https://github.com/sbt/sbt.git
Merge master and adapt solution
A new case class ArtifactPattern was created which models both searching with and without version.
This commit is contained in:
commit
6dbcad89d6
|
|
@ -0,0 +1,5 @@
|
|||
sudo: false
|
||||
language: scala
|
||||
jdk: oraclejdk8
|
||||
script:
|
||||
- sbt ";^test ;^scripted"
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
# Changelog
|
||||
|
||||
## 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))
|
||||

|
||||
|
||||
- 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)
|
||||
39
README.md
39
README.md
|
|
@ -1,46 +1,47 @@
|
|||
# sbt-dependency-graph
|
||||
|
||||
[](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.
|
||||
|
||||
## Preliminaries
|
||||
|
||||
The plugin works best with sbt >= 0.13.6. See the [compatibility notes](#compatibility-notes) to use this plugin with an older version of sbt.
|
||||
|
||||
## Usage Instructions
|
||||
|
||||
Since sbt-dependency-graph is an informational tool rather than one that changes your build, you will more than likely wish to
|
||||
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`:
|
||||
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.8.2")
|
||||
addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.0")
|
||||
```
|
||||
|
||||
To add the plugin only to a single project, put this line into `project/plugins.sbt` of your project, instead.
|
||||
|
||||
This plugin is an auto-plugin which will be automatically enabled starting from sbt 0.13.5.
|
||||
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).
|
||||
* `dependencyGraph`: Shows an ASCII graph of the project's dependencies on the sbt console
|
||||
* `dependencyList`: Shows a flat list of all transitive dependencies on the sbt console (sorted by organization and name)
|
||||
* `whatDependsOn <organization> <module> <revision>`: Find out what depends on an artifact. Shows a reverse dependency
|
||||
tree for the selected module.
|
||||
* `whatDependsOn <organization> <module> <revision>?`: Find out what depends on an artifact. Shows a reverse dependency
|
||||
tree for the selected module. The `<revision>` 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-<config>.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-<config>.dot`.
|
||||
Use [graphviz](http://www.graphviz.org/) to render it to your preferred graphic format.
|
||||
* `ivyReport`: let's ivy generate the resolution report for you project. Use
|
||||
* `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
|
||||
|
||||
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 <org> <module> <version>"`.
|
||||
|
||||
## Configuration settings
|
||||
|
||||
* `filterScalaLibrary`: Defines if the scala library should be excluded from the output of the dependency-* functions.
|
||||
|
|
@ -64,19 +65,6 @@ dependencyDotFile := file("dependencies.dot") //render dot file to `./dependenci
|
|||
|
||||
* [#19]: There's an unfixed bug with graph generation for particular layouts. Workaround:
|
||||
Use `dependency-tree` instead of `dependency-graph`.
|
||||
* [#39]: When using sbt-dependency-graph with sbt < 0.13.6.
|
||||
|
||||
## Compatibility notes
|
||||
|
||||
* sbt < 0.13.6: The plugin will fall back on the old ivy report XML backend which suffers from [#39].
|
||||
* sbt < 0.13.5: Old versions of sbt have no `AutoPlugin` support, you need to add
|
||||
|
||||
```scala
|
||||
net.virtualvoid.sbt.graph.DependencyGraphSettings.graphSettings
|
||||
```
|
||||
to your `build.sbt` or (`~/.sbt/0.13/user.sbt` for global configuration) to enable the plugin.
|
||||
* sbt <= 0.12.x: Old versions of sbt are not actively supported any more. Please use the old version from the [0.7 branch](https://github.com/jrudolph/sbt-dependency-graph/tree/0.7).
|
||||
|
||||
|
||||
## License
|
||||
|
||||
|
|
@ -85,4 +73,3 @@ Published under the [Apache License 2.0](http://en.wikipedia.org/wiki/Apache_lic
|
|||
[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
|
||||
[#39]: https://github.com/jrudolph/sbt-dependency-graph/issues/39
|
||||
|
|
|
|||
42
build.sbt
42
build.sbt
|
|
@ -1,28 +1,28 @@
|
|||
crossBuildingSettings
|
||||
scriptedLaunchOpts += s"-Dproject.version=${version.value}"
|
||||
|
||||
CrossBuilding.crossSbtVersions := Seq("0.13")
|
||||
|
||||
CrossBuilding.scriptedSettings
|
||||
|
||||
libraryDependencies += "com.github.mdr" %% "ascii-graphs" % "0.0.3"
|
||||
|
||||
libraryDependencies <++= scalaVersion { version =>
|
||||
if (version startsWith "2.1") Seq("org.scala-lang" % "scala-reflect" % version % "provided")
|
||||
else Nil
|
||||
libraryDependencies ++= {
|
||||
if ((sbtVersion in pluginCrossBuild).value startsWith "0.13")
|
||||
Seq("com.github.mdr" %% "ascii-graphs" % "0.0.3")
|
||||
else
|
||||
Nil
|
||||
}
|
||||
|
||||
libraryDependencies <+= scalaVersion { version =>
|
||||
if (version startsWith "2.9") "org.specs2" % "specs2_2.9.3" % "1.12.4.1" % "test"
|
||||
else "org.specs2" %% "specs2" % "2.3.11" % "test"
|
||||
}
|
||||
|
||||
scalacOptions ++= Seq("-deprecation", "-unchecked")
|
||||
libraryDependencies += "org.specs2" %% "specs2-core" % "3.10.0" % Test
|
||||
|
||||
sbt.CrossBuilding.latestCompatibleVersionMapper ~= {
|
||||
original => {
|
||||
case "0.13" => "0.13.6"
|
||||
case x => original(x)
|
||||
}
|
||||
}
|
||||
libraryDependencies += Defaults.sbtPluginExtra(
|
||||
"com.dwijnand" % "sbt-compat" % "1.2.6",
|
||||
(sbtBinaryVersion in pluginCrossBuild).value,
|
||||
(scalaBinaryVersion in update).value
|
||||
)
|
||||
|
||||
crossSbtVersions := Seq("1.1.6", "0.13.16")
|
||||
|
||||
scalacOptions ++= Seq(
|
||||
"-deprecation",
|
||||
"-encoding", "UTF-8",
|
||||
"-feature",
|
||||
"-unchecked"
|
||||
)
|
||||
|
||||
ScalariformSupport.formatSettings
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
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.
|
||||
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
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).
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
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.
|
||||
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1 +0,0 @@
|
|||
This is a maintenance release fixing an exception when generating graphs without a terminal [#32](https://github.com/jrudolph/sbt-dependency-graph/issues/32).
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
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))
|
||||

|
||||
|
||||
- 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)
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
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)!
|
||||
|
|
@ -1 +0,0 @@
|
|||
[sbt-dependency-graph](https://github.com/jrudolph/sbt-dependency-graph/) is an sbt plugin to visualize dependencies of your build.
|
||||
|
|
@ -4,8 +4,6 @@ name := "sbt-dependency-graph"
|
|||
|
||||
organization := "net.virtual-void"
|
||||
|
||||
version := "0.8.3-SNAPSHOT"
|
||||
|
||||
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")
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
import java.net.URL
|
||||
|
||||
object Helpers {
|
||||
def generatePomExtra(scmUrl: String, scmConnection: String,
|
||||
developerId: String, developerName: String): xml.NodeSeq =
|
||||
<scm>
|
||||
<url>{ scmUrl }</url>
|
||||
<connection>{ scmConnection }</connection>
|
||||
</scm>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>{ developerId }</id>
|
||||
<name>{ developerName }</name>
|
||||
</developer>
|
||||
</developers>
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
sbt.version=0.13.8
|
||||
sbt.version=1.1.6
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0")
|
||||
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0")
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
addSbtPlugin("net.virtual-void" % "sbt-cross-building" % "0.8.1")
|
||||
libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value
|
||||
|
||||
addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.2.1")
|
||||
addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2")
|
||||
addSbtPlugin("com.dwijnand" % "sbt-dynver" % "2.0.0")
|
||||
|
|
|
|||
27
publish.sbt
27
publish.sbt
|
|
@ -1,7 +1,9 @@
|
|||
publishTo <<= version { v: String =>
|
||||
publishTo := {
|
||||
val nexus = "https://oss.sonatype.org/"
|
||||
if (v.trim.endsWith("SNAPSHOT")) Some("snapshots" at nexus + "content/repositories/snapshots")
|
||||
else Some("releases" at nexus + "service/local/staging/deploy/maven2")
|
||||
Some {
|
||||
if (version.value.trim.contains("+")) "snapshots" at nexus + "content/repositories/snapshots"
|
||||
else "releases" at nexus + "service/local/staging/deploy/maven2"
|
||||
}
|
||||
}
|
||||
|
||||
publishMavenStyle := true
|
||||
|
|
@ -10,9 +12,20 @@ publishArtifact in Test := false
|
|||
|
||||
pomIncludeRepository := { _ => false }
|
||||
|
||||
pomExtra :=
|
||||
Helpers.generatePomExtra("git@github.com:jrudolph/sbt-dependency-graph.git",
|
||||
"scm:git:git@github.com:jrudolph/sbt-dependency-graph.git",
|
||||
"jrudolph", "Johannes Rudolph")
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
|
||||
{
|
||||
"organization":"net.virtualvoid",
|
||||
"name":"sbt-dependency-graph",
|
||||
"version":"0.5.1",
|
||||
"description":"An sbt plugin which allows to create a graphml file from the dependencies of the project.",
|
||||
"site":"http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"tags":["dependency","graph","sbt-plugin","sbt"],
|
||||
"docs":"http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"licenses": [{
|
||||
"name": "Apache License 2.0",
|
||||
"url": "https://github.com/jrudolph/sbt-dependency-graph/raw/master/LICENSE"
|
||||
}],
|
||||
"resolvers": ["http://scala-tools.org/repo-releases"],
|
||||
"dependencies": [],
|
||||
"scalas": ["2.9.1"],
|
||||
"sbt": true
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
|
||||
{
|
||||
"organization":"net.virtual-void",
|
||||
"name":"sbt-dependency-graph",
|
||||
"version":"0.5.2",
|
||||
"description":"An sbt plugin which allows to create a graphml file from the dependencies of the project.",
|
||||
"site":"http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"tags":["dependency","graph","sbt-plugin","sbt"],
|
||||
"docs":"http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"licenses": [{
|
||||
"name": "Apache License 2.0",
|
||||
"url": "https://github.com/jrudolph/sbt-dependency-graph/raw/master/LICENSE"
|
||||
}],
|
||||
"resolvers": ["http://scala-tools.org/repo-releases"],
|
||||
"dependencies": [],
|
||||
"scalas": ["2.9.1"],
|
||||
"sbt": true
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"organization":"net.virtual-void",
|
||||
"name":"sbt-dependency-graph",
|
||||
"version":"0.6.0",
|
||||
"description":"An sbt plugin to visualize dependencies of your build.",
|
||||
"site":"http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"tags":["dependency","graph","sbt-plugin","sbt"],
|
||||
"docs":"http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"licenses": [{
|
||||
"name": "Apache License 2.0",
|
||||
"url": "https://github.com/jrudolph/sbt-dependency-graph/raw/master/LICENSE"
|
||||
}],
|
||||
"resolvers": ["https://oss.sonatype.org/content/repositories/releases"],
|
||||
"dependencies": [],
|
||||
"scalas": ["2.9.1"],
|
||||
"sbt": true
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"organization" : "net.virtual-void",
|
||||
"name" : "sbt-dependency-graph",
|
||||
"version" : "0.7.0",
|
||||
"description" : "An sbt plugin to visualize dependencies of your build.",
|
||||
"site" : "http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"tags" : [ "dependency", "graph", "sbt-plugin", "sbt" ],
|
||||
"docs" : "http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"resolvers" : [ "https://oss.sonatype.org/content/repositories/releases" ],
|
||||
"dependencies" : [ {
|
||||
"organization" : "org.scala-sbt",
|
||||
"name" : "scripted-sbt",
|
||||
"version" : "0.12.0"
|
||||
}, {
|
||||
"organization" : "org.scala-sbt",
|
||||
"name" : "sbt-launch",
|
||||
"version" : "0.12.0"
|
||||
}, {
|
||||
"organization" : "com.github.mdr",
|
||||
"name" : "ascii-graphs",
|
||||
"version" : "0.0.2"
|
||||
} ],
|
||||
"scalas" : [ "2.9.2" ],
|
||||
"licenses" : [ {
|
||||
"name" : "Apache License 2.0",
|
||||
"url" : "https://github.com/jrudolph/sbt-dependency-graph/raw/master/LICENSE"
|
||||
} ],
|
||||
"sbt" : true
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"organization" : "net.virtual-void",
|
||||
"name" : "sbt-dependency-graph",
|
||||
"version" : "0.7.1",
|
||||
"description" : "An sbt plugin to visualize dependencies of your build.",
|
||||
"site" : "http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"tags" : [ "dependency", "graph", "sbt-plugin", "sbt" ],
|
||||
"docs" : "http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"resolvers" : [ "https://oss.sonatype.org/content/repositories/releases" ],
|
||||
"dependencies" : [ {
|
||||
"organization" : "org.scala-sbt",
|
||||
"name" : "scripted-sbt",
|
||||
"version" : "0.12.0"
|
||||
}, {
|
||||
"organization" : "org.scala-sbt",
|
||||
"name" : "sbt-launch",
|
||||
"version" : "0.12.0"
|
||||
}, {
|
||||
"organization" : "com.github.mdr",
|
||||
"name" : "ascii-graphs",
|
||||
"version" : "0.0.2"
|
||||
} ],
|
||||
"scalas" : [ "2.9.2" ],
|
||||
"licenses" : [ {
|
||||
"name" : "Apache License 2.0",
|
||||
"url" : "https://github.com/jrudolph/sbt-dependency-graph/raw/master/LICENSE"
|
||||
} ],
|
||||
"sbt" : true
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"organization" : "net.virtual-void",
|
||||
"name" : "sbt-dependency-graph",
|
||||
"version" : "0.7.2",
|
||||
"description" : "An sbt plugin to visualize dependencies of your build.",
|
||||
"site" : "http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"tags" : [ "dependency", "graph", "sbt-plugin", "sbt" ],
|
||||
"docs" : "http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"resolvers" : [ "https://oss.sonatype.org/content/repositories/releases" ],
|
||||
"dependencies" : [ {
|
||||
"organization" : "org.scala-sbt",
|
||||
"name" : "scripted-sbt",
|
||||
"version" : "0.12.1"
|
||||
}, {
|
||||
"organization" : "org.scala-sbt",
|
||||
"name" : "sbt-launch",
|
||||
"version" : "0.12.1"
|
||||
}, {
|
||||
"organization" : "com.github.mdr",
|
||||
"name" : "ascii-graphs",
|
||||
"version" : "0.0.2"
|
||||
} ],
|
||||
"scalas" : [ "2.9.2" ],
|
||||
"licenses" : [ {
|
||||
"name" : "Apache License 2.0",
|
||||
"url" : "https://github.com/jrudolph/sbt-dependency-graph/raw/master/LICENSE"
|
||||
} ],
|
||||
"sbt" : true
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"organization" : "net.virtual-void",
|
||||
"name" : "sbt-dependency-graph",
|
||||
"version" : "0.7.3",
|
||||
"description" : "An sbt plugin to visualize dependencies of your build.",
|
||||
"site" : "http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"tags" : [ "dependency", "graph", "sbt-plugin", "sbt" ],
|
||||
"docs" : "http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"resolvers" : [ "https://oss.sonatype.org/content/repositories/releases" ],
|
||||
"dependencies" : [ {
|
||||
"organization" : "org.scala-sbt",
|
||||
"name" : "scripted-sbt",
|
||||
"version" : "0.12.1"
|
||||
}, {
|
||||
"organization" : "org.scala-sbt",
|
||||
"name" : "sbt-launch",
|
||||
"version" : "0.12.1"
|
||||
}, {
|
||||
"organization" : "com.github.mdr",
|
||||
"name" : "ascii-graphs",
|
||||
"version" : "0.0.2"
|
||||
} ],
|
||||
"scalas" : [ "2.9.2" ],
|
||||
"licenses" : [ {
|
||||
"name" : "Apache License 2.0",
|
||||
"url" : "https://github.com/jrudolph/sbt-dependency-graph/raw/master/LICENSE"
|
||||
} ],
|
||||
"sbt" : true
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"organization" : "net.virtual-void",
|
||||
"name" : "sbt-dependency-graph",
|
||||
"version" : "0.7.4",
|
||||
"description" : "An sbt plugin to visualize dependencies of your build.",
|
||||
"site" : "http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"tags" : [ "dependency", "graph", "sbt-plugin", "sbt" ],
|
||||
"docs" : "http://github.com/jrudolph/sbt-dependency-graph",
|
||||
"resolvers" : [ "https://oss.sonatype.org/content/repositories/releases" ],
|
||||
"dependencies" : [ {
|
||||
"organization" : "org.scala-sbt",
|
||||
"name" : "scripted-sbt",
|
||||
"version" : "0.12.1"
|
||||
}, {
|
||||
"organization" : "org.scala-sbt",
|
||||
"name" : "sbt-launch",
|
||||
"version" : "0.12.1"
|
||||
}, {
|
||||
"organization" : "com.github.mdr",
|
||||
"name" : "ascii-graphs",
|
||||
"version" : "0.0.2"
|
||||
} ],
|
||||
"scalas" : [ "2.9.2" ],
|
||||
"licenses" : [ {
|
||||
"name" : "Apache License 2.0",
|
||||
"url" : "https://github.com/jrudolph/sbt-dependency-graph/raw/master/LICENSE"
|
||||
} ],
|
||||
"sbt" : true
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package net.virtualvoid.sbt.graph
|
||||
|
||||
trait ModuleGraphProtocolCompat
|
||||
|
|
@ -18,6 +18,8 @@ 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 =
|
||||
|
|
@ -35,4 +37,23 @@ object AsciiGraph {
|
|||
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.")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package sbt
|
||||
package dependencygraph
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
import Keys._
|
||||
import Def.Initialize
|
||||
import CrossVersion._
|
||||
|
||||
import scala.concurrent.duration.FiniteDuration
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is copied directly from https://github.com/sbt/sbt/blob/2952a2b9b672c5402b824ad2d2076243eb643598/main/src/main/scala/sbt/Defaults.scala#L1471-L1523
|
||||
* and then changed to update the UpdateConfiguration to ignore missing artifacts.
|
||||
*/
|
||||
def updateTask(task: TaskKey[_]): Initialize[Task[UpdateReport]] = Def.task {
|
||||
val depsUpdated = transitiveUpdate.value.exists(!_.stats.cached)
|
||||
val isRoot = executionRoots.value contains resolvedScoped.value
|
||||
val forceUpdate = forceUpdatePeriod.value
|
||||
val s = streams.value
|
||||
val fullUpdateOutput = s.cacheDirectory / "out"
|
||||
val forceUpdateByTime = forceUpdate match {
|
||||
case None ⇒ false
|
||||
case Some(period) ⇒
|
||||
val elapsedDuration = new FiniteDuration(System.currentTimeMillis() - fullUpdateOutput.lastModified(), TimeUnit.MILLISECONDS)
|
||||
fullUpdateOutput.exists() && elapsedDuration > period
|
||||
}
|
||||
val scalaProvider = appConfiguration.value.provider.scalaProvider
|
||||
|
||||
// Only substitute unmanaged jars for managed jars when the major.minor parts of the versions the same for:
|
||||
// the resolved Scala version and the scalaHome version: compatible (weakly- no qualifier checked)
|
||||
// the resolved Scala version and the declared scalaVersion: assume the user intended scalaHome to override anything with scalaVersion
|
||||
def subUnmanaged(subVersion: String, jars: Seq[File]) = (sv: String) ⇒
|
||||
(partialVersion(sv), partialVersion(subVersion), partialVersion(scalaVersion.value)) match {
|
||||
case (Some(res), Some(sh), _) if res == sh ⇒ jars
|
||||
case (Some(res), _, Some(decl)) if res == decl ⇒ jars
|
||||
case _ ⇒ Nil
|
||||
}
|
||||
val subScalaJars: String ⇒ Seq[File] = Defaults.unmanagedScalaInstanceOnly.value match {
|
||||
case Some(si) ⇒ subUnmanaged(si.version, si.jars)
|
||||
case None ⇒ sv ⇒ if (scalaProvider.version == sv) scalaProvider.jars else Nil
|
||||
}
|
||||
val transform: UpdateReport ⇒ UpdateReport = r ⇒ sbt.Classpaths.substituteScalaFiles(scalaOrganization.value, r)(subScalaJars)
|
||||
val uwConfig = (unresolvedWarningConfiguration in update).value
|
||||
val show = Reference.display(thisProjectRef.value)
|
||||
val st = state.value
|
||||
val logicalClock = LogicalClock(st.hashCode)
|
||||
val depDir = dependencyCacheDirectory.value
|
||||
val uc0 = (updateConfiguration in task).value
|
||||
val ms = publishMavenStyle.value
|
||||
val cw = compatibilityWarningOptions.value
|
||||
// Normally, log would capture log messages at all levels.
|
||||
// Ivy logs are treated specially using sbt.UpdateConfiguration.logging.
|
||||
// This code bumps up the sbt.UpdateConfiguration.logging to Full when logLevel is Debug.
|
||||
import UpdateLogging.{ Full, DownloadOnly, Default }
|
||||
val uc = (logLevel in update).?.value orElse st.get(logLevel.key) match {
|
||||
case Some(Level.Debug) if uc0.logging == Default ⇒ uc0.copy(logging = Full)
|
||||
case Some(x) if uc0.logging == Default ⇒ uc0.copy(logging = DownloadOnly)
|
||||
case _ ⇒ uc0
|
||||
}
|
||||
val ewo =
|
||||
if (executionRoots.value exists { _.key == evicted.key }) EvictionWarningOptions.empty
|
||||
else (evictionWarningOptions in update).value
|
||||
sbt.Classpaths.cachedUpdate(s.cacheDirectory / updateCacheName.value, show, ivyModule.value, uc, transform,
|
||||
skip = (skip in update).value, force = isRoot || forceUpdateByTime, depsUpdated = depsUpdated,
|
||||
uwConfig = uwConfig, logicalClock = logicalClock, depDir = Some(depDir),
|
||||
ewo = ewo, mavenStyle = ms, compatWarning = cw, log = s.log)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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[_]]
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package sbt
|
||||
package dependencygraph
|
||||
|
||||
import Keys._
|
||||
import Def.Initialize
|
||||
|
||||
import CrossVersion.partialVersion
|
||||
import sbt.internal.LibraryManagement
|
||||
|
||||
object DependencyGraphSbtCompat {
|
||||
object Implicits
|
||||
|
||||
// https://github.com/sbt/sbt/blob/4ce4fb72bde3b8acfaf526b79d32ca1463bc687b/main/src/main/scala/sbt/Defaults.scala#L2298 adapted
|
||||
// to allow customization of UpdateConfiguration
|
||||
def updateTask(task: TaskKey[_]): Initialize[Task[UpdateReport]] = Def.task {
|
||||
val depsUpdated = transitiveUpdate.value.exists(!_.stats.cached)
|
||||
val isRoot = executionRoots.value contains resolvedScoped.value
|
||||
val s = streams.value
|
||||
val scalaProvider = appConfiguration.value.provider.scalaProvider
|
||||
|
||||
// Only substitute unmanaged jars for managed jars when the major.minor parts of the versions the same for:
|
||||
// the resolved Scala version and the scalaHome version: compatible (weakly- no qualifier checked)
|
||||
// the resolved Scala version and the declared scalaVersion: assume the user intended scalaHome to override anything with scalaVersion
|
||||
def subUnmanaged(subVersion: String, jars: Seq[File]) = (sv: String) ⇒
|
||||
(partialVersion(sv), partialVersion(subVersion), partialVersion(scalaVersion.value)) match {
|
||||
case (Some(res), Some(sh), _) if res == sh ⇒ jars
|
||||
case (Some(res), _, Some(decl)) if res == decl ⇒ jars
|
||||
case _ ⇒ Nil
|
||||
}
|
||||
|
||||
val subScalaJars: String ⇒ Seq[File] = SbtAccess.unmanagedScalaInstanceOnly.value match {
|
||||
case Some(si) ⇒ subUnmanaged(si.version, si.allJars)
|
||||
case None ⇒ sv ⇒ if (scalaProvider.version == sv) scalaProvider.jars else Nil
|
||||
}
|
||||
|
||||
val transform: UpdateReport ⇒ UpdateReport =
|
||||
r ⇒ Classpaths.substituteScalaFiles(scalaOrganization.value, r)(subScalaJars)
|
||||
|
||||
val evictionOptions = Def.taskDyn {
|
||||
if (executionRoots.value.exists(_.key == evicted.key))
|
||||
Def.task(EvictionWarningOptions.empty)
|
||||
else Def.task((evictionWarningOptions in update).value)
|
||||
}.value
|
||||
|
||||
LibraryManagement.cachedUpdate(
|
||||
// LM API
|
||||
lm = dependencyResolution.value,
|
||||
// Ivy-free ModuleDescriptor
|
||||
module = ivyModule.value,
|
||||
s.cacheStoreFactory.sub(updateCacheName.value),
|
||||
Reference.display(thisProjectRef.value),
|
||||
(updateConfiguration in task).value,
|
||||
transform = transform,
|
||||
skip = (skip in update).value,
|
||||
force = isRoot,
|
||||
depsUpdated = transitiveUpdate.value.exists(!_.stats.cached),
|
||||
uwConfig = (unresolvedWarningConfiguration in update).value,
|
||||
ewo = evictionOptions,
|
||||
mavenStyle = publishMavenStyle.value,
|
||||
compatWarning = compatibilityWarningOptions.value,
|
||||
log = s.log)
|
||||
}
|
||||
}
|
||||
|
|
@ -19,53 +19,76 @@ package net.virtualvoid.sbt.graph
|
|||
import sbt._
|
||||
|
||||
trait DependencyGraphKeys {
|
||||
val dependencyGraphMLFile = SettingKey[File]("dependency-graph-ml-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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
val dependencyDot = TaskKey[File](
|
||||
"dependency-dot",
|
||||
"Creates a dot file containing the dependency-graph for a project")
|
||||
val dependencyDotString = TaskKey[String]("dependency-dot-string",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
val dependencyBrowseGraph = TaskKey[URI](
|
||||
"dependency-browse-graph",
|
||||
"Opens an HTML page that can be used to view the graph.")
|
||||
val moduleGraph = TaskKey[ModuleGraph]("module-graph",
|
||||
val moduleGraph = TaskKey[ModuleGraph](
|
||||
"module-graph",
|
||||
"The dependency graph for a project")
|
||||
val moduleGraphIvyReport = TaskKey[ModuleGraph]("module-graph-ivy-report",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
val dependencyGraph = InputKey[Unit](
|
||||
"dependency-graph",
|
||||
"Prints the ascii graph to the console")
|
||||
val asciiTree = TaskKey[String]("dependency-tree-string",
|
||||
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",
|
||||
val dependencyTree = TaskKey[Unit](
|
||||
"dependency-tree",
|
||||
"Prints an ascii tree of all the dependencies to the console")
|
||||
val dependencyList = TaskKey[Unit]("dependency-list",
|
||||
val dependencyList = TaskKey[Unit](
|
||||
"dependency-list",
|
||||
"Prints a list of all dependencies to the console")
|
||||
val dependencyStats = TaskKey[Unit]("dependency-stats",
|
||||
val dependencyStats = TaskKey[Unit](
|
||||
"dependency-stats",
|
||||
"Prints statistics for all dependencies to the console")
|
||||
val ivyReportFunction = TaskKey[String ⇒ File]("ivy-report-function",
|
||||
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",
|
||||
val ivyReport = TaskKey[File](
|
||||
"ivy-report",
|
||||
"A task which returns the location of the ivy report file for a given configuration (default `compile`).")
|
||||
val ignoreMissingUpdate = Keys.update in ivyReport
|
||||
val filterScalaLibrary = SettingKey[Boolean]("filter-scala-library",
|
||||
val filterScalaLibrary = SettingKey[Boolean](
|
||||
"filter-scala-library",
|
||||
"Specifies if scala dependency should be filtered in dependency-* output")
|
||||
|
||||
val licenseInfo = TaskKey[Unit]("dependency-license-info",
|
||||
val licenseInfo = TaskKey[Unit](
|
||||
"dependency-license-info",
|
||||
"Aggregates and shows information about the licenses of dependencies")
|
||||
|
||||
// internal
|
||||
|
|
|
|||
|
|
@ -16,157 +16,142 @@
|
|||
|
||||
package net.virtualvoid.sbt.graph
|
||||
|
||||
import scala.language.reflectiveCalls
|
||||
|
||||
import sbt._
|
||||
import Keys._
|
||||
|
||||
import CrossVersion._
|
||||
|
||||
import sbt.complete.Parser
|
||||
|
||||
import org.apache.ivy.core.resolve.ResolveOptions
|
||||
|
||||
import net.virtualvoid.sbt.graph.backend.{ IvyReport, SbtUpdateReport }
|
||||
import net.virtualvoid.sbt.graph.rendering.DagreHTML
|
||||
import net.virtualvoid.sbt.graph.rendering.{ AsciiGraph, DagreHTML }
|
||||
import net.virtualvoid.sbt.graph.util.IOUtil
|
||||
import internal.librarymanagement._
|
||||
import librarymanagement._
|
||||
import sbt.dependencygraph.DependencyGraphSbtCompat
|
||||
import sbt.dependencygraph.DependencyGraphSbtCompat.Implicits._
|
||||
|
||||
object DependencyGraphSettings {
|
||||
import DependencyGraphKeys._
|
||||
import ModuleGraphProtocol._
|
||||
|
||||
def graphSettings = Seq(
|
||||
ivyReportFunction <<= ivyReportFunctionTask,
|
||||
updateConfiguration in ignoreMissingUpdate <<= updateConfiguration(config ⇒ new UpdateConfiguration(config.retrieve, true, config.logging)),
|
||||
ignoreMissingUpdateT,
|
||||
filterScalaLibrary in Global := true) ++ Seq(Compile, Test, IntegrationTest, Runtime, Provided, Optional).flatMap(ivyReportForConfig)
|
||||
def graphSettings = baseSettings ++ reportSettings
|
||||
|
||||
def baseSettings = Seq(
|
||||
ivyReportFunction := ivyReportFunctionTask.value,
|
||||
updateConfiguration in ignoreMissingUpdate := updateConfiguration.value.withMissingOk(true),
|
||||
ignoreMissingUpdate := DependencyGraphSbtCompat.updateTask(ignoreMissingUpdate).value,
|
||||
filterScalaLibrary in Global := true)
|
||||
|
||||
def reportSettings =
|
||||
Seq(Compile, Test, IntegrationTest, Runtime, Provided, Optional).flatMap(ivyReportForConfig)
|
||||
|
||||
def ivyReportForConfig(config: Configuration) = inConfig(config)(Seq(
|
||||
ivyReport <<= ivyReportFunction map (_(config.toString)) dependsOn (ignoreMissingUpdate),
|
||||
crossProjectId <<= (scalaVersion, scalaBinaryVersion, projectID)((sV, sBV, id) ⇒ CrossVersion(sV, sBV)(id)),
|
||||
moduleGraphSbt <<= moduleGraphSbtTask,
|
||||
moduleGraphIvyReport <<= moduleGraphIvyReportTask,
|
||||
moduleGraph <<= (sbtVersion, moduleGraphSbt, moduleGraphIvyReport) { (version, graphSbt, graphIvy) ⇒
|
||||
version match {
|
||||
case Version(0, 13, x, _) if x >= 6 ⇒ graphSbt
|
||||
case _ ⇒ graphIvy
|
||||
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 <<= (scalaVersion, moduleGraph, filterScalaLibrary) map { (scalaV, graph, filter) ⇒
|
||||
if (filter) GraphTransformations.ignoreScalaLibrary(scalaV, graph)
|
||||
else graph
|
||||
},
|
||||
moduleGraphStore <<= moduleGraph storeAs moduleGraphStore triggeredBy moduleGraph,
|
||||
asciiGraph <<= moduleGraph map rendering.AsciiGraph.asciiGraph,
|
||||
dependencyGraph <<= InputTask(shouldForceParser) { force ⇒
|
||||
(force, moduleGraph, streams) map { (force, graph, streams) ⇒
|
||||
if (force || graph.nodes.size < 15) {
|
||||
streams.log.info(rendering.AsciiGraph.asciiGraph(graph))
|
||||
streams.log.info("\n\n")
|
||||
streams.log.info("Note: The old tree layout is still available by using `dependency-tree`")
|
||||
} else {
|
||||
streams.log.info(rendering.AsciiTree.asciiTree(graph))
|
||||
moduleGraph := {
|
||||
// FIXME: remove busywork
|
||||
val scalaVersion = Keys.scalaVersion.value
|
||||
val moduleGraph = DependencyGraphKeys.moduleGraph.value
|
||||
|
||||
if (!force) {
|
||||
streams.log.info("\n")
|
||||
streams.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.")
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filterScalaLibrary.value) GraphTransformations.ignoreScalaLibrary(scalaVersion, moduleGraph)
|
||||
else moduleGraph
|
||||
},
|
||||
asciiTree <<= moduleGraph map rendering.AsciiTree.asciiTree,
|
||||
dependencyTree <<= print(asciiTree),
|
||||
dependencyGraphMLFile <<= target / "dependencies-%s.graphml".format(config.toString),
|
||||
dependencyGraphML <<= dependencyGraphMLTask,
|
||||
dependencyDotFile <<= target / "dependencies-%s.dot".format(config.toString),
|
||||
dependencyDotString <<= dependencyDotStringTask,
|
||||
dependencyDot <<= writeToFile(dependencyDotString, dependencyDotFile),
|
||||
dependencyBrowseGraphTarget <<= target / "browse-dependency-graph",
|
||||
dependencyBrowseGraphHTML <<= browseGraphHTMLTask,
|
||||
dependencyBrowseGraph <<= (dependencyBrowseGraphHTML, streams).map { (uri, streams) ⇒
|
||||
streams.log.info("Opening in browser...")
|
||||
moduleGraphStore := (moduleGraph storeAs moduleGraphStore triggeredBy moduleGraph).value,
|
||||
asciiTree := rendering.AsciiTree.asciiTree(moduleGraph.value),
|
||||
dependencyTree := print(asciiTree).value,
|
||||
dependencyGraphMLFile := { target.value / "dependencies-%s.graphml".format(config.toString) },
|
||||
dependencyGraphML := dependencyGraphMLTask.value,
|
||||
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,
|
||||
dependencyBrowseGraphTarget := { target.value / "browse-dependency-graph" },
|
||||
dependencyBrowseGraphHTML := browseGraphHTMLTask.value,
|
||||
dependencyBrowseGraph := {
|
||||
val uri = dependencyBrowseGraphHTML.value
|
||||
streams.value.log.info("Opening in browser...")
|
||||
java.awt.Desktop.getDesktop.browse(uri)
|
||||
uri
|
||||
},
|
||||
dependencyList <<= printFromGraph(rendering.FlatList.render(_, _.id.idString)),
|
||||
dependencyStats <<= printFromGraph(rendering.Statistics.renderModuleStatsList),
|
||||
dependencyDotHeader := """digraph "dependency-graph" {
|
||||
| graph[rankdir="LR"]
|
||||
| edge [
|
||||
| arrowtail="none"
|
||||
| ]""".stripMargin,
|
||||
dependencyList := printFromGraph(rendering.FlatList.render(_, _.id.idString)).value,
|
||||
dependencyStats := printFromGraph(rendering.Statistics.renderModuleStatsList).value,
|
||||
dependencyDotHeader :=
|
||||
"""|digraph "dependency-graph" {
|
||||
| graph[rankdir="LR"]
|
||||
| edge [
|
||||
| arrowtail="none"
|
||||
| ]""".stripMargin,
|
||||
dependencyDotNodeLabel := { (organisation: String, name: String, version: String) ⇒
|
||||
"""%s<BR/><B>%s</B><BR/>%s""".format(organisation, name, version)
|
||||
},
|
||||
whatDependsOn <<= InputTask(artifactIdParser) { module ⇒
|
||||
(module, streams, moduleGraph) map { (module, streams, graph) ⇒
|
||||
if (module.version.isEmpty) {
|
||||
val modules = graph.reverseDependencyMap.filter(m ⇒ m._1.copy(version = "") == module).keys
|
||||
modules.foreach(m ⇒ streams.log.info(rendering.AsciiTree.asciiTree(GraphTransformations.reverseGraphStartingAt(graph, m))))
|
||||
} else streams.log.info(rendering.AsciiTree.asciiTree(GraphTransformations.reverseGraphStartingAt(graph, module)))
|
||||
}
|
||||
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)
|
||||
}
|
||||
modules
|
||||
.foreach { module ⇒
|
||||
streams.value.log.info(rendering.AsciiTree.asciiTree(GraphTransformations.reverseGraphStartingAt(graph, module)))
|
||||
}
|
||||
},
|
||||
licenseInfo <<= (moduleGraph, streams) map showLicenseInfo))
|
||||
licenseInfo := showLicenseInfo(moduleGraph.value, streams.value)) ++ AsciiGraph.asciiGraphSetttings)
|
||||
|
||||
def ivyReportFunctionTask =
|
||||
(sbtVersion, target, projectID, ivyModule, appConfiguration, streams) map { (sbtV, target, projectID, ivyModule, config, streams) ⇒
|
||||
sbtV match {
|
||||
case Version(0, min, fix, _) if min > 12 || (min == 12 && fix >= 3) ⇒
|
||||
(c: String) ⇒ file("%s/resolution-cache/reports/%s-%s-%s.xml".format(target, projectID.organization, crossName(ivyModule), c))
|
||||
case Version(0, min, fix, _) if min == 12 && fix >= 1 && fix < 3 ⇒
|
||||
ivyModule.withModule(streams.log) { (i, moduleDesc, _) ⇒
|
||||
val id = ResolveOptions.getDefaultResolveId(moduleDesc)
|
||||
(c: String) ⇒ file("%s/resolution-cache/reports/%s/%s-resolved.xml" format (target, id, c))
|
||||
}
|
||||
case _ ⇒
|
||||
val home = config.provider.scalaProvider.launcher.ivyHome
|
||||
(c: String) ⇒ file("%s/cache/%s-%s-%s.xml" format (home, projectID.organization, crossName(ivyModule), c))
|
||||
}
|
||||
def ivyReportFunctionTask = Def.task {
|
||||
val crossTarget = Keys.crossTarget.value
|
||||
val projectID = Keys.projectID.value
|
||||
val ivyModule = Keys.ivyModule.value
|
||||
|
||||
(config: String) ⇒ {
|
||||
val org = projectID.organization
|
||||
val name = crossName(ivyModule)
|
||||
file(s"${crossTarget}/resolution-cache/reports/$org-$name-$config.xml")
|
||||
}
|
||||
|
||||
def moduleGraphIvyReportTask = ivyReport map (absoluteReportPath.andThen(IvyReport.fromReportFile))
|
||||
def moduleGraphSbtTask =
|
||||
(ignoreMissingUpdate, crossProjectId, configuration) map { (update, root, config) ⇒
|
||||
update.configuration(config.name).map(report ⇒ SbtUpdateReport.fromConfigurationReport(report, root)).getOrElse(ModuleGraph.empty)
|
||||
}
|
||||
|
||||
def printAsciiGraphTask =
|
||||
(streams, asciiGraph) map (_.log.info(_))
|
||||
}
|
||||
|
||||
def dependencyGraphMLTask =
|
||||
(moduleGraph, dependencyGraphMLFile, streams) map { (graph, resultFile, streams) ⇒
|
||||
rendering.GraphML.saveAsGraphML(graph, resultFile.getAbsolutePath)
|
||||
streams.log.info("Wrote dependency graph to '%s'" format resultFile)
|
||||
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 dependencyDotStringTask =
|
||||
(moduleGraph, dependencyDotHeader, dependencyDotNodeLabel).map {
|
||||
(graph, dotHead, nodeLabel) ⇒ rendering.DOT.dotGraph(graph, dotHead, nodeLabel, rendering.DOT.AngleBrackets)
|
||||
}
|
||||
|
||||
def browseGraphHTMLTask =
|
||||
(moduleGraph, dependencyDotHeader, dependencyDotNodeLabel, dependencyBrowseGraphTarget, streams).map { (graph, dotHead, nodeLabel, target, streams) ⇒
|
||||
val dotGraph = rendering.DOT.dotGraph(graph, dotHead, nodeLabel, rendering.DOT.LabelTypeHtml)
|
||||
val link = DagreHTML.createLink(dotGraph, target)
|
||||
streams.log.info(s"HTML graph written to $link")
|
||||
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 writeToFile(dataTask: TaskKey[String], fileTask: SettingKey[File]) =
|
||||
(dataTask, fileTask, streams).map { (data, outFile, streams) ⇒
|
||||
IOUtil.writeToFile(data, outFile)
|
||||
Def.task {
|
||||
val outFile = fileTask.value
|
||||
IOUtil.writeToFile(dataTask.value, outFile)
|
||||
|
||||
streams.log.info("Wrote dependency graph to '%s'" format outFile)
|
||||
streams.value.log.info("Wrote dependency graph to '%s'" format outFile)
|
||||
outFile
|
||||
}
|
||||
|
||||
def absoluteReportPath = (file: File) ⇒ file.getAbsolutePath
|
||||
|
||||
def print(key: TaskKey[String]) =
|
||||
(streams, key) map (_.log.info(_))
|
||||
Def.task { streams.value.log.info(key.value) }
|
||||
|
||||
def printFromGraph(f: ModuleGraph ⇒ String) =
|
||||
(streams, moduleGraph) map ((streams, graph) ⇒ streams.log.info(f(graph)))
|
||||
Def.task { streams.value.log.info(f(moduleGraph.value)) }
|
||||
|
||||
def showLicenseInfo(graph: ModuleGraph, streams: TaskStreams) {
|
||||
def showLicenseInfo(graph: ModuleGraph, streams: TaskStreams): Unit = {
|
||||
val output =
|
||||
graph.nodes.filter(_.isUsed).groupBy(_.license).toSeq.sortBy(_._1).map {
|
||||
case (license, modules) ⇒
|
||||
|
|
@ -183,24 +168,32 @@ object DependencyGraphSettings {
|
|||
(Space ~> token("--force")).?.map(_.isDefined)
|
||||
}
|
||||
|
||||
val artifactIdParser: Initialize[State ⇒ Parser[ModuleId]] =
|
||||
resolvedScoped { ctx ⇒
|
||||
(state: State) ⇒
|
||||
val graph = loadFromContext(moduleGraphStore, ctx, state) getOrElse ModuleGraph(Nil, Nil)
|
||||
case class ArtifactPattern(
|
||||
organisation: String,
|
||||
name: String,
|
||||
version: Option[String])
|
||||
|
||||
import sbt.complete.DefaultParsers._
|
||||
graph.nodes.map(_.id).map {
|
||||
case id @ ModuleId(org, name, version) ⇒
|
||||
(Space ~ token(org) ~ token(Space ~ name) ~ token(Space ~ version).?).map(_._2 match {
|
||||
case Some(_) ⇒ id
|
||||
case None ⇒ id.copy(version = "")
|
||||
})
|
||||
}.reduceOption(_ | _).getOrElse {
|
||||
(Space ~> token(StringBasic, "organization") ~ Space ~ token(StringBasic, "module") ~ (Space ~ token(StringBasic, "version")).?).map {
|
||||
case (((org, _), mod), version) ⇒
|
||||
ModuleId(org, mod, version.map(_._2).getOrElse(""))
|
||||
}
|
||||
val artifactPatternParser: Def.Initialize[State ⇒ Parser[ArtifactPattern]] =
|
||||
resolvedScoped { ctx ⇒ (state: State) ⇒
|
||||
val graph = loadFromContext(moduleGraphStore, ctx, state) getOrElse ModuleGraph(Nil, Nil)
|
||||
|
||||
import sbt.complete.DefaultParsers._
|
||||
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(failure("No dependencies found"))
|
||||
}
|
||||
|
||||
// This is to support 0.13.8's InlineConfigurationWithExcludes while not forcing 0.13.8
|
||||
|
|
@ -222,34 +215,4 @@ object DependencyGraphSettings {
|
|||
case _ ⇒ None
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is copied directly from sbt/main/Defaults.java and then changed to update the UpdateConfiguration
|
||||
* to ignore missing artifacts.
|
||||
*/
|
||||
def ignoreMissingUpdateT =
|
||||
ignoreMissingUpdate <<= Def.task {
|
||||
val depsUpdated = transitiveUpdate.value.exists(!_.stats.cached)
|
||||
val isRoot = executionRoots.value contains resolvedScoped.value
|
||||
val s = streams.value
|
||||
val scalaProvider = appConfiguration.value.provider.scalaProvider
|
||||
|
||||
// Only substitute unmanaged jars for managed jars when the major.minor parts of the versions the same for:
|
||||
// the resolved Scala version and the scalaHome version: compatible (weakly- no qualifier checked)
|
||||
// the resolved Scala version and the declared scalaVersion: assume the user intended scalaHome to override anything with scalaVersion
|
||||
def subUnmanaged(subVersion: String, jars: Seq[File]) = (sv: String) ⇒
|
||||
(partialVersion(sv), partialVersion(subVersion), partialVersion(scalaVersion.value)) match {
|
||||
case (Some(res), Some(sh), _) if res == sh ⇒ jars
|
||||
case (Some(res), _, Some(decl)) if res == decl ⇒ jars
|
||||
case _ ⇒ Nil
|
||||
}
|
||||
val subScalaJars: String ⇒ Seq[File] = SbtAccess.unmanagedScalaInstanceOnly.value match {
|
||||
case Some(si) ⇒ subUnmanaged(si.version, si.jars)
|
||||
case None ⇒ sv ⇒ if (scalaProvider.version == sv) scalaProvider.jars else Nil
|
||||
}
|
||||
val transform: UpdateReport ⇒ UpdateReport = r ⇒ Classpaths.substituteScalaFiles(scalaOrganization.value, r)(subScalaJars)
|
||||
|
||||
val show = Reference.display(thisProjectRef.value)
|
||||
Classpaths.cachedUpdate(s.cacheDirectory, show, ivyModule.value, (updateConfiguration in ignoreMissingUpdate).value, transform, skip = (skip in update).value, force = isRoot, depsUpdated = depsUpdated, log = s.log)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ object IvyReport {
|
|||
revision ← mod \ "revision"
|
||||
rev = revision.attribute("name").get.text
|
||||
moduleId = moduleIdFromElement(mod, rev)
|
||||
module = Module(moduleId,
|
||||
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))
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
package net.virtualvoid.sbt.graph
|
||||
package backend
|
||||
|
||||
import scala.language.implicitConversions
|
||||
import scala.language.reflectiveCalls
|
||||
|
||||
import sbt._
|
||||
|
||||
object SbtUpdateReport {
|
||||
|
|
@ -35,7 +38,8 @@ object SbtUpdateReport {
|
|||
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(
|
||||
(
|
||||
Module(
|
||||
id = report.module,
|
||||
license = report.licenses.headOption.map(_._1),
|
||||
evictedByVersion = evictedByVersion,
|
||||
|
|
|
|||
|
|
@ -18,19 +18,23 @@ package net.virtualvoid.sbt.graph
|
|||
|
||||
import java.io.File
|
||||
|
||||
import scala.collection.mutable.{ MultiMap, HashMap, Set }
|
||||
import sbinary.Format
|
||||
|
||||
case class ModuleId(organisation: String,
|
||||
name: String,
|
||||
version: String) {
|
||||
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) {
|
||||
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
|
||||
|
|
@ -65,8 +69,9 @@ case class ModuleGraph(nodes: Seq[Module], edges: Seq[Edge]) {
|
|||
nodes.filter(n ⇒ !edges.exists(_._2 == n.id)).sortBy(_.id.idString)
|
||||
}
|
||||
|
||||
import sbinary.{ Format, DefaultProtocol }
|
||||
object ModuleGraphProtocol extends DefaultProtocol {
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -20,15 +20,17 @@ package rendering
|
|||
object DOT {
|
||||
val EvictedStyle = "stroke-dasharray: 5,5"
|
||||
|
||||
def dotGraph(graph: ModuleGraph,
|
||||
dotHead: String,
|
||||
nodeFormation: (String, String, String) ⇒ String,
|
||||
labelRendering: HTMLLabelRendering): String = {
|
||||
def dotGraph(
|
||||
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)
|
||||
""" "%s"[%s style="%s"]""".format(n.id.idString,
|
||||
""" "%s"[%s style="%s"]""".format(
|
||||
n.id.idString,
|
||||
labelRendering.renderLabel(label),
|
||||
style)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import net.virtualvoid.sbt.graph.ModuleGraph
|
|||
import scala.xml.XML
|
||||
|
||||
object GraphML {
|
||||
def saveAsGraphML(graph: ModuleGraph, outputFile: String) {
|
||||
def saveAsGraphML(graph: ModuleGraph, outputFile: String): Unit = {
|
||||
val nodesXml =
|
||||
for (n ← graph.nodes)
|
||||
yield <node id={ n.id.idString }><data key="d0">
|
||||
|
|
|
|||
|
|
@ -20,12 +20,12 @@ 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]) {
|
||||
id: ModuleId,
|
||||
numDirectDependencies: Int,
|
||||
numTransitiveDependencies: Int,
|
||||
selfSize: Option[Long],
|
||||
transitiveSize: Long,
|
||||
transitiveDependencyStats: Map[ModuleId, ModuleStats]) {
|
||||
def transitiveStatsWithSelf: Map[ModuleId, ModuleStats] = transitiveDependencyStats + (id -> this)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,16 +5,19 @@
|
|||
*/
|
||||
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 = {
|
||||
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) + ".."
|
||||
|
|
@ -52,7 +55,7 @@ object AsciiTreeLayout {
|
|||
}
|
||||
|
||||
def defaultColumnSize: Int = {
|
||||
val termWidth = sbt.SbtAccess.getTerminalWidth
|
||||
val termWidth = SbtAccess.getTerminalWidth
|
||||
if (termWidth > 20) termWidth - 8
|
||||
else 80 // ignore termWidth
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,11 +14,13 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sbt
|
||||
package sbt.dependencygraph
|
||||
|
||||
import sbt.Defaults
|
||||
|
||||
/** Accessors to private[sbt] symbols. */
|
||||
object SbtAccess {
|
||||
val unmanagedScalaInstanceOnly = Defaults.unmanagedScalaInstanceOnly
|
||||
|
||||
def getTerminalWidth: Int = JLine.usingTerminal(_.getWidth)
|
||||
def getTerminalWidth: Int = sbt.internal.util.JLine.usingTerminal(_.getWidth)
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
sbt.version=0.13.6
|
||||
|
|
@ -5,7 +5,9 @@ libraryDependencies ++= Seq(
|
|||
"ch.qos.logback" % "logback-classic" % "1.0.7"
|
||||
)
|
||||
|
||||
TaskKey[Unit]("check") <<= (ivyReport in Test, asciiTree in Test) map { (report, graph) =>
|
||||
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-e95e05_2.9.2:0.1-SNAPSHOT [S]
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
../../build.properties
|
||||
|
|
@ -1,17 +1,22 @@
|
|||
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") <<= (ivyReport in Test, asciiTree in Test) map { (report, graph) =>
|
||||
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.13
|
||||
| +-org.codehaus.jackson:jackson-mapper-asl:1.9.13
|
||||
| +-org.codehaus.jackson:jackson-core-asl:1.9.13
|
||||
| +-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"))
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
../../build.properties
|
||||
|
|
@ -1 +1 @@
|
|||
addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.8.3-SNAPSHOT")
|
||||
addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % sys.props("project.version"))
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ scalaVersion := "2.9.2"
|
|||
libraryDependencies +=
|
||||
"at.blub" % "blib" % "1.2.3" % "test"
|
||||
|
||||
TaskKey[Unit]("check") <<= (ivyReport in Test, asciiTree in Test) map { (report, graph) =>
|
||||
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).mkString("\n")
|
||||
val expectedGraph =
|
||||
"""default:default-91180e_2.9.2:0.1-SNAPSHOT
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
../../build.properties
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
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<BR/><B>test-dot-file-generation_2.9.2</B><BR/>0.1-SNAPSHOT> style=""]
|
||||
| "just-a-transitive-dependency:just-a-transitive-dependency_2.9.2:0.1-SNAPSHOT"[label=<just-a-transitive-dependency<BR/><B>just-a-transitive-dependency_2.9.2</B><BR/>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<BR/><B>just-a-transitive-dependency-endpoint_2.9.2</B><BR/>0.1-SNAPSHOT> style=""]
|
||||
| "just-a-dependency:just-a-dependency_2.9.2:0.1-SNAPSHOT"[label=<just-a-dependency<BR/><B>just-a-dependency_2.9.2</B><BR/>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
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
import collection.mutable.ListBuffer
|
||||
|
||||
import sbt._
|
||||
import sbt.Keys._
|
||||
|
||||
import net.virtualvoid.sbt.graph.DependencyGraphKeys._
|
||||
|
||||
object Build extends sbt.Build {
|
||||
|
||||
def defaultSettings =
|
||||
Seq(scalaVersion := "2.9.2")
|
||||
|
||||
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") <<= (dependencyDot in Compile) map { (dotFile) =>
|
||||
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<BR/><B>test-dot-file-generation_2.9.2</B><BR/>0.1-SNAPSHOT> style=""]
|
||||
| "just-a-transitive-dependency:just-a-transitive-dependency_2.9.2:0.1-SNAPSHOT"[label=<just-a-transitive-dependency<BR/><B>just-a-transitive-dependency_2.9.2</B><BR/>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<BR/><B>just-a-transitive-dependency-endpoint_2.9.2</B><BR/>0.1-SNAPSHOT> style=""]
|
||||
| "just-a-dependency:just-a-dependency_2.9.2:0.1-SNAPSHOT"[label=<just-a-dependency<BR/><B>just-a-dependency_2.9.2</B><BR/>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
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
../../build.properties
|
||||
Loading…
Reference in New Issue