diff --git a/build.sbt b/build.sbt
index f517ad661..2bec08fac 100644
--- a/build.sbt
+++ b/build.sbt
@@ -594,7 +594,7 @@ lazy val mainProj = (project in file("main"))
scalaXml.value ++
Seq(launcherInterface) ++
log4jDependencies ++
- Seq(scalaCacheCaffeine, lmCousier)
+ Seq(scalaCacheCaffeine, lmCoursierShaded)
},
Compile / scalacOptions -= "-Xfatal-warnings",
managedSourceDirectories in Compile +=
diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala
index ceb89bff2..4e0a41e65 100755
--- a/main/src/main/scala/sbt/Defaults.scala
+++ b/main/src/main/scala/sbt/Defaults.scala
@@ -12,7 +12,7 @@ import java.net.{ URI, URL, URLClassLoader }
import java.util.Optional
import java.util.concurrent.{ Callable, TimeUnit }
-import coursier.core.{ Configuration => CConfiguration }
+import lmcoursier.definitions.{ Configuration => CConfiguration }
import org.apache.ivy.core.module.descriptor.ModuleDescriptor
import org.apache.ivy.core.module.id.ModuleRevisionId
import sbt.Def.{ Initialize, ScopedKey, Setting, SettingsDefinition }
@@ -230,7 +230,7 @@ object Defaults extends BuildCommon {
// coursier settings
csrExtraCredentials :== Nil,
csrLogger :== None,
- csrCachePath :== coursier.cache.CacheDefaults.location,
+ csrCachePath :== LMCoursier.defaultCacheLocation,
csrMavenProfiles :== Set.empty,
)
@@ -2136,7 +2136,7 @@ object Classpaths {
val old = csrCachePath.value
val ip = ivyPaths.value
val defaultIvyCache = bootIvyHome(appConfiguration.value)
- if (old != coursier.cache.CacheDefaults.location) old
+ if (old != LMCoursier.defaultCacheLocation) old
else if (ip.ivyHome == defaultIvyCache) old
else
ip.ivyHome match {
@@ -2406,13 +2406,13 @@ object Classpaths {
} tag (Tags.Update, Tags.Network)).value,
)
) ++ Seq(
- csrProject := LMCoursier.coursierProjectTask.value,
+ csrProject := CoursierInputsTasks.coursierProjectTask.value,
csrConfiguration := LMCoursier.coursierConfigurationTask(false, false).value,
- csrResolvers := LMCoursier.coursierResolversTask.value,
- csrRecursiveResolvers := LMCoursier.coursierRecursiveResolversTask.value,
+ csrResolvers := CoursierRepositoriesTasks.coursierResolversTask.value,
+ csrRecursiveResolvers := CoursierRepositoriesTasks.coursierRecursiveResolversTask.value,
csrSbtResolvers := LMCoursier.coursierSbtResolversTask.value,
- csrInterProjectDependencies := LMCoursier.coursierInterProjectDependenciesTask.value,
- csrFallbackDependencies := LMCoursier.coursierFallbackDependenciesTask.value,
+ csrInterProjectDependencies := CoursierInputsTasks.coursierInterProjectDependenciesTask.value,
+ csrFallbackDependencies := CoursierInputsTasks.coursierFallbackDependenciesTask.value,
) ++
IvyXml.generateIvyXmlSettings() ++
LMCoursier.publicationsSetting(Seq(Compile, Test).map(c => c -> CConfiguration(c.name)))
diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala
index 7464c2f0f..500e02f7c 100644
--- a/main/src/main/scala/sbt/Keys.scala
+++ b/main/src/main/scala/sbt/Keys.scala
@@ -32,8 +32,8 @@ import sbt.librarymanagement.ivy.{ Credentials, IvyConfiguration, IvyPaths, Upda
import sbt.testing.Framework
import sbt.util.{ Level, Logger }
import xsbti.compile._
-import coursier.cache.CacheLogger
-import coursier.lmcoursier.{ CoursierConfiguration, FallbackDependency }
+import lmcoursier.definitions.CacheLogger
+import lmcoursier.{ CoursierConfiguration, FallbackDependency }
import scala.concurrent.duration.{ Duration, FiniteDuration }
import scala.xml.{ NodeSeq, Node => XNode }
@@ -357,15 +357,15 @@ object Keys {
val csrCachePath = settingKey[File]("Coursier cache path").withRank(CSetting)
val csrMavenProfiles = settingKey[Set[String]]("").withRank(CSetting)
private[sbt] val csrConfiguration = taskKey[CoursierConfiguration]("General dependency management (Coursier) settings, such as the resolvers and options to use.").withRank(DTask)
- private[sbt] val csrProject = taskKey[coursier.core.Project]("")
+ private[sbt] val csrProject = taskKey[lmcoursier.definitions.Project]("")
private[sbt] val csrResolvers = taskKey[Seq[Resolver]]("")
private[sbt] val csrRecursiveResolvers = taskKey[Seq[Resolver]]("Resolvers of the current project, plus those of all from its inter-dependency projects")
private[sbt] val csrSbtResolvers = taskKey[Seq[Resolver]]("Resolvers used for sbt artifacts.")
- private[sbt] val csrInterProjectDependencies = taskKey[Seq[coursier.core.Project]]("Projects the current project depends on, possibly transitively")
+ private[sbt] val csrInterProjectDependencies = taskKey[Seq[lmcoursier.definitions.Project]]("Projects the current project depends on, possibly transitively")
private[sbt] val csrFallbackDependencies = taskKey[Seq[FallbackDependency]]("")
private[sbt] val csrLogger = taskKey[Option[CacheLogger]]("")
- private[sbt] val csrExtraCredentials = taskKey[Seq[coursier.credentials.Credentials]]("")
- private[sbt] val csrPublications = taskKey[Seq[(coursier.core.Configuration, coursier.core.Publication)]]("")
+ private[sbt] val csrExtraCredentials = taskKey[Seq[lmcoursier.credentials.Credentials]]("")
+ private[sbt] val csrPublications = taskKey[Seq[(lmcoursier.definitions.Configuration, lmcoursier.definitions.Publication)]]("")
val internalConfigurationMap = settingKey[Configuration => Configuration]("Maps configurations to the actual configuration used to define the classpath.").withRank(CSetting)
val classpathConfiguration = taskKey[Configuration]("The configuration used to define the classpath.").withRank(CTask)
diff --git a/main/src/main/scala/sbt/Project.scala b/main/src/main/scala/sbt/Project.scala
index 9a55a760a..d570c3432 100755
--- a/main/src/main/scala/sbt/Project.scala
+++ b/main/src/main/scala/sbt/Project.scala
@@ -758,6 +758,28 @@ object Project extends ProjectExtra {
def updateExtraBuilds(s: State, f: List[URI] => List[URI]): State =
setExtraBuilds(s, f(extraBuilds(s)))
+ // used by Coursier integration
+ private[sbt] def transitiveInterDependencies(
+ state: State,
+ projectRef: ProjectRef
+ ): Seq[ProjectRef] = {
+ def dependencies(map: Map[ProjectRef, Seq[ProjectRef]], id: ProjectRef): Set[ProjectRef] = {
+ def helper(map: Map[ProjectRef, Seq[ProjectRef]], acc: Set[ProjectRef]): Set[ProjectRef] =
+ if (acc.exists(map.contains)) {
+ val (kept, rem) = map.partition { case (k, _) => acc(k) }
+ helper(rem, acc ++ kept.valuesIterator.flatten)
+ } else
+ acc
+ helper(map - id, map.getOrElse(id, Nil).toSet)
+ }
+ val allProjectsDeps: Map[ProjectRef, Seq[ProjectRef]] =
+ (for {
+ (p, ref) <- Project.structure(state).allProjectPairs
+ } yield ref -> p.dependencies.map(_.project)).toMap
+ val deps = dependencies(allProjectsDeps.toMap, projectRef)
+ Project.structure(state).allProjectRefs.filter(p => deps(p))
+ }
+
object LoadAction extends Enumeration {
val Return, Current, Plugins = Value
}
diff --git a/main/src/main/scala/sbt/internal/BuildStructure.scala b/main/src/main/scala/sbt/internal/BuildStructure.scala
index a1b556fe5..309e72844 100644
--- a/main/src/main/scala/sbt/internal/BuildStructure.scala
+++ b/main/src/main/scala/sbt/internal/BuildStructure.scala
@@ -38,6 +38,12 @@ final class BuildStructure(
case (build, unit) => refs(build, unit.defined.values.toSeq)
}
def allProjectRefs(build: URI): Seq[ProjectRef] = refs(build, allProjects(build))
+ def allProjectPairs: Seq[(ResolvedProject, ProjectRef)] =
+ for {
+ (build, unit) <- units.toSeq
+ p: ResolvedProject <- unit.defined.values.toSeq
+ } yield (p, ProjectRef(build, p.id))
+
val extra: BuildUtil[ResolvedProject] = BuildUtil(root, units, index.keyIndex, data)
private[this] def refs(build: URI, projects: Seq[ResolvedProject]): Seq[ProjectRef] =
projects.map { p =>
diff --git a/main/src/main/scala/sbt/internal/LMCoursier.scala b/main/src/main/scala/sbt/internal/LMCoursier.scala
index 57c3505b4..7dec70905 100644
--- a/main/src/main/scala/sbt/internal/LMCoursier.scala
+++ b/main/src/main/scala/sbt/internal/LMCoursier.scala
@@ -8,54 +8,15 @@
package sbt
package internal
-import coursier.core.{
- Attributes => CAttributes,
- Classifier,
- Configuration => CConfiguration,
- Dependency => CDependency,
- Extension => CExtension,
- Info => CInfo,
- Module,
- ModuleName,
- Organization => COrganization,
- Project => CProject,
- Publication => CPublication,
- Type => CType
-}
-import coursier.credentials.DirectCredentials
-import coursier.lmcoursier._
-import sbt.io.IO
+import java.io.File
+import lmcoursier.definitions.{ Classifier, Configuration => CConfiguration }
+import lmcoursier._
import sbt.librarymanagement._
import Keys._
-import sbt.librarymanagement.ivy.{
- FileCredentials,
- Credentials,
- DirectCredentials => IvyDirectCredentials
-}
-import sbt.ScopeFilter.Make._
-import scala.collection.JavaConverters._
+import sbt.internal.librarymanagement.{ CoursierArtifactsTasks, CoursierInputsTasks }
private[sbt] object LMCoursier {
-
- def coursierProjectTask: Def.Initialize[sbt.Task[CProject]] =
- Def.task {
- val auOpt = apiURL.value
- val proj = Inputs.coursierProject(
- projectID.value,
- allDependencies.value,
- excludeDependencies.value,
- ivyConfigurations.value,
- scalaVersion.value,
- scalaBinaryVersion.value,
- streams.value.log
- )
- auOpt match {
- case Some(au) =>
- val props = proj.properties :+ ("info.apiURL" -> au.toString)
- proj.copy(properties = props)
- case _ => proj
- }
- }
+ def defaultCacheLocation: File = CoursierDependencyResolution.defaultCacheLocation
def coursierConfigurationTask(
withClassifiers: Boolean,
@@ -90,7 +51,7 @@ private[sbt] object LMCoursier {
_.overrideScalaVersion
)
val profiles = csrMavenProfiles.value
- val credentials = credentialsTask.value
+ val credentials = CoursierInputsTasks.credentialsTask.value
val createLogger = csrLogger.value
@@ -107,11 +68,10 @@ private[sbt] object LMCoursier {
.withInterProjectDependencies(interProjectDependencies.toVector)
.withFallbackDependencies(fallbackDeps.toVector)
.withExcludeDependencies(
- excludeDeps.toVector.sorted
- .map {
- case (o, n) =>
- (o.value, n.value)
- }
+ excludeDeps.toVector.map {
+ case (o, n) =>
+ (o.value, n.value)
+ }.sorted
)
.withAutoScalaLibrary(autoScalaLib)
.withSbtScalaJars(sbtBootJars.toVector)
@@ -129,80 +89,6 @@ private[sbt] object LMCoursier {
}
}
- val credentialsTask = Def.task {
- val log = streams.value.log
-
- val creds = sbt.Keys.credentials.value
- .flatMap {
- case dc: IvyDirectCredentials => List(dc)
- case fc: FileCredentials =>
- Credentials.loadCredentials(fc.path) match {
- case Left(err) =>
- log.warn(s"$err, ignoring it")
- Nil
- case Right(dc) => List(dc)
- }
- }
- .map { c =>
- DirectCredentials()
- .withHost(c.host)
- .withUsername(c.userName)
- .withPassword(c.passwd)
- .withRealm(Some(c.realm).filter(_.nonEmpty))
- }
- creds ++ csrExtraCredentials.value
- }
-
- def coursierRecursiveResolversTask: Def.Initialize[sbt.Task[Seq[Resolver]]] =
- Def.taskDyn {
- val state = sbt.Keys.state.value
- val projectRef = sbt.Keys.thisProjectRef.value
-
- val projects = allRecursiveInterDependencies(state, projectRef)
- Def.task {
- csrResolvers.all(ScopeFilter(inProjects(projectRef +: projects: _*))).value.flatten
- }
- }
-
- def coursierResolversTask: Def.Initialize[sbt.Task[Seq[Resolver]]] =
- Def.taskDyn {
- val bootResOpt = bootResolvers.value
- val overrideFlag = overrideBuildResolvers.value
- Def.task {
- val result0 = resultTask(bootResOpt, overrideFlag).value
- val reorderResolvers = true // coursierReorderResolvers.value
- val keepPreloaded = false // coursierKeepPreloaded.value
- val paths = ivyPaths.value
- val result1 =
- if (reorderResolvers) ResolutionParams.reorderResolvers(result0)
- else result0
- val result2 =
- paths.ivyHome match {
- case Some(ivyHome) =>
- val ivyHomeUri = IO.toURI(ivyHome).getSchemeSpecificPart
- result1 map {
- case r: FileRepository =>
- val ivyPatterns = r.patterns.ivyPatterns map {
- _.replaceAllLiterally("$" + "{ivy.home}", ivyHomeUri)
- }
- val artifactPatterns = r.patterns.artifactPatterns map {
- _.replaceAllLiterally("$" + "{ivy.home}", ivyHomeUri)
- }
- val p =
- r.patterns.withIvyPatterns(ivyPatterns).withArtifactPatterns(artifactPatterns)
- r.withPatterns(p)
- case r => r
- }
- case _ => result1
- }
- if (keepPreloaded) result2
- else
- result2.filter { r =>
- !r.name.startsWith("local-preloaded")
- }
- }
- }
-
private val pluginIvySnapshotsBase = Resolver.SbtRepositoryRoot.stripSuffix("/") + "/ivy-snapshots"
def coursierSbtResolversTask: Def.Initialize[sbt.Task[Seq[Resolver]]] = Def.task {
@@ -234,314 +120,7 @@ private[sbt] object LMCoursier {
}
}
- def coursierInterProjectDependenciesTask: Def.Initialize[sbt.Task[Seq[CProject]]] =
- Def.taskDyn {
-
- val state = sbt.Keys.state.value
- val projectRef = sbt.Keys.thisProjectRef.value
-
- val projectRefs = allRecursiveInterDependencies(state, projectRef)
-
- Def.task {
- val projects = csrProject.all(ScopeFilter(inProjects(projectRefs: _*))).value
- 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 =>
- CConfiguration(c.getName) -> c.getExtends.map(CConfiguration(_)).toSeq
- }.toMap
- val deps = v.getDependencies.flatMap(dependencyFromIvy)
- CProject(
- module,
- v.getModuleRevisionId.getRevision,
- deps,
- configurations,
- None,
- Nil,
- Nil,
- Nil,
- None,
- None,
- None,
- relocated = false,
- None,
- Nil,
- CInfo.empty
- )
- }
-
- projects ++ extraProjects
- }
- }
-
- def coursierFallbackDependenciesTask: Def.Initialize[sbt.Task[Seq[FallbackDependency]]] =
- Def.taskDyn {
- val s = state.value
- val projectRef = sbt.Keys.thisProjectRef.value
-
- val projects = allRecursiveInterDependencies(s, projectRef)
- Def.task {
- val allDeps =
- allDependencies.all(ScopeFilter(inProjects(projectRef +: projects: _*))).value.flatten
-
- FromSbt.fallbackDependencies(
- allDeps,
- scalaVersion.in(projectRef).value,
- scalaBinaryVersion.in(projectRef).value
- )
- }
- }
-
def publicationsSetting(packageConfigs: Seq[(Configuration, CConfiguration)]): Def.Setting[_] = {
- csrPublications := coursierPublicationsTask(packageConfigs: _*).value
- }
-
- def coursierPublicationsTask(
- configsMap: (Configuration, CConfiguration)*
- ): Def.Initialize[sbt.Task[Seq[(CConfiguration, CPublication)]]] =
- Def.task {
- val s = sbt.Keys.state.value
- val projectRef = sbt.Keys.thisProjectRef.value
- val projId = sbt.Keys.projectID.value
- val sv = sbt.Keys.scalaVersion.value
- val sbv = sbt.Keys.scalaBinaryVersion.value
- val ivyConfs = sbt.Keys.ivyConfigurations.value
- val extracted = Project.extract(s)
- import extracted._
-
- val sourcesConfigOpt =
- if (ivyConfigurations.value.exists(_.name == "sources"))
- Some(CConfiguration("sources"))
- else
- None
-
- val docsConfigOpt =
- if (ivyConfigurations.value.exists(_.name == "docs"))
- Some(CConfiguration("docs"))
- else
- None
-
- val sbtBinArtifacts =
- for ((config, targetConfig) <- configsMap) yield {
-
- val publish = getOpt(
- publishArtifact
- .in(projectRef)
- .in(packageBin)
- .in(config)
- ).getOrElse(false)
-
- if (publish)
- getOpt(
- artifact
- .in(projectRef)
- .in(packageBin)
- .in(config)
- ).map(targetConfig -> _)
- else
- None
- }
-
- val sbtSourceArtifacts =
- for ((config, targetConfig) <- configsMap) yield {
-
- val publish = getOpt(
- publishArtifact
- .in(projectRef)
- .in(packageSrc)
- .in(config)
- ).getOrElse(false)
-
- if (publish)
- getOpt(
- artifact
- .in(projectRef)
- .in(packageSrc)
- .in(config)
- ).map(sourcesConfigOpt.getOrElse(targetConfig) -> _)
- else
- None
- }
-
- val sbtDocArtifacts =
- for ((config, targetConfig) <- configsMap) yield {
-
- val publish =
- getOpt(
- publishArtifact
- .in(projectRef)
- .in(packageDoc)
- .in(config)
- ).getOrElse(false)
-
- if (publish)
- getOpt(
- artifact
- .in(projectRef)
- .in(packageDoc)
- .in(config)
- ).map(docsConfigOpt.getOrElse(targetConfig) -> _)
- else
- None
- }
-
- val sbtArtifacts = sbtBinArtifacts ++ sbtSourceArtifacts ++ sbtDocArtifacts
-
- def artifactPublication(artifact: Artifact) = {
-
- val name = FromSbt.sbtCrossVersionName(
- artifact.name,
- projId.crossVersion,
- sv,
- sbv
- )
-
- CPublication(
- name,
- CType(artifact.`type`),
- CExtension(artifact.extension),
- artifact.classifier.fold(Classifier.empty)(Classifier(_))
- )
- }
-
- val sbtArtifactsPublication = sbtArtifacts.collect {
- case Some((config, artifact)) =>
- config -> artifactPublication(artifact)
- }
-
- val stdArtifactsSet = sbtArtifacts.flatMap(_.map { case (_, a) => a }.toSeq).toSet
-
- // Second-way of getting artifacts from SBT
- // No obvious way of getting the corresponding publishArtifact value for the ones
- // only here, it seems.
- val extraSbtArtifacts = getOpt(
- sbt.Keys.artifacts
- .in(projectRef)
- ).getOrElse(Nil)
- .filterNot(stdArtifactsSet)
-
- // Seems that SBT does that - if an artifact has no configs,
- // it puts it in all of them. See for example what happens to
- // the standalone JAR artifact of the coursier cli module.
- def allConfigsIfEmpty(configs: Iterable[ConfigRef]): Iterable[ConfigRef] =
- if (configs.isEmpty) ivyConfs.filter(_.isPublic).map(c => ConfigRef(c.name)) else configs
-
- val extraSbtArtifactsPublication = for {
- artifact <- extraSbtArtifacts
- config <- allConfigsIfEmpty(artifact.configurations.map(x => ConfigRef(x.name)))
- // FIXME If some configurations from artifact.configurations are not public, they may leak here :\
- } yield CConfiguration(config.name) -> artifactPublication(artifact)
-
- sbtArtifactsPublication ++ extraSbtArtifactsPublication
- }
-
- private def moduleFromIvy(id: org.apache.ivy.core.module.id.ModuleRevisionId): Module =
- Module(
- COrganization(id.getOrganisation),
- ModuleName(id.getName),
- id.getExtraAttributes.asScala.map {
- case (k0, v0) => k0.asInstanceOf[String] -> v0.asInstanceOf[String]
- }.toMap
- )
-
- private def dependencyFromIvy(
- desc: org.apache.ivy.core.module.descriptor.DependencyDescriptor
- ): Seq[(CConfiguration, CDependency)] = {
-
- val id = desc.getDependencyRevisionId
- val module = moduleFromIvy(id)
- val exclusions = desc.getAllExcludeRules.map { rule =>
- // we're ignoring rule.getConfigurations and rule.getMatcher here
- val modId = rule.getId.getModuleId
- // we're ignoring modId.getAttributes here
- (COrganization(modId.getOrganisation), ModuleName(modId.getName))
- }.toSet
-
- val configurations = desc.getModuleConfigurations.toVector
- .flatMap(s => coursier.ivy.IvyXml.mappings(s))
-
- def dependency(conf: CConfiguration, attr: CAttributes) = CDependency(
- module,
- id.getRevision,
- conf,
- exclusions,
- attr,
- optional = false,
- desc.isTransitive
- )
-
- val attributes: CConfiguration => CAttributes = {
-
- val artifacts = desc.getAllDependencyArtifacts
-
- val m = artifacts.toVector.flatMap { art =>
- val attr = CAttributes(CType(art.getType), Classifier.empty)
- art.getConfigurations.map(CConfiguration(_)).toVector.map { conf =>
- conf -> attr
- }
- }.toMap
-
- c => m.getOrElse(c, CAttributes.empty)
- }
-
- configurations.map {
- case (from, to) =>
- from -> dependency(to, attributes(to))
- }
- }
-
- private def resultTask(
- bootResOpt: Option[Seq[Resolver]],
- overrideFlag: Boolean
- ): Def.Initialize[sbt.Task[Seq[Resolver]]] =
- bootResOpt.filter(_ => overrideFlag) match {
- case Some(r) => Def.task(r)
- case None =>
- Def.taskDyn {
- val extRes = externalResolvers.value
- val isSbtPlugin = sbtPlugin.value
- if (isSbtPlugin)
- Def.task {
- Seq(
- sbtResolver.value,
- Classpaths.sbtPluginReleases
- ) ++ extRes
- } else
- Def.task(extRes)
- }
- }
-
- def allRecursiveInterDependencies(state: sbt.State, projectRef: sbt.ProjectRef) = {
- def dependencies(map: Map[String, Seq[String]], id: String): Set[String] = {
-
- def helper(map: Map[String, Seq[String]], acc: Set[String]): Set[String] =
- if (acc.exists(map.contains)) {
- val (kept, rem) = map.partition { case (k, _) => acc(k) }
- helper(rem, acc ++ kept.valuesIterator.flatten)
- } else
- acc
-
- helper(map - id, map.getOrElse(id, Nil).toSet)
- }
-
- val allProjectsDeps =
- for (p <- Project.structure(state).allProjects)
- yield p.id -> p.dependencies.map(_.project.project)
-
- val deps = dependencies(allProjectsDeps.toMap, projectRef.project)
-
- Project.structure(state).allProjectRefs.filter(p => deps(p.project))
+ csrPublications := CoursierArtifactsTasks.coursierPublicationsTask(packageConfigs: _*).value
}
}
diff --git a/main/src/main/scala/sbt/internal/LibraryManagement.scala b/main/src/main/scala/sbt/internal/LibraryManagement.scala
index eaed30432..a6f12b680 100644
--- a/main/src/main/scala/sbt/internal/LibraryManagement.scala
+++ b/main/src/main/scala/sbt/internal/LibraryManagement.scala
@@ -8,7 +8,7 @@
package sbt
package internal
-import coursier.lmcoursier.CoursierDependencyResolution
+import lmcoursier.CoursierDependencyResolution
import java.io.File
import sbt.internal.librarymanagement._
import sbt.internal.util.{ ConsoleAppender, LogOption }
diff --git a/main/src/main/scala/sbt/internal/librarymanagement/CoursierArtifactsTasks.scala b/main/src/main/scala/sbt/internal/librarymanagement/CoursierArtifactsTasks.scala
new file mode 100644
index 000000000..23e64aae2
--- /dev/null
+++ b/main/src/main/scala/sbt/internal/librarymanagement/CoursierArtifactsTasks.scala
@@ -0,0 +1,157 @@
+/*
+ * sbt
+ * Copyright 2011 - 2018, Lightbend, Inc.
+ * Copyright 2008 - 2010, Mark Harrah
+ * Licensed under Apache License 2.0 (see LICENSE)
+ */
+
+package sbt
+package internal
+package librarymanagement
+
+import lmcoursier.definitions.{
+ Classifier,
+ Configuration => CConfiguration,
+ Extension => CExtension,
+ Publication => CPublication,
+ Type => CType
+}
+import sbt.librarymanagement._
+import sbt.Keys._
+
+object CoursierArtifactsTasks {
+ def coursierPublicationsTask(
+ configsMap: (sbt.librarymanagement.Configuration, CConfiguration)*
+ ): Def.Initialize[sbt.Task[Seq[(CConfiguration, CPublication)]]] =
+ Def.task {
+ val s = sbt.Keys.state.value
+ val projectRef = sbt.Keys.thisProjectRef.value
+ val projId = sbt.Keys.projectID.value
+ val sv = sbt.Keys.scalaVersion.value
+ val sbv = sbt.Keys.scalaBinaryVersion.value
+ val ivyConfs = sbt.Keys.ivyConfigurations.value
+ val extracted = Project.extract(s)
+ import extracted._
+
+ val sourcesConfigOpt =
+ if (ivyConfigurations.value.exists(_.name == "sources"))
+ Some(CConfiguration("sources"))
+ else
+ None
+
+ val docsConfigOpt =
+ if (ivyConfigurations.value.exists(_.name == "docs"))
+ Some(CConfiguration("docs"))
+ else
+ None
+
+ val sbtBinArtifacts =
+ for ((config, targetConfig) <- configsMap) yield {
+
+ val publish = getOpt(
+ publishArtifact
+ .in(projectRef)
+ .in(packageBin)
+ .in(config)
+ ).getOrElse(false)
+
+ if (publish)
+ getOpt(
+ artifact
+ .in(projectRef)
+ .in(packageBin)
+ .in(config)
+ ).map(targetConfig -> _)
+ else
+ None
+ }
+
+ val sbtSourceArtifacts =
+ for ((config, targetConfig) <- configsMap) yield {
+
+ val publish = getOpt(
+ publishArtifact
+ .in(projectRef)
+ .in(packageSrc)
+ .in(config)
+ ).getOrElse(false)
+
+ if (publish)
+ getOpt(
+ artifact
+ .in(projectRef)
+ .in(packageSrc)
+ .in(config)
+ ).map(sourcesConfigOpt.getOrElse(targetConfig) -> _)
+ else
+ None
+ }
+
+ val sbtDocArtifacts =
+ for ((config, targetConfig) <- configsMap) yield {
+
+ val publish =
+ getOpt(
+ publishArtifact
+ .in(projectRef)
+ .in(packageDoc)
+ .in(config)
+ ).getOrElse(false)
+
+ if (publish)
+ getOpt(
+ artifact
+ .in(projectRef)
+ .in(packageDoc)
+ .in(config)
+ ).map(docsConfigOpt.getOrElse(targetConfig) -> _)
+ else
+ None
+ }
+
+ val sbtArtifacts = sbtBinArtifacts ++ sbtSourceArtifacts ++ sbtDocArtifacts
+
+ def artifactPublication(artifact: Artifact) = {
+
+ val name = CrossVersion(projId.crossVersion, sv, sbv)
+ .fold(artifact.name)(_(artifact.name))
+
+ CPublication(
+ name,
+ CType(artifact.`type`),
+ CExtension(artifact.extension),
+ artifact.classifier.fold(Classifier(""))(Classifier(_))
+ )
+ }
+
+ val sbtArtifactsPublication = sbtArtifacts.collect {
+ case Some((config, artifact)) =>
+ config -> artifactPublication(artifact)
+ }
+
+ val stdArtifactsSet = sbtArtifacts.flatMap(_.map { case (_, a) => a }.toSeq).toSet
+
+ // Second-way of getting artifacts from SBT
+ // No obvious way of getting the corresponding publishArtifact value for the ones
+ // only here, it seems.
+ val extraSbtArtifacts = getOpt(
+ sbt.Keys.artifacts
+ .in(projectRef)
+ ).getOrElse(Nil)
+ .filterNot(stdArtifactsSet)
+
+ // Seems that SBT does that - if an artifact has no configs,
+ // it puts it in all of them. See for example what happens to
+ // the standalone JAR artifact of the coursier cli module.
+ def allConfigsIfEmpty(configs: Iterable[ConfigRef]): Iterable[ConfigRef] =
+ if (configs.isEmpty) ivyConfs.filter(_.isPublic).map(c => ConfigRef(c.name)) else configs
+
+ val extraSbtArtifactsPublication = for {
+ artifact <- extraSbtArtifacts
+ config <- allConfigsIfEmpty(artifact.configurations.map(x => ConfigRef(x.name)))
+ // FIXME If some configurations from artifact.configurations are not public, they may leak here :\
+ } yield CConfiguration(config.name) -> artifactPublication(artifact)
+
+ sbtArtifactsPublication ++ extraSbtArtifactsPublication
+ }
+}
diff --git a/main/src/main/scala/sbt/internal/librarymanagement/CoursierInputsTasks.scala b/main/src/main/scala/sbt/internal/librarymanagement/CoursierInputsTasks.scala
new file mode 100644
index 000000000..e50b1a874
--- /dev/null
+++ b/main/src/main/scala/sbt/internal/librarymanagement/CoursierInputsTasks.scala
@@ -0,0 +1,235 @@
+/*
+ * sbt
+ * Copyright 2011 - 2018, Lightbend, Inc.
+ * Copyright 2008 - 2010, Mark Harrah
+ * Licensed under Apache License 2.0 (see LICENSE)
+ */
+
+package sbt
+package internal
+package librarymanagement
+
+import sbt.librarymanagement._
+import sbt.util.Logger
+import sbt.Keys._
+import lmcoursier.definitions.{
+ Attributes => CAttributes,
+ Classifier,
+ Configuration => CConfiguration,
+ Dependency => CDependency,
+ // Extension => CExtension,
+ Info => CInfo,
+ Module,
+ ModuleName,
+ Organization => COrganization,
+ Project => CProject,
+ // Publication => CPublication,
+ Type => CType
+}
+import lmcoursier.credentials.DirectCredentials
+import lmcoursier.{ FallbackDependency, FromSbt, Inputs }
+import sbt.librarymanagement.ivy.{
+ FileCredentials,
+ Credentials,
+ DirectCredentials => IvyDirectCredentials
+}
+import sbt.ScopeFilter.Make._
+import scala.collection.JavaConverters._
+
+private[sbt] object CoursierInputsTasks {
+ private def coursierProject0(
+ projId: ModuleID,
+ dependencies: Seq[ModuleID],
+ excludeDeps: Seq[InclExclRule],
+ configurations: Seq[sbt.librarymanagement.Configuration],
+ sv: String,
+ sbv: String,
+ log: Logger
+ ): CProject = {
+
+ val exclusions0 = Inputs.exclusions(excludeDeps, sv, sbv, log)
+
+ val configMap = Inputs.configExtends(configurations)
+
+ val proj = FromSbt.project(
+ projId,
+ dependencies,
+ configMap,
+ sv,
+ sbv
+ )
+
+ proj.copy(
+ dependencies = proj.dependencies.map {
+ case (config, dep) =>
+ (config, dep.copy(exclusions = dep.exclusions ++ exclusions0))
+ }
+ )
+ }
+
+ private[sbt] def coursierProjectTask: Def.Initialize[sbt.Task[CProject]] =
+ Def.task {
+ val auOpt = apiURL.value
+ val proj = coursierProject0(
+ projectID.value,
+ allDependencies.value,
+ allExcludeDependencies.value,
+ // should projectID.configurations be used instead?
+ ivyConfigurations.value,
+ scalaVersion.value,
+ scalaBinaryVersion.value,
+ streams.value.log
+ )
+ auOpt match {
+ case Some(au) =>
+ val props = proj.properties :+ ("info.apiURL" -> au.toString)
+ proj.copy(properties = props)
+ case _ => proj
+ }
+ }
+
+ private def moduleFromIvy(id: org.apache.ivy.core.module.id.ModuleRevisionId): Module =
+ Module(
+ COrganization(id.getOrganisation),
+ ModuleName(id.getName),
+ id.getExtraAttributes.asScala.map {
+ case (k0, v0) => k0.asInstanceOf[String] -> v0.asInstanceOf[String]
+ }.toMap
+ )
+
+ private def dependencyFromIvy(
+ desc: org.apache.ivy.core.module.descriptor.DependencyDescriptor
+ ): Seq[(CConfiguration, CDependency)] = {
+
+ val id = desc.getDependencyRevisionId
+ val module = moduleFromIvy(id)
+ val exclusions = desc.getAllExcludeRules.map { rule =>
+ // we're ignoring rule.getConfigurations and rule.getMatcher here
+ val modId = rule.getId.getModuleId
+ // we're ignoring modId.getAttributes here
+ (COrganization(modId.getOrganisation), ModuleName(modId.getName))
+ }.toSet
+
+ val configurations = desc.getModuleConfigurations.toVector
+ .flatMap(Inputs.ivyXmlMappings)
+
+ def dependency(conf: CConfiguration, attr: CAttributes) = CDependency(
+ module,
+ id.getRevision,
+ conf,
+ exclusions,
+ attr,
+ optional = false,
+ desc.isTransitive
+ )
+
+ val attributes: CConfiguration => CAttributes = {
+
+ val artifacts = desc.getAllDependencyArtifacts
+
+ val m = artifacts.toVector.flatMap { art =>
+ val attr = CAttributes(CType(art.getType), Classifier(""))
+ art.getConfigurations.map(CConfiguration(_)).toVector.map { conf =>
+ conf -> attr
+ }
+ }.toMap
+
+ c => m.getOrElse(c, CAttributes(CType(""), Classifier("")))
+ }
+
+ configurations.map {
+ case (from, to) =>
+ from -> dependency(to, attributes(to))
+ }
+ }
+
+ private[sbt] def coursierInterProjectDependenciesTask: Def.Initialize[sbt.Task[Seq[CProject]]] =
+ Def.taskDyn {
+
+ val state = sbt.Keys.state.value
+ val projectRef = sbt.Keys.thisProjectRef.value
+
+ val projectRefs = Project.transitiveInterDependencies(state, projectRef)
+
+ Def.task {
+ val projects = csrProject.all(ScopeFilter(inProjects(projectRefs: _*))).value
+ 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 =>
+ CConfiguration(c.getName) -> c.getExtends.map(CConfiguration(_)).toSeq
+ }.toMap
+ val deps = v.getDependencies.flatMap(dependencyFromIvy)
+ CProject(
+ module,
+ v.getModuleRevisionId.getRevision,
+ deps,
+ configurations,
+ Nil,
+ None,
+ Nil,
+ CInfo("", "", Nil, Nil, None)
+ )
+ }
+
+ projects ++ extraProjects
+ }
+ }
+
+ private[sbt] def coursierFallbackDependenciesTask
+ : Def.Initialize[sbt.Task[Seq[FallbackDependency]]] =
+ Def.taskDyn {
+ val state = sbt.Keys.state.value
+ val projectRef = sbt.Keys.thisProjectRef.value
+
+ val projects = Project.transitiveInterDependencies(state, projectRef)
+
+ Def.task {
+ val allDeps =
+ allDependencies.all(ScopeFilter(inProjects(projectRef +: projects: _*))).value.flatten
+
+ FromSbt.fallbackDependencies(
+ allDeps,
+ scalaVersion.value,
+ scalaBinaryVersion.value
+ )
+ }
+ }
+
+ val credentialsTask = Def.task {
+ val log = streams.value.log
+ val creds = sbt.Keys.credentials.value
+ .flatMap {
+ case dc: IvyDirectCredentials => List(dc)
+ case fc: FileCredentials =>
+ Credentials.loadCredentials(fc.path) match {
+ case Left(err) =>
+ log.warn(s"$err, ignoring it")
+ Nil
+ case Right(dc) => List(dc)
+ }
+ }
+ .map { c =>
+ DirectCredentials()
+ .withHost(c.host)
+ .withUsername(c.userName)
+ .withPassword(c.passwd)
+ .withRealm(Some(c.realm).filter(_.nonEmpty))
+ .withHttpsOnly(false)
+ .withMatchHost(true)
+ }
+ creds ++ csrExtraCredentials.value
+ }
+}
diff --git a/main/src/main/scala/sbt/internal/librarymanagement/CoursierRepositoriesTasks.scala b/main/src/main/scala/sbt/internal/librarymanagement/CoursierRepositoriesTasks.scala
new file mode 100644
index 000000000..bccf63fe6
--- /dev/null
+++ b/main/src/main/scala/sbt/internal/librarymanagement/CoursierRepositoriesTasks.scala
@@ -0,0 +1,111 @@
+/*
+ * sbt
+ * Copyright 2011 - 2018, Lightbend, Inc.
+ * Copyright 2008 - 2010, Mark Harrah
+ * Licensed under Apache License 2.0 (see LICENSE)
+ */
+
+package sbt
+package internal
+package librarymanagement
+
+import sbt.librarymanagement._
+import sbt.Keys._
+import sbt.ScopeFilter.Make._
+
+private[sbt] object CoursierRepositoriesTasks {
+ private object CResolvers {
+ private val slowReposBase = Seq(
+ "https://repo.typesafe.com/",
+ "https://repo.scala-sbt.org/",
+ "http://repo.typesafe.com/",
+ "http://repo.scala-sbt.org/"
+ )
+
+ private val fastReposBase = Seq(
+ "http://repo1.maven.org/",
+ "https://repo1.maven.org/"
+ )
+
+ private def url(res: Resolver): Option[String] =
+ res match {
+ case m: sbt.librarymanagement.MavenRepository =>
+ Some(m.root)
+ case u: URLRepository =>
+ u.patterns.artifactPatterns.headOption
+ .orElse(u.patterns.ivyPatterns.headOption)
+ case _ =>
+ None
+ }
+
+ private def fastRepo(res: Resolver): Boolean =
+ url(res).exists(u => fastReposBase.exists(u.startsWith))
+
+ private def slowRepo(res: Resolver): Boolean =
+ url(res).exists(u => slowReposBase.exists(u.startsWith))
+
+ def reorderResolvers(resolvers: Seq[Resolver]): Seq[Resolver] =
+ if (resolvers.exists(fastRepo) && resolvers.exists(slowRepo)) {
+ val (slow, other) = resolvers.partition(slowRepo)
+ other ++ slow
+ } else
+ resolvers
+ }
+
+ private def resultTask(
+ bootResOpt: Option[Seq[Resolver]],
+ overrideFlag: Boolean
+ ): Def.Initialize[sbt.Task[Seq[Resolver]]] =
+ bootResOpt.filter(_ => overrideFlag) match {
+ case Some(r) => Def.task(r)
+ case None =>
+ Def.taskDyn {
+ val extRes = externalResolvers.value
+ val isSbtPlugin = sbtPlugin.value
+ if (isSbtPlugin)
+ Def.task {
+ Seq(
+ sbtResolver.value,
+ Classpaths.sbtPluginReleases
+ ) ++ extRes
+ } else
+ Def.task(extRes)
+ }
+ }
+
+ def coursierResolversTask: Def.Initialize[sbt.Task[Seq[Resolver]]] =
+ Def.taskDyn {
+
+ val bootResOpt = bootResolvers.value
+ val overrideFlag = overrideBuildResolvers.value
+
+ Def.task {
+ val result = resultTask(bootResOpt, overrideFlag).value
+ val reorderResolvers = true // coursierReorderResolvers.value
+ val keepPreloaded = true // coursierKeepPreloaded.value
+
+ val result0 =
+ if (reorderResolvers)
+ CResolvers.reorderResolvers(result)
+ else
+ result
+
+ if (keepPreloaded)
+ result0
+ else
+ result0.filter { r =>
+ !r.name.startsWith("local-preloaded")
+ }
+ }
+ }
+
+ def coursierRecursiveResolversTask: Def.Initialize[sbt.Task[Seq[Resolver]]] =
+ Def.taskDyn {
+ val state = sbt.Keys.state.value
+ val projectRef = sbt.Keys.thisProjectRef.value
+ val projects = Project.transitiveInterDependencies(state, projectRef)
+ Def.task {
+ csrResolvers.all(ScopeFilter(inProjects(projectRef +: projects: _*))).value.flatten
+ }
+ }
+}
diff --git a/main/src/main/scala/sbt/internal/librarymanagement/IvyXml.scala b/main/src/main/scala/sbt/internal/librarymanagement/IvyXml.scala
index 7cb58451a..966d0fb6e 100644
--- a/main/src/main/scala/sbt/internal/librarymanagement/IvyXml.scala
+++ b/main/src/main/scala/sbt/internal/librarymanagement/IvyXml.scala
@@ -12,7 +12,7 @@ package librarymanagement
import java.nio.charset.StandardCharsets.UTF_8
import java.nio.file.Files
-import coursier.core.{ Configuration, Project }
+import lmcoursier.definitions.{ Configuration, Project }
import org.apache.ivy.core.module.id.ModuleRevisionId
import Def.Setting
import sbt.Keys.{
@@ -29,7 +29,7 @@ import scala.xml.{ Node, PrefixedAttribute }
object IvyXml {
import sbt.Project._
- def rawContent(
+ private def rawContent(
currentProject: Project,
shadedConfigOpt: Option[Configuration]
): String = {
@@ -47,7 +47,7 @@ object IvyXml {
}
// These are required for publish to be fine, later on.
- def writeFiles(
+ private def writeFiles(
currentProject: Project,
shadedConfigOpt: Option[Configuration],
ivySbt: IvySbt,
@@ -77,12 +77,12 @@ object IvyXml {
()
}
- def content(project0: Project, shadedConfigOpt: Option[Configuration]): Node = {
+ private def content(project0: Project, shadedConfigOpt: Option[Configuration]): Node = {
val filterOutDependencies =
shadedConfigOpt.toSet[Configuration].flatMap { shadedConfig =>
project0.dependencies
- .collect { case (`shadedConfig`, dep) => dep }
+ .collect { case (conf, dep) if conf.value == shadedConfig.value => dep }
}
val project: Project = project0.copy(
@@ -118,8 +118,8 @@ object IvyXml {
} % infoAttrs
val confElems = project.configurations.toVector.collect {
- case (name, extends0) if !shadedConfigOpt.contains(name) =>
- val extends1 = shadedConfigOpt.fold(extends0)(c => extends0.filter(_ != c))
+ case (name, extends0) if !shadedConfigOpt.exists(_.value == name.value) =>
+ val extends1 = shadedConfigOpt.fold(extends0)(c => extends0.filter(_.value != c.value))
val n =
if (extends1.nonEmpty)
n % .attributes
@@ -138,7 +138,7 @@ object IvyXml {
configs.map(_.value).mkString(",")
} />
- if (pub.classifier.nonEmpty)
+ if (pub.classifier.value.nonEmpty)
n % .attributes
else
n
@@ -174,7 +174,7 @@ object IvyXml {
}
- def makeIvyXmlBefore[T](
+ private def makeIvyXmlBefore[T](
task: TaskKey[T],
shadedConfigOpt: Option[Configuration]
): Setting[Task[T]] =
@@ -220,6 +220,6 @@ object IvyXml {
def generateIvyXmlSettings(
shadedConfigOpt: Option[Configuration] = None
): Seq[Setting[_]] =
- (needsIvyXml ++ needsIvyXmlLocal).map(IvyXml.makeIvyXmlBefore(_, shadedConfigOpt))
+ (needsIvyXml ++ needsIvyXmlLocal).map(makeIvyXmlBefore(_, shadedConfigOpt))
}
diff --git a/project/Dependencies.scala b/project/Dependencies.scala
index 64c9a8f26..ebc440cca 100644
--- a/project/Dependencies.scala
+++ b/project/Dependencies.scala
@@ -100,8 +100,8 @@ object Dependencies {
def addSbtZincCompile(p: Project): Project =
addSbtModule(p, sbtZincPath, "zincCompile", zincCompile)
- val lmCousierVersion = "1.1.0-M14"
- val lmCousier = "io.get-coursier" %% "lm-coursier" % lmCousierVersion
+ val lmCoursierVersion = "1.1.0-M14-1"
+ val lmCoursierShaded = "io.get-coursier" %% "lm-coursier-shaded" % lmCoursierVersion
val sjsonNewScalaJson = Def.setting {
"com.eed3si9n" %% "sjson-new-scalajson" % contrabandSjsonNewVersion.value