Remove sbt-coursier, sbt-lm-coursier

This commit is contained in:
Adrien Piquerez 2024-10-09 09:14:16 +02:00
parent 7a325bc414
commit 4992ad868f
19 changed files with 0 additions and 2285 deletions

View File

@ -1,60 +0,0 @@
package coursier
import java.io.{File, FileInputStream}
import java.util.Properties
import lmcoursier.definitions.Authentication
// actually deprecated (all public ways of creating that are)
sealed abstract class Credentials extends Product with Serializable {
def user: String
def password: String
def authentication: Authentication =
Authentication(user, password)
}
object Credentials {
private final case class Direct(user: String, password: String) extends Credentials {
override def toString = s"Direct($user, ******)"
}
private final case class FromFile(file: File) extends Credentials {
private lazy val props = {
val p = new Properties()
p.load(new FileInputStream(file))
p
}
private def findKey(keys: Seq[String]) = keys
.iterator
.map(props.getProperty)
.filter(_ != null)
.toStream
.headOption
.getOrElse {
throw new NoSuchElementException(s"${keys.head} key in $file")
}
lazy val user: String = findKey(FromFile.fileUserKeys)
lazy val password: String = findKey(FromFile.filePasswordKeys)
}
private object FromFile {
// from sbt.Credentials
private val fileUserKeys = Seq("user", "user.name", "username")
private val filePasswordKeys = Seq("password", "pwd", "pass", "passwd")
}
@deprecated("Use coursierExtraCredentials rather than coursierCredentials", "1.1.0-M14")
def apply(user: String, password: String): Credentials =
Direct(user, password)
@deprecated("Use coursierExtraCredentials rather than coursierCredentials", "1.1.0-M14")
def apply(file: File): Credentials =
FromFile(file)
}

View File

@ -1,138 +0,0 @@
package coursier.sbtcoursiershared
import lmcoursier.definitions.{Classifier, Configuration, Extension, Publication, Type}
import coursier.sbtcoursiershared.Structure._
import sbt.librarymanagement.{Artifact => _, Configuration => _, _}
import sbt.Def
import sbt.Keys._
private[sbtcoursiershared] object ArtifactsTasks {
def coursierPublicationsTask(
configsMap: (sbt.librarymanagement.Configuration, Configuration)*
): Def.Initialize[sbt.Task[Seq[(Configuration, Publication)]]] =
Def.task {
val state = 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 sourcesConfigOpt =
if (ivyConfigurations.value.exists(_.name == "sources"))
Some(Configuration("sources"))
else
None
val docsConfigOpt =
if (ivyConfigurations.value.exists(_.name == "docs"))
Some(Configuration("docs"))
else
None
val sbtBinArtifacts =
for ((config, targetConfig) <- configsMap) yield {
val publish = publishArtifact
.in(projectRef)
.in(packageBin)
.in(config)
.getOrElse(state, false)
if (publish)
artifact
.in(projectRef)
.in(packageBin)
.in(config)
.find(state)
.map(targetConfig -> _)
else
None
}
val sbtSourceArtifacts =
for ((config, targetConfig) <- configsMap) yield {
val publish = publishArtifact
.in(projectRef)
.in(packageSrc)
.in(config)
.getOrElse(state, false)
if (publish)
artifact
.in(projectRef)
.in(packageSrc)
.in(config)
.find(state)
.map(sourcesConfigOpt.getOrElse(targetConfig) -> _)
else
None
}
val sbtDocArtifacts =
for ((config, targetConfig) <- configsMap) yield {
val publish = publishArtifact
.in(projectRef)
.in(packageDoc)
.in(config)
.getOrElse(state, false)
if (publish)
artifact
.in(projectRef)
.in(packageDoc)
.in(config)
.find(state)
.map(docsConfigOpt.getOrElse(targetConfig) -> _)
else
None
}
val sbtArtifacts = sbtBinArtifacts ++ sbtSourceArtifacts ++ sbtDocArtifacts
def artifactPublication(artifact: sbt.Artifact) = {
val name = CrossVersion(projId.crossVersion, sv, sbv)
.fold(artifact.name)(_(artifact.name))
Publication(
name,
Type(artifact.`type`),
Extension(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 = sbt.Keys.artifacts.in(projectRef).getOrElse(state, 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 Configuration(config.name) -> artifactPublication(artifact)
sbtArtifactsPublication ++ extraSbtArtifactsPublication
}
}

View File

@ -1,270 +0,0 @@
package coursier.sbtcoursiershared
import lmcoursier.definitions.{Attributes, Classifier, Configuration, Dependency, Extension, Info, Module, ModuleName, Organization, Project, Publication, Strict, Type}
import lmcoursier.{FallbackDependency, FromSbt, Inputs}
import coursier.sbtcoursiershared.SbtCoursierShared.autoImport._
import coursier.sbtcoursiershared.Structure._
import lmcoursier.credentials.DirectCredentials
import sbt.{Def, SettingKey}
import sbt.Keys._
import sbt.librarymanagement.{ConflictManager, InclExclRule, ModuleID}
import sbt.util.Logger
import scala.collection.JavaConverters._
import scala.language.reflectiveCalls
object InputsTasks {
lazy val actualExcludeDependencies =
try {
sbt.Keys
.asInstanceOf[{ def allExcludeDependencies: SettingKey[scala.Seq[InclExclRule]] }]
.allExcludeDependencies
} catch {
case _: NoSuchMethodException =>
excludeDependencies
}
private def coursierProject0(
projId: ModuleID,
dependencies: Seq[ModuleID],
configurations: Seq[sbt.librarymanagement.Configuration],
sv: String,
sbv: String,
log: Logger
): Project = {
val configMap = Inputs.configExtendsSeq(configurations).toMap
FromSbt.project(
projId,
dependencies,
configMap,
sv,
sbv
)
}
private[sbtcoursiershared] def coursierProjectTask: Def.Initialize[sbt.Task[Project]] =
Def.taskDyn {
val state = sbt.Keys.state.value
val projectRef = sbt.Keys.thisProjectRef.value
val allDependenciesTask = allDependencies.in(projectRef).get(state)
Def.task {
coursierProject0(
projectID.in(projectRef).get(state),
allDependenciesTask.value,
// should projectID.configurations be used instead?
ivyConfigurations.in(projectRef).get(state),
scalaVersion.in(projectRef).get(state),
scalaBinaryVersion.in(projectRef).get(state),
state.log
)
}
}
private def moduleFromIvy(id: org.apache.ivy.core.module.id.ModuleRevisionId): Module =
Module(
Organization(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[(Configuration, Dependency)] = {
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
(Organization(modId.getOrganisation), ModuleName(modId.getName))
}
.toSet
val configurations = desc
.getModuleConfigurations
.toVector
.flatMap(Inputs.ivyXmlMappings)
def dependency(conf: Configuration, pub: Publication) = Dependency(
module,
id.getRevision,
conf,
exclusions,
pub,
optional = false,
desc.isTransitive
)
val publications: Configuration => Publication = {
val artifacts = desc.getAllDependencyArtifacts
val m = artifacts.toVector.flatMap { art =>
val pub = Publication(art.getName, Type(art.getType), Extension(art.getExt), Classifier(""))
art.getConfigurations.map(Configuration(_)).toVector.map { conf =>
conf -> pub
}
}.toMap
c => m.getOrElse(c, Publication("", Type(""), Extension(""), Classifier("")))
}
configurations.map {
case (from, to) =>
from -> dependency(to, publications(to))
}
}
private[sbtcoursiershared] def coursierInterProjectDependenciesTask: Def.Initialize[sbt.Task[Seq[Project]]] =
Def.taskDyn {
val state = sbt.Keys.state.value
val projectRef = sbt.Keys.thisProjectRef.value
val projectRefs = Structure.allRecursiveInterDependencies(state, projectRef)
val t = coursierProject.forAllProjectsOpt(state, projectRefs :+ projectRef)
Def.task {
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?")
Nil
case (_, Some(p)) =>
Seq(p)
}
}
}
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 {
val state = sbt.Keys.state.value
val projectRef = sbt.Keys.thisProjectRef.value
val projects = allRecursiveInterDependencies(state, projectRef)
val allDependenciesTask = allDependencies
.forAllProjects(state, projectRef +: projects)
.map(_.values.toVector.flatten)
Def.task {
val allDependencies = allDependenciesTask.value
FromSbt.fallbackDependencies(
allDependencies,
scalaVersion.in(projectRef).get(state),
scalaBinaryVersion.in(projectRef).get(state)
)
}
}
val credentialsTask = Def.taskDyn {
val useSbtCredentials = coursierUseSbtCredentials.value
val fromSbt =
if (useSbtCredentials)
Def.task {
val log = streams.value.log
sbt.Keys.credentials.value
.flatMap {
case dc: sbt.DirectCredentials => List(dc)
case fc: sbt.FileCredentials =>
sbt.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)
}
}
else
Def.task(Seq.empty[DirectCredentials])
Def.task {
fromSbt.value ++ coursierExtraCredentials.value
}
}
def strictTask = Def.task {
val cm = conflictManager.value
val log = streams.value.log
cm.name match {
case ConflictManager.latestRevision.name =>
None
case ConflictManager.strict.name =>
val strict = Strict()
.withInclude(Set((cm.organization, cm.module)))
Some(strict)
case other =>
log.warn(s"Unsupported conflict manager $other")
None
}
}
}

View File

@ -1,109 +0,0 @@
package coursier.sbtcoursiershared
import java.io.File
import java.nio.charset.StandardCharsets.UTF_8
import java.nio.file.Files
import lmcoursier.{Inputs, IvyXml}
import lmcoursier.definitions.{Configuration, Project}
import org.apache.ivy.core.module.id.ModuleRevisionId
import sbt.{Def, Setting, Task, TaskKey}
import sbt.internal.librarymanagement.IvySbt
import sbt.librarymanagement.{CrossVersion, PublishConfiguration}
import scala.collection.JavaConverters._
object IvyXmlGeneration {
// These are required for publish to be fine, later on.
private def writeFiles(
currentProject: Project,
exclusions: Seq[(String, String)],
overrides: Seq[(String, String, String)],
ivySbt: IvySbt,
log: sbt.util.Logger
): File = {
val ivyCacheManager = ivySbt.withIvy(log)(ivy =>
ivy.getResolutionCacheManager
)
val ivyModule = ModuleRevisionId.newInstance(
currentProject.module.organization.value,
currentProject.module.name.value,
currentProject.version,
currentProject.module.attributes.asJava
)
val cacheIvyFile = ivyCacheManager.getResolvedIvyFileInCache(ivyModule)
val cacheIvyPropertiesFile = ivyCacheManager.getResolvedIvyPropertiesInCache(ivyModule)
val content0 = IvyXml(currentProject, exclusions, overrides)
cacheIvyFile.getParentFile.mkdirs()
log.info(s"Writing Ivy file $cacheIvyFile")
Files.write(cacheIvyFile.toPath, content0.getBytes(UTF_8))
// Just writing an empty file here... Are these only used?
cacheIvyPropertiesFile.getParentFile.mkdirs()
Files.write(cacheIvyPropertiesFile.toPath, Array.emptyByteArray)
cacheIvyFile
}
def writeIvyXml: Def.Initialize[Task[File]] =
Def.task {
import SbtCoursierShared.autoImport._
val sv = sbt.Keys.scalaVersion.value
val sbv = sbt.Keys.scalaBinaryVersion.value
val log = sbt.Keys.streams.value.log
val currentProject = {
val proj = coursierProject.value
val publications = coursierPublications.value
proj.withPublications(publications)
}
val overrides = Inputs.forceVersions(sbt.Keys.dependencyOverrides.value, sv, sbv).map {
case (mod, ver) =>
(mod.organization.value, mod.name.value, ver)
}
val excludeDeps = Inputs.exclusionsSeq(InputsTasks.actualExcludeDependencies.value, sv, sbv, log)
.map {
case (org, name) =>
(org.value, name.value)
}
writeFiles(currentProject, excludeDeps, overrides, sbt.Keys.ivySbt.value, log)
}
private def makeIvyXmlBefore[T](task: TaskKey[T]): Setting[Task[T]] =
task := task.dependsOn {
Def.taskDyn {
import SbtCoursierShared.autoImport._
val doGen = coursierGenerateIvyXml.value
if (doGen)
Def.task {
coursierWriteIvyXml.value
()
}
else
Def.task(())
}
}.value
private lazy val needsIvyXmlLocal = Seq(sbt.Keys.publishLocalConfiguration) ++ getPubConf("makeIvyXmlLocalConfiguration")
private lazy val needsIvyXml = Seq(sbt.Keys.publishConfiguration) ++ getPubConf("makeIvyXmlConfiguration")
private[this] def getPubConf(method: String): List[TaskKey[PublishConfiguration]] =
try {
val cls = sbt.Keys.getClass
val m = cls.getMethod(method)
val task = m.invoke(sbt.Keys).asInstanceOf[TaskKey[PublishConfiguration]]
List(task)
} catch {
case _: Throwable => // FIXME Too wide
Nil
}
def generateIvyXmlSettings: Seq[Setting[_]] =
(needsIvyXml ++ needsIvyXmlLocal).map(makeIvyXmlBefore)
}

View File

@ -1,25 +0,0 @@
package coursier.sbtcoursiershared
import java.util.{Properties => JProperties}
object Properties {
private lazy val props = {
val p = new JProperties
try {
p.load(
getClass
.getClassLoader
.getResourceAsStream("coursier/sbtcoursier.properties")
)
}
catch {
case _: NullPointerException =>
}
p
}
lazy val version = props.getProperty("version")
lazy val commitHash = props.getProperty("commit-hash")
}

View File

@ -1,111 +0,0 @@
package coursier.sbtcoursiershared
import coursier.sbtcoursiershared.SbtCoursierShared.autoImport._
import coursier.sbtcoursiershared.Structure._
import sbt.{Classpaths, Def}
import sbt.Keys._
import sbt.librarymanagement.{Resolver, URLRepository}
private[sbtcoursiershared] object RepositoriesTasks {
private object Resolvers {
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 = coursierReorderResolvers.value
val keepPreloaded = coursierKeepPreloaded.value
val result0 =
if (reorderResolvers)
Resolvers.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 = allRecursiveInterDependencies(state, projectRef)
val t = coursierResolvers
.forAllProjects(state, projectRef +: projects)
.map(_.values.toVector.flatten)
Def.task(t.value)
}
}

View File

@ -1,194 +0,0 @@
package coursier.sbtcoursiershared
import java.io.File
import coursier.{Credentials => LegacyCredentials}
import lmcoursier.credentials.Credentials
import lmcoursier.{CoursierDependencyResolution, FallbackDependency}
import lmcoursier.definitions.{CacheLogger, Configuration, Project, Publication}
import lmcoursier.internal.SbtCoursierCache
import lmcoursier.syntax._
import sbt.{AutoPlugin, Classpaths, Compile, Setting, TaskKey, Test, settingKey, taskKey}
import sbt.Keys._
import sbt.librarymanagement.DependencyBuilders.OrganizationArtifactName
import sbt.librarymanagement.{ModuleID, Resolver, URLRepository}
import scala.concurrent.duration.FiniteDuration
object SbtCoursierShared extends AutoPlugin {
override def trigger = allRequirements
override def requires = sbt.plugins.JvmPlugin
object autoImport {
val coursierGenerateIvyXml = settingKey[Boolean]("")
val coursierWriteIvyXml = taskKey[File]("")
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")
val coursierReorderResolvers = settingKey[Boolean](
"Whether resolvers should be re-ordered so that typically slow ones are given a lower priority"
)
val coursierResolvers = taskKey[Seq[Resolver]]("")
val coursierRecursiveResolvers = taskKey[Seq[Resolver]]("Resolvers of the current project, plus those of all from its inter-dependency projects")
val coursierSbtResolvers = taskKey[Seq[Resolver]]("")
val coursierFallbackDependencies = taskKey[Seq[FallbackDependency]]("")
val mavenProfiles = settingKey[Set[String]]("")
val versionReconciliation = taskKey[Seq[ModuleID]]("")
private[coursier] val actualCoursierCredentials = TaskKey[Map[String, LegacyCredentials]]("coursierCredentials", "")
val coursierUseSbtCredentials = settingKey[Boolean]("")
@deprecated("Use coursierExtraCredentials rather than coursierCredentials", "1.1.0-M14")
val coursierCredentials = actualCoursierCredentials
val coursierExtraCredentials = taskKey[Seq[Credentials]]("")
val coursierLogger = taskKey[Option[CacheLogger]]("")
val coursierCache = settingKey[File]("")
val sbtCoursierVersion = Properties.version
val coursierRetry = taskKey[Option[(FiniteDuration, Int)]]("Retry for downloading dependencies")
}
import autoImport._
def publicationsSetting(packageConfigs: Seq[(sbt.Configuration, Configuration)]): Setting[_] =
coursierPublications := ArtifactsTasks.coursierPublicationsTask(packageConfigs: _*).value
override def globalSettings: Seq[Setting[_]] =
Seq(
coursierUseSbtCredentials := true,
actualCoursierCredentials := Map.empty,
coursierExtraCredentials := Nil
)
override def buildSettings: Seq[Setting[_]] =
Seq(
coursierReorderResolvers := true,
coursierKeepPreloaded := false,
coursierLogger := None,
coursierCache := CoursierDependencyResolution.defaultCacheLocation,
coursierRetry := None
)
private val pluginIvySnapshotsBase = Resolver.SbtRepositoryRoot.stripSuffix("/") + "/ivy-snapshots"
override def projectSettings = settings(pubSettings = true)
def settings(pubSettings: Boolean) =
Seq[Setting[_]](
clean := {
val noWarningPlz = clean.value
SbtCoursierCache.default.clear()
},
onUnload := {
SbtCoursierCache.default.clear()
onUnload.value
},
coursierGenerateIvyXml := true,
coursierWriteIvyXml := IvyXmlGeneration.writeIvyXml.value,
coursierProject := InputsTasks.coursierProjectTask.value,
coursierInterProjectDependencies := InputsTasks.coursierInterProjectDependenciesTask.value,
coursierExtraProjects := InputsTasks.coursierExtraProjectsTask.value
) ++ {
if (pubSettings)
Seq(
publicationsSetting(Seq(Compile, Test).map(c => c -> Configuration(c.name)))
)
else
Nil
} ++ Seq(
// Tests artifacts from Maven repositories are given this type.
// Adding it here so that these work straightaway.
classpathTypes += "test-jar", // FIXME Should this go in buildSettings?
coursierResolvers := RepositoriesTasks.coursierResolversTask.value,
coursierRecursiveResolvers := RepositoriesTasks.coursierRecursiveResolversTask.value,
coursierSbtResolvers := {
// TODO Add docker-based integration test for that, see https://github.com/coursier/coursier/issues/632
val resolvers =
sbt.Classpaths.bootRepositories(appConfiguration.value).toSeq.flatten ++ // required because of the hack above it seems
externalResolvers.in(updateSbtClassifiers).value
val pluginIvySnapshotsFound = resolvers.exists {
case repo: URLRepository =>
repo
.patterns
.artifactPatterns
.headOption
.exists(_.startsWith(pluginIvySnapshotsBase))
case _ => false
}
val resolvers0 =
if (pluginIvySnapshotsFound && !resolvers.contains(Classpaths.sbtPluginReleases))
resolvers :+ Classpaths.sbtPluginReleases
else
resolvers
if (SbtCoursierShared.autoImport.coursierKeepPreloaded.value)
resolvers0
else
resolvers0.filter { r =>
!r.name.startsWith("local-preloaded")
}
},
coursierFallbackDependencies := InputsTasks.coursierFallbackDependenciesTask.value,
ivyConfigurations := {
val confs = ivyConfigurations.value
val names = confs.map(_.name).toSet
// Yes, adding those back in sbt 1.0. Can't distinguish between config test (whose jars with classifier tests ought to
// be added), and sources / docs else (if their JARs are in compile, they would get added too then).
val extraSources =
if (names("sources"))
None
else
Some(
sbt.Configuration.of(
id = "Sources",
name = "sources",
description = "",
isPublic = true,
extendsConfigs = Vector.empty,
transitive = false
)
)
val extraDocs =
if (names("docs"))
None
else
Some(
sbt.Configuration.of(
id = "Docs",
name = "docs",
description = "",
isPublic = true,
extendsConfigs = Vector.empty,
transitive = false
)
)
confs ++ extraSources.toSeq ++ extraDocs.toSeq
},
mavenProfiles := Set.empty,
versionReconciliation := Seq.empty,
coursierRetry := None
) ++ {
if (pubSettings)
IvyXmlGeneration.generateIvyXmlSettings
else
Nil
}
}

View File

@ -1,74 +0,0 @@
package coursier.sbtcoursiershared
import sbt._
object Structure {
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 <- structure(state).allProjects)
yield p.id -> p.dependencies.map(_.project.project)
val deps = dependencies(allProjectsDeps.toMap, projectRef.project)
structure(state).allProjectRefs.filter(p => deps(p.project))
}
// vv things from sbt-structure vv
def structure(state: State) =
sbt.Project.structure(state)
implicit class `enrich SettingKey`[T](key: SettingKey[T]) {
def find(state: State): Option[T] =
key.get(structure(state).data)
def get(state: State): T =
find(state).get
def getOrElse(state: State, default: => T): T =
find(state).getOrElse(default)
}
implicit class `enrich TaskKey`[T](key: TaskKey[T]) {
def find(state: State): Option[sbt.Task[T]] =
key.get(structure(state).data)
def get(state: State): sbt.Task[T] =
find(state).get
def forAllProjects(state: State, projects: Seq[ProjectRef]): sbt.Task[Map[ProjectRef, T]] = {
val tasks = projects.flatMap(p => key.in(p).get(structure(state).data).map(_.map(it => (p, it))))
std.TaskExtra.joinTasks(tasks).join.map(_.toMap)
}
// ^^ things from sbt-structure ^^
def forAllProjectsOpt(state: State, projects: Seq[ProjectRef]): sbt.Task[Map[ProjectRef, Option[T]]] = {
val settings = structure(state).data
val tasks = projects.map { p =>
val taskOpt = key.in(p).get(settings)
taskOpt match {
case None =>
Def.task(p -> Option.empty[T]).evaluate(settings)
case Some(t) =>
t.map(p -> Option(_))
}
}
std.TaskExtra.joinTasks(tasks).join.map(_.toMap)
}
}
}

View File

@ -1,93 +0,0 @@
package coursier.sbtcoursier
import java.io.File
import coursier.cache.FileCache
import coursier.core._
import coursier.util.Artifact
import lmcoursier.internal.{ArtifactsParams, ArtifactsRun}
import coursier.sbtcoursier.Keys._
import coursier.sbtcoursiershared.InputsTasks.credentialsTask
import coursier.sbtcoursiershared.SbtCoursierShared.autoImport.{coursierCache, coursierLogger}
import lmcoursier.definitions.ToCoursier
import sbt.Def
import sbt.Keys._
object ArtifactsTasks {
def artifactsTask(
withClassifiers: Boolean,
sbtClassifiers: Boolean = false,
ignoreArtifactErrors: Boolean = false,
includeSignatures: Boolean = false
): Def.Initialize[sbt.Task[Map[Artifact, File]]] = {
val resTask: sbt.Def.Initialize[sbt.Task[Seq[Resolution]]] =
if (withClassifiers && sbtClassifiers)
Def.task(coursierSbtClassifiersResolutions.value.values.toVector)
else
Def.task(coursierResolutions.value.values.toVector)
val classifiersTask: sbt.Def.Initialize[sbt.Task[Option[Seq[Classifier]]]] =
if (withClassifiers) {
if (sbtClassifiers)
Def.task(Some(coursierSbtClassifiersModule.value.classifiers.map(Classifier(_))))
else
Def.task(Some(transitiveClassifiers.value.map(Classifier(_))))
} else
Def.task(None)
Def.task {
val projectName = thisProjectRef.value.project
val parallelDownloads = coursierParallelDownloads.value
val artifactsChecksums = coursierArtifactsChecksums.value
val cachePolicies = coursierCachePolicies.value
val ttl = coursierTtl.value
val cache = coursierCache.value
val createLogger = coursierLogger.value.map(ToCoursier.cacheLogger)
val credentials = credentialsTask.value.map(ToCoursier.credentials)
val log = streams.value.log
val verbosityLevel = coursierVerbosity.value
val classifiers = classifiersTask.value
val res = resTask.value
val params = ArtifactsParams(
classifiers = classifiers,
resolutions = res,
includeSignatures = includeSignatures,
loggerOpt = createLogger,
projectName = projectName,
sbtClassifiers = sbtClassifiers,
cache = FileCache()
.withLocation(cache)
.withChecksums(artifactsChecksums)
.withTtl(ttl)
.withCachePolicies(cachePolicies)
.withCredentials(credentials)
.withFollowHttpToHttpsRedirections(true),
parallel = parallelDownloads,
classpathOrder = true,
missingOk = sbtClassifiers
)
val resOrError = ArtifactsRun(
params,
verbosityLevel,
log
)
resOrError match {
case Left(err) =>
throw err
case Right(res0) =>
res0.artifacts.toMap
}
}
}
}

View File

@ -1,195 +0,0 @@
package coursier.sbtcoursier
import coursier.cache.CacheDefaults
import coursier.core.{Configuration, ResolutionProcess}
import coursier.sbtcoursiershared.SbtCoursierShared
import sbt.{Cache => _, Configuration => _, _}
import sbt.Keys._
object CoursierPlugin extends AutoPlugin {
override def trigger = allRequirements
override def requires = SbtCoursierShared
import SbtCoursierShared.autoImport._
object autoImport {
val coursierParallelDownloads = Keys.coursierParallelDownloads
val coursierMaxIterations = Keys.coursierMaxIterations
val coursierChecksums = Keys.coursierChecksums
val coursierArtifactsChecksums = Keys.coursierArtifactsChecksums
val coursierCachePolicies = Keys.coursierCachePolicies
val coursierTtl = Keys.coursierTtl
val coursierVerbosity = Keys.coursierVerbosity
val coursierConfigGraphs = Keys.coursierConfigGraphs
val coursierSbtClassifiersModule = Keys.coursierSbtClassifiersModule
val coursierConfigurations = Keys.coursierConfigurations
val coursierParentProjectCache = Keys.coursierParentProjectCache
val coursierResolutions = Keys.coursierResolutions
val coursierSbtClassifiersResolutions = Keys.coursierSbtClassifiersResolutions
val coursierDependencyTree = Keys.coursierDependencyTree
val coursierDependencyInverseTree = Keys.coursierDependencyInverseTree
val coursierWhatDependsOn = Keys.coursierWhatDependsOn
val coursierArtifacts = Keys.coursierArtifacts
val coursierSignedArtifacts = Keys.coursierSignedArtifacts
val coursierClassifiersArtifacts = Keys.coursierClassifiersArtifacts
val coursierSbtClassifiersArtifacts = Keys.coursierSbtClassifiersArtifacts
@deprecated("Use sbtCoursierVersion instead", "1.1.0-M9")
val coursierVersion = sbtCoursierVersion
val addSbtCoursier: Seq[Def.Setting[_]] = {
import sbt._
Seq(
addSbtPlugin("io.get-coursier" % "sbt-coursier" % sbtCoursierVersion),
// seems needed for some sbt plugins (https://github.com/coursier/coursier/issues/450)
classpathTypes += "maven-plugin"
)
}
}
import autoImport._
lazy val treeSettings = Seq(
coursierDependencyTree := DisplayTasks.coursierDependencyTreeTask(
inverse = false
).value,
coursierDependencyInverseTree := DisplayTasks.coursierDependencyTreeTask(
inverse = true
).value,
coursierWhatDependsOn := Def.inputTaskDyn {
import sbt.complete.DefaultParsers._
val input = token(SpaceClass ~ NotQuoted, "<arg>").parsed._2
DisplayTasks.coursierWhatDependsOnTask(input)
}.evaluated
)
// allows to get the actual repo list when sbt starts up
private val hackHack = Seq(
// TODO Add docker-based non reg test for that, with sbt-assembly 0.14.5 in ~/.sbt/1.0/plugins/plugins.sbt
// along with the required extra repo https://repository.jboss.org/nexus/content/repositories/public
// (required for coursier, because of bad checksums on central)
appConfiguration.in(updateSbtClassifiers) := {
val app = appConfiguration.in(updateSbtClassifiers).value
// hack to trigger https://github.com/sbt/sbt/blob/v1.0.1/main/src/main/scala/sbt/Defaults.scala#L2856,
// to have the third case be used instead of the second one, at https://github.com/sbt/sbt/blob/v1.0.1/main/src/main/scala/sbt/Defaults.scala#L2069
new xsbti.AppConfiguration {
def provider() = {
import scala.language.reflectiveCalls
val prov = app.provider()
val noWarningForDeprecatedStuffProv = prov.asInstanceOf[{
def mainClass(): Class[_ <: xsbti.AppMain]
}]
new xsbti.AppProvider {
def newMain() = prov.newMain()
def components() = prov.components()
def mainClass() = noWarningForDeprecatedStuffProv.mainClass()
def mainClasspath() = prov.mainClasspath()
def loader() = prov.loader()
def scalaProvider() = {
val scalaProv = prov.scalaProvider()
val noWarningForDeprecatedStuffScalaProv = scalaProv.asInstanceOf[{
def libraryJar(): File
def compilerJar(): File
}]
new xsbti.ScalaProvider {
def app(id: xsbti.ApplicationID) = scalaProv.app(id)
def loader() = scalaProv.loader()
def jars() = scalaProv.jars()
def libraryJar() = noWarningForDeprecatedStuffScalaProv.libraryJar()
def version() = scalaProv.version()
def compilerJar() = noWarningForDeprecatedStuffScalaProv.compilerJar()
def launcher() = {
val launch = scalaProv.launcher()
new xsbti.Launcher {
def app(id: xsbti.ApplicationID, version: String) = launch.app(id, version)
def checksums() = launch.checksums()
def globalLock() = launch.globalLock()
def bootDirectory() = launch.bootDirectory()
def appRepositories() = launch.appRepositories()
def topLoader() = launch.topLoader()
def getScala(version: String) = launch.getScala(version)
def getScala(version: String, reason: String) = launch.getScala(version, reason)
def getScala(version: String, reason: String, scalaOrg: String) = launch.getScala(version, reason, scalaOrg)
def isOverrideRepositories = launch.isOverrideRepositories
def ivyRepositories() =
throw new NoSuchMethodError("nope")
def ivyHome() = launch.ivyHome()
}
}
}
}
def entryPoint() = prov.entryPoint()
def id() = prov.id()
}
}
def arguments() = app.arguments()
def baseDirectory() = app.baseDirectory()
}
}
)
def coursierSettings: Seq[Setting[_]] = hackHack ++ Seq(
coursierArtifacts := ArtifactsTasks.artifactsTask(withClassifiers = false).value,
coursierSignedArtifacts := ArtifactsTasks.artifactsTask(withClassifiers = false, includeSignatures = true).value,
coursierClassifiersArtifacts := ArtifactsTasks.artifactsTask(
withClassifiers = true
).value,
coursierSbtClassifiersArtifacts := ArtifactsTasks.artifactsTask(
withClassifiers = true,
sbtClassifiers = true
).value,
update := UpdateTasks.updateTask(withClassifiers = false).value,
updateClassifiers := UpdateTasks.updateTask(withClassifiers = true).value,
updateSbtClassifiers.in(Defaults.TaskGlobal) := UpdateTasks.updateTask(withClassifiers = true, sbtClassifiers = true).value,
coursierConfigGraphs := InputsTasks.ivyGraphsTask.value,
coursierSbtClassifiersModule := classifiersModule.in(updateSbtClassifiers).value,
coursierConfigurations := InputsTasks.coursierConfigurationsTask.value,
coursierParentProjectCache := InputsTasks.parentProjectCacheTask.value,
coursierResolutions := (Def.taskDyn {
val missingOk = updateConfiguration.value.missingOk
ResolutionTasks.resolutionsTask(missingOk = missingOk)
}).value,
Keys.actualCoursierResolution := {
val config = Configuration(Compile.name)
coursierResolutions
.value
.getOrElse(
config,
sys.error(s"Resolution for configuration $config not found")
)
},
coursierSbtClassifiersResolutions := (Def.taskDyn {
val missingOk = (updateConfiguration in updateSbtClassifiers).value.missingOk
ResolutionTasks.resolutionsTask(
sbtClassifiers = true,
missingOk = missingOk,
)
}).value
)
override lazy val buildSettings = super.buildSettings ++ Seq(
coursierParallelDownloads := 6,
coursierMaxIterations := ResolutionProcess.defaultMaxIterations,
coursierChecksums := Seq(Some("SHA-1"), None),
coursierArtifactsChecksums := Seq(None),
coursierCachePolicies := CacheDefaults.cachePolicies,
coursierTtl := CacheDefaults.ttl,
coursierVerbosity := Settings.defaultVerbosityLevel(sLog.value)
)
override lazy val projectSettings = coursierSettings ++
inConfig(Compile)(treeSettings) ++
inConfig(Test)(treeSettings)
}

View File

@ -1,135 +0,0 @@
package coursier.sbtcoursier
import coursier.core._
import lmcoursier.definitions.ToCoursier
import coursier.parse.ModuleParser
import coursier.sbtcoursier.Keys._
import coursier.sbtcoursiershared.SbtCoursierShared.autoImport._
import coursier.util.Print
import sbt.Def
import sbt.Keys._
import scala.collection.mutable
object DisplayTasks {
private case class ResolutionResult(config: Configuration, resolution: Resolution, dependencies: Seq[Dependency])
private def coursierResolutionTask(
sbtClassifiers: Boolean = false,
ignoreArtifactErrors: Boolean = false
): Def.Initialize[sbt.Task[Seq[ResolutionResult]]] = {
val currentProjectTask =
if (sbtClassifiers)
Def.task {
val sv = scalaVersion.value
val sbv = scalaBinaryVersion.value
val cm = coursierSbtClassifiersModule.value
SbtCoursierFromSbt.sbtClassifiersProject(cm, sv, sbv)
}
else
Def.task {
val proj = coursierProject.value
val publications = coursierPublications.value
proj.withPublications(publications)
}
val resolutionsTask =
if (sbtClassifiers)
coursierSbtClassifiersResolutions
else
coursierResolutions
Def.task {
val currentProject = ToCoursier.project(currentProjectTask.value)
val config = Configuration(configuration.value.name)
val configs = coursierConfigurations.value
val includedConfigs = configs.getOrElse(config, Set.empty) + config
val resolutions = resolutionsTask.value
for {
(subGraphConfig, res) <- resolutions.toSeq
if includedConfigs(subGraphConfig)
} yield {
val dependencies0 = currentProject
.dependencies
.collect {
case (`subGraphConfig`, dep) =>
dep
}
.sortBy { dep =>
(dep.module.organization, dep.module.name, dep.version)
}
val subRes = res.subset(dependencies0)
ResolutionResult(subGraphConfig, subRes, dependencies0)
}
}
}
def coursierDependencyTreeTask(
inverse: Boolean,
sbtClassifiers: Boolean = false,
ignoreArtifactErrors: Boolean = false
) = Def.task {
val projectName = thisProjectRef.value.project
val resolutions = coursierResolutionTask(sbtClassifiers, ignoreArtifactErrors).value
for (ResolutionResult(subGraphConfig, resolution, dependencies) <- resolutions) {
streams.value.log.info(
s"$projectName (configuration ${subGraphConfig.value})" + "\n" +
Print.dependencyTree(
resolution,
dependencies,
printExclusions = true,
inverse,
colors = !sys.props.get("sbt.log.noformat").toSeq.contains("true")
)
)
}
}
def coursierWhatDependsOnTask(
moduleName: String,
sbtClassifiers: Boolean = false,
ignoreArtifactErrors: Boolean = false
) = Def.task {
val module = ModuleParser.module(moduleName, scalaVersion.value)
.right
.getOrElse(throw new RuntimeException(s"Could not parse module `$moduleName`"))
val projectName = thisProjectRef.value.project
val resolutions = coursierResolutionTask(sbtClassifiers, ignoreArtifactErrors).value
val result = new mutable.StringBuilder
for (ResolutionResult(subGraphConfig, resolution, _) <- resolutions) {
val roots = resolution
.minDependencies
.filter(f => f.module == module)
.toVector
.sortBy(_.toString) // elements already have the same module, there's not much left for sorting
val strToPrint = s"$projectName (configurations ${subGraphConfig.value})" + "\n" +
Print.dependencyTree(
resolution,
roots,
printExclusions = true,
reverse = true,
colors = !sys.props.get("sbt.log.noformat").toSeq.contains("true")
)
streams.value.log.info(strToPrint)
result.append(strToPrint)
result.append("\n")
}
result.toString
}
}

View File

@ -1,69 +0,0 @@
package coursier.sbtcoursier
import coursier.ProjectCache
import coursier.core._
import lmcoursier._
import lmcoursier.definitions.ToCoursier
import coursier.sbtcoursier.Keys._
import coursier.sbtcoursiershared.SbtCoursierShared.autoImport._
import coursier.sbtcoursiershared.Structure._
import sbt.librarymanagement.{Configuration => _, _}
import sbt.Def
import sbt.Keys._
object InputsTasks {
def coursierConfigurationsTask: Def.Initialize[sbt.Task[Map[Configuration, Set[Configuration]]]] =
Def.task {
Inputs.coursierConfigurationsMap(ivyConfigurations.value).map {
case (k, v) =>
ToCoursier.configuration(k) -> v.map(ToCoursier.configuration)
}
}
def ivyGraphsTask: Def.Initialize[sbt.Task[Seq[(Configuration, Seq[Configuration])]]] =
Def.task {
val p = coursierProject.value
Inputs.orderedConfigurations(p.configurations.toSeq).map {
case (config, extends0) =>
(ToCoursier.configuration(config), extends0.map(ToCoursier.configuration))
}
}
def parentProjectCacheTask: Def.Initialize[sbt.Task[Map[Seq[sbt.librarymanagement.Resolver], Seq[coursier.ProjectCache]]]] =
Def.taskDyn {
val state = sbt.Keys.state.value
val projectRef = sbt.Keys.thisProjectRef.value
val projectDeps = structure(state).allProjects
.find(_.id == projectRef.project)
.map(_.dependencies.map(_.project.project).toSet)
.getOrElse(Set.empty)
val projects = structure(state).allProjectRefs.filter(p => projectDeps(p.project))
val t =
for {
m <- coursierRecursiveResolvers.forAllProjects(state, projects)
n <- coursierResolutions.forAllProjects(state, m.keys.toSeq)
} yield
n.foldLeft(Map.empty[Seq[Resolver], Seq[ProjectCache]]) {
case (caches, (ref, resolutions)) =>
val mainResOpt = resolutions.collectFirst {
case (Configuration.compile, v) => v
}
val r = for {
resolvers <- m.get(ref)
resolution <- mainResOpt
} yield
caches.updated(resolvers, resolution.projectCache +: caches.getOrElse(resolvers, Seq.empty))
r.getOrElse(caches)
}
Def.task(t.value)
}
}

View File

@ -1,55 +0,0 @@
package coursier.sbtcoursier
import java.io.File
import coursier.cache.CachePolicy
import coursier.ProjectCache
import coursier.core._
import coursier.util.Artifact
import sbt.librarymanagement.{GetClassifiersModule, Resolver}
import sbt.{InputKey, SettingKey, TaskKey}
import scala.concurrent.duration.{Duration, FiniteDuration}
object Keys {
val coursierParallelDownloads = SettingKey[Int]("coursier-parallel-downloads")
val coursierMaxIterations = SettingKey[Int]("coursier-max-iterations")
val coursierChecksums = SettingKey[Seq[Option[String]]]("coursier-checksums")
val coursierArtifactsChecksums = SettingKey[Seq[Option[String]]]("coursier-artifacts-checksums")
val coursierCachePolicies = SettingKey[Seq[CachePolicy]]("coursier-cache-policies")
val coursierTtl = SettingKey[Option[Duration]]("coursier-ttl")
val coursierVerbosity = SettingKey[Int]("coursier-verbosity")
val coursierConfigGraphs = TaskKey[Seq[(Configuration, Seq[Configuration])]]("coursier-config-graphs")
val coursierSbtClassifiersModule = TaskKey[GetClassifiersModule]("coursier-sbt-classifiers-module")
val coursierConfigurations = TaskKey[Map[Configuration, Set[Configuration]]]("coursier-configurations")
val coursierParentProjectCache = TaskKey[Map[Seq[Resolver], Seq[ProjectCache]]]("coursier-parent-project-cache")
val coursierResolutions = TaskKey[Map[Configuration, Resolution]]("coursier-resolutions")
private[coursier] val actualCoursierResolution = TaskKey[Resolution]("coursier-resolution")
val coursierSbtClassifiersResolutions = TaskKey[Map[Configuration, Resolution]]("coursier-sbt-classifiers-resolution")
val coursierDependencyTree = TaskKey[Unit](
"coursier-dependency-tree",
"Prints dependencies and transitive dependencies as a tree"
)
val coursierDependencyInverseTree = TaskKey[Unit](
"coursier-dependency-inverse-tree",
"Prints dependencies and transitive dependencies as an inverted tree (dependees as children)"
)
val coursierWhatDependsOn = InputKey[String](
"coursier-what-depends-on",
"Prints dependencies and transitive dependencies as an inverted tree for a specific module (dependees as children)"
)
val coursierArtifacts = TaskKey[Map[Artifact, File]]("coursier-artifacts")
val coursierSignedArtifacts = TaskKey[Map[Artifact, File]]("coursier-signed-artifacts")
val coursierClassifiersArtifacts = TaskKey[Map[Artifact, File]]("coursier-classifiers-artifacts")
val coursierSbtClassifiersArtifacts = TaskKey[Map[Artifact, File]]("coursier-sbt-classifiers-artifacts")
}

View File

@ -1,189 +0,0 @@
package coursier.sbtcoursier
import coursier.ProjectCache
import coursier.cache.FileCache
import coursier.core._
import coursier.internal.Typelevel
import lmcoursier.definitions.ToCoursier
import lmcoursier.{FallbackDependency, FromSbt, Inputs}
import lmcoursier.internal.{InterProjectRepository, ResolutionParams, ResolutionRun, Resolvers}
import coursier.sbtcoursier.Keys._
import coursier.sbtcoursiershared.InputsTasks.{credentialsTask, strictTask}
import coursier.sbtcoursiershared.SbtCoursierShared.autoImport._
import coursier.util.{ModuleMatcher, ModuleMatchers}
import sbt.Def
import sbt.Keys._
object ResolutionTasks {
def resolutionsTask(
sbtClassifiers: Boolean = false,
missingOk: Boolean = false,
): Def.Initialize[sbt.Task[Map[Configuration, coursier.Resolution]]] = {
val currentProjectTask: sbt.Def.Initialize[sbt.Task[(Project, Seq[FallbackDependency], Seq[(Configuration, Seq[Configuration])])]] =
if (sbtClassifiers)
Def.task {
val sv = scalaVersion.value
val sbv = scalaBinaryVersion.value
val cm = coursierSbtClassifiersModule.value
val proj = ToCoursier.project(SbtCoursierFromSbt.sbtClassifiersProject(cm, sv, sbv))
val fallbackDeps = FromSbt.fallbackDependencies(
cm.dependencies,
sv,
sbv
)
(proj, fallbackDeps, cm.configurations.map(c => Configuration(c.name) -> Nil))
}
else
Def.task {
val baseConfigGraphs = coursierConfigGraphs.value
val publications = coursierPublications.value
(ToCoursier.project(coursierProject.value.withPublications(publications)), coursierFallbackDependencies.value, baseConfigGraphs)
}
val resolversTask =
if (sbtClassifiers)
Def.task(coursierSbtResolvers.value)
else
Def.task(coursierRecursiveResolvers.value.distinct)
val retrySettings = Def.task(coursierRetry.value)
Def.task {
val projectName = thisProjectRef.value.project
val sv = scalaVersion.value
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
val maxIterations = coursierMaxIterations.value
val cachePolicies = coursierCachePolicies.value
val ttl = coursierTtl.value
val cache = coursierCache.value
val createLogger = coursierLogger.value.map(ToCoursier.cacheLogger)
val log = streams.value.log
// are these always defined? (e.g. for Java only projects?)
val so = Organization(scalaOrganization.value)
val userForceVersions = Inputs.forceVersions(dependencyOverrides.value, sv, sbv)
val verbosityLevel = coursierVerbosity.value
val userEnabledProfiles = mavenProfiles.value
val versionReconciliations0 = versionReconciliation.value.map { mod =>
Reconciliation(mod.revision) match {
case Some(rec) =>
val (mod0, _) = FromSbt.moduleVersion(mod, sv, sbv)
val matcher = ModuleMatchers.only(Organization(mod0.organization.value), ModuleName(mod0.name.value))
matcher -> rec
case None =>
throw new Exception(s"Unrecognized reconciliation: '${mod.revision}'")
}
}
val typelevel = Organization(scalaOrganization.value) == Typelevel.typelevelOrg
val interProjectRepo = InterProjectRepository(interProjectDependencies)
val extraProjectsRepo = InterProjectRepository(extraProjects)
val ivyProperties = ResolutionParams.defaultIvyProperties(ivyPaths.value.ivyHome)
val authenticationByRepositoryId = actualCoursierCredentials.value.mapValues(_.authentication)
val (currentProject, fallbackDependencies, orderedConfigs) = currentProjectTask.value
val autoScalaLib = autoScalaLibrary.value && scalaModuleInfo.value.forall(_.overrideScalaVersion)
val resolvers = resolversTask.value
// TODO Warn about possible duplicated modules from source repositories?
val credentials = credentialsTask.value.map(ToCoursier.credentials)
val strictOpt = strictTask.value.map(ToCoursier.strict)
val parentProjectCache: ProjectCache = coursierParentProjectCache.value
.get(resolvers)
.map(_.foldLeft[ProjectCache](Map.empty)(_ ++ _))
.getOrElse(Map.empty)
val excludeDeps = Inputs.exclusions(
coursier.sbtcoursiershared.InputsTasks.actualExcludeDependencies.value,
sv,
sbv,
log
).map {
case (org, name) =>
(Organization(org.value), ModuleName(name.value))
}
val mainRepositories = resolvers
.flatMap { resolver =>
Resolvers.repository(
resolver,
ivyProperties,
log,
authenticationByRepositoryId.get(resolver.name).map { a =>
Authentication(a.user, a.password)
.withOptional(a.optional)
.withRealmOpt(a.realmOpt)
},
Seq(),
)
}
val resOrError = ResolutionRun.resolutions(
ResolutionParams(
dependencies = currentProject.dependencies,
fallbackDependencies = fallbackDependencies,
orderedConfigs = orderedConfigs,
autoScalaLibOpt = if (autoScalaLib) Some((so, sv)) else None,
mainRepositories = mainRepositories,
parentProjectCache = parentProjectCache,
interProjectDependencies = interProjectDependencies,
internalRepositories = Seq(interProjectRepo, extraProjectsRepo),
sbtClassifiers = sbtClassifiers,
projectName = projectName,
loggerOpt = createLogger,
cache = FileCache()
.withLocation(cache)
.withCachePolicies(cachePolicies)
.withTtl(ttl)
.withChecksums(checksums)
.withCredentials(credentials)
.withFollowHttpToHttpsRedirections(true),
parallel = parallelDownloads,
params = coursier.params.ResolutionParams()
.withMaxIterations(maxIterations)
.withProfiles(userEnabledProfiles)
.withForceVersion(userForceVersions.map { case (k, v) => (ToCoursier.module(k), v) }.toMap)
.withTypelevel(typelevel)
.addReconciliation(versionReconciliations0: _*)
.withExclusions(excludeDeps),
strictOpt = strictOpt,
missingOk = missingOk,
retry = retrySettings.value.getOrElse(ResolutionParams.defaultRetry)
),
verbosityLevel,
log
)
resOrError match {
case Left(err) =>
throw err
case Right(res) =>
res
}
}
}
}

View File

@ -1,37 +0,0 @@
package coursier.sbtcoursier
import lmcoursier.FromSbt
import lmcoursier.definitions.Configuration
import sbt.librarymanagement.GetClassifiersModule
object SbtCoursierFromSbt {
def sbtClassifiersProject(
cm: GetClassifiersModule,
scalaVersion: String,
scalaBinaryVersion: String
) = {
val p = FromSbt.project(
cm.id,
cm.dependencies,
cm.configurations.map(cfg => Configuration(cfg.name) -> cfg.extendsConfigs.map(c => Configuration(c.name))).toMap,
scalaVersion,
scalaBinaryVersion
)
// for w/e reasons, the dependencies sometimes don't land in the right config above
// this is a loose attempt at fixing that
cm.configurations match {
case Seq(cfg) =>
p.withDependencies(
p.dependencies.map {
case (_, d) => (Configuration(cfg.name), d)
}
)
case _ =>
p
}
}
}

View File

@ -1,46 +0,0 @@
package coursier.sbtcoursier
import sbt.Logger
import scala.util.{Failure, Success, Try}
object Settings {
private val baseDefaultVerbosityLevel =
if (System.console() == null) // non interactive mode
0
else
1
def defaultVerbosityLevel(logger: Logger): Int = {
def fromOption(value: Option[String], description: String): Option[Int] =
value
.filter(_.nonEmpty)
.flatMap { str =>
Try(str.toInt) match {
case Success(level) => Some(level)
case Failure(_) =>
logger.warn(
s"unrecognized $description value (should be an integer), ignoring it."
)
None
}
}
val fromEnv = fromOption(
sys.env.get("COURSIER_VERBOSITY"),
"COURSIER_VERBOSITY environment variable"
)
def fromProps = fromOption(
sys.props.get("coursier.verbosity"),
"Java property coursier.verbosity"
)
fromEnv
.orElse(fromProps)
.getOrElse(baseDefaultVerbosityLevel)
}
}

View File

@ -1,148 +0,0 @@
package coursier.sbtcoursier
import coursier.core._
import coursier.sbtcoursier.Keys._
import coursier.sbtcoursiershared.SbtCoursierShared.autoImport._
import lmcoursier.definitions.ToCoursier
import lmcoursier.Inputs
import lmcoursier.internal.{SbtBootJars, SbtCoursierCache, UpdateParams, UpdateRun}
import sbt.Def
import sbt.Keys._
import sbt.librarymanagement.UpdateReport
object UpdateTasks {
def updateTask(
withClassifiers: Boolean,
sbtClassifiers: Boolean = false,
includeSignatures: Boolean = false
): Def.Initialize[sbt.Task[UpdateReport]] = {
val currentProjectTask =
if (sbtClassifiers)
Def.task {
val sv = scalaVersion.value
val sbv = scalaBinaryVersion.value
SbtCoursierFromSbt.sbtClassifiersProject(coursierSbtClassifiersModule.value, sv, sbv)
}
else
Def.task {
val proj = coursierProject.value
val publications = coursierPublications.value
proj.withPublications(publications)
}
val resTask =
if (withClassifiers && sbtClassifiers)
coursierSbtClassifiersResolutions
else
coursierResolutions
// we should be able to call .value on that one here, its conditions don't originate from other tasks
val artifactFilesOrErrors0Task =
if (withClassifiers) {
if (sbtClassifiers)
Keys.coursierSbtClassifiersArtifacts
else
Keys.coursierClassifiersArtifacts
} else if (includeSignatures)
Keys.coursierSignedArtifacts
else
Keys.coursierArtifacts
val configsTask: sbt.Def.Initialize[sbt.Task[Map[Configuration, Set[Configuration]]]] =
if (withClassifiers && sbtClassifiers)
Def.task {
val cm = coursierSbtClassifiersModule.value
cm.configurations.map(c => Configuration(c.name) -> Set(Configuration(c.name))).toMap
}
else
coursierConfigurations
val classifiersTask: sbt.Def.Initialize[sbt.Task[Option[Seq[Classifier]]]] =
if (withClassifiers) {
if (sbtClassifiers)
Def.task {
val cm = coursierSbtClassifiersModule.value
Some(cm.classifiers.map(Classifier(_)))
}
else
Def.task(Some(transitiveClassifiers.value.map(Classifier(_))))
} else
Def.task(None)
Def.taskDyn {
val so = Organization(scalaOrganization.value)
val internalSbtScalaProvider = appConfiguration.value.provider.scalaProvider
val sbtBootJarOverrides = SbtBootJars(
so, // this seems plain wrong - this assumes that the scala org of the project is the same
// as the one that started SBT. This will scrap the scala org specific JARs by the ones
// that booted SBT, even if the latter come from the standard org.scala-lang org.
// But SBT itself does it this way, and not doing so may make two different versions
// of the scala JARs land in the classpath...
internalSbtScalaProvider.version(),
internalSbtScalaProvider.jars()
)
val log = streams.value.log
val verbosityLevel = coursierVerbosity.value
val p = ToCoursier.project(currentProjectTask.value)
val dependencies = p.dependencies
val res = resTask.value
val key = SbtCoursierCache.ReportKey(
dependencies,
res,
withClassifiers,
sbtClassifiers,
includeSignatures
)
val interProjectDependencies = coursierInterProjectDependencies.value.map(ToCoursier.project)
SbtCoursierCache.default.reportOpt(key) match {
case Some(report) =>
Def.task(report)
case None =>
Def.task {
val artifactFilesOrErrors0 = artifactFilesOrErrors0Task.value
val classifiers = classifiersTask.value
val configs = configsTask.value
val sv = scalaVersion.value
val sbv = scalaBinaryVersion.value
val forceVersions = Inputs.forceVersions(dependencyOverrides.value, sv, sbv)
.map {
case (m, v) =>
(ToCoursier.module(m), v)
}
.toMap
val params = UpdateParams(
(p.module, p.version),
artifactFilesOrErrors0,
None,
classifiers,
configs,
dependencies,
forceVersions,
interProjectDependencies,
res,
includeSignatures,
sbtBootJarOverrides,
classpathOrder = true,
missingOk = sbtClassifiers,
classLoaders = Nil,
)
val rep = UpdateRun.update(params, verbosityLevel, log)
SbtCoursierCache.default.putReport(key, rep)
rep
}
}
}
}
}

View File

@ -1,215 +0,0 @@
package coursier.sbtlmcoursier
import lmcoursier.definitions.{Authentication, ModuleMatchers, Reconciliation}
import lmcoursier.{CoursierConfiguration, CoursierDependencyResolution, Inputs}
import lmcoursier.syntax._
import coursier.sbtcoursiershared.InputsTasks.{credentialsTask, strictTask}
import coursier.sbtcoursiershared.{InputsTasks, SbtCoursierShared}
import sbt.{AutoPlugin, Classpaths, Def, Setting, Task, taskKey}
import sbt.Project.inTask
import sbt.KeyRanks.DTask
import sbt.Keys.{appConfiguration, autoScalaLibrary, classpathTypes, dependencyOverrides, dependencyResolution, ivyPaths, scalaBinaryVersion, scalaModuleInfo, scalaOrganization, scalaVersion, streams, updateClassifiers, updateConfiguration, updateSbtClassifiers}
import sbt.librarymanagement.DependencyResolution
import scala.language.reflectiveCalls
import sbt.TaskKey
object LmCoursierPlugin extends AutoPlugin {
import SbtCoursierShared.autoImport._
object autoImport {
val coursierConfiguration = taskKey[CoursierConfiguration]("General dependency management (Coursier) settings, such as the resolvers and options to use.").withRank(DTask)
val addSbtCoursier: Seq[Def.Setting[_]] = {
import sbt._
Seq(
addSbtPlugin("io.get-coursier" % "sbt-lm-coursier" % sbtCoursierVersion),
// seems needed for some sbt plugins (https://github.com/coursier/coursier/issues/450)
classpathTypes += "maven-plugin"
)
}
}
import autoImport._
override def trigger = allRequirements
// this transitively requires IvyPlugin which is needed to override it,
// so that it doesn't override us :|
override def requires = SbtCoursierShared
private lazy val scalaCompilerBridgeScopeOpt: Option[TaskKey[Unit]] =
try {
// only added in sbt 1.3.x
val key = sbt.Keys
.asInstanceOf[{ def scalaCompilerBridgeScope: TaskKey[Unit] }]
.scalaCompilerBridgeScope
Some(key)
}
catch {
case _: NoSuchMethodError | _: NoSuchMethodException =>
None
}
// putting this in projectSettings like sbt.plugins.IvyPlugin does :|
override def projectSettings: Seq[Setting[_]] =
Seq(
dependencyResolution := mkDependencyResolution.value,
coursierConfiguration := mkCoursierConfiguration().value,
updateClassifiers := Def.taskDyn {
val lm = dependencyResolution.in(updateClassifiers).value
Def.task(sbt.hack.Foo.updateTask(lm).value)
}.value
) ++
setCsrConfiguration ++
inTask(updateClassifiers)(
Seq(
dependencyResolution := mkDependencyResolution.value,
coursierConfiguration := mkCoursierConfiguration(withClassifiers = true).value
)
) ++
inTask(updateSbtClassifiers)(
Seq(
dependencyResolution := mkDependencyResolution.value,
coursierConfiguration := mkCoursierConfiguration(sbtClassifiers = true).value
)
) ++ {
scalaCompilerBridgeScopeOpt match {
case None => Nil
case Some(scalaCompilerBridgeScopeKey) =>
inTask(scalaCompilerBridgeScopeKey)(
Seq(
dependencyResolution := mkDependencyResolution.value,
coursierConfiguration := mkCoursierConfiguration().value
)
)
}
}
private def setCsrConfiguration: Seq[Setting[_]] = {
val csrConfigurationOpt = try {
val key = sbt.Keys.asInstanceOf[{
def csrConfiguration: TaskKey[CoursierConfiguration]
}].csrConfiguration
Some(key)
} catch {
case _: NoSuchMethodException =>
None
}
csrConfigurationOpt.toSeq.map { csrConfiguration =>
csrConfiguration := coursierConfiguration.value
}
}
private def mkCoursierConfiguration(withClassifiers: Boolean = false, sbtClassifiers: Boolean = false): Def.Initialize[Task[CoursierConfiguration]] =
Def.taskDyn {
val resolversTask =
if (sbtClassifiers)
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))
else
Def.task(None)
Def.task {
val rs = resolversTask.value
val scalaOrg = scalaOrganization.value
val scalaVer = scalaVersion.value
val sbv = scalaBinaryVersion.value
val interProjectDependencies = interProjectDependenciesTask.value
val extraProjects = coursierExtraProjects.value
val excludeDeps = Inputs.exclusions(
InputsTasks.actualExcludeDependencies.value,
scalaVer,
scalaBinaryVersion.value,
streams.value.log
)
val fallbackDeps = coursierFallbackDependencies.value
val autoScalaLib = autoScalaLibrary.value && scalaModuleInfo.value.forall(_.overrideScalaVersion)
val profiles = mavenProfiles.value
val versionReconciliations0 = versionReconciliation.value.map { mod =>
Reconciliation(mod.revision) match {
case Some(rec) =>
val (mod0, _) = lmcoursier.FromSbt.moduleVersion(mod, scalaVer, sbv)
val matcher = ModuleMatchers.only(mod0)
matcher -> rec
case None =>
throw new Exception(s"Unrecognized reconciliation: '${mod.revision}'")
}
}
val userForceVersions = Inputs.forceVersions(dependencyOverrides.value, scalaVer, sbv)
val authenticationByRepositoryId = actualCoursierCredentials.value.mapValues { c =>
val a = c.authentication
Authentication(a.user, a.password, a.optional, a.realmOpt, headers = Nil, httpsOnly = true, passOnRedirect = false)
}
val credentials = credentialsTask.value
val strict = strictTask.value
val createLogger = coursierLogger.value
val cache = coursierCache.value
val internalSbtScalaProvider = appConfiguration.value.provider.scalaProvider
val sbtBootJars = internalSbtScalaProvider.jars()
val sbtScalaVersion = internalSbtScalaProvider.version()
val sbtScalaOrganization = "org.scala-lang" // always assuming sbt uses mainline scala
val classifiers = classifiersTask.value
val updateConfig = updateConfiguration.value
val s = streams.value
Classpaths.warnResolversConflict(rs, s.log)
CoursierConfiguration()
.withResolvers(rs.toVector)
.withInterProjectDependencies(interProjectDependencies.toVector)
.withExtraProjects(extraProjects.toVector)
.withFallbackDependencies(fallbackDeps.toVector)
.withExcludeDependencies(
excludeDeps
.toVector
.map {
case (o, n) =>
(o.value, n.value)
}
.sorted
)
.withAutoScalaLibrary(autoScalaLib)
.withSbtScalaJars(sbtBootJars.toVector)
.withSbtScalaVersion(sbtScalaVersion)
.withSbtScalaOrganization(sbtScalaOrganization)
.withClassifiers(classifiers.toVector.flatten)
.withHasClassifiers(classifiers.nonEmpty)
.withMavenProfiles(profiles.toVector.sorted)
.withReconciliation(versionReconciliations0.toVector)
.withScalaOrganization(scalaOrg)
.withScalaVersion(scalaVer)
.withAuthenticationByRepositoryId(authenticationByRepositoryId.toVector.sortBy(_._1))
.withCredentials(credentials)
.withLogger(createLogger)
.withCache(cache)
.withLog(s.log)
.withIvyHome(ivyPaths.value.ivyHome)
.withStrict(strict)
.withForceVersions(userForceVersions.toVector)
.withSbtClassifiers(sbtClassifiers)
// seems missingOk is false in the updateConfig of updateSbtClassifiers?
.withUpdateConfiguration(updateConfig.withMissingOk(updateConfig.missingOk || sbtClassifiers))
}
}
private def mkDependencyResolution: Def.Initialize[Task[DependencyResolution]] =
Def.task {
CoursierDependencyResolution(coursierConfiguration.value, None)
}
}

View File

@ -1,122 +0,0 @@
package sbt.hack
import sbt._
import sbt.Keys._
import sbt.internal.LibraryManagement
import sbt.librarymanagement.DependencyResolution
import scala.language.reflectiveCalls
object Foo {
// same implementation as update in sbt, except DependencyResolution is passed as argument
// and the unmanagedJarsTask stuff was removed (already handled in lm-coursier via
// SbtBootJars and all)
def updateTask(lm: DependencyResolution): Def.Initialize[Task[UpdateReport]] = Def.task {
val s = streams.value
val cacheDirectory = streams.value.cacheDirectory
val isRoot = executionRoots.value contains resolvedScoped.value
val shouldForce = isRoot || {
forceUpdatePeriod.value match {
case None => false
case Some(period) =>
val fullUpdateOutput = cacheDirectory / "out"
val now = System.currentTimeMillis
val diff = now - fullUpdateOutput.lastModified()
val elapsedDuration = new scala.concurrent.duration.FiniteDuration(diff, java.util.concurrent.TimeUnit.MILLISECONDS)
fullUpdateOutput.exists() && elapsedDuration > period
}
}
val state0 = state.value
val updateConf = {
// Log captures log messages at all levels, except ivy logs.
// Use full level when debug is enabled so that ivy logs are shown.
import UpdateLogging.{ Full, DownloadOnly, Default }
val conf = updateConfiguration.value
val maybeUpdateLevel = (logLevel in update).?.value
val conf1 = maybeUpdateLevel.orElse(state0.get(logLevel.key)) match {
case Some(Level.Debug) if conf.logging == Default => conf.withLogging(logging = Full)
case Some(_) if conf.logging == Default => conf.withLogging(logging = DownloadOnly)
case _ => conf
}
// logical clock is folded into UpdateConfiguration
conf1.withLogicalClock(LogicalClock(state0.hashCode))
}
val evictionOptions = Def.taskDyn {
if (executionRoots.value.exists(_.key == evicted.key))
Def.task(EvictionWarningOptions.empty)
else Def.task((evictionWarningOptions in update).value)
}.value
try {
LibraryManagement.cachedUpdate(
// LM API
lm = lm,
// Ivy-free ModuleDescriptor
module = ivyModule.value,
s.cacheStoreFactory.sub(updateCacheName.value),
Reference.display(thisProjectRef.value),
updateConf,
identity,
skip = (skip in update).value,
force = shouldForce,
depsUpdated = transitiveUpdate.value.exists(!_.stats.cached),
uwConfig = (unresolvedWarningConfiguration in update).value,
ewo = evictionOptions,
mavenStyle = publishMavenStyle.value,
compatWarning = compatibilityWarningOptions.value,
log = s.log
)
} catch {
case _: NoSuchMethodError =>
// cachedUpdate method changed in https://github.com/sbt/sbt/commit/6c7faf2b8611f122a37b824c6e08e950855d939f
import sbt.internal.librarymanagement.CompatibilityWarningOptions
import sbt.librarymanagement.{DependencyResolution, ModuleDescriptor, UnresolvedWarningConfiguration, UpdateConfiguration}
import sbt.util.CacheStoreFactory
LibraryManagement.asInstanceOf[{
def cachedUpdate(
lm: DependencyResolution,
module: ModuleDescriptor,
cacheStoreFactory: CacheStoreFactory,
label: String,
updateConfig: UpdateConfiguration,
transform: UpdateReport => UpdateReport,
skip: Boolean,
force: Boolean,
depsUpdated: Boolean,
uwConfig: UnresolvedWarningConfiguration,
ewo: EvictionWarningOptions,
mavenStyle: Boolean,
compatWarning: CompatibilityWarningOptions,
includeCallers: Boolean,
includeDetails: Boolean,
log: Logger
): UpdateReport
}].cachedUpdate(
// LM API
lm = lm,
// Ivy-free ModuleDescriptor
module = ivyModule.value,
s.cacheStoreFactory.sub(updateCacheName.value),
Reference.display(thisProjectRef.value),
updateConf,
identity,
skip = (skip in update).value,
force = shouldForce,
depsUpdated = transitiveUpdate.value.exists(!_.stats.cached),
uwConfig = (unresolvedWarningConfiguration in update).value,
ewo = evictionOptions,
mavenStyle = publishMavenStyle.value,
compatWarning = compatibilityWarningOptions.value,
includeCallers = false,
includeDetails = false,
log = s.log
)
}
}
}