Local ivy2 support

This commit is contained in:
Alexandre Archambault 2015-06-26 00:59:07 +01:00
parent 717fdf1ad5
commit 95f51fdb8f
5 changed files with 168 additions and 107 deletions

View File

@ -22,9 +22,7 @@ case class Coursier(scope: List[String],
val centralCacheDir = new File(sys.props("user.home") + "/.coursier/cache/metadata/central")
val centralFilesCacheDir = new File(sys.props("user.home") + "/.coursier/cache/files/central")
val base = centralCacheDir.toURI
def fileRepr(f: File) =
base.relativize(f.toURI).getPath
def fileRepr(f: File) = f.toString
val logger: MetadataFetchLogger with FilesLogger = new MetadataFetchLogger with FilesLogger {
def println(s: String) = Console.err.println(s)
@ -60,7 +58,12 @@ case class Coursier(scope: List[String],
)
)
val repositories = Seq[Repository](
cachedMavenCentral
cachedMavenCentral,
repository.ivy2Local.copy(
fetchMetadata = repository.ivy2Local.fetchMetadata.copy(
logger = Some(logger)
)
)
)
val (splitDependencies, malformed) = remainingArgs.toList
@ -132,7 +135,13 @@ case class Coursier(scope: List[String],
val artifacts = res.artifacts
val files = new Files(Seq(cachedMavenCentral.fetchMetadata.root -> centralFilesCacheDir), () => ???, Some(logger))
val files = new Files(
Seq(
cachedMavenCentral.fetchMetadata.root -> centralFilesCacheDir
),
() => ???,
Some(logger)
)
val tasks = artifacts.map(files.file(_, cachePolicy).run)
val task = Task.gatherUnordered(tasks)

View File

@ -2,7 +2,7 @@ package coursier
package core
import java.io._
import java.net.URL
import java.net.{URI, URL}
import scala.io.Codec
import scalaz._, Scalaz._
@ -19,18 +19,13 @@ case class DefaultFetchMetadata(root: String,
cache: Option[File] = None,
logger: Option[MetadataFetchLogger] = None) extends FetchMetadata {
def apply(artifact: Artifact, cachePolicy: CachePolicy): EitherT[Task, String, String] = {
lazy val localFile = {
for {
cache0 <- cache.toRightDisjunction("No cache")
f = new File(cache0, artifact.url)
} yield f
}
val isLocal = root.startsWith("file:///")
def locally = {
def apply(artifact: Artifact, cachePolicy: CachePolicy): EitherT[Task, String, String] = {
def locally(eitherFile: String \/ File) = {
Task {
for {
f0 <- localFile
f0 <- eitherFile
f <- Some(f0).filter(_.exists()).toRightDisjunction("Not found in cache")
content <- \/.fromTryCatchNonFatal{
logger.foreach(_.readingFromCache(f))
@ -40,32 +35,42 @@ case class DefaultFetchMetadata(root: String,
}
}
def remote = {
val urlStr = root + artifact.url
val url = new URL(urlStr)
if (isLocal) EitherT(locally(\/-(new File(new URI(root + artifact.url) .getPath))))
else {
lazy val localFile = {
for {
cache0 <- cache.toRightDisjunction("No cache")
f = new File(cache0, artifact.url)
} yield f
}
def log = Task(logger.foreach(_.downloading(urlStr)))
def get = DefaultFetchMetadata.readFully(url.openStream())
def remote = {
val urlStr = root + artifact.url
val url = new URL(urlStr)
log.flatMap(_ => get)
}
def log = Task(logger.foreach(_.downloading(urlStr)))
def get = DefaultFetchMetadata.readFully(url.openStream())
def save(s: String) = {
localFile.fold(_ => Task.now(()), f =>
Task {
if (!f.exists()) {
logger.foreach(_.puttingInCache(f))
f.getParentFile.mkdirs()
val w = new PrintWriter(f)
try w.write(s)
finally w.close()
()
log.flatMap(_ => get)
}
def save(s: String) = {
localFile.fold(_ => Task.now(()), f =>
Task {
if (!f.exists()) {
logger.foreach(_.puttingInCache(f))
f.getParentFile.mkdirs()
val w = new PrintWriter(f)
try w.write(s)
finally w.close()
()
}
}
}
)
}
)
}
EitherT(cachePolicy.saving(locally)(remote)(save))
EitherT(cachePolicy.saving(locally(localFile))(remote)(save))
}
}
}

View File

@ -66,7 +66,7 @@ object Repository {
Artifact.javadoc -> (base + "-javadoc.jar"),
Artifact.javadocSigMd5 -> (base + "-javadoc.jar.asc.md5"),
Artifact.javadocSigSha1 -> (base + "-javadoc.jar.asc.sha1"),
Artifact.javadocSig -> (base + "-javadoc.asc.jar")
Artifact.javadocSig -> (base + "-javadoc.jar.asc")
))
}
}
@ -83,27 +83,35 @@ case class MavenRepository[F <: FetchMetadata](fetchMetadata: F,
import Repository._
def ivyLikePath(org: String, name: String, version: String, subDir: String, baseSuffix: String, ext: String) = Seq(
org,
name,
version,
subDir,
s"$name$baseSuffix.$ext"
)
def projectArtifact(module: Module, version: String): Artifact = {
if (ivyLike) ???
else {
val path = (
val path = (
if (ivyLike)
ivyLikePath(module.organization, module.name, version, "poms", "", "pom")
else
module.organization.split('.').toSeq ++ Seq(
module.name,
version,
s"${module.name}-$version.pom"
)
) .map(encodeURIComponent)
) .map(encodeURIComponent)
Artifact(
path.mkString("/"),
Map(
Artifact.md5 -> "",
Artifact.sha1 -> ""
),
Attributes("pom", "")
)
.withDefaultSignature
}
Artifact(
path.mkString("/"),
Map(
Artifact.md5 -> "",
Artifact.sha1 -> ""
),
Attributes("pom", "")
)
.withDefaultSignature
}
def versionsArtifact(module: Module): Option[Artifact] =
@ -202,12 +210,18 @@ case class MavenRepository[F <: FetchMetadata](fetchMetadata: F,
def artifacts(dependency: Dependency,
project: Project): Seq[Artifact] = {
def ivyLikePath0(subDir: String, baseSuffix: String, ext: String) =
ivyLikePath(dependency.module.organization, dependency.module.name, project.version, subDir, baseSuffix, ext)
val path =
dependency.module.organization.split('.').toSeq ++ Seq(
dependency.module.name,
project.version,
s"${dependency.module.name}-${project.version}${Some(dependency.attributes.classifier).filter(_.nonEmpty).map("-"+_).mkString}.${dependency.attributes.`type`}"
)
if (ivyLike)
ivyLikePath0(dependency.attributes.`type` + "s", "", dependency.attributes.`type`)
else
dependency.module.organization.split('.').toSeq ++ Seq(
dependency.module.name,
project.version,
s"${dependency.module.name}-${project.version}${Some(dependency.attributes.classifier).filter(_.nonEmpty).map("-"+_).mkString}.${dependency.attributes.`type`}"
)
var artifact =
Artifact(
@ -217,10 +231,31 @@ case class MavenRepository[F <: FetchMetadata](fetchMetadata: F,
)
.withDefaultChecksums
if (dependency.attributes.`type` == "jar")
artifact = artifact
.withDefaultSignature
.withJavadocSources
if (dependency.attributes.`type` == "jar") {
artifact = artifact.withDefaultSignature
artifact =
if (ivyLike) {
val srcPath = fetchMetadata.root + ivyLikePath0("srcs", "-sources", "jar").mkString("/")
val javadocPath = fetchMetadata.root + ivyLikePath0("docs", "-javadoc", "jar").mkString("/")
artifact
.copy(extra = artifact.extra ++ Map(
Artifact.sourcesMd5 -> (srcPath + ".md5"),
Artifact.sourcesSha1 -> (srcPath + ".sha1"),
Artifact.sources -> srcPath,
Artifact.sourcesSigMd5 -> (srcPath + ".asc.md5"),
Artifact.sourcesSigSha1 -> (srcPath + ".asc.sha1"),
Artifact.sourcesSig -> (srcPath + ".asc"),
Artifact.javadocMd5 -> (javadocPath + ".md5"),
Artifact.javadocSha1 -> (javadocPath + ".sha1"),
Artifact.javadoc -> javadocPath,
Artifact.javadocSigMd5 -> (javadocPath + ".asc.md5"),
Artifact.javadocSigSha1 -> (javadocPath + ".asc.sha1"),
Artifact.javadocSig -> (javadocPath + ".asc")
))
} else artifact.withJavadocSources
}
Seq(artifact)
}

View File

@ -9,4 +9,6 @@ package object repository {
val sonatypeReleases = MavenRepository(DefaultFetchMetadata("https://oss.sonatype.org/content/repositories/releases/"))
val sonatypeSnapshots = MavenRepository(DefaultFetchMetadata("https://oss.sonatype.org/content/repositories/snapshots/"))
lazy val ivy2Local = MavenRepository(DefaultFetchMetadata("file://" + sys.props("user.home") + "/.ivy2/local/"), ivyLike = true)
}

View File

@ -1,6 +1,6 @@
package coursier
import java.net.URL
import java.net.{URI, URL}
import coursier.core.CachePolicy
@ -24,65 +24,75 @@ case class Files(cache: Seq[(String, File)],
def file(artifact: Artifact,
cachePolicy: CachePolicy): EitherT[Task, String, File] = {
cache.find{case (base, _) => artifact.url.startsWith(base)} match {
case None => ???
case Some((base, cacheDir)) =>
val file = new File(cacheDir, artifact.url.stripPrefix(base))
if (artifact.url.startsWith("file:///")) {
val f = new File(new URI(artifact.url) .getPath)
EitherT(Task.now(
if (f.exists()) {
logger.foreach(_.foundLocally(f))
\/-(f)
} else -\/("Not found")
))
} else {
cache.find{case (base, _) => artifact.url.startsWith(base)} match {
case None => ???
case Some((base, cacheDir)) =>
val file = new File(cacheDir, artifact.url.stripPrefix(base))
def locally = {
Task {
if (file.exists()) {
logger.foreach(_.foundLocally(file))
\/-(file)
def locally = {
Task {
if (file.exists()) {
logger.foreach(_.foundLocally(file))
\/-(file)
}
else -\/("Not found in cache")
}
else -\/("Not found in cache")
}
}
def remote = {
// FIXME A lot of things can go wrong here and are not properly handled:
// - checksums should be validated
// - what if the connection gets closed during the transfer (partial file on disk)?
// - what if someone is trying to write this file at the same time? (no locking of any kind yet)
// - ...
Task {
try {
file.getParentFile.mkdirs()
logger.foreach(_.downloadingArtifact(artifact.url))
val url = new URL(artifact.url)
val b = Array.fill[Byte](Files.bufferSize)(0)
val in = new BufferedInputStream(url.openStream(), Files.bufferSize)
def remote = {
// FIXME A lot of things can go wrong here and are not properly handled:
// - checksums should be validated
// - what if the connection gets closed during the transfer (partial file on disk)?
// - what if someone is trying to write this file at the same time? (no locking of any kind yet)
// - ...
Task {
try {
val out = new FileOutputStream(file)
file.getParentFile.mkdirs()
logger.foreach(_.downloadingArtifact(artifact.url))
val url = new URL(artifact.url)
val b = Array.fill[Byte](Files.bufferSize)(0)
val in = new BufferedInputStream(url.openStream(), Files.bufferSize)
try {
@tailrec
def helper(): Unit = {
val read = in.read(b)
if (read >= 0) {
out.write(b, 0, read)
helper()
val out = new FileOutputStream(file)
try {
@tailrec
def helper(): Unit = {
val read = in.read(b)
if (read >= 0) {
out.write(b, 0, read)
helper()
}
}
}
helper()
} finally out.close()
} finally in.close()
helper()
} finally out.close()
} finally in.close()
logger.foreach(_.downloadedArtifact(artifact.url, success = true))
\/-(file)
}
catch { case e: Exception =>
logger.foreach(_.downloadedArtifact(artifact.url, success = false))
-\/(e.getMessage)
logger.foreach(_.downloadedArtifact(artifact.url, success = true))
\/-(file)
}
catch { case e: Exception =>
logger.foreach(_.downloadedArtifact(artifact.url, success = false))
-\/(e.getMessage)
}
}
}
}
EitherT(cachePolicy(locally)(remote))
EitherT(cachePolicy(locally)(remote))
}
}
}