Skip to content

Commit b0e5504

Browse files
committed
feat(fossid): Improve PURL mapping
When a snippet has no artifact name and if it contains a GitHub URL, map instead the URL to a PURL with "GitHub" type. Also, if a snippet has no artifact name, fallback to a PURL with "Generic" type. Signed-off-by: Nicolas Nobelis <nicolas.nobelis@bosch.com>
1 parent ee1308a commit b0e5504

2 files changed

Lines changed: 77 additions & 9 deletions

File tree

plugins/scanners/fossid/src/main/kotlin/Utils.kt

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import org.apache.logging.log4j.kotlin.loggerOf
2828
import org.ossreviewtoolkit.clients.fossid.model.result.Snippet
2929
import org.ossreviewtoolkit.clients.fossid.model.rules.IgnoreRule
3030
import org.ossreviewtoolkit.clients.fossid.model.rules.RuleType
31+
import org.ossreviewtoolkit.downloader.VcsHost
3132
import org.ossreviewtoolkit.model.Issue
3233
import org.ossreviewtoolkit.model.PackageProvider
3334
import org.ossreviewtoolkit.model.Severity
@@ -150,17 +151,37 @@ private fun urlToPackageType(url: String): String =
150151
}
151152
}
152153

153-
internal fun Snippet.toPurl(url: String): String =
154-
when {
155-
purl != null -> checkNotNull(purl)
156-
157-
artifact.isNullOrEmpty() -> ""
154+
internal fun Snippet.toPurl(url: String): String {
155+
purl?.also { return it }
156+
157+
if (artifact.isNullOrEmpty()) {
158+
val vcsHost = VcsHost.fromUrl(url)
159+
if (vcsHost != null) {
160+
val orga = vcsHost.getUserOrOrganization(url)
161+
val repo = vcsHost.getProject(url)
162+
163+
if (orga != null && repo != null) {
164+
return PackageURLBuilder.aPackageURL().withType("github")
165+
.withNamespace(orga)
166+
.withName(repo)
167+
.withVersion(version)
168+
.build()
169+
.canonicalize()
170+
}
171+
}
158172

159-
else -> PackageURLBuilder.aPackageURL()
160-
.withType(urlToPackageType(url))
173+
return PackageURLBuilder.aPackageURL().withType("generic")
161174
.withNamespace(author)
162-
.withName(artifact)
175+
.withName(url)
163176
.withVersion(version)
164177
.build()
165178
.canonicalize()
166179
}
180+
181+
return PackageURLBuilder.aPackageURL().withType(urlToPackageType(url))
182+
.withNamespace(author)
183+
.withName(artifact)
184+
.withVersion(version)
185+
.build()
186+
.canonicalize()
187+
}

plugins/scanners/fossid/src/test/kotlin/FossIdSnippetMappingTest.kt

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,54 @@ class FossIdSnippetMappingTest : WordSpec({
170170
with(finding.snippets) {
171171
this shouldHaveSize 2
172172
first().purl shouldBe "pkg:maven/com/vdurmont/semver4j@3.1.0"
173-
last().purl shouldBe ""
173+
last().purl shouldBe "pkg:generic/com/vdurmont/https%3A%2F%2Frepo1.maven.org%2Fmaven2%2Fcom%2F" +
174+
"vdurmont%2Fsemver4j%2F3.1.0%2F@3.1.0"
175+
}
176+
}
177+
}
178+
179+
"map github url to purl" {
180+
val issues = mutableListOf<Issue>()
181+
val listSnippets = flowOf(
182+
"src/main/java/Tokenizer.java" to
183+
setOf(
184+
createSnippet(
185+
2,
186+
MatchType.FULL,
187+
"pkg:maven/com.vdurmont/semver4j@3.1.0",
188+
"MIT",
189+
"com/vdurmont/semver4j/Tokenizer.java"
190+
).copy(
191+
author = "com/vdurmont",
192+
artifact = null,
193+
version = "3.1.0",
194+
url = "https://github.com/MartinPulec/UltraGrid/archive/refs/heads/devel.tar.gz",
195+
purl = null
196+
)
197+
)
198+
)
199+
val rawResults = RawResults(
200+
emptyList(),
201+
emptyList(),
202+
emptyList(),
203+
emptyList(),
204+
listSnippets,
205+
emptyMap()
206+
)
207+
208+
val mappedSnippets = mapSnippetFindings(
209+
rawResults,
210+
500,
211+
issues,
212+
emptyMap(),
213+
emptyList(),
214+
mutableSetOf()
215+
)
216+
217+
issues should beEmpty()
218+
mappedSnippets.shouldBeSingleton { finding ->
219+
finding.snippets.shouldBeSingleton { snippet ->
220+
snippet.purl shouldBe "pkg:github/martinpulec/ultragrid@3.1.0"
174221
}
175222
}
176223
}

0 commit comments

Comments
 (0)