Skip to content

Commit

Permalink
Analyzer: Pass the labels to the resolveDependencies functions
Browse files Browse the repository at this point in the history
This allows implementing a dependency resolution logic depending on the
labels given as parameters to the AnalyzerCommand. This is useful, for
instance, for custom analyzer plugins.

Signed-off-by: Nicolas Nobelis <nicolas.nobelis@bosch.io>
  • Loading branch information
nnobelis authored and sschuberth committed Nov 5, 2021
1 parent b2f5e15 commit 9ebfa9c
Show file tree
Hide file tree
Showing 29 changed files with 58 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ abstract class AbstractIntegrationSpec : StringSpec() {
managedFilesForTest.entries.forAll { (manager, files) ->
println("Resolving $manager dependencies in $files.")
val results = manager.create(USER_DIR, DEFAULT_ANALYZER_CONFIGURATION, DEFAULT_REPOSITORY_CONFIGURATION)
.resolveDependencies(files)
.resolveDependencies(files, emptyMap())

results.projectResults.size shouldBe files.size
results.projectResults.values.flatten().forAll { result ->
Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/funTest/kotlin/managers/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import org.ossreviewtoolkit.model.yamlMapper
fun Any?.toYaml() = yamlMapper.writeValueAsString(this)!!

fun PackageManager.resolveSingleProject(definitionFile: File, resolveScopes: Boolean = false): ProjectAnalyzerResult {
val managerResult = resolveDependencies(listOf(definitionFile))
val managerResult = resolveDependencies(listOf(definitionFile), emptyMap())

return managerResult.projectResults[definitionFile].let { resultList ->
resultList.shouldNotBeNull()
Expand Down
4 changes: 2 additions & 2 deletions analyzer/src/funTest/kotlin/managers/MavenFunTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class MavenFunTest : StringSpec() {
// jgnash-core depends on jgnash-resources, so we also have to pass the pom.xml of jgnash-resources to
// resolveDependencies so that it is available in the Maven.projectsByIdentifier cache. Otherwise resolution
// of transitive dependencies would not work.
val managerResult = createMaven().resolveDependencies(listOf(pomFileCore, pomFileResources))
val managerResult = createMaven().resolveDependencies(listOf(pomFileCore, pomFileResources), emptyMap())
val result = managerResult.projectResults[pomFileCore]

result.shouldNotBeNull()
Expand Down Expand Up @@ -98,7 +98,7 @@ class MavenFunTest : StringSpec() {
// app depends on lib, so we also have to pass the pom.xml of lib to resolveDependencies so that it is
// available in the Maven.projectsByIdentifier cache. Otherwise resolution of transitive dependencies would
// not work.
val managerResult = createMaven().resolveDependencies(listOf(pomFileApp, pomFileLib))
val managerResult = createMaven().resolveDependencies(listOf(pomFileApp, pomFileLib), emptyMap())
val result = managerResult.projectResults[pomFileApp]

result.shouldNotBeNull()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class SpdxDocumentFileFunTest : WordSpec({
val packageFileZlib = projectDir.resolve("package/libs/zlib/package.spdx.yml")

val definitionFiles = listOf(packageFileCurl, packageFileZlib)
val actualResult = createSpdxDocumentFile().resolveDependencies(definitionFiles)
val actualResult = createSpdxDocumentFile().resolveDependencies(definitionFiles, emptyMap())
// Extract only ProjectAnalyzerResults to avoid depending on other analyzer result specific items (e.g.
// the dependency graph).
.projectResults.values.flatten().sortedBy { it.project.id }
Expand Down
4 changes: 2 additions & 2 deletions analyzer/src/main/kotlin/Analyzer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import org.ossreviewtoolkit.utils.core.log
/**
* The class to run the analysis. The signatures of public functions in this class define the library API.
*/
class Analyzer(private val config: AnalyzerConfiguration) {
class Analyzer(private val config: AnalyzerConfiguration, private val labels: Map<String, String> = emptyMap()) {
data class ManagedFileInfo(
val absoluteProjectPath: File,
val managedFiles: Map<PackageManager, List<File>>,
Expand Down Expand Up @@ -129,7 +129,7 @@ class Analyzer(private val config: AnalyzerConfiguration) {
runBlocking(Dispatchers.IO) {
managedFiles.map { (manager, files) ->
async {
val results = manager.resolveDependencies(files)
val results = manager.resolveDependencies(files, labels)

// By convention, project ids must be of the type of the respective package manager.
results.projectResults.forEach { (_, result) ->
Expand Down
10 changes: 7 additions & 3 deletions analyzer/src/main/kotlin/PackageManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,10 @@ abstract class PackageManager(
* Return a tree of resolved dependencies (not necessarily declared dependencies, in case conflicts were resolved)
* for all [definitionFiles] which were found by searching the [analysisRoot] directory. By convention, the
* [definitionFiles] must be absolute.
* [labels] are the labels given as parameters to the [org.ossreviewtoolkit.cli.commands.AnalyzerCommand]. They can
* be used by package manager implementations to decide how dependencies are resolved.
*/
open fun resolveDependencies(definitionFiles: List<File>): PackageManagerResult {
open fun resolveDependencies(definitionFiles: List<File>, labels: Map<String, String>): PackageManagerResult {
definitionFiles.forEach { definitionFile ->
requireNotNull(definitionFile.relativeToOrNull(analysisRoot)) {
"'$definitionFile' must be an absolute path below '$analysisRoot'."
Expand All @@ -238,7 +240,7 @@ abstract class PackageManager(
val duration = measureTime {
@Suppress("TooGenericExceptionCaught")
try {
result[definitionFile] = resolveDependencies(definitionFile)
result[definitionFile] = resolveDependencies(definitionFile, labels)
} catch (e: Exception) {
e.showStackTrace()

Expand Down Expand Up @@ -280,8 +282,10 @@ abstract class PackageManager(
/**
* Resolve dependencies for a single absolute [definitionFile] and return a list of [ProjectAnalyzerResult]s, with
* one result for each project found in the definition file.
* [labels] are the labels given as parameters to the [org.ossreviewtoolkit.cli.commands.AnalyzerCommand]. They can
* be used by package manager implementations to decide how dependencies are resolved.
*/
abstract fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult>
abstract fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult>

protected fun requireLockfile(workingDir: File, condition: () -> Boolean) {
require(analyzerConfig.allowDynamicVersions || condition()) {
Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/Bower.kt
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ class Bower(

override fun beforeResolution(definitionFiles: List<File>) = checkVersion(analyzerConfig.ignoreToolVersions)

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
val workingDir = definitionFile.parentFile

stashDirectories(workingDir.resolve("bower_components")).use {
Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/Bundler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class Bundler(
}
}

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
val workingDir = definitionFile.parentFile
requireLockfile(workingDir) { workingDir.resolve("Gemfile.lock").isFile }

Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/Cargo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class Cargo(
return pkg.toReference(linkage, dependencies)
}

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
// Get the project name and version. If one of them is missing return null, because this is a workspace
// definition file that does not contain a project.
val pkgDefinition = Toml().read(definitionFile)
Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/Carthage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class Carthage(
) = Carthage(managerName, analysisRoot, analyzerConfig, repoConfig)
}

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
// Transitive dependencies are only supported if the dependency itself uses Carthage.
// See: https://github.com/Carthage/Carthage#nested-dependencies
val workingDir = definitionFile.parentFile
Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/CocoaPods.kt
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class CocoaPods(

override fun beforeResolution(definitionFiles: List<File>) = checkVersion(analyzerConfig.ignoreToolVersions)

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
// CocoaPods originally used and may still use the Specs repository on GitHub [1] as package metadata database.
// Using [1] requires an initial clone which is slow to do and consumes already more than 5 GB on disk, see
// also [2]. (Final) CDN support has been added in version 1.7.2 [3] to speed things up.
Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/Composer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ class Composer(
checkVersion(analyzerConfig.ignoreToolVersions)
}

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
val workingDir = definitionFile.parentFile

stashDirectories(workingDir.resolve("vendor")).use {
Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/Conan.kt
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class Conan(
/**
* Primary method for resolving dependencies from [definitionFile].
*/
override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> =
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> =
try {
resolvedDependenciesInternal(definitionFile)
} finally {
Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/DotNet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class DotNet(

private val reader = DotNetPackageFileReader()

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> =
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> =
listOf(resolveNuGetDependencies(definitionFile, reader, NuGetSupport.create(definitionFile)))
}

Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/GoDep.kt
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class GoDep(
override fun transformVersion(output: String) =
output.lineSequence().first { it.contains("version") }.substringAfter(':').trim().removePrefix("v")

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
val projectDir = resolveProjectRoot(definitionFile)
val projectVcs = processProjectVcs(projectDir)
val gopath = createTempDirectory("$ORT_NAME-${projectDir.name}-gopath").toFile()
Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/GoMod.kt
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class GoMod(
.contains("vendor")
}

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
val projectDir = definitionFile.parentFile

stashDirectories(projectDir.resolve("vendor")).use {
Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/Gradle.kt
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class Gradle(
override fun createPackageManagerResult(projectResults: Map<File, List<ProjectAnalyzerResult>>) =
PackageManagerResult(projectResults, graphBuilder.build(), graphBuilder.packages())

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
val gradleSystemProperties = mutableListOf<Pair<String, String>>()
val gradleProperties = mutableListOf<Pair<String, String>>()

Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/Maven.kt
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class Maven(
override fun createPackageManagerResult(projectResults: Map<File, List<ProjectAnalyzerResult>>) =
PackageManagerResult(projectResults, graphBuilder.build(), graphBuilder.packages())

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
val workingDir = definitionFile.parentFile
val projectBuildingResult = mvn.buildMavenProject(definitionFile)
val mavenProject = projectBuildingResult.project
Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/Npm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ open class Npm(
override fun createPackageManagerResult(projectResults: Map<File, List<ProjectAnalyzerResult>>) =
PackageManagerResult(projectResults, graphBuilder.build(), graphBuilder.packages())

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
val workingDir = definitionFile.parentFile

stashDirectories(workingDir.resolve("node_modules")).use {
Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/NuGet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class NuGet(

private val reader = NuGetPackageFileReader()

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> =
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> =
listOf(resolveNuGetDependencies(definitionFile, reader, NuGetSupport.create(definitionFile)))
}

Expand Down
2 changes: 1 addition & 1 deletion analyzer/src/main/kotlin/managers/Pip.kt
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ class Pip(
VirtualEnv.checkVersion(analyzerConfig.ignoreToolVersions)

@Suppress("LongMethod")
override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
// For an overview, dependency resolution involves the following steps:
// 1. Install dependencies via pip (inside a virtualenv, for isolation from globally installed packages).
// 2. Get metadata about the local project via pydep (only for setup.py-based projects).
Expand Down
4 changes: 2 additions & 2 deletions analyzer/src/main/kotlin/managers/Pipenv.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class Pipenv(

override fun beforeResolution(definitionFiles: List<File>) = checkVersion(analyzerConfig.ignoreToolVersions)

override fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
// For an overview, dependency resolution involves the following steps:
// 1. Generate "requirements.txt" file with `pipenv` command
// 2. Use existing "Pip" PackageManager to do the actual dependency resolution
Expand All @@ -74,7 +74,7 @@ class Pipenv(
.copyTo(requirementsFile)

return Pip(managerName, analysisRoot, analyzerConfig, repoConfig)
.resolveDependencies(requirementsFile)
.resolveDependencies(requirementsFile, labels)
.also { requirementsFile.delete() }
}
}
Loading

0 comments on commit 9ebfa9c

Please sign in to comment.