diff --git a/src/main/scala/ch/epfl/scala/GithubDependencyGraphPlugin.scala b/src/main/scala/ch/epfl/scala/GithubDependencyGraphPlugin.scala index 2233c36..cb9f355 100644 --- a/src/main/scala/ch/epfl/scala/GithubDependencyGraphPlugin.scala +++ b/src/main/scala/ch/epfl/scala/GithubDependencyGraphPlugin.scala @@ -6,7 +6,9 @@ import scala.util.Properties import ch.epfl.scala.githubapi._ import sbt.Scoped.richTaskSeq import sbt._ -import sbt.plugins.IvyPlugin +import sbt.internal.util.complete.Parser +import sbt.internal.util.complete.Parsers +import sbt.plugins.JvmPlugin import sjsonnew.shaded.scalajson.ast.unsafe.JString object GithubDependencyGraphPlugin extends AutoPlugin { @@ -26,18 +28,18 @@ object GithubDependencyGraphPlugin extends AutoPlugin { val githubManifestsKey: AttributeKey[Map[String, githubapi.Manifest]] = AttributeKey("githubDependencyManifests") val githubProjectsKey: AttributeKey[Seq[ProjectRef]] = AttributeKey("githubProjectRefs") val githubDependencyManifest: TaskKey[githubapi.Manifest] = taskKey("The dependency manifest of the project") - val githubStoreDependencyManifests: TaskKey[StateTransform] = - taskKey("Store the dependency manifests of all projects in the attribute map.") + val githubStoreDependencyManifests: InputKey[StateTransform] = + inputKey("Store the dependency manifests of all projects of a Scala version in the attribute map.") .withRank(KeyRanks.DTask) } import autoImport._ override def trigger = allRequirements - override def requires: Plugins = IvyPlugin + override def requires: Plugins = JvmPlugin override def globalSettings: Seq[Setting[_]] = Def.settings( - githubStoreDependencyManifests := storeManifestsTask.value, + githubStoreDependencyManifests := storeManifestsTask.evaluated, Keys.commands ++= SubmitDependencyGraph.commands ) @@ -46,12 +48,27 @@ object GithubDependencyGraphPlugin extends AutoPlugin { githubDependencyManifest / Keys.aggregate := false ) - private def storeManifestsTask: Def.Initialize[Task[StateTransform]] = Def.taskDyn { - val projectRefs = Keys.state.value + private val scalaVersionParser = { + import Parsers._ + import Parser._ + val validOpChars = Set('.', '-', '+') + identifier( + charClass(alphanum, "alphanum"), + charClass(c => alphanum(c) || validOpChars.contains(c), "version character") + ) + } + + private def storeManifestsTask: Def.Initialize[InputTask[StateTransform]] = Def.inputTaskDyn { + val scalaVersionInput = (Parsers.Space ~> scalaVersionParser).parsed + val state = Keys.state.value + + val projectRefs = state .get(githubProjectsKey) .getOrElse( throw new MessageOnlyException(s"The ${githubProjectsKey.label} attribute is not initialized") ) + .filter(ref => state.setting(ref / Keys.scalaVersion) == scalaVersionInput) + Def.task { val manifests: Map[String, Manifest] = projectRefs .map(ref => (ref / githubDependencyManifest).?) diff --git a/src/main/scala/ch/epfl/scala/SubmitDependencyGraph.scala b/src/main/scala/ch/epfl/scala/SubmitDependencyGraph.scala index 842640d..08077d0 100644 --- a/src/main/scala/ch/epfl/scala/SubmitDependencyGraph.scala +++ b/src/main/scala/ch/epfl/scala/SubmitDependencyGraph.scala @@ -45,14 +45,14 @@ object SubmitDependencyGraph { private def submit(state: State, input: SubmitInput): State = { checkGithubEnv() // fail fast if the Github CI environment is incomplete - val projectRefs = getProjectRefs(state, input) + val projectRefs = getScalaProjectRefs(state, input) val scalaVersions = getScalaVersions(state, input, projectRefs) val initState = state .put(githubManifestsKey, Map.empty[String, Manifest]) .put(githubProjectsKey, projectRefs) val storeAllManifests = scalaVersions.flatMap { scalaVersion => - Seq(s"++$scalaVersion", githubStoreDependencyManifests.key.label) + Seq(s"++$scalaVersion", s"${githubStoreDependencyManifests.key} $scalaVersion") } val commands = storeAllManifests :+ SubmitInternal commands.toList ::: initState @@ -89,12 +89,15 @@ object SubmitDependencyGraph { } } - private def getProjectRefs(state: State, input: SubmitInput): Seq[ProjectRef] = { + // project refs that have a Scala version, filtered according to input.projects + private def getScalaProjectRefs(state: State, input: SubmitInput): Seq[ProjectRef] = { val loadedBuild = state.setting(Keys.loadedBuild) - val allProjectRefs = loadedBuild.allProjectRefs.map(_._1) + val allScalaProjectRefs = loadedBuild.allProjectRefs + .map(_._1) + .filter(ref => state.getSetting(ref / Keys.scalaVersion).isDefined) val projectFilter = input.projects.toSet - if (projectFilter.isEmpty) allProjectRefs - else allProjectRefs.filter(ref => projectFilter.contains(ref.project)) + if (projectFilter.isEmpty) allScalaProjectRefs + else allScalaProjectRefs.filter(ref => projectFilter.contains(ref.project)) } private def getScalaVersions(state: State, input: SubmitInput, projectRefs: Seq[ProjectRef]): Seq[String] = { diff --git a/src/sbt-test/dependency-graph/ci-submit/build.sbt b/src/sbt-test/dependency-graph/ci-submit/build.sbt index d07288e..84cc0d5 100644 --- a/src/sbt-test/dependency-graph/ci-submit/build.sbt +++ b/src/sbt-test/dependency-graph/ci-submit/build.sbt @@ -7,31 +7,42 @@ inThisBuild( Seq( organization := "ch.epfl.scala", version := "1.2.0-SNAPSHOT", - useCoursier := true, - scalaVersion := "2.12.15", + scalaVersion := "2.13.8" + ) +) + +val a = project + .in(file("a")) + .settings( + scalaVersion := "2.13.8", crossScalaVersions := Seq( "2.12.16", "2.13.8", "3.1.3" ) ) -) - -val a = project.in(file("a")) +// b is not cross-compiled +// but we should still be able to resolve the manifests of the build on 2.12.16 and 3.1.3 +// this pattern is taken from scalameta/metals where metals, not cross-compiled, depends on mtags +// which is cross-compiled val b = project .in(file("b")) .settings( - libraryDependencies += "org.typelevel" %% "cats-core" % "2.8.0" + scalaVersion := "2.13.8" ) + .dependsOn(a) -Global / checkManifests := { +checkManifests := { + val logger = streams.value.log val expectedSize: Int = (Space ~> NatBasic).parsed val manifests = state.value.get(githubManifestsKey).getOrElse { throw new MessageOnlyException(s"Not found ${githubManifestsKey.label} attribute") } + logger.info(s"found ${manifests.size} manifests") assert( manifests.size == expectedSize, s"expected $expectedSize manifests, found ${manifests.size}" ) } +checkManifests / aggregate := false diff --git a/src/sbt-test/dependency-graph/ci-submit/test b/src/sbt-test/dependency-graph/ci-submit/test index dfb5d04..8473687 100644 --- a/src/sbt-test/dependency-graph/ci-submit/test +++ b/src/sbt-test/dependency-graph/ci-submit/test @@ -1,6 +1,10 @@ > 'githubSubmitDependencyGraph {}' -> checkManifests 9 +> checkManifests 5 > 'githubSubmitDependencyGraph {"projects":[], "scalaVersions":["2.13.8"]}' > checkManifests 3 +> 'githubSubmitDependencyGraph {"projects":[], "scalaVersions":["2.12.16", "2.13.8"]}' +> checkManifests 4 +> 'githubSubmitDependencyGraph {"projects":["a", "b"], "scalaVersions":[]}' +> checkManifests 4 > 'githubSubmitDependencyGraph {"projects":["a"], "scalaVersions":["2.12.16", "3.1.3"]}' > checkManifests 2