Skip to content

Commit 5f67c4e

Browse files
wkl3nkmnonnenmacher
authored andcommitted
refactor(scanner): Extract VCSPath filtering functions
Scanners generally do not consider the VCSPath when performing an ORT scan on a repository, as they scan the entire repository and its dependencies. The resulting scan data is cached for reuse across multiple scans. When reusing cached scan results for ORT scans with a specified VCSPath, where only a subset of the repository is scanned, it is necessary to filter out extraneous scan results. Helper functions already exist to handle this filtering. This refactoring extracts these helper functions and allows ORT Server to use them. See: eclipse-apoapsis/ort-server#1358 Signed-off-by: Wolfgang Klenk <[email protected]>
1 parent b724b62 commit 5f67c4e

File tree

2 files changed

+65
-44
lines changed

2 files changed

+65
-44
lines changed

scanner/src/main/kotlin/Scanner.kt

+6-44
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ import org.ossreviewtoolkit.model.KnownProvenance
3939
import org.ossreviewtoolkit.model.OrtResult
4040
import org.ossreviewtoolkit.model.Package
4141
import org.ossreviewtoolkit.model.PackageType
42-
import org.ossreviewtoolkit.model.Provenance
4342
import org.ossreviewtoolkit.model.ProvenanceResolutionResult
44-
import org.ossreviewtoolkit.model.RepositoryProvenance
4543
import org.ossreviewtoolkit.model.ScanResult
4644
import org.ossreviewtoolkit.model.ScanSummary
4745
import org.ossreviewtoolkit.model.ScannerRun
@@ -54,14 +52,16 @@ import org.ossreviewtoolkit.model.createAndLogIssue
5452
import org.ossreviewtoolkit.model.mapLicense
5553
import org.ossreviewtoolkit.model.utils.FileArchiver
5654
import org.ossreviewtoolkit.model.utils.ProvenanceFileStorage
57-
import org.ossreviewtoolkit.model.utils.getKnownProvenancesWithoutVcsPath
5855
import org.ossreviewtoolkit.model.utils.vcsPath
5956
import org.ossreviewtoolkit.scanner.provenance.NestedProvenance
6057
import org.ossreviewtoolkit.scanner.provenance.NestedProvenanceResolver
6158
import org.ossreviewtoolkit.scanner.provenance.NestedProvenanceScanResult
6259
import org.ossreviewtoolkit.scanner.provenance.PackageProvenanceResolver
6360
import org.ossreviewtoolkit.scanner.provenance.ProvenanceDownloader
6461
import org.ossreviewtoolkit.scanner.utils.FileListResolver
62+
import org.ossreviewtoolkit.scanner.utils.alignRevisions
63+
import org.ossreviewtoolkit.scanner.utils.filterScanResultsByVcsPaths
64+
import org.ossreviewtoolkit.scanner.utils.getVcsPathsForProvenances
6565
import org.ossreviewtoolkit.utils.common.CommandLineTool
6666
import org.ossreviewtoolkit.utils.common.collectMessages
6767
import org.ossreviewtoolkit.utils.common.safeDeleteRecursively
@@ -190,25 +190,9 @@ class Scanner(
190190
).filterByVcsPath()
191191
}
192192

193-
val vcsPathsForProvenances = buildMap<KnownProvenance, MutableSet<String>> {
194-
provenances.forEach { provenance ->
195-
val packageVcsPath = provenance.packageProvenance?.vcsPath.orEmpty()
193+
val vcsPathsForProvenances = getVcsPathsForProvenances(provenances)
196194

197-
provenance.getKnownProvenancesWithoutVcsPath().forEach { (repositoryPath, provenance) ->
198-
getVcsPathForRepositoryOrNull(packageVcsPath, repositoryPath)?.let { vcsPath ->
199-
getOrPut(provenance) { mutableSetOf() } += vcsPath
200-
}
201-
}
202-
}
203-
}
204-
205-
val scanResults = controller.getAllScanResults().map { scanResult ->
206-
scanResult.copy(provenance = scanResult.provenance.alignRevisions())
207-
}.mapNotNullTo(mutableSetOf()) { scanResult ->
208-
vcsPathsForProvenances[scanResult.provenance]?.let {
209-
scanResult.copy(summary = scanResult.summary.filterByPaths(it))
210-
}
211-
}
195+
val filteredScanResults = filterScanResultsByVcsPaths(controller.getAllScanResults(), vcsPathsForProvenances)
212196

213197
val files = controller.getAllFileLists().mapTo(mutableSetOf()) { (provenance, fileList) ->
214198
FileList(
@@ -229,7 +213,7 @@ class Scanner(
229213
return ScannerRun.EMPTY.copy(
230214
config = scannerConfig,
231215
provenances = provenances,
232-
scanResults = scanResults,
216+
scanResults = filteredScanResults,
233217
files = files,
234218
scanners = scanners
235219
)
@@ -782,13 +766,6 @@ fun ScanResult.toNestedProvenanceScanResult(nestedProvenance: NestedProvenance):
782766
return NestedProvenanceScanResult(nestedProvenance, scanResultsByProvenance)
783767
}
784768

785-
fun <T : Provenance> T.alignRevisions(): Provenance =
786-
if (this is RepositoryProvenance) {
787-
copy(vcsInfo = vcsInfo.copy(revision = resolvedRevision))
788-
} else {
789-
this
790-
}
791-
792769
private fun ScanController.getSubRepositories(id: Identifier): Map<String, VcsInfo> {
793770
val nestedProvenance = getNestedProvenance(id) ?: return emptyMap()
794771

@@ -802,21 +779,6 @@ private fun ProvenanceResolutionResult.filterByVcsPath(): ProvenanceResolutionRe
802779
}
803780
)
804781

805-
/**
806-
* Return the VCS path applicable to a (sub-) repository which appears under [repositoryPath] in the source tree of
807-
* a package residing in [vcsPath], or null if the subtrees for [repositoryPath] and [vcsPath] are disjoint.
808-
*/
809-
private fun getVcsPathForRepositoryOrNull(vcsPath: String, repositoryPath: String): String? {
810-
val repoPathFile = File(repositoryPath)
811-
val vcsPathFile = File(vcsPath)
812-
813-
return if (repoPathFile.startsWith(vcsPathFile)) {
814-
""
815-
} else {
816-
runCatching { vcsPathFile.toRelativeString(repoPathFile) }.getOrNull()
817-
}
818-
}
819-
820782
private fun FileList.filterByVcsPaths(paths: Collection<String>): FileList =
821783
if (paths.any { it.isBlank() }) {
822784
this

scanner/src/main/kotlin/utils/Utils.kt

+59
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,15 @@
1919

2020
package org.ossreviewtoolkit.scanner.utils
2121

22+
import java.io.File
23+
24+
import org.ossreviewtoolkit.model.KnownProvenance
2225
import org.ossreviewtoolkit.model.Provenance
26+
import org.ossreviewtoolkit.model.ProvenanceResolutionResult
2327
import org.ossreviewtoolkit.model.RepositoryProvenance
28+
import org.ossreviewtoolkit.model.ScanResult
29+
import org.ossreviewtoolkit.model.utils.getKnownProvenancesWithoutVcsPath
30+
import org.ossreviewtoolkit.model.utils.vcsPath
2431
import org.ossreviewtoolkit.scanner.ScanStorageException
2532

2633
/**
@@ -31,3 +38,55 @@ internal fun requireEmptyVcsPath(provenance: Provenance) {
3138
throw ScanStorageException("Repository provenances with a non-empty VCS path are not supported.")
3239
}
3340
}
41+
42+
/**
43+
* Return a map of VCS paths for each [KnownProvenance] contained in [provenances].
44+
*/
45+
fun getVcsPathsForProvenances(provenances: Set<ProvenanceResolutionResult>) =
46+
buildMap<KnownProvenance, MutableSet<String>> {
47+
provenances.forEach { provenance ->
48+
val packageVcsPath = provenance.packageProvenance?.vcsPath.orEmpty()
49+
50+
provenance.getKnownProvenancesWithoutVcsPath().forEach { (repositoryPath, provenance) ->
51+
getVcsPathForRepositoryOrNull(packageVcsPath, repositoryPath)?.let { vcsPath ->
52+
getOrPut(provenance) { mutableSetOf() } += vcsPath
53+
}
54+
}
55+
}
56+
}
57+
58+
/**
59+
* Filter [ScanResult]s by the VCS paths of the [KnownProvenance]s contained in [vcsPathsForProvenances].
60+
*/
61+
fun filterScanResultsByVcsPaths(
62+
allScanResults: List<ScanResult>,
63+
vcsPathsForProvenances: Map<KnownProvenance, MutableSet<String>>
64+
) = allScanResults.map { scanResult ->
65+
scanResult.copy(provenance = scanResult.provenance.alignRevisions())
66+
}.mapNotNullTo(mutableSetOf()) { scanResult ->
67+
vcsPathsForProvenances[scanResult.provenance]?.let {
68+
scanResult.copy(summary = scanResult.summary.filterByPaths(it))
69+
}
70+
}
71+
72+
/**
73+
* Return the VCS path applicable to a (sub-) repository which appears under [repositoryPath] in the source tree of
74+
* a package residing in [vcsPath], or null if the subtrees for [repositoryPath] and [vcsPath] are disjoint.
75+
*/
76+
private fun getVcsPathForRepositoryOrNull(vcsPath: String, repositoryPath: String): String? {
77+
val repoPathFile = File(repositoryPath)
78+
val vcsPathFile = File(vcsPath)
79+
80+
return if (repoPathFile.startsWith(vcsPathFile)) {
81+
""
82+
} else {
83+
runCatching { vcsPathFile.toRelativeString(repoPathFile) }.getOrNull()
84+
}
85+
}
86+
87+
internal fun <T : Provenance> T.alignRevisions(): Provenance =
88+
if (this is RepositoryProvenance) {
89+
copy(vcsInfo = vcsInfo.copy(revision = resolvedRevision))
90+
} else {
91+
this
92+
}

0 commit comments

Comments
 (0)