Merge pull request #304 from alexarchambault/topic/develop

Various fixes
This commit is contained in:
Alexandre Archambault 2016-07-25 00:17:54 +02:00 committed by GitHub
commit 3c7d3b8443
33 changed files with 363 additions and 97 deletions

View File

@ -48,7 +48,7 @@ if echo "$TRAVIS_SCALA_VERSION" | grep -q "^2\.10"; then
SBT_COMMANDS="$SBT_COMMANDS plugin/scripted"
fi
SBT_COMMANDS="$SBT_COMMANDS coreJVM/mimaReportBinaryIssues cache/mimaReportBinaryIssues"
SBT_COMMANDS="$SBT_COMMANDS tut coreJVM/mimaReportBinaryIssues cache/mimaReportBinaryIssues"
if isNotPr && publish && isMaster; then
SBT_COMMANDS="$SBT_COMMANDS publish"

View File

@ -447,7 +447,7 @@ scala> val repositories = Seq(
| Cache.ivy2Local,
| MavenRepository("https://repo1.maven.org/maven2")
| )
repositories: Seq[coursier.core.Repository] = List(IvyRepository(file://${user.home}/.ivy2/local/[organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext],None,None,Map(),true,true,true,true,None), MavenRepository(https://repo1.maven.org/maven2,None,false,None))
repositories: Seq[coursier.core.Repository] = List(IvyRepository(Pattern(List(Const(file://), Var(user.home), Const(/local/), Var(organisation), Const(/), Var(module), Const(/), Opt(WrappedArray(Const(scala_), Var(scalaVersion), Const(/))), Opt(WrappedArray(Const(sbt_), Var(sbtVersion), Const(/))), Var(revision), Const(/), Var(type), Const(s/), Var(artifact), Opt(WrappedArray(Const(-), Var(classifier))), Const(.), Var(ext))),None,None,true,true,true,true,None), MavenRepository(https://repo1.maven.org/maven2,None,false,None))
```
The first one, `Cache.ivy2Local`, is defined in `coursier.Cache`, itself from the `coursier-cache` module that
we added above. As we can see, it is an `IvyRepository`, picking things under `~/.ivy2/local`. An `IvyRepository`
@ -554,6 +554,8 @@ We're using the `Cache.file` method, that can also be given a `Logger` (for more
#### Inter-project repository in the SBT plugin is a bit naive
**Fixed in 1.0.0-M13**
The inter-project repository is the pseudo-repository, nesting the metadata
of sub-projects. It gets confused in at least these two cases:

View File

@ -148,6 +148,14 @@ lazy val core = crossProject
Seq(
// Since 1.0.0-M13
// reworked VersionConstraint
ProblemFilters.exclude[MissingClassProblem]("coursier.core.VersionConstraint$Interval"),
ProblemFilters.exclude[MissingClassProblem]("coursier.core.VersionConstraint$Preferred"),
ProblemFilters.exclude[MissingClassProblem]("coursier.core.VersionConstraint$Preferred$"),
ProblemFilters.exclude[MissingClassProblem]("coursier.core.VersionConstraint$Interval$"),
ProblemFilters.exclude[FinalClassProblem]("coursier.core.VersionConstraint"),
ProblemFilters.exclude[IncompatibleResultTypeProblem]("coursier.core.VersionConstraint.repr"),
ProblemFilters.exclude[IncompatibleMethTypeProblem]("coursier.core.VersionConstraint.this"),
// Extra `actualVersion` field in `Project`
ProblemFilters.exclude[MissingTypesProblem]("coursier.core.Project$"),
ProblemFilters.exclude[MissingMethodProblem]("coursier.core.Project.apply"),

View File

@ -75,10 +75,12 @@ case class Bootstrap(
val helper = new Helper(options.common, remainingArgs)
val isolatedDeps = options.isolated.isolatedDeps(options.common.defaultArtifactType)
val (_, isolatedArtifactFiles) =
options.isolated.targets.foldLeft((Vector.empty[String], Map.empty[String, (Seq[String], Seq[File])])) {
case ((done, acc), target) =>
val subRes = helper.res.subset(options.isolated.isolatedDeps.getOrElse(target, Nil).toSet)
val subRes = helper.res.subset(isolatedDeps.getOrElse(target, Nil).toSet)
val subArtifacts = subRes.artifacts.map(_.url)
val filteredSubArtifacts = subArtifacts.diff(done)
@ -86,7 +88,7 @@ case class Bootstrap(
def subFiles0 = helper.fetch(
sources = false,
javadoc = false,
subset = options.isolated.isolatedDeps.getOrElse(target, Seq.empty).toSet
subset = isolatedDeps.getOrElse(target, Seq.empty).toSet
)
val (subUrls, subFiles) =

View File

@ -244,6 +244,7 @@ class Helper(
Dependency(
module,
version,
attributes = Attributes(defaultArtifactType, ""),
configuration = configOpt.getOrElse(defaultConfiguration),
exclusions = excludes
)
@ -254,6 +255,7 @@ class Helper(
Dependency(
module,
version,
attributes = Attributes(defaultArtifactType, ""),
configuration = configOpt.getOrElse(defaultConfiguration),
exclusions = excludes,
transitive = false

View File

@ -104,6 +104,9 @@ case class Launch(
if (options.isolated.isolated.isEmpty)
(parentLoader0, files0)
else {
val isolatedDeps = options.isolated.isolatedDeps(options.common.defaultArtifactType)
val (isolatedLoader, filteredFiles0) = options.isolated.targets.foldLeft((parentLoader0, files0)) {
case ((parent, files0), target) =>
@ -111,7 +114,7 @@ case class Launch(
val isolatedFiles = helper.fetch(
sources = false,
javadoc = false,
subset = options.isolated.isolatedDeps.getOrElse(target, Seq.empty).toSet
subset = isolatedDeps.getOrElse(target, Seq.empty).toSet
)
if (options.common.verbosityLevel >= 2) {
@ -199,6 +202,7 @@ case class Launch(
Helper.errPrintln(s"Error: method main not found in $mainClass0")
sys.exit(255)
}
method.setAccessible(true)
if (options.common.verbosityLevel >= 2)
Helper.errPrintln(s"Launching $mainClass0 ${userArgs.mkString(" ")}")
@ -206,5 +210,9 @@ case class Launch(
Helper.errPrintln(s"Launching")
Thread.currentThread().setContextClassLoader(loader)
method.invoke(null, userArgs.toArray)
try method.invoke(null, userArgs.toArray)
catch {
case e: java.lang.reflect.InvocationTargetException =>
throw Option(e.getCause).getOrElse(e)
}
}

View File

@ -58,6 +58,10 @@ case class CommonOptions(
@Value("configuration")
@Short("c")
defaultConfiguration: String = "default(compile)",
@Help("Default artifact type (make it empty to follow POM packaging - default: jar)")
@Value("type")
@Short("a")
defaultArtifactType: String = "jar",
@Help("Maximum number of parallel downloads (default: 6)")
@Short("n")
parallel: Int = 6,
@ -145,13 +149,19 @@ case class IsolatedLoaderOptions(
t -> modVers
}
lazy val isolatedDeps = isolatedModuleVersions.map {
case (t, l) =>
t -> l.map {
case (mod, ver) =>
Dependency(mod, ver, configuration = "runtime")
}
}
def isolatedDeps(defaultArtifactType: String) =
isolatedModuleVersions.map {
case (t, l) =>
t -> l.map {
case (mod, ver) =>
Dependency(
mod,
ver,
configuration = "runtime",
attributes = Attributes(defaultArtifactType, "")
)
}
}
}

View File

@ -43,12 +43,12 @@ object Parse {
}
def versionConstraint(s: String): Option[VersionConstraint] = {
def noConstraint = if (s.isEmpty) Some(VersionConstraint.None) else None
def noConstraint = if (s.isEmpty) Some(VersionConstraint.all) else None
noConstraint
.orElse(ivyLatestSubRevisionInterval(s).map(VersionConstraint.Interval))
.orElse(version(s).map(VersionConstraint.Preferred))
.orElse(versionInterval(s).map(VersionConstraint.Interval))
.orElse(ivyLatestSubRevisionInterval(s).map(VersionConstraint.interval))
.orElse(version(s).map(VersionConstraint.preferred))
.orElse(versionInterval(s).map(VersionConstraint.interval))
}
val fallbackConfigRegex = {

View File

@ -140,25 +140,26 @@ object Resolution {
* Returns `None` in case of conflict.
*/
def mergeVersions(versions: Seq[String]): Option[String] = {
val (nonParsedConstraints, parsedConstraints) =
versions
.map(v => v -> Parse.versionConstraint(v))
.partition(_._2.isEmpty)
val parseResults = versions.map(v => v -> Parse.versionConstraint(v))
val nonParsedConstraints = parseResults.collect {
case (repr, None) => repr
}
// FIXME Report this in return type, not this way
if (nonParsedConstraints.nonEmpty)
Console.err.println(
s"Ignoring unparsed versions: ${nonParsedConstraints.map(_._1)}"
s"Ignoring unparsed versions: $nonParsedConstraints"
)
val intervalOpt =
(Option(VersionInterval.zero) /: parsedConstraints) {
case (acc, (_, someCstr)) =>
acc.flatMap(_.merge(someCstr.get.interval))
}
val parsedConstraints = parseResults.collect {
case (_, Some(c)) => c
}
intervalOpt
.map(_.constraint.repr)
VersionConstraint
.merge(parsedConstraints: _*)
.flatMap(_.repr)
}
/**

View File

@ -1,5 +1,8 @@
package coursier.core
import scalaz.{ -\/, \/, \/- }
import scalaz.Scalaz.ToEitherOps
case class VersionInterval(from: Option[Version],
to: Option[Version],
fromIncluded: Boolean,
@ -64,9 +67,9 @@ case class VersionInterval(from: Option[Version],
def constraint: VersionConstraint =
this match {
case VersionInterval.zero => VersionConstraint.None
case VersionInterval(Some(version), None, true, false) => VersionConstraint.Preferred(version)
case itv => VersionConstraint.Interval(itv)
case VersionInterval.zero => VersionConstraint.all
case VersionInterval(Some(version), None, true, false) => VersionConstraint.preferred(version)
case itv => VersionConstraint.interval(itv)
}
def repr: String = Seq(
@ -82,23 +85,54 @@ object VersionInterval {
val zero = VersionInterval(None, None, fromIncluded = false, toIncluded = false)
}
sealed abstract class VersionConstraint(
val interval: VersionInterval,
val repr: String
)
final case class VersionConstraint(
interval: VersionInterval,
preferred: Seq[Version]
) {
def blend: Option[VersionInterval \/ Version] =
if (interval.isValid) {
val preferredInInterval = preferred.filter(interval.contains)
if (preferredInInterval.isEmpty)
Some(interval.left)
else
Some(preferredInInterval.max.right)
} else
None
def repr: Option[String] =
blend.map {
case -\/(itv) =>
if (itv == VersionInterval.zero)
""
else
itv.repr
case \/-(v) => v.repr
}
}
object VersionConstraint {
/** Currently treated as minimum... */
final case class Preferred(version: Version) extends VersionConstraint(
VersionInterval(Some(version), Option.empty, fromIncluded = true, toIncluded = false),
version.repr
)
final case class Interval(interval0: VersionInterval) extends VersionConstraint(
interval0,
interval0.repr
)
case object None extends VersionConstraint(
VersionInterval.zero,
"" // Once parsed, "(,)" becomes "" because of this
)
def preferred(version: Version): VersionConstraint =
VersionConstraint(VersionInterval.zero, Seq(version))
def interval(interval: VersionInterval): VersionConstraint =
VersionConstraint(interval, Nil)
val all = VersionConstraint(VersionInterval.zero, Nil)
def merge(constraints: VersionConstraint*): Option[VersionConstraint] = {
val intervals = constraints.map(_.interval)
val intervalOpt =
(Option(VersionInterval.zero) /: intervals) {
case (acc, itv) =>
acc.flatMap(_.merge(itv))
}
for (interval <- intervalOpt) yield {
val preferreds = constraints.flatMap(_.preferred).distinct
VersionConstraint(interval, preferreds)
}
}
}

View File

@ -48,7 +48,12 @@ object MavenRepository {
val defaultPackaging = "jar"
def defaultPublications(moduleName: String, packaging: String) = Seq(
"compile" -> Publication(moduleName, packaging, MavenSource.typeExtension(packaging), ""),
"compile" -> Publication(
moduleName,
packaging,
MavenSource.typeExtension(packaging),
MavenSource.typeDefaultClassifier(packaging)
),
"docs" -> Publication(moduleName, "doc", "jar", "javadoc"),
"sources" -> Publication(moduleName, "src", "jar", "sources")
)

View File

@ -136,12 +136,20 @@ case class MavenSource(
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,
MavenSource.typeExtension(type0),
dependency.attributes.classifier
extension,
classifier
)
)
} else
@ -163,10 +171,27 @@ object MavenSource {
"jar" -> "jar",
"bundle" -> "jar",
"doc" -> "jar",
"src" -> "jar"
"src" -> "jar",
"test-jar" -> "jar",
"ejb-client" -> "jar"
)
def typeExtension(`type`: String): String =
typeExtensions.getOrElse(`type`, `type`)
// see https://github.com/apache/maven/blob/c023e58104b71e27def0caa034d39ab0fa0373b6/maven-core/src/main/resources/META-INF/plexus/artifact-handlers.xml
// discussed in https://github.com/alexarchambault/coursier/issues/298
val typeDefaultClassifiers: Map[String, String] = Map(
"test-jar" -> "tests",
"javadoc" -> "javadoc",
"java-source" -> "sources",
"ejb-client" -> "client"
)
def typeDefaultClassifierOpt(`type`: String): Option[String] =
typeDefaultClassifiers.get(`type`)
def typeDefaultClassifier(`type`: String): String =
typeDefaultClassifierOpt(`type`).getOrElse("")
}

View File

@ -11,7 +11,7 @@ package object coursier {
version: String,
// Substituted by Resolver with its own default configuration (compile)
configuration: String = "",
attributes: Attributes = Attributes(),
attributes: Attributes = Attributes("jar"),
exclusions: Set[(String, String)] = Set.empty,
optional: Boolean = false,
transitive: Boolean = true

View File

@ -136,7 +136,7 @@ object Parse {
else if (s.startsWith("sonatype:"))
MavenRepository(s"https://oss.sonatype.org/content/repositories/${s.stripPrefix("sonatype:")}").right
else if (s.startsWith("bintray:"))
MavenRepository(s"https://dl.bintray.com/${s.stripPrefix("bintray:")}/maven").right
MavenRepository(s"https://dl.bintray.com/${s.stripPrefix("bintray:")}").right
else if (s.startsWith("typesafe:ivy-"))
IvyRepository.fromPattern(
(s"https://repo.typesafe.com/typesafe/ivy-" + s.stripPrefix("typesafe:ivy-") + "/") +:

View File

@ -135,8 +135,13 @@ object Cache {
// but it would then have required properties, which would have cluttered
// output here.
val ivy2Local = coursier.Cache.ivy2Local.copy(
pattern = coursier.Cache.ivy2Local.pattern.replace("file:" + sys.props("user.home"), "file://${user.home}")
import coursier.ivy.Pattern.Chunk, Chunk._
val ivy2Local = coursier.ivy.IvyRepository.fromPattern(
coursier.ivy.Pattern(
Seq[Chunk]("file://", Var("user.home"), "/local/") ++ coursier.ivy.Pattern.default.chunks
),
dropInfoAttributes = true
)
def fetch() = coursier.Cache.fetch()
@ -576,6 +581,8 @@ We're using the `Cache.file` method, that can also be given a `Logger` (for more
#### Inter-project repository in the SBT plugin is a bit naive
**Fixed in 1.0.0-M13**
The inter-project repository is the pseudo-repository, nesting the metadata
of sub-projects. It gets confused in at least these two cases:

View File

@ -26,7 +26,7 @@ object CoursierPlugin extends AutoPlugin {
val coursierFallbackDependencies = Keys.coursierFallbackDependencies
val coursierCache = Keys.coursierCache
val coursierProject = Keys.coursierProject
val coursierProjects = Keys.coursierProjects
val coursierInterProjectDependencies = Keys.coursierInterProjectDependencies
val coursierPublications = Keys.coursierPublications
val coursierSbtClassifiersModule = Keys.coursierSbtClassifiersModule
@ -67,7 +67,7 @@ object CoursierPlugin extends AutoPlugin {
coursierSourceRepositories := Nil,
coursierResolvers <<= Tasks.coursierResolversTask,
coursierSbtResolvers <<= externalResolvers in updateSbtClassifiers,
coursierUseSbtCredentials := true,
coursierUseSbtCredentials := false,
coursierCredentials := Map.empty,
coursierFallbackDependencies <<= Tasks.coursierFallbackDependenciesTask,
coursierCache := Cache.default,
@ -82,7 +82,7 @@ object CoursierPlugin extends AutoPlugin {
ignoreArtifactErrors = true
),
coursierProject <<= Tasks.coursierProjectTask,
coursierProjects <<= Tasks.coursierProjectsTask,
coursierInterProjectDependencies <<= Tasks.coursierInterProjectDependenciesTask,
coursierPublications <<= Tasks.coursierPublicationsTask,
coursierSbtClassifiersModule <<= classifiersModule in updateSbtClassifiers,
coursierConfigurations <<= Tasks.coursierConfigurationsTask,

View File

@ -31,7 +31,7 @@ object Keys {
val coursierFallbackDependencies = TaskKey[Seq[(Module, String, URL, Boolean)]]("coursier-fallback-dependencies")
val coursierProject = TaskKey[Project]("coursier-project")
val coursierProjects = TaskKey[Seq[Project]]("coursier-projects")
val coursierInterProjectDependencies = TaskKey[Seq[Project]]("coursier-inter-project-dependencies", "Projects the current project depends on, possibly transitively")
val coursierPublications = TaskKey[Seq[(String, Publication)]]("coursier-publications")
val coursierSbtClassifiersModule = TaskKey[GetClassifiersModule]("coursier-sbt-classifiers-module")

View File

@ -96,9 +96,32 @@ object Tasks {
}
}
def coursierProjectsTask: Def.Initialize[sbt.Task[Seq[Project]]] =
sbt.Keys.state.flatMap { state =>
val projects = structure(state).allProjectRefs
def coursierInterProjectDependenciesTask: Def.Initialize[sbt.Task[Seq[Project]]] =
(
sbt.Keys.state,
sbt.Keys.thisProjectRef
).flatMap { (state, projectRef) =>
def dependencies(map: Map[String, Seq[String]], id: String): Set[String] = {
def helper(map: Map[String, Seq[String]], acc: Set[String]): Set[String] =
if (acc.exists(map.contains)) {
val (kept, rem) = map.partition { case (k, _) => acc(k) }
helper(rem, acc ++ kept.valuesIterator.flatten)
} else
acc
helper(map - id, map.getOrElse(id, Nil).toSet)
}
val allProjectsDeps =
for (p <- structure(state).allProjects)
yield p.id -> p.dependencies.map(_.project.project)
val deps = dependencies(allProjectsDeps.toMap, projectRef.project)
val projects = structure(state).allProjectRefs.filter(p => deps(p.project))
coursierProject.forAllProjects(state, projects).map(_.values.toVector)
}
@ -271,7 +294,7 @@ object Tasks {
(proj.copy(publications = publications), fallbackDeps)
}
val projects = coursierProjects.value
val interProjectDependencies = coursierInterProjectDependencies.value
val parallelDownloads = coursierParallelDownloads.value
val checksums = coursierChecksums.value
@ -363,12 +386,12 @@ object Tasks {
userForceVersions ++
sourceRepositoriesForcedDependencies ++
forcedScalaModules(so, sv) ++
projects.map(_.moduleVersion)
interProjectDependencies.map(_.moduleVersion)
)
if (verbosityLevel >= 2) {
log.info("InterProjectRepository")
for (p <- projects)
for (p <- interProjectDependencies)
log.info(s" ${p.module}:${p.version}")
}
@ -380,7 +403,7 @@ object Tasks {
withArtifacts = false
)
val interProjectRepo = InterProjectRepository(projects)
val interProjectRepo = InterProjectRepository(interProjectDependencies)
val ivyProperties = Map(
"ivy.home" -> (new File(sys.props("user.home")).toURI.getPath + ".ivy2")

View File

@ -23,7 +23,9 @@ object ToSbt {
// FIXME Get these two from publications
artifact.attributes.`type`,
MavenSource.typeExtension(artifact.attributes.`type`),
Some(artifact.attributes.classifier).filter(_.nonEmpty),
Some(artifact.attributes.classifier)
.filter(_.nonEmpty)
.orElse(MavenSource.typeDefaultClassifierOpt(artifact.attributes.`type`)),
Nil,
Some(url(artifact.url)),
Map.empty

View File

@ -2,6 +2,7 @@ scalaVersion := "2.11.8"
resolvers += "authenticated" at "http://localhost:8080"
coursierUseSbtCredentials := true
credentials += Credentials("", "localhost", "user", "pass")
coursierCachePolicies := {

View File

@ -0,0 +1,10 @@
scalaVersion := "2.11.8"
libraryDependencies += "org.apache.hadoop" % "hadoop-yarn-server-resourcemanager" % "2.7.1"
coursierCachePolicies := {
if (sys.props("os.name").startsWith("Windows"))
coursierCachePolicies.value
else
Seq(coursier.CachePolicy.ForceDownload)
}

View File

@ -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)
}

View File

@ -0,0 +1,8 @@
import java.io.File
import java.nio.file.Files
import org.apache.zookeeper.ZooKeeper
object Main extends App {
Files.write(new File("output").toPath, classOf[ZooKeeper].getSimpleName.getBytes("UTF-8"))
}

View File

@ -0,0 +1,3 @@
$ delete output
> run
$ exists output

View File

@ -0,0 +1,6 @@
object A {
def msg = "OK"
}

View File

@ -0,0 +1,13 @@
import java.io.File
import java.nio.file.Files
import argonaut._, Argonaut._, ArgonautShapeless._
object Main extends App {
case class CC(i: Int, s: String)
val msg = CC(2, A.msg).asJson.spaces2
Files.write(new File("output").toPath, msg.getBytes("UTF-8"))
}

View File

@ -0,0 +1,38 @@
lazy val sharedSettings = Seq(
scalaVersion := "2.11.8",
coursierCachePolicies := {
if (sys.props("os.name").startsWith("Windows"))
coursierCachePolicies.value
else
Seq(coursier.CachePolicy.ForceDownload)
}
)
/** Module with the same Maven coordinates as shapeless 2.3.1 */
lazy val `shapeless-mock` = project
.settings(sharedSettings)
.settings(
organization := "com.chuusai",
name := "shapeless",
version := "2.3.1"
)
lazy val a = project
.settings(sharedSettings)
.settings(
organization := "com.pany",
name := "a",
version := "0.0.1"
)
/** Transitively depends on the - real - shapeless 2.3.1 */
lazy val b = project
.dependsOn(a)
.settings(sharedSettings)
.settings(
organization := "com.pany",
name := "b",
version := "0.0.1",
libraryDependencies += "com.github.alexarchambault" %% "argonaut-shapeless_6.2" % "1.2.0-M1"
)

View File

@ -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)
}

View File

@ -0,0 +1,3 @@
$ delete output
> b/run
$ exists output

View File

@ -0,0 +1,3 @@
org.webjars.bower:jquery:3.1.0:compile
org.webjars.bower:jquery-mousewheel:3.1.13:compile
org.webjars.bower:malihu-custom-scrollbar-plugin:3.1.5:compile

View File

@ -104,7 +104,7 @@ object CentralTests extends TestSuite {
)(
f: Artifact => T
): Future[T] = async {
val dep = Dependency(module, version, transitive = false)
val dep = Dependency(module, version, transitive = false, attributes = Attributes())
val res = await(resolve(Set(dep), extraRepo = extraRepo))
res.artifacts match {
@ -237,6 +237,15 @@ object CentralTests extends TestSuite {
)
}
'versionInterval - {
// Warning: needs to be updated when new versions of org.webjars.bower:jquery and
// org.webjars.bower:jquery-mousewheel are published :-|
resolutionCheck(
Module("org.webjars.bower", "malihu-custom-scrollbar-plugin"),
"3.1.5"
)
}
'latestRevision - {
* - resolutionCheck(
Module("com.chuusai", "shapeless_2.11"),
@ -346,6 +355,42 @@ object CentralTests extends TestSuite {
assert(nonUnique.isEmpty)
}
}
'testJarType - {
// dependencies with type "test-jar" should be given the classifier "tests" by default
async {
val deps = Set(
Dependency(
Module("org.apache.hadoop", "hadoop-yarn-server-resourcemanager"),
"2.7.1"
)
)
val res = await(resolve(deps))
assert(res.errors.isEmpty)
assert(res.conflicts.isEmpty)
assert(res.isDone)
val dependencyArtifacts = res.dependencyArtifacts
val zookeeperTestArtifacts = dependencyArtifacts.collect {
case (dep, artifact)
if dep.module == Module("org.apache.zookeeper", "zookeeper") &&
dep.attributes.`type` == "test-jar" =>
artifact
}
assert(zookeeperTestArtifacts.length == 1)
val zookeeperTestArtifact = zookeeperTestArtifacts.head
assert(zookeeperTestArtifact.attributes.`type` == "test-jar")
assert(zookeeperTestArtifact.attributes.classifier == "tests")
zookeeperTestArtifact.url.endsWith("-tests.jar")
}
}
}
}

View File

@ -10,45 +10,30 @@ object VersionConstraintTests extends TestSuite {
'parse{
'empty{
val c0 = Parse.versionConstraint("")
assert(c0 == Some(VersionConstraint.None))
assert(c0 == Some(VersionConstraint.all))
}
'basicVersion{
val c0 = Parse.versionConstraint("1.2")
assert(c0 == Some(VersionConstraint.Preferred(Version("1.2"))))
assert(c0 == Some(VersionConstraint.preferred(Version("1.2"))))
}
'basicVersionInterval{
val c0 = Parse.versionConstraint("(,1.2]")
assert(c0 == Some(VersionConstraint.Interval(VersionInterval(None, Some(Version("1.2")), false, true))))
assert(c0 == Some(VersionConstraint.interval(VersionInterval(None, Some(Version("1.2")), false, true))))
}
}
'repr{
'empty{
val s0 = VersionConstraint.None.repr
assert(s0 == "")
val s0 = VersionConstraint.all.repr
assert(s0 == Some(""))
}
'preferred{
val s0 = VersionConstraint.Preferred(Version("2.1")).repr
assert(s0 == "2.1")
val s0 = VersionConstraint.preferred(Version("2.1")).repr
assert(s0 == Some("2.1"))
}
'interval{
val s0 = VersionConstraint.Interval(VersionInterval(None, Some(Version("2.1")), false, true)).repr
assert(s0 == "(,2.1]")
}
}
'interval{
'empty{
val s0 = VersionConstraint.None.interval
assert(s0 == VersionInterval.zero)
}
'preferred{
val s0 = VersionConstraint.Preferred(Version("2.1")).interval
assert(s0 == VersionInterval(Some(Version("2.1")), None, true, false))
}
'interval{
val s0 = VersionConstraint.Interval(VersionInterval(None, Some(Version("2.1")), false, true)).interval
assert(s0 == VersionInterval(None, Some(Version("2.1")), false, true))
val s0 = VersionConstraint.interval(VersionInterval(None, Some(Version("2.1")), false, true)).repr
assert(s0 == Some("(,2.1]"))
}
}
}

View File

@ -269,17 +269,17 @@ object VersionIntervalTests extends TestSuite {
'none{
val s1 = "(,)"
val c1 = Parse.versionInterval(s1).map(_.constraint)
assert(c1 == Some(VersionConstraint.None))
assert(c1 == Some(VersionConstraint.all))
}
'preferred{
val s1 = "[1.3,)"
val c1 = Parse.versionInterval(s1).map(_.constraint)
assert(c1 == Some(VersionConstraint.Preferred(Parse.version("1.3").get)))
assert(c1 == Some(VersionConstraint.preferred(Parse.version("1.3").get)))
}
'interval{
val s1 = "[1.3,2.4)"
val c1 = Parse.versionInterval(s1).map(_.constraint)
assert(c1 == Some(VersionConstraint.Interval(VersionInterval(Parse.version("1.3"), Parse.version("2.4"), true, false))))
assert(c1 == Some(VersionConstraint.interval(VersionInterval(Parse.version("1.3"), Parse.version("2.4"), true, false))))
}
}
}