The “except” part is exactly the point. The bigger topic of @Lance’s plugin is to make (also parent) POMs available offline. I.e. the plugin needs to get parent POM files some somewhere , not necessarily from an ArtifactResolutionQuery
(though I agree that would be a convenient solution).
As I also answered in Slack, you can perfectly fine get the ancestor POMs through ArtifactResolutionQuery
s. And after you got them through it, they should also be in the cache, while it should be totally irrelevant whether they are in the cache directory as files or not if you get them properly through the query.
If a regular ArtifactResolutionQuery
would always download the parent POMs also as files , even if binary metadata is already available, and put them into Gradle’s cache, the plugin could simply pick them up from the cache.
Which would be a very bad idea and not very portable across Gradle versions. Cache layout can change and so on. Especially if there is a proper way to do it already, just not convenient.
Gradle is excellent in avoiding unnecessary work. And downloading the parent POM as file and putting it to the cache is totally unnecessary work if it is already present in a more efficient format, so why should Gradle waste time?
If you want the actual POM, there is a way to get it and that is an ArtifactResolutionQuery
.
As an example here is how I check for jdk-version activated profiles in dependencies which are not supported by Gradle and thus need to be taken account for manually by component metadata rules to fixup the dependencies:
val checkForJdkActivatedProfiles by tasks.registering {
doLast {
val pomReader = MavenXpp3Reader()
fun collectAncestorPoms(pom: ResolvedArtifactResult, result: MutableList<ResolvedArtifactResult>) {
val parent = FileReader(pom.file)
.use { pomReader.read(it) }
.parent
if (parent != null) {
val parentPom = dependencies
.createArtifactResolutionQuery()
.forModule(parent.groupId, parent.artifactId, parent.version)
.withArtifacts(MavenModule::class.java, MavenPomArtifact::class.java)
.execute()
.resolvedComponents
.asSequence()
.flatMap { it.getArtifacts(MavenPomArtifact::class.java).asSequence() }
.filterIsInstance<ResolvedArtifactResult>()
.single()
result.add(parentPom)
collectAncestorPoms(parentPom, result)
}
}
dependencies
.createArtifactResolutionQuery()
.forComponents(configurations.filter { it.isCanBeResolved }.flatMap { configuration ->
configuration.incoming.resolutionResult.allDependencies.mapNotNull {
(it as? ResolvedDependencyResult)?.selected?.id
}
}.distinct())
.withArtifacts(MavenModule::class.java, MavenPomArtifact::class.java)
.execute()
.resolvedComponents
.asSequence()
.flatMap { it.getArtifacts(MavenPomArtifact::class.java).asSequence() }
.filterIsInstance<ResolvedArtifactResult>()
.map { pom ->
val ancestorPoms = mutableListOf<ResolvedArtifactResult>()
collectAncestorPoms(pom, ancestorPoms)
Pair(pom, ancestorPoms)
}
.forEach { (bottomPom, ancestorPoms) ->
sequenceOf(bottomPom, *ancestorPoms.toTypedArray()).forEach { pom ->
FileReader(pom.file)
.use { pomReader.read(it) }
.profiles
.forEach { profile ->
if ((profile.activation?.jdk != null) && (!profile.dependencies.isNullOrEmpty())) {
println("jdk activated Maven profile with dependencies found in ${pom.id}")
if (pom != bottomPom) {
println("ancestor of dependency ${bottomPom.id}")
}
}
}
}
}
}
}
Even if the parent POMs would always land in the cache directory, the logic would not change much as you would still need to parse the POM to get the parent coordinates to get the POM from the cache and so on, so you can right away use the proper supported way to get it.
The point of this thread is to save this boilerplate and instead just be able to also get the ancestor POMs from the initial artifact resolution query.