Offline option in CLI tool, minor refactoring in MavenRepository

This commit is contained in:
Alexandre Archambault 2015-07-04 15:19:34 +01:00
parent 7c4cf0ff72
commit ee1a6a68f6
8 changed files with 90 additions and 62 deletions

View File

@ -4,15 +4,18 @@ package cli
import java.io.File
import caseapp._
import coursier.core.{Fetch, Parse, Repository}, Repository.CachePolicy
import coursier.core.{MavenRepository, Parse, Repository}, Repository.CachePolicy
import scalaz.concurrent.Task
case class Coursier(scope: List[String],
keepOptional: Boolean,
fetch: Boolean,
@ExtraName("v") verbose: List[Unit],
@ExtraName("N") maxIterations: Int = 100) extends App {
case class Coursier(
scope: List[String],
keepOptional: Boolean,
fetch: Boolean,
@ExtraName("c") offline: Boolean,
@ExtraName("v") verbose: List[Unit],
@ExtraName("N") maxIterations: Int = 100
) extends App {
val verbose0 = verbose.length
@ -26,8 +29,8 @@ case class Coursier(scope: List[String],
def fileRepr(f: File) = f.toString
val logger: Fetch.Logger with FilesLogger =
new Fetch.Logger with FilesLogger {
val logger: MavenRepository.Logger with FilesLogger =
new MavenRepository.Logger with FilesLogger {
def println(s: String) = Console.err.println(s)
def downloading(url: String) =
@ -55,17 +58,13 @@ case class Coursier(scope: List[String],
}
val cachedMavenCentral = Repository.mavenCentral.copy(
fetch = Repository.mavenCentral.fetch.copy(
cache = Some(centralCacheDir),
logger = if (verbose0 <= 1) None else Some(logger)
)
cache = Some(centralCacheDir),
logger = if (verbose0 <= 1) None else Some(logger)
)
val repositories = Seq[Repository](
cachedMavenCentral,
Repository.ivy2Local.copy(
fetch = Repository.ivy2Local.fetch.copy(
logger = if (verbose0 <= 1) None else Some(logger)
)
logger = if (verbose0 <= 1) None else Some(logger)
)
)
@ -149,13 +148,17 @@ case class Coursier(scope: List[String],
if (fetch) {
println()
val cachePolicy: CachePolicy = CachePolicy.Default
val cachePolicy: CachePolicy =
if (offline)
CachePolicy.LocalOnly
else
CachePolicy.Default
val artifacts = res.artifacts
val files = new Files(
Seq(
cachedMavenCentral.fetch.root -> centralFilesCacheDir
cachedMavenCentral.root -> centralFilesCacheDir
),
() => ???,
if (verbose0 <= 0) None else Some(logger)

View File

@ -12,7 +12,7 @@ import js.Dynamic.{global => g}
import scala.scalajs.js.timers._
object Fetch {
object MavenRepository {
def encodeURIComponent(s: String): String =
g.encodeURIComponent(s).asInstanceOf[String]
@ -84,18 +84,24 @@ object Fetch {
}
case class Fetch(root: String,
logger: Option[Fetch.Logger] = None) {
case class MavenRepository(
root: String,
ivyLike: Boolean = false,
logger: Option[MavenRepository.Logger] = None
) extends BaseMavenRepository(root, ivyLike) {
def apply(artifact: Artifact,
cachePolicy: Repository.CachePolicy): EitherT[Task, String, String] = {
def fetch(
artifact: Artifact,
cachePolicy: Repository.CachePolicy
): EitherT[Task, String, String] = {
val url0 = root + artifact.url
EitherT(
Task { implicit ec =>
Future(logger.foreach(_.fetching(url0)))
.flatMap(_ => Fetch.get(url0))
.flatMap(_ => MavenRepository.get(url0))
.map{ s => logger.foreach(_.fetched(url0)); \/-(s) }
.recover{case e: Exception =>
logger.foreach(_.other(url0, e.getMessage))

View File

@ -1,7 +1,7 @@
package coursier
package test
import coursier.core.{Fetch, Repository}
import coursier.core.{Repository, MavenRepository}
import coursier.test.compatibility._
import utest._
@ -18,7 +18,7 @@ object JsTests extends TestSuite {
}
'get{
Fetch.get("http://repo1.maven.org/maven2/ch/qos/logback/logback-classic/1.1.3/logback-classic-1.1.3.pom")
MavenRepository.get("http://repo1.maven.org/maven2/ch/qos/logback/logback-classic/1.1.3/logback-classic-1.1.3.pom")
.map(core.compatibility.xmlParse)
.map{ xml =>
assert(xml.right.toOption.exists(_.label == "project"))

View File

@ -8,14 +8,19 @@ import scala.io.Codec
import scalaz._, Scalaz._
import scalaz.concurrent.Task
case class Fetch(root: String,
cache: Option[File] = None,
logger: Option[Fetch.Logger] = None) {
case class MavenRepository(
root: String,
cache: Option[File] = None,
ivyLike: Boolean = false,
logger: Option[MavenRepository.Logger] = None
) extends BaseMavenRepository(root, ivyLike) {
val isLocal = root.startsWith("file:///")
def apply(artifact: Artifact,
cachePolicy: Repository.CachePolicy): EitherT[Task, String, String] = {
def fetch(
artifact: Artifact,
cachePolicy: Repository.CachePolicy
): EitherT[Task, String, String] = {
def locally(eitherFile: String \/ File) = {
Task {
@ -44,7 +49,7 @@ case class Fetch(root: String,
val url = new URL(urlStr)
def log = Task(logger.foreach(_.downloading(urlStr)))
def get = Fetch.readFully(url.openStream())
def get = MavenRepository.readFully(url.openStream())
log.flatMap(_ => get)
}
@ -70,7 +75,7 @@ case class Fetch(root: String,
}
object Fetch {
object MavenRepository {
trait Logger {
def downloading(url: String): Unit

View File

@ -1,6 +1,6 @@
package coursier.test
import coursier.core.Fetch
import coursier.core.MavenRepository
import scala.concurrent.{ExecutionContext, Future}
import scalaz.concurrent.Task
@ -14,10 +14,12 @@ package object compatibility {
}
def textResource(path: String)(implicit ec: ExecutionContext): Future[String] = Future {
def is = getClass.getClassLoader
.getResource(path).openStream()
def is = getClass
.getClassLoader
.getResource(path)
.openStream()
new String(Fetch.readFullySync(is), "UTF-8")
new String(MavenRepository.readFullySync(is), "UTF-8")
}
}

View File

@ -1,6 +1,6 @@
package coursier.core
import coursier.core.Resolution.ModuleVersion
import coursier.core.Repository.CachePolicy
import scalaz.{-\/, \/-, \/, EitherT}
import scalaz.concurrent.Task
@ -8,19 +8,21 @@ import scalaz.concurrent.Task
import coursier.core.compatibility.encodeURIComponent
trait Repository {
def find(module: Module,
version: String,
cachePolicy: Repository.CachePolicy = Repository.CachePolicy.Default): EitherT[Task, String, (Artifact.Source, Project)]
def find(
module: Module,
version: String,
cachePolicy: Repository.CachePolicy = Repository.CachePolicy.Default
): EitherT[Task, String, (Artifact.Source, Project)]
}
object Repository {
val mavenCentral = MavenRepository(Fetch("https://repo1.maven.org/maven2/"))
val mavenCentral = MavenRepository("https://repo1.maven.org/maven2/")
val sonatypeReleases = MavenRepository(Fetch("https://oss.sonatype.org/content/repositories/releases/"))
val sonatypeSnapshots = MavenRepository(Fetch("https://oss.sonatype.org/content/repositories/snapshots/"))
val sonatypeReleases = MavenRepository("https://oss.sonatype.org/content/repositories/releases/")
val sonatypeSnapshots = MavenRepository("https://oss.sonatype.org/content/repositories/snapshots/")
lazy val ivy2Local = MavenRepository(Fetch("file://" + sys.props("user.home") + "/.ivy2/local/"), ivyLike = true)
lazy val ivy2Local = MavenRepository("file://" + sys.props("user.home") + "/.ivy2/local/", ivyLike = true)
/**
@ -34,9 +36,11 @@ object Repository {
* version (e.g. version interval). Which version get chosen depends on
* the repository implementation.
*/
def find(repositories: Seq[Repository],
module: Module,
version: String): EitherT[Task, Seq[String], (Artifact.Source, Project)] = {
def find(
repositories: Seq[Repository],
module: Module,
version: String
): EitherT[Task, Seq[String], (Artifact.Source, Project)] = {
val lookups = repositories.map(repo => repo -> repo.find(module, version).run)
val task = lookups.foldLeft(Task.now(-\/(Nil)): Task[Seq[String] \/ (Artifact.Source, Project)]) {
@ -131,7 +135,7 @@ object Repository {
}
}
object MavenRepository {
object BaseMavenRepository {
def ivyLikePath(org: String,
name: String,
@ -154,7 +158,7 @@ object MavenRepository {
project: Project): Seq[Artifact] = {
def ivyLikePath0(subDir: String, baseSuffix: String, ext: String) =
MavenRepository.ivyLikePath(dependency.module.organization, dependency.module.name, project.version, subDir, baseSuffix, ext)
BaseMavenRepository.ivyLikePath(dependency.module.organization, dependency.module.name, project.version, subDir, baseSuffix, ext)
val path =
if (ivyLike)
@ -206,13 +210,20 @@ object MavenRepository {
}
case class MavenRepository(fetch: Fetch,
ivyLike: Boolean = false) extends Repository {
abstract class BaseMavenRepository(
root: String,
ivyLike: Boolean
) extends Repository {
def fetch(
artifact: Artifact,
cachePolicy: CachePolicy
): EitherT[Task, String, String]
import Repository._
import MavenRepository._
import BaseMavenRepository._
val source = MavenRepository.Source(fetch.root, ivyLike)
val source = BaseMavenRepository.Source(root, ivyLike)
def projectArtifact(module: Module, version: String): Artifact = {
val path = (

View File

@ -59,7 +59,8 @@ object CoursierBuild extends Build {
organization := "com.github.alexarchambault",
scalaVersion := "2.11.6",
crossScalaVersions := Seq("2.10.5", "2.11.6"),
resolvers += "Scalaz Bintray Repo" at "http://dl.bintray.com/scalaz/releases"
resolvers += "Scalaz Bintray Repo" at "http://dl.bintray.com/scalaz/releases",
resolvers += Resolver.sonatypeRepo("snapshots")
) ++ publishingSettings
private lazy val commonCoreSettings = commonSettings ++ Seq[Setting[_]](
@ -123,7 +124,7 @@ object CoursierBuild extends Build {
.settings(
name := "coursier-cli",
libraryDependencies ++= Seq(
"com.github.alexarchambault" %% "case-app" % "0.2.2",
"com.github.alexarchambault" %% "case-app" % "0.3.0-SNAPSHOT",
"ch.qos.logback" % "logback-classic" % "1.1.3"
) ++ {
if (scalaVersion.value startsWith "2.10.")

View File

@ -1,7 +1,7 @@
package coursier
package web
import coursier.core.{Repository, MavenRepository, Fetch}
import coursier.core.{Repository, BaseMavenRepository, MavenRepository}
import japgolly.scalajs.react.vdom.{TagMod, Attr}
import japgolly.scalajs.react.vdom.Attrs.dangerouslySetInnerHtml
import japgolly.scalajs.react.{ReactEventI, ReactComponentB, BackendScope}
@ -111,7 +111,7 @@ class Backend($: BackendScope[Unit, State]) {
g.$("#resLogTab a:last").tab("show")
$.modState(_.copy(resolving = true, log = Nil))
val logger: Fetch.Logger = new Fetch.Logger {
val logger: MavenRepository.Logger = new MavenRepository.Logger {
def fetched(url: String) = {
println(s"<- $url")
$.modState(s => s.copy(log = s"<- $url" +: s.log))
@ -135,7 +135,7 @@ class Backend($: BackendScope[Unit, State]) {
res
.process
.run(fetch(s.repositories.map(r => r.copy(fetch = r.fetch.copy(logger = Some(logger))))), 100)
.run(fetch(s.repositories.map(r => r.copy(logger = Some(logger)))), 100)
}
// For reasons that are unclear to me, not delaying this when using the runNow execution context
@ -246,7 +246,7 @@ object App {
)),
<.td(Seq[Seq[TagMod]](
res.projectCache.get(dep.moduleVersion) match {
case Some((source: MavenRepository.Source, proj)) if !source.ivyLike =>
case Some((source: BaseMavenRepository.Source, proj)) if !source.ivyLike =>
// FIXME Maven specific, generalize with source.artifacts
val version0 = finalVersionOpt getOrElse dep.version
val relPath =
@ -401,14 +401,14 @@ object App {
def repoItem(repo: MavenRepository) =
<.tr(
<.td(
<.a(^.href := repo.fetch.root,
repo.fetch.root
<.a(^.href := repo.root,
repo.root
)
)
)
val sortedRepos = repos
.sortBy(repo => repo.fetch.root)
.sortBy(repo => repo.root)
<.table(^.`class` := "table",
<.thead(