mirror of https://github.com/sbt/sbt.git
Coursier dependency resolution integration
This adds dependency to LM implemented using Coursier. I had to copy paste a bunch of code from sbt-coursier-shared to break the dependency to sbt. `Global / useCoursier := false` or `-Dsbt.coursier=false` be used to opt-out of using Coursier for the dependency resolution.
This commit is contained in:
parent
42bc2ea04d
commit
38f94a6e31
|
|
@ -590,7 +590,12 @@ lazy val mainProj = (project in file("main"))
|
||||||
if (xs exists { s => s.contains(s""""$sv"""") }) ()
|
if (xs exists { s => s.contains(s""""$sv"""") }) ()
|
||||||
else sys.error("PluginCross.scala does not match up with the scalaVersion " + sv)
|
else sys.error("PluginCross.scala does not match up with the scalaVersion " + sv)
|
||||||
},
|
},
|
||||||
libraryDependencies ++= scalaXml.value ++ Seq(launcherInterface) ++ log4jDependencies ++ Seq(scalaCacheCaffeine),
|
libraryDependencies ++= {
|
||||||
|
scalaXml.value ++
|
||||||
|
Seq(launcherInterface) ++
|
||||||
|
log4jDependencies ++
|
||||||
|
Seq(scalaCacheCaffeine, lmCousier)
|
||||||
|
},
|
||||||
Compile / scalacOptions -= "-Xfatal-warnings",
|
Compile / scalacOptions -= "-Xfatal-warnings",
|
||||||
managedSourceDirectories in Compile +=
|
managedSourceDirectories in Compile +=
|
||||||
baseDirectory.value / "src" / "main" / "contraband-scala",
|
baseDirectory.value / "src" / "main" / "contraband-scala",
|
||||||
|
|
@ -650,6 +655,7 @@ lazy val sbtProj = (project in file("sbt"))
|
||||||
)
|
)
|
||||||
.configure(addSbtIO, addSbtCompilerBridge)
|
.configure(addSbtIO, addSbtCompilerBridge)
|
||||||
|
|
||||||
|
/*
|
||||||
lazy val sbtBig = (project in file(".big"))
|
lazy val sbtBig = (project in file(".big"))
|
||||||
.dependsOn(sbtProj)
|
.dependsOn(sbtProj)
|
||||||
.settings(
|
.settings(
|
||||||
|
|
@ -685,6 +691,7 @@ lazy val sbtBig = (project in file(".big"))
|
||||||
}).transform(node).head
|
}).transform(node).head
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
*/
|
||||||
|
|
||||||
lazy val sbtIgnoredProblems = {
|
lazy val sbtIgnoredProblems = {
|
||||||
Vector(
|
Vector(
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import java.net.{ URI, URL, URLClassLoader }
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
import java.util.concurrent.{ Callable, TimeUnit }
|
import java.util.concurrent.{ Callable, TimeUnit }
|
||||||
|
|
||||||
|
import coursier.core.{ Configuration => CConfiguration }
|
||||||
import org.apache.ivy.core.module.descriptor.ModuleDescriptor
|
import org.apache.ivy.core.module.descriptor.ModuleDescriptor
|
||||||
import org.apache.ivy.core.module.id.ModuleRevisionId
|
import org.apache.ivy.core.module.id.ModuleRevisionId
|
||||||
import sbt.Def.{ Initialize, ScopedKey, Setting, SettingsDefinition }
|
import sbt.Def.{ Initialize, ScopedKey, Setting, SettingsDefinition }
|
||||||
|
|
@ -200,6 +201,7 @@ object Defaults extends BuildCommon {
|
||||||
exportJars :== false,
|
exportJars :== false,
|
||||||
trackInternalDependencies :== TrackLevel.TrackAlways,
|
trackInternalDependencies :== TrackLevel.TrackAlways,
|
||||||
exportToInternal :== TrackLevel.TrackAlways,
|
exportToInternal :== TrackLevel.TrackAlways,
|
||||||
|
useCoursier :== LibraryManagement.defaultUseCoursier,
|
||||||
retrieveManaged :== false,
|
retrieveManaged :== false,
|
||||||
retrieveManagedSync :== false,
|
retrieveManagedSync :== false,
|
||||||
configurationsToRetrieve :== None,
|
configurationsToRetrieve :== None,
|
||||||
|
|
@ -224,7 +226,12 @@ object Defaults extends BuildCommon {
|
||||||
pomAllRepositories :== false,
|
pomAllRepositories :== false,
|
||||||
pomIncludeRepository :== Classpaths.defaultRepositoryFilter,
|
pomIncludeRepository :== Classpaths.defaultRepositoryFilter,
|
||||||
updateOptions := UpdateOptions(),
|
updateOptions := UpdateOptions(),
|
||||||
forceUpdatePeriod :== None
|
forceUpdatePeriod :== None,
|
||||||
|
// coursier settings
|
||||||
|
csrExtraCredentials :== Nil,
|
||||||
|
csrLogger :== None,
|
||||||
|
csrCachePath :== coursier.cache.CacheDefaults.location,
|
||||||
|
csrMavenProfiles :== Set.empty,
|
||||||
)
|
)
|
||||||
|
|
||||||
/** Core non-plugin settings for sbt builds. These *must* be on every build or the sbt engine will fail to run at all. */
|
/** Core non-plugin settings for sbt builds. These *must* be on every build or the sbt engine will fail to run at all. */
|
||||||
|
|
@ -2125,6 +2132,14 @@ object Classpaths {
|
||||||
}).value,
|
}).value,
|
||||||
moduleName := normalizedName.value,
|
moduleName := normalizedName.value,
|
||||||
ivyPaths := IvyPaths(baseDirectory.value, bootIvyHome(appConfiguration.value)),
|
ivyPaths := IvyPaths(baseDirectory.value, bootIvyHome(appConfiguration.value)),
|
||||||
|
csrCachePath := {
|
||||||
|
val old = csrCachePath.value
|
||||||
|
val ip = ivyPaths.value
|
||||||
|
val defaultIvyCache = bootIvyHome(appConfiguration.value)
|
||||||
|
if (old != coursier.cache.CacheDefaults.location) old
|
||||||
|
else if (ip.ivyHome == defaultIvyCache) old
|
||||||
|
else ip.ivyHome.getOrElse(old)
|
||||||
|
},
|
||||||
dependencyCacheDirectory := {
|
dependencyCacheDirectory := {
|
||||||
val st = state.value
|
val st = state.value
|
||||||
BuildPaths.getDependencyDirectory(st, BuildPaths.getGlobalBase(st))
|
BuildPaths.getDependencyDirectory(st, BuildPaths.getGlobalBase(st))
|
||||||
|
|
@ -2181,10 +2196,7 @@ object Classpaths {
|
||||||
)
|
)
|
||||||
else None
|
else None
|
||||||
},
|
},
|
||||||
dependencyResolution := IvyDependencyResolution(
|
dependencyResolution := LibraryManagement.dependencyResolutionTask.value,
|
||||||
ivyConfiguration.value,
|
|
||||||
CustomHttp.okhttpClient.value
|
|
||||||
),
|
|
||||||
publisher := IvyPublisher(ivyConfiguration.value, CustomHttp.okhttpClient.value),
|
publisher := IvyPublisher(ivyConfiguration.value, CustomHttp.okhttpClient.value),
|
||||||
ivyConfiguration := mkIvyConfiguration.value,
|
ivyConfiguration := mkIvyConfiguration.value,
|
||||||
ivyConfigurations := {
|
ivyConfigurations := {
|
||||||
|
|
@ -2198,6 +2210,44 @@ object Classpaths {
|
||||||
if (managedScalaInstance.value && scalaHome.value.isEmpty) Configurations.ScalaTool :: Nil
|
if (managedScalaInstance.value && scalaHome.value.isEmpty) Configurations.ScalaTool :: Nil
|
||||||
else Nil
|
else Nil
|
||||||
},
|
},
|
||||||
|
// Coursier needs these
|
||||||
|
ivyConfigurations := {
|
||||||
|
val confs = ivyConfigurations.value
|
||||||
|
val names = confs.map(_.name).toSet
|
||||||
|
val extraSources =
|
||||||
|
if (names("sources"))
|
||||||
|
None
|
||||||
|
else
|
||||||
|
Some(
|
||||||
|
Configuration.of(
|
||||||
|
id = "Sources",
|
||||||
|
name = "sources",
|
||||||
|
description = "",
|
||||||
|
isPublic = true,
|
||||||
|
extendsConfigs = Vector.empty,
|
||||||
|
transitive = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val extraDocs =
|
||||||
|
if (names("docs"))
|
||||||
|
None
|
||||||
|
else
|
||||||
|
Some(
|
||||||
|
Configuration.of(
|
||||||
|
id = "Docs",
|
||||||
|
name = "docs",
|
||||||
|
description = "",
|
||||||
|
isPublic = true,
|
||||||
|
extendsConfigs = Vector.empty,
|
||||||
|
transitive = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val use = useCoursier.value
|
||||||
|
if (use) confs ++ extraSources.toSeq ++ extraDocs.toSeq
|
||||||
|
else confs
|
||||||
|
},
|
||||||
moduleSettings := moduleSettings0.value,
|
moduleSettings := moduleSettings0.value,
|
||||||
makePomConfiguration := MakePomConfiguration()
|
makePomConfiguration := MakePomConfiguration()
|
||||||
.withFile((artifactPath in makePom).value)
|
.withFile((artifactPath in makePom).value)
|
||||||
|
|
@ -2342,8 +2392,17 @@ object Classpaths {
|
||||||
case Right(ur) => ur
|
case Right(ur) => ur
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} tag (Tags.Update, Tags.Network)).value
|
} tag (Tags.Update, Tags.Network)).value,
|
||||||
)
|
csrProject := LMCoursier.coursierProjectTask.value,
|
||||||
|
csrConfiguration := LMCoursier.coursierConfigurationTask(false, false).value,
|
||||||
|
csrResolvers := LMCoursier.coursierResolversTask.value,
|
||||||
|
csrRecursiveResolvers := LMCoursier.coursierRecursiveResolversTask.value,
|
||||||
|
csrSbtResolvers := LMCoursier.coursierSbtResolversTask.value,
|
||||||
|
csrInterProjectDependencies := LMCoursier.coursierInterProjectDependenciesTask.value,
|
||||||
|
csrFallbackDependencies := LMCoursier.coursierFallbackDependenciesTask.value,
|
||||||
|
) ++
|
||||||
|
IvyXml.generateIvyXmlSettings() ++
|
||||||
|
LMCoursier.publicationsSetting(Seq(Compile, Test).map(c => c -> CConfiguration(c.name)))
|
||||||
|
|
||||||
val jvmBaseSettings: Seq[Setting[_]] = Seq(
|
val jvmBaseSettings: Seq[Setting[_]] = Seq(
|
||||||
libraryDependencies ++= autoLibraryDependency(
|
libraryDependencies ++= autoLibraryDependency(
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ import sbt.librarymanagement.ivy.{ Credentials, IvyConfiguration, IvyPaths, Upda
|
||||||
import sbt.testing.Framework
|
import sbt.testing.Framework
|
||||||
import sbt.util.{ Level, Logger }
|
import sbt.util.{ Level, Logger }
|
||||||
import xsbti.compile._
|
import xsbti.compile._
|
||||||
|
import coursier.cache.CacheLogger
|
||||||
|
import coursier.lmcoursier.{ CoursierConfiguration, FallbackDependency }
|
||||||
|
|
||||||
import scala.concurrent.duration.{ Duration, FiniteDuration }
|
import scala.concurrent.duration.{ Duration, FiniteDuration }
|
||||||
import scala.xml.{ NodeSeq, Node => XNode }
|
import scala.xml.{ NodeSeq, Node => XNode }
|
||||||
|
|
@ -351,6 +353,20 @@ object Keys {
|
||||||
val fullClasspathAsJars = taskKey[Classpath]("The exported classpath, consisting of build products and unmanaged and managed, internal and external dependencies, all as JARs.")
|
val fullClasspathAsJars = taskKey[Classpath]("The exported classpath, consisting of build products and unmanaged and managed, internal and external dependencies, all as JARs.")
|
||||||
val internalDependencyConfigurations = settingKey[Seq[(ProjectRef, Set[String])]]("The project configurations that this configuration depends on")
|
val internalDependencyConfigurations = settingKey[Seq[(ProjectRef, Set[String])]]("The project configurations that this configuration depends on")
|
||||||
|
|
||||||
|
val useCoursier = settingKey[Boolean]("Use Coursier for dependency resolution.").withRank(BSetting)
|
||||||
|
val csrCachePath = settingKey[File]("Coursier cache path").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 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 csrFallbackDependencies = taskKey[Seq[FallbackDependency]]("")
|
||||||
|
private[sbt] val csrMavenProfiles = settingKey[Set[String]]("")
|
||||||
|
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)]]("")
|
||||||
|
|
||||||
val internalConfigurationMap = settingKey[Configuration => Configuration]("Maps configurations to the actual configuration used to define the classpath.").withRank(CSetting)
|
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)
|
val classpathConfiguration = taskKey[Configuration]("The configuration used to define the classpath.").withRank(CTask)
|
||||||
val ivyConfiguration = taskKey[IvyConfiguration]("General dependency management (Ivy) settings, such as the resolvers and paths to use.").withRank(DTask)
|
val ivyConfiguration = taskKey[IvyConfiguration]("General dependency management (Ivy) settings, such as the resolvers and paths to use.").withRank(DTask)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,524 @@
|
||||||
|
/*
|
||||||
|
* sbt
|
||||||
|
* Copyright 2011 - 2018, Lightbend, Inc.
|
||||||
|
* Copyright 2008 - 2010, Mark Harrah
|
||||||
|
* Licensed under Apache License 2.0 (see LICENSE)
|
||||||
|
*/
|
||||||
|
|
||||||
|
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.librarymanagement._
|
||||||
|
import Keys._
|
||||||
|
import sbt.librarymanagement.ivy.{
|
||||||
|
FileCredentials,
|
||||||
|
Credentials,
|
||||||
|
DirectCredentials => IvyDirectCredentials
|
||||||
|
}
|
||||||
|
import sbt.ScopeFilter.Make._
|
||||||
|
import scala.collection.JavaConverters._
|
||||||
|
|
||||||
|
private[sbt] object LMCoursier {
|
||||||
|
|
||||||
|
def coursierProjectTask: Def.Initialize[sbt.Task[CProject]] =
|
||||||
|
Def.task {
|
||||||
|
Inputs.coursierProject(
|
||||||
|
projectID.value,
|
||||||
|
allDependencies.value,
|
||||||
|
excludeDependencies.value,
|
||||||
|
// should projectID.configurations be used instead?
|
||||||
|
ivyConfigurations.value,
|
||||||
|
scalaVersion.value,
|
||||||
|
scalaBinaryVersion.value,
|
||||||
|
streams.value.log
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
def coursierConfigurationTask(
|
||||||
|
withClassifiers: Boolean,
|
||||||
|
sbtClassifiers: Boolean
|
||||||
|
): Def.Initialize[Task[CoursierConfiguration]] =
|
||||||
|
Def.taskDyn {
|
||||||
|
val resolversTask =
|
||||||
|
if (sbtClassifiers)
|
||||||
|
csrSbtResolvers
|
||||||
|
else
|
||||||
|
csrRecursiveResolvers
|
||||||
|
val classifiersTask: sbt.Def.Initialize[sbt.Task[Option[Seq[Classifier]]]] =
|
||||||
|
if (withClassifiers && !sbtClassifiers)
|
||||||
|
Def.task(Some(sbt.Keys.transitiveClassifiers.value.map(Classifier(_))))
|
||||||
|
else
|
||||||
|
Def.task(None)
|
||||||
|
Def.task {
|
||||||
|
val rs = resolversTask.value
|
||||||
|
val scalaOrg = scalaOrganization.value
|
||||||
|
val scalaVer = scalaVersion.value
|
||||||
|
val interProjectDependencies = csrInterProjectDependencies.value
|
||||||
|
val excludeDeps = Inputs.exclusions(
|
||||||
|
excludeDependencies.value,
|
||||||
|
scalaVer,
|
||||||
|
scalaBinaryVersion.value,
|
||||||
|
streams.value.log
|
||||||
|
)
|
||||||
|
val fallbackDeps = csrFallbackDependencies.value
|
||||||
|
val autoScalaLib = autoScalaLibrary.value && scalaModuleInfo.value.forall(
|
||||||
|
_.overrideScalaVersion
|
||||||
|
)
|
||||||
|
val profiles = csrMavenProfiles.value
|
||||||
|
val credentials = credentialsTask.value
|
||||||
|
|
||||||
|
val createLogger = csrLogger.value
|
||||||
|
|
||||||
|
val cache = csrCachePath.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 s = streams.value
|
||||||
|
Classpaths.warnResolversConflict(rs, s.log)
|
||||||
|
CoursierConfiguration()
|
||||||
|
.withResolvers(rs.toVector)
|
||||||
|
.withInterProjectDependencies(interProjectDependencies.toVector)
|
||||||
|
.withFallbackDependencies(fallbackDeps.toVector)
|
||||||
|
.withExcludeDependencies(
|
||||||
|
excludeDeps.toVector.sorted
|
||||||
|
.map {
|
||||||
|
case (o, n) =>
|
||||||
|
(o.value, n.value)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.withAutoScalaLibrary(autoScalaLib)
|
||||||
|
.withSbtScalaJars(sbtBootJars.toVector)
|
||||||
|
.withSbtScalaVersion(sbtScalaVersion)
|
||||||
|
.withSbtScalaOrganization(sbtScalaOrganization)
|
||||||
|
.withClassifiers(classifiers.toVector.flatten.map(_.value))
|
||||||
|
.withHasClassifiers(classifiers.nonEmpty)
|
||||||
|
.withMavenProfiles(profiles.toVector.sorted)
|
||||||
|
.withScalaOrganization(scalaOrg)
|
||||||
|
.withScalaVersion(scalaVer)
|
||||||
|
.withCredentials(credentials)
|
||||||
|
.withLogger(createLogger)
|
||||||
|
.withCache(cache)
|
||||||
|
.withLog(s.log)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 result = resultTask(bootResOpt, overrideFlag).value
|
||||||
|
val reorderResolvers = true // coursierReorderResolvers.value
|
||||||
|
val keepPreloaded = false // coursierKeepPreloaded.value
|
||||||
|
|
||||||
|
val result0 =
|
||||||
|
if (reorderResolvers)
|
||||||
|
ResolutionParams.reorderResolvers(result)
|
||||||
|
else
|
||||||
|
result
|
||||||
|
|
||||||
|
if (keepPreloaded)
|
||||||
|
result0
|
||||||
|
else
|
||||||
|
result0.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 {
|
||||||
|
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
|
||||||
|
val keepPreloaded = true // coursierKeepPreloaded.value
|
||||||
|
if (keepPreloaded)
|
||||||
|
resolvers0
|
||||||
|
else
|
||||||
|
resolvers0.filter { r =>
|
||||||
|
!r.name.startsWith("local-preloaded")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,12 +5,15 @@
|
||||||
* Licensed under Apache License 2.0 (see LICENSE)
|
* Licensed under Apache License 2.0 (see LICENSE)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sbt.internal
|
package sbt
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import coursier.lmcoursier.CoursierDependencyResolution
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
import sbt.internal.librarymanagement._
|
import sbt.internal.librarymanagement._
|
||||||
|
import sbt.internal.util.{ ConsoleAppender, LogOption }
|
||||||
import sbt.librarymanagement._
|
import sbt.librarymanagement._
|
||||||
|
import sbt.librarymanagement.ivy.IvyDependencyResolution
|
||||||
import sbt.librarymanagement.syntax._
|
import sbt.librarymanagement.syntax._
|
||||||
import sbt.util.{ CacheStore, CacheStoreFactory, Logger, Tracked }
|
import sbt.util.{ CacheStore, CacheStoreFactory, Logger, Tracked }
|
||||||
import sbt.io.IO
|
import sbt.io.IO
|
||||||
|
|
@ -19,6 +22,43 @@ private[sbt] object LibraryManagement {
|
||||||
|
|
||||||
private type UpdateInputs = (Long, ModuleSettings, UpdateConfiguration)
|
private type UpdateInputs = (Long, ModuleSettings, UpdateConfiguration)
|
||||||
|
|
||||||
|
def defaultUseCoursier: Boolean = {
|
||||||
|
val coursierOpt = sys.props
|
||||||
|
.get("sbt.coursier")
|
||||||
|
.flatMap(
|
||||||
|
str =>
|
||||||
|
ConsoleAppender.parseLogOption(str) match {
|
||||||
|
case LogOption.Always => Some(true)
|
||||||
|
case LogOption.Never => Some(false)
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
val ivyOpt = sys.props
|
||||||
|
.get("sbt.ivy")
|
||||||
|
.flatMap(
|
||||||
|
str =>
|
||||||
|
ConsoleAppender.parseLogOption(str) match {
|
||||||
|
case LogOption.Always => Some(true)
|
||||||
|
case LogOption.Never => Some(false)
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
val notIvyOpt = ivyOpt map { !_ }
|
||||||
|
coursierOpt.orElse(notIvyOpt).getOrElse(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
def dependencyResolutionTask: Def.Initialize[Task[DependencyResolution]] = Def.taskDyn {
|
||||||
|
if (Keys.useCoursier.value) {
|
||||||
|
Def.task { CoursierDependencyResolution(Keys.csrConfiguration.value) }
|
||||||
|
} else
|
||||||
|
Def.task {
|
||||||
|
IvyDependencyResolution(
|
||||||
|
Keys.ivyConfiguration.value,
|
||||||
|
CustomHttp.okhttpClient.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def cachedUpdate(
|
def cachedUpdate(
|
||||||
lm: DependencyResolution,
|
lm: DependencyResolution,
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,224 @@
|
||||||
|
/*
|
||||||
|
* 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 java.nio.charset.StandardCharsets.UTF_8
|
||||||
|
import java.nio.file.Files
|
||||||
|
|
||||||
|
import coursier.core.{ Configuration, Project }
|
||||||
|
import org.apache.ivy.core.module.id.ModuleRevisionId
|
||||||
|
import Def.Setting
|
||||||
|
import sbt.Keys.{
|
||||||
|
csrProject,
|
||||||
|
csrPublications,
|
||||||
|
publishLocalConfiguration,
|
||||||
|
publishConfiguration,
|
||||||
|
useCoursier
|
||||||
|
}
|
||||||
|
import sbt.librarymanagement.PublishConfiguration
|
||||||
|
import scala.collection.JavaConverters._
|
||||||
|
import scala.xml.{ Node, PrefixedAttribute }
|
||||||
|
|
||||||
|
object IvyXml {
|
||||||
|
import sbt.Project._
|
||||||
|
|
||||||
|
def rawContent(
|
||||||
|
currentProject: Project,
|
||||||
|
shadedConfigOpt: Option[Configuration]
|
||||||
|
): String = {
|
||||||
|
|
||||||
|
// Important: width = Int.MaxValue, so that no tag gets truncated.
|
||||||
|
// In particular, that prevents things like <foo /> to be split to
|
||||||
|
// <foo>
|
||||||
|
// </foo>
|
||||||
|
// by the pretty-printer.
|
||||||
|
// See https://github.com/sbt/sbt/issues/3412.
|
||||||
|
val printer = new scala.xml.PrettyPrinter(Int.MaxValue, 2)
|
||||||
|
|
||||||
|
"""<?xml version="1.0" encoding="UTF-8"?>""" + '\n' +
|
||||||
|
printer.format(content(currentProject, shadedConfigOpt))
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are required for publish to be fine, later on.
|
||||||
|
def writeFiles(
|
||||||
|
currentProject: Project,
|
||||||
|
shadedConfigOpt: Option[Configuration],
|
||||||
|
ivySbt: IvySbt,
|
||||||
|
log: sbt.util.Logger
|
||||||
|
): Unit = {
|
||||||
|
|
||||||
|
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 = rawContent(currentProject, shadedConfigOpt)
|
||||||
|
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)
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
||||||
|
def content(project0: Project, shadedConfigOpt: Option[Configuration]): Node = {
|
||||||
|
|
||||||
|
val filterOutDependencies =
|
||||||
|
shadedConfigOpt.toSet[Configuration].flatMap { shadedConfig =>
|
||||||
|
project0.dependencies
|
||||||
|
.collect { case (`shadedConfig`, dep) => dep }
|
||||||
|
}
|
||||||
|
|
||||||
|
val project: Project = project0.copy(
|
||||||
|
dependencies = project0.dependencies.collect {
|
||||||
|
case p @ (_, dep) if !filterOutDependencies(dep) => p
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
val infoAttrs = project.module.attributes.foldLeft[xml.MetaData](xml.Null) {
|
||||||
|
case (acc, (k, v)) =>
|
||||||
|
new PrefixedAttribute("e", k, v, acc)
|
||||||
|
}
|
||||||
|
|
||||||
|
val licenseElems = project.info.licenses.map {
|
||||||
|
case (name, urlOpt) =>
|
||||||
|
val n = <license name={name} />
|
||||||
|
|
||||||
|
urlOpt.fold(n) { url =>
|
||||||
|
n % <x url={url} />.attributes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val infoElem = {
|
||||||
|
<info
|
||||||
|
organisation={project.module.organization.value}
|
||||||
|
module={project.module.name.value}
|
||||||
|
revision={project.version}
|
||||||
|
>
|
||||||
|
{licenseElems}
|
||||||
|
<description>{project.info.description}</description>
|
||||||
|
</info>
|
||||||
|
} % infoAttrs
|
||||||
|
|
||||||
|
val confElems = project.configurations.toVector.collect {
|
||||||
|
case (name, extends0) if !shadedConfigOpt.contains(name) =>
|
||||||
|
val extends1 = shadedConfigOpt.fold(extends0)(c => extends0.filter(_ != c))
|
||||||
|
val n = <conf name={name.value} visibility="public" description="" />
|
||||||
|
if (extends1.nonEmpty)
|
||||||
|
n % <x extends={extends1.map(_.value).mkString(",")} />.attributes
|
||||||
|
else
|
||||||
|
n
|
||||||
|
}
|
||||||
|
|
||||||
|
val publications = project.publications
|
||||||
|
.groupBy { case (_, p) => p }
|
||||||
|
.mapValues { _.map { case (cfg, _) => cfg } }
|
||||||
|
|
||||||
|
val publicationElems = publications.map {
|
||||||
|
case (pub, configs) =>
|
||||||
|
val n =
|
||||||
|
<artifact name={pub.name} type={pub.`type`.value} ext={pub.ext.value} conf={
|
||||||
|
configs.map(_.value).mkString(",")
|
||||||
|
} />
|
||||||
|
|
||||||
|
if (pub.classifier.nonEmpty)
|
||||||
|
n % <x e:classifier={pub.classifier.value} />.attributes
|
||||||
|
else
|
||||||
|
n
|
||||||
|
}
|
||||||
|
|
||||||
|
val dependencyElems = project.dependencies.toVector.map {
|
||||||
|
case (conf, dep) =>
|
||||||
|
val excludes = dep.exclusions.toSeq.map {
|
||||||
|
case (org, name) =>
|
||||||
|
<exclude org={org.value} module={name.value} name="*" type="*" ext="*" conf="" matcher="exact"/>
|
||||||
|
}
|
||||||
|
|
||||||
|
val n =
|
||||||
|
<dependency org={dep.module.organization.value} name={dep.module.name.value} rev={
|
||||||
|
dep.version
|
||||||
|
} conf={s"${conf.value}->${dep.configuration.value}"}>
|
||||||
|
{excludes}
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
val moduleAttrs = dep.module.attributes.foldLeft[xml.MetaData](xml.Null) {
|
||||||
|
case (acc, (k, v)) =>
|
||||||
|
new PrefixedAttribute("e", k, v, acc)
|
||||||
|
}
|
||||||
|
|
||||||
|
n % moduleAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
<ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra">
|
||||||
|
{infoElem}
|
||||||
|
<configurations>{confElems}</configurations>
|
||||||
|
<publications>{publicationElems}</publications>
|
||||||
|
<dependencies>{dependencyElems}</dependencies>
|
||||||
|
</ivy-module>
|
||||||
|
}
|
||||||
|
|
||||||
|
def makeIvyXmlBefore[T](
|
||||||
|
task: TaskKey[T],
|
||||||
|
shadedConfigOpt: Option[Configuration]
|
||||||
|
): Setting[Task[T]] =
|
||||||
|
task := task.dependsOn {
|
||||||
|
Def.taskDyn {
|
||||||
|
val doGen = useCoursier.value
|
||||||
|
if (doGen)
|
||||||
|
Def.task {
|
||||||
|
val currentProject = {
|
||||||
|
val proj = csrProject.value
|
||||||
|
val publications = csrPublications.value
|
||||||
|
proj.copy(publications = publications)
|
||||||
|
}
|
||||||
|
IvyXml.writeFiles(
|
||||||
|
currentProject,
|
||||||
|
shadedConfigOpt,
|
||||||
|
sbt.Keys.ivySbt.value,
|
||||||
|
sbt.Keys.streams.value.log
|
||||||
|
)
|
||||||
|
} else
|
||||||
|
Def.task(())
|
||||||
|
}
|
||||||
|
}.value
|
||||||
|
|
||||||
|
private lazy val needsIvyXmlLocal = Seq(publishLocalConfiguration) ++ getPubConf(
|
||||||
|
"makeIvyXmlLocalConfiguration"
|
||||||
|
)
|
||||||
|
private lazy val needsIvyXml = Seq(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(
|
||||||
|
shadedConfigOpt: Option[Configuration] = None
|
||||||
|
): Seq[Setting[_]] =
|
||||||
|
(needsIvyXml ++ needsIvyXmlLocal).map(IvyXml.makeIvyXmlBefore(_, shadedConfigOpt))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -29,22 +29,7 @@ object Dependencies {
|
||||||
private val utilScripted = "org.scala-sbt" %% "util-scripted" % utilVersion
|
private val utilScripted = "org.scala-sbt" %% "util-scripted" % utilVersion
|
||||||
|
|
||||||
private val libraryManagementCore = "org.scala-sbt" %% "librarymanagement-core" % lmVersion
|
private val libraryManagementCore = "org.scala-sbt" %% "librarymanagement-core" % lmVersion
|
||||||
|
private val libraryManagementImpl = "org.scala-sbt" %% "librarymanagement-ivy" % lmVersion
|
||||||
private val libraryManagementImpl = {
|
|
||||||
val lmOrganization =
|
|
||||||
sys.props.get("sbt.build.lm.organization") match {
|
|
||||||
case Some(impl) => impl
|
|
||||||
case _ => "org.scala-sbt"
|
|
||||||
}
|
|
||||||
|
|
||||||
val lmModuleName =
|
|
||||||
sys.props.get("sbt.build.lm.moduleName") match {
|
|
||||||
case Some(impl) => impl
|
|
||||||
case _ => "librarymanagement-ivy"
|
|
||||||
}
|
|
||||||
|
|
||||||
lmOrganization %% lmModuleName % lmVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
val launcherVersion = "1.0.4"
|
val launcherVersion = "1.0.4"
|
||||||
val launcherInterface = "org.scala-sbt" % "launcher-interface" % launcherVersion
|
val launcherInterface = "org.scala-sbt" % "launcher-interface" % launcherVersion
|
||||||
|
|
@ -115,6 +100,9 @@ object Dependencies {
|
||||||
def addSbtZincCompile(p: Project): Project =
|
def addSbtZincCompile(p: Project): Project =
|
||||||
addSbtModule(p, sbtZincPath, "zincCompile", zincCompile)
|
addSbtModule(p, sbtZincPath, "zincCompile", zincCompile)
|
||||||
|
|
||||||
|
val lmCousierVersion = "1.1.0-M14"
|
||||||
|
val lmCousier = "io.get-coursier" %% "lm-coursier" % lmCousierVersion
|
||||||
|
|
||||||
val sjsonNewScalaJson = Def.setting {
|
val sjsonNewScalaJson = Def.setting {
|
||||||
"com.eed3si9n" %% "sjson-new-scalajson" % contrabandSjsonNewVersion.value
|
"com.eed3si9n" %% "sjson-new-scalajson" % contrabandSjsonNewVersion.value
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,9 @@ def retrieveID = org % "test-retrieve" % "2.0"
|
||||||
|
|
||||||
// check that the test class is on the compile classpath, either because it was compiled or because it was properly retrieved
|
// check that the test class is on the compile classpath, either because it was compiled or because it was properly retrieved
|
||||||
def checkTask(classpath: TaskKey[Classpath]) = Def task {
|
def checkTask(classpath: TaskKey[Classpath]) = Def task {
|
||||||
val loader = ClasspathUtilities.toLoader((classpath in Compile).value.files, scalaInstance.value.loader)
|
val deps = libraryDependencies.value
|
||||||
|
val cp = (classpath in Compile).value.files
|
||||||
|
val loader = ClasspathUtilities.toLoader(cp, scalaInstance.value.loader)
|
||||||
try { Class.forName("test.Test", false, loader); () }
|
try { Class.forName("test.Test", false, loader); () }
|
||||||
catch { case _: ClassNotFoundException | _: NoClassDefFoundError => sys.error("Dependency not retrieved properly") }
|
catch { case _: ClassNotFoundException | _: NoClassDefFoundError => sys.error(s"Dependency not retrieved properly: $deps, $cp") }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue