diff --git a/build.sbt b/build.sbt
index ab195ffae..f33b9585a 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,7 +1,8 @@
ScriptedPlugin.scriptedSettings
libraryDependencies ++= {
- if (sbtVersion.value startsWith "0.13")
+ println(s"Evaluated ${sbtVersion in pluginCrossBuild value}")
+ if ((sbtVersion in pluginCrossBuild).value startsWith "0.13")
Seq("com.github.mdr" %% "ascii-graphs" % "0.0.3")
else
Nil
@@ -12,3 +13,19 @@ libraryDependencies += "org.specs2" %% "specs2-core" % "3.9.1" % "test"
scalacOptions ++= Seq("-deprecation", "-unchecked")
ScalariformSupport.formatSettings
+
+crossSbtVersions := Seq("1.0.1", "0.13.16")
+
+//sbtVersion in pluginCrossBuild := "1.0.0"
+
+/*
+Try to prevent silly warnings
+
+libraryDependencies += ("org.scala-sbt" %% "main-settings" % "1.0.1-SNAPSHOT")//.excludeAll(ExclusionRule(organization = "org.scala-sbt"))
+
+libraryDependencies += "org.scala-sbt" %% "command" % "1.0.0"force()
+libraryDependencies += "org.scala-sbt" %% "completion" % "1.0.0"force()
+libraryDependencies += "org.scala-sbt" %% "task-system" % "1.0.0"force()
+libraryDependencies += "org.scala-sbt" %% "core-macros" % "1.0.0" force()
+
+*/
\ No newline at end of file
diff --git a/src/main/scala-sbt-0.13/sbt/compat/SbtCompat.scala b/src/main/scala-sbt-0.13/sbt/compat/SbtCompat.scala
new file mode 100644
index 000000000..c3d8570bd
--- /dev/null
+++ b/src/main/scala-sbt-0.13/sbt/compat/SbtCompat.scala
@@ -0,0 +1,11 @@
+package sbt.compat
+
+object SbtCompat {
+ object librarymanagement
+ object internal {
+ object librarymanagement
+ object util {
+ val JLine: { def usingTerminal[T](f: jline.Terminal => T): T } = sbt.JLine
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/scala-sbt-1.0/sbt/compat/SbtCompat.scala b/src/main/scala-sbt-1.0/sbt/compat/SbtCompat.scala
new file mode 100644
index 000000000..9da65489d
--- /dev/null
+++ b/src/main/scala-sbt-1.0/sbt/compat/SbtCompat.scala
@@ -0,0 +1,3 @@
+package sbt.compat
+
+object SbtCompat
\ No newline at end of file
diff --git a/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala b/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala
index 790453585..fd3828488 100644
--- a/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala
+++ b/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala
@@ -25,48 +25,58 @@ import net.virtualvoid.sbt.graph.backend.{ IvyReport, SbtUpdateReport }
import net.virtualvoid.sbt.graph.rendering.{ AsciiGraph, DagreHTML }
import net.virtualvoid.sbt.graph.util.IOUtil
+import sbt.compat.SbtCompat._
+import internal.librarymanagement._
+import librarymanagement._
+
object DependencyGraphSettings {
import DependencyGraphKeys._
import ModuleGraphProtocol._
def graphSettings = Seq(
- ivyReportFunction <<= ivyReportFunctionTask,
- updateConfiguration in ignoreMissingUpdate <<= updateConfiguration(config ⇒ new UpdateConfiguration(config.retrieve, true, config.logging)),
- ignoreMissingUpdateT,
+ ivyReportFunction := ivyReportFunctionTask.value,
+ updateConfiguration in ignoreMissingUpdate := updateConfiguration.value.withMissingOk(true),
+ ignoreMissingUpdate := update.value,
filterScalaLibrary in Global := true) ++ 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
+ 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,
- 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),
+ dependencyList := printFromGraph(rendering.FlatList.render(_, _.id.idString)).value,
+ dependencyStats := printFromGraph(rendering.Statistics.renderModuleStatsList).value,
dependencyDotHeader := """digraph "dependency-graph" {
| graph[rankdir="LR"]
| edge [
@@ -75,79 +85,71 @@ object DependencyGraphSettings {
dependencyDotNodeLabel := { (organisation: String, name: String, version: String) ⇒
"""%s
%s
%s""".format(organisation, name, version)
},
- whatDependsOn <<= InputTask(artifactIdParser) { module ⇒
- (module, streams, moduleGraph) map { (module, streams, graph) ⇒
- streams.log.info(rendering.AsciiTree.asciiTree(GraphTransformations.reverseGraphStartingAt(graph, module)))
- }
+ whatDependsOn := {
+ val module = artifactIdParser.parsed
+ streams.value.log.info(rendering.AsciiTree.asciiTree(GraphTransformations.reverseGraphStartingAt(moduleGraph.value, module)))
},
- licenseInfo <<= (moduleGraph, streams) map showLicenseInfo) ++ AsciiGraph.asciiGraphSetttings)
+ 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 {
+ // FIXME: and remove busywork after https://github.com/sbt/sbt/issues/3299 is fixed
+ val target = Keys.target.value
+ val projectID = Keys.projectID.value
+ val ivyModule = Keys.ivyModule.value
+
+ sbtVersion.value 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.value.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 = appConfiguration.value.provider.scalaProvider.launcher.ivyHome
+ (c: String) ⇒ file("%s/cache/%s-%s-%s.xml" format (home, projectID.organization, crossName(ivyModule), c))
}
-
- 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) {
val output =
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")
+ modules.map("\t %s" format _.id.idString).mkString("\n")
}.mkString("\n\n")
streams.log.info(output)
}
@@ -159,7 +161,7 @@ object DependencyGraphSettings {
(Space ~> token("--force")).?.map(_.isDefined)
}
- val artifactIdParser: Initialize[State ⇒ Parser[ModuleId]] =
+ val artifactIdParser: Def.Initialize[State ⇒ Parser[ModuleId]] =
resolvedScoped { ctx ⇒
(state: State) ⇒
val graph = loadFromContext(moduleGraphStore, ctx, state) getOrElse ModuleGraph(Nil, Nil)
@@ -197,11 +199,17 @@ object DependencyGraphSettings {
}
/**
- * This is copied directly from sbt/main/Defaults.java and then changed to update the UpdateConfiguration
+ * This is copied directly from sbt/main/Defaults.scala and then changed to update the UpdateConfiguration
* to ignore missing artifacts.
*/
- def ignoreMissingUpdateT =
- ignoreMissingUpdate <<= Def.task {
+ /*def ignoreMissingUpdateT =
+ ignoreMissingUpdate := {
+ // FIXME: remove busywork
+
+ val scalaVersion = Keys.scalaVersion.value
+ val unmanagedScalaInstanceOnly = SbtAccess.unmanagedScalaInstanceOnly.value
+ val scalaOrganization = Keys.scalaOrganization.value
+
val depsUpdated = transitiveUpdate.value.exists(!_.stats.cached)
val isRoot = executionRoots.value contains resolvedScoped.value
val s = streams.value
@@ -211,18 +219,19 @@ object DependencyGraphSettings {
// 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 {
+ (partialVersion(sv), partialVersion(subVersion), partialVersion(scalaVersion)) 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)
+ val subScalaJars: String ⇒ Seq[File] = unmanagedScalaInstanceOnly 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 transform: UpdateReport ⇒ UpdateReport = r ⇒ Classpaths.substituteScalaFiles(scalaOrganization, 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)
- }
+ SbtAccess.cachedUpdater(
+ s.cacheDirectory, show, ivyModule.value, (updateConfiguration in ignoreMissingUpdate).value, transform, skip = (skip in update).value, force = isRoot, depsUpdated = depsUpdated, log = s.log)
+ }*/
}
diff --git a/src/main/scala/net/virtualvoid/sbt/graph/model.scala b/src/main/scala/net/virtualvoid/sbt/graph/model.scala
index 68b6a8862..850a43047 100644
--- a/src/main/scala/net/virtualvoid/sbt/graph/model.scala
+++ b/src/main/scala/net/virtualvoid/sbt/graph/model.scala
@@ -16,9 +16,13 @@
package net.virtualvoid.sbt.graph
-import java.io.File
+import java.io.{ ByteArrayInputStream, ByteArrayOutputStream, File }
+import java.util.Base64
-import scala.collection.mutable.{ MultiMap, HashMap, Set }
+import sbinary.{ JavaInput, JavaOutput }
+import sjsonnew.{ Builder, Unbuilder }
+
+import scala.collection.mutable.{ HashMap, MultiMap, Set }
case class ModuleId(organisation: String,
name: String,
@@ -71,4 +75,21 @@ object ModuleGraphProtocol extends DefaultProtocol {
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)
+
+ //
+ 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/src/main/scala/sbt/SbtAccess.scala b/src/main/scala/sbt/SbtAccess.scala
index a75a57c31..455e232e1 100644
--- a/src/main/scala/sbt/SbtAccess.scala
+++ b/src/main/scala/sbt/SbtAccess.scala
@@ -16,9 +16,18 @@
package sbt
+import sbt.compat.SbtCompat._
+import librarymanagement._
+import internal._
+import librarymanagement._
+import Classpaths._
+import LibraryManagement._
+import internal.util.JLine
+
/** Accessors to private[sbt] symbols. */
object SbtAccess {
val unmanagedScalaInstanceOnly = Defaults.unmanagedScalaInstanceOnly
def getTerminalWidth: Int = JLine.usingTerminal(_.getWidth)
+
}