Merge pull request #504 from coursier/topic/tweak-dir-listing-cache

Tweak dir listing cache
This commit is contained in:
Alexandre Archambault 2017-04-19 11:49:30 +02:00 committed by GitHub
commit c144feca94
2 changed files with 83 additions and 21 deletions

View File

@ -624,14 +624,16 @@ object Cache {
} }
} }
def errFile(file: File) = new File(file.getParentFile, "." + file.getName + ".error")
def remoteKeepErrors(file: File, url: String): EitherT[Task, FileError, Unit] = { def remoteKeepErrors(file: File, url: String): EitherT[Task, FileError, Unit] = {
val errFile = new File(file.getParentFile, "." + file.getName + ".error") val errFile0 = errFile(file)
def validErrFileExists = def validErrFileExists =
EitherT { EitherT {
Task { Task {
(referenceFileExists && errFile.exists()).right[FileError] (referenceFileExists && errFile0.exists()).right[FileError]
} }
} }
@ -639,8 +641,8 @@ object Cache {
EitherT { EitherT {
Task { Task {
if (referenceFileExists) { if (referenceFileExists) {
if (!errFile.exists()) if (!errFile0.exists())
FileUtil.write(errFile, "".getBytes("UTF-8")) FileUtil.write(errFile0, "".getBytes("UTF-8"))
} }
().right[FileError] ().right[FileError]
@ -650,8 +652,8 @@ object Cache {
def deleteErrFile = def deleteErrFile =
EitherT { EitherT {
Task { Task {
if (errFile.exists()) if (errFile0.exists())
errFile.delete() errFile0.delete()
().right[FileError] ().right[FileError]
} }
@ -681,6 +683,23 @@ object Cache {
} }
} }
def localInfo(file: File, url: String): EitherT[Task, FileError, Boolean] = {
val errFile0 = errFile(file)
// memo-ized
lazy val res =
if (file.exists())
true.right[FileError]
else if (referenceFileExists && errFile0.exists())
FileError.NotFound(url, Some(true)).left[Boolean]
else
false.right[FileError]
EitherT(Task(res))
}
def checkFileExists(file: File, url: String, log: Boolean = true): EitherT[Task, FileError, Unit] = def checkFileExists(file: File, url: String, log: Boolean = true): EitherT[Task, FileError, Unit] =
EitherT { EitherT {
Task { Task {
@ -695,16 +714,42 @@ object Cache {
val urls = val urls =
artifact.url +: { artifact.url +: {
checksums checksums
.intersect(artifact.checksumUrls.keySet)
.toSeq .toSeq
.map(artifact.checksumUrls) .flatMap(artifact.checksumUrls.get)
} }
val cachePolicy0 = cachePolicy match {
case CachePolicy.UpdateChanging if !artifact.changing =>
CachePolicy.FetchMissing
case CachePolicy.LocalUpdateChanging if !artifact.changing =>
CachePolicy.LocalOnly
case other =>
other
}
val requiredArtifactCheck = artifact.extra.get("required") match {
case None =>
EitherT(Task.now(().right[FileError]))
case Some(required) =>
cachePolicy0 match {
case CachePolicy.LocalOnly | CachePolicy.LocalUpdateChanging | CachePolicy.LocalUpdate =>
val file = localFile(required.url, cache, artifact.authentication.map(_.user))
localInfo(file, required.url).flatMap {
case true =>
EitherT(Task.now(().right[FileError]))
case false =>
EitherT(Task.now(FileError.NotFound(file.toString).left[Unit]))
}
case _ =>
EitherT(Task.now(().right[FileError]))
}
}
val tasks = val tasks =
for (url <- urls) yield { for (url <- urls) yield {
val file = localFile(url, cache, artifact.authentication.map(_.user)) val file = localFile(url, cache, artifact.authentication.map(_.user))
val res = def res =
if (url.startsWith("file:/")) { if (url.startsWith("file:/")) {
// for debug purposes, flaky with URL-encoded chars anyway // for debug purposes, flaky with URL-encoded chars anyway
// def filtered(s: String) = // def filtered(s: String) =
@ -722,15 +767,6 @@ object Cache {
EitherT(Task.now[FileError \/ Unit](().right)) EitherT(Task.now[FileError \/ Unit](().right))
} }
val cachePolicy0 = cachePolicy match {
case CachePolicy.UpdateChanging if !artifact.changing =>
CachePolicy.FetchMissing
case CachePolicy.LocalUpdateChanging if !artifact.changing =>
CachePolicy.LocalOnly
case other =>
other
}
cachePolicy0 match { cachePolicy0 match {
case CachePolicy.LocalOnly => case CachePolicy.LocalOnly =>
checkFileExists(file, url) checkFileExists(file, url)
@ -747,8 +783,10 @@ object Cache {
} }
} }
requiredArtifactCheck
res.run.map((file, url) -> _) .flatMap(_ => res)
.run
.map((file, url) -> _)
} }
Nondeterminism[Task].gather(tasks) Nondeterminism[Task].gather(tasks)

View File

@ -282,10 +282,34 @@ final case class MavenRepository(
None None
val projectArtifact0 = projectArtifact(module, version, versioningValue)
val listFilesUrl = urlFor(modulePath(module, version)) + "/" val listFilesUrl = urlFor(modulePath(module, version)) + "/"
val listFilesArtifact =
Artifact(
listFilesUrl,
Map.empty,
Map(
"metadata" -> projectArtifact0
),
Attributes("", ""),
changing = changing.getOrElse(version.contains("-SNAPSHOT")),
authentication
)
val requiringDirListingProjectArtifact = projectArtifact0
.copy(
extra = projectArtifact0.extra + (
// In LocalUpdate and LocalUpdateChanging mode, makes getting the POM fail if the POM
// is in cache, but no info about the directory listing is (directory listing not in cache and no kept error
// for it).
"required" -> listFilesArtifact
)
)
for { for {
str <- fetch(projectArtifact(module, version, versioningValue)) str <- fetch(requiringDirListingProjectArtifact)
rawListFilesPageOpt <- EitherT(F.map(fetch(artifactFor(listFilesUrl)).run) { rawListFilesPageOpt <- EitherT(F.map(fetch(artifactFor(listFilesUrl)).run) {
e => \/-(e.toOption): String \/ Option[String] e => \/-(e.toOption): String \/ Option[String]
}) })