Don't rely on directory listings anymore

This commit is contained in:
Alexandre Archambault 2018-09-19 15:22:27 +02:00
parent 9968a12d10
commit 48c58d1e96
3 changed files with 15 additions and 282 deletions

View File

@ -316,110 +316,21 @@ final case class MavenRepository(
proj <- Pom.project(xml, relocationAsDependency = true).right
} yield proj
def isArtifact(fileName: String, prefix: String): Option[(String, String)] =
// TODO There should be a regex for that...
if (fileName.startsWith(prefix)) {
val end = fileName.stripPrefix(prefix)
val idx = end.indexOf('.')
if (idx >= 0) {
val ext = end.drop(idx + 1)
val rem = end.take(idx)
if (rem.isEmpty)
Some(("", ext))
else if (rem.startsWith("-"))
Some((rem.drop(1), ext))
else
None
} else
None
} else
None
val projectArtifact0 = projectArtifact(module, version, versioningValue)
val listFilesUrl = urlFor(moduleVersionPath(module, version)) + "/"
val changing0 = changing.getOrElse(isSnapshot(version))
val listFilesArtifact =
Artifact(
listFilesUrl,
Map.empty,
Map(
"metadata" -> projectArtifact0
),
Attributes("", ""),
changing = changing0,
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 {
str <- fetch(requiringDirListingProjectArtifact)
rawListFilesPageOpt <- EitherT(F.map(fetch(artifactFor(listFilesUrl, changing0)).run) {
e => Right(e.right.toOption): Either[String, Option[String]]
})
str <- fetch(projectArtifact0)
proj0 <- EitherT(F.point[Either[String, Project]](parseRawPom(str)))
} yield {
val foundPublications =
rawListFilesPageOpt match {
case Some(rawListFilesPage) =>
val files = WebPage.listFiles(listFilesUrl, rawListFilesPage)
val prefix = s"${module.name}-${versioningValue.getOrElse(version)}"
val packagingTpeMap = proj0.packagingOpt
.filter(_ != Pom.relocatedPackaging)
.map { packaging =>
(MavenSource.typeDefaultClassifier(packaging), MavenSource.typeExtension(packaging)) -> packaging
}
.toMap
files
.flatMap(isArtifact(_, prefix))
.map {
case (classifier, ext) =>
val tpe = packagingTpeMap.getOrElse(
(classifier, ext),
MavenSource.classifierExtensionDefaultTypeOpt(classifier, ext).getOrElse(ext)
)
val config = MavenSource.typeDefaultConfig(tpe).getOrElse("compile")
config -> Publication(
module.name,
tpe,
ext,
classifier
)
}
case None =>
// Publications can't be listed - MavenSource then handles that
Nil
}
val proj = Pom.addOptionalDependenciesInConfig(
proj0.copy(configurations = defaultConfigurations),
} yield
Pom.addOptionalDependenciesInConfig(
proj0.copy(
actualVersionOpt = Some(version),
configurations = defaultConfigurations
),
Set("", "default"),
"optional"
)
proj.copy(
actualVersionOpt = Some(version),
publications = foundPublications
)
}
}
def find[F[_]](

View File

@ -32,7 +32,11 @@ final case class MavenSource(
val versioning = project
.snapshotVersioning
.flatMap(versioning =>
mavenVersioning(versioning, publication.classifier, publication.`type`)
mavenVersioning(
versioning,
publication.classifier,
MavenSource.typeExtension(publication.`type`)
)
)
val path = dependency.module.organization.split('.').toSeq ++ Seq(
@ -52,6 +56,7 @@ final case class MavenSource(
authentication = authentication
)
.withDefaultChecksums
.withDefaultSignature
if (publication.ext == "jar")
artifact = artifact.withDefaultSignature
@ -133,142 +138,6 @@ final case class MavenSource(
.map(artifactWithExtra)
}
private val types = Map("sha1" -> "SHA-1", "sha256" -> "SHA-256", "md5" -> "MD5", "asc" -> "sig")
private def artifactsKnownPublications(
dependency: Dependency,
project: Project,
overrideClassifiers: Option[Seq[String]]
): Seq[Artifact] = {
final case class EnrichedPublication(
publication: Publication,
extra: Map[String, EnrichedPublication]
) {
def artifact: Artifact =
artifact(publication.`type`)
def artifact(versioningType: String): Artifact = {
val versioningExtension = MavenSource.typeExtensions.getOrElse(versioningType, versioningType)
val versioning = project
.snapshotVersioning
.flatMap(versioning =>
mavenVersioning(versioning, publication.classifier, versioningExtension)
)
val path = dependency.module.organization.split('.').toSeq ++ Seq(
MavenRepository.dirModuleName(dependency.module, sbtAttrStub),
project.actualVersion,
s"${dependency.module.name}-${versioning getOrElse project.actualVersion}${Some(publication.classifier).filter(_.nonEmpty).map("-" + _).mkString}.${publication.ext}"
)
val changing0 = changing.getOrElse(isSnapshot(project.actualVersion))
val extra0 = extra.mapValues(_.artifact(versioningType)).iterator.toMap
Artifact(
root + path.mkString("/"),
extra0.filterKeys(MavenSource.checksumTypes).mapValues(_.url).iterator.toMap,
extra0,
publication.attributes,
changing = changing0,
authentication = authentication
)
}
}
def groupedEnrichedPublications(publications: Seq[Publication]): Seq[EnrichedPublication] = {
def helper(publications: Seq[Publication]): Seq[EnrichedPublication] = {
var publications0 = publications
.map { pub =>
pub.ext -> EnrichedPublication(pub, Map())
}
.toMap
val byLength = publications0.toVector.sortBy(-_._1.length)
for {
(ext, _) <- byLength
idx = ext.lastIndexOf('.')
if idx >= 0
subExt = ext.substring(idx + 1)
baseExt = ext.substring(0, idx)
tpe <- types.get(subExt)
mainPub <- publications0.get(baseExt)
} {
val pub = publications0(ext)
publications0 += baseExt -> mainPub.copy(
extra = mainPub.extra + (tpe -> pub)
)
publications0 -= ext
}
publications0.values.toVector
}
publications
.groupBy(p => (p.name, p.classifier))
.mapValues(helper)
.values
.toVector
.flatten
}
val enrichedPublications = groupedEnrichedPublications(project.publications.map(_._2))
val metadataArtifactOpt = enrichedPublications.collectFirst {
case pub if pub.publication.name == dependency.module.name &&
pub.publication.ext == "pom" &&
pub.publication.classifier.isEmpty =>
pub.artifact
}
def withMetadataExtra(artifact: Artifact) =
metadataArtifactOpt.fold(artifact) { metadataArtifact =>
artifact.copy(
extra = artifact.extra + ("metadata" -> metadataArtifact)
)
}
val res = overrideClassifiers match {
case Some(classifiers) =>
val classifiersSet = classifiers.toSet
enrichedPublications.collect {
case p if classifiersSet(p.publication.classifier) =>
p.artifact
}
case None =>
if (dependency.attributes.classifier.nonEmpty)
// FIXME We're ignoring dependency.attributes.`type` in this case
enrichedPublications.collect {
case p if p.publication.classifier == dependency.attributes.classifier =>
p.artifact
}
else if (dependency.attributes.`type`.nonEmpty)
enrichedPublications.collect {
case p
if (p.publication.classifier.isEmpty || p.publication.classifier == MavenSource.typeDefaultClassifier(dependency.attributes.`type`)) && (
p.publication.`type` == dependency.attributes.`type` ||
(p.publication.ext == dependency.attributes.`type` && project.packagingOpt.toSeq.contains(p.publication.`type`)) // wow
) =>
p.artifact
}
else
enrichedPublications.collect {
case p if p.publication.classifier.isEmpty =>
p.artifact
}
}
res.map(withMetadataExtra)
}
private val dummyArtifact = Artifact("", Map(), Map(), Attributes("", ""), changing = false, None)
def artifacts(
@ -285,52 +154,13 @@ final case class MavenSource(
extra = a.extra.mapValues(makeOptional).iterator.toMap + (Artifact.optionalKey -> dummyArtifact)
)
def merge(a: Artifact, other: Artifact): Artifact = {
assert(a.url == other.url, s"Merging artifacts with different URLs (${a.url}, ${other.url})")
val extra =
a.extra.map {
case (k, v) =>
k -> other.extra.get(k).fold(v)(merge(v, _))
} ++
other.extra
.filterKeys(k => !a.extra.contains(k) && k != Artifact.optionalKey)
a.copy(
checksumUrls = other.checksumUrls ++ a.checksumUrls,
extra = extra
)
}
val defaultPublications = artifactsUnknownPublications(dependency, project, overrideClassifiers)
artifactsUnknownPublications(dependency, project, overrideClassifiers)
.map(makeOptional)
if (project.publications.isEmpty)
defaultPublications
else {
val listedPublications = artifactsKnownPublications(dependency, project, overrideClassifiers)
val listedUrls = listedPublications.map(_.url).toSet
val defaultPublicationsMap = defaultPublications
.map(a => a.url -> a)
.toMap
val listedPublications0 = listedPublications.map { a =>
defaultPublicationsMap
.get(a.url)
.fold(a)(merge(a, _))
}
val extraPublications = defaultPublications
.filter(a => !listedUrls(a.url))
listedPublications0 ++ extraPublications
}
}
}
object MavenSource {
private val checksumTypes = Set("MD5", "SHA-1", "SHA-256")
val typeExtensions: Map[String, String] = Map(
"eclipse-plugin" -> "jar",
"maven-plugin" -> "jar",
@ -373,12 +203,4 @@ object MavenSource {
def classifierExtensionDefaultTypeOpt(classifier: String, ext: String): Option[String] =
classifierExtensionDefaultTypes.get((classifier, ext))
val typeDefaultConfigs: Map[String, String] = Map(
"doc" -> "docs",
"src" -> "sources"
)
def typeDefaultConfig(`type`: String): Option[String] =
typeDefaultConfigs.get(`type`)
}

@ -1 +1 @@
Subproject commit ed446075ace7914af71a39ac7b00f17fa5d9190b
Subproject commit cdad75ba739422d2f110e0e70093e21c4cb0e6d6