mirror of https://github.com/sbt/sbt.git
Better handling of artifacts from Maven repos
Doesn't seem to break things
This commit is contained in:
parent
5559c5ce01
commit
6b89af3924
|
|
@ -37,6 +37,7 @@ function isMasterOrDevelop() {
|
|||
-- \
|
||||
-d tests/jvm/src/test/resources/test-repo/http/abc.com \
|
||||
-u user -P pass -r realm \
|
||||
--list-pages \
|
||||
-v &
|
||||
|
||||
# TODO Add coverage once https://github.com/scoverage/sbt-scoverage/issues/111 is fixed
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ build_script:
|
|||
- sbt ++2.10.6 clean compile
|
||||
- sbt ++2.10.6 coreJVM/publishLocal cache/publishLocal # to make the scripted tests happy
|
||||
test_script:
|
||||
- ps: Start-Job { & java -jar -noverify C:\projects\coursier\coursier launch -r http://dl.bintray.com/scalaz/releases io.get-coursier:http-server-java7_2.11:1.0.0-SNAPSHOT -- -d /C:/projects/coursier/tests/jvm/src/test/resources/test-repo/http/abc.com -u user -P pass -r realm -v }
|
||||
- ps: Start-Job { & java -jar -noverify C:\projects\coursier\coursier launch -r http://dl.bintray.com/scalaz/releases io.get-coursier:http-server-java7_2.11:1.0.0-SNAPSHOT -- -d /C:/projects/coursier/tests/jvm/src/test/resources/test-repo/http/abc.com -u user -P pass -r realm --list-pages -v }
|
||||
- sbt ++2.12.1 testsJVM/test testsJVM/it:test # Would node be around for testsJS/test?
|
||||
- sbt ++2.11.8 testsJVM/test testsJVM/it:test
|
||||
- sbt ++2.10.6 testsJVM/test testsJVM/it:test sbt-coursier/scripted sbt-coursier/publishLocal sbt-shading/scripted
|
||||
|
|
|
|||
17
build.sbt
17
build.sbt
|
|
@ -20,6 +20,23 @@ lazy val core = crossProject
|
|||
import com.typesafe.tools.mima.core._
|
||||
|
||||
Seq(
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.maven.MavenRepository.defaultPublications"),
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.maven.MavenRepository.defaultPackaging"),
|
||||
ProblemFilters.exclude[MissingClassProblem]("coursier.maven.MavenSource$DocSourcesArtifactExtensions"),
|
||||
ProblemFilters.exclude[MissingTypesProblem]("coursier.core.Project$"),
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.core.Project.apply"),
|
||||
ProblemFilters.exclude[IncompatibleResultTypeProblem]("coursier.core.Project.copy$default$13"),
|
||||
ProblemFilters.exclude[IncompatibleResultTypeProblem]("coursier.core.Project.copy$default$12"),
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.core.Project.copy"),
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.core.Project.this"),
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.maven.MavenRepository.copy$default$5"),
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.maven.MavenRepository.packagingBlacklist"),
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.maven.MavenRepository.copy"),
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.maven.MavenRepository.this"),
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.maven.MavenRepository.apply$default$5"),
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.maven.MavenRepository.ignorePackaging"),
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.maven.MavenRepository.<init>$default$5"),
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.maven.MavenRepository.apply"),
|
||||
ProblemFilters.exclude[FinalClassProblem]("coursier.core.Activation$Os"),
|
||||
ProblemFilters.exclude[FinalClassProblem]("coursier.core.Version"),
|
||||
ProblemFilters.exclude[FinalClassProblem]("coursier.core.Authentication"),
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ final case class Project(
|
|||
profiles: Seq[Profile],
|
||||
versions: Option[Versions],
|
||||
snapshotVersioning: Option[SnapshotVersioning],
|
||||
packagingOpt: Option[String],
|
||||
|
||||
/**
|
||||
* Optional exact version used to get this project metadata.
|
||||
* May not match `version` for projects having a wrong version in their metadata.
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ object Resolution {
|
|||
type Key = (String, String, String)
|
||||
|
||||
def key(dep: Dependency): Key =
|
||||
(dep.module.organization, dep.module.name, dep.attributes.`type`)
|
||||
(dep.module.organization, dep.module.name, if (dep.attributes.`type`.isEmpty) "jar" else dep.attributes.`type`)
|
||||
|
||||
def add(
|
||||
dict: Map[Key, (String, Dependency)],
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ object IvyXml {
|
|||
version,
|
||||
toConf,
|
||||
allConfsExcludes ++ excludes.getOrElse(fromConf, Set.empty),
|
||||
Attributes("jar", ""), // should come from possible artifact nodes
|
||||
Attributes("", ""), // should come from possible artifact nodes
|
||||
optional = false,
|
||||
transitive = transitive
|
||||
)
|
||||
|
|
@ -158,6 +158,7 @@ object IvyXml {
|
|||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
if (publicationsOpt.isEmpty)
|
||||
// no publications node -> default JAR artifact
|
||||
Seq("*" -> Publication(module.name, "jar", "jar", ""))
|
||||
|
|
|
|||
|
|
@ -45,19 +45,6 @@ object MavenRepository {
|
|||
"test" -> Seq("runtime")
|
||||
)
|
||||
|
||||
val defaultPackaging = "jar"
|
||||
|
||||
def defaultPublications(moduleName: String, packaging: String) = Seq(
|
||||
"compile" -> Publication(
|
||||
moduleName,
|
||||
packaging,
|
||||
MavenSource.typeExtension(packaging),
|
||||
MavenSource.typeDefaultClassifier(packaging)
|
||||
),
|
||||
"docs" -> Publication(moduleName, "doc", "jar", "javadoc"),
|
||||
"sources" -> Publication(moduleName, "src", "jar", "sources")
|
||||
)
|
||||
|
||||
def dirModuleName(module: Module, sbtAttrStub: Boolean): String =
|
||||
if (sbtAttrStub) {
|
||||
var name = module.name
|
||||
|
|
@ -69,10 +56,6 @@ object MavenRepository {
|
|||
} else
|
||||
module.name
|
||||
|
||||
val ignorePackaging = Set(
|
||||
Module("org.apache.zookeeper", "zookeeper", Map.empty)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
final case class MavenRepository(
|
||||
|
|
@ -80,8 +63,7 @@ final case class MavenRepository(
|
|||
changing: Option[Boolean] = None,
|
||||
/** Hackish hack for sbt plugins mainly - what this does really sucks */
|
||||
sbtAttrStub: Boolean = false,
|
||||
authentication: Option[Authentication] = None,
|
||||
packagingBlacklist: Set[Module] = MavenRepository.ignorePackaging
|
||||
authentication: Option[Authentication] = None
|
||||
) extends Repository {
|
||||
|
||||
import Repository._
|
||||
|
|
@ -262,30 +244,89 @@ final case class MavenRepository(
|
|||
F: Monad[F]
|
||||
): EitherT[F, String, Project] = {
|
||||
|
||||
fetch(projectArtifact(module, version, versioningValue)).flatMap { str =>
|
||||
EitherT {
|
||||
F.point[String \/ Project] {
|
||||
for {
|
||||
xml <- \/.fromEither(compatibility.xmlParse(str))
|
||||
_ <- if (xml.label == "project") \/-(()) else -\/("Project definition not found")
|
||||
proj <- Pom.project(xml)
|
||||
} yield {
|
||||
val packagingOpt =
|
||||
if (packagingBlacklist(module))
|
||||
None
|
||||
else
|
||||
Pom.packagingOpt(xml)
|
||||
def parseRawPom(str: String) =
|
||||
for {
|
||||
xml <- \/.fromEither(compatibility.xmlParse(str))
|
||||
_ <- if (xml.label == "project") \/-(()) else -\/("Project definition not found")
|
||||
proj <- Pom.project(xml)
|
||||
} yield proj
|
||||
|
||||
proj.copy(
|
||||
configurations = defaultConfigurations,
|
||||
publications = defaultPublications(
|
||||
module.name,
|
||||
packagingOpt.getOrElse(defaultPackaging)
|
||||
)
|
||||
)
|
||||
}
|
||||
def artifactFor(url: String) =
|
||||
Artifact(
|
||||
url,
|
||||
Map.empty,
|
||||
Map.empty,
|
||||
Attributes("", ""),
|
||||
changing = true,
|
||||
authentication
|
||||
)
|
||||
|
||||
def isArtifact(fileName: String, prefix: String): Option[(String, String)] =
|
||||
// TODO There should be a regex for that...
|
||||
if (fileName.startsWith(prefix)) {
|
||||
val end = fileName.stripPrefix(prefix)
|
||||
val idx = end.lastIndexOf('.')
|
||||
if (idx >= 0) {
|
||||
val ext = end.drop(idx + 1)
|
||||
val rem = end.take(idx)
|
||||
if (rem.isEmpty)
|
||||
Some(("", ext))
|
||||
else if (rem.startsWith("-"))
|
||||
Some((rem.drop(1), ext))
|
||||
else
|
||||
None
|
||||
} else
|
||||
None
|
||||
} else
|
||||
None
|
||||
|
||||
|
||||
val listFilesUrl = urlFor(modulePath(module, version)) + "/"
|
||||
|
||||
for {
|
||||
str <- fetch(projectArtifact(module, version, versioningValue))
|
||||
rawListFilesPage <- fetch(artifactFor(listFilesUrl))
|
||||
proj <- EitherT(F.point[String \/ Project](parseRawPom(str)))
|
||||
} yield {
|
||||
|
||||
val files = coursier.core.compatibility.listWebPageFiles(listFilesUrl, rawListFilesPage)
|
||||
|
||||
val versioning = proj
|
||||
.snapshotVersioning
|
||||
.flatMap(versioning =>
|
||||
mavenVersioning(versioning, "", "")
|
||||
)
|
||||
|
||||
val prefix = s"${module.name}-${versioning.getOrElse(version)}"
|
||||
|
||||
val packagingTpeMap = proj.packagingOpt
|
||||
.map { packaging =>
|
||||
(MavenSource.typeDefaultClassifier(packaging), MavenSource.typeExtension(packaging)) -> packaging
|
||||
}
|
||||
}
|
||||
.toMap
|
||||
|
||||
val foundPublications = files
|
||||
.flatMap(isArtifact(_, prefix))
|
||||
.map {
|
||||
case (classifier, ext) =>
|
||||
val tpe = packagingTpeMap.getOrElse(
|
||||
(classifier, ext),
|
||||
MavenSource.classifierExtensionDefaultTypeOpt(classifier, ext).getOrElse(ext)
|
||||
)
|
||||
val config = MavenSource.typeDefaultConfig(tpe).getOrElse("compile")
|
||||
config -> Publication(
|
||||
module.name,
|
||||
tpe,
|
||||
ext,
|
||||
classifier
|
||||
)
|
||||
}
|
||||
|
||||
proj.copy(
|
||||
actualVersionOpt = Some(version),
|
||||
configurations = defaultConfigurations,
|
||||
publications = foundPublications
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,34 +13,6 @@ final case class MavenSource(
|
|||
import Repository._
|
||||
import MavenRepository._
|
||||
|
||||
private implicit class DocSourcesArtifactExtensions(val underlying: Artifact) {
|
||||
def withJavadocSources: Artifact = {
|
||||
val base = underlying.url.stripSuffix(".jar")
|
||||
underlying.copy(extra = underlying.extra ++ Seq(
|
||||
"sources" -> Artifact(
|
||||
base + "-sources.jar",
|
||||
Map.empty,
|
||||
Map.empty,
|
||||
Attributes("jar", "src"), // Are these the right attributes?
|
||||
changing = underlying.changing,
|
||||
authentication = authentication
|
||||
)
|
||||
.withDefaultChecksums
|
||||
.withDefaultSignature,
|
||||
"javadoc" -> Artifact(
|
||||
base + "-javadoc.jar",
|
||||
Map.empty,
|
||||
Map.empty,
|
||||
Attributes("jar", "javadoc"), // Same comment as above
|
||||
changing = underlying.changing,
|
||||
authentication = authentication
|
||||
)
|
||||
.withDefaultChecksums
|
||||
.withDefaultSignature
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
def artifacts(
|
||||
dependency: Dependency,
|
||||
project: Project,
|
||||
|
|
@ -73,9 +45,9 @@ final case class MavenSource(
|
|||
)
|
||||
.withDefaultChecksums
|
||||
|
||||
if (publication.ext == "jar") {
|
||||
if (publication.ext == "jar")
|
||||
// TODO Get available signature / checksums from directory listing
|
||||
artifact = artifact.withDefaultSignature
|
||||
}
|
||||
|
||||
artifact
|
||||
}
|
||||
|
|
@ -92,68 +64,33 @@ final case class MavenSource(
|
|||
val publications0 = overrideClassifiers match {
|
||||
case Some(classifiers) =>
|
||||
val classifiersSet = classifiers.toSet
|
||||
val publications = project.publications.collect {
|
||||
|
||||
project.publications.collect {
|
||||
case (_, p) if classifiersSet(p.classifier) =>
|
||||
p
|
||||
}
|
||||
|
||||
// Unlike with Ivy metadata, Maven POMs don't list the available publications (~artifacts)
|
||||
// so we give a chance to any classifier we're given by returning some publications
|
||||
// no matter what, even if we're unsure they're available.
|
||||
if (publications.isEmpty)
|
||||
classifiers.map { classifier =>
|
||||
Publication(
|
||||
dependency.module.name,
|
||||
"jar",
|
||||
"jar",
|
||||
classifier
|
||||
)
|
||||
}
|
||||
else
|
||||
publications
|
||||
|
||||
case None =>
|
||||
|
||||
val publications =
|
||||
if (dependency.attributes.classifier.nonEmpty)
|
||||
// FIXME We're ignoring dependency.attributes.`type` in this case
|
||||
project.publications.collect {
|
||||
case (_, p) if p.classifier == dependency.attributes.classifier =>
|
||||
p
|
||||
}
|
||||
else if (dependency.attributes.`type`.nonEmpty)
|
||||
project.publications.collect {
|
||||
case (_, p) if p.`type` == dependency.attributes.`type` =>
|
||||
p
|
||||
}
|
||||
else
|
||||
project.publications.collect {
|
||||
case (_, p) if p.classifier.isEmpty =>
|
||||
p
|
||||
}
|
||||
|
||||
// See comment above
|
||||
if (publications.isEmpty) {
|
||||
val type0 = if (dependency.attributes.`type`.isEmpty) "jar" else dependency.attributes.`type`
|
||||
|
||||
val extension = MavenSource.typeExtension(type0)
|
||||
|
||||
val classifier =
|
||||
if (dependency.attributes.classifier.isEmpty)
|
||||
MavenSource.typeDefaultClassifier(type0)
|
||||
else
|
||||
dependency.attributes.classifier
|
||||
|
||||
Seq(
|
||||
Publication(
|
||||
dependency.module.name,
|
||||
type0,
|
||||
extension,
|
||||
classifier
|
||||
)
|
||||
)
|
||||
} else
|
||||
publications
|
||||
if (dependency.attributes.classifier.nonEmpty)
|
||||
// FIXME We're ignoring dependency.attributes.`type` in this case
|
||||
project.publications.collect {
|
||||
case (_, p) if p.classifier == dependency.attributes.classifier =>
|
||||
p
|
||||
}
|
||||
else if (dependency.attributes.`type`.nonEmpty)
|
||||
project.publications.collect {
|
||||
case (_, p)
|
||||
if p.`type` == dependency.attributes.`type` ||
|
||||
p.ext == dependency.attributes.`type` // wow
|
||||
=>
|
||||
p
|
||||
}
|
||||
else
|
||||
project.publications.collect {
|
||||
case (_, p) if p.classifier.isEmpty =>
|
||||
p
|
||||
}
|
||||
}
|
||||
|
||||
publications0.map(artifactWithExtra)
|
||||
|
|
@ -194,4 +131,22 @@ object MavenSource {
|
|||
def typeDefaultClassifier(`type`: String): String =
|
||||
typeDefaultClassifierOpt(`type`).getOrElse("")
|
||||
|
||||
}
|
||||
val classifierExtensionDefaultTypes: Map[(String, String), String] = Map(
|
||||
("tests", "jar") -> "test-jar",
|
||||
("javadoc", "jar") -> "doc",
|
||||
("sources", "jar") -> "src"
|
||||
// don't know much about "client" classifier, not including it here
|
||||
)
|
||||
|
||||
def classifierExtensionDefaultTypeOpt(classifier: String, ext: String): Option[String] =
|
||||
classifierExtensionDefaultTypes.get((classifier, ext))
|
||||
|
||||
val typeDefaultConfigs: Map[String, String] = Map(
|
||||
"doc" -> "docs",
|
||||
"src" -> "sources"
|
||||
)
|
||||
|
||||
def typeDefaultConfig(`type`: String): Option[String] =
|
||||
typeDefaultConfigs.get(`type`)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,6 @@ object Pom {
|
|||
private def readVersion(node: Node) =
|
||||
text(node, "version", "Version").getOrElse("").trim
|
||||
|
||||
private val defaultType = "jar"
|
||||
private val defaultClassifier = ""
|
||||
|
||||
def dependency(node: Node): String \/ (String, Dependency) = {
|
||||
for {
|
||||
mod <- module(node)
|
||||
|
|
@ -52,7 +49,7 @@ object Pom {
|
|||
version0,
|
||||
"",
|
||||
exclusions.map(mod => (mod.organization, mod.name)).toSet,
|
||||
Attributes(typeOpt getOrElse defaultType, classifierOpt getOrElse defaultClassifier),
|
||||
Attributes(typeOpt.getOrElse(""), classifierOpt.getOrElse("")),
|
||||
optional,
|
||||
transitive = true
|
||||
)
|
||||
|
|
@ -253,6 +250,7 @@ object Pom {
|
|||
profiles,
|
||||
None,
|
||||
None,
|
||||
packagingOpt(pom),
|
||||
None,
|
||||
Nil,
|
||||
Info(
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ package object coursier {
|
|||
version: String,
|
||||
// Substituted by Resolver with its own default configuration (compile)
|
||||
configuration: String = "",
|
||||
attributes: Attributes = Attributes("jar"),
|
||||
attributes: Attributes = Attributes(),
|
||||
exclusions: Set[(String, String)] = Set.empty,
|
||||
optional: Boolean = false,
|
||||
transitive: Boolean = true
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ import java.net.NetworkInterface
|
|||
import java.nio.channels.{ FileLock, OverlappingFileLockException }
|
||||
|
||||
import org.http4s.dsl._
|
||||
import org.http4s.headers.Authorization
|
||||
import org.http4s.headers.{ Authorization, `Content-Type` }
|
||||
import org.http4s.server.HttpService
|
||||
import org.http4s.server.blaze.BlazeBuilder
|
||||
import org.http4s.{ BasicCredentials, Challenge, EmptyBody, Request, Response }
|
||||
import org.http4s.{ BasicCredentials, Challenge, EmptyBody, MediaType, Request, Response }
|
||||
|
||||
import caseapp._
|
||||
|
||||
|
|
@ -45,7 +45,10 @@ final case class HttpServerApp(
|
|||
password: String,
|
||||
@ExtraName("r")
|
||||
@ValueDescription("realm")
|
||||
realm: String
|
||||
realm: String,
|
||||
@ExtraName("l")
|
||||
@HelpMessage("Generate content listing pages for directories")
|
||||
listPages: Boolean
|
||||
) extends App {
|
||||
|
||||
val baseDir = new File(if (directory.isEmpty) "." else directory)
|
||||
|
|
@ -171,16 +174,65 @@ final case class HttpServerApp(
|
|||
Locked()
|
||||
}
|
||||
|
||||
def isDirectory(f: File): Task[Option[Boolean]] =
|
||||
Task {
|
||||
if (f.isDirectory)
|
||||
Some(true)
|
||||
else if (f.isFile)
|
||||
Some(false)
|
||||
else
|
||||
None
|
||||
}
|
||||
|
||||
def directoryListingPage(dir: File, title: String): Task[String] =
|
||||
Task {
|
||||
val entries = dir
|
||||
.listFiles()
|
||||
.flatMap { f =>
|
||||
def name = f.getName
|
||||
if (f.isDirectory)
|
||||
Seq(name + "/")
|
||||
else if (f.isFile)
|
||||
Seq(name)
|
||||
else
|
||||
Nil
|
||||
}
|
||||
|
||||
// meh escaping
|
||||
// TODO Use to scalatags to generate that
|
||||
s"""<!DOCTYPE html>
|
||||
|<html>
|
||||
|<head>
|
||||
|<title>$title</title>
|
||||
|</head>
|
||||
|<body>
|
||||
|<ul>
|
||||
|${entries.map(e => " <li><a href=\"" + e + "\">" + e + "</a></li>").mkString("\n")}
|
||||
|</ul>
|
||||
|</body>
|
||||
|</html>
|
||||
""".stripMargin
|
||||
}
|
||||
|
||||
def getService = authenticated {
|
||||
case (method @ (GET | HEAD)) -> path =>
|
||||
if (verbosityLevel >= 1)
|
||||
Console.err.println(s"${method.name} $path")
|
||||
|
||||
val f = new File(baseDir, path.toList.mkString("/"))
|
||||
val resp = if (f.exists())
|
||||
Ok(f)
|
||||
else
|
||||
NotFound()
|
||||
val relPath = path.toList.mkString("/")
|
||||
val f = new File(baseDir, relPath)
|
||||
val resp =
|
||||
for {
|
||||
isDirOpt <- isDirectory(f)
|
||||
resp <- isDirOpt match {
|
||||
case Some(true) if listPages =>
|
||||
directoryListingPage(f, relPath).flatMap(page =>
|
||||
Ok(page).withContentType(Some(`Content-Type`(MediaType.`text/html`)))
|
||||
)
|
||||
case Some(false) => Ok(f)
|
||||
case _ => NotFound()
|
||||
}
|
||||
} yield resp
|
||||
|
||||
method match {
|
||||
case HEAD =>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ object CoursierPlugin extends AutoPlugin {
|
|||
object autoImport {
|
||||
val coursierParallelDownloads = Keys.coursierParallelDownloads
|
||||
val coursierMaxIterations = Keys.coursierMaxIterations
|
||||
val coursierDefaultArtifactType = Keys.coursierDefaultArtifactType
|
||||
val coursierChecksums = Keys.coursierChecksums
|
||||
val coursierArtifactsChecksums = Keys.coursierArtifactsChecksums
|
||||
val coursierCachePolicies = Keys.coursierCachePolicies
|
||||
|
|
@ -76,7 +75,6 @@ object CoursierPlugin extends AutoPlugin {
|
|||
) = Seq(
|
||||
coursierParallelDownloads := 6,
|
||||
coursierMaxIterations := 50,
|
||||
coursierDefaultArtifactType := "",
|
||||
coursierChecksums := Seq(Some("SHA-1"), None),
|
||||
coursierArtifactsChecksums := Seq(None),
|
||||
coursierCachePolicies := CachePolicy.default,
|
||||
|
|
|
|||
|
|
@ -78,8 +78,10 @@ final case class FallbackDependenciesRepository(
|
|||
fallbacks.get(dependency.moduleVersion) match {
|
||||
case None => Nil
|
||||
case Some((url, changing)) =>
|
||||
val url0 = url.toString
|
||||
val ext = url0.substring(url0.lastIndexOf('.') + 1)
|
||||
Seq(
|
||||
Artifact(url.toString, Map.empty, Map.empty, Attributes("jar", ""), changing, None)
|
||||
Artifact(url0, Map.empty, Map.empty, Attributes(ext, ""), changing, None)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -121,6 +123,7 @@ final case class FallbackDependenciesRepository(
|
|||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Nil,
|
||||
Info.empty
|
||||
)
|
||||
|
|
|
|||
|
|
@ -53,8 +53,7 @@ object FromSbt {
|
|||
def dependencies(
|
||||
module: ModuleID,
|
||||
scalaVersion: String,
|
||||
scalaBinaryVersion: String,
|
||||
defaultArtifactType: String
|
||||
scalaBinaryVersion: String
|
||||
): Seq[(String, Dependency)] = {
|
||||
|
||||
// TODO Warn about unsupported properties in `module`
|
||||
|
|
@ -76,10 +75,10 @@ object FromSbt {
|
|||
|
||||
val attributes =
|
||||
if (module.explicitArtifacts.isEmpty)
|
||||
Seq(Attributes(defaultArtifactType, ""))
|
||||
Seq(Attributes("", ""))
|
||||
else
|
||||
module.explicitArtifacts.map { a =>
|
||||
Attributes(`type` = a.extension, classifier = a.classifier.getOrElse(""))
|
||||
Attributes(`type` = a.`type`, classifier = a.classifier.getOrElse(""))
|
||||
}
|
||||
|
||||
for {
|
||||
|
|
@ -107,15 +106,14 @@ object FromSbt {
|
|||
allDependencies: Seq[ModuleID],
|
||||
ivyConfigurations: Map[String, Seq[String]],
|
||||
scalaVersion: String,
|
||||
scalaBinaryVersion: String,
|
||||
defaultArtifactType: String
|
||||
scalaBinaryVersion: String
|
||||
): Project = {
|
||||
|
||||
// FIXME Ignored for now - easy to support though
|
||||
// val sbtDepOverrides = dependencyOverrides.value
|
||||
// val sbtExclusions = excludeDependencies.value
|
||||
|
||||
val deps = allDependencies.flatMap(dependencies(_, scalaVersion, scalaBinaryVersion, defaultArtifactType))
|
||||
val deps = allDependencies.flatMap(dependencies(_, scalaVersion, scalaBinaryVersion))
|
||||
|
||||
Project(
|
||||
Module(
|
||||
|
|
@ -133,6 +131,7 @@ object FromSbt {
|
|||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Nil,
|
||||
Info.empty
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import scalaz.\/
|
|||
object Keys {
|
||||
val coursierParallelDownloads = SettingKey[Int]("coursier-parallel-downloads")
|
||||
val coursierMaxIterations = SettingKey[Int]("coursier-max-iterations")
|
||||
val coursierDefaultArtifactType = SettingKey[String]("coursier-default-artifact-type")
|
||||
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")
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ object Tasks {
|
|||
lazy val projId = projectID.in(projectRef).get(state)
|
||||
lazy val sv = scalaVersion.in(projectRef).get(state)
|
||||
lazy val sbv = scalaBinaryVersion.in(projectRef).get(state)
|
||||
lazy val defaultArtifactType = coursierDefaultArtifactType.in(projectRef).get(state)
|
||||
|
||||
for {
|
||||
allDependencies <- allDependenciesTask
|
||||
|
|
@ -129,8 +128,7 @@ object Tasks {
|
|||
allDependencies,
|
||||
configurations.map { cfg => cfg.name -> cfg.extendsConfigs.map(_.name) }.toMap,
|
||||
sv,
|
||||
sbv,
|
||||
defaultArtifactType
|
||||
sbv
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -333,15 +331,13 @@ object Tasks {
|
|||
if (sbtClassifiers) {
|
||||
val sv = scalaVersion.value
|
||||
val sbv = scalaBinaryVersion.value
|
||||
val defaultArtifactType = coursierDefaultArtifactType.value
|
||||
|
||||
val proj = FromSbt.project(
|
||||
cm.id,
|
||||
cm.modules,
|
||||
cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap,
|
||||
sv,
|
||||
sbv,
|
||||
defaultArtifactType
|
||||
sbv
|
||||
)
|
||||
|
||||
val fallbackDeps = FromSbt.fallbackDependencies(
|
||||
|
|
@ -828,15 +824,13 @@ object Tasks {
|
|||
if (sbtClassifiers) {
|
||||
val sv = scalaVersion.value
|
||||
val sbv = scalaBinaryVersion.value
|
||||
val defaultArtifactType = coursierDefaultArtifactType.value
|
||||
|
||||
FromSbt.project(
|
||||
cm.id,
|
||||
cm.modules,
|
||||
cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap,
|
||||
sv,
|
||||
sbv,
|
||||
defaultArtifactType
|
||||
sbv
|
||||
)
|
||||
} else {
|
||||
val proj = coursierProject.value
|
||||
|
|
@ -977,15 +971,13 @@ object Tasks {
|
|||
val cm = coursierSbtClassifiersModule.value
|
||||
val sv = scalaVersion.value
|
||||
val sbv = scalaBinaryVersion.value
|
||||
val defaultArtifactType = coursierDefaultArtifactType.value
|
||||
|
||||
FromSbt.project(
|
||||
cm.id,
|
||||
cm.modules,
|
||||
cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap,
|
||||
sv,
|
||||
sbv,
|
||||
defaultArtifactType
|
||||
sbv
|
||||
)
|
||||
} else {
|
||||
val proj = coursierProject.value
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ object Shading {
|
|||
res: Resolution,
|
||||
configs: Map[String, Set[String]],
|
||||
artifactFilesOrErrors: Map[Artifact, FileError \/ File],
|
||||
classpathTypes: Set[String],
|
||||
shadingNamespace: String,
|
||||
baseConfig: String,
|
||||
shadedConf: String,
|
||||
|
|
@ -97,7 +98,12 @@ object Shading {
|
|||
)
|
||||
}
|
||||
|
||||
val dependencyArtifacts = res.dependencyArtifacts.toMap
|
||||
val dependencyArtifacts = res.dependencyArtifacts
|
||||
.filter { case (_, a) => classpathTypes(a.`type`) }
|
||||
.groupBy(_._1)
|
||||
.mapValues(_.map(_._2))
|
||||
.iterator
|
||||
.toMap
|
||||
|
||||
val artifactFilesOrErrors0 = artifactFilesOrErrors
|
||||
.collect {
|
||||
|
|
@ -121,6 +127,7 @@ object Shading {
|
|||
.dependencies
|
||||
.toSeq
|
||||
.flatMap(dependencyArtifacts.get)
|
||||
.flatten
|
||||
.map(_.url)
|
||||
.flatMap(artifactFilesOrErrors0.get)
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ object ShadingPlugin extends AutoPlugin {
|
|||
coursierResolution.in(baseSbtConfiguration).value,
|
||||
coursierConfigurations.in(baseSbtConfiguration).value,
|
||||
Keys.coursierArtifacts.in(baseSbtConfiguration).value,
|
||||
classpathTypes.value,
|
||||
shadingNamespace.?.value.getOrElse {
|
||||
throw new NoSuchElementException("shadingNamespace key not set")
|
||||
},
|
||||
|
|
|
|||
|
|
@ -99,11 +99,12 @@ object CentralTests extends TestSuite {
|
|||
module: Module,
|
||||
version: String,
|
||||
artifactType: String,
|
||||
attributes: Attributes = Attributes(),
|
||||
extraRepo: Option[Repository] = None
|
||||
)(
|
||||
f: Artifact => T
|
||||
): Future[T] =
|
||||
withArtifacts(module, version, artifactType, extraRepo) {
|
||||
withArtifacts(module, version, artifactType, attributes, extraRepo) {
|
||||
case Seq(artifact) =>
|
||||
f(artifact)
|
||||
case other =>
|
||||
|
|
@ -117,11 +118,12 @@ object CentralTests extends TestSuite {
|
|||
module: Module,
|
||||
version: String,
|
||||
artifactType: String,
|
||||
attributes: Attributes = Attributes(),
|
||||
extraRepo: Option[Repository] = None
|
||||
)(
|
||||
f: Seq[Artifact] => T
|
||||
): Future[T] = {
|
||||
val dep = Dependency(module, version, transitive = false, attributes = Attributes())
|
||||
val dep = Dependency(module, version, transitive = false, attributes = attributes)
|
||||
withArtifacts(dep, artifactType, extraRepo)(f)
|
||||
}
|
||||
|
||||
|
|
@ -145,8 +147,14 @@ object CentralTests extends TestSuite {
|
|||
f(artifacts)
|
||||
}
|
||||
|
||||
def ensureHasArtifactWithExtension(module: Module, version: String, artifactType: String, extension: String): Future[Unit] =
|
||||
withArtifact(module, version, artifactType) { artifact =>
|
||||
def ensureHasArtifactWithExtension(
|
||||
module: Module,
|
||||
version: String,
|
||||
artifactType: String,
|
||||
extension: String,
|
||||
attributes: Attributes = Attributes()
|
||||
): Future[Unit] =
|
||||
withArtifact(module, version, artifactType, attributes = attributes) { artifact =>
|
||||
assert(artifact.url.endsWith("." + extension))
|
||||
}
|
||||
|
||||
|
|
@ -161,8 +169,8 @@ object CentralTests extends TestSuite {
|
|||
rootDependencies = Set(dep),
|
||||
dependencies = Set(
|
||||
dep.withCompileScope,
|
||||
Dependency(Module("ch.qos.logback", "logback-core"), "1.1.3").withCompileScope.withJarAttributeType,
|
||||
Dependency(Module("org.slf4j", "slf4j-api"), "1.7.7").withCompileScope.withJarAttributeType))
|
||||
Dependency(Module("ch.qos.logback", "logback-core"), "1.1.3").withCompileScope,
|
||||
Dependency(Module("org.slf4j", "slf4j-api"), "1.7.7").withCompileScope))
|
||||
|
||||
assert(res == expected)
|
||||
}
|
||||
|
|
@ -177,8 +185,8 @@ object CentralTests extends TestSuite {
|
|||
rootDependencies = Set(dep),
|
||||
dependencies = Set(
|
||||
dep.withCompileScope,
|
||||
Dependency(Module("org.ow2.asm", "asm-tree"), "5.0.2").withCompileScope.withJarAttributeType,
|
||||
Dependency(Module("org.ow2.asm", "asm"), "5.0.2").withCompileScope.withJarAttributeType))
|
||||
Dependency(Module("org.ow2.asm", "asm-tree"), "5.0.2").withCompileScope,
|
||||
Dependency(Module("org.ow2.asm", "asm"), "5.0.2").withCompileScope))
|
||||
|
||||
assert(res == expected)
|
||||
}
|
||||
|
|
@ -338,12 +346,22 @@ object CentralTests extends TestSuite {
|
|||
|
||||
'bundle - {
|
||||
// has packaging bundle - ensuring coursier gives its artifact the .jar extension
|
||||
ensureHasArtifactWithExtension(
|
||||
* - ensureHasArtifactWithExtension(
|
||||
Module("com.google.guava", "guava"),
|
||||
"17.0",
|
||||
"bundle",
|
||||
"jar"
|
||||
)
|
||||
|
||||
// even though packaging is bundle, depending on attribute type "jar" should still find
|
||||
// an artifact
|
||||
* - ensureHasArtifactWithExtension(
|
||||
Module("com.google.guava", "guava"),
|
||||
"17.0",
|
||||
"bundle",
|
||||
"jar",
|
||||
attributes = Attributes("jar")
|
||||
)
|
||||
}
|
||||
|
||||
'mavenPlugin - {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ object PomParsingTests extends TestSuite {
|
|||
Module("comp", "lib"),
|
||||
"2.1",
|
||||
attributes = Attributes(classifier = "extra")
|
||||
).withJarAttributeType
|
||||
)
|
||||
)
|
||||
|
||||
val result = Pom.dependency(xmlParse(depNode).right.get)
|
||||
|
|
@ -131,7 +131,7 @@ object PomParsingTests extends TestSuite {
|
|||
None,
|
||||
Profile.Activation(Nil),
|
||||
Seq(
|
||||
"" -> Dependency(Module("comp", "lib"), "0.2").withJarAttributeType),
|
||||
"" -> Dependency(Module("comp", "lib"), "0.2")),
|
||||
Nil,
|
||||
Map.empty
|
||||
))
|
||||
|
|
@ -163,7 +163,7 @@ object PomParsingTests extends TestSuite {
|
|||
Profile.Activation(Nil),
|
||||
Nil,
|
||||
Seq(
|
||||
"test" -> Dependency(Module("comp", "lib"), "0.2").withJarAttributeType),
|
||||
"test" -> Dependency(Module("comp", "lib"), "0.2")),
|
||||
Map.empty
|
||||
))
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ package object test {
|
|||
|
||||
implicit class DependencyOps(val underlying: Dependency) extends AnyVal {
|
||||
def withCompileScope: Dependency = underlying.copy(configuration = "compile")
|
||||
def withJarAttributeType: Dependency = underlying.copy(attributes = underlying.attributes.copy(`type` = "jar"))
|
||||
}
|
||||
|
||||
implicit class ResolutionOps(val underlying: Resolution) extends AnyVal {
|
||||
|
|
@ -62,6 +61,7 @@ package object test {
|
|||
profiles: Seq[Profile] = Seq.empty,
|
||||
versions: Option[core.Versions] = None,
|
||||
snapshotVersioning: Option[core.SnapshotVersioning] = None,
|
||||
packaging: Option[String] = None,
|
||||
publications: Seq[(String, core.Publication)] = Nil
|
||||
): Project =
|
||||
core.Project(
|
||||
|
|
@ -76,6 +76,7 @@ package object test {
|
|||
versions,
|
||||
snapshotVersioning,
|
||||
None,
|
||||
packaging,
|
||||
publications,
|
||||
Info.empty
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue