-
Notifications
You must be signed in to change notification settings - Fork 381
analyzer: Decouple the implementations of the two Gradle package managers #11942
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a02aa1b
5395e7c
72d3aed
26ff549
94cb08f
ecc6462
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,7 +19,7 @@ | |
|
|
||
| package org.ossreviewtoolkit.plugins.packagemanagers.gradleplugin | ||
|
|
||
| import OrtDependency | ||
| import OrtComponent | ||
| import OrtDependencyTreeModel | ||
|
|
||
| import org.apache.maven.model.building.FileModelSource | ||
|
|
@@ -54,10 +54,10 @@ internal class OrtModelBuilder : ToolingModelBuilder { | |
| private val logger = Logging.getLogger(OrtModelBuilder::class.java) | ||
| private val errors = mutableListOf<String>() | ||
| private val warnings = mutableListOf<String>() | ||
| private val globalDependencySubtrees = mutableMapOf<String, List<OrtDependency>>() | ||
| private val globalDependencySubtrees = mutableMapOf<String, List<OrtComponent>>() | ||
|
|
||
| // Only create one "OrtDependency" for each "ResolvedComponentResult". | ||
| private val ortDependencyCache = mutableMapOf<ResolvedComponentResult, OrtDependency>() | ||
| // Only create one "OrtComponent" for each "ResolvedComponentResult". | ||
| private val ortComponentCache = mutableMapOf<ResolvedComponentResult, OrtComponent>() | ||
|
|
||
| override fun canBuild(modelName: String): Boolean = modelName == OrtDependencyTreeModel::class.java.name | ||
|
|
||
|
|
@@ -88,7 +88,7 @@ internal class OrtModelBuilder : ToolingModelBuilder { | |
|
|
||
| // Omit configurations without dependencies. | ||
| root.dependencies.takeUnless { it.isEmpty() }?.let { dep -> | ||
| OrtConfigurationImpl(name = config.name, dependencies = dep.toOrtDependencies(poms, emptySet())) | ||
| OrtConfigurationImpl(name = config.name, dependencies = dep.toOrtComponents(poms, emptySet())) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -103,63 +103,22 @@ internal class OrtModelBuilder : ToolingModelBuilder { | |
| ) | ||
| } | ||
|
|
||
| /** | ||
| * Resolve the POM files for all dependences in the given [Gradle configuration][config] incl. their parent POMs. | ||
| */ | ||
| private fun Project.resolvePoms(config: Configuration): Map<String, ModelBuildingResult> { | ||
| val allComponentIds = config.incoming.resolutionResult.allDependencies | ||
| .filterIsInstance<ResolvedDependencyResult>() | ||
| .map { it.selected.id } | ||
| .distinct() | ||
|
|
||
| // Get the POM files for all resolved dependencies. | ||
| val pomFiles = resolvePoms(allComponentIds) | ||
|
|
||
| val fileModelBuilder = FileModelBuilder { groupId, artifactId, version -> | ||
| val moduleId = DefaultModuleIdentifier.newId(groupId, artifactId) | ||
| val componentId = DefaultModuleComponentIdentifier.newId(moduleId, version) | ||
|
|
||
| val pomFile = resolvePoms(listOf(componentId)).single().file | ||
|
|
||
| FileModelSource(pomFile) | ||
| } | ||
|
|
||
| return pomFiles.associate { | ||
| // Trigger resolution of parent POMs by building the POM model. | ||
| it.id.componentIdentifier.toString() to fileModelBuilder.buildModel(it.file) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Resolve the POM files for the given [componentIds] and return them. | ||
| */ | ||
| private fun Project.resolvePoms(componentIds: List<ComponentIdentifier>): List<ResolvedArtifactResult> { | ||
| val resolutionResult = dependencies.createArtifactResolutionQuery() | ||
| .forComponents(componentIds) | ||
| .withArtifacts(MavenModule::class.java, MavenPomArtifact::class.java) | ||
| .execute() | ||
|
|
||
| return resolutionResult.resolvedComponents.flatMap { | ||
| it.getArtifacts(MavenPomArtifact::class.java) | ||
| }.filterIsInstance<ResolvedArtifactResult>() | ||
| } | ||
|
|
||
| private fun Collection<DependencyResult>.toOrtDependencies( | ||
| private fun Collection<DependencyResult>.toOrtComponents( | ||
| poms: Map<String, ModelBuildingResult>, | ||
| visited: Set<ComponentIdentifier> | ||
| ): List<OrtDependency> = | ||
| ): List<OrtComponent> = | ||
| if (GradleVersion.current() < GradleVersion.version("5.1")) { | ||
| this | ||
| } else { | ||
| filterNot { it.isConstraint } | ||
| }.mapNotNull { | ||
| it.toOrtDependency(poms, visited) | ||
| it.toOrtComponent(poms, visited) | ||
| } | ||
|
|
||
| private fun DependencyResult.toOrtDependency( | ||
| private fun DependencyResult.toOrtComponent( | ||
| poms: Map<String, ModelBuildingResult>, | ||
| visited: Set<ComponentIdentifier> | ||
| ): OrtDependency? { | ||
| ): OrtComponent? { | ||
| if (this is UnresolvedDependencyResult) { | ||
| if (attempted is ProjectComponentSelector) { | ||
| // Ignore unresolved project dependencies. For example for complex Android projects, Gradle's | ||
|
|
@@ -199,8 +158,8 @@ internal class OrtModelBuilder : ToolingModelBuilder { | |
| // Cut the graph on cyclic dependencies. | ||
| if (id in visited) return null | ||
|
|
||
| if (selected in ortDependencyCache) { | ||
| return ortDependencyCache[selected] | ||
| if (selected in ortComponentCache) { | ||
| return ortComponentCache[selected] | ||
| } | ||
|
|
||
| if (id is ModuleComponentIdentifier) { | ||
|
|
@@ -215,13 +174,11 @@ internal class OrtModelBuilder : ToolingModelBuilder { | |
|
|
||
| // Check if we have scanned the dependencies of this subtree before, and if so, reuse them. | ||
| val dependencies = globalDependencySubtrees.getOrPut(id.displayName) { | ||
| selected.dependencies.toOrtDependencies(poms, visited + id) | ||
| selected.dependencies.toOrtComponents(poms, visited + id) | ||
| } | ||
|
|
||
| return OrtDependencyImpl( | ||
| groupId = id.group, | ||
| artifactId = id.module, | ||
| version = id.version, | ||
| return OrtComponentImpl( | ||
| componentId = OrtComponentIdentifierImpl(id.group, id.module, id.version), | ||
| classifier = "", | ||
| extension = modelBuildingResult?.effectiveModel?.packaging.orEmpty(), | ||
| variants = selected.variants.associate { | ||
|
|
@@ -244,18 +201,20 @@ internal class OrtModelBuilder : ToolingModelBuilder { | |
| }, | ||
| localPath = null | ||
| ).also { | ||
| ortDependencyCache[selected] = it | ||
| ortComponentCache[selected] = it | ||
| } | ||
| } | ||
|
|
||
| if (id is ProjectComponentIdentifier) { | ||
| val moduleId = selected.moduleVersion ?: return null | ||
| val dependencies = selected.dependencies.toOrtDependencies(poms, visited + id) | ||
|
|
||
| return OrtDependencyImpl( | ||
| groupId = moduleId.group, | ||
| artifactId = moduleId.name, | ||
| version = moduleId.version.takeUnless { it == "unspecified" }.orEmpty(), | ||
| val dependencies = selected.dependencies.toOrtComponents(poms, visited + id) | ||
|
|
||
| return OrtComponentImpl( | ||
| componentId = OrtComponentIdentifierImpl( | ||
| groupId = moduleId.group, | ||
| artifactId = moduleId.name, | ||
| version = moduleId.version.takeUnless { it == "unspecified" }.orEmpty() | ||
| ), | ||
| classifier = "", | ||
| extension = "", | ||
| variants = selected.variants.associate { | ||
|
|
@@ -270,7 +229,7 @@ internal class OrtModelBuilder : ToolingModelBuilder { | |
| mavenModel = null, | ||
| localPath = id.projectPath | ||
| ).also { | ||
| ortDependencyCache[selected] = it | ||
| ortComponentCache[selected] = it | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -316,6 +275,44 @@ internal class OrtModelBuilder : ToolingModelBuilder { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Resolve the POM files for all dependences in the given [Gradle configuration][config] incl. their parent POMs. | ||
| */ | ||
| private fun Project.resolvePoms(config: Configuration): Map<String, ModelBuildingResult> { | ||
| val allComponentIds = config.incoming.resolutionResult.allComponents.map { it.id } | ||
|
sschuberth marked this conversation as resolved.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Commit message nit: You don't refer to [1] currently, but should do so after " |
||
|
|
||
| // Get the POM files for all resolved dependencies. | ||
| val pomFiles = resolvePoms(allComponentIds) | ||
|
|
||
| val fileModelBuilder = FileModelBuilder { groupId, artifactId, version -> | ||
| val moduleId = DefaultModuleIdentifier.newId(groupId, artifactId) | ||
| val componentId = DefaultModuleComponentIdentifier.newId(moduleId, version) | ||
|
|
||
| val pomFile = resolvePoms(listOf(componentId)).single().file | ||
|
|
||
| FileModelSource(pomFile) | ||
| } | ||
|
|
||
| return pomFiles.associate { | ||
| // Trigger resolution of parent POMs by building the POM model. | ||
| it.id.componentIdentifier.toString() to fileModelBuilder.buildModel(it.file) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Resolve the POM files for the given [componentIds] and return them. | ||
| */ | ||
| private fun Project.resolvePoms(componentIds: List<ComponentIdentifier>): List<ResolvedArtifactResult> { | ||
| val resolutionResult = dependencies.createArtifactResolutionQuery() | ||
| .forComponents(componentIds.distinct()) | ||
| .withArtifacts(MavenModule::class.java, MavenPomArtifact::class.java) | ||
| .execute() | ||
|
|
||
| return resolutionResult.resolvedComponents.flatMap { | ||
| it.getArtifacts(MavenPomArtifact::class.java) | ||
| }.filterIsInstance<ResolvedArtifactResult>() | ||
| } | ||
|
|
||
| /** | ||
| * Add a string with information about the causes of the given [exception] to this [StringBuilder]. This is used to | ||
| * log the reason why a dependency could not be resolved. To get meaningful information, all causes need to be obtained | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,8 +19,9 @@ | |
|
|
||
| package org.ossreviewtoolkit.plugins.packagemanagers.gradleplugin | ||
|
|
||
| import OrtComponent | ||
| import OrtComponentIdentifier | ||
| import OrtConfiguration | ||
| import OrtDependency | ||
| import OrtDependencyTreeModel | ||
| import OrtMavenModel | ||
| import OrtRepository | ||
|
|
@@ -42,24 +43,29 @@ internal class OrtDependencyTreeModelImpl( | |
| @Suppress("SerialVersionUIDInSerializableClass") | ||
| internal class OrtConfigurationImpl( | ||
| override val name: String, | ||
| override val dependencies: List<OrtDependency> | ||
| override val dependencies: List<OrtComponent> | ||
| ) : OrtConfiguration, Serializable | ||
|
|
||
| @Suppress("LongParameterList", "SerialVersionUIDInSerializableClass") | ||
| internal class OrtDependencyImpl( | ||
| internal class OrtComponentIdentifierImpl( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does |
||
| override val groupId: String, | ||
| override val artifactId: String, | ||
| override val version: String, | ||
| override val version: String | ||
| ) : OrtComponentIdentifier, Serializable | ||
|
|
||
| @Suppress("LongParameterList", "SerialVersionUIDInSerializableClass") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also this became shorter now, but I guess |
||
| internal class OrtComponentImpl( | ||
| override val componentId: OrtComponentIdentifier, | ||
| override val classifier: String, | ||
| override val extension: String, | ||
| override val variants: Map<String, Map<String, String>>, | ||
| override val dependencies: List<OrtDependency>, | ||
| override val dependencies: List<OrtComponent>, | ||
| override val error: String?, | ||
| override val warning: String?, | ||
| override val pomFile: String?, | ||
| override val mavenModel: OrtMavenModel?, | ||
| override val localPath: String? | ||
| ) : OrtDependency, Serializable | ||
| ) : OrtComponent, Serializable | ||
|
|
||
| @Suppress("SerialVersionUIDInSerializableClass") | ||
| internal class OrtMavenModelImpl( | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.