Skip to content

Commit

Permalink
Merge pull request #29 from sbt/wip/sandwich
Browse files Browse the repository at this point in the history
implement secondary match
  • Loading branch information
eed3si9n authored Aug 23, 2020
2 parents 5dfbcfb + ba8d3c7 commit f8973ae
Show file tree
Hide file tree
Showing 12 changed files with 183 additions and 11 deletions.
52 changes: 43 additions & 9 deletions src/main/scala/sbt/VirtualAxis.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,50 @@ object VirtualAxis {
abstract class StrongAxis extends VirtualAxis


def isMatch(lhs: Seq[VirtualAxis], rhs: Seq[VirtualAxis]): Boolean = {
def isCompatible(v: VirtualAxis, stack: Seq[VirtualAxis]): Boolean =
v match {
case v: WeakAxis =>
val clazz = v.getClass
stack.contains(v) || !stack.exists(_.getClass == clazz)
case v: StrongAxis =>
stack.contains(v)
def isMatch(lhs: Seq[VirtualAxis], rhs: Seq[VirtualAxis]): Boolean =
lhs.forall(isStronglyCompatible(_, rhs)) && rhs.forall(isStronglyCompatible(_, lhs))

private[sbt] def isStronglyCompatible(v: VirtualAxis, stack: Seq[VirtualAxis]): Boolean =
v match {
case v: WeakAxis =>
val clazz = v.getClass
stack.contains(v) || !stack.exists(_.getClass == clazz)
case v: StrongAxis =>
stack.contains(v)
}

def isSecondaryMatch(lhs: Seq[VirtualAxis], rhs: Seq[VirtualAxis]): Boolean =
lhs.forall(isSecondaryCompatible(_, rhs)) && rhs.forall(isSecondaryCompatible(_, lhs))

def isSecondaryCompatible(v: VirtualAxis, stack: Seq[VirtualAxis]): Boolean =
v match {
case v: ScalaVersionAxis =>
val thatSVOpt = (stack collect {
case x: ScalaVersionAxis => x
}).headOption
thatSVOpt match {
case Some(ScalaVersionAxis(sv, _)) =>
(v.scalaVersion == sv) ||
isScala2Scala3Sandwich(partialVersion(v.scalaVersion), partialVersion(sv))
case _ => true
}
case _ =>
isStronglyCompatible(v, stack)
}

private[sbt] def isScala2Scala3Sandwich(sbv1: Option[(Long, Long)], sbv2: Option[(Long, Long)]): Boolean = {
def str(x: Option[(Long, Long)]): String =
x match {
case Some((a, b)) => s"$a.$b"
case _ => "0.0"
}
lhs.forall(isCompatible(_, rhs)) && rhs.forall(isCompatible(_, lhs))
isScala2Scala3Sandwich(str(sbv1), str(sbv2))
}

private[sbt] def isScala2Scala3Sandwich(sbv1: String, sbv2: String): Boolean = {
def compare(a: String, b: String): Boolean =
a == "2.13" && (b.startsWith("0.") || b.startsWith("3.0"))
compare(sbv1, sbv2) || compare(sbv2, sbv1)
}

case class ScalaVersionAxis(scalaVersion: String, value: String) extends WeakAxis {
Expand Down
46 changes: 44 additions & 2 deletions src/main/scala/sbt/internal/ProjectMatrix.scala
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ object ProjectMatrix {
def isMatch(that: ProjectRow): Boolean =
VirtualAxis.isMatch(this.axisValues, that.axisValues)

def isSecondaryMatch(that: ProjectRow): Boolean =
VirtualAxis.isSecondaryMatch(this.axisValues, that.axisValues)

override def toString: String = s"ProjectRow($autoScalaLibrary, $axisValues)"
}

Expand Down Expand Up @@ -246,7 +249,8 @@ object ProjectMatrix {
crossTarget := Keys.target.value,
sourceDirectory := base.getAbsoluteFile / "src",
inConfig(Compile)(makeSources(nonScalaDirSuffix, svDirSuffix)),
inConfig(Test)(makeSources(nonScalaDirSuffix, svDirSuffix))
inConfig(Test)(makeSources(nonScalaDirSuffix, svDirSuffix)),
projectDependencies := projectDependenciesTask.value,
)
.settings(self.settings)
.configure(transforms: _*)
Expand All @@ -255,6 +259,43 @@ object ProjectMatrix {
}): _*)
}

// backport of https://github.com/sbt/sbt/pull/5767
def projectDependenciesTask: Def.Initialize[Task[Seq[ModuleID]]] =
Def.task {
val orig = projectDependencies.value
val sbv = scalaBinaryVersion.value
val ref = thisProjectRef.value
val data = settingsData.value
val deps = buildDependencies.value
val sbtV = VersionNumber(sbtVersion.value)

if (sbtV._1.getOrElse(0L) == 1 && (sbtV._2.getOrElse(0L) < 4)) {
deps.classpath(ref) flatMap { dep =>
val depProjIdOpt = (dep.project / projectID).get(data)
val depSVOpt = (dep.project / scalaVersion).get(data)
val depSBVOpt = (dep.project / scalaBinaryVersion).get(data)
val depCrossOpt = (dep.project / crossVersion).get(data)
(depProjIdOpt, depSVOpt, depSBVOpt, depCrossOpt) match {
case (Some(depProjId), Some(depSV), Some(depSBV), Some(depCross)) =>
if (sbv == depSBV || depCross != CrossVersion.binary)
Some(
depProjId.withConfigurations(dep.configuration).withExplicitArtifacts(Vector.empty)
)
else if (VirtualAxis.isScala2Scala3Sandwich(sbv, depSBV) && depCross == CrossVersion.binary)
Some(
depProjId
.withCrossVersion(CrossVersion.constant(depSBV))
.withConfigurations(dep.configuration)
.withExplicitArtifacts(Vector.empty)
)
else sys.error(s"scalaBinaryVersion mismatch: expected $sbv but found ${depSBV}")
case _ => None
}
}
} else {
orig
}
}

override lazy val componentProjects: Seq[Project] = resolvedMappings.values.toList

Expand All @@ -275,7 +316,8 @@ object ProjectMatrix {

// resolve to the closest match for the given row
private[sbt] def resolveMatch(thatRow: ProjectRow): ProjectReference =
rows.find(r => r.isMatch(thatRow)) match {
(rows.find(r => r.isMatch(thatRow)) orElse
rows.find(r => r.isSecondaryMatch(thatRow))) match {
case Some(r) => LocalProject(resolveProjectIds(r))
case _ => sys.error(s"no rows were found in $id matching $thatRow: $rows")
}
Expand Down
5 changes: 5 additions & 0 deletions src/sbt-test/projectMatrix/jvm-sandwich/bar-app/D.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package example

object D {
val x = C.x
}
5 changes: 5 additions & 0 deletions src/sbt-test/projectMatrix/jvm-sandwich/bar-core/C.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package example

object C {
val x = 1
}
5 changes: 5 additions & 0 deletions src/sbt-test/projectMatrix/jvm-sandwich/baz-app/F.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package example

object F {
val x = E.x
}
5 changes: 5 additions & 0 deletions src/sbt-test/projectMatrix/jvm-sandwich/baz-core/E.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package example

object E {
val x = 1
}
54 changes: 54 additions & 0 deletions src/sbt-test/projectMatrix/jvm-sandwich/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
lazy val check = taskKey[Unit]("")

val dottyVersion = "0.23.0"
ThisBuild / resolvers += "scala-integration" at "https://scala-ci.typesafe.com/artifactory/scala-integration/"
// TODO use 2.13.4 when it's out
lazy val scala213 = "2.13.4-bin-aeee8f0"

lazy val fooApp = (projectMatrix in file("foo-app"))
.dependsOn(fooCore)
.settings(
name := "foo app",
)
.jvmPlatform(scalaVersions = Seq(dottyVersion))

lazy val fooCore = (projectMatrix in file("foo-core"))
.settings(
name := "foo core",
)
.jvmPlatform(scalaVersions = Seq(scala213, "2.12.12"))

lazy val barApp = (projectMatrix in file("bar-app"))
.dependsOn(barCore)
.settings(
name := "bar app",
)
.jvmPlatform(scalaVersions = Seq(scala213))

lazy val barCore = (projectMatrix in file("bar-core"))
.settings(
name := "bar core",
)
.jvmPlatform(scalaVersions = Seq(dottyVersion))

// choose 2.13 when bazCore offers both 2.13 and Dotty
lazy val bazApp = (projectMatrix in file("baz-app"))
.dependsOn(bazCore)
.settings(
name := "baz app",
check := {
val cp = (Compile / fullClasspath).value
.map(_.data.getName)

assert(cp.contains("baz-core_2.13-0.1.0-SNAPSHOT.jar"), s"$cp")
assert(!cp.contains("baz-core_0.23-0.1.0-SNAPSHOT.jar"), s"$cp")
},
)
.jvmPlatform(scalaVersions = Seq(scala213))

lazy val bazCore = (projectMatrix in file("baz-core"))
.settings(
name := "baz core",
exportJars := true,
)
.jvmPlatform(scalaVersions = Seq(scala213, dottyVersion))
5 changes: 5 additions & 0 deletions src/sbt-test/projectMatrix/jvm-sandwich/foo-app/B.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package example

object B {
val x = A.x
}
5 changes: 5 additions & 0 deletions src/sbt-test/projectMatrix/jvm-sandwich/foo-core/A.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package example

object A {
val x = 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.3.13
6 changes: 6 additions & 0 deletions src/sbt-test/projectMatrix/jvm-sandwich/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
sys.props.get("plugin.version") match {
case Some(x) => addSbtPlugin("com.eed3si9n" % "sbt-projectmatrix" % x)
case _ => sys.error("""|The system property 'plugin.version' is not defined.
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
}
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.4.1")
5 changes: 5 additions & 0 deletions src/sbt-test/projectMatrix/jvm-sandwich/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
> fooAppJVM0_23/compile

> barAppJVM2_13/compile

> bazAppJVM2_13/check

0 comments on commit f8973ae

Please sign in to comment.