mirror of https://github.com/sbt/sbt.git
Local ivy2 support
This commit is contained in:
parent
717fdf1ad5
commit
95f51fdb8f
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue