mirror of https://github.com/sbt/sbt.git
commit
56b6f57f96
|
|
@ -74,8 +74,7 @@ object TermDisplay {
|
|||
val start =
|
||||
actualFraction match {
|
||||
case None =>
|
||||
val elem = if (watching) "." else "?"
|
||||
s" [ $elem ] "
|
||||
" [ ] "
|
||||
case Some(frac) =>
|
||||
val elem = if (watching) "." else "#"
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ final case class Attributes(
|
|||
) {
|
||||
def publication(name: String, ext: String): Publication =
|
||||
Publication(name, `type`, ext, classifier)
|
||||
|
||||
def isEmpty: Boolean =
|
||||
`type`.isEmpty && classifier.isEmpty
|
||||
}
|
||||
|
||||
final case class Project(
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@ package core
|
|||
|
||||
import scala.annotation.tailrec
|
||||
import scala.language.higherKinds
|
||||
|
||||
import scalaz.{Monad, -\/, \/-}
|
||||
import scalaz.Scalaz.{ToFunctorOps, ToTraverseOps, vectorInstance}
|
||||
import scalaz.{-\/, Monad, \/, \/-}
|
||||
import scalaz.Scalaz.{ToFunctorOps, ToBindOps, ToTraverseOps, vectorInstance}
|
||||
|
||||
|
||||
sealed abstract class ResolutionProcess {
|
||||
|
|
@ -166,7 +165,10 @@ object ResolutionProcess {
|
|||
Missing(resolution0.missingFromCache.toSeq, resolution0, apply)
|
||||
}
|
||||
|
||||
private def fetchAll[F[_]](modVers: Seq[(Module, String)], fetch: Fetch.Metadata[F])(implicit F: Monad[F]) = {
|
||||
private[coursier] def fetchAll[F[_]](
|
||||
modVers: Seq[(Module, String)],
|
||||
fetch: Fetch.Metadata[F]
|
||||
)(implicit F: Monad[F]): F[Vector[((Module, String), Seq[String] \/ (Artifact.Source, Project))]] = {
|
||||
|
||||
def uniqueModules(modVers: Seq[(Module, String)]): Stream[Seq[(Module, String)]] = {
|
||||
|
||||
|
|
@ -191,8 +193,11 @@ object ResolutionProcess {
|
|||
|
||||
uniqueModules(modVers)
|
||||
.toVector
|
||||
.traverse(fetch)
|
||||
.map(_.flatten)
|
||||
.foldLeft(F.point(Vector.empty[((Module, String), Seq[String] \/ (Artifact.Source, Project))])) {
|
||||
(acc, l) =>
|
||||
for (v <- acc; e <- fetch(l))
|
||||
yield v ++ e
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,9 @@ final case class MavenSource(
|
|||
overrideClassifiers: Option[Seq[String]]
|
||||
): Seq[Artifact] = {
|
||||
|
||||
val packagingTpeMap = project.packagingOpt
|
||||
.filter(_ != Pom.relocatedPackaging)
|
||||
val packagingOpt = project.packagingOpt.filter(_ != Pom.relocatedPackaging)
|
||||
|
||||
val packagingTpeMap = packagingOpt
|
||||
.map { packaging =>
|
||||
(MavenSource.typeDefaultClassifier(packaging), MavenSource.typeExtension(packaging)) -> packaging
|
||||
}
|
||||
|
|
@ -67,7 +68,18 @@ final case class MavenSource(
|
|||
)
|
||||
}
|
||||
|
||||
lazy val defaultPublication = {
|
||||
lazy val defaultPublications = {
|
||||
|
||||
val packagingPublicationOpt = packagingOpt
|
||||
.filter(_ => dependency.attributes.isEmpty)
|
||||
.map { packaging =>
|
||||
Publication(
|
||||
dependency.module.name,
|
||||
packaging,
|
||||
MavenSource.typeExtension(packaging),
|
||||
MavenSource.typeDefaultClassifier(packaging)
|
||||
)
|
||||
}
|
||||
|
||||
val type0 = if (dependency.attributes.`type`.isEmpty) "jar" else dependency.attributes.`type`
|
||||
|
||||
|
|
@ -84,41 +96,41 @@ final case class MavenSource(
|
|||
MavenSource.classifierExtensionDefaultTypeOpt(classifier, ext).getOrElse(ext)
|
||||
)
|
||||
|
||||
Publication(
|
||||
dependency.module.name,
|
||||
tpe,
|
||||
ext,
|
||||
classifier
|
||||
)
|
||||
val pubs = packagingPublicationOpt.toSeq :+
|
||||
Publication(
|
||||
dependency.module.name,
|
||||
tpe,
|
||||
ext,
|
||||
classifier
|
||||
)
|
||||
|
||||
pubs.distinct
|
||||
}
|
||||
|
||||
overrideClassifiers match {
|
||||
case Some(classifiers) =>
|
||||
|
||||
classifiers
|
||||
.map { classifier =>
|
||||
if (classifier == dependency.attributes.classifier)
|
||||
defaultPublication
|
||||
else {
|
||||
val ext = "jar"
|
||||
val tpe = packagingTpeMap.getOrElse(
|
||||
(classifier, ext),
|
||||
MavenSource.classifierExtensionDefaultTypeOpt(classifier, ext).getOrElse(ext)
|
||||
)
|
||||
overrideClassifiers
|
||||
.fold(defaultPublications) { classifiers =>
|
||||
classifiers.flatMap { classifier =>
|
||||
if (classifier == dependency.attributes.classifier)
|
||||
defaultPublications
|
||||
else {
|
||||
val ext = "jar"
|
||||
val tpe = packagingTpeMap.getOrElse(
|
||||
(classifier, ext),
|
||||
MavenSource.classifierExtensionDefaultTypeOpt(classifier, ext).getOrElse(ext)
|
||||
)
|
||||
|
||||
Seq(
|
||||
Publication(
|
||||
dependency.module.name,
|
||||
tpe,
|
||||
ext,
|
||||
classifier
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
.map(artifactWithExtra)
|
||||
|
||||
case None =>
|
||||
Seq(defaultPublication).map(artifactWithExtra)
|
||||
}
|
||||
}
|
||||
}
|
||||
.map(artifactWithExtra)
|
||||
}
|
||||
|
||||
private val types = Map("sha1" -> "SHA-1", "md5" -> "MD5", "asc" -> "sig")
|
||||
|
|
@ -239,7 +251,7 @@ final case class MavenSource(
|
|||
else if (dependency.attributes.`type`.nonEmpty)
|
||||
enrichedPublications.collect {
|
||||
case p
|
||||
if p.publication.classifier.isEmpty && (
|
||||
if (p.publication.classifier.isEmpty || p.publication.classifier == MavenSource.typeDefaultClassifier(dependency.attributes.`type`)) && (
|
||||
p.publication.`type` == dependency.attributes.`type` ||
|
||||
(p.publication.ext == dependency.attributes.`type` && project.packagingOpt.toSeq.contains(p.publication.`type`)) // wow
|
||||
) =>
|
||||
|
|
@ -290,14 +302,14 @@ final case class MavenSource(
|
|||
}
|
||||
|
||||
val defaultPublications = artifactsUnknownPublications(dependency, project, overrideClassifiers)
|
||||
.map(makeOptional)
|
||||
|
||||
if (project.publications.isEmpty)
|
||||
defaultPublications
|
||||
else {
|
||||
val listedPublications = artifactsKnownPublications(dependency, project, overrideClassifiers)
|
||||
val listedUrls = listedPublications.map(_.url).toSet
|
||||
val defaultPublications0 = defaultPublications.map(makeOptional)
|
||||
val defaultPublicationsMap = defaultPublications0
|
||||
val defaultPublicationsMap = defaultPublications
|
||||
.map(a => a.url -> a)
|
||||
.toMap
|
||||
val listedPublications0 = listedPublications.map { a =>
|
||||
|
|
@ -305,7 +317,7 @@ final case class MavenSource(
|
|||
.get(a.url)
|
||||
.fold(a)(merge(a, _))
|
||||
}
|
||||
val extraPublications = defaultPublications0
|
||||
val extraPublications = defaultPublications
|
||||
.filter(a => !listedUrls(a.url))
|
||||
|
||||
listedPublications0 ++ extraPublications
|
||||
|
|
|
|||
|
|
@ -207,6 +207,8 @@ object Parse {
|
|||
).right
|
||||
else if (s.startsWith("ivy:"))
|
||||
IvyRepository.parse(s.stripPrefix("ivy:"))
|
||||
else if (s == "jitpack")
|
||||
MavenRepository("https://jitpack.io").right
|
||||
else
|
||||
MavenRepository(s).right
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,34 @@ object FromSbt {
|
|||
(module0, version, url, module.isChanging)
|
||||
}
|
||||
|
||||
def sbtClassifiersProject(
|
||||
cm: GetClassifiersModule,
|
||||
scalaVersion: String,
|
||||
scalaBinaryVersion: String
|
||||
) = {
|
||||
|
||||
val p = FromSbt.project(
|
||||
cm.id,
|
||||
cm.dependencies,
|
||||
cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.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.copy(
|
||||
dependencies = p.dependencies.map {
|
||||
case (_, d) => (cfg.name, d)
|
||||
}
|
||||
)
|
||||
case _ =>
|
||||
p
|
||||
}
|
||||
}
|
||||
|
||||
def project(
|
||||
projectID: ModuleID,
|
||||
allDependencies: Seq[ModuleID],
|
||||
|
|
|
|||
|
|
@ -550,13 +550,7 @@ object Tasks {
|
|||
|
||||
val (currentProject, fallbackDependencies, configGraphs) =
|
||||
if (sbtClassifiers) {
|
||||
val proj = FromSbt.project(
|
||||
cm.id,
|
||||
cm.dependencies,
|
||||
cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap,
|
||||
sv,
|
||||
sbv
|
||||
)
|
||||
val proj = FromSbt.sbtClassifiersProject(cm, sv, sbv)
|
||||
|
||||
val fallbackDeps = FromSbt.fallbackDependencies(
|
||||
cm.dependencies,
|
||||
|
|
@ -1112,13 +1106,7 @@ object Tasks {
|
|||
|
||||
val currentProject =
|
||||
if (sbtClassifiers)
|
||||
FromSbt.project(
|
||||
cm.id,
|
||||
cm.dependencies,
|
||||
cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap,
|
||||
sv,
|
||||
sbv
|
||||
)
|
||||
FromSbt.sbtClassifiersProject(cm, sv, sbv)
|
||||
else
|
||||
proj.copy(publications = publications)
|
||||
|
||||
|
|
@ -1155,7 +1143,7 @@ object Tasks {
|
|||
|
||||
val configs =
|
||||
if (withClassifiers && sbtClassifiers)
|
||||
cm.configurations.map(c => c.name -> Set.empty[String]).toMap
|
||||
cm.configurations.map(c => c.name -> Set(c.name)).toMap
|
||||
else
|
||||
shadedConfigOpt.fold(configs0) {
|
||||
case (baseConfig, shadedConfig) =>
|
||||
|
|
@ -1277,13 +1265,7 @@ object Tasks {
|
|||
|
||||
val currentProject =
|
||||
if (sbtClassifiers)
|
||||
FromSbt.project(
|
||||
cm.id,
|
||||
cm.dependencies,
|
||||
cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap,
|
||||
sv,
|
||||
sbv
|
||||
)
|
||||
FromSbt.sbtClassifiersProject(cm, sv, sbv)
|
||||
else
|
||||
proj.copy(publications = publications)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
import Compatibility._
|
||||
|
||||
scalaVersion := appConfiguration.value.provider.scalaProvider.version
|
||||
|
||||
lazy val updateSbtClassifiersCheck = TaskKey[Unit]("updateSbtClassifiersCheck")
|
||||
|
||||
updateSbtClassifiersCheck := {
|
||||
|
||||
val configReport = updateSbtClassifiers
|
||||
.value
|
||||
.configuration(Default)
|
||||
.getOrElse {
|
||||
throw new Exception(
|
||||
"default configuration not found in updateSbtClassifiers report"
|
||||
)
|
||||
}
|
||||
|
||||
def artifacts(org: String, name: String) = configReport
|
||||
.modules
|
||||
.collect {
|
||||
case moduleReport
|
||||
if moduleReport.module.organization == org &&
|
||||
moduleReport.module.name == name =>
|
||||
moduleReport.artifacts
|
||||
}
|
||||
.toSeq
|
||||
.flatten
|
||||
|
||||
def ensureHasArtifact(org: String, name: String) =
|
||||
assert(
|
||||
artifacts(org, name).exists(_._2.getName.endsWith("-sources.jar")),
|
||||
s"$org:$name not found"
|
||||
)
|
||||
|
||||
ensureHasArtifact("org.scala-lang", "scala-library")
|
||||
ensureHasArtifact("io.get-coursier", "coursier_" + scalaBinaryVersion.value)
|
||||
ensureHasArtifact("io.get-coursier", "sbt-coursier")
|
||||
}
|
||||
|
|
@ -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,8 @@
|
|||
object Compatibility {
|
||||
|
||||
implicit class UpdateReportOps(val rep: sbt.UpdateReport) extends AnyVal {
|
||||
def configuration(conf: sbt.Configuration) =
|
||||
rep.configuration(conf.name)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
object Compatibility
|
||||
|
|
@ -0,0 +1 @@
|
|||
> updateSbtClassifiersCheck
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package coursier.test
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
import coursier.{Fetch, Module}
|
||||
import coursier.core.ResolutionProcess
|
||||
import utest._
|
||||
|
||||
import scala.collection.JavaConverters._
|
||||
import scala.concurrent.duration.DurationInt
|
||||
import scalaz.{-\/, \/-}
|
||||
import scalaz.concurrent.Task
|
||||
|
||||
object ResolutionProcessTests extends TestSuite {
|
||||
|
||||
val tests = TestSuite {
|
||||
|
||||
'fetchAll - {
|
||||
|
||||
// check that tasks fetching different versions of the same module are spawned sequentially
|
||||
// rather than all at once
|
||||
def check(extra: Int): Unit = {
|
||||
|
||||
val mod = Module("org", "name")
|
||||
val modVers = (1 to (9 + extra))
|
||||
.map(_.toString)
|
||||
.map((mod, _))
|
||||
|
||||
val called = new ConcurrentHashMap[String, Unit]
|
||||
|
||||
val fetch: Fetch.Metadata[Task] = {
|
||||
|
||||
case Seq((`mod`, "9")) =>
|
||||
// never calls the callback
|
||||
Task.async { _ =>
|
||||
called.put("9", ())
|
||||
()
|
||||
}
|
||||
|
||||
case Seq(mv @ (`mod`, v)) =>
|
||||
Task.async { cb =>
|
||||
called.put(v, ())
|
||||
cb(\/-(Seq((mv, -\/(Seq("w/e"))))))
|
||||
}
|
||||
|
||||
case _ => sys.error(s"Cannot happen ($modVers)")
|
||||
}
|
||||
|
||||
val res = ResolutionProcess.fetchAll(modVers, fetch)
|
||||
.timed(1.second)
|
||||
.attempt
|
||||
.unsafePerformSync
|
||||
|
||||
// must have timed out
|
||||
assert(res.swap.exists[Throwable] { case _: java.util.concurrent.TimeoutException => true; case _ => false })
|
||||
|
||||
val called0 = called.asScala.iterator.map(_._1).toSet
|
||||
val expectedCalled = (0 to extra)
|
||||
.map(9 + _)
|
||||
.map(_.toString)
|
||||
.toSet
|
||||
assert(called0 == expectedCalled)
|
||||
}
|
||||
|
||||
* - check(0)
|
||||
* - check(1)
|
||||
* - check(3)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 93eccec4ffd1719586b6f1e1dddefcbea6722e7d
|
||||
Subproject commit 6b2578a25220930e60b505b90e636092757d6397
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
android.arch.core:core:1.0.0-alpha3:compile
|
||||
android.arch.lifecycle:common:1.0.0-alpha3:compile
|
||||
android.arch.lifecycle:extensions:1.0.0-alpha3:compile
|
||||
android.arch.lifecycle:runtime:1.0.0-alpha3:compile
|
||||
com.android.support:support-annotations:25.3.1:compile
|
||||
com.android.support:support-compat:25.3.1:compile
|
||||
com.android.support:support-core-ui:25.3.1:compile
|
||||
com.android.support:support-core-utils:25.3.1:compile
|
||||
com.android.support:support-fragment:25.3.1:compile
|
||||
com.android.support:support-media-compat:25.3.1:compile
|
||||
|
|
@ -569,6 +569,7 @@ abstract class CentralTests extends TestSuite {
|
|||
|
||||
val zookeeperTestArtifact = zookeeperTestArtifacts.head
|
||||
|
||||
assert(!isActualCentral || !zookeeperTestArtifact.isOptional)
|
||||
assert(zookeeperTestArtifact.attributes.`type` == "test-jar")
|
||||
assert(zookeeperTestArtifact.attributes.classifier == "tests")
|
||||
zookeeperTestArtifact.url.endsWith("-tests.jar")
|
||||
|
|
@ -822,6 +823,33 @@ abstract class CentralTests extends TestSuite {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
'packagingTpe - {
|
||||
val mod = Module("android.arch.lifecycle", "extensions")
|
||||
val ver = "1.0.0-alpha3"
|
||||
|
||||
val extraRepo = MavenRepository("https://maven.google.com")
|
||||
|
||||
* - resolutionCheck(mod, ver, extraRepos = Seq(extraRepo))
|
||||
|
||||
* - withArtifacts(mod, ver, "*", extraRepos = Seq(extraRepo), transitive = true) { artifacts =>
|
||||
val urls = artifacts.map(_.url).toSet
|
||||
val expectedUrls = Set(
|
||||
"https://maven.google.com/com/android/support/support-fragment/25.3.1/support-fragment-25.3.1.aar",
|
||||
"https://maven.google.com/android/arch/core/core/1.0.0-alpha3/core-1.0.0-alpha3.aar",
|
||||
"https://maven.google.com/android/arch/lifecycle/runtime/1.0.0-alpha3/runtime-1.0.0-alpha3.aar",
|
||||
"https://maven.google.com/android/arch/lifecycle/extensions/1.0.0-alpha3/extensions-1.0.0-alpha3.aar",
|
||||
"https://maven.google.com/com/android/support/support-compat/25.3.1/support-compat-25.3.1.aar",
|
||||
"https://maven.google.com/com/android/support/support-media-compat/25.3.1/support-media-compat-25.3.1.aar",
|
||||
"https://maven.google.com/com/android/support/support-core-ui/25.3.1/support-core-ui-25.3.1.aar",
|
||||
"https://maven.google.com/com/android/support/support-core-utils/25.3.1/support-core-utils-25.3.1.aar",
|
||||
"https://maven.google.com/com/android/support/support-annotations/25.3.1/support-annotations-25.3.1.jar",
|
||||
"https://maven.google.com/android/arch/lifecycle/common/1.0.0-alpha3/common-1.0.0-alpha3.jar"
|
||||
)
|
||||
|
||||
assert(expectedUrls.forall(urls))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,5 +42,10 @@ object ParseTests extends TestSuite {
|
|||
val res = Parse.repository("typesafe:releases")
|
||||
assert(res.exists(isMavenRepo))
|
||||
}
|
||||
|
||||
"jitpack" - {
|
||||
val res = Parse.repository("jitpack")
|
||||
assert(res.exists(isMavenRepo))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue