Skip to content

Commit

Permalink
fix(cargo): Treat projects outside the analyzer root as packages
Browse files Browse the repository at this point in the history
E.g. when analyzing a single Cargo project in a sub-directory with a
`cargo.toml` file that points to "path dependencies" in a parent
directory, these dependencies should not be seen as projects but as
packages. This restores the behavior from before 7522a0c.

Resolves #8571.

Signed-off-by: Sebastian Schuberth <[email protected]>
  • Loading branch information
sschuberth committed Apr 26, 2024
1 parent d7ae28e commit 4dd1612
Showing 1 changed file with 24 additions and 4 deletions.
28 changes: 24 additions & 4 deletions plugins/package-managers/cargo/src/main/kotlin/Cargo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class Cargo(
val pkg = packageById.getValue(node.id)
PackageReference(
id = Identifier("Crate", "", pkg.name, pkg.version),
linkage = if (pkg.isProject()) PackageLinkage.PROJECT_STATIC else PackageLinkage.STATIC,
linkage = if (pkg.isProject(analysisRoot)) PackageLinkage.PROJECT_STATIC else PackageLinkage.STATIC,
dependencies = dependencyNodes.toPackageReferences()
)
}
Expand Down Expand Up @@ -191,14 +191,30 @@ class Cargo(
)

val nonProjectPackages = packageById.values.mapNotNullTo(mutableSetOf()) { cargoPkg ->
cargoPkg.takeUnless { it.isProject() }?.toPackage(hashes)
cargoPkg.takeUnless { it.isProject(analysisRoot) }?.toPackage(hashes)
}

return listOf(ProjectAnalyzerResult(project, nonProjectPackages))
}
}

private fun CargoMetadata.Package.isProject() = source == null
/**
* Return the local path for this Cargo package if applicable, or null if the Cargo package is not local.
*/
private fun CargoMetadata.Package.getLocalPath(): File? =
id.substringAfter("path+file://", "").ifEmpty { null }
?.removeSuffix(")")?.substringBefore("#")?.let { File(it) }

/**
* Return whether this Cargo package is supposed to be regarded as an ORT project. The [analysisRoot] is used to check
* whether this Cargo package lives within the analyzer root.
*/
private fun CargoMetadata.Package.isProject(analysisRoot: File): Boolean {
val isWithinAnalyzerRoot = getLocalPath()?.startsWith(analysisRoot.absoluteFile) == true

// If a package cannot be retrieved from anywhere but lies within the analyzer root, treat it as a project.
return source == null && isWithinAnalyzerRoot
}

private fun CargoMetadata.Package.toPackage(hashes: Map<String, String>): Package {
val declaredLicenses = parseDeclaredLicenses()
Expand All @@ -209,6 +225,9 @@ private fun CargoMetadata.Package.toPackage(hashes: Map<String, String>): Packag
// https://github.com/rust-lang/cargo/pull/4920
val declaredLicensesProcessed = DeclaredLicenseProcessor.process(declaredLicenses, operator = SpdxOperator.OR)

val vcs = repository?.let { VcsHost.parseUrl(it) }.orEmpty()
val vcsProcessed = getLocalPath()?.let { PackageManager.processProjectVcs(it) } ?: vcs.normalize()

return Package(
id = Identifier(
type = "Crate",
Expand All @@ -225,7 +244,8 @@ private fun CargoMetadata.Package.toPackage(hashes: Map<String, String>): Packag
binaryArtifact = RemoteArtifact.EMPTY,
sourceArtifact = parseSourceArtifact(hashes).orEmpty(),
homepageUrl = homepage.orEmpty(),
vcs = repository?.let { VcsHost.parseUrl(it) }.orEmpty()
vcs = vcs,
vcsProcessed = vcsProcessed
)
}

Expand Down

0 comments on commit 4dd1612

Please sign in to comment.