diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/CoursierConfiguration.scala b/modules/lm-coursier/src/main/scala/lmcoursier/CoursierConfiguration.scala index 69a209c67..1abea41ad 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/CoursierConfiguration.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/CoursierConfiguration.scala @@ -35,7 +35,8 @@ final class CoursierConfiguration private ( val cache: Option[File], val ivyHome: Option[File], val followHttpToHttpsRedirections: Option[Boolean], - val strict: Option[Strict] + val strict: Option[Strict], + val extraProjects: Vector[Project] ) extends Serializable { private def this() = @@ -62,7 +63,8 @@ final class CoursierConfiguration private ( None, None, None, - None + None, + Vector.empty ) def this( @@ -112,7 +114,8 @@ final class CoursierConfiguration private ( cache, ivyHome, followHttpToHttpsRedirections, - None + None, + Vector.empty ) override def equals(o: Any): Boolean = @@ -140,7 +143,8 @@ final class CoursierConfiguration private ( cache == other.cache && ivyHome == other.ivyHome && followHttpToHttpsRedirections == other.followHttpToHttpsRedirections && - strict == other.strict + strict == other.strict && + extraProjects == other.extraProjects case _ => false } @@ -169,11 +173,12 @@ final class CoursierConfiguration private ( code = 37 * (code + ivyHome.##) code = 37 * (code + followHttpToHttpsRedirections.##) code = 37 * (code + strict.##) + code = 37 * (code + extraProjects.##) code } override def toString: String = - s"CoursierConfiguration($log, $resolvers, $parallelDownloads, $maxIterations, $sbtScalaOrganization, $sbtScalaVersion, $sbtScalaJars, $interProjectDependencies, $excludeDependencies, $fallbackDependencies, $autoScalaLibrary, $hasClassifiers, $classifiers, $mavenProfiles, $scalaOrganization, $scalaVersion, $authenticationByRepositoryId, $credentials, $logger, $cache, $ivyHome, $followHttpToHttpsRedirections, $strict)" + s"CoursierConfiguration($log, $resolvers, $parallelDownloads, $maxIterations, $sbtScalaOrganization, $sbtScalaVersion, $sbtScalaJars, $interProjectDependencies, $excludeDependencies, $fallbackDependencies, $autoScalaLibrary, $hasClassifiers, $classifiers, $mavenProfiles, $scalaOrganization, $scalaVersion, $authenticationByRepositoryId, $credentials, $logger, $cache, $ivyHome, $followHttpToHttpsRedirections, $strict, $extraProjects)" private[this] def copy( log: Option[Logger] = log, @@ -198,7 +203,8 @@ final class CoursierConfiguration private ( cache: Option[File] = cache, ivyHome: Option[File] = ivyHome, followHttpToHttpsRedirections: Option[Boolean] = followHttpToHttpsRedirections, - strict: Option[Strict] = strict + strict: Option[Strict] = strict, + extraProjects: Vector[Project] = extraProjects ): CoursierConfiguration = new CoursierConfiguration( log, @@ -223,7 +229,8 @@ final class CoursierConfiguration private ( cache, ivyHome, followHttpToHttpsRedirections, - strict + strict, + extraProjects ) def withLog(log: Option[Logger]): CoursierConfiguration = @@ -323,6 +330,9 @@ final class CoursierConfiguration private ( copy(strict = Some(strict)) def withStrict(strictOpt: Option[Strict]): CoursierConfiguration = copy(strict = strictOpt) + + def withExtraProjects(extraProjects: Vector[Project]): CoursierConfiguration = + copy(extraProjects = extraProjects) } object CoursierConfiguration { @@ -375,7 +385,8 @@ object CoursierConfiguration { cache, None, None, - None + None, + Vector.empty ) def apply( @@ -423,7 +434,8 @@ object CoursierConfiguration { Option(cache), None, None, - None + None, + Vector.empty ) def apply( @@ -472,6 +484,7 @@ object CoursierConfiguration { cache, ivyHome, None, - None + None, + Vector.empty ) } diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala b/modules/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala index 69c440b20..d3e38b4f7 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala @@ -65,6 +65,21 @@ class CoursierDependencyResolution(conf: CoursierConfiguration) extends Dependen sv.split('.').take(2).mkString(".") } + val interProjectDependencies = { + val (mod, ver) = FromSbt.moduleVersion(module0.module, sv, sbv, optionalCrossVer = true) + + val needed = conf.interProjectDependencies.exists { p => + p.module == mod && p.version == ver + } + + if (needed) + conf.interProjectDependencies.map(ToCoursier.project) + else + Vector.empty[coursier.core.Project] + } + + val extraProjects = conf.extraProjects.map(ToCoursier.project) + val verbosityLevel = 0 val ttl = CacheDefaults.ttl @@ -95,7 +110,8 @@ class CoursierDependencyResolution(conf: CoursierConfiguration) extends Dependen ) } - val interProjectRepo = InterProjectRepository(conf.interProjectDependencies.map(ToCoursier.project)) + val interProjectRepo = InterProjectRepository(interProjectDependencies) + val extraProjectsRepo = InterProjectRepository(extraProjects) val dependencies = module0 .dependencies @@ -131,8 +147,8 @@ class CoursierDependencyResolution(conf: CoursierConfiguration) extends Dependen autoScalaLibOpt = if (conf.autoScalaLibrary) Some((so, sv)) else None, mainRepositories = mainRepositories, parentProjectCache = Map.empty, - interProjectDependencies = conf.interProjectDependencies.map(ToCoursier.project), - internalRepositories = Seq(interProjectRepo), + interProjectDependencies = interProjectDependencies, + internalRepositories = Seq(interProjectRepo, extraProjectsRepo), sbtClassifiers = false, projectName = projectName, loggerOpt = loggerOpt, diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/FromSbt.scala b/modules/lm-coursier/src/main/scala/lmcoursier/FromSbt.scala index 0fee39809..088666e65 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/FromSbt.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/FromSbt.scala @@ -34,7 +34,7 @@ object FromSbt { !k.startsWith(SbtPomExtraProperties.POM_INFO_KEY_PREFIX) } - private def moduleVersion( + def moduleVersion( module: ModuleID, scalaVersion: String, scalaBinaryVersion: String, diff --git a/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/InputsTasks.scala b/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/InputsTasks.scala index dc77eeb01..376380999 100644 --- a/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/InputsTasks.scala +++ b/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/InputsTasks.scala @@ -147,10 +147,10 @@ object InputsTasks { val projectRefs = Structure.allRecursiveInterDependencies(state, projectRef) - val t = coursierProject.forAllProjectsOpt(state, projectRefs) + val t = coursierProject.forAllProjectsOpt(state, projectRefs :+ projectRef) Def.task { - val projects = t.value.toVector.flatMap { + t.value.toVector.flatMap { case (ref, None) => if (ref.build != projectRef.build) state.log.warn(s"Cannot get coursier info for project under ${ref.build}, is sbt-coursier also added to it?") @@ -158,44 +158,47 @@ object InputsTasks { case (_, Some(p)) => Seq(p) } - val projectModules = projects.map(_.module).toSet - - // this includes org.scala-sbt:global-plugins referenced from meta-builds in particular - val extraProjects = sbt.Keys.projectDescriptors.value - .map { - case (k, v) => - moduleFromIvy(k) -> v - } - .filter { - case (module, _) => - !projectModules(module) - } - .toVector - .map { - case (module, v) => - val configurations = v - .getConfigurations - .map { c => - Configuration(c.getName) -> c.getExtends.map(Configuration(_)).toSeq - } - .toMap - val deps = v.getDependencies.flatMap(dependencyFromIvy) - Project( - module, - v.getModuleRevisionId.getRevision, - deps, - configurations, - Nil, - None, - Nil, - Info("", "", Nil, Nil, None) - ) - } - - projects ++ extraProjects } } + private[sbtcoursiershared] def coursierExtraProjectsTask: Def.Initialize[sbt.Task[Seq[Project]]] = + Def.task { + val projects = coursierInterProjectDependencies.value + val projectModules = projects.map(_.module).toSet + + // this includes org.scala-sbt:global-plugins referenced from meta-builds in particular + sbt.Keys.projectDescriptors.value + .map { + case (k, v) => + moduleFromIvy(k) -> v + } + .filter { + case (module, _) => + !projectModules(module) + } + .toVector + .map { + case (module, v) => + val configurations = v + .getConfigurations + .map { c => + Configuration(c.getName) -> c.getExtends.map(Configuration(_)).toSeq + } + .toMap + val deps = v.getDependencies.flatMap(dependencyFromIvy) + Project( + module, + v.getModuleRevisionId.getRevision, + deps, + configurations, + Nil, + None, + Nil, + Info("", "", Nil, Nil, None) + ) + } + } + private[sbtcoursiershared] def coursierFallbackDependenciesTask: Def.Initialize[sbt.Task[Seq[FallbackDependency]]] = Def.taskDyn { diff --git a/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/SbtCoursierShared.scala b/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/SbtCoursierShared.scala index e273af4d3..be2de497a 100644 --- a/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/SbtCoursierShared.scala +++ b/modules/sbt-coursier-shared/src/main/scala/coursier/sbtcoursiershared/SbtCoursierShared.scala @@ -21,6 +21,7 @@ object SbtCoursierShared extends AutoPlugin { val coursierGenerateIvyXml = settingKey[Boolean]("") val coursierProject = TaskKey[Project]("coursier-project") val coursierInterProjectDependencies = TaskKey[Seq[Project]]("coursier-inter-project-dependencies", "Projects the current project depends on, possibly transitively") + val coursierExtraProjects = TaskKey[Seq[Project]]("coursier-extra-projects", "") val coursierPublications = TaskKey[Seq[(Configuration, Publication)]]("coursier-publications") val coursierKeepPreloaded = settingKey[Boolean]("Whether to take into account sbt preloaded repositories or not") @@ -79,7 +80,8 @@ object SbtCoursierShared extends AutoPlugin { }, coursierGenerateIvyXml := true, coursierProject := InputsTasks.coursierProjectTask.value, - coursierInterProjectDependencies := InputsTasks.coursierInterProjectDependenciesTask.value + coursierInterProjectDependencies := InputsTasks.coursierInterProjectDependenciesTask.value, + coursierExtraProjects := InputsTasks.coursierExtraProjectsTask.value ) ++ { if (pubSettings) Seq( diff --git a/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/ResolutionTasks.scala b/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/ResolutionTasks.scala index c0c021352..013e8ee60 100644 --- a/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/ResolutionTasks.scala +++ b/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/ResolutionTasks.scala @@ -56,6 +56,7 @@ object ResolutionTasks { val sbv = scalaBinaryVersion.value val interProjectDependencies = coursierInterProjectDependencies.value.map(ToCoursier.project) + val extraProjects = coursierExtraProjects.value.map(ToCoursier.project) val parallelDownloads = coursierParallelDownloads.value val checksums = coursierChecksums.value @@ -86,6 +87,7 @@ object ResolutionTasks { val typelevel = Organization(scalaOrganization.value) == Typelevel.typelevelOrg val interProjectRepo = InterProjectRepository(interProjectDependencies) + val extraProjectsRepo = InterProjectRepository(extraProjects) val ivyProperties = ResolutionParams.defaultIvyProperties(ivyPaths.value.ivyHome) @@ -131,7 +133,7 @@ object ResolutionTasks { mainRepositories = mainRepositories, parentProjectCache = parentProjectCache, interProjectDependencies = interProjectDependencies, - internalRepositories = Seq(interProjectRepo), + internalRepositories = Seq(interProjectRepo, extraProjectsRepo), sbtClassifiers = sbtClassifiers, projectName = projectName, loggerOpt = createLogger, diff --git a/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/LICENSE b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/LICENSE new file mode 100644 index 000000000..728844ee3 --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2015 The dotty-example-project contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/README.md b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/README.md new file mode 100644 index 000000000..e476c5c1d --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/README.md @@ -0,0 +1 @@ +Cut-n-pasted from https://github.com/lampepfl/dotty-example-project/tree/a753b14e281bbaa6c69f26298913ad6feba969c7 diff --git a/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/build.sbt b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/build.sbt new file mode 100644 index 000000000..817bf2f68 --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/build.sbt @@ -0,0 +1,24 @@ +scalaVersion.in(ThisBuild) := "0.16.0-RC3" + +organization.in(ThisBuild) := "ch.epfl.lamp" +version.in(ThisBuild) := "0.16.0-bin-SNAPSHOT" + +// same projects (same module / versions) as the dotty-build +// these shouldn't make the internal dependency resolutions of sbt-dotty crash +lazy val `dotty-compiler` = project +lazy val `dotty-doc` = project +lazy val `dotty-interfaces` = project +lazy val `dotty-library` = project +lazy val `dotty-sbt-bridge` = project +lazy val `dotty` = project + +lazy val foo = project + .in(file(".")) + .dependsOn( + `dotty-compiler`, + `dotty-doc`, + `dotty-interfaces`, + `dotty-library`, + `dotty-sbt-bridge`, + `dotty` + ) diff --git a/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/project/build.properties b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/project/build.properties new file mode 100644 index 000000000..16dc090c5 --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/project/build.properties @@ -0,0 +1,3 @@ +# sbt-coursier scripted tests: required, as we default to sbt 1.0.3, +# but sbt-dotty requires sbt >= 1.2.7 +sbt.version=1.2.7 diff --git a/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/project/plugins.sbt b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/project/plugins.sbt new file mode 100644 index 000000000..7b0d11a1f --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/project/plugins.sbt @@ -0,0 +1,2 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.3.3") +addSbtCoursier diff --git a/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/project/project/plugins.sbt b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/project/project/plugins.sbt new file mode 100644 index 000000000..71a44ffd3 --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/project/project/plugins.sbt @@ -0,0 +1,13 @@ +addSbtPlugin { + + val name = sys.props.getOrElse( + "plugin.name", + sys.error("plugin.name Java property not set") + ) + val version = sys.props.getOrElse( + "plugin.version", + sys.error("plugin.version Java property not set") + ) + + "io.get-coursier" % name % version +} \ No newline at end of file diff --git a/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/src/main/scala/Main.scala b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/src/main/scala/Main.scala new file mode 100644 index 000000000..8a44ae4ef --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/src/main/scala/Main.scala @@ -0,0 +1,16 @@ + +object Main { + + def main(args: Array[String]): Unit = { + + runExample("Trait Params")(TraitParams.test) + + } + + private def runExample(name: String)(f: => Unit) = { + println(Console.MAGENTA + s"$name example:" + Console.RESET) + f + println() + } + +} diff --git a/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/src/main/scala/TraitParams.scala b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/src/main/scala/TraitParams.scala new file mode 100644 index 000000000..5d4409971 --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/src/main/scala/TraitParams.scala @@ -0,0 +1,21 @@ +/** + * Trait Parameters: https://dotty.epfl.ch/docs/reference/other-new-features/trait-parameters.html + */ +object TraitParams { + + trait Base(val msg: String) + class A extends Base("Hello") + class B extends Base("Dotty!") + + // Union types only exist in Dotty, so there's no chance that this will accidentally be compiled with Scala 2 + private def printMessages(msgs: (A | B)*) = println(msgs.map(_.msg).mkString(" ")) + + def test: Unit = { + + printMessages(new A, new B) + + // Sanity check the classpath: this won't run if the dotty jar is not present. + val x: Int => Int = z => z + x(1) + } +} diff --git a/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/test b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/test new file mode 100644 index 000000000..3a957361c --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/shared-1/dotty-scala-instance/test @@ -0,0 +1 @@ +> foo/scalaInstance diff --git a/modules/sbt-lm-coursier/src/main/scala/coursier/sbtlmcoursier/LmCoursierPlugin.scala b/modules/sbt-lm-coursier/src/main/scala/coursier/sbtlmcoursier/LmCoursierPlugin.scala index 87dc2f5e0..ee60cecaa 100644 --- a/modules/sbt-lm-coursier/src/main/scala/coursier/sbtlmcoursier/LmCoursierPlugin.scala +++ b/modules/sbt-lm-coursier/src/main/scala/coursier/sbtlmcoursier/LmCoursierPlugin.scala @@ -69,6 +69,11 @@ object LmCoursierPlugin extends AutoPlugin { coursierSbtResolvers else coursierRecursiveResolvers + val interProjectDependenciesTask: sbt.Def.Initialize[sbt.Task[Seq[lmcoursier.definitions.Project]]] = + if (sbtClassifiers) + Def.task(Seq.empty[lmcoursier.definitions.Project]) + else + Def.task(coursierInterProjectDependencies.value) val classifiersTask: sbt.Def.Initialize[sbt.Task[Option[Seq[String]]]] = if (withClassifiers && !sbtClassifiers) Def.task(Some(sbt.Keys.transitiveClassifiers.value)) @@ -78,7 +83,8 @@ object LmCoursierPlugin extends AutoPlugin { val rs = resolversTask.value val scalaOrg = scalaOrganization.value val scalaVer = scalaVersion.value - val interProjectDependencies = coursierInterProjectDependencies.value + val interProjectDependencies = interProjectDependenciesTask.value + val extraProjects = coursierExtraProjects.value val excludeDeps = Inputs.exclusions( InputsTasks.actualExcludeDependencies.value, scalaVer, @@ -110,6 +116,7 @@ object LmCoursierPlugin extends AutoPlugin { CoursierConfiguration() .withResolvers(rs.toVector) .withInterProjectDependencies(interProjectDependencies.toVector) + .withExtraProjects(extraProjects.toVector) .withFallbackDependencies(fallbackDeps.toVector) .withExcludeDependencies( excludeDeps