mirror of https://github.com/sbt/sbt.git
Don't let two different scala JARs land in the classpath...
...because of SBT
This commit is contained in:
parent
72d0ac9728
commit
80bd9c0dea
|
|
@ -0,0 +1,114 @@
|
|||
package coursier
|
||||
|
||||
import java.io.File
|
||||
|
||||
import coursier.core.Publication
|
||||
|
||||
import scalaz.{ EitherT, Monad }
|
||||
import scalaz.Scalaz.ToEitherOps
|
||||
|
||||
object SbtScalaJarsRepository {
|
||||
|
||||
// Will break in 2.11, where scala-parser-combinators_2.11 and scala-xml_2.11, with different
|
||||
// org and versions, are thrown into the mix.
|
||||
// To handle these well, we would need to fetch actual infos about the scala-* dependencies
|
||||
// from actual repos, and use that from SbtScalaJarsRepository.
|
||||
|
||||
val looseDependencies = Map(
|
||||
"scala-compiler" -> Set(
|
||||
"scala-library",
|
||||
"scala-reflect"
|
||||
),
|
||||
"scala-reflect" -> Set(
|
||||
"scala-library"
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
case class SbtScalaJarsRepository(
|
||||
scalaOrg: String,
|
||||
scalaVersion: String,
|
||||
jars: Seq[File]
|
||||
) extends Repository { repo =>
|
||||
|
||||
val foundNames = jars.collect {
|
||||
case jar if jar.getName.endsWith(".jar") =>
|
||||
jar.getName.stripSuffix(".jar")
|
||||
}.toSet
|
||||
|
||||
val dependencies = SbtScalaJarsRepository.looseDependencies
|
||||
.filterKeys(foundNames)
|
||||
.mapValues(_.filter(foundNames))
|
||||
|
||||
val artifacts = jars.collect {
|
||||
case jar if jar.getName.endsWith(".jar") =>
|
||||
val name = jar.getName.stripSuffix(".jar")
|
||||
val mod = Module(scalaOrg, name)
|
||||
|
||||
val proj = Project(
|
||||
mod,
|
||||
scalaVersion,
|
||||
dependencies.getOrElse(name, Set.empty[String]).toVector.map { depName =>
|
||||
val dep = Dependency(Module(scalaOrg, depName), scalaVersion)
|
||||
"compile" -> dep
|
||||
},
|
||||
MavenRepository.defaultConfigurations,
|
||||
None,
|
||||
Nil,
|
||||
Nil,
|
||||
Nil,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Seq("compile" -> Publication(name, "jar", "jar", "")),
|
||||
Info("", "", Nil, Nil, None)
|
||||
)
|
||||
|
||||
(mod, scalaVersion) -> ((proj, jar))
|
||||
}.toMap
|
||||
|
||||
val source: Artifact.Source = new Artifact.Source {
|
||||
def artifacts(
|
||||
dependency: Dependency,
|
||||
project: Project,
|
||||
overrideClassifiers: Option[Seq[String]]
|
||||
) =
|
||||
if (overrideClassifiers.isEmpty)
|
||||
repo.artifacts.get(project.moduleVersion) match {
|
||||
case Some((_, f)) =>
|
||||
Seq(
|
||||
Artifact(
|
||||
f.toURI.toString,
|
||||
Map.empty,
|
||||
Map.empty,
|
||||
Attributes("jar", ""),
|
||||
changing = true,
|
||||
None
|
||||
)
|
||||
)
|
||||
case None =>
|
||||
Nil
|
||||
}
|
||||
else
|
||||
Nil
|
||||
}
|
||||
|
||||
def find[F[_]](
|
||||
module: Module,
|
||||
version: String,
|
||||
fetch: Fetch.Content[F]
|
||||
)(implicit
|
||||
F: Monad[F]
|
||||
): EitherT[F, String, (Artifact.Source, Project)] = {
|
||||
|
||||
val res = artifacts.get((module, version)) match {
|
||||
case None =>
|
||||
s"not found in internal SBT scala JARs: $module:$version".left
|
||||
case Some((p, _)) =>
|
||||
(source, p).right
|
||||
}
|
||||
|
||||
EitherT(F.point(res))
|
||||
}
|
||||
}
|
||||
|
|
@ -429,6 +429,17 @@ object Tasks {
|
|||
|
||||
val interProjectRepo = InterProjectRepository(interProjectDependencies)
|
||||
|
||||
val internalSbtScalaProvider = appConfiguration.value.provider.scalaProvider
|
||||
val internalSbtScalaJarsRepo = SbtScalaJarsRepository(
|
||||
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 ivyHome = sys.props.getOrElse(
|
||||
"ivy.home",
|
||||
new File(sys.props("user.home")).toURI.getPath + ".ivy2"
|
||||
|
|
@ -509,7 +520,7 @@ object Tasks {
|
|||
}
|
||||
}
|
||||
|
||||
val internalRepositories = Seq(globalPluginsRepo, interProjectRepo)
|
||||
val internalRepositories = Seq(globalPluginsRepo, interProjectRepo, internalSbtScalaJarsRepo)
|
||||
|
||||
val repositories =
|
||||
internalRepositories ++
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
scalaVersion := appConfiguration.value.provider.scalaProvider.version
|
||||
|
||||
coursierCachePolicies := {
|
||||
if (sys.props("os.name").startsWith("Windows"))
|
||||
coursierCachePolicies.value
|
||||
else
|
||||
Seq(coursier.CachePolicy.ForceDownload)
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
val pluginVersion = sys.props.getOrElse(
|
||||
"plugin.version",
|
||||
throw new RuntimeException(
|
||||
"""|The system property 'plugin.version' is not defined.
|
||||
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin
|
||||
)
|
||||
)
|
||||
|
||||
addSbtPlugin("io.get-coursier" % "sbt-coursier" % pluginVersion)
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
|
||||
object Main extends App {
|
||||
|
||||
val cp = new collection.mutable.ArrayBuffer[File]
|
||||
|
||||
def buildCp(loader: ClassLoader): Unit =
|
||||
if (loader != null) {
|
||||
loader match {
|
||||
case u: java.net.URLClassLoader =>
|
||||
cp ++= u.getURLs
|
||||
.map(_.toURI)
|
||||
.map(new File(_))
|
||||
case _ =>
|
||||
}
|
||||
|
||||
buildCp(loader.getParent)
|
||||
}
|
||||
|
||||
buildCp(Thread.currentThread().getContextClassLoader)
|
||||
|
||||
val sbtBase = new File(sys.props.getOrElse(
|
||||
"sbt.global.base",
|
||||
sys.props("user.home") + "/.sbt"
|
||||
))
|
||||
val prefix = new File(sbtBase, "boot").getAbsolutePath
|
||||
|
||||
def fromBootAndUnique(name: String): Unit = {
|
||||
val jars = cp.filter(_.getName.startsWith(name)).distinct
|
||||
assert(jars.length == 1, s"Found 0 or multiple JARs for $name: $jars")
|
||||
|
||||
val Seq(jar) = jars
|
||||
|
||||
assert(jar.getAbsolutePath.startsWith(prefix), s"JAR for $name ($jar) not under $prefix")
|
||||
}
|
||||
|
||||
fromBootAndUnique("scala-library")
|
||||
fromBootAndUnique("scala-reflect")
|
||||
fromBootAndUnique("scala-compiler")
|
||||
|
||||
Files.write(new File("output").toPath, "OK".getBytes("UTF-8"))
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
$ delete output
|
||||
> run
|
||||
$ exists output
|
||||
Loading…
Reference in New Issue