mirror of https://github.com/sbt/sbt.git
commit
de3b704731
2
USAGE.md
2
USAGE.md
|
|
@ -5,7 +5,7 @@ Ensure you have a dependency on its artifact, e.g. add in `build.sbt`,
|
|||
resolvers += Resolver.sonatypeRepo("snapshots")
|
||||
|
||||
libraryDependencies +=
|
||||
"eu.frowning-lambda" %% "coursier" % "0.1.0-SNAPSHOT"
|
||||
"com.github.alexarchambault" %% "coursier" % "0.1.0-SNAPSHOT"
|
||||
```
|
||||
|
||||
Then,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ case class Coursier(scope: List[String],
|
|||
base.relativize(f.toURI).getPath
|
||||
|
||||
val logger: RemoteLogger with ArtifactDownloaderLogger = new RemoteLogger with ArtifactDownloaderLogger {
|
||||
def println(s: String) = Console.err.println(s)
|
||||
|
||||
def downloading(url: String) =
|
||||
println(s"Downloading $url")
|
||||
def downloaded(url: String, success: Boolean) =
|
||||
|
|
@ -91,16 +93,27 @@ case class Coursier(scope: List[String],
|
|||
).run
|
||||
|
||||
if (!res.isDone) {
|
||||
println(s"Maximum number of iteration reached!")
|
||||
Console.err.println(s"Maximum number of iteration reached!")
|
||||
sys exit 1
|
||||
}
|
||||
|
||||
def repr(dep: Dependency) =
|
||||
s"${dep.module.organization}:${dep.module.name}:${dep.`type`}:${Some(dep.classifier).filter(_.nonEmpty).map(_+":").mkString}${dep.version}"
|
||||
def repr(dep: Dependency) = {
|
||||
val (type0, classifier) = dep.artifacts match {
|
||||
case maven: Artifacts.Maven => (maven.`type`, maven.classifier)
|
||||
}
|
||||
|
||||
// dep.version can be an interval, whereas the one from project can't
|
||||
val version = res.projectsCache.get(dep.moduleVersion).map(_._2.version).getOrElse(dep.version)
|
||||
val extra =
|
||||
if (version == dep.version) ""
|
||||
else s" ($version for ${dep.version})"
|
||||
|
||||
s"${dep.module.organization}:${dep.module.name}:$type0:${Some(classifier).filter(_.nonEmpty).map(_+":").mkString}$version$extra"
|
||||
}
|
||||
|
||||
val trDeps = res.dependencies.toList.sortBy(repr)
|
||||
|
||||
println("\n" + trDeps.map(repr).mkString("\n"))
|
||||
println("\n" + trDeps.map(repr).distinct.mkString("\n"))
|
||||
|
||||
if (res.conflicts.nonEmpty) {
|
||||
// Needs test
|
||||
|
|
@ -143,12 +156,12 @@ case class Coursier(scope: List[String],
|
|||
(repo, deps) <- sorted
|
||||
dl = downloaders(repo)
|
||||
dep <- deps
|
||||
(_, proj) = res.projectsCache(dep.moduleVersion)
|
||||
} yield {
|
||||
dl.artifact(dep, cachePolicy = cachePolicy).run.map {
|
||||
case -\/(err) =>
|
||||
println(s"Failed to get ${repr(dep)}: $err")
|
||||
case \/-(f) =>
|
||||
println(s"${repr(dep)}:\n ${fileRepr(f)}")
|
||||
dl.artifacts(dep, proj, cachePolicy = cachePolicy).map { results =>
|
||||
val errorCount = results.count{case -\/(_) => true; case _ => false}
|
||||
val resultsRepr = results.map(_.map(fileRepr).merge).map(" " + _).mkString("\n")
|
||||
println(s"${repr(dep)} (${results.length} artifact(s)${if (errorCount > 0) s", $errorCount error(s)" else ""}):\n$resultsRepr")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,13 +77,13 @@ trait Logger {
|
|||
def other(url: String, msg: String): Unit
|
||||
}
|
||||
|
||||
case class Remote(base: String, logger: Option[Logger] = None) extends Repository {
|
||||
case class Remote(base: String, logger: Option[Logger] = None) extends MavenRepository {
|
||||
|
||||
def find(module: Module,
|
||||
version: String,
|
||||
cachePolicy: CachePolicy): EitherT[Task, String, Project] = {
|
||||
def findNoInterval(module: Module,
|
||||
version: String,
|
||||
cachePolicy: CachePolicy): EitherT[Task, String, Project] = {
|
||||
|
||||
val relPath = {
|
||||
val path = {
|
||||
module.organization.split('.').toSeq ++ Seq(
|
||||
module.name,
|
||||
version,
|
||||
|
|
@ -91,7 +91,7 @@ case class Remote(base: String, logger: Option[Logger] = None) extends Repositor
|
|||
)
|
||||
} .map(Remote.encodeURIComponent)
|
||||
|
||||
val url = base + relPath.mkString("/")
|
||||
val url = base + path.mkString("/")
|
||||
|
||||
EitherT(Task{ implicit ec =>
|
||||
logger.foreach(_.fetching(url))
|
||||
|
|
@ -111,6 +111,28 @@ case class Remote(base: String, logger: Option[Logger] = None) extends Repositor
|
|||
|
||||
def versions(organization: String,
|
||||
name: String,
|
||||
cachePolicy: CachePolicy): EitherT[Task, String, Versions] = ???
|
||||
cachePolicy: CachePolicy): EitherT[Task, String, Versions] = {
|
||||
|
||||
val path = {
|
||||
organization.split('.').toSeq ++ Seq(
|
||||
name,
|
||||
"maven-metadata.xml"
|
||||
)
|
||||
} .map(Remote.encodeURIComponent)
|
||||
|
||||
val url = base + path.mkString("/")
|
||||
|
||||
EitherT(Task{ implicit ec =>
|
||||
logger.foreach(_.fetching(url))
|
||||
Remote.get(url).recover{case e: Exception => Left(e.getMessage)}.map{ eitherXml =>
|
||||
logger.foreach(_.fetched(url))
|
||||
for {
|
||||
xml <- \/.fromEither(eitherXml)
|
||||
_ <- if (xml.label == "metadata") \/-(()) else -\/("Metadata not found")
|
||||
versions <- Xml.versions(xml)
|
||||
} yield versions
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@ package object concurrent {
|
|||
def runF(implicit ec: ExecutionContext) = Future.traverse(tasks)(_.runF)
|
||||
}
|
||||
|
||||
implicit val taskFunctor: Functor[Task] =
|
||||
new Functor[Task] {
|
||||
def map[A, B](fa: Task[A])(f: A => B): Task[B] =
|
||||
fa.map(f)
|
||||
implicit val taskMonad: Monad[Task] =
|
||||
new Monad[Task] {
|
||||
def point[A](a: => A): Task[A] = Task.now(a)
|
||||
def bind[A,B](fa: Task[A])(f: A => Task[B]): Task[B] = fa.flatMap(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,26 @@
|
|||
package coursier.test
|
||||
|
||||
import scala.concurrent.{Promise, ExecutionContext, Future}
|
||||
import scala.scalajs.js
|
||||
import js.Dynamic.{global => g}
|
||||
|
||||
package object compatibility {
|
||||
|
||||
implicit val executionContext = scala.scalajs.concurrent.JSExecutionContext.Implicits.queue
|
||||
|
||||
lazy val fs = g.require("fs")
|
||||
|
||||
def textResource(path: String)(implicit ec: ExecutionContext): Future[String] = {
|
||||
val p = Promise[String]()
|
||||
|
||||
fs.readFile("core/src/test/resources/" + path, "utf-8", {
|
||||
(err: js.Dynamic, data: js.Dynamic) =>
|
||||
if (err == null) p.success(data.asInstanceOf[String])
|
||||
else p.failure(new Exception(err.toString))
|
||||
()
|
||||
}: js.Function2[js.Dynamic, js.Dynamic, Unit])
|
||||
|
||||
p.future
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,15 +21,14 @@ case class ArtifactDownloader(root: String, cache: File, logger: Option[Artifact
|
|||
|
||||
def artifact(module: Module,
|
||||
version: String,
|
||||
classifier: String,
|
||||
`type`: String,
|
||||
artifact: Artifacts.Artifact,
|
||||
cachePolicy: CachePolicy): EitherT[Task, String, File] = {
|
||||
|
||||
val relPath =
|
||||
module.organization.split('.').toSeq ++ Seq(
|
||||
module.name,
|
||||
version,
|
||||
s"${module.name}-$version${Some(classifier).filter(_.nonEmpty).map("-"+_).mkString}.${`type`}"
|
||||
s"${module.name}-$version${Some(artifact.classifier).filter(_.nonEmpty).map("-"+_).mkString}.${artifact.`type`}"
|
||||
)
|
||||
|
||||
val file = (cache /: relPath)(new File(_, _))
|
||||
|
|
@ -64,19 +63,19 @@ case class ArtifactDownloader(root: String, cache: File, logger: Option[Artifact
|
|||
val in = new BufferedInputStream(url.openStream(), bufferSize)
|
||||
|
||||
try {
|
||||
val w = new FileOutputStream(file)
|
||||
val out = new FileOutputStream(file)
|
||||
try {
|
||||
@tailrec
|
||||
def helper(): Unit = {
|
||||
val read = in.read(b)
|
||||
if (read >= 0) {
|
||||
w.write(b, 0, read)
|
||||
out.write(b, 0, read)
|
||||
helper()
|
||||
}
|
||||
}
|
||||
|
||||
helper()
|
||||
} finally w.close()
|
||||
} finally out.close()
|
||||
} finally in.close()
|
||||
|
||||
logger.foreach(_.downloadedArtifact(urlStr, success = true))
|
||||
|
|
@ -92,9 +91,24 @@ case class ArtifactDownloader(root: String, cache: File, logger: Option[Artifact
|
|||
EitherT(cachePolicy(locally)(remote))
|
||||
}
|
||||
|
||||
def artifact(dependency: Dependency,
|
||||
cachePolicy: CachePolicy = CachePolicy.Default): EitherT[Task, String, File] =
|
||||
artifact(dependency.module, dependency.version, dependency.classifier, dependency.`type`, cachePolicy = cachePolicy)
|
||||
def artifacts(dependency: Dependency,
|
||||
project: Project,
|
||||
cachePolicy: CachePolicy = CachePolicy.Default): Task[Seq[String \/ File]] = {
|
||||
|
||||
val artifacts0 =
|
||||
dependency.artifacts match {
|
||||
case s: Artifacts.Sufficient => s.artifacts
|
||||
case p: Artifacts.WithProject => p.artifacts(project)
|
||||
}
|
||||
|
||||
val tasks =
|
||||
artifacts0 .map { artifact0 =>
|
||||
// Important: using version from project, as the one from dependency can be an interval
|
||||
artifact(dependency.module, project.version, artifact0, cachePolicy = cachePolicy).run
|
||||
}
|
||||
|
||||
Task.gatherUnordered(tasks)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -138,23 +152,15 @@ object Remote {
|
|||
|
||||
case class Remote(root: String,
|
||||
cache: Option[File] = None,
|
||||
logger: Option[RemoteLogger] = None) extends Repository {
|
||||
logger: Option[RemoteLogger] = None) extends MavenRepository {
|
||||
|
||||
def find(module: Module,
|
||||
version: String,
|
||||
cachePolicy: CachePolicy): EitherT[Task, String, Project] = {
|
||||
private def get(path: Seq[String],
|
||||
cachePolicy: CachePolicy): EitherT[Task, String, String] = {
|
||||
|
||||
val relPath =
|
||||
module.organization.split('.').toSeq ++ Seq(
|
||||
module.name,
|
||||
version,
|
||||
s"${module.name}-$version.pom"
|
||||
)
|
||||
|
||||
def localFile = {
|
||||
lazy val localFile = {
|
||||
for {
|
||||
cache0 <- cache.toRightDisjunction("No cache")
|
||||
f = (cache0 /: relPath)(new File(_, _))
|
||||
f = (cache0 /: path)(new File(_, _))
|
||||
} yield f
|
||||
}
|
||||
|
||||
|
|
@ -172,7 +178,7 @@ case class Remote(root: String,
|
|||
}
|
||||
|
||||
def remote = {
|
||||
val urlStr = root + relPath.mkString("/")
|
||||
val urlStr = root + path.mkString("/")
|
||||
val url = new URL(urlStr)
|
||||
|
||||
def log = Task(logger.foreach(_.downloading(urlStr)))
|
||||
|
|
@ -196,7 +202,21 @@ case class Remote(root: String,
|
|||
)
|
||||
}
|
||||
|
||||
val task = cachePolicy.saving(locally)(remote)(save)
|
||||
EitherT(cachePolicy.saving(locally)(remote)(save))
|
||||
}
|
||||
|
||||
def findNoInterval(module: Module,
|
||||
version: String,
|
||||
cachePolicy: CachePolicy): EitherT[Task, String, Project] = {
|
||||
|
||||
val path =
|
||||
module.organization.split('.').toSeq ++ Seq(
|
||||
module.name,
|
||||
version,
|
||||
s"${module.name}-$version.pom"
|
||||
)
|
||||
|
||||
val task = get(path, cachePolicy).run
|
||||
.map(eitherStr =>
|
||||
for {
|
||||
str <- eitherStr
|
||||
|
|
@ -213,29 +233,13 @@ case class Remote(root: String,
|
|||
name: String,
|
||||
cachePolicy: CachePolicy): EitherT[Task, String, Versions] = {
|
||||
|
||||
val relPath =
|
||||
val path =
|
||||
organization.split('.').toSeq ++ Seq(
|
||||
name,
|
||||
"maven-metadata.xml"
|
||||
)
|
||||
|
||||
def locally = {
|
||||
???
|
||||
}
|
||||
|
||||
def remote = {
|
||||
val urlStr = root + relPath.mkString("/")
|
||||
val url = new URL(urlStr)
|
||||
|
||||
Remote.readFully(url.openStream())
|
||||
}
|
||||
|
||||
def save(s: String) = {
|
||||
// TODO
|
||||
Task.now(())
|
||||
}
|
||||
|
||||
val task = cachePolicy.saving(locally)(remote)(save)
|
||||
val task = get(path, cachePolicy).run
|
||||
.map(eitherStr =>
|
||||
for {
|
||||
str <- eitherStr
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package coursier
|
||||
|
||||
import coursier.core.Resolver.ModuleVersion
|
||||
|
||||
import scalaz.EitherT
|
||||
import scalaz.concurrent.Task
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package coursier.test
|
||||
|
||||
import scala.concurrent.Future
|
||||
import coursier.core.Remote
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
import scalaz.concurrent.Task
|
||||
|
||||
package object compatibility {
|
||||
|
|
@ -11,4 +13,11 @@ package object compatibility {
|
|||
def runF: Future[T] = Future.successful(underlying.run)
|
||||
}
|
||||
|
||||
def textResource(path: String)(implicit ec: ExecutionContext): Future[String] = Future {
|
||||
def is = getClass.getClassLoader
|
||||
.getResource(path).openStream()
|
||||
|
||||
new String(Remote.readFullySync(is), "UTF-8")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,205 +0,0 @@
|
|||
package coursier.core
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import coursier.core.compatibility._
|
||||
|
||||
/** Same kind of ordering as aether-util/src/main/java/org/eclipse/aether/util/version/GenericVersion.java */
|
||||
object ComparableVersion {
|
||||
|
||||
sealed trait Item extends Ordered[Item] {
|
||||
def compare(other: Item): Int =
|
||||
(this, other) match {
|
||||
case (Number(a), Number(b)) => a.compare(b)
|
||||
case (BigNumber(a), BigNumber(b)) => a.compare(b)
|
||||
case (Number(a), BigNumber(b)) => -b.compare(a)
|
||||
case (BigNumber(a), Number(b)) => a.compare(b)
|
||||
case (Qualifier(_, a), Qualifier(_, b)) => a.compare(b)
|
||||
case (Literal(a), Literal(b)) => a.compareToIgnoreCase(b)
|
||||
|
||||
case _ =>
|
||||
val rel0 = compareToEmpty
|
||||
val rel1 = other.compareToEmpty
|
||||
|
||||
if (rel0 == rel1) order.compare(other.order)
|
||||
else rel0.compare(rel1)
|
||||
}
|
||||
|
||||
def order: Int
|
||||
def isEmpty: Boolean = compareToEmpty == 0
|
||||
def compareToEmpty: Int = 1
|
||||
}
|
||||
|
||||
sealed trait Numeric extends Item
|
||||
case class Number(value: Int) extends Numeric {
|
||||
val order = 0
|
||||
override def compareToEmpty = value.compare(0)
|
||||
}
|
||||
case class BigNumber(value: BigInt) extends Numeric {
|
||||
val order = 0
|
||||
override def compareToEmpty = value.compare(0)
|
||||
}
|
||||
case class Qualifier(value: String, level: Int) extends Item {
|
||||
val order = -2
|
||||
override def compareToEmpty = level.compare(0)
|
||||
}
|
||||
case class Literal(value: String) extends Item {
|
||||
val order = -1
|
||||
override def compareToEmpty = if (value.isEmpty) 0 else 1
|
||||
}
|
||||
|
||||
case object Min extends Item {
|
||||
val order = -8
|
||||
override def compareToEmpty = -1
|
||||
}
|
||||
case object Max extends Item {
|
||||
val order = 8
|
||||
}
|
||||
|
||||
val empty = Number(0)
|
||||
|
||||
val qualifiers = Seq[Qualifier](
|
||||
Qualifier("alpha", -5),
|
||||
Qualifier("beta", -4),
|
||||
Qualifier("milestone", -3),
|
||||
Qualifier("cr", -2),
|
||||
Qualifier("rc", -2),
|
||||
Qualifier("snapshot", -1),
|
||||
Qualifier("ga", 0),
|
||||
Qualifier("final", 0),
|
||||
Qualifier("sp", 1)
|
||||
)
|
||||
|
||||
val qualifiersMap = qualifiers.map(q => q.value -> q).toMap
|
||||
|
||||
object Tokenizer {
|
||||
sealed trait Separator
|
||||
case object Dot extends Separator
|
||||
case object Hyphen extends Separator
|
||||
case object Underscore extends Separator
|
||||
case object None extends Separator
|
||||
|
||||
def apply(s: String): (Item, Stream[(Separator, Item)]) = {
|
||||
def parseItem(s: Stream[Char]): (Item, Stream[Char]) = {
|
||||
if (s.isEmpty || !s.head.letterOrDigit) (empty, s)
|
||||
else if (s.head.isDigit) {
|
||||
def digits(b: StringBuilder, s: Stream[Char]): (String, Stream[Char]) =
|
||||
if (s.isEmpty || !s.head.isDigit) (b.result(), s)
|
||||
else digits(b + s.head, s.tail)
|
||||
|
||||
val (digits0, rem) = digits(new StringBuilder, s)
|
||||
val item =
|
||||
if (digits0.length >= 10) BigNumber(BigInt(digits0))
|
||||
else Number(digits0.toInt)
|
||||
|
||||
(item, rem)
|
||||
} else {
|
||||
assert(s.head.letter)
|
||||
|
||||
def letters(b: StringBuilder, s: Stream[Char]): (String, Stream[Char]) =
|
||||
if (s.isEmpty || !s.head.letter) (b.result().toLowerCase, s)
|
||||
else letters(b + s.head, s.tail)
|
||||
|
||||
val (letters0, rem) = letters(new StringBuilder, s)
|
||||
val item =
|
||||
qualifiersMap.getOrElse(letters0, Literal(letters0))
|
||||
|
||||
(item, rem)
|
||||
}
|
||||
}
|
||||
|
||||
def parseSeparator(s: Stream[Char]): (Separator, Stream[Char]) = {
|
||||
assert(s.nonEmpty)
|
||||
|
||||
s.head match {
|
||||
case '.' => (Dot, s.tail)
|
||||
case '-' => (Hyphen, s.tail)
|
||||
case '_' => (Underscore, s.tail)
|
||||
case _ => (None, s)
|
||||
}
|
||||
}
|
||||
|
||||
def helper(s: Stream[Char]): Stream[(Separator, Item)] = {
|
||||
if (s.isEmpty) Stream()
|
||||
else {
|
||||
val (sep, rem0) = parseSeparator(s)
|
||||
val (item, rem) = parseItem(rem0)
|
||||
|
||||
(sep, item) #:: helper(rem)
|
||||
}
|
||||
}
|
||||
|
||||
val (first, rem) = parseItem(s.toStream)
|
||||
(first, helper(rem))
|
||||
}
|
||||
}
|
||||
|
||||
def parse(s: String): ComparableVersion = {
|
||||
val (first, tokens) = Tokenizer(s)
|
||||
|
||||
def isNumeric(item: Item) = item match { case _: Numeric => true; case _ => false }
|
||||
|
||||
def postProcess(prevIsNumeric: Option[Boolean], item: Item, tokens0: Stream[(Tokenizer.Separator, Item)]): Stream[Item] = {
|
||||
val tokens = {
|
||||
var _tokens = tokens0
|
||||
|
||||
if (isNumeric(item)) {
|
||||
val nextNonDotZero = _tokens.dropWhile{case (Tokenizer.Dot, n: Numeric) => n.isEmpty; case _ => false }
|
||||
if (nextNonDotZero.forall(t => t._1 == Tokenizer.Hyphen || ((t._1 == Tokenizer.Dot || t._1 == Tokenizer.None) && !isNumeric(t._2)))) { // Dot && isNumeric(t._2)
|
||||
_tokens = nextNonDotZero
|
||||
}
|
||||
}
|
||||
|
||||
_tokens
|
||||
}
|
||||
|
||||
def ifFollowedByNumberElse(ifFollowedByNumber: Item, default: Item) = {
|
||||
val followedByNumber = tokens.headOption
|
||||
.exists{ case (Tokenizer.None, num: Numeric) if !num.isEmpty => true; case _ => false }
|
||||
|
||||
if (followedByNumber) ifFollowedByNumber
|
||||
else default
|
||||
}
|
||||
|
||||
def next =
|
||||
if (tokens.isEmpty) Stream()
|
||||
else postProcess(Some(isNumeric(item)), tokens.head._2, tokens.tail)
|
||||
|
||||
item match {
|
||||
case Literal("min") => Min #:: next
|
||||
case Literal("max") => Max #:: next
|
||||
case Literal("a") =>
|
||||
ifFollowedByNumberElse(qualifiersMap("alpha"), item) #:: next
|
||||
case Literal("b") =>
|
||||
ifFollowedByNumberElse(qualifiersMap("beta"), item) #:: next
|
||||
case Literal("m") =>
|
||||
ifFollowedByNumberElse(qualifiersMap("milestone"), item) #:: next
|
||||
case _ =>
|
||||
item #:: next
|
||||
}
|
||||
}
|
||||
|
||||
ComparableVersion(postProcess(None, first, tokens).toList)
|
||||
}
|
||||
|
||||
@tailrec
|
||||
def listCompare(first: List[Item], second: List[Item]): Int = {
|
||||
if (first.isEmpty && second.isEmpty) 0
|
||||
else if (first.isEmpty) {
|
||||
assert(second.nonEmpty)
|
||||
-second.dropWhile(_.isEmpty).headOption.fold(0)(_.compareToEmpty)
|
||||
} else if (second.isEmpty) {
|
||||
assert(first.nonEmpty)
|
||||
first.dropWhile(_.isEmpty).headOption.fold(0)(_.compareToEmpty)
|
||||
} else {
|
||||
val rel = first.head.compare(second.head)
|
||||
if (rel == 0) listCompare(first.tail, second.tail)
|
||||
else rel
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case class ComparableVersion(items: List[ComparableVersion.Item]) extends Ordered[ComparableVersion] {
|
||||
def compare(other: ComparableVersion) = ComparableVersion.listCompare(items, other.items)
|
||||
def isEmpty = items.forall(_.isEmpty)
|
||||
}
|
||||
|
|
@ -32,20 +32,44 @@ sealed abstract class Scope(val name: String)
|
|||
case class Dependency(module: Module,
|
||||
version: String,
|
||||
scope: Scope,
|
||||
`type`: String,
|
||||
classifier: String,
|
||||
artifacts: Artifacts,
|
||||
exclusions: Set[(String, String)],
|
||||
optional: Boolean) {
|
||||
def moduleVersion = (module, version)
|
||||
}
|
||||
|
||||
sealed trait Artifacts
|
||||
|
||||
object Artifacts {
|
||||
/**
|
||||
* May become a bit more complicated with Ivy support,
|
||||
* but should still point at one single artifact.
|
||||
*/
|
||||
case class Artifact(`type`: String,
|
||||
classifier: String)
|
||||
|
||||
sealed trait WithProject extends Artifacts {
|
||||
def artifacts(project: Project): Seq[Artifact]
|
||||
}
|
||||
|
||||
sealed trait Sufficient extends Artifacts {
|
||||
def artifacts: Seq[Artifact]
|
||||
}
|
||||
|
||||
case class Maven(`type`: String,
|
||||
classifier: String) extends Sufficient {
|
||||
def artifacts: Seq[Artifact] = Seq(Artifact(`type`, classifier))
|
||||
}
|
||||
}
|
||||
|
||||
case class Project(module: Module,
|
||||
version: String,
|
||||
dependencies: Seq[Dependency],
|
||||
parent: Option[(Module, String)],
|
||||
dependencyManagement: Seq[Dependency],
|
||||
properties: Map[String, String],
|
||||
profiles: Seq[Profile]) {
|
||||
profiles: Seq[Profile],
|
||||
versions: Option[Versions]) {
|
||||
def moduleVersion = (module, version)
|
||||
}
|
||||
|
||||
|
|
@ -66,3 +90,12 @@ case class Profile(id: String,
|
|||
dependencies: Seq[Dependency],
|
||||
dependencyManagement: Seq[Dependency],
|
||||
properties: Map[String, String])
|
||||
|
||||
case class Versions(latest: String,
|
||||
release: String,
|
||||
available: List[String],
|
||||
lastUpdated: Option[Versions.DateTime])
|
||||
|
||||
object Versions {
|
||||
case class DateTime(year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ object Parse {
|
|||
strTo = s0.drop(commaIdx + 1)
|
||||
from <- if (strFrom.isEmpty) Some(None) else version(strFrom).map(Some(_))
|
||||
to <- if (strTo.isEmpty) Some(None) else version(strTo).map(Some(_))
|
||||
} yield VersionInterval(from.filterNot(_.cmp.isEmpty), to.filterNot(_.cmp.isEmpty), fromIncluded, toIncluded)
|
||||
} yield VersionInterval(from.filterNot(_.isEmpty), to.filterNot(_.isEmpty), fromIncluded, toIncluded)
|
||||
}
|
||||
|
||||
def versionConstraint(s: String): Option[VersionConstraint] = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package coursier.core
|
||||
|
||||
import scalaz.{\/, EitherT}
|
||||
import scalaz.{-\/, \/-, \/, EitherT}
|
||||
import scalaz.concurrent.Task
|
||||
|
||||
trait Repository {
|
||||
|
|
@ -36,3 +36,38 @@ object CachePolicy {
|
|||
remote
|
||||
}
|
||||
}
|
||||
|
||||
trait MavenRepository extends Repository {
|
||||
|
||||
def find(module: Module,
|
||||
version: String,
|
||||
cachePolicy: CachePolicy): EitherT[Task, String, Project] = {
|
||||
|
||||
Parse.versionInterval(version).filter(_.isValid) match {
|
||||
case None => findNoInterval(module, version, cachePolicy)
|
||||
case Some(itv) =>
|
||||
versions(module.organization, module.name, cachePolicy).flatMap { versions0 =>
|
||||
val eitherVersion = {
|
||||
val release = Version(versions0.release)
|
||||
if (itv.contains(release)) \/-(versions0.release)
|
||||
else {
|
||||
val inInterval = versions0.available.map(Version(_)).filter(itv.contains)
|
||||
if (inInterval.isEmpty) -\/(s"No version found for $version")
|
||||
else \/-(inInterval.max.repr)
|
||||
}
|
||||
}
|
||||
|
||||
eitherVersion match {
|
||||
case -\/(reason) => EitherT[Task, String, Project](Task.now(-\/(reason)))
|
||||
case \/-(version0) => findNoInterval(module, version0, cachePolicy)
|
||||
.map(_.copy(versions = Some(versions0)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def findNoInterval(module: Module,
|
||||
version: String,
|
||||
cachePolicy: CachePolicy): EitherT[Task, String, Project]
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,9 @@ object Resolver {
|
|||
|
||||
type DepMgmtKey = (String, String, String)
|
||||
def dependencyManagementKey(dep: Dependency): DepMgmtKey =
|
||||
(dep.module.organization, dep.module.name, dep.`type`)
|
||||
dep.artifacts match {
|
||||
case Artifacts.Maven(type0, _) => (dep.module.organization, dep.module.name, type0)
|
||||
}
|
||||
def dependencyManagementAdd(m: Map[DepMgmtKey, Dependency], dep: Dependency): Map[DepMgmtKey, Dependency] = {
|
||||
val key = dependencyManagementKey(dep)
|
||||
if (m.contains(key)) m else m + (key -> dep)
|
||||
|
|
@ -119,7 +121,13 @@ object Resolver {
|
|||
name = substituteProps(dep.module.name)
|
||||
),
|
||||
version = substituteProps(dep.version),
|
||||
`type` = substituteProps(dep.`type`),
|
||||
artifacts = dep.artifacts match {
|
||||
case maven: Artifacts.Maven =>
|
||||
maven.copy(
|
||||
`type` = substituteProps(maven.`type`),
|
||||
classifier = substituteProps(maven.classifier)
|
||||
)
|
||||
},
|
||||
scope = Parse.scope(substituteProps(dep.scope.name)),
|
||||
exclusions = dep.exclusions
|
||||
.map{case (org, name) => (substituteProps(org), substituteProps(name))}
|
||||
|
|
@ -249,49 +257,6 @@ object Resolver {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersection of exclusions. A module is excluded by the result if it is excluded
|
||||
* by both `first` and `second`.
|
||||
*/
|
||||
def exclusionsIntersect(first: Set[(String, String)],
|
||||
second: Set[(String, String)]): Set[(String, String)] = {
|
||||
|
||||
val (firstAll, firstNonAll) = first.partition{case ("*", "*") => true; case _ => false }
|
||||
val (secondAll, secondNonAll) = second.partition{case ("*", "*") => true; case _ => false }
|
||||
|
||||
if (firstAll.nonEmpty && secondAll.nonEmpty) Set(("*", "*"))
|
||||
else {
|
||||
val firstOrgWildcards = firstNonAll.collect{ case ("*", name) => name }
|
||||
val firstNameWildcards = firstNonAll.collect{ case (org, "*") => org }
|
||||
val secondOrgWildcards = secondNonAll.collect{ case ("*", name) => name }
|
||||
val secondNameWildcards = secondNonAll.collect{ case (org, "*") => org }
|
||||
|
||||
val orgWildcards =
|
||||
(firstOrgWildcards intersect secondOrgWildcards) ++
|
||||
(if (secondAll.nonEmpty) firstOrgWildcards else Set.empty) ++
|
||||
(if (firstAll.nonEmpty) secondOrgWildcards else Set.empty)
|
||||
|
||||
val nameWildcards =
|
||||
(firstNameWildcards intersect secondNameWildcards) ++
|
||||
(if (secondAll.nonEmpty) firstNameWildcards else Set.empty) ++
|
||||
(if (firstAll.nonEmpty) secondNameWildcards else Set.empty)
|
||||
|
||||
val firstRemaining = firstNonAll.filter{ case (org, name) => org != "*" && name != "*" }
|
||||
val secondRemaining = secondNonAll.filter{ case (org, name) => org != "*" && name != "*" }
|
||||
|
||||
val remaining =
|
||||
(firstRemaining intersect secondRemaining) ++
|
||||
(if (secondAll.nonEmpty) firstRemaining else Set.empty) ++
|
||||
(if (firstAll.nonEmpty) secondRemaining else Set.empty) ++
|
||||
(if (secondOrgWildcards.nonEmpty) firstRemaining.filter(e => secondOrgWildcards(e._2)) else Set.empty) ++
|
||||
(if (firstOrgWildcards.nonEmpty) secondRemaining.filter(e => firstOrgWildcards(e._2)) else Set.empty) ++
|
||||
(if (secondNameWildcards.nonEmpty) firstRemaining.filter(e => secondNameWildcards(e._1)) else Set.empty) ++
|
||||
(if (firstNameWildcards.nonEmpty) secondRemaining.filter(e => firstNameWildcards(e._1)) else Set.empty)
|
||||
|
||||
orgWildcards.map(name => ("*", name)) ++ nameWildcards.map(org => (org, "*")) ++ remaining
|
||||
}
|
||||
}
|
||||
|
||||
def withDefaultScope(dep: Dependency): Dependency =
|
||||
if (dep.scope.name.isEmpty) dep.copy(scope = Scope.Compile)
|
||||
else dep
|
||||
|
|
@ -393,7 +358,7 @@ object Resolver {
|
|||
* Transitive dependencies of the current dependencies, according to what there currently is in cache.
|
||||
* No attempt is made to solve version conflicts here.
|
||||
*/
|
||||
def transitiveDependencies =
|
||||
def transitiveDependencies: Seq[Dependency] =
|
||||
for {
|
||||
dep <- (dependencies -- conflicts).toList
|
||||
trDep <- finalDependencies0(dep)
|
||||
|
|
@ -404,11 +369,11 @@ object Resolver {
|
|||
* trying to solve version conflicts. Transitive dependencies are calculated with the current cache.
|
||||
*
|
||||
* May contain dependencies added in previous iterations, but no more required. These are filtered below, see
|
||||
* @newDependencies.
|
||||
* `newDependencies`.
|
||||
*
|
||||
* Returns a tuple made of the conflicting dependencies, and all the dependencies.
|
||||
*/
|
||||
def nextDependenciesAndConflicts = {
|
||||
def nextDependenciesAndConflicts: (Seq[Dependency], Seq[Dependency]) = {
|
||||
merge(dependencies ++ transitiveDependencies)
|
||||
}
|
||||
|
||||
|
|
@ -436,23 +401,23 @@ object Resolver {
|
|||
missingFromCache.isEmpty && isFixPoint
|
||||
}
|
||||
|
||||
private def key(dep: Dependency) =
|
||||
(dep.module.organization, dep.module.name, dep.scope)
|
||||
private def eraseVersion(dep: Dependency) = dep.copy(version = "")
|
||||
|
||||
/**
|
||||
* Returns a map giving the dependency that brought each of the dependency of the "next" dependency set,
|
||||
* along with the exclusions that the source dependency adds to it.
|
||||
* Returns a map giving the dependencies that brought each of the dependency of the "next" dependency set.
|
||||
*
|
||||
* The versions of all the dependencies returned are erased (emptied).
|
||||
*/
|
||||
def reverseDependenciesAndExclusions = {
|
||||
def reverseDependencies: Map[Dependency, Vector[Dependency]] = {
|
||||
val (updatedConflicts, updatedDeps) = nextDependenciesAndConflicts
|
||||
|
||||
val trDepsSeq =
|
||||
for {
|
||||
dep <- updatedDeps
|
||||
trDep <- finalDependencies0(dep)
|
||||
} yield key(trDep) -> (key(dep), trDep.exclusions)
|
||||
} yield eraseVersion(trDep) -> eraseVersion(dep)
|
||||
|
||||
val knownDeps = (updatedDeps ++ updatedConflicts).map(key).toSet
|
||||
val knownDeps = (updatedDeps ++ updatedConflicts).map(eraseVersion).toSet
|
||||
|
||||
trDepsSeq
|
||||
.groupBy(_._1)
|
||||
|
|
@ -462,48 +427,38 @@ object Resolver {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a map, whose keys are the dependencies from the "next" dependency set,
|
||||
* filtering out those that are no more required, and whose values are the exclusions
|
||||
* added to them by the dependencies that brought them here.
|
||||
* Returns dependencies from the "next" dependency set, filtering out
|
||||
* those that are no more required.
|
||||
*
|
||||
* The versions of all the dependencies returned are erased (emptied).
|
||||
*/
|
||||
def remainingDependenciesAndExclusions = {
|
||||
val rootDependenciesExclusions = rootDependencies
|
||||
.map(dep => key(dep) -> dep.exclusions)
|
||||
.toMap
|
||||
|
||||
type D = (String, String, Scope)
|
||||
def remainingDependencies: Set[Dependency] = {
|
||||
val rootDependencies0 = rootDependencies.map(eraseVersion)
|
||||
|
||||
@tailrec
|
||||
def helper[T](reverseDeps: Map[D, Vector[(D, T)]]): Map[D, Vector[(D, T)]] = {
|
||||
val (toRemove, remaining) = reverseDeps.partition(kv => kv._2.isEmpty && !rootDependenciesExclusions.contains(kv._1))
|
||||
def helper(reverseDeps: Map[Dependency, Vector[Dependency]]): Map[Dependency, Vector[Dependency]] = {
|
||||
val (toRemove, remaining) = reverseDeps.partition(kv => kv._2.isEmpty && !rootDependencies0(kv._1))
|
||||
|
||||
if (toRemove.isEmpty) reverseDeps
|
||||
else helper(remaining.mapValues(_.filter(x => remaining.contains(x._1) || rootDependenciesExclusions.contains(x._1))).toList.toMap)
|
||||
else helper(remaining.mapValues(_.filter(x => remaining.contains(x) || rootDependencies0(x))).toList.toMap)
|
||||
}
|
||||
|
||||
val filteredReverseDependenciesAndExclusions = helper(reverseDependenciesAndExclusions)
|
||||
val filteredReverseDependencies = helper(reverseDependencies)
|
||||
|
||||
(rootDependenciesExclusions.keySet ++ filteredReverseDependenciesAndExclusions.keySet)
|
||||
.toList
|
||||
.map{case dep => dep ->
|
||||
(filteredReverseDependenciesAndExclusions.get(dep).map(_.map(_._2)).getOrElse(Nil) ++ rootDependenciesExclusions.get(dep))
|
||||
.reduce(exclusionsIntersect)
|
||||
}
|
||||
.toMap
|
||||
rootDependencies0 ++ filteredReverseDependencies.keys
|
||||
}
|
||||
|
||||
/**
|
||||
* The final next dependency set, stripped of no more required ones.
|
||||
*/
|
||||
def newDependencies = {
|
||||
val remainingDeps0 = remainingDependenciesAndExclusions
|
||||
def newDependencies: Set[Dependency] = {
|
||||
val remainingDependencies0 = remainingDependencies
|
||||
nextDependenciesAndConflicts._2
|
||||
.filter(dep => remainingDeps0.contains(key(dep)))
|
||||
.map(dep => dep.copy(exclusions = remainingDeps0(key(dep))))
|
||||
.filter(dep => remainingDependencies0(eraseVersion(dep)))
|
||||
.toSet
|
||||
}
|
||||
|
||||
private def nextNoMissingUnsafe(): Resolution = {
|
||||
private def nextNoMissingUnsafe: Resolution = {
|
||||
val (newConflicts, _) = nextDependenciesAndConflicts
|
||||
copy(dependencies = newDependencies ++ newConflicts, conflicts = newConflicts.toSet)
|
||||
}
|
||||
|
|
@ -512,9 +467,9 @@ object Resolver {
|
|||
* If no module info is missing, the next state of the resolution, which can be immediately calculated.
|
||||
* Else, the current resolution itself.
|
||||
*/
|
||||
def nextIfNoMissing(): Resolution = {
|
||||
def nextIfNoMissing: Resolution = {
|
||||
val missing = missingFromCache
|
||||
if (missing.isEmpty) nextNoMissingUnsafe()
|
||||
if (missing.isEmpty) nextNoMissingUnsafe
|
||||
else this
|
||||
}
|
||||
|
||||
|
|
@ -523,8 +478,8 @@ object Resolver {
|
|||
*/
|
||||
def next(fetchModule: ModuleVersion => EitherT[Task, List[String], (Repository, Project)]): Task[Resolution] = {
|
||||
val missing = missingFromCache
|
||||
if (missing.isEmpty) Task.now(nextNoMissingUnsafe())
|
||||
else fetch(missing.toList, fetchModule).map(_.nextIfNoMissing())
|
||||
if (missing.isEmpty) Task.now(nextNoMissingUnsafe)
|
||||
else fetch(missing.toList, fetchModule).map(_.nextIfNoMissing)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -636,20 +591,20 @@ object Resolver {
|
|||
val lookups = modules.map(dep => fetchModule(dep).run.map(dep -> _))
|
||||
val gatheredLookups = Task.gatherUnordered(lookups, exceptionCancels = true)
|
||||
gatheredLookups.flatMap{ lookupResults =>
|
||||
val errors0 = errors ++ lookupResults.collect{case (mod, -\/(repoErrors)) => mod -> repoErrors}
|
||||
val newProjects = lookupResults.collect{case (mod, \/-(proj)) => mod -> proj}
|
||||
val errors0 = errors ++ lookupResults.collect{case (modVer, -\/(repoErrors)) => modVer -> repoErrors}
|
||||
val newProjects = lookupResults.collect{case (modVer, \/-(proj)) => modVer -> proj}
|
||||
|
||||
/*
|
||||
* newProjects are project definitions, fresh from the repositories. We need to add
|
||||
* dependency management / inheritance-related bits to them.
|
||||
*/
|
||||
|
||||
newProjects.foldLeft(Task.now(copy(errors = errors0))) { case (accTask, (mod, (repo, proj))) =>
|
||||
newProjects.foldLeft(Task.now(copy(errors = errors0))) { case (accTask, (modVer, (repo, proj))) =>
|
||||
for {
|
||||
current <- accTask
|
||||
updated <- current.fetch(current.dependencyManagementMissing(proj).toList, fetchModule)
|
||||
proj0 = updated.withDependencyManagement(proj)
|
||||
} yield updated.copy(projectsCache = updated.projectsCache + (proj0.moduleVersion -> (repo, proj0)))
|
||||
} yield updated.copy(projectsCache = updated.projectsCache + (modVer -> (repo, proj0)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,104 +1,210 @@
|
|||
package coursier.core
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import coursier.core.compatibility._
|
||||
|
||||
case class Versions(latest: String,
|
||||
release: String,
|
||||
available: List[String],
|
||||
lastUpdated: Option[DateTime])
|
||||
|
||||
/** Used internally by Resolver */
|
||||
/**
|
||||
* Used internally by Resolver.
|
||||
*
|
||||
* Same kind of ordering as aether-util/src/main/java/org/eclipse/aether/util/version/GenericVersion.java
|
||||
*/
|
||||
case class Version(repr: String) extends Ordered[Version] {
|
||||
|
||||
lazy val cmp = ComparableVersion.parse(repr)
|
||||
|
||||
def compare(other: Version): Int = {
|
||||
cmp.compare(other.cmp)
|
||||
}
|
||||
lazy val items = Version.items(repr)
|
||||
def compare(other: Version) = Version.listCompare(items, other.items)
|
||||
def isEmpty = items.forall(_.isEmpty)
|
||||
}
|
||||
|
||||
case class VersionInterval(from: Option[Version],
|
||||
to: Option[Version],
|
||||
fromIncluded: Boolean,
|
||||
toIncluded: Boolean) {
|
||||
object Version {
|
||||
|
||||
def isValid: Boolean = {
|
||||
val fromToOrder =
|
||||
for {
|
||||
f <- from
|
||||
t <- to
|
||||
cmd = f.compare(t)
|
||||
} yield cmd < 0 || (cmd == 0 && fromIncluded && toIncluded)
|
||||
sealed trait Item extends Ordered[Item] {
|
||||
def compare(other: Item): Int =
|
||||
(this, other) match {
|
||||
case (Number(a), Number(b)) => a.compare(b)
|
||||
case (BigNumber(a), BigNumber(b)) => a.compare(b)
|
||||
case (Number(a), BigNumber(b)) => -b.compare(a)
|
||||
case (BigNumber(a), Number(b)) => a.compare(b)
|
||||
case (Qualifier(_, a), Qualifier(_, b)) => a.compare(b)
|
||||
case (Literal(a), Literal(b)) => a.compareToIgnoreCase(b)
|
||||
|
||||
fromToOrder.forall(x => x) && (from.nonEmpty || !fromIncluded) && (to.nonEmpty || !toIncluded)
|
||||
}
|
||||
case _ =>
|
||||
val rel0 = compareToEmpty
|
||||
val rel1 = other.compareToEmpty
|
||||
|
||||
def merge(other: VersionInterval): Option[VersionInterval] = {
|
||||
val (newFrom, newFromIncluded) =
|
||||
(from, other.from) match {
|
||||
case (Some(a), Some(b)) =>
|
||||
val cmp = a.compare(b)
|
||||
if (cmp < 0) (Some(b), other.fromIncluded)
|
||||
else if (cmp > 0) (Some(a), fromIncluded)
|
||||
else (Some(a), fromIncluded && other.fromIncluded)
|
||||
|
||||
case (Some(a), None) => (Some(a), fromIncluded)
|
||||
case (None, Some(b)) => (Some(b), other.fromIncluded)
|
||||
case (None, None) => (None, false)
|
||||
if (rel0 == rel1) order.compare(other.order)
|
||||
else rel0.compare(rel1)
|
||||
}
|
||||
|
||||
val (newTo, newToIncluded) =
|
||||
(to, other.to) match {
|
||||
case (Some(a), Some(b)) =>
|
||||
val cmp = a.compare(b)
|
||||
if (cmp < 0) (Some(a), toIncluded)
|
||||
else if (cmp > 0) (Some(b), other.toIncluded)
|
||||
else (Some(a), toIncluded && other.toIncluded)
|
||||
|
||||
case (Some(a), None) => (Some(a), toIncluded)
|
||||
case (None, Some(b)) => (Some(b), other.toIncluded)
|
||||
case (None, None) => (None, false)
|
||||
}
|
||||
|
||||
Some(VersionInterval(newFrom, newTo, newFromIncluded, newToIncluded))
|
||||
.filter(_.isValid)
|
||||
def order: Int
|
||||
def isEmpty: Boolean = compareToEmpty == 0
|
||||
def compareToEmpty: Int = 1
|
||||
}
|
||||
|
||||
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)
|
||||
sealed trait Numeric extends Item
|
||||
case class Number(value: Int) extends Numeric {
|
||||
val order = 0
|
||||
override def compareToEmpty = value.compare(0)
|
||||
}
|
||||
case class BigNumber(value: BigInt) extends Numeric {
|
||||
val order = 0
|
||||
override def compareToEmpty = value.compare(0)
|
||||
}
|
||||
case class Qualifier(value: String, level: Int) extends Item {
|
||||
val order = -2
|
||||
override def compareToEmpty = level.compare(0)
|
||||
}
|
||||
case class Literal(value: String) extends Item {
|
||||
val order = -1
|
||||
override def compareToEmpty = if (value.isEmpty) 0 else 1
|
||||
}
|
||||
|
||||
case object Min extends Item {
|
||||
val order = -8
|
||||
override def compareToEmpty = -1
|
||||
}
|
||||
case object Max extends Item {
|
||||
val order = 8
|
||||
}
|
||||
|
||||
val empty = Number(0)
|
||||
|
||||
val qualifiers = Seq[Qualifier](
|
||||
Qualifier("alpha", -5),
|
||||
Qualifier("beta", -4),
|
||||
Qualifier("milestone", -3),
|
||||
Qualifier("cr", -2),
|
||||
Qualifier("rc", -2),
|
||||
Qualifier("snapshot", -1),
|
||||
Qualifier("ga", 0),
|
||||
Qualifier("final", 0),
|
||||
Qualifier("sp", 1)
|
||||
)
|
||||
|
||||
val qualifiersMap = qualifiers.map(q => q.value -> q).toMap
|
||||
|
||||
object Tokenizer {
|
||||
sealed trait Separator
|
||||
case object Dot extends Separator
|
||||
case object Hyphen extends Separator
|
||||
case object Underscore extends Separator
|
||||
case object None extends Separator
|
||||
|
||||
def apply(s: String): (Item, Stream[(Separator, Item)]) = {
|
||||
def parseItem(s: Stream[Char]): (Item, Stream[Char]) = {
|
||||
if (s.isEmpty || !s.head.letterOrDigit) (empty, s)
|
||||
else if (s.head.isDigit) {
|
||||
def digits(b: StringBuilder, s: Stream[Char]): (String, Stream[Char]) =
|
||||
if (s.isEmpty || !s.head.isDigit) (b.result(), s)
|
||||
else digits(b + s.head, s.tail)
|
||||
|
||||
val (digits0, rem) = digits(new StringBuilder, s)
|
||||
val item =
|
||||
if (digits0.length >= 10) BigNumber(BigInt(digits0))
|
||||
else Number(digits0.toInt)
|
||||
|
||||
(item, rem)
|
||||
} else {
|
||||
assert(s.head.letter)
|
||||
|
||||
def letters(b: StringBuilder, s: Stream[Char]): (String, Stream[Char]) =
|
||||
if (s.isEmpty || !s.head.letter) (b.result().toLowerCase, s)
|
||||
else letters(b + s.head, s.tail)
|
||||
|
||||
val (letters0, rem) = letters(new StringBuilder, s)
|
||||
val item =
|
||||
qualifiersMap.getOrElse(letters0, Literal(letters0))
|
||||
|
||||
(item, rem)
|
||||
}
|
||||
}
|
||||
|
||||
def parseSeparator(s: Stream[Char]): (Separator, Stream[Char]) = {
|
||||
assert(s.nonEmpty)
|
||||
|
||||
s.head match {
|
||||
case '.' => (Dot, s.tail)
|
||||
case '-' => (Hyphen, s.tail)
|
||||
case '_' => (Underscore, s.tail)
|
||||
case _ => (None, s)
|
||||
}
|
||||
}
|
||||
|
||||
def helper(s: Stream[Char]): Stream[(Separator, Item)] = {
|
||||
if (s.isEmpty) Stream()
|
||||
else {
|
||||
val (sep, rem0) = parseSeparator(s)
|
||||
val (item, rem) = parseItem(rem0)
|
||||
|
||||
(sep, item) #:: helper(rem)
|
||||
}
|
||||
}
|
||||
|
||||
val (first, rem) = parseItem(s.toStream)
|
||||
(first, helper(rem))
|
||||
}
|
||||
}
|
||||
|
||||
def items(repr: String): List[Item] = {
|
||||
val (first, tokens) = Tokenizer(repr)
|
||||
|
||||
def isNumeric(item: Item) = item match { case _: Numeric => true; case _ => false }
|
||||
|
||||
def postProcess(prevIsNumeric: Option[Boolean], item: Item, tokens0: Stream[(Tokenizer.Separator, Item)]): Stream[Item] = {
|
||||
val tokens = {
|
||||
var _tokens = tokens0
|
||||
|
||||
if (isNumeric(item)) {
|
||||
val nextNonDotZero = _tokens.dropWhile{case (Tokenizer.Dot, n: Numeric) => n.isEmpty; case _ => false }
|
||||
if (nextNonDotZero.forall(t => t._1 == Tokenizer.Hyphen || ((t._1 == Tokenizer.Dot || t._1 == Tokenizer.None) && !isNumeric(t._2)))) { // Dot && isNumeric(t._2)
|
||||
_tokens = nextNonDotZero
|
||||
}
|
||||
}
|
||||
|
||||
_tokens
|
||||
}
|
||||
|
||||
def ifFollowedByNumberElse(ifFollowedByNumber: Item, default: Item) = {
|
||||
val followedByNumber = tokens.headOption
|
||||
.exists{ case (Tokenizer.None, num: Numeric) if !num.isEmpty => true; case _ => false }
|
||||
|
||||
if (followedByNumber) ifFollowedByNumber
|
||||
else default
|
||||
}
|
||||
|
||||
def next =
|
||||
if (tokens.isEmpty) Stream()
|
||||
else postProcess(Some(isNumeric(item)), tokens.head._2, tokens.tail)
|
||||
|
||||
item match {
|
||||
case Literal("min") => Min #:: next
|
||||
case Literal("max") => Max #:: next
|
||||
case Literal("a") =>
|
||||
ifFollowedByNumberElse(qualifiersMap("alpha"), item) #:: next
|
||||
case Literal("b") =>
|
||||
ifFollowedByNumberElse(qualifiersMap("beta"), item) #:: next
|
||||
case Literal("m") =>
|
||||
ifFollowedByNumberElse(qualifiersMap("milestone"), item) #:: next
|
||||
case _ =>
|
||||
item #:: next
|
||||
}
|
||||
}
|
||||
|
||||
def repr: String = Seq(
|
||||
if (fromIncluded) "[" else "(",
|
||||
from.map(_.repr).mkString,
|
||||
",",
|
||||
to.map(_.repr).mkString,
|
||||
if (toIncluded) "]" else ")"
|
||||
).mkString
|
||||
}
|
||||
postProcess(None, first, tokens).toList
|
||||
}
|
||||
|
||||
object VersionInterval {
|
||||
val zero = VersionInterval(None, None, fromIncluded = false, toIncluded = false)
|
||||
}
|
||||
@tailrec
|
||||
def listCompare(first: List[Item], second: List[Item]): Int = {
|
||||
if (first.isEmpty && second.isEmpty) 0
|
||||
else if (first.isEmpty) {
|
||||
assert(second.nonEmpty)
|
||||
-second.dropWhile(_.isEmpty).headOption.fold(0)(_.compareToEmpty)
|
||||
} else if (second.isEmpty) {
|
||||
assert(first.nonEmpty)
|
||||
first.dropWhile(_.isEmpty).headOption.fold(0)(_.compareToEmpty)
|
||||
} else {
|
||||
val rel = first.head.compare(second.head)
|
||||
if (rel == 0) listCompare(first.tail, second.tail)
|
||||
else rel
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait VersionConstraint {
|
||||
def interval: VersionInterval
|
||||
def repr: String
|
||||
}
|
||||
object VersionConstraint {
|
||||
/** Currently treated as minimum... */
|
||||
case class Preferred(version: Version) extends VersionConstraint {
|
||||
def interval: VersionInterval = VersionInterval(Some(version), Option.empty, fromIncluded = true, toIncluded = false)
|
||||
def repr: String = version.repr
|
||||
}
|
||||
case class Interval(interval: VersionInterval) extends VersionConstraint {
|
||||
def repr: String = interval.repr
|
||||
}
|
||||
case object None extends VersionConstraint {
|
||||
val interval = VersionInterval.zero
|
||||
def repr: String = "" // Once parsed, "(,)" becomes "" because of this
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
package coursier.core
|
||||
|
||||
case class VersionInterval(from: Option[Version],
|
||||
to: Option[Version],
|
||||
fromIncluded: Boolean,
|
||||
toIncluded: Boolean) {
|
||||
|
||||
def isValid: Boolean = {
|
||||
val fromToOrder =
|
||||
for {
|
||||
f <- from
|
||||
t <- to
|
||||
cmd = f.compare(t)
|
||||
} yield cmd < 0 || (cmd == 0 && fromIncluded && toIncluded)
|
||||
|
||||
fromToOrder.forall(x => x) && (from.nonEmpty || !fromIncluded) && (to.nonEmpty || !toIncluded)
|
||||
}
|
||||
|
||||
def contains(version: Version): Boolean = {
|
||||
val fromCond =
|
||||
from.forall { from0 =>
|
||||
val cmp = from0.compare(version)
|
||||
cmp < 0 || cmp == 0 && fromIncluded
|
||||
}
|
||||
lazy val toCond =
|
||||
to.forall { to0 =>
|
||||
val cmp = version.compare(to0)
|
||||
cmp < 0 || cmp == 0 && toIncluded
|
||||
}
|
||||
|
||||
fromCond && toCond
|
||||
}
|
||||
|
||||
def merge(other: VersionInterval): Option[VersionInterval] = {
|
||||
val (newFrom, newFromIncluded) =
|
||||
(from, other.from) match {
|
||||
case (Some(a), Some(b)) =>
|
||||
val cmp = a.compare(b)
|
||||
if (cmp < 0) (Some(b), other.fromIncluded)
|
||||
else if (cmp > 0) (Some(a), fromIncluded)
|
||||
else (Some(a), fromIncluded && other.fromIncluded)
|
||||
|
||||
case (Some(a), None) => (Some(a), fromIncluded)
|
||||
case (None, Some(b)) => (Some(b), other.fromIncluded)
|
||||
case (None, None) => (None, false)
|
||||
}
|
||||
|
||||
val (newTo, newToIncluded) =
|
||||
(to, other.to) match {
|
||||
case (Some(a), Some(b)) =>
|
||||
val cmp = a.compare(b)
|
||||
if (cmp < 0) (Some(a), toIncluded)
|
||||
else if (cmp > 0) (Some(b), other.toIncluded)
|
||||
else (Some(a), toIncluded && other.toIncluded)
|
||||
|
||||
case (Some(a), None) => (Some(a), toIncluded)
|
||||
case (None, Some(b)) => (Some(b), other.toIncluded)
|
||||
case (None, None) => (None, false)
|
||||
}
|
||||
|
||||
Some(VersionInterval(newFrom, newTo, newFromIncluded, newToIncluded))
|
||||
.filter(_.isValid)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
def repr: String = Seq(
|
||||
if (fromIncluded) "[" else "(",
|
||||
from.map(_.repr).mkString,
|
||||
",",
|
||||
to.map(_.repr).mkString,
|
||||
if (toIncluded) "]" else ")"
|
||||
).mkString
|
||||
}
|
||||
|
||||
object VersionInterval {
|
||||
val zero = VersionInterval(None, None, fromIncluded = false, toIncluded = false)
|
||||
}
|
||||
|
||||
sealed trait VersionConstraint {
|
||||
def interval: VersionInterval
|
||||
def repr: String
|
||||
}
|
||||
object VersionConstraint {
|
||||
/** Currently treated as minimum... */
|
||||
case class Preferred(version: Version) extends VersionConstraint {
|
||||
def interval: VersionInterval = VersionInterval(Some(version), Option.empty, fromIncluded = true, toIncluded = false)
|
||||
def repr: String = version.repr
|
||||
}
|
||||
case class Interval(interval: VersionInterval) extends VersionConstraint {
|
||||
def repr: String = interval.repr
|
||||
}
|
||||
case object None extends VersionConstraint {
|
||||
val interval = VersionInterval.zero
|
||||
def repr: String = "" // Once parsed, "(,)" becomes "" because of this
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
package coursier.core
|
||||
|
||||
import coursier.core.compatibility.DateTime
|
||||
|
||||
import scalaz._
|
||||
|
||||
object Xml {
|
||||
|
|
@ -87,8 +85,7 @@ object Xml {
|
|||
mod,
|
||||
version0,
|
||||
scopeOpt getOrElse defaultScope,
|
||||
typeOpt getOrElse defaultType,
|
||||
classifierOpt getOrElse defaultClassifier,
|
||||
Artifacts.Maven(typeOpt getOrElse defaultType, classifierOpt getOrElse defaultClassifier),
|
||||
exclusions.map(mod => (mod.organization, mod.name)).toSet,
|
||||
optional
|
||||
)
|
||||
|
|
@ -117,17 +114,18 @@ object Xml {
|
|||
def profile(node: Node): String \/ Profile = {
|
||||
import Scalaz._
|
||||
|
||||
val id = text(node, "id", "Profile ID").getOrElse("")
|
||||
|
||||
val xmlActivationOpt = node.child
|
||||
.find(_.label == "activation")
|
||||
val (activeByDefault, activation) = xmlActivationOpt.fold((Option.empty[Boolean], Activation(Nil)))(profileActivation)
|
||||
|
||||
val xmlDeps = node.child
|
||||
.find(_.label == "dependencies")
|
||||
.map(_.child.filter(_.label == "dependency"))
|
||||
.getOrElse(Seq.empty)
|
||||
|
||||
for {
|
||||
id <- text(node, "id", "Profile ID")
|
||||
|
||||
xmlActivationOpt = node.child
|
||||
.find(_.label == "activation")
|
||||
(activeByDefault, activation) = xmlActivationOpt.fold((Option.empty[Boolean], Activation(Nil)))(profileActivation)
|
||||
|
||||
xmlDeps = node.child
|
||||
.find(_.label == "dependencies")
|
||||
.map(_.child.filter(_.label == "dependency"))
|
||||
.getOrElse(Seq.empty)
|
||||
deps <- xmlDeps.toList.traverseU(dependency)
|
||||
|
||||
xmlDepMgmts = node.child
|
||||
|
|
@ -141,6 +139,7 @@ object Xml {
|
|||
.find(_.label == "properties")
|
||||
.map(_.child.collect{case elem if elem.isElement => elem})
|
||||
.getOrElse(Seq.empty)
|
||||
|
||||
properties <- {
|
||||
import Scalaz._
|
||||
xmlProperties.toList.traverseU(property)
|
||||
|
|
@ -210,7 +209,8 @@ object Xml {
|
|||
parentModuleOpt.map((_, parentVersionOpt.getOrElse(""))),
|
||||
depMgmts,
|
||||
properties.toMap,
|
||||
profiles
|
||||
profiles,
|
||||
None
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -238,7 +238,7 @@ object Xml {
|
|||
lastUpdatedOpt = text(xmlVersioning, "lastUpdated", "Last update date and time")
|
||||
.toOption
|
||||
.filter(s => s.length == 14 && s.forall(_.isDigit))
|
||||
.map(s => DateTime(
|
||||
.map(s => Versions.DateTime(
|
||||
s.substring(0, 4).toInt,
|
||||
s.substring(4, 6).toInt,
|
||||
s.substring(6, 8).toInt,
|
||||
|
|
|
|||
|
|
@ -1,263 +0,0 @@
|
|||
package coursier.core.compatibility
|
||||
|
||||
// Cut-n-pasted from http4s 0.7.0
|
||||
// Replaced Writer usages with StringBuilder
|
||||
|
||||
final class DateTime private (val year: Int, // the year
|
||||
val month: Int, // the month of the year. January is 1.
|
||||
val day: Int, // the day of the month. The first day is 1.
|
||||
val hour: Int, // the hour of the day. The first hour is 0.
|
||||
val minute: Int, // the minute of the hour. The first minute is 0.
|
||||
val second: Int, // the second of the minute. The first second is 0.
|
||||
val weekday: Int, // the day of the week. Sunday is 0.
|
||||
val clicks: Long) // milliseconds since January 1, 1970, 00:00:00 GMT
|
||||
extends Ordered[DateTime] with Product6[Int, Int, Int, Int, Int, Int] {
|
||||
import DateTime.StringBuilderExtensions
|
||||
|
||||
/**
|
||||
* The day of the week as a 3 letter abbreviation:
|
||||
* `Sun`, `Mon`, `Tue`, `Wed`, `Thu`, `Fri` or `Sat`
|
||||
*/
|
||||
def weekdayStr: String = DateTime.WEEKDAYS(weekday)
|
||||
|
||||
/**
|
||||
* The day of the month as a 3 letter abbreviation:
|
||||
* `Jan`, `Feb`, `Mar`, `Apr`, `May`, `Jun`, `Jul`, `Aug`, `Sep`, `Oct`, `Nov` or `Dec`
|
||||
*/
|
||||
def monthStr: String = DateTime.MONTHS(month - 1)
|
||||
|
||||
/**
|
||||
* Creates a new `DateTime` that represents the point in time the given number of ms later.
|
||||
*/
|
||||
def +(millis: Long): DateTime = DateTime(clicks + millis)
|
||||
|
||||
/**
|
||||
* Creates a new `DateTime` that represents the point in time the given number of ms earlier.
|
||||
*/
|
||||
def -(millis: Long): DateTime = DateTime(clicks - millis)
|
||||
|
||||
/**
|
||||
* `yyyy-mm-ddThh:mm:ss`
|
||||
*/
|
||||
override def toString = toIsoDateTimeString
|
||||
|
||||
/**
|
||||
* `yyyy-mm-dd`
|
||||
*/
|
||||
def renderIsoDate(w: StringBuilder): w.type = {
|
||||
put_##(put_##(w << year << '-', month) << '-', day)
|
||||
w
|
||||
}
|
||||
|
||||
/**
|
||||
* `yyyy-mm-dd`
|
||||
*/
|
||||
def toIsoDateString = { val w = new StringBuilder; renderIsoDate(w).result() }
|
||||
|
||||
/**
|
||||
* `yyyy-mm-ddThh:mm:ss`
|
||||
*/
|
||||
def renderIsoDateTimeString(w: StringBuilder): w.type = {
|
||||
put_##(put_##(put_##(renderIsoDate(w) << 'T', hour) << ':', minute) << ':', second)
|
||||
w
|
||||
}
|
||||
|
||||
/**
|
||||
* `yyyy-mm-ddThh:mm:ss`
|
||||
*/
|
||||
def toIsoDateTimeString = { val w = new StringBuilder; renderIsoDateTimeString(w).result() }
|
||||
|
||||
/**
|
||||
* `yyyy-mm-dd hh:mm:ss`
|
||||
*/
|
||||
def renderIsoLikeDateTimeString(w: StringBuilder): w.type = {
|
||||
put_##(put_##(put_##(renderIsoDate(w) << ' ', hour) << ':', minute) << ':', second)
|
||||
w
|
||||
}
|
||||
|
||||
/**
|
||||
* `yyyy-mm-dd hh:mm:ss`
|
||||
*/
|
||||
def toIsoLikeDateTimeString = { val w = new StringBuilder; renderIsoLikeDateTimeString(w).result() }
|
||||
|
||||
/**
|
||||
* RFC1123 date string, e.g. `Sun, 06 Nov 1994 08:49:37 GMT`
|
||||
*/
|
||||
def renderRfc1123DateTimeString(w: StringBuilder): w.type = {
|
||||
w ++= weekdayStr
|
||||
w ++= ", "
|
||||
put_##(put_##(put_##(put_##(w << weekdayStr << ',' << ' ', day) << ' ' << monthStr << ' ' << year << ' ', hour) << ':', minute) << ':', second) << " GMT"
|
||||
w
|
||||
}
|
||||
|
||||
/**
|
||||
* RFC1123 date string, e.g. `Sun, 06 Nov 1994 08:49:37 GMT`
|
||||
*/
|
||||
def toRfc1123DateTimeString = { val w = new StringBuilder; renderRfc1123DateTimeString(w).result() }
|
||||
|
||||
private def put_##(w: StringBuilder, i: Int): w.type = {
|
||||
w << (i / 10 + '0').toChar << (i % 10 + '0').toChar
|
||||
w
|
||||
}
|
||||
|
||||
def compare(that: DateTime): Int = math.signum(clicks - that.clicks).toInt
|
||||
|
||||
override def hashCode() = clicks.##
|
||||
|
||||
override def equals(obj: Any) = obj match {
|
||||
case x: DateTime ⇒ x.clicks == clicks
|
||||
case _ ⇒ false
|
||||
}
|
||||
|
||||
override def _1: Int = year
|
||||
override def _2: Int = month
|
||||
override def _3: Int = day
|
||||
override def _4: Int = hour
|
||||
override def _5: Int = minute
|
||||
override def _6: Int = second
|
||||
|
||||
override def canEqual(that: Any): Boolean = that.isInstanceOf[DateTime]
|
||||
}
|
||||
|
||||
object DateTime {
|
||||
|
||||
private implicit class StringBuilderExtensions(val b: StringBuilder) extends AnyVal {
|
||||
def <<(s: String): b.type = b ++= s
|
||||
def <<(c: Char): b.type = b += c
|
||||
def <<(n: Int): b.type = b ++= n.toString
|
||||
}
|
||||
|
||||
val WEEKDAYS = Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")
|
||||
val MONTHS = Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
|
||||
val MinValue = DateTime(1800, 1, 1)
|
||||
val MaxValue = DateTime(2199, 12, 31, 23, 59, 59)
|
||||
|
||||
/**
|
||||
* Creates a new `DateTime` with the given properties.
|
||||
* Note that this implementation discards milliseconds (i.e. rounds down to full seconds).
|
||||
*/
|
||||
def apply(year: Int, month: Int, day: Int, hour: Int = 0, minute: Int = 0, second: Int = 0): DateTime = {
|
||||
require(1800 <= year && year <= 9999, "year must be >= 1800 and <= 9999")
|
||||
require(1 <= month && month <= 12, "month must be >= 1 and <= 12")
|
||||
require(1 <= day && day <= 31, "day must be >= 1 and <= 31")
|
||||
require(0 <= hour && hour <= 23, "hour must be >= 0 and <= 23")
|
||||
require(0 <= minute && minute <= 59, "minute_ must be >= 0 and <= 59")
|
||||
require(0 <= second && second <= 59, "second must be >= 0 and <= 59")
|
||||
|
||||
// compute yearday from month/monthday
|
||||
val m = month - 1
|
||||
var d = (m % 7) * 30 + (m % 7 + 1) / 2 + day
|
||||
val isLeap = ((year % 4 == 0) && !(year % 100 == 0)) || (year % 400 == 0)
|
||||
if (m >= 7) d += 214
|
||||
if (d >= 61) d -= 1 // skip non-existent Feb 30
|
||||
if (!isLeap && (d >= 60)) d -= 1 // skip non-existent Feb 29
|
||||
|
||||
// convert year/yearday to days since Jan 1, 1970, 00:00:00
|
||||
val y = year - 1
|
||||
d += y * 365 + y / 4 - y / 100 + y / 400
|
||||
val dn = d - (1969 * 365 + 492 - 19 + 4)
|
||||
val c = (dn - 1) * 86400L + hour * 3600L + minute * 60L + second // seconds since Jan 1, 1970, 00:00:00
|
||||
|
||||
new DateTime(year, month, day, hour, minute, second, weekday = d % 7, clicks = c * 1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `DateTime` from the number of milli seconds
|
||||
* since the start of "the epoch", namely January 1, 1970, 00:00:00 GMT.
|
||||
* Note that this implementation discards milliseconds (i.e. rounds down to full seconds).
|
||||
*/
|
||||
def apply(clicks: Long): DateTime = {
|
||||
require(DateTime.MinValue.clicks <= clicks && clicks <= DateTime.MaxValue.clicks,
|
||||
"DateTime value must be >= " + DateTime.MinValue + " and <= " + DateTime.MaxValue)
|
||||
|
||||
// based on a fast RFC1123 implementation (C) 2000 by Tim Kientzle <kientzle@acm.org>
|
||||
val c = clicks - clicks % 1000
|
||||
|
||||
// compute day number, seconds since beginning of day
|
||||
var s = c
|
||||
if (s >= 0) s /= 1000 // seconds since 1 Jan 1970
|
||||
else s = (s - 999) / 1000 // floor(sec/1000)
|
||||
|
||||
var dn = (s / 86400).toInt
|
||||
s %= 86400 // positive seconds since beginning of day
|
||||
if (s < 0) { s += 86400; dn -= 1 }
|
||||
dn += 1969 * 365 + 492 - 19 + 4 // days since "1 Jan, year 1"
|
||||
|
||||
// convert days since 1 Jan, year 1 to year/yearday
|
||||
var y = 400 * (dn / 146097).toInt + 1
|
||||
var d = dn % 146097
|
||||
if (d == 146096) { y += 399; d = 365 } // last year of 400 is long
|
||||
else {
|
||||
y += 100 * (d / 36524)
|
||||
d %= 36524
|
||||
y += 4 * (d / 1461)
|
||||
d %= 1461
|
||||
if (d == 1460) { y += 3; d = 365 } // last year out of 4 is long
|
||||
else {
|
||||
y += d / 365
|
||||
d %= 365
|
||||
}
|
||||
}
|
||||
|
||||
val isLeap = ((y % 4 == 0) && !(y % 100 == 0)) || (y % 400 == 0)
|
||||
|
||||
// compute month/monthday from year/yearday
|
||||
if (!isLeap && (d >= 59)) d += 1 // skip non-existent Feb 29
|
||||
if (d >= 60) d += 1 // skip non-existent Feb 30
|
||||
var mon = ((d % 214) / 61) * 2 + ((d % 214) % 61) / 31
|
||||
if (d > 213) mon += 7
|
||||
d = ((d % 214) % 61) % 31 + 1
|
||||
|
||||
// convert second to hour/min/sec
|
||||
var m = (s / 60).toInt
|
||||
val h = m / 60
|
||||
m %= 60
|
||||
s %= 60
|
||||
val w = (dn + 1) % 7 // day of week, 0==Sun
|
||||
|
||||
new DateTime(year = y, month = mon + 1, day = d, hour = h, minute = m, second = s.toInt, weekday = w, clicks = c)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `DateTime` instance for the current point in time.
|
||||
* Note that this implementation discards milliseconds (i.e. rounds down to full seconds).
|
||||
*/
|
||||
def now: DateTime = apply(System.currentTimeMillis)
|
||||
|
||||
/**
|
||||
* Creates a new DateTime instance from the given String,
|
||||
* if it adheres to the format `yyyy-mm-ddThh:mm:ss[.SSSZ]`.
|
||||
* Note that this implementation discards milliseconds (i.e. rounds down to full seconds).
|
||||
*/
|
||||
def fromIsoDateTimeString(string: String): Option[DateTime] = {
|
||||
def c(ix: Int) = string.charAt(ix)
|
||||
def isDigit(c: Char) = '0' <= c && c <= '9'
|
||||
def i(ix: Int) = {
|
||||
val x = c(ix)
|
||||
require(isDigit(x))
|
||||
x - '0'
|
||||
}
|
||||
def check(len: Int): Boolean =
|
||||
len match {
|
||||
case 19 ⇒ c(4) == '-' && c(7) == '-' && c(10) == 'T' && c(13) == ':' && c(16) == ':'
|
||||
case 24 ⇒ check(19) && c(19) == '.' && isDigit(c(20)) && isDigit(c(21)) && isDigit(c(22)) && c(23) == 'Z'
|
||||
case _ ⇒ false
|
||||
}
|
||||
if (check(string.length)) {
|
||||
try {
|
||||
val year = i(0) * 1000 + i(1) * 100 + i(2) * 10 + i(3)
|
||||
val month = i(5) * 10 + i(6)
|
||||
val day = i(8) * 10 + i(9)
|
||||
val hour = i(11) * 10 + i(12)
|
||||
val min = i(14) * 10 + i(15)
|
||||
val sec = i(17) * 10 + i(18)
|
||||
Some(DateTime(year, month, day, hour, min, sec))
|
||||
} catch { case _: IllegalArgumentException ⇒ None }
|
||||
} else None
|
||||
}
|
||||
|
||||
val UnixEpoch = DateTime(0L)
|
||||
|
||||
def unapply(dt: DateTime): Option[(Int, Int, Int, Int, Int, Int)] =
|
||||
Some((dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second))
|
||||
}
|
||||
|
|
@ -7,12 +7,21 @@ package object coursier {
|
|||
object Dependency {
|
||||
def apply(module: Module,
|
||||
version: String,
|
||||
scope: Scope = Scope.Other(""), // Subsituted by Resolver with its own default scope (compile)
|
||||
`type`: String = "jar",
|
||||
classifier: String = "",
|
||||
scope: Scope = Scope.Other(""), // Substituted by Resolver with its own default scope (compile)
|
||||
artifacts: Artifacts = Artifacts.Maven(),
|
||||
exclusions: Set[(String, String)] = Set.empty,
|
||||
optional: Boolean = false): Dependency =
|
||||
core.Dependency(module, version, scope, `type`, classifier, exclusions, optional)
|
||||
core.Dependency(module, version, scope, artifacts, exclusions, optional)
|
||||
}
|
||||
|
||||
type Artifacts = core.Artifacts
|
||||
object Artifacts {
|
||||
type Maven = core.Artifacts.Maven
|
||||
object Maven {
|
||||
def apply(`type`: String = "jar",
|
||||
classifier: String = ""): Maven =
|
||||
core.Artifacts.Maven(`type`, classifier)
|
||||
}
|
||||
}
|
||||
|
||||
type Project = core.Project
|
||||
|
|
@ -23,8 +32,9 @@ package object coursier {
|
|||
parent: Option[ModuleVersion] = None,
|
||||
dependencyManagement: Seq[Dependency] = Seq.empty,
|
||||
properties: Map[String, String] = Map.empty,
|
||||
profiles: Seq[Profile] = Seq.empty): Project =
|
||||
core.Project(module, version, dependencies, parent, dependencyManagement, properties, profiles)
|
||||
profiles: Seq[Profile] = Seq.empty,
|
||||
versions: Option[core.Versions] = None): Project =
|
||||
core.Project(module, version, dependencies, parent, dependencyManagement, properties, profiles, versions)
|
||||
}
|
||||
|
||||
type Profile = core.Profile
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
com.chuusai:shapeless_2.11:jar:2.2.0
|
||||
com.github.alexarchambault:argonaut-shapeless_6.1_2.11:jar:0.2.0
|
||||
com.github.julien-truffaut:monocle-core_2.11:jar:1.1.0
|
||||
com.github.julien-truffaut:monocle-macro_2.11:jar:1.1.0
|
||||
io.argonaut:argonaut_2.11:jar:6.1
|
||||
org.scala-lang.modules:scala-parser-combinators_2.11:jar:1.0.2
|
||||
org.scala-lang.modules:scala-xml_2.11:jar:1.0.2
|
||||
org.scala-lang:scala-library:jar:2.11.6
|
||||
org.scala-lang:scala-reflect:jar:2.11.6
|
||||
org.scalaz:scalaz-core_2.11:jar:7.1.1
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
com.chuusai:shapeless_2.11:jar:2.2.0
|
||||
com.github.alexarchambault:argonaut-shapeless_6.1_2.11:jar:0.2.0
|
||||
com.github.julien-truffaut:monocle-core_2.11:jar:1.1.0
|
||||
com.github.julien-truffaut:monocle-macro_2.11:jar:1.1.0
|
||||
io.argonaut:argonaut_2.11:jar:6.1
|
||||
org.scala-lang.modules:scala-parser-combinators_2.11:jar:1.0.2
|
||||
org.scala-lang.modules:scala-xml_2.11:jar:1.0.2
|
||||
org.scala-lang:scala-library:jar:2.11.6
|
||||
org.scala-lang:scala-reflect:jar:2.11.6
|
||||
org.scalaz:scalaz-core_2.11:jar:7.1.1
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
aopalliance:aopalliance:jar:1.0
|
||||
asm:asm:jar:3.1
|
||||
com.clearspring.analytics:stream:jar:2.7.0
|
||||
com.esotericsoftware.kryo:kryo:jar:2.21
|
||||
com.esotericsoftware.minlog:minlog:jar:1.2
|
||||
com.esotericsoftware.reflectasm:reflectasm:jar:shaded:1.07
|
||||
com.fasterxml.jackson.core:jackson-annotations:jar:2.4.4
|
||||
com.fasterxml.jackson.core:jackson-core:jar:2.4.4
|
||||
com.fasterxml.jackson.core:jackson-databind:jar:2.4.4
|
||||
com.fasterxml.jackson.module:jackson-module-scala_2.11:jar:2.4.4
|
||||
com.google.code.findbugs:jsr305:jar:2.0.1
|
||||
com.google.guava:guava:jar:14.0.1
|
||||
com.google.inject:guice:jar:3.0
|
||||
com.google.protobuf:protobuf-java:jar:2.5.0
|
||||
com.ning:compress-lzf:jar:1.0.0
|
||||
com.sun.jersey.contribs:jersey-guice:jar:1.9
|
||||
com.sun.jersey.jersey-test-framework:jersey-test-framework-core:jar:1.9
|
||||
com.sun.jersey.jersey-test-framework:jersey-test-framework-grizzly2:jar:1.9
|
||||
com.sun.jersey:jersey-client:jar:1.9
|
||||
com.sun.jersey:jersey-core:jar:1.9
|
||||
com.sun.jersey:jersey-grizzly2:jar:1.9
|
||||
com.sun.jersey:jersey-json:jar:1.9
|
||||
com.sun.jersey:jersey-server:jar:1.9
|
||||
com.sun.xml.bind:jaxb-impl:jar:2.2.3-1
|
||||
com.thoughtworks.paranamer:paranamer:jar:2.6
|
||||
com.twitter:chill-java:jar:0.5.0
|
||||
com.twitter:chill_2.11:jar:0.5.0
|
||||
com.typesafe:config:jar:1.2.1
|
||||
commons-beanutils:commons-beanutils-core:jar:1.8.0
|
||||
commons-beanutils:commons-beanutils:jar:1.7.0
|
||||
commons-cli:commons-cli:jar:1.2
|
||||
commons-codec:commons-codec:jar:1.4
|
||||
commons-collections:commons-collections:jar:3.2.1
|
||||
commons-configuration:commons-configuration:jar:1.6
|
||||
commons-digester:commons-digester:jar:1.8
|
||||
commons-httpclient:commons-httpclient:jar:3.1
|
||||
commons-io:commons-io:jar:2.4
|
||||
commons-lang:commons-lang:jar:2.5
|
||||
commons-logging:commons-logging:jar:1.1.1
|
||||
commons-net:commons-net:jar:3.1
|
||||
io.dropwizard.metrics:metrics-core:jar:3.1.0
|
||||
io.dropwizard.metrics:metrics-graphite:jar:3.1.0
|
||||
io.dropwizard.metrics:metrics-json:jar:3.1.0
|
||||
io.dropwizard.metrics:metrics-jvm:jar:3.1.0
|
||||
io.netty:netty-all:jar:4.0.23.Final
|
||||
io.netty:netty:jar:3.8.0.Final
|
||||
javax.activation:activation:jar:1.1
|
||||
javax.inject:javax.inject:jar:1
|
||||
javax.servlet:javax.servlet-api:jar:3.0.1
|
||||
javax.xml.bind:jaxb-api:jar:2.2.2
|
||||
jline:jline:jar:0.9.94
|
||||
log4j:log4j:jar:1.2.17
|
||||
net.java.dev.jets3t:jets3t:jar:0.7.1
|
||||
net.jpountz.lz4:lz4:jar:1.2.0
|
||||
net.sf.py4j:py4j:jar:0.8.2.1
|
||||
org.apache.avro:avro:jar:1.7.4
|
||||
org.apache.commons:commons-compress:jar:1.4.1
|
||||
org.apache.commons:commons-lang3:jar:3.3.2
|
||||
org.apache.commons:commons-math3:jar:3.1.1
|
||||
org.apache.commons:commons-math:jar:2.1
|
||||
org.apache.curator:curator-client:jar:2.4.0
|
||||
org.apache.curator:curator-framework:jar:2.4.0
|
||||
org.apache.curator:curator-recipes:jar:2.4.0
|
||||
org.apache.hadoop:hadoop-annotations:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-auth:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-client:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-common:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-hdfs:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-mapreduce-client-app:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-mapreduce-client-common:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-mapreduce-client-core:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-mapreduce-client-jobclient:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-mapreduce-client-shuffle:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-yarn-api:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-yarn-client:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-yarn-common:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-yarn-server-common:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-yarn-server-nodemanager:jar:2.2.0
|
||||
org.apache.ivy:ivy:jar:2.4.0
|
||||
org.apache.mesos:mesos:jar:shaded-protobuf:0.21.0
|
||||
org.apache.spark:spark-core_2.11:jar:1.3.1
|
||||
org.apache.spark:spark-network-common_2.11:jar:1.3.1
|
||||
org.apache.spark:spark-network-shuffle_2.11:jar:1.3.1
|
||||
org.apache.zookeeper:zookeeper:jar:3.4.5
|
||||
org.codehaus.jackson:jackson-core-asl:jar:1.8.8
|
||||
org.codehaus.jackson:jackson-jaxrs:jar:1.8.3
|
||||
org.codehaus.jackson:jackson-mapper-asl:jar:1.8.8
|
||||
org.codehaus.jackson:jackson-xc:jar:1.8.3
|
||||
org.codehaus.jettison:jettison:jar:1.1
|
||||
org.eclipse.jetty.orbit:javax.servlet:jar:3.0.0.v201112011016
|
||||
org.glassfish.external:management-api:jar:3.0.0-b012
|
||||
org.glassfish.gmbal:gmbal-api-only:jar:3.0.0-b023
|
||||
org.glassfish.grizzly:grizzly-framework:jar:2.1.2
|
||||
org.glassfish.grizzly:grizzly-http-server:jar:2.1.2
|
||||
org.glassfish.grizzly:grizzly-http-servlet:jar:2.1.2
|
||||
org.glassfish.grizzly:grizzly-http:jar:2.1.2
|
||||
org.glassfish.grizzly:grizzly-rcm:jar:2.1.2
|
||||
org.glassfish:javax.servlet:jar:3.1
|
||||
org.json4s:json4s-ast_2.11:jar:3.2.10
|
||||
org.json4s:json4s-core_2.11:jar:3.2.10
|
||||
org.json4s:json4s-jackson_2.11:jar:3.2.10
|
||||
org.mortbay.jetty:jetty-util:jar:6.1.26
|
||||
org.objenesis:objenesis:jar:1.2
|
||||
org.roaringbitmap:RoaringBitmap:jar:0.4.5
|
||||
org.scala-lang.modules:scala-parser-combinators_2.11:jar:1.0.1
|
||||
org.scala-lang.modules:scala-xml_2.11:jar:1.0.1
|
||||
org.scala-lang:scala-compiler:jar:2.11.0
|
||||
org.scala-lang:scala-library:jar:2.11.2
|
||||
org.scala-lang:scala-reflect:jar:2.11.2
|
||||
org.scala-lang:scalap:jar:2.11.0
|
||||
org.slf4j:jcl-over-slf4j:jar:1.7.10
|
||||
org.slf4j:jul-to-slf4j:jar:1.7.10
|
||||
org.slf4j:slf4j-api:jar:1.7.10
|
||||
org.slf4j:slf4j-log4j12:jar:1.7.10
|
||||
org.spark-project.akka:akka-actor_2.11:jar:2.3.4-spark
|
||||
org.spark-project.akka:akka-remote_2.11:jar:2.3.4-spark
|
||||
org.spark-project.akka:akka-slf4j_2.11:jar:2.3.4-spark
|
||||
org.spark-project.protobuf:protobuf-java:jar:2.5.0-spark
|
||||
org.spark-project.spark:unused:jar:1.0.0
|
||||
org.spark-project:pyrolite:jar:2.0.1
|
||||
org.tachyonproject:tachyon-client:jar:0.5.0
|
||||
org.tachyonproject:tachyon:jar:0.5.0
|
||||
org.tukaani:xz:jar:1.0
|
||||
org.uncommons.maths:uncommons-maths:jar:1.2.2a
|
||||
org.xerial.snappy:snappy-java:jar:1.1.1.6
|
||||
oro:oro:jar:2.0.8
|
||||
stax:stax-api:jar:1.0.1
|
||||
xmlenc:xmlenc:jar:0.52
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
aopalliance:aopalliance:jar:1.0
|
||||
asm:asm:jar:3.1
|
||||
com.clearspring.analytics:stream:jar:2.7.0
|
||||
com.esotericsoftware.kryo:kryo:jar:2.21
|
||||
com.esotericsoftware.minlog:minlog:jar:1.2
|
||||
com.esotericsoftware.reflectasm:reflectasm:jar:shaded:1.07
|
||||
com.fasterxml.jackson.core:jackson-annotations:jar:2.4.0
|
||||
com.fasterxml.jackson.core:jackson-core:jar:2.4.4
|
||||
com.fasterxml.jackson.core:jackson-databind:jar:2.4.4
|
||||
com.fasterxml.jackson.module:jackson-module-scala_2.11:jar:2.4.4
|
||||
com.google.code.findbugs:jsr305:jar:1.3.9
|
||||
com.google.guava:guava:jar:14.0.1
|
||||
com.google.inject:guice:jar:3.0
|
||||
com.google.protobuf:protobuf-java:jar:2.5.0
|
||||
com.ning:compress-lzf:jar:1.0.0
|
||||
com.sun.jersey.contribs:jersey-guice:jar:1.9
|
||||
com.sun.jersey.jersey-test-framework:jersey-test-framework-core:jar:1.9
|
||||
com.sun.jersey.jersey-test-framework:jersey-test-framework-grizzly2:jar:1.9
|
||||
com.sun.jersey:jersey-client:jar:1.9
|
||||
com.sun.jersey:jersey-core:jar:1.9
|
||||
com.sun.jersey:jersey-grizzly2:jar:1.9
|
||||
com.sun.jersey:jersey-json:jar:1.9
|
||||
com.sun.jersey:jersey-server:jar:1.9
|
||||
com.sun.xml.bind:jaxb-impl:jar:2.2.3-1
|
||||
com.thoughtworks.paranamer:paranamer:jar:2.6
|
||||
com.twitter:chill-java:jar:0.5.0
|
||||
com.twitter:chill_2.11:jar:0.5.0
|
||||
com.typesafe:config:jar:1.2.1
|
||||
commons-beanutils:commons-beanutils-core:jar:1.8.0
|
||||
commons-beanutils:commons-beanutils:jar:1.7.0
|
||||
commons-cli:commons-cli:jar:1.2
|
||||
commons-codec:commons-codec:jar:1.3
|
||||
commons-collections:commons-collections:jar:3.2.1
|
||||
commons-configuration:commons-configuration:jar:1.6
|
||||
commons-digester:commons-digester:jar:1.8
|
||||
commons-httpclient:commons-httpclient:jar:3.1
|
||||
commons-io:commons-io:jar:2.1
|
||||
commons-lang:commons-lang:jar:2.5
|
||||
commons-logging:commons-logging:jar:1.1.1
|
||||
commons-net:commons-net:jar:2.2
|
||||
io.dropwizard.metrics:metrics-core:jar:3.1.0
|
||||
io.dropwizard.metrics:metrics-graphite:jar:3.1.0
|
||||
io.dropwizard.metrics:metrics-json:jar:3.1.0
|
||||
io.dropwizard.metrics:metrics-jvm:jar:3.1.0
|
||||
io.netty:netty-all:jar:4.0.23.Final
|
||||
io.netty:netty:jar:3.8.0.Final
|
||||
javax.activation:activation:jar:1.1
|
||||
javax.inject:javax.inject:jar:1
|
||||
javax.servlet:javax.servlet-api:jar:3.0.1
|
||||
javax.xml.bind:jaxb-api:jar:2.2.2
|
||||
jline:jline:jar:0.9.94
|
||||
log4j:log4j:jar:1.2.17
|
||||
net.java.dev.jets3t:jets3t:jar:0.7.1
|
||||
net.jpountz.lz4:lz4:jar:1.2.0
|
||||
net.sf.py4j:py4j:jar:0.8.2.1
|
||||
org.apache.avro:avro:jar:1.7.4
|
||||
org.apache.commons:commons-compress:jar:1.4.1
|
||||
org.apache.commons:commons-lang3:jar:3.3.2
|
||||
org.apache.commons:commons-math3:jar:3.1.1
|
||||
org.apache.commons:commons-math:jar:2.1
|
||||
org.apache.curator:curator-client:jar:2.4.0
|
||||
org.apache.curator:curator-framework:jar:2.4.0
|
||||
org.apache.curator:curator-recipes:jar:2.4.0
|
||||
org.apache.hadoop:hadoop-annotations:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-auth:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-client:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-common:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-hdfs:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-mapreduce-client-app:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-mapreduce-client-common:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-mapreduce-client-core:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-mapreduce-client-jobclient:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-mapreduce-client-shuffle:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-yarn-api:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-yarn-client:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-yarn-common:jar:2.2.0
|
||||
org.apache.hadoop:hadoop-yarn-server-common:jar:2.2.0
|
||||
org.apache.ivy:ivy:jar:2.4.0
|
||||
org.apache.mesos:mesos:jar:shaded-protobuf:0.21.0
|
||||
org.apache.spark:spark-core_2.11:jar:1.3.1
|
||||
org.apache.spark:spark-network-common_2.11:jar:1.3.1
|
||||
org.apache.spark:spark-network-shuffle_2.11:jar:1.3.1
|
||||
org.apache.zookeeper:zookeeper:jar:3.4.5
|
||||
org.codehaus.jackson:jackson-core-asl:jar:1.8.8
|
||||
org.codehaus.jackson:jackson-jaxrs:jar:1.8.3
|
||||
org.codehaus.jackson:jackson-mapper-asl:jar:1.8.8
|
||||
org.codehaus.jackson:jackson-xc:jar:1.8.3
|
||||
org.codehaus.jettison:jettison:jar:1.1
|
||||
org.eclipse.jetty.orbit:javax.servlet:jar:3.0.0.v201112011016
|
||||
org.glassfish.external:management-api:jar:3.0.0-b012
|
||||
org.glassfish.gmbal:gmbal-api-only:jar:3.0.0-b023
|
||||
org.glassfish.grizzly:grizzly-framework:jar:2.1.2
|
||||
org.glassfish.grizzly:grizzly-http-server:jar:2.1.2
|
||||
org.glassfish.grizzly:grizzly-http-servlet:jar:2.1.2
|
||||
org.glassfish.grizzly:grizzly-http:jar:2.1.2
|
||||
org.glassfish.grizzly:grizzly-rcm:jar:2.1.2
|
||||
org.glassfish:javax.servlet:jar:3.1
|
||||
org.json4s:json4s-ast_2.11:jar:3.2.10
|
||||
org.json4s:json4s-core_2.11:jar:3.2.10
|
||||
org.json4s:json4s-jackson_2.11:jar:3.2.10
|
||||
org.mortbay.jetty:jetty-util:jar:6.1.26
|
||||
org.objenesis:objenesis:jar:1.2
|
||||
org.roaringbitmap:RoaringBitmap:jar:0.4.5
|
||||
org.scala-lang.modules:scala-parser-combinators_2.11:jar:1.0.1
|
||||
org.scala-lang.modules:scala-xml_2.11:jar:1.0.1
|
||||
org.scala-lang:scala-compiler:jar:2.11.0
|
||||
org.scala-lang:scala-library:jar:2.11.2
|
||||
org.scala-lang:scala-reflect:jar:2.11.2
|
||||
org.scala-lang:scalap:jar:2.11.0
|
||||
org.slf4j:jcl-over-slf4j:jar:1.7.10
|
||||
org.slf4j:jul-to-slf4j:jar:1.7.10
|
||||
org.slf4j:slf4j-api:jar:1.7.10
|
||||
org.slf4j:slf4j-log4j12:jar:1.7.10
|
||||
org.spark-project.akka:akka-actor_2.11:jar:2.3.4-spark
|
||||
org.spark-project.akka:akka-remote_2.11:jar:2.3.4-spark
|
||||
org.spark-project.akka:akka-slf4j_2.11:jar:2.3.4-spark
|
||||
org.spark-project.protobuf:protobuf-java:jar:2.5.0-spark
|
||||
org.spark-project.spark:unused:jar:1.0.0
|
||||
org.spark-project:pyrolite:jar:2.0.1
|
||||
org.tachyonproject:tachyon-client:jar:0.5.0
|
||||
org.tachyonproject:tachyon:jar:0.5.0
|
||||
org.tukaani:xz:jar:1.0
|
||||
org.uncommons.maths:uncommons-maths:jar:1.2.2a
|
||||
org.xerial.snappy:snappy-java:jar:1.1.1.6
|
||||
oro:oro:jar:2.0.8
|
||||
stax:stax-api:jar:1.0.1
|
||||
xmlenc:xmlenc:jar:0.52
|
||||
|
|
@ -12,26 +12,41 @@ object CentralTests extends TestSuite {
|
|||
repository.mavenCentral
|
||||
)
|
||||
|
||||
def repr(dep: Dependency) = {
|
||||
val (type0, classifier) = dep.artifacts match {
|
||||
case maven: Artifacts.Maven => (maven.`type`, maven.classifier)
|
||||
}
|
||||
s"${dep.module.organization}:${dep.module.name}:$type0:${Some(classifier).filter(_.nonEmpty).map(_+":").mkString}${dep.version}"
|
||||
}
|
||||
|
||||
def resolutionCheck(module: Module, version: String) =
|
||||
async {
|
||||
val expected = await(textResource(s"resolutions/${module.organization}:${module.name}:$version")).split('\n').toSeq
|
||||
|
||||
val dep = Dependency(module, version)
|
||||
val res = await(resolve(Set(dep), fetchFrom(repositories)).runF)
|
||||
|
||||
val result = res.dependencies.toVector.map(repr).sorted.distinct
|
||||
|
||||
for (((e, r), idx) <- expected.zip(result).zipWithIndex if e != r)
|
||||
println(s"Line $idx:\n expected: $e\n got:$r")
|
||||
|
||||
assert(result == expected)
|
||||
}
|
||||
|
||||
val tests = TestSuite {
|
||||
'logback{
|
||||
async {
|
||||
val dep = Dependency(Module("ch.qos.logback", "logback-classic"), "1.1.3")
|
||||
val res0 =
|
||||
await(resolve(Set(dep), fetchFrom(repositories))
|
||||
.runF)
|
||||
|
||||
val res = res0.copy(
|
||||
projectsCache = Map.empty, errors = Map.empty // No validating these here
|
||||
)
|
||||
val res = await(resolve(Set(dep), fetchFrom(repositories)).runF)
|
||||
.copy(projectsCache = Map.empty, errors = Map.empty) // No validating these here
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(
|
||||
dep.withCompileScope,
|
||||
Dependency(Module("ch.qos.logback", "logback-core"), "1.1.3").withCompileScope,
|
||||
Dependency(Module("org.slf4j", "slf4j-api"), "1.7.7").withCompileScope
|
||||
)
|
||||
)
|
||||
Dependency(Module("org.slf4j", "slf4j-api"), "1.7.7").withCompileScope))
|
||||
|
||||
assert(res == expected)
|
||||
}
|
||||
|
|
@ -39,26 +54,43 @@ object CentralTests extends TestSuite {
|
|||
'asm{
|
||||
async {
|
||||
val dep = Dependency(Module("org.ow2.asm", "asm-commons"), "5.0.2")
|
||||
val res0 =
|
||||
await(resolve(Set(dep), fetchFrom(repositories))
|
||||
.runF)
|
||||
|
||||
val res = res0.copy(
|
||||
projectsCache = Map.empty, errors = Map.empty // No validating these here
|
||||
)
|
||||
val res = await(resolve(Set(dep), fetchFrom(repositories)).runF)
|
||||
.copy(projectsCache = Map.empty, errors = Map.empty) // No validating these here
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(
|
||||
dep.withCompileScope,
|
||||
Dependency(Module("org.ow2.asm", "asm-tree"), "5.0.2").withCompileScope,
|
||||
Dependency(Module("org.ow2.asm", "asm"), "5.0.2").withCompileScope
|
||||
)
|
||||
)
|
||||
Dependency(Module("org.ow2.asm", "asm"), "5.0.2").withCompileScope))
|
||||
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'jodaVersionInterval{
|
||||
async {
|
||||
val dep = Dependency(Module("joda-time", "joda-time"), "[2.2,2.8]")
|
||||
val res0 = await(resolve(Set(dep), fetchFrom(repositories)).runF)
|
||||
val res = res0.copy(projectsCache = Map.empty, errors = Map.empty)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(
|
||||
dep.withCompileScope))
|
||||
|
||||
assert(res == expected)
|
||||
assert(res0.projectsCache.contains(dep.moduleVersion))
|
||||
|
||||
val (_, proj) = res0.projectsCache(dep.moduleVersion)
|
||||
assert(proj.version == "2.8")
|
||||
}
|
||||
}
|
||||
'spark{
|
||||
resolutionCheck(Module("org.apache.spark", "spark-core_2.11"), "1.3.1")
|
||||
}
|
||||
'argonautShapeless{
|
||||
resolutionCheck(Module("com.github.alexarchambault", "argonaut-shapeless_6.1_2.11"), "0.2.0")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package coursier
|
|||
package test
|
||||
|
||||
import utest._
|
||||
import core.Resolver.{ exclusionsAdd, exclusionsIntersect }
|
||||
import core.Resolver.exclusionsAdd
|
||||
|
||||
object ExclusionsTests extends TestSuite {
|
||||
|
||||
|
|
@ -66,59 +66,6 @@ object ExclusionsTests extends TestSuite {
|
|||
assert(resultb2 == eb)
|
||||
}
|
||||
}
|
||||
|
||||
'intersect{
|
||||
'basicZero{
|
||||
val result1l = exclusionsIntersect(e1, Set.empty)
|
||||
val result1r = exclusionsIntersect(Set.empty, e1)
|
||||
val result2l = exclusionsIntersect(e2, Set.empty)
|
||||
val result2r = exclusionsIntersect(Set.empty, e2)
|
||||
assert(result1l == Set.empty)
|
||||
assert(result1r == Set.empty)
|
||||
assert(result2l == Set.empty)
|
||||
assert(result2r == Set.empty)
|
||||
}
|
||||
'basic{
|
||||
val expected = e1 ++ e2
|
||||
val result12 = exclusionsIntersect(e1, e2)
|
||||
val result21 = exclusionsIntersect(e2, e1)
|
||||
assert(result12 == Set.empty)
|
||||
assert(result21 == Set.empty)
|
||||
}
|
||||
|
||||
'nameBlob{
|
||||
val result1b = exclusionsIntersect(e1, enb)
|
||||
val resultb1 = exclusionsIntersect(enb, e1)
|
||||
val result2b = exclusionsIntersect(e2, enb)
|
||||
val resultb2 = exclusionsIntersect(enb, e2)
|
||||
assert(result1b == e1)
|
||||
assert(resultb1 == e1)
|
||||
assert(result2b == Set.empty)
|
||||
assert(resultb2 == Set.empty)
|
||||
}
|
||||
|
||||
'orgBlob{
|
||||
val result1b = exclusionsIntersect(e1, eob)
|
||||
val resultb1 = exclusionsIntersect(eob, e1)
|
||||
val result2b = exclusionsIntersect(e2, eob)
|
||||
val resultb2 = exclusionsIntersect(eob, e2)
|
||||
assert(result1b == e1)
|
||||
assert(resultb1 == e1)
|
||||
assert(result2b == Set.empty)
|
||||
assert(resultb2 == Set.empty)
|
||||
}
|
||||
|
||||
'blob{
|
||||
val result1b = exclusionsIntersect(e1, eb)
|
||||
val resultb1 = exclusionsIntersect(eb, e1)
|
||||
val result2b = exclusionsIntersect(e2, eb)
|
||||
val resultb2 = exclusionsIntersect(eb, e2)
|
||||
assert(result1b == e1)
|
||||
assert(resultb1 == e1)
|
||||
assert(result2b == e2)
|
||||
assert(resultb2 == e2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ object PomParsingTests extends TestSuite {
|
|||
</dependency>
|
||||
"""
|
||||
|
||||
val expected = \/-(Dependency(Module("comp", "lib"), "2.1", classifier = "extra"))
|
||||
val expected = \/-(Dependency(Module("comp", "lib"), "2.1", artifacts = Artifacts.Maven(classifier = "extra")))
|
||||
|
||||
val result = Xml.dependency(xmlParse(depNode).right.get)
|
||||
|
||||
|
|
@ -40,6 +40,21 @@ object PomParsingTests extends TestSuite {
|
|||
|
||||
assert(result == expected)
|
||||
}
|
||||
'beFineWithProfilesWithNoId{
|
||||
val profileNode = """
|
||||
<profile>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
</profile>
|
||||
"""
|
||||
|
||||
val expected = \/-(Profile("", Some(true), Activation(Nil), Nil, Nil, Map.empty))
|
||||
|
||||
val result = Xml.profile(xmlParse(profileNode).right.get)
|
||||
|
||||
assert(result == expected)
|
||||
}
|
||||
'readProfileActivatedByDefault{
|
||||
val profileNode ="""
|
||||
<profile>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ object ResolverTests extends TestSuite {
|
|||
Project(Module("acme", "play-json"), "2.4.0"),
|
||||
|
||||
Project(Module("acme", "play"), "2.4.1",
|
||||
Seq(
|
||||
dependencies = Seq(
|
||||
Dependency(Module("acme", "play-json"), "${playJsonVersion}"),
|
||||
Dependency(Module("${project.groupId}", "${configName}"), "1.3.0")),
|
||||
properties = Map(
|
||||
|
|
@ -52,9 +52,8 @@ object ResolverTests extends TestSuite {
|
|||
exclusions = Set(("acme", "play-json"))))),
|
||||
|
||||
Project(Module("se.ikea", "billy"), "18.0",
|
||||
Seq(
|
||||
Dependency(Module("acme", "play"), "")
|
||||
),
|
||||
dependencies = Seq(
|
||||
Dependency(Module("acme", "play"), "")),
|
||||
parent = Some(Module("se.ikea", "parent"), "18.0")),
|
||||
|
||||
Project(Module("org.gnome", "parent"), "7.0",
|
||||
|
|
@ -62,7 +61,7 @@ object ResolverTests extends TestSuite {
|
|||
Dependency(Module("org.gnu", "glib"), "13.4"))),
|
||||
|
||||
Project(Module("org.gnome", "panel-legacy"), "7.0",
|
||||
Seq(
|
||||
dependencies = Seq(
|
||||
Dependency(Module("org.gnome", "desktop"), "${project.version}")),
|
||||
parent = Some(Module("org.gnome", "parent"), "7.0")),
|
||||
|
||||
|
|
@ -71,13 +70,13 @@ object ResolverTests extends TestSuite {
|
|||
Dependency(Module("gov.nsa", "crypto"), "536.89"))),
|
||||
|
||||
Project(Module("com.mailapp", "mail-client"), "2.1",
|
||||
Seq(
|
||||
dependencies = Seq(
|
||||
Dependency(Module("gov.nsa", "secure-pgp"), "10.0",
|
||||
exclusions = Set(("*", "${crypto.name}")))),
|
||||
properties = Map("crypto.name" -> "crypto", "dummy" -> "2")),
|
||||
|
||||
Project(Module("com.thoughtworks.paranamer", "paranamer-parent"), "2.6",
|
||||
Seq(
|
||||
dependencies = Seq(
|
||||
Dependency(Module("junit", "junit"), "")),
|
||||
dependencyManagement = Seq(
|
||||
Dependency(Module("junit", "junit"), "4.11", scope = Scope.Test))),
|
||||
|
|
@ -88,44 +87,33 @@ object ResolverTests extends TestSuite {
|
|||
Project(Module("com.github.dummy", "libb"), "0.3.3",
|
||||
profiles = Seq(
|
||||
Profile("default", activeByDefault = Some(true), dependencies = Seq(
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6")
|
||||
))
|
||||
)),
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))))),
|
||||
|
||||
Project(Module("com.github.dummy", "libb"), "0.4.2",
|
||||
Seq(
|
||||
Dependency(Module("org.scalaverification", "scala-verification"), "1.12.4")
|
||||
),
|
||||
dependencies = Seq(
|
||||
Dependency(Module("org.scalaverification", "scala-verification"), "1.12.4")),
|
||||
profiles = Seq(
|
||||
Profile("default", activeByDefault = Some(true), dependencies = Seq(
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"),
|
||||
Dependency(Module("org.scalaverification", "scala-verification"), "1.12.4", scope = Scope.Test)
|
||||
))
|
||||
)),
|
||||
Dependency(Module("org.scalaverification", "scala-verification"), "1.12.4", scope = Scope.Test))))),
|
||||
|
||||
Project(Module("com.github.dummy", "libb"), "0.5.3",
|
||||
properties = Map("special" -> "true"),
|
||||
profiles = Seq(
|
||||
Profile("default", activation = Profile.Activation(properties = Seq("special" -> None)), dependencies = Seq(
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6")
|
||||
))
|
||||
)),
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))))),
|
||||
|
||||
Project(Module("com.github.dummy", "libb"), "0.5.4",
|
||||
properties = Map("special" -> "true"),
|
||||
profiles = Seq(
|
||||
Profile("default", activation = Profile.Activation(properties = Seq("special" -> Some("true"))), dependencies = Seq(
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6")
|
||||
))
|
||||
)),
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))))),
|
||||
|
||||
Project(Module("com.github.dummy", "libb"), "0.5.5",
|
||||
properties = Map("special" -> "true"),
|
||||
profiles = Seq(
|
||||
Profile("default", activation = Profile.Activation(properties = Seq("special" -> Some("!false"))), dependencies = Seq(
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6")
|
||||
))
|
||||
)),
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))))),
|
||||
|
||||
Project(Module("com.github.dummy", "libb-parent"), "0.5.6",
|
||||
properties = Map("special" -> "true")),
|
||||
|
|
@ -135,9 +123,21 @@ object ResolverTests extends TestSuite {
|
|||
properties = Map("special" -> "true"),
|
||||
profiles = Seq(
|
||||
Profile("default", activation = Profile.Activation(properties = Seq("special" -> Some("!false"))), dependencies = Seq(
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6")
|
||||
))
|
||||
))
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))))),
|
||||
|
||||
Project(Module("an-org", "a-name"), "1.0"),
|
||||
|
||||
Project(Module("an-org", "a-lib"), "1.0",
|
||||
Seq(Dependency(Module("an-org", "a-name"), "1.0"))),
|
||||
|
||||
Project(Module("an-org", "another-lib"), "1.0",
|
||||
Seq(Dependency(Module("an-org", "a-name"), "1.0"))),
|
||||
|
||||
// Must bring transitively an-org:a-name, as an optional dependency
|
||||
Project(Module("an-org", "an-app"), "1.0",
|
||||
Seq(
|
||||
Dependency(Module("an-org", "a-lib"), "1.0", exclusions = Set(("an-org", "a-name"))),
|
||||
Dependency(Module("an-org", "another-lib"), "1.0", optional = true)))
|
||||
)
|
||||
|
||||
val projectsMap = projects.map(p => p.moduleVersion -> p).toMap
|
||||
|
|
@ -153,8 +153,7 @@ object ResolverTests extends TestSuite {
|
|||
val res = await(resolve(
|
||||
Set.empty,
|
||||
fetchFrom(repositories)
|
||||
).runF
|
||||
)
|
||||
).runF)
|
||||
|
||||
assert(res == Resolution.empty)
|
||||
}
|
||||
|
|
@ -178,236 +177,215 @@ object ResolverTests extends TestSuite {
|
|||
}
|
||||
'single{
|
||||
async {
|
||||
val dep = Dependency(Module("acme", "config"), "1.3.0")
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories)
|
||||
).runF)
|
||||
val dep = Dependency(Module("acme", "config"), "1.3.0")
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories)
|
||||
).runF)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope),
|
||||
projectsCache = Map(dep.moduleVersion -> (testRepository, projectsMap(dep.moduleVersion)))
|
||||
)
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope),
|
||||
projectsCache = Map(dep.moduleVersion -> (testRepository, projectsMap(dep.moduleVersion)))
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'oneTransitiveDependency{
|
||||
async {
|
||||
val dep = Dependency(Module("acme", "play"), "2.4.0")
|
||||
val trDep = Dependency(Module("acme", "play-json"), "2.4.0")
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories)
|
||||
).runF)
|
||||
val dep = Dependency(Module("acme", "play"), "2.4.0")
|
||||
val trDep = Dependency(Module("acme", "play-json"), "2.4.0")
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories)
|
||||
).runF)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope, trDep.withCompileScope),
|
||||
projectsCache = Map(
|
||||
projectsMap(dep.moduleVersion).kv,
|
||||
projectsMap(trDep.moduleVersion).kv
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope, trDep.withCompileScope),
|
||||
projectsCache = Map(
|
||||
projectsMap(dep.moduleVersion).kv,
|
||||
projectsMap(trDep.moduleVersion).kv
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'twoTransitiveDependencyWithProps{
|
||||
async {
|
||||
val dep = Dependency(Module("acme", "play"), "2.4.1")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("acme", "play-json"), "2.4.0"),
|
||||
Dependency(Module("acme", "config"), "1.3.0")
|
||||
)
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories)
|
||||
).runF)
|
||||
val dep = Dependency(Module("acme", "play"), "2.4.1")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("acme", "play-json"), "2.4.0"),
|
||||
Dependency(Module("acme", "config"), "1.3.0")
|
||||
)
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories)
|
||||
).runF)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope),
|
||||
projectsCache = Map(
|
||||
projectsMap(dep.moduleVersion).kv
|
||||
) ++ trDeps.map(trDep => projectsMap(trDep.moduleVersion).kv)
|
||||
)
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope),
|
||||
projectsCache = Map(
|
||||
projectsMap(dep.moduleVersion).kv
|
||||
) ++ trDeps.map(trDep => projectsMap(trDep.moduleVersion).kv)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'exclude{
|
||||
async {
|
||||
val dep = Dependency(Module("acme", "play-extra-no-config"), "2.4.1")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("acme", "play"), "2.4.1",
|
||||
exclusions = Set(("acme", "config"))),
|
||||
Dependency(Module("acme", "play-json"), "2.4.0",
|
||||
exclusions = Set(("acme", "config")))
|
||||
)
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories)
|
||||
).runF)
|
||||
val dep = Dependency(Module("acme", "play-extra-no-config"), "2.4.1")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("acme", "play"), "2.4.1",
|
||||
exclusions = Set(("acme", "config"))),
|
||||
Dependency(Module("acme", "play-json"), "2.4.0",
|
||||
exclusions = Set(("acme", "config")))
|
||||
)
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories)
|
||||
).runF)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope),
|
||||
projectsCache = Map(
|
||||
projectsMap(dep.moduleVersion).kv
|
||||
) ++ trDeps.map(trDep => projectsMap(trDep.moduleVersion).kv)
|
||||
)
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope),
|
||||
projectsCache = Map(
|
||||
projectsMap(dep.moduleVersion).kv
|
||||
) ++ trDeps.map(trDep => projectsMap(trDep.moduleVersion).kv)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'excludeOrgWildcard{
|
||||
async {
|
||||
val dep = Dependency(Module("acme", "play-extra-no-config-no"), "2.4.1")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("acme", "play"), "2.4.1",
|
||||
exclusions = Set(("*", "config"))),
|
||||
Dependency(Module("acme", "play-json"), "2.4.0",
|
||||
exclusions = Set(("*", "config")))
|
||||
)
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories)
|
||||
).runF)
|
||||
val dep = Dependency(Module("acme", "play-extra-no-config-no"), "2.4.1")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("acme", "play"), "2.4.1",
|
||||
exclusions = Set(("*", "config"))),
|
||||
Dependency(Module("acme", "play-json"), "2.4.0",
|
||||
exclusions = Set(("*", "config")))
|
||||
)
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories)
|
||||
).runF)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope),
|
||||
projectsCache = Map(
|
||||
projectsMap(dep.moduleVersion).kv
|
||||
) ++ trDeps.map(trDep => projectsMap(trDep.moduleVersion).kv)
|
||||
)
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope),
|
||||
projectsCache = Map(
|
||||
projectsMap(dep.moduleVersion).kv
|
||||
) ++ trDeps.map(trDep => projectsMap(trDep.moduleVersion).kv)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'filter{
|
||||
async {
|
||||
val dep = Dependency(Module("hudsucker", "mail"), "10.0")
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None)
|
||||
val dep = Dependency(Module("hudsucker", "mail"), "10.0")
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope),
|
||||
projectsCache = Map(
|
||||
projectsMap(dep.moduleVersion).kv
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope),
|
||||
projectsCache = Map(
|
||||
projectsMap(dep.moduleVersion).kv
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'parentDepMgmt{
|
||||
async {
|
||||
val dep = Dependency(Module("se.ikea", "billy"), "18.0")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("acme", "play"), "2.4.0",
|
||||
exclusions = Set(("acme", "play-json")))
|
||||
)
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty)
|
||||
val dep = Dependency(Module("se.ikea", "billy"), "18.0")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("acme", "play"), "2.4.0",
|
||||
exclusions = Set(("acme", "play-json")))
|
||||
)
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope)
|
||||
)
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'parentDependencies{
|
||||
async {
|
||||
val dep = Dependency(Module("org.gnome", "panel-legacy"), "7.0")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("org.gnu", "glib"), "13.4"),
|
||||
Dependency(Module("org.gnome", "desktop"), "7.0"))
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty, errors = Map.empty)
|
||||
val dep = Dependency(Module("org.gnome", "panel-legacy"), "7.0")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("org.gnu", "glib"), "13.4"),
|
||||
Dependency(Module("org.gnome", "desktop"), "7.0"))
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty, errors = Map.empty)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope)
|
||||
)
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'propertiesInExclusions{
|
||||
async {
|
||||
val dep = Dependency(Module("com.mailapp", "mail-client"), "2.1")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("gov.nsa", "secure-pgp"), "10.0", exclusions = Set(("*", "crypto"))))
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty, errors = Map.empty)
|
||||
val dep = Dependency(Module("com.mailapp", "mail-client"), "2.1")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("gov.nsa", "secure-pgp"), "10.0", exclusions = Set(("*", "crypto"))))
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty, errors = Map.empty)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope)
|
||||
)
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'depMgmtInParentDeps{
|
||||
async {
|
||||
val dep = Dependency(Module("com.thoughtworks.paranamer", "paranamer"), "2.6")
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty, errors = Map.empty)
|
||||
val dep = Dependency(Module("com.thoughtworks.paranamer", "paranamer"), "2.6")
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty, errors = Map.empty)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope)
|
||||
)
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'depsFromDefaultProfile{
|
||||
async {
|
||||
val dep = Dependency(Module("com.github.dummy", "libb"), "0.3.3")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty, errors = Map.empty)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
'depsFromPropertyActivatedProfile{
|
||||
val f =
|
||||
for (version <- Seq("0.5.3", "0.5.4", "0.5.5", "0.5.6")) yield {
|
||||
async {
|
||||
val dep = Dependency(Module("com.github.dummy", "libb"), version)
|
||||
val dep = Dependency(Module("com.github.dummy", "libb"), "0.3.3")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))
|
||||
val res = await(resolve(
|
||||
|
|
@ -423,28 +401,95 @@ object ResolverTests extends TestSuite {
|
|||
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
'depsFromPropertyActivatedProfile{
|
||||
val f =
|
||||
for (version <- Seq("0.5.3", "0.5.4", "0.5.5", "0.5.6")) yield {
|
||||
async {
|
||||
val dep = Dependency(Module("com.github.dummy", "libb"), version)
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty, errors = Map.empty)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
|
||||
scala.concurrent.Future.sequence(f)
|
||||
}
|
||||
'depsScopeOverrideFromProfile{
|
||||
async {
|
||||
// Like com.google.inject:guice:3.0 with org.sonatype.sisu.inject:cglib
|
||||
val dep = Dependency(Module("com.github.dummy", "libb"), "0.4.2")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty, errors = Map.empty)
|
||||
// Like com.google.inject:guice:3.0 with org.sonatype.sisu.inject:cglib
|
||||
val dep = Dependency(Module("com.github.dummy", "libb"), "0.4.2")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("org.escalier", "librairie-standard"), "2.11.6"))
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty, errors = Map.empty)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope)
|
||||
)
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
|
||||
'exclusionsAndOptionalShouldGoAlong{
|
||||
async {
|
||||
val dep = Dependency(Module("an-org", "an-app"), "1.0")
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("an-org", "a-lib"), "1.0", exclusions = Set(("an-org", "a-name"))),
|
||||
Dependency(Module("an-org", "another-lib"), "1.0", optional = true),
|
||||
Dependency(Module("an-org", "a-name"), "1.0", optional = true))
|
||||
val res = await(resolve(
|
||||
Set(dep),
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty, errors = Map.empty)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = Set(dep.withCompileScope),
|
||||
dependencies = Set(dep.withCompileScope) ++ trDeps.map(_.withCompileScope)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
|
||||
'exclusionsOfDependenciesFromDifferentPathsShouldNotCollide{
|
||||
async {
|
||||
val deps = Set(
|
||||
Dependency(Module("an-org", "an-app"), "1.0"),
|
||||
Dependency(Module("an-org", "a-lib"), "1.0", optional = true))
|
||||
val trDeps = Seq(
|
||||
Dependency(Module("an-org", "a-lib"), "1.0", exclusions = Set(("an-org", "a-name"))),
|
||||
Dependency(Module("an-org", "another-lib"), "1.0", optional = true),
|
||||
Dependency(Module("an-org", "a-name"), "1.0", optional = true))
|
||||
val res = await(resolve(
|
||||
deps,
|
||||
fetchFrom(repositories),
|
||||
filter = Some(_.scope == Scope.Compile)
|
||||
).runF).copy(filter = None, projectsCache = Map.empty, errors = Map.empty)
|
||||
|
||||
val expected = Resolution(
|
||||
rootDependencies = deps.map(_.withCompileScope),
|
||||
dependencies = (deps ++ trDeps).map(_.withCompileScope)
|
||||
)
|
||||
|
||||
assert(res == expected)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -121,6 +121,46 @@ object VersionIntervalTests extends TestSuite {
|
|||
}
|
||||
}
|
||||
|
||||
'contains{
|
||||
val v21 = Version("2.1")
|
||||
val v22 = Version("2.2")
|
||||
val v23 = Version("2.3")
|
||||
val v24 = Version("2.4")
|
||||
val v25 = Version("2.5")
|
||||
val v26 = Version("2.6")
|
||||
val v27 = Version("2.7")
|
||||
val v28 = Version("2.8")
|
||||
|
||||
'basic{
|
||||
val itv = Parse.versionInterval("[2.2,)").get
|
||||
|
||||
assert(!itv.contains(v21))
|
||||
assert(itv.contains(v22))
|
||||
assert(itv.contains(v23))
|
||||
assert(itv.contains(v24))
|
||||
}
|
||||
'open{
|
||||
val itv = Parse.versionInterval("(2.2,)").get
|
||||
|
||||
assert(!itv.contains(v21))
|
||||
assert(!itv.contains(v22))
|
||||
assert(itv.contains(v23))
|
||||
assert(itv.contains(v24))
|
||||
}
|
||||
'segment{
|
||||
val itv = Parse.versionInterval("[2.2,2.8]").get
|
||||
|
||||
assert(!itv.contains(v21))
|
||||
assert(itv.contains(v22))
|
||||
assert(itv.contains(v23))
|
||||
assert(itv.contains(v24))
|
||||
assert(itv.contains(v25))
|
||||
assert(itv.contains(v26))
|
||||
assert(itv.contains(v27))
|
||||
assert(itv.contains(v28))
|
||||
}
|
||||
}
|
||||
|
||||
'parse{
|
||||
'malformed{
|
||||
val s1 = "[1.1]"
|
||||
|
|
@ -225,77 +265,6 @@ object VersionIntervalTests extends TestSuite {
|
|||
}
|
||||
}
|
||||
|
||||
'repr{
|
||||
'basic {
|
||||
val s1 = "[1.1,1.3]"
|
||||
val repr1 = Parse.versionInterval(s1).map(_.repr)
|
||||
assert(repr1 == Some(s1))
|
||||
|
||||
val s2 = "(1.1,1.3]"
|
||||
val repr2 = Parse.versionInterval(s2).map(_.repr)
|
||||
assert(repr2 == Some(s2))
|
||||
|
||||
val s3 = "[1.1,1.3)"
|
||||
val repr3 = Parse.versionInterval(s3).map(_.repr)
|
||||
assert(repr3 == Some(s3))
|
||||
|
||||
val s4 = "(1.1,1.3)"
|
||||
val repr4 = Parse.versionInterval(s4).map(_.repr)
|
||||
assert(repr4 == Some(s4))
|
||||
}
|
||||
'leftEmptyVersions {
|
||||
val s1 = "[,1.3]"
|
||||
val repr1 = Parse.versionInterval(s1).map(_.repr)
|
||||
assert(repr1 == Some(s1))
|
||||
|
||||
val s2 = "(,1.3]"
|
||||
val repr2 = Parse.versionInterval(s2).map(_.repr)
|
||||
assert(repr2 == Some(s2))
|
||||
|
||||
val s3 = "[,1.3)"
|
||||
val repr3 = Parse.versionInterval(s3).map(_.repr)
|
||||
assert(repr3 == Some(s3))
|
||||
|
||||
val s4 = "(,1.3)"
|
||||
val repr4 = Parse.versionInterval(s4).map(_.repr)
|
||||
assert(repr4 == Some(s4))
|
||||
}
|
||||
'rightEmptyVersions {
|
||||
val s1 = "[1.3,]"
|
||||
val repr1 = Parse.versionInterval(s1).map(_.repr)
|
||||
assert(repr1 == Some(s1))
|
||||
|
||||
val s2 = "(1.3,]"
|
||||
val repr2 = Parse.versionInterval(s2).map(_.repr)
|
||||
assert(repr2 == Some(s2))
|
||||
|
||||
val s3 = "[1.3,)"
|
||||
val repr3 = Parse.versionInterval(s3).map(_.repr)
|
||||
assert(repr3 == Some(s3))
|
||||
|
||||
val s4 = "(1.3,)"
|
||||
val repr4 = Parse.versionInterval(s4).map(_.repr)
|
||||
assert(repr4 == Some(s4))
|
||||
}
|
||||
'bothEmptyVersions {
|
||||
val s1 = "[,]"
|
||||
val repr1 = Parse.versionInterval(s1).map(_.repr)
|
||||
assert(repr1 == Some(s1))
|
||||
|
||||
val s2 = "(,]"
|
||||
val repr2 = Parse.versionInterval(s2).map(_.repr)
|
||||
assert(repr2 == Some(s2))
|
||||
|
||||
val s3 = "[,)"
|
||||
val repr3 = Parse.versionInterval(s3).map(_.repr)
|
||||
assert(repr3 == Some(s3))
|
||||
|
||||
val s4 = "(,]"
|
||||
val repr4 = Parse.versionInterval(s4).map(_.repr)
|
||||
assert(repr4 == Some(s4))
|
||||
}
|
||||
}
|
||||
|
||||
'constraint{
|
||||
'none{
|
||||
val s1 = "(,)"
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
package coursier
|
||||
package test
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
import utest._
|
||||
|
||||
object ComparableVersionTests extends TestSuite {
|
||||
import core.ComparableVersion.parse
|
||||
object VersionTests extends TestSuite {
|
||||
import core.Version
|
||||
|
||||
def compare(first: String, second: String) = parse(first).compare(parse(second))
|
||||
def compare(first: String, second: String) = Version(first).compare(Version(second))
|
||||
|
||||
def increasing(versions: String*): Boolean =
|
||||
versions.iterator.sliding(2).withPartial(false).forall{case Seq(a, b) => compare(a, b) < 0 }
|
||||
|
|
@ -16,18 +14,31 @@ object ComparableVersionTests extends TestSuite {
|
|||
val tests = TestSuite {
|
||||
'stackOverflow{
|
||||
val s = "." * 100000
|
||||
val v = parse(s)
|
||||
val v = Version(s)
|
||||
assert(v.isEmpty)
|
||||
}
|
||||
|
||||
'empty{
|
||||
val v0 = parse("0")
|
||||
val v = parse("")
|
||||
val v0 = Version("0")
|
||||
val v = Version("")
|
||||
|
||||
assert(v0.isEmpty)
|
||||
assert(v.isEmpty)
|
||||
}
|
||||
|
||||
'max{
|
||||
val v21 = Version("2.1")
|
||||
val v22 = Version("2.2")
|
||||
val v23 = Version("2.3")
|
||||
val v24 = Version("2.4")
|
||||
val v241 = Version("2.4.1")
|
||||
|
||||
val l = Seq(v21, v22, v23, v24, v241)
|
||||
val max = l.max
|
||||
|
||||
assert(max == v241)
|
||||
}
|
||||
|
||||
'numericOrdering{
|
||||
assert(compare("1.2", "1.10") < 0)
|
||||
}
|
||||
|
|
@ -328,6 +339,7 @@ object ComparableVersionTests extends TestSuite {
|
|||
|
||||
// 'CaseInsensitiveOrderingOfQualifiersIsLocaleIndependent
|
||||
// {
|
||||
// import java.util.Locale
|
||||
// val orig = Locale.getDefault
|
||||
// try {
|
||||
// for ( locale <- Seq(Locale.ENGLISH, new Locale( "tr" )) ) {
|
||||
|
|
@ -8,6 +8,9 @@ import sbtrelease.ReleasePlugin.ReleaseKeys.{ publishArtifactsAction, versionBum
|
|||
import sbtrelease.Version.Bump
|
||||
import com.typesafe.sbt.pgp.PgpKeys
|
||||
|
||||
import xerial.sbt.Pack._
|
||||
|
||||
|
||||
object CoursierBuild extends Build {
|
||||
|
||||
lazy val publishingSettings = Seq[Setting[_]](
|
||||
|
|
@ -53,7 +56,7 @@ object CoursierBuild extends Build {
|
|||
) ++ releaseSettings
|
||||
|
||||
lazy val commonSettings = Seq[Setting[_]](
|
||||
organization := "eu.frowning-lambda",
|
||||
organization := "com.github.alexarchambault",
|
||||
version := "0.1.0-SNAPSHOT",
|
||||
scalaVersion := "2.11.6",
|
||||
crossScalaVersions := Seq("2.10.5", "2.11.6"),
|
||||
|
|
@ -65,6 +68,8 @@ object CoursierBuild extends Build {
|
|||
libraryDependencies += "org.scala-lang.modules" %% "scala-async" % "0.9.1" % "provided",
|
||||
unmanagedSourceDirectories in Compile += (baseDirectory in LocalRootProject).value / "core" / "src" / "main" / "scala",
|
||||
unmanagedSourceDirectories in Test += (baseDirectory in LocalRootProject).value / "core" / "src" / "test" / "scala",
|
||||
unmanagedResourceDirectories in Compile += (baseDirectory in LocalRootProject).value / "core" / "src" / "main" / "resources",
|
||||
unmanagedResourceDirectories in Test += (baseDirectory in LocalRootProject).value / "core" / "src" / "test" / "resources",
|
||||
testFrameworks += new TestFramework("utest.runner.Framework")
|
||||
)
|
||||
|
||||
|
|
@ -98,8 +103,14 @@ object CoursierBuild extends Build {
|
|||
|
||||
lazy val cli = Project(id = "cli", base = file("cli"))
|
||||
.dependsOn(coreJvm)
|
||||
.settings(commonSettings ++ xerial.sbt.Pack.packAutoSettings: _*)
|
||||
.settings(commonSettings ++ packAutoSettings ++ publishPackTxzArchive ++ publishPackZipArchive: _*)
|
||||
.settings(
|
||||
packArchivePrefix := s"coursier-cli_${scalaBinaryVersion.value}",
|
||||
packArchiveTxzArtifact := Artifact("coursier-cli", "arch", "tar.xz"),
|
||||
packArchiveZipArtifact := Artifact("coursier-cli", "arch", "zip")
|
||||
)
|
||||
.settings(
|
||||
name := "coursier-cli",
|
||||
libraryDependencies ++= Seq(
|
||||
"com.github.alexarchambault" %% "case-app" % "0.2.2",
|
||||
"ch.qos.logback" % "logback-classic" % "1.1.3"
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ cp -R "$DIR/classes/css" staging
|
|||
|
||||
for i in staging/*.html; do
|
||||
mv "$i" "$i.0"
|
||||
grep -v "src=\"\.\.\/web-" < "$i.0" > "$i"
|
||||
sed "s/src=\"\.\.\/web-/src=\"web-/g" < "$i.0" > "$i"
|
||||
rm -f "$i.0"
|
||||
done
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- FIXME Get from WebJars -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
|
||||
<!-- FIXME Get from WebJar -->
|
||||
<link rel="stylesheet" href="css/bootstrap-treeview.css">
|
||||
|
||||
<style>
|
||||
|
|
@ -46,16 +46,8 @@
|
|||
|
||||
<div class="collapse navbar-collapse" id="mainNavBar">
|
||||
<ul class="nav navbar-nav">
|
||||
<!-- class="active" -->
|
||||
<li><a href="#demo" data-toggle="tab">Demo</a></li>
|
||||
<li><a href="https://github.com/alexarchambault/coursier/blob/master/USAGE.md">Usage</a></li>
|
||||
<!-- <li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Usage <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#usageCli" data-toggle="tab">Command-line</a></li>
|
||||
<li><a href="#usageApi" data-toggle="tab">API</a></li>
|
||||
</ul>
|
||||
</li> -->
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
|
@ -74,13 +66,10 @@
|
|||
<p>Pure Scala Artifact Fetching</p>
|
||||
<p><a href="https://github.com/alexarchambault/coursier">Project Page</a></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="demo">
|
||||
|
||||
<div id="demoContent"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="usageCli">
|
||||
|
|
@ -113,15 +102,12 @@
|
|||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
|
||||
|
||||
<!-- during dev -->
|
||||
<script type="text/javascript" src="../web-jsdeps.js"></script>
|
||||
<script type="text/javascript" src="../web-fastopt.js"></script>
|
||||
<!-- github pages -->
|
||||
<script type="text/javascript" src="web-jsdeps.js"></script>
|
||||
<script type="text/javascript" src="web-fastopt.js"></script>
|
||||
<!-- Paths changed by push-gh-pages.sh before pushing to gh-pages -->
|
||||
<script src="../web-jsdeps.js"></script>
|
||||
<script src="../web-fastopt.js"></script>
|
||||
|
||||
<script type="text/javascript" src="https://cdn.rawgit.com/strathausen/dracula/26010eb3b0df037cf507886897e20c02c4ec041b/lib/dracula_graph.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.rawgit.com/strathausen/dracula/26010eb3b0df037cf507886897e20c02c4ec041b/lib/dracula_graffle.js"></script>
|
||||
<script src="https://cdn.rawgit.com/strathausen/dracula/26010eb3b0df037cf507886897e20c02c4ec041b/lib/dracula_graph.js"></script>
|
||||
<script src="https://cdn.rawgit.com/strathausen/dracula/26010eb3b0df037cf507886897e20c02c4ec041b/lib/dracula_graffle.js"></script>
|
||||
|
||||
<script>
|
||||
// From http://www.bootply.com/VQqzOawoYc
|
||||
|
|
|
|||
|
|
@ -40,11 +40,11 @@ class Backend($: BackendScope[Unit, State]) {
|
|||
}
|
||||
|
||||
for {
|
||||
((org, name, scope), par) <- resolution.reverseDependenciesAndExclusions.toList
|
||||
from = s"$org:$name:${scope.name}"
|
||||
(dep, parents) <- resolution.reverseDependencies.toList
|
||||
from = s"${dep.module.organization}:${dep.module.name}:${dep.scope.name}"
|
||||
_ = addNode(from)
|
||||
((parOrg, parName, parScope), _) <- par
|
||||
to = s"$parOrg:$parName:${parScope.name}"
|
||||
parDep <- parents
|
||||
to = s"${parDep.module.organization}:${parDep.module.name}:${parDep.scope.name}"
|
||||
_ = addNode(to)
|
||||
} {
|
||||
graph.addEdge(from, to)
|
||||
|
|
@ -203,8 +203,12 @@ object App {
|
|||
|
||||
def infoLabel(label: String) =
|
||||
<.span(^.`class` := "label label-info", label)
|
||||
def errorLabel(label: String, desc: String) =
|
||||
<.button(^.`type` := "button", ^.`class` := "btn btn-xs btn-danger",
|
||||
def errorPopOver(label: String, desc: String) =
|
||||
popOver("danger", label, desc)
|
||||
def infoPopOver(label: String, desc: String) =
|
||||
popOver("info", label, desc)
|
||||
def popOver(`type`: String, label: String, desc: String) =
|
||||
<.button(^.`type` := "button", ^.`class` := s"btn btn-xs btn-${`type`}",
|
||||
Attr("data-trigger") := "focus",
|
||||
Attr("data-toggle") := "popover", Attr("data-placement") := "bottom",
|
||||
Attr("data-content") := desc,
|
||||
|
|
@ -213,28 +217,34 @@ object App {
|
|||
label
|
||||
)
|
||||
|
||||
def depItem(dep: Dependency) =
|
||||
def depItem(dep: Dependency, finalVersionOpt: Option[String]) = {
|
||||
val (type0, classifier) = dep.artifacts match {
|
||||
case maven: Artifacts.Maven => (maven.`type`, maven.classifier)
|
||||
}
|
||||
|
||||
<.tr(
|
||||
^.`class` := (if (res.errors.contains(dep.moduleVersion)) "danger" else ""),
|
||||
<.td(dep.module.organization),
|
||||
<.td(dep.module.name),
|
||||
<.td(dep.version),
|
||||
<.td(finalVersionOpt.fold(dep.version)(finalVersion => s"$finalVersion (for ${dep.version})")),
|
||||
<.td(Seq[Seq[TagMod]](
|
||||
if (dep.scope == Scope.Compile) Seq() else Seq(infoLabel(dep.scope.name)),
|
||||
if (dep.`type`.isEmpty || dep.`type` == "jar") Seq() else Seq(infoLabel(dep.`type`)),
|
||||
if (dep.classifier.isEmpty) Seq() else Seq(infoLabel(dep.classifier)),
|
||||
if (type0.isEmpty || type0 == "jar") Seq() else Seq(infoLabel(type0)),
|
||||
if (classifier.isEmpty) Seq() else Seq(infoLabel(classifier)),
|
||||
Some(dep.exclusions).filter(_.nonEmpty).map(excls => infoPopOver("Exclusions", excls.toList.sorted.map{case (org, name) => s"$org:$name"}.mkString("; "))).toSeq,
|
||||
if (dep.optional) Seq(infoLabel("optional")) else Seq(),
|
||||
res.errors.get(dep.moduleVersion).map(errs => errorLabel("Error", errs.mkString("; "))).toSeq
|
||||
res.errors.get(dep.moduleVersion).map(errs => errorPopOver("Error", errs.mkString("; "))).toSeq
|
||||
)),
|
||||
<.td(Seq[Seq[TagMod]](
|
||||
res.projectsCache.get(dep.moduleVersion) match {
|
||||
case Some((repo: Remote, _)) =>
|
||||
// FIXME Maven specific, generalize if/when adding support for Ivy
|
||||
val version0 = finalVersionOpt getOrElse dep.version
|
||||
val relPath =
|
||||
dep.module.organization.split('.').toSeq ++ Seq(
|
||||
dep.module.name,
|
||||
dep.version,
|
||||
s"${dep.module.name}-${dep.version}"
|
||||
version0,
|
||||
s"${dep.module.name}-$version0"
|
||||
)
|
||||
|
||||
Seq(
|
||||
|
|
@ -250,6 +260,7 @@ object App {
|
|||
}
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
val sortedDeps = res.dependencies.toList
|
||||
.sortBy(dep => coursier.core.Module.unapply(dep.module).get)
|
||||
|
|
@ -265,7 +276,7 @@ object App {
|
|||
)
|
||||
),
|
||||
<.tbody(
|
||||
sortedDeps.map(depItem)
|
||||
sortedDeps.map(dep => depItem(dep, res.projectsCache.get(dep.moduleVersion).map(_._2.version).filter(_ != dep.version)))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue