mirror of https://github.com/sbt/sbt.git
Merge pull request #328 from alexarchambault/topic/develop
Switch to scalaz 7.2, some fixes / enhancements in SBT plugin
This commit is contained in:
commit
0d9a594792
|
|
@ -121,7 +121,10 @@ lazy val core = crossProject
|
|||
.settings(mimaDefaultSettings: _*)
|
||||
.settings(
|
||||
name := "coursier",
|
||||
libraryDependencies += "com.lihaoyi" %%% "fastparse" % "0.3.7",
|
||||
libraryDependencies ++= Seq(
|
||||
"org.scalaz" %%% "scalaz-core" % "7.2.5",
|
||||
"com.lihaoyi" %%% "fastparse" % "0.3.7"
|
||||
),
|
||||
resourceGenerators.in(Compile) += {
|
||||
(target, version).map { (dir, ver) =>
|
||||
import sys.process._
|
||||
|
|
@ -218,7 +221,6 @@ lazy val core = crossProject
|
|||
.jvmSettings(
|
||||
libraryDependencies ++=
|
||||
Seq(
|
||||
"org.scalaz" %% "scalaz-core" % "7.1.2",
|
||||
"org.jsoup" % "jsoup" % "1.9.2"
|
||||
) ++ {
|
||||
if (scalaVersion.value.startsWith("2.10.")) Seq()
|
||||
|
|
@ -229,7 +231,6 @@ lazy val core = crossProject
|
|||
)
|
||||
.jsSettings(
|
||||
libraryDependencies ++= Seq(
|
||||
"com.github.japgolly.fork.scalaz" %%% "scalaz-core" % (if (scalaVersion.value.startsWith("2.10.")) "7.1.1" else "7.1.2"),
|
||||
"org.scala-js" %%% "scalajs-dom" % "0.9.1",
|
||||
"be.doeraene" %%% "scalajs-jquery" % "0.9.0"
|
||||
)
|
||||
|
|
@ -278,7 +279,7 @@ lazy val cache = project
|
|||
.settings(
|
||||
name := "coursier-cache",
|
||||
libraryDependencies ++= Seq(
|
||||
"org.scalaz" %% "scalaz-concurrent" % "7.1.2"
|
||||
"org.scalaz" %% "scalaz-concurrent" % "7.2.5"
|
||||
),
|
||||
previousArtifacts := Set("com.github.alexarchambault" %% moduleName.value % binaryCompatibilityVersion),
|
||||
binaryIssueFilters ++= {
|
||||
|
|
|
|||
|
|
@ -32,16 +32,16 @@ object CacheParse {
|
|||
}
|
||||
|
||||
val validatedUrl = try {
|
||||
url.map(Cache.url).validation
|
||||
url.map(Cache.url)
|
||||
} catch {
|
||||
case e: MalformedURLException =>
|
||||
("Error parsing URL " + url + Option(e.getMessage).fold("")(" (" + _ + ")")).failure
|
||||
("Error parsing URL " + url + Option(e.getMessage).fold("")(" (" + _ + ")")).left
|
||||
}
|
||||
|
||||
validatedUrl.flatMap { url =>
|
||||
Option(url.getUserInfo) match {
|
||||
case None =>
|
||||
repo.validation
|
||||
repo
|
||||
case Some(userInfo) =>
|
||||
userInfo.split(":", 2) match {
|
||||
case Array(user, password) =>
|
||||
|
|
@ -52,7 +52,7 @@ object CacheParse {
|
|||
url.getFile
|
||||
).toString
|
||||
|
||||
repo.validation.map {
|
||||
repo.map {
|
||||
case m: MavenRepository =>
|
||||
m.copy(
|
||||
root = baseUrl,
|
||||
|
|
@ -73,10 +73,10 @@ object CacheParse {
|
|||
}
|
||||
|
||||
case _ =>
|
||||
s"No password found in user info of URL $url".failure
|
||||
s"No password found in user info of URL $url".left
|
||||
}
|
||||
}
|
||||
}
|
||||
}.validation
|
||||
}
|
||||
|
||||
def repositories(l: Seq[String]): ValidationNel[String, Seq[Repository]] =
|
||||
|
|
@ -85,25 +85,25 @@ object CacheParse {
|
|||
}
|
||||
|
||||
def cachePolicies(s: String): ValidationNel[String, Seq[CachePolicy]] =
|
||||
s.split(',').toVector.traverseU {
|
||||
s.split(',').toVector.traverseM[({ type L[X] = ValidationNel[String, X] })#L, CachePolicy] {
|
||||
case "offline" =>
|
||||
Seq(CachePolicy.LocalOnly).successNel
|
||||
Vector(CachePolicy.LocalOnly).successNel
|
||||
case "update-local-changing" =>
|
||||
Seq(CachePolicy.LocalUpdateChanging).successNel
|
||||
Vector(CachePolicy.LocalUpdateChanging).successNel
|
||||
case "update-local" =>
|
||||
Seq(CachePolicy.LocalUpdate).successNel
|
||||
Vector(CachePolicy.LocalUpdate).successNel
|
||||
case "update-changing" =>
|
||||
Seq(CachePolicy.UpdateChanging).successNel
|
||||
Vector(CachePolicy.UpdateChanging).successNel
|
||||
case "update" =>
|
||||
Seq(CachePolicy.Update).successNel
|
||||
Vector(CachePolicy.Update).successNel
|
||||
case "missing" =>
|
||||
Seq(CachePolicy.FetchMissing).successNel
|
||||
Vector(CachePolicy.FetchMissing).successNel
|
||||
case "force" =>
|
||||
Seq(CachePolicy.ForceDownload).successNel
|
||||
Vector(CachePolicy.ForceDownload).successNel
|
||||
case "default" =>
|
||||
Seq(CachePolicy.LocalOnly, CachePolicy.FetchMissing).successNel
|
||||
Vector(CachePolicy.LocalOnly, CachePolicy.FetchMissing).successNel
|
||||
case other =>
|
||||
s"Unrecognized mode: $other".failureNel
|
||||
}.map(_.flatten)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class Helper(
|
|||
case Success(cp) => cp
|
||||
case Failure(errors) =>
|
||||
prematureExit(
|
||||
s"Error parsing modes:\n${errors.list.map(" "+_).mkString("\n")}"
|
||||
s"Error parsing modes:\n${errors.list.toList.map(" "+_).mkString("\n")}"
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ class Helper(
|
|||
sourceRepositories ++ repos
|
||||
case Failure(errors) =>
|
||||
prematureExit(
|
||||
s"Error with repositories:\n${errors.list.map(" "+_).mkString("\n")}"
|
||||
s"Error with repositories:\n${errors.list.toList.map(" "+_).mkString("\n")}"
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,17 +12,17 @@ case class PropertiesPattern(chunks: Seq[PropertiesPattern.ChunkOrProperty]) {
|
|||
|
||||
def substituteProperties(properties: Map[String, String]): String \/ Pattern = {
|
||||
|
||||
val validation = chunks.toVector.traverseU {
|
||||
val validation = chunks.toVector.traverseM[({ type L[X] = ValidationNel[String, X] })#L, Pattern.Chunk] {
|
||||
case ChunkOrProperty.Prop(name, alternativesOpt) =>
|
||||
properties.get(name) match {
|
||||
case Some(value) =>
|
||||
Seq(Pattern.Chunk.Const(value)).successNel
|
||||
Vector(Pattern.Chunk.Const(value)).successNel
|
||||
case None =>
|
||||
alternativesOpt match {
|
||||
case Some(alt) =>
|
||||
PropertiesPattern(alt)
|
||||
.substituteProperties(properties)
|
||||
.map(_.chunks)
|
||||
.map(_.chunks.toVector)
|
||||
.validation
|
||||
.toValidationNel
|
||||
case None =>
|
||||
|
|
@ -33,17 +33,17 @@ case class PropertiesPattern(chunks: Seq[PropertiesPattern.ChunkOrProperty]) {
|
|||
case ChunkOrProperty.Opt(l @ _*) =>
|
||||
PropertiesPattern(l)
|
||||
.substituteProperties(properties)
|
||||
.map(l => Seq(Pattern.Chunk.Opt(l.chunks: _*)))
|
||||
.map(l => Vector(Pattern.Chunk.Opt(l.chunks: _*)))
|
||||
.validation
|
||||
.toValidationNel
|
||||
|
||||
case ChunkOrProperty.Var(name) =>
|
||||
Seq(Pattern.Chunk.Var(name)).successNel
|
||||
Vector(Pattern.Chunk.Var(name)).successNel
|
||||
|
||||
case ChunkOrProperty.Const(value) =>
|
||||
Seq(Pattern.Chunk.Const(value)).successNel
|
||||
Vector(Pattern.Chunk.Const(value)).successNel
|
||||
|
||||
}.map(_.flatten).map(Pattern(_))
|
||||
}.map(Pattern(_))
|
||||
|
||||
validation.disjunction.leftMap { notFoundProps =>
|
||||
s"Property(ies) not found: ${notFoundProps.toList.mkString(", ")}"
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ object CoursierPlugin extends AutoPlugin {
|
|||
val mavenProfiles = Keys.mavenProfiles
|
||||
val coursierSourceRepositories = Keys.coursierSourceRepositories
|
||||
val coursierResolvers = Keys.coursierResolvers
|
||||
val coursierRecursiveResolvers = Keys.coursierRecursiveResolvers
|
||||
val coursierSbtResolvers = Keys.coursierSbtResolvers
|
||||
val coursierUseSbtCredentials = Keys.coursierUseSbtCredentials
|
||||
val coursierCredentials = Keys.coursierCredentials
|
||||
|
|
@ -68,6 +69,7 @@ object CoursierPlugin extends AutoPlugin {
|
|||
mavenProfiles := Set.empty,
|
||||
coursierSourceRepositories := Nil,
|
||||
coursierResolvers <<= Tasks.coursierResolversTask,
|
||||
coursierRecursiveResolvers <<= Tasks.coursierRecursiveResolversTask,
|
||||
coursierSbtResolvers <<= externalResolvers in updateSbtClassifiers,
|
||||
coursierUseSbtCredentials := false,
|
||||
coursierCredentials := Map.empty,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ object Keys {
|
|||
|
||||
val coursierSourceRepositories = SettingKey[Seq[File]]("coursier-source-repositories")
|
||||
val coursierResolvers = TaskKey[Seq[Resolver]]("coursier-resolvers")
|
||||
val coursierRecursiveResolvers = TaskKey[Seq[Resolver]]("coursier-recursive-resolvers", "Resolvers of the current project, plus those of all from its inter-dependency projects")
|
||||
val coursierSbtResolvers = TaskKey[Seq[Resolver]]("coursier-sbt-resolvers")
|
||||
val coursierUseSbtCredentials = SettingKey[Boolean]("coursier-use-sbt-credentials")
|
||||
val coursierCredentials = TaskKey[Map[String, Credentials]]("coursier-credentials")
|
||||
|
|
|
|||
|
|
@ -27,6 +27,29 @@ import scalaz.concurrent.{ Task, Strategy }
|
|||
|
||||
object Tasks {
|
||||
|
||||
def allRecursiveInterDependencies(state: sbt.State, projectRef: sbt.ProjectRef) = {
|
||||
|
||||
def dependencies(map: Map[String, Seq[String]], id: String): Set[String] = {
|
||||
|
||||
def helper(map: Map[String, Seq[String]], acc: Set[String]): Set[String] =
|
||||
if (acc.exists(map.contains)) {
|
||||
val (kept, rem) = map.partition { case (k, _) => acc(k) }
|
||||
helper(rem, acc ++ kept.valuesIterator.flatten)
|
||||
} else
|
||||
acc
|
||||
|
||||
helper(map - id, map.getOrElse(id, Nil).toSet)
|
||||
}
|
||||
|
||||
val allProjectsDeps =
|
||||
for (p <- structure(state).allProjects)
|
||||
yield p.id -> p.dependencies.map(_.project.project)
|
||||
|
||||
val deps = dependencies(allProjectsDeps.toMap, projectRef.project)
|
||||
|
||||
structure(state).allProjectRefs.filter(p => deps(p.project))
|
||||
}
|
||||
|
||||
def coursierResolversTask: Def.Initialize[sbt.Task[Seq[Resolver]]] =
|
||||
(
|
||||
externalResolvers,
|
||||
|
|
@ -46,13 +69,30 @@ object Tasks {
|
|||
}
|
||||
}
|
||||
|
||||
def coursierRecursiveResolversTask: Def.Initialize[sbt.Task[Seq[Resolver]]] =
|
||||
(
|
||||
sbt.Keys.state,
|
||||
sbt.Keys.thisProjectRef
|
||||
).flatMap { (state, projectRef) =>
|
||||
|
||||
val projects = allRecursiveInterDependencies(state, projectRef)
|
||||
|
||||
coursierResolvers
|
||||
.forAllProjects(state, projectRef +: projects)
|
||||
.map(_.values.toVector.flatten)
|
||||
}
|
||||
|
||||
def coursierFallbackDependenciesTask: Def.Initialize[sbt.Task[Seq[(Module, String, URL, Boolean)]]] =
|
||||
(
|
||||
sbt.Keys.state,
|
||||
sbt.Keys.thisProjectRef
|
||||
).flatMap { (state, projectRef) =>
|
||||
|
||||
val allDependenciesTask = allDependencies.in(projectRef).get(state)
|
||||
val projects = allRecursiveInterDependencies(state, projectRef)
|
||||
|
||||
val allDependenciesTask = allDependencies
|
||||
.forAllProjects(state, projectRef +: projects)
|
||||
.map(_.values.toVector.flatten)
|
||||
|
||||
for {
|
||||
allDependencies <- allDependenciesTask
|
||||
|
|
@ -103,25 +143,7 @@ object Tasks {
|
|||
sbt.Keys.thisProjectRef
|
||||
).flatMap { (state, projectRef) =>
|
||||
|
||||
def dependencies(map: Map[String, Seq[String]], id: String): Set[String] = {
|
||||
|
||||
def helper(map: Map[String, Seq[String]], acc: Set[String]): Set[String] =
|
||||
if (acc.exists(map.contains)) {
|
||||
val (kept, rem) = map.partition { case (k, _) => acc(k) }
|
||||
helper(rem, acc ++ kept.valuesIterator.flatten)
|
||||
} else
|
||||
acc
|
||||
|
||||
helper(map - id, map.getOrElse(id, Nil).toSet)
|
||||
}
|
||||
|
||||
val allProjectsDeps =
|
||||
for (p <- structure(state).allProjects)
|
||||
yield p.id -> p.dependencies.map(_.project.project)
|
||||
|
||||
val deps = dependencies(allProjectsDeps.toMap, projectRef.project)
|
||||
|
||||
val projects = structure(state).allProjectRefs.filter(p => deps(p.project))
|
||||
val projects = allRecursiveInterDependencies(state, projectRef)
|
||||
|
||||
coursierProject.forAllProjects(state, projects).map(_.values.toVector)
|
||||
}
|
||||
|
|
@ -374,7 +396,7 @@ object Tasks {
|
|||
if (sbtClassifiers)
|
||||
coursierSbtResolvers.value
|
||||
else
|
||||
coursierResolvers.value
|
||||
coursierRecursiveResolvers.value.distinct
|
||||
|
||||
val sourceRepositories = coursierSourceRepositories.value.map { dir =>
|
||||
// FIXME Don't hardcode this path?
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
case class A(msg: String)
|
||||
|
||||
object A {
|
||||
def default = A("OK")
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
|
||||
object Main extends App {
|
||||
|
||||
val msg = shapeless.Generic[A].to(A.default).head
|
||||
|
||||
Files.write(new File("output").toPath, msg.getBytes("UTF-8"))
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
lazy val a = project
|
||||
.settings(sharedSettings)
|
||||
.settings(
|
||||
libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.234" from "https://oss.sonatype.org/content/repositories/releases/com/chuusai/shapeless_2.11/2.3.1/shapeless_2.11-2.3.1.jar"
|
||||
)
|
||||
|
||||
lazy val b = project
|
||||
.dependsOn(a)
|
||||
.settings(sharedSettings)
|
||||
|
||||
lazy val root = project
|
||||
.in(file("."))
|
||||
.aggregate(a, b)
|
||||
.settings(sharedSettings)
|
||||
|
||||
|
||||
lazy val sharedSettings = Seq(
|
||||
scalaVersion := "2.11.8",
|
||||
coursierCachePolicies := {
|
||||
if (sys.props("os.name").startsWith("Windows"))
|
||||
coursierCachePolicies.value
|
||||
else
|
||||
Seq(coursier.CachePolicy.ForceDownload)
|
||||
}
|
||||
)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
val pluginVersion = sys.props.getOrElse(
|
||||
"plugin.version",
|
||||
throw new RuntimeException(
|
||||
"""|The system property 'plugin.version' is not defined.
|
||||
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin
|
||||
)
|
||||
)
|
||||
|
||||
addSbtPlugin("io.get-coursier" % "sbt-coursier" % pluginVersion)
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
$ delete output
|
||||
> b/run
|
||||
$ exists output
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
case class A(msg: String)
|
||||
|
||||
object A {
|
||||
def default = A("OK")
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
|
||||
import scalaz.stream._
|
||||
import scalaz.concurrent.Task
|
||||
|
||||
object Main extends App {
|
||||
|
||||
val pch = Process.constant((i:Int) => Task.now(())).take(3)
|
||||
val count = Process.constant(1).toSource.to(pch).runLog.run.size
|
||||
assert(count == 3)
|
||||
|
||||
Files.write(new File("output").toPath, A.default.msg.getBytes("UTF-8"))
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
|
||||
lazy val a = project
|
||||
.settings(sharedSettings)
|
||||
.settings(
|
||||
resolvers += "Scalaz Bintray Repo" at "https://dl.bintray.com/scalaz/releases"
|
||||
)
|
||||
|
||||
lazy val b = project
|
||||
.dependsOn(a)
|
||||
.settings(sharedSettings)
|
||||
.settings(
|
||||
// resolver added in inter-project dependency only - should still be fine
|
||||
libraryDependencies += "org.scalaz.stream" %% "scalaz-stream" % "0.7.1a"
|
||||
)
|
||||
|
||||
lazy val root = project
|
||||
.in(file("."))
|
||||
.aggregate(a, b)
|
||||
.settings(sharedSettings)
|
||||
|
||||
|
||||
lazy val sharedSettings = Seq(
|
||||
scalaVersion := "2.11.8",
|
||||
coursierCachePolicies := {
|
||||
if (sys.props("os.name").startsWith("Windows"))
|
||||
coursierCachePolicies.value
|
||||
else
|
||||
Seq(coursier.CachePolicy.ForceDownload)
|
||||
}
|
||||
)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
val pluginVersion = sys.props.getOrElse(
|
||||
"plugin.version",
|
||||
throw new RuntimeException(
|
||||
"""|The system property 'plugin.version' is not defined.
|
||||
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin
|
||||
)
|
||||
)
|
||||
|
||||
addSbtPlugin("io.get-coursier" % "sbt-coursier" % pluginVersion)
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
$ delete output
|
||||
> b/run
|
||||
$ exists output
|
||||
|
|
@ -4,6 +4,5 @@ com.lihaoyi:sourcecode_2.11:0.1.1:default
|
|||
io.get-coursier:coursier_2.11:1.0.0-SNAPSHOT:compile
|
||||
org.jsoup:jsoup:1.9.2:default
|
||||
org.scala-lang:scala-library:2.11.8:default
|
||||
org.scala-lang.modules:scala-parser-combinators_2.11:1.0.4:default
|
||||
org.scala-lang.modules:scala-xml_2.11:1.0.5:default
|
||||
org.scalaz:scalaz-core_2.11:7.1.2:default
|
||||
org.scalaz:scalaz-core_2.11:7.2.5:default
|
||||
|
|
|
|||
Loading…
Reference in New Issue