Remove scalaz dependency from core and cache, add scalaz-interop module

This commit is contained in:
Alexandre Archambault 2018-03-12 11:18:18 +01:00
parent fb5a2fde12
commit 29f8d7b680
27 changed files with 137 additions and 81 deletions

View File

@ -160,12 +160,15 @@ val start = Resolution(
Create a fetch function able to get things from a few repositories via a local cache,
```scala
import coursier.interop.scalaz._
import scalaz.concurrent.Task
val repositories = Seq(
Cache.ivy2Local,
MavenRepository("https://repo1.maven.org/maven2")
)
val fetch = Fetch.from(repositories, Cache.fetch())
val fetch = Fetch.from(repositories, Cache.fetch[Task]())
```
Then run the resolution per-se,
@ -468,7 +471,7 @@ The resolution process will go on by giving successive `Resolution`s, until the
`start` above is only the initial state - it is far from over, as the `isDone` method on it tells,
```scala
scala> start.isDone
res4: Boolean = false
res5: Boolean = false
```
@ -507,7 +510,7 @@ scala> MavenRepository(
| "https://nexus.corp.com/content/repositories/releases",
| authentication = Some(Authentication("user", "pass"))
| )
res6: coursier.maven.MavenRepository = MavenRepository(https://nexus.corp.com/content/repositories/releases,None,true,Some(Authentication(user, *******)))
res7: coursier.maven.MavenRepository = MavenRepository(https://nexus.corp.com/content/repositories/releases,None,true,Some(Authentication(user, *******)))
```
Now that we have repositories, we're going to mix these with things from the `coursier-cache` module,

View File

@ -17,7 +17,7 @@ install:
build_script:
- sbt ++2.11.12 clean compile coreJVM/publishLocal
- sbt ++2.10.7 clean compile
- sbt ++2.12.4 coreJVM/publishLocal cacheJVM/publishLocal cli/publishLocal extra/publishLocal sbt-shared/publishLocal
- sbt ++2.12.4 coreJVM/publishLocal cacheJVM/publishLocal cli/publishLocal extra/publishLocal scalazJVM/publishLocal sbt-shared/publishLocal
- sbt ++2.10.7 coreJVM/publishLocal cacheJVM/publishLocal extra/publishLocal sbt-shared/publishLocal
test_script:
- ps: Start-Job -filepath .\scripts\start-it-auth-server.ps1 -ArgumentList $pwd

View File

@ -30,7 +30,6 @@ lazy val core = crossProject
.settings(
shared,
name := "coursier",
libs += CrossDeps.scalazCore.value,
Mima.previousArtifacts,
Mima.coreFilters
)
@ -40,7 +39,7 @@ lazy val coreJs = core.js
lazy val tests = crossProject
.disablePlugins(ScriptedPlugin)
.dependsOn(core, cache % "test")
.dependsOn(core, cache % "test", scalaz)
.jsSettings(
scalaJSStage.in(Global) := FastOptStage
)
@ -93,13 +92,31 @@ lazy val cache = crossProject
shared,
Mima.previousArtifacts,
coursierPrefix,
libs += Deps.scalazConcurrent,
Mima.cacheFilters
)
lazy val cacheJvm = cache.jvm
lazy val cacheJs = cache.js
lazy val scalaz = crossProject
.disablePlugins(ScriptedPlugin)
.dependsOn(cache)
.jvmSettings(
libs += Deps.scalazConcurrent
)
.jsSettings(
libs += CrossDeps.scalazCore.value
)
.settings(
name := "scalaz-interop",
shared,
Mima.previousArtifacts,
coursierPrefix
)
lazy val scalazJvm = scalaz.jvm
lazy val scalazJs = scalaz.js
lazy val bootstrap = project
.disablePlugins(ScriptedPlugin)
.settings(
@ -146,7 +163,7 @@ lazy val extra = project
)
lazy val cli = project
.dependsOn(coreJvm, cacheJvm, extra)
.dependsOn(coreJvm, cacheJvm, extra, scalazJvm)
.disablePlugins(ScriptedPlugin)
.enablePlugins(PackPlugin, SbtProguard)
.settings(
@ -223,7 +240,7 @@ lazy val web = project
lazy val readme = project
.in(file("doc/readme"))
.dependsOn(coreJvm, cacheJvm)
.dependsOn(coreJvm, cacheJvm, scalazJvm)
.disablePlugins(ScriptedPlugin)
.enablePlugins(TutPlugin)
.settings(
@ -255,7 +272,7 @@ lazy val `sbt-shared` = project
)
lazy val `sbt-coursier` = project
.dependsOn(coreJvm, cacheJvm, extra, `sbt-shared`)
.dependsOn(coreJvm, cacheJvm, extra, `sbt-shared`, scalazJvm)
.disablePlugins(ScriptedPlugin)
.settings(
plugin,
@ -307,6 +324,7 @@ lazy val jvm = project
`proxy-tests`,
paths,
cacheJvm,
scalazJvm,
bootstrap,
extra,
cli,
@ -345,6 +363,7 @@ lazy val `sbt-plugins` = project
.aggregate(
coreJvm,
cacheJvm,
scalazJvm,
extra,
`sbt-shared`,
`sbt-coursier`,
@ -376,6 +395,8 @@ lazy val coursier = project
`sbt-coursier`,
`sbt-pgp-coursier`,
`sbt-shading`,
scalazJvm,
scalazJs,
web,
readme,
okhttp

1
cache/BUILD vendored
View File

@ -2,7 +2,6 @@ scala_library(
name = "cache",
dependencies = [
"core:core",
"3rdparty/jvm:scalaz-concurrent",
"paths/src/main/java:paths",
],
sources = rglobs("jvm/*.scala", "shared/*.scala"),

View File

@ -1,7 +1,8 @@
package coursier
import scala.concurrent.{ ExecutionContext, Future }
import scalaz.{ Nondeterminism, Reducer }
import coursier.util.Gather
import scala.concurrent.{ExecutionContext, Future}
/**
* Minimal Future-based Task.
@ -35,18 +36,14 @@ object Task {
def runF(implicit ec: ExecutionContext) = Future.traverse(tasks)(_.runF)
}
implicit val taskMonad: Nondeterminism[Task] =
new Nondeterminism[Task] {
def point[A](a: => A): Task[A] = Task.now(a)
implicit val gather: Gather[Task] =
new Gather[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)
override def reduceUnordered[A, M](fs: Seq[Task[A]])(implicit R: Reducer[A, M]): Task[M] =
def gather[A](elems: Seq[Task[A]]): Task[Seq[A]] = {
Task { implicit ec =>
val f = Future.sequence(fs.map(_.runF))
f.map { l =>
(R.zero /: l)(R.snoc)
}
Future.sequence(elems.map(_.runF))
}
def chooseAny[A](head: Task[A], tail: Seq[Task[A]]): Task[(A, Seq[Task[A]])] =
???
}
}
}

View File

@ -3,7 +3,6 @@ package coursier.util
import java.util.concurrent.{ExecutorService, Executors, ThreadFactory}
import scala.language.higherKinds
import scalaz.concurrent.{Task => ScalazTask}
trait Schedulable[F[_]] extends Gather[F] {
def schedule[A](pool: ExecutorService)(f: => A): F[A]
@ -11,20 +10,6 @@ trait Schedulable[F[_]] extends Gather[F] {
object Schedulable {
implicit val scalazTask: Schedulable[ScalazTask] =
new Schedulable[ScalazTask] {
def point[A](a: A) =
ScalazTask.point(a)
def schedule[A](pool: ExecutorService)(f: => A) =
ScalazTask(f)(pool)
def gather[A](elems: Seq[ScalazTask[A]]) =
ScalazTask.taskInstance.gather(elems)
def bind[A, B](elem: ScalazTask[A])(f: A => ScalazTask[B]) =
ScalazTask.taskInstance.bind(elem)(f)
}
def fixedThreadPool(size: Int): ExecutorService =
Executors.newFixedThreadPool(
size,

View File

@ -8,6 +8,7 @@ scala_library(
"extra/src/main/scala/coursier:fallback-deps-repo",
"extra/src/main/scala/coursier/extra:extra",
"extra/src/main/scala-2.12/coursier/extra:native",
"scalaz:scalaz-interop",
":util",
],
sources = globs(

View File

@ -10,14 +10,14 @@ import coursier.cli.options.{CommonOptions, IsolatedLoaderOptions}
import coursier.cli.scaladex.Scaladex
import coursier.cli.util.{JsonElem, JsonPrintRequirement, JsonReport}
import coursier.extra.Typelevel
import coursier.interop.scalaz._
import coursier.ivy.IvyRepository
import coursier.util.Parse.ModuleRequirements
import coursier.util.{Parse, Print}
import coursier.util.{Gather, Parse, Print}
import scala.annotation.tailrec
import scala.concurrent.duration.Duration
import scalaz.concurrent.{Strategy, Task}
import scalaz.Nondeterminism
object Helper {
@ -145,14 +145,14 @@ class Helper(
None
val fetchs = cachePolicies.map(p =>
Cache.fetch(cache, p, checksums = Nil, logger = logger, pool = pool, ttl = ttl0)
Cache.fetch[Task](cache, p, checksums = Nil, logger = logger, pool = pool, ttl = ttl0)
)
logger.foreach(_.init())
val scaladex = Scaladex.cached(fetchs: _*)
val res = Nondeterminism[Task].gather(scaladexRawDependencies.map { s =>
val res = Gather[Task].gather(scaladexRawDependencies.map { s =>
val deps = scaladex.dependencies(
s,
scalaVersion,
@ -192,6 +192,7 @@ class Helper(
.collect { case Right(l) => l }
.flatten
.map { case (mod, ver) => (Dependency(mod, ver), Map[String, String]()) }
.toList
}
val (forceVersionErrors, forceVersions0) = Parse.moduleVersions(forceVersion, scalaVersion)

View File

@ -6,12 +6,12 @@ import java.util.concurrent.ExecutorService
import argonaut._, Argonaut._, ArgonautShapeless._
import coursier.core.{Artifact, Attributes}
import coursier.util.EitherT
import coursier.interop.scalaz._
import coursier.util.{EitherT, Gather}
import coursier.{Fetch, Module}
import scalaz.concurrent.Task
import scala.language.higherKinds
import scalaz.Nondeterminism
import scalaz.concurrent.Task
object Scaladex {
@ -48,7 +48,7 @@ object Scaladex {
Right(new String(b, StandardCharsets.UTF_8))
})(pool))
}, Nondeterminism[Task])
}, Gather[Task])
def cached(fetch: Fetch.Content[Task]*): Scaladex[Task] =
Scaladex({
@ -59,13 +59,13 @@ object Scaladex {
)
(get(fetch.head) /: fetch.tail)(_ orElse get(_))
}, Nondeterminism[Task])
}, Gather[Task])
}
// TODO Add F[_] type param, change `fetch` type to `String => EitherT[F, String, String]`, adjust method signatures accordingly, ...
case class Scaladex[F[_]](fetch: String => EitherT[F, String, String], F: Nondeterminism[F]) {
case class Scaladex[F[_]](fetch: String => EitherT[F, String, String], G: Gather[F]) {
private implicit def F0 = F
private implicit val G0 = G
// quick & dirty API for querying scaladex
@ -141,8 +141,8 @@ case class Scaladex[F[_]](fetch: String => EitherT[F, String, String], F: Nondet
orgNameOrError.flatMap {
case (ghOrg, ghRepo, artifactNames) =>
val moduleVersions = F.map(F.gather(artifactNames.map { artifactName =>
F.map(artifactInfos(ghOrg, ghRepo, artifactName).run) {
val moduleVersions = G.map(G.gather(artifactNames.map { artifactName =>
G.map(artifactInfos(ghOrg, ghRepo, artifactName).run) {
case Left(err) =>
logger(s"Cannot get infos about artifact $artifactName from $ghOrg/$ghRepo: $err, ignoring it")
Nil
@ -152,7 +152,7 @@ case class Scaladex[F[_]](fetch: String => EitherT[F, String, String], F: Nondet
}
}))(_.flatten)
EitherT(F.map(moduleVersions) { l =>
EitherT(G.map(moduleVersions) { l =>
if (l.isEmpty)
Left(s"No module found for $ghOrg/$ghRepo")
else

View File

@ -2,7 +2,6 @@ scala_library(
name = "core",
dependencies = [
"3rdparty/jvm:fastParse",
"3rdparty/jvm:scalaz-core",
"3rdparty/jvm:jsoup",
# TODO(wisechengyi) for some reason there is no compile error
# and this is needed at runtime.

View File

@ -44,11 +44,6 @@ final case class EitherT[F[_], L, R](run: F[Either[L, R]]) {
}
)
def scalaz(implicit M: Monad[F]): _root_.scalaz.EitherT[F, L, R] =
_root_.scalaz.EitherT(
M.map(run)(_root_.scalaz.\/.fromEither)
)
}
object EitherT {

View File

@ -7,12 +7,5 @@ trait Gather[F[_]] extends Monad[F] {
}
object Gather {
implicit def fromScalaz[F[_]](implicit N: scalaz.Nondeterminism[F]): Gather[F] =
new Gather[F] {
def point[A](a: A) = N.pure(a)
def bind[A, B](elem: F[A])(f: A => F[B]) = N.bind(elem)(f)
def gather[A](elems: Seq[F[A]]) = N.map(N.gather(elems))(l => l)
}
def apply[F[_]](implicit G: Gather[F]): Gather[F] = G
}

View File

@ -9,13 +9,3 @@ trait Monad[F[_]] {
def map[A, B](elem: F[A])(f: A => B): F[B] =
bind(elem)(a => point(f(a)))
}
object Monad {
implicit def fromScalaz[F[_]](implicit M: scalaz.Monad[F]): Monad[F] =
new Monad[F] {
def point[A](a: A) = M.pure(a)
def bind[A, B](elem: F[A])(f: A => F[B]) = M.bind(elem)(f)
}
}

View File

@ -166,8 +166,8 @@ object Cache {
dropInfoAttributes = true
)
def fetch() = coursier.Cache.fetch()
def file(artifact: Artifact) = coursier.Cache.file(artifact)
def fetch[F[_]: coursier.util.Schedulable]() = coursier.Cache.fetch[F]()
def file[F[_]: coursier.util.Schedulable](artifact: Artifact) = coursier.Cache.file[F](artifact)
}
```
@ -187,12 +187,15 @@ val start = Resolution(
Create a fetch function able to get things from a few repositories via a local cache,
```tut:silent
import coursier.interop.scalaz._
import scalaz.concurrent.Task
val repositories = Seq(
Cache.ivy2Local,
MavenRepository("https://repo1.maven.org/maven2")
)
val fetch = Fetch.from(repositories, Cache.fetch())
val fetch = Fetch.from(repositories, Cache.fetch[Task]())
```
Then run the resolution per-se,

View File

@ -6,6 +6,7 @@ import java.util.concurrent.{ConcurrentHashMap, ExecutorService, Executors}
import coursier.core.{Authentication, Publication}
import coursier.extra.Typelevel
import coursier.interop.scalaz._
import coursier.ivy.{IvyRepository, PropertiesPattern}
import coursier.Keys._
import coursier.Structure._
@ -1015,7 +1016,7 @@ object Tasks {
val artifactFileOrErrorTasks = allArtifacts.toVector.distinct.map { a =>
def f(p: CachePolicy) =
Cache.file(
Cache.file[Task](
a,
cache,
p,

9
scalaz/BUILD Normal file
View File

@ -0,0 +1,9 @@
scala_library(
name = "scalaz-interop",
dependencies = [
"core:core",
"cache:cache",
"3rdparty/jvm:scalaz-concurrent",
],
sources = rglobs("jvm/*.scala", "shared/*.scala"),
)

View File

@ -0,0 +1,3 @@
package coursier.interop
abstract class PlatformScalazImplicits

View File

@ -0,0 +1,24 @@
package coursier.interop
import java.util.concurrent.ExecutorService
import coursier.util.Schedulable
import _root_.scalaz.concurrent.{Task => ScalazTask}
abstract class PlatformScalazImplicits {
implicit val scalazTaskSchedulable: Schedulable[ScalazTask] =
new Schedulable[ScalazTask] {
def point[A](a: A) =
ScalazTask.point(a)
def schedule[A](pool: ExecutorService)(f: => A) =
ScalazTask(f)(pool)
def gather[A](elems: Seq[ScalazTask[A]]) =
ScalazTask.taskInstance.gather(elems)
def bind[A, B](elem: ScalazTask[A])(f: A => ScalazTask[B]) =
ScalazTask.taskInstance.bind(elem)(f)
}
}

View File

@ -0,0 +1,26 @@
package coursier.interop
import coursier.util.{Gather, Monad}
import scala.language.higherKinds
object scalaz extends LowPriorityScalazImplicits {
implicit def coursierMonadFromScalaz[F[_]](implicit M: _root_.scalaz.Monad[F]): Monad[F] =
new Monad[F] {
def point[A](a: A) = M.pure(a)
def bind[A, B](elem: F[A])(f: A => F[B]) = M.bind(elem)(f)
}
}
abstract class LowPriorityScalazImplicits extends PlatformScalazImplicits {
implicit def coursierGatherFromScalaz[F[_]](implicit N: _root_.scalaz.Nondeterminism[F]): Gather[F] =
new Gather[F] {
def point[A](a: A) = N.pure(a)
def bind[A, B](elem: F[A])(f: A => F[B]) = N.bind(elem)(f)
def gather[A](elems: Seq[F[A]]) = N.map(N.gather(elems))(l => l)
}
}

View File

@ -3,6 +3,7 @@ package coursier
import java.io._
import java.nio.charset.Charset
import coursier.interop.scalaz._
import coursier.util.EitherT
import scala.language.implicitConversions

View File

@ -5,6 +5,7 @@ import java.io.File
import coursier.cache.protocol.TestprotocolHandler
import coursier.internal.FileUtil
import coursier.interop.scalaz._
import utest._

View File

@ -4,6 +4,7 @@ package test
import java.io.File
import java.math.BigInteger
import coursier.interop.scalaz._
import utest._
import scalaz.concurrent.Strategy

View File

@ -4,6 +4,7 @@ import java.util.concurrent.ConcurrentHashMap
import coursier.{Fetch, Module}
import coursier.core.ResolutionProcess
import coursier.interop.scalaz._
import utest._
import scala.collection.JavaConverters._

View File

@ -3,6 +3,7 @@ package coursier.test
import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Paths}
import coursier.interop.scalaz._
import coursier.util.{EitherT, TestEscape}
import coursier.{Cache, Fetch, Platform}

View File

@ -1,4 +1,3 @@
io.get-coursier:coursier_2.11:1.1.0-SNAPSHOT:compile
org.scala-lang:scala-library:2.11.12:default
org.scala-lang.modules:scala-xml_2.11:1.0.6:default
org.scalaz:scalaz-core_2.11:7.2.16:default

View File

@ -4,6 +4,7 @@ package test
import utest._
import scala.async.Async.{async, await}
import coursier.interop.scalaz._
import coursier.MavenRepository
import coursier.Platform.fetch
import coursier.test.compatibility._

View File

@ -2,6 +2,7 @@ package coursier
package test
import coursier.core.Repository
import coursier.interop.scalaz._
import coursier.maven.MavenRepository
import utest._
import scala.async.Async.{ async, await }