Skip to content

Commit 9ffd2c5

Browse files
committed
feat(Provenance): Add DirectoryProvenance as a LocalProvenance
In contrast to the previously added `RemoteProvenance` stands the `LocalProvenance`, which has no remote source, but instead references a local input of some kind. The `DirectoryProvenance` references a local project directory, which is lacking supported (remote) version control. It is defined by its local directory path only. Since ORT needs further refactoring until `DirectoryProvenance` can be fully utilized, it the new class can not be used right now. However the presence of a new `KnownProvenance` class, results in `when` conditional cases not being exhaustive anymore. To circumvent this issue, the following changes were made: 1. Whereever possible `RemoteProvenance` is used as parameter type instead of `KnownProvenance`. 2. When necessary `KnownProvenance`s are cast to `RemoteProvenance`. 3. If `Provenance` is expected, `DirectoryProvenance` is handled like `UnknownProvenance`. The excaption being `hash` and `storageKey`, which both default to an empty string. However, since the rest of the code does not handle `DirectoryProvenance`, this should not become an issue. See [1] for more context on the new Provenance Hierarchy. [1]: #8803 (comment) Signed-off-by: Jens Keim <[email protected]>
1 parent 19da2db commit 9ffd2c5

15 files changed

+64
-22
lines changed

model/src/main/kotlin/Provenance.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize
2626
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
2727
import com.fasterxml.jackson.module.kotlin.treeToValue
2828

29+
import java.nio.file.Files
30+
import java.nio.file.Path
31+
2932
/**
3033
* Provenance information about the origin of source code.
3134
*/
@@ -45,6 +48,8 @@ sealed interface KnownProvenance : Provenance
4548

4649
sealed interface RemoteProvenance : KnownProvenance
4750

51+
sealed interface LocalProvenance : KnownProvenance
52+
4853
/**
4954
* Provenance information for a source artifact.
5055
*/
@@ -83,6 +88,23 @@ data class RepositoryProvenance(
8388
override fun matches(pkg: Package): Boolean = vcsInfo == pkg.vcsProcessed
8489
}
8590

91+
/**
92+
* Provenance information for a local directory path.
93+
*/
94+
data class DirectoryProvenance(
95+
val directoryPath: Path
96+
) : LocalProvenance {
97+
init {
98+
require(Files.exists(directoryPath)) { "The directory path must exist." }
99+
}
100+
101+
/**
102+
* Return true if this provenance's directoryPath matches the package URL of the [package][pkg],
103+
* as it contains the local file path for non-remote Provenances.
104+
*/
105+
override fun matches(pkg: Package): Boolean = directoryPath.toString() == pkg.purl
106+
}
107+
86108
/**
87109
* A custom deserializer for polymorphic deserialization of [Provenance] without requiring type information.
88110
*/

model/src/main/kotlin/ProvenanceResolutionResult.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ data class ProvenanceResolutionResult(
3737
* The resolved provenance of the package. Can only be null if a [packageProvenanceResolutionIssue] occurred.
3838
*/
3939
@JsonInclude(JsonInclude.Include.NON_NULL)
40-
val packageProvenance: KnownProvenance? = null,
40+
val packageProvenance: RemoteProvenance? = null,
4141

4242
/**
4343
* The (recursive) sub-repositories of [packageProvenance]. The map can only be empty if a

model/src/main/kotlin/config/PackageConfiguration.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package org.ossreviewtoolkit.model.config
2222
import com.fasterxml.jackson.annotation.JsonInclude
2323

2424
import org.ossreviewtoolkit.model.ArtifactProvenance
25+
import org.ossreviewtoolkit.model.DirectoryProvenance
2526
import org.ossreviewtoolkit.model.Identifier
2627
import org.ossreviewtoolkit.model.Provenance
2728
import org.ossreviewtoolkit.model.RepositoryProvenance
@@ -84,6 +85,7 @@ data class PackageConfiguration(
8485
is UnknownProvenance -> false
8586
is ArtifactProvenance -> sourceArtifactUrl != null && sourceArtifactUrl == provenance.sourceArtifact.url
8687
is RepositoryProvenance -> vcs != null && vcs.matches(provenance)
88+
is DirectoryProvenance -> false
8789
}
8890
}
8991
}

model/src/main/kotlin/utils/FileProvenanceFileStorage.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import java.io.InputStream
2424
import org.apache.logging.log4j.kotlin.logger
2525

2626
import org.ossreviewtoolkit.model.ArtifactProvenance
27+
import org.ossreviewtoolkit.model.DirectoryProvenance
2728
import org.ossreviewtoolkit.model.HashAlgorithm
2829
import org.ossreviewtoolkit.model.KnownProvenance
2930
import org.ossreviewtoolkit.model.RepositoryProvenance
@@ -81,6 +82,7 @@ private fun KnownProvenance.hash(): String {
8182
val key = when (this) {
8283
is ArtifactProvenance -> "${sourceArtifact.url}${sourceArtifact.hash.value}"
8384
is RepositoryProvenance -> "${vcsInfo.type}${vcsInfo.url}$resolvedRevision"
85+
is DirectoryProvenance -> ""
8486
}
8587

8688
return HashAlgorithm.SHA1.calculate(key.toByteArray())

model/src/main/kotlin/utils/PostgresProvenanceFileStorage.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import org.jetbrains.exposed.sql.insert
3636
import org.jetbrains.exposed.sql.selectAll
3737

3838
import org.ossreviewtoolkit.model.ArtifactProvenance
39+
import org.ossreviewtoolkit.model.DirectoryProvenance
3940
import org.ossreviewtoolkit.model.KnownProvenance
4041
import org.ossreviewtoolkit.model.RepositoryProvenance
4142
import org.ossreviewtoolkit.model.utils.DatabaseUtils.checkDatabaseEncoding
@@ -121,4 +122,5 @@ private fun KnownProvenance.storageKey(): String =
121122
is ArtifactProvenance -> "source-artifact|${sourceArtifact.url}|${sourceArtifact.hash}"
122123
// The trailing "|" is kept for backward compatibility because there used to be an additional parameter.
123124
is RepositoryProvenance -> "vcs|${vcsInfo.type}|${vcsInfo.url}|$resolvedRevision|"
125+
is DirectoryProvenance -> ""
124126
}

model/src/main/kotlin/utils/PurlExtensions.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package org.ossreviewtoolkit.model.utils
2222
import java.net.URLDecoder
2323

2424
import org.ossreviewtoolkit.model.ArtifactProvenance
25+
import org.ossreviewtoolkit.model.DirectoryProvenance
2526
import org.ossreviewtoolkit.model.Hash
2627
import org.ossreviewtoolkit.model.Identifier
2728
import org.ossreviewtoolkit.model.Package
@@ -101,6 +102,8 @@ fun Provenance.toPurlExtras(): PurlExtras =
101102
)
102103
}
103104

105+
is DirectoryProvenance -> PurlExtras()
106+
104107
is UnknownProvenance -> PurlExtras()
105108
}
106109

scanner/src/main/kotlin/ScanController.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import org.ossreviewtoolkit.model.Issue
2424
import org.ossreviewtoolkit.model.KnownProvenance
2525
import org.ossreviewtoolkit.model.Package
2626
import org.ossreviewtoolkit.model.Provenance
27+
import org.ossreviewtoolkit.model.RemoteProvenance
2728
import org.ossreviewtoolkit.model.RepositoryProvenance
2829
import org.ossreviewtoolkit.model.ScanResult
2930
import org.ossreviewtoolkit.model.ScanSummary
@@ -79,7 +80,7 @@ internal class ScanController(
7980
* A map of package [Identifier]s to their resolved [KnownProvenance]s. These provenances are used to filter the
8081
* scan results for a package based on the VCS path.
8182
*/
82-
private val packageProvenances = mutableMapOf<Identifier, KnownProvenance>()
83+
private val packageProvenances = mutableMapOf<Identifier, RemoteProvenance>()
8384

8485
/**
8586
* A map of package [Identifier]s to their resolved [KnownProvenance]s with the VCS path removed. These provenances
@@ -130,7 +131,7 @@ internal class ScanController(
130131
/**
131132
* Set the [provenance] for the package denoted by [id], overwriting any existing values.
132133
*/
133-
fun putPackageProvenance(id: Identifier, provenance: KnownProvenance) {
134+
fun putPackageProvenance(id: Identifier, provenance: RemoteProvenance) {
134135
packageProvenances[id] = provenance
135136
packageProvenancesWithoutVcsPath[id] = when (provenance) {
136137
is RepositoryProvenance -> provenance.copy(vcsInfo = provenance.vcsInfo.copy(path = ""))
@@ -262,7 +263,7 @@ internal class ScanController(
262263
fun getPackagesForProvenanceWithoutVcsPath(provenance: KnownProvenance): Set<Identifier> =
263264
packageProvenancesWithoutVcsPath.filter { (_, packageProvenance) -> packageProvenance == provenance }.keys
264265

265-
fun getPackageProvenance(id: Identifier): KnownProvenance? = packageProvenances[id]
266+
fun getPackageProvenance(id: Identifier): RemoteProvenance? = packageProvenances[id]
266267

267268
/**
268269
* Return the package provenanceResolutionIssue associated with the given [id].

scanner/src/main/kotlin/Scanner.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import org.ossreviewtoolkit.model.OrtResult
4141
import org.ossreviewtoolkit.model.Package
4242
import org.ossreviewtoolkit.model.PackageType
4343
import org.ossreviewtoolkit.model.ProvenanceResolutionResult
44+
import org.ossreviewtoolkit.model.RemoteProvenance
4445
import org.ossreviewtoolkit.model.ScanResult
4546
import org.ossreviewtoolkit.model.ScanSummary
4647
import org.ossreviewtoolkit.model.ScannerRun
@@ -258,7 +259,7 @@ class Scanner(
258259
}.awaitAll()
259260
}.forEach { (pkg, result) ->
260261
result.onSuccess { provenance ->
261-
controller.putPackageProvenance(pkg.id, provenance)
262+
controller.putPackageProvenance(pkg.id, provenance as RemoteProvenance)
262263
}.onFailure {
263264
controller.putPackageProvenanceResolutionIssue(
264265
pkg.id,
@@ -279,7 +280,7 @@ class Scanner(
279280
controller.getPackageProvenancesWithoutVcsPath().map { provenance ->
280281
async {
281282
provenance to runCatching {
282-
nestedProvenanceResolver.resolveNestedProvenance(provenance)
283+
nestedProvenanceResolver.resolveNestedProvenance(provenance as RemoteProvenance)
283284
}
284285
}
285286
}.awaitAll()
@@ -574,7 +575,7 @@ class Scanner(
574575
context: ScanContext
575576
): Map<PathScannerWrapper, ScanResult> {
576577
val downloadDir = try {
577-
provenanceDownloader.download(provenance)
578+
provenanceDownloader.download(provenance as RemoteProvenance)
578579
} catch (e: DownloadException) {
579580
val issue = createAndLogIssue(
580581
"Downloader", "Could not download provenance $provenance: ${e.collectMessages()}"

scanner/src/main/kotlin/provenance/NestedProvenanceResolver.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import org.apache.logging.log4j.kotlin.logger
2323

2424
import org.ossreviewtoolkit.downloader.WorkingTreeCache
2525
import org.ossreviewtoolkit.model.ArtifactProvenance
26-
import org.ossreviewtoolkit.model.KnownProvenance
2726
import org.ossreviewtoolkit.model.Provenance
27+
import org.ossreviewtoolkit.model.RemoteProvenance
2828
import org.ossreviewtoolkit.model.RepositoryProvenance
2929

3030
/**
@@ -36,7 +36,7 @@ interface NestedProvenanceResolver {
3636
* [NestedProvenance] always contains only the provided [ArtifactProvenance]. For a [RepositoryProvenance] the
3737
* resolver looks for nested repositories, for example Git submodules or Mercurial subrepositories.
3838
*/
39-
suspend fun resolveNestedProvenance(provenance: KnownProvenance): NestedProvenance
39+
suspend fun resolveNestedProvenance(provenance: RemoteProvenance): NestedProvenance
4040
}
4141

4242
/**
@@ -46,7 +46,7 @@ class DefaultNestedProvenanceResolver(
4646
private val storage: NestedProvenanceStorage,
4747
private val workingTreeCache: WorkingTreeCache
4848
) : NestedProvenanceResolver {
49-
override suspend fun resolveNestedProvenance(provenance: KnownProvenance): NestedProvenance {
49+
override suspend fun resolveNestedProvenance(provenance: RemoteProvenance): NestedProvenance {
5050
return when (provenance) {
5151
is ArtifactProvenance -> NestedProvenance(root = provenance, subRepositories = emptyMap())
5252
is RepositoryProvenance -> resolveNestedRepository(provenance)

scanner/src/main/kotlin/provenance/ProvenanceDownloader.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ import org.ossreviewtoolkit.downloader.DownloadException
2929
import org.ossreviewtoolkit.downloader.Downloader
3030
import org.ossreviewtoolkit.downloader.WorkingTreeCache
3131
import org.ossreviewtoolkit.model.ArtifactProvenance
32-
import org.ossreviewtoolkit.model.KnownProvenance
3332
import org.ossreviewtoolkit.model.Package
33+
import org.ossreviewtoolkit.model.RemoteProvenance
3434
import org.ossreviewtoolkit.model.RepositoryProvenance
3535
import org.ossreviewtoolkit.model.config.DownloaderConfiguration
3636
import org.ossreviewtoolkit.utils.common.safeDeleteRecursively
@@ -48,7 +48,7 @@ fun interface ProvenanceDownloader {
4848
*
4949
* Throws a [DownloadException] if the download fails.
5050
*/
51-
fun download(provenance: KnownProvenance): File
51+
fun download(provenance: RemoteProvenance): File
5252

5353
/**
5454
* Download the source code specified by the provided [nestedProvenance] incl. sub-repositories and return the path
@@ -61,7 +61,7 @@ fun interface ProvenanceDownloader {
6161
// Use the provenanceDownloader to download each provenance from nestedProvenance separately, because they are
6262
// likely already cached if a path scanner wrapper is used.
6363

64-
val root = download(nestedProvenance.root)
64+
val root = download(nestedProvenance.root as RemoteProvenance)
6565

6666
nestedProvenance.subRepositories.forEach { (path, provenance) ->
6767
val tempDir = download(provenance)
@@ -83,7 +83,7 @@ class DefaultProvenanceDownloader(
8383
) : ProvenanceDownloader {
8484
private val downloader = Downloader(config)
8585

86-
override fun download(provenance: KnownProvenance): File {
86+
override fun download(provenance: RemoteProvenance): File {
8787
val downloadDir = createOrtTempDir()
8888

8989
when (provenance) {

0 commit comments

Comments
 (0)