Merge pull request #328 from alexarchambault/topic/develop

Switch to scalaz 7.2, some fixes / enhancements in SBT plugin
This commit is contained in:
Alexandre Archambault 2016-08-21 23:37:44 +02:00 committed by GitHub
commit 0d9a594792
18 changed files with 196 additions and 52 deletions

View File

@ -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 ++= {

View File

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

View File

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

View File

@ -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(", ")}"

View File

@ -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,

View File

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

View File

@ -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?

View File

@ -0,0 +1,6 @@
case class A(msg: String)
object A {
def default = A("OK")
}

View File

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

View File

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

View File

@ -0,0 +1,11 @@
{
val pluginVersion = sys.props.getOrElse(
"plugin.version",
throw new RuntimeException(
"""|The system property 'plugin.version' is not defined.
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin
)
)
addSbtPlugin("io.get-coursier" % "sbt-coursier" % pluginVersion)
}

View File

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

View File

@ -0,0 +1,6 @@
case class A(msg: String)
object A {
def default = A("OK")
}

View File

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

View File

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

View File

@ -0,0 +1,11 @@
{
val pluginVersion = sys.props.getOrElse(
"plugin.version",
throw new RuntimeException(
"""|The system property 'plugin.version' is not defined.
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin
)
)
addSbtPlugin("io.get-coursier" % "sbt-coursier" % pluginVersion)
}

View File

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

View File

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