Compiles with sbt 1.0 and sbt 0.13

1. ascii-graphs

We need a 2.12 version of ascii-graphs. The last commit to the project is in June 2013 (https://github.com/mdr/ascii-graphs/graphs/contributors). We are now in October 2017. I opened a PR (https://github.com/mdr/ascii-graphs/pull/11) but I don't expect any progress on this front. We can maintain a fork or drop ascii-graphs.

2. ignoreMissingUpdate

ignoreMissingUpdate is a tricky one. Here is some explanation:

we need to duplicate the updateTask

in sbt it's define as:

```scala
def updateTask: Initialize[Task[UpdateReport]] = Def.task {
  // ...
  val uc0 = updateConfiguration.value
  // ...
}
```

since it's not scoped to our task (ex: `updateConfiguration in ignoreMissingUpdate`) we cannot just do

```scala
updateConfiguration in ignoreMissingUpdate := {
  updateConfiguration.value.withMissingOk(true)
}
```

For example, the following example yield `"u2: false"

```
val update2 = TaskKey[Unit]("update2", "...")
val update2Configuration = SettingKey[Boolean]("...")

update2 := Def.task {
  val u2 = (update2Configuration in update2).value
  println(s"u2: $u2")
}.value

update2Configuration := false
update2Configuration in update2 := true
```

3. cross publishing

We can use the ^ operator to publish. For example: `sbt "^ publish"` to publish for both sbt 0.13 and 1.0.
This commit is contained in:
Guillaume Massé 2017-10-17 00:06:55 +02:00
parent 8591a5adae
commit 66f801bf92
17 changed files with 300 additions and 77 deletions

View File

@ -2,4 +2,12 @@ sudo: false
language: scala
jdk: oraclejdk7
script:
- sbt test scripted
# pending https://github.com/mdr/ascii-graphs/pull/11
- git clone git://github.com/MasseGuillaume/ascii-graphs.git
- pushd ascii-graphs
- git checkout 2.12
- sbt "+ publishLocal"
- popd
- sbt ";^test ;^scripted"

View File

@ -1,10 +1,18 @@
ScriptedPlugin.scriptedSettings
libraryDependencies ++= Seq(
"com.github.mdr" %% "ascii-graphs" % "0.0.3",
"org.specs2" %% "specs2" % "2.3.11" % Test
"com.github.mdr" %% "ascii-graphs" % "0.0.7-SNAPSHOT",
"org.specs2" %% "specs2-core" % "3.9.5" % Test
)
libraryDependencies += Defaults.sbtPluginExtra(
"com.dwijnand" % "sbt-compat" % "1.1.0",
(sbtBinaryVersion in pluginCrossBuild).value,
(scalaBinaryVersion in update).value
)
crossSbtVersions := List("0.13.16", "1.0.2")
scalacOptions ++= Seq(
"-deprecation",
"-encoding",
@ -14,3 +22,6 @@ scalacOptions ++= Seq(
)
ScalariformSupport.formatSettings
addCommandAlias("c1", ";cls;^^ 1.0.2;compile")
addCommandAlias("c0", ";cls;^^ 0.13.16;compile")

View File

@ -0,0 +1,25 @@
package net.virtualvoid.sbt.graph
import sbt._
import Keys._
import CrossVersion._
import DependencyGraphKeys._
object compat {
def convertConfig(config: sbt.Configuration): String = {
config.toString
}
/**
* This is copied directly from sbt/main/Defaults.java and then changed to update the UpdateConfiguration
* to ignore missing artifacts.
*/
def ingnoreMissingSettings: Seq[Setting[_]] = Seq(
updateConfiguration in ignoreMissingUpdate := {
val config = updateConfiguration.value
new UpdateConfiguration(config.retrieve, true, config.logging)
},
ignoreMissingUpdate := sbt.Compat.updateTask(ignoreMissingUpdate).value
)
}

View File

@ -0,0 +1,26 @@
/*
* Copyright 2015 Johannes Rudolph
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.virtualvoid.sbt.graph
import sbinary.{ Format, DefaultProtocol }
object ModuleGraphProtocol extends DefaultProtocol {
implicit def seqFormat[T: Format]: Format[Seq[T]] = wrap[Seq[T], List[T]](_.toList, _.toSeq)
implicit val ModuleIdFormat: Format[ModuleId] = asProduct3(ModuleId)(ModuleId.unapply(_).get)
implicit val ModuleFormat: Format[Module] = asProduct6(Module)(Module.unapply(_).get)
implicit val ModuleGraphFormat: Format[ModuleGraph] = asProduct2(ModuleGraph.apply _)(ModuleGraph.unapply(_).get)
}

View File

@ -0,0 +1,48 @@
package sbt
import Keys._
import Def.Initialize
import CrossVersion.partialVersion
object Compat {
// https://github.com/sbt/sbt/blob/e3c4db5ae80fa3e2a40b7a81bee0822e49f76aaf/main/src/main/scala/sbt/Defaults.scala#L1471
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 show = Reference.display(thisProjectRef.value)
Classpaths.cachedUpdate(
cacheFile = s.cacheDirectory,
label = show,
module = ivyModule.value,
config = (updateConfiguration in task).value,
transform = transform,
skip = (skip in update).value,
force = isRoot,
depsUpdated = depsUpdated,
log = s.log)
}
}

View File

@ -0,0 +1,19 @@
package net.virtualvoid.sbt.graph
import DependencyGraphKeys._
import sbt._
import Keys._
object compat {
def convertConfig(config: sbt.Configuration): sbt.Configuration = {
config
}
val ingnoreMissingSettings: Seq[Setting[_]] = Seq(
updateConfiguration in ignoreMissingUpdate := {
updateConfiguration.value.withMissingOk(true)
},
ignoreMissingUpdate := sbt.Compat.updateTask(ignoreMissingUpdate).value
)
}

View File

@ -0,0 +1,70 @@
/*
* Copyright 2015 Johannes Rudolph
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.virtualvoid.sbt.graph
import sjsonnew._, LList.:*:
object ModuleGraphProtocol extends BasicJsonProtocol {
implicit val ModuleIdFormat: IsoLList[ModuleId] =
LList.isoCurried(
(m: ModuleId) =>
("organisation", m.organisation) :*:
("name", m.name) :*:
("version", m.version) :*:
LNil
) { case
(_, organisation) :*:
(_, name) :*:
(version, _) :*:
LNil => ModuleId(organisation, name, version)
}
implicit val ModuleFormat: IsoLList[Module] =
LList.isoCurried(
(m: Module) =>
("id", m.id) :*:
("license", m.license) :*:
("extraInfo", m.extraInfo) :*:
("evictedByVersion", m.evictedByVersion) :*:
("jarFile", m.jarFile) :*:
("error", m.error) :*:
LNil
) {
case
(_, id) :*:
(_, license) :*:
(_, extraInfo) :*:
(_, evictedByVersion) :*:
(_, jarFile) :*:
(_, error) :*:
LNil => Module(id, license, extraInfo, evictedByVersion, jarFile, error)
}
implicit val ModuleGraphFormat: IsoLList[ModuleGraph] =
LList.isoCurried(
(g: ModuleGraph) =>
("nodes", g.nodes) :*:
("edges", g.edges) :*:
LNil
) { case
(_, nodes) :*:
(_, edges) :*:
LNil => ModuleGraph(nodes, edges)
}
}

View File

@ -0,0 +1,62 @@
package sbt
import Keys._
import Def.Initialize
import CrossVersion.partialVersion
import sbt.internal.LibraryManagement
object Compat {
// https://github.com/sbt/sbt/blob/4ce4fb72bde3b8acfaf526b79d32ca1463bc687b/main/src/main/scala/sbt/Defaults.scala#L2298
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
)
}
}

View File

@ -16,10 +16,13 @@
package net.virtualvoid.sbt.graph
import compat._
import sbt.librarymanagement._
import sbt._
import Keys._
import CrossVersion._
import sbt.CrossVersion._
import sbt.complete.Parser
@ -35,21 +38,26 @@ object DependencyGraphSettings {
import DependencyGraphKeys._
import ModuleGraphProtocol._
def graphSettings = Seq(
def graphSettings = baseSettings ++ ingnoreMissingSettings ++ reportSettings
def baseSettings = Seq(
ivyReportFunction := ivyReportFunctionTask.value,
updateConfiguration in ignoreMissingUpdate := {
val config = updateConfiguration.value
new UpdateConfiguration(config.retrieve, true, config.logging)
},
ignoreMissingUpdateT,
filterScalaLibrary in Global := true) ++ Seq(Compile, Test, IntegrationTest, Runtime, Provided, Optional).flatMap(ivyReportForConfig)
filterScalaLibrary in Global := true)
def reportSettings =
Seq(Compile, Test, IntegrationTest, Runtime, Provided, Optional).flatMap(ivyReportForConfig)
def ivyReportForConfig(config: Configuration) = inConfig(config)(Seq(
ivyReport := {
Def.task {
ivyReportFunction.value.apply(config.toString)
val ivyReportF = ivyReportFunction.value
ivyReportF(config.toString)
}.dependsOn(ignoreMissingUpdate)
}.value,
// ivyReport := { Def.task { ivyReportFunction.value.apply(config.toString) } dependsOn (ignoreMissingUpdate) }.value,
crossProjectId := sbt.CrossVersion(
scalaVersion.value,
scalaBinaryVersion.value)(projectID.value),
@ -58,9 +66,10 @@ object DependencyGraphSettings {
val root = crossProjectId.value
val config = configuration.value
update.configuration(config.name).map(report
update.configuration(convertConfig(config)).map(report
SbtUpdateReport.fromConfigurationReport(report, root)).getOrElse(ModuleGraph.empty)
},
moduleGraphIvyReport := {
IvyReport.fromReportFile(absoluteReportPath(ivyReport.value))
},
@ -216,7 +225,7 @@ object DependencyGraphSettings {
type HasModule = {
val module: ModuleID
}
def crossName(ivyModule: IvySbt#Module) =
def crossName(ivyModule: ModuleDescriptor) =
ivyModule.moduleSettings match {
case ic: InlineConfiguration ic.module.name
case hm: HasModule if hm.getClass.getName == "sbt.InlineConfigurationWithExcludes" hm.module.name
@ -231,47 +240,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(
cacheFile = s.cacheDirectory,
label = show,
module = ivyModule.value,
config = (updateConfiguration in ignoreMissingUpdate).value,
transform = transform,
skip = (skip in update).value,
force = isRoot,
depsUpdated = depsUpdated,
log = s.log)
}.value
}

View File

@ -63,12 +63,4 @@ case class ModuleGraph(nodes: Seq[Module], edges: Seq[Edge]) {
def roots: Seq[Module] =
nodes.filter(n !edges.exists(_._2 == n.id)).sortBy(_.id.idString)
}
import sbinary.{ Format, DefaultProtocol }
object ModuleGraphProtocol extends DefaultProtocol {
implicit def seqFormat[T: Format]: Format[Seq[T]] = wrap[Seq[T], List[T]](_.toList, _.toSeq)
implicit val ModuleIdFormat: Format[ModuleId] = asProduct3(ModuleId)(ModuleId.unapply(_).get)
implicit val ModuleFormat: Format[Module] = asProduct6(Module)(Module.unapply(_).get)
implicit val ModuleGraphFormat: Format[ModuleGraph] = asProduct2(ModuleGraph.apply _)(ModuleGraph.unapply(_).get)
}
}

View File

@ -17,11 +17,12 @@
package net.virtualvoid.sbt.graph
package rendering
import com.github.mdr.ascii.layout._
import com.github.mdr.ascii.graph.Graph
import com.github.mdr.ascii.layout.GraphLayout
object AsciiGraph {
def asciiGraph(graph: ModuleGraph): String =
Layouter.renderGraph(buildAsciiGraph(graph))
GraphLayout.renderGraph(buildAsciiGraph(graph))
private def buildAsciiGraph(moduleGraph: ModuleGraph): Graph[String] = {
def renderVertex(module: Module): String =
@ -31,7 +32,7 @@ object AsciiGraph {
module.error.map("\nerror: " + _).getOrElse("") +
module.evictedByVersion.map(_ formatted "\nevicted by: %s").getOrElse("")
val vertices = moduleGraph.nodes.map(renderVertex).toList
val vertices = moduleGraph.nodes.map(renderVertex).toSet
val edges = moduleGraph.edges.toList.map { case (from, to) (renderVertex(moduleGraph.module(from)), renderVertex(moduleGraph.module(to))) }
Graph(vertices, edges)
}

View File

@ -20,5 +20,5 @@ package sbt
object SbtAccess {
val unmanagedScalaInstanceOnly = Defaults.unmanagedScalaInstanceOnly
def getTerminalWidth: Int = JLine.usingTerminal(_.getWidth)
def getTerminalWidth: Int = internal.util.JLine.usingTerminal(_.getWidth)
}

View File

@ -1,7 +1,6 @@
scalaVersion := "2.9.2"
scalaVersion := "2.12.3"
libraryDependencies +=
"at.blub" % "blib" % "1.2.3" % "test"
libraryDependencies += "at.blub" % "blib" % "1.2.3" % Test
TaskKey[Unit]("check") := {
val report = (ivyReport in Test).value