Skip to content

Commit

Permalink
feat(CompareCommand): Add a comparison for the Repositorys
Browse files Browse the repository at this point in the history
This commit adds new data classes to track the differences of the two ORT
results and especially of two repositories.

Signed-off-by: Onur Demirci <[email protected]>
  • Loading branch information
bs-ondem committed Nov 27, 2023
1 parent 9597966 commit 816be38
Showing 1 changed file with 216 additions and 0 deletions.
216 changes: 216 additions & 0 deletions plugins/commands/compare/src/main/kotlin/CompareCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,30 @@ import com.github.difflib.UnifiedDiffUtils
import java.time.Instant

import org.ossreviewtoolkit.model.OrtResult
import org.ossreviewtoolkit.model.PackageCuration
import org.ossreviewtoolkit.model.Repository
import org.ossreviewtoolkit.model.VcsInfo
import org.ossreviewtoolkit.model.config.Curations
import org.ossreviewtoolkit.model.config.Excludes
import org.ossreviewtoolkit.model.config.IssueResolution
import org.ossreviewtoolkit.model.config.LicenseChoices
import org.ossreviewtoolkit.model.config.LicenseFindingCuration
import org.ossreviewtoolkit.model.config.PackageConfiguration
import org.ossreviewtoolkit.model.config.PackageLicenseChoice
import org.ossreviewtoolkit.model.config.PackageManagerConfiguration
import org.ossreviewtoolkit.model.config.PathExclude
import org.ossreviewtoolkit.model.config.RepositoryAnalyzerConfiguration
import org.ossreviewtoolkit.model.config.RepositoryConfiguration
import org.ossreviewtoolkit.model.config.Resolutions
import org.ossreviewtoolkit.model.config.RuleViolationResolution
import org.ossreviewtoolkit.model.config.ScopeExclude
import org.ossreviewtoolkit.model.config.VulnerabilityResolution
import org.ossreviewtoolkit.model.mapper
import org.ossreviewtoolkit.plugins.commands.api.OrtCommand
import org.ossreviewtoolkit.utils.common.expandTilde
import org.ossreviewtoolkit.utils.common.getCommonParentFile
import org.ossreviewtoolkit.utils.ort.Environment
import org.ossreviewtoolkit.utils.spdx.model.SpdxLicenseChoice

class CompareCommand : OrtCommand(
name = "compare",
Expand Down Expand Up @@ -167,12 +186,142 @@ class CompareCommand : OrtCommand(
throw ProgramResult(0)
}

val diff = resultA.diff(resultB)

echo(deserializer.writeValueAsString(diff))

throw ProgramResult(1)
}
}
}
}

private fun OrtResult.diff(other: OrtResult) =
OrtResultDiff(
repositoryDiff = repository.diff(other.repository)
)

private fun Repository.diff(other: Repository): RepositoryDiff? =
if (this == other) {
null
} else {
RepositoryDiff(
vcsA = vcs.takeIf { it != other.vcs },
vcsB = other.vcs.takeIf { it != vcs },
vcsProcessedA = vcsProcessed.takeIf { it != other.vcsProcessed },
vcsProcessedB = other.vcsProcessed.takeIf { it != vcsProcessed },
nestedRepositoriesA = nestedRepositories.takeIf { it != other.nestedRepositories },
nestedRepositoriesB = other.nestedRepositories.takeIf { it != nestedRepositories },
configDiff = config.diff(other.config)
)
}

private fun RepositoryConfiguration.diff(other: RepositoryConfiguration): RepositoryConfigurationDiff? =
if (this == other) {
null
} else {
RepositoryConfigurationDiff(
analyzerConfigDiff = analyzer.diff(other.analyzer),
excludeDiff = excludes.diff(other.excludes),
resolutionsDiff = resolutions.diff(other.resolutions),
curationsDiff = curations.diff(other.curations),
packageConfigurationsA = (packageConfigurations - other.packageConfigurations.toSet())
.takeUnless { it.isEmpty() },
packageConfigurationsB = (other.packageConfigurations - packageConfigurations.toSet())
.takeUnless { it.isEmpty() },
licenseChoicesDiff = licenseChoices.diff(other.licenseChoices)
)
}

private fun Excludes.diff(other: Excludes): ExcludesDiff? =
if (this == other) {
null
} else {
ExcludesDiff(
pathsA = (paths - other.paths.toSet()).takeUnless { it.isEmpty() },
pathsB = (other.paths - paths.toSet()).takeUnless { it.isEmpty() },
scopesA = (scopes - other.scopes.toSet()).takeUnless { it.isEmpty() },
scopesB = (other.scopes - scopes.toSet()).takeUnless { it.isEmpty() }
)
}

private fun Resolutions.diff(other: Resolutions): ResolutionsDiff? =
if (this == other) {
null
} else {
ResolutionsDiff(
issuesA = (issues - other.issues.toSet()).takeUnless { it.isEmpty() },
issuesB = (other.issues - issues.toSet()).takeUnless { it.isEmpty() },
ruleViolationsA = (ruleViolations - other.ruleViolations.toSet()).takeUnless { it.isEmpty() },
ruleViolationsB = (other.ruleViolations - ruleViolations.toSet()).takeUnless { it.isEmpty() },
vulnerabilitiesA = (vulnerabilities - other.vulnerabilities.toSet()).takeUnless { it.isEmpty() },
vulnerabilitiesB = (other.vulnerabilities - vulnerabilities.toSet()).takeUnless { it.isEmpty() }
)
}

private fun Curations.diff(other: Curations): CurationsDiff? =
if (this == other) {
null
} else {
CurationsDiff(
packagesA = (packages - other.packages.toSet()).takeUnless { it.isEmpty() },
packagesB = (other.packages - packages.toSet()).takeUnless { it.isEmpty() },
licenseFindingsA = (licenseFindings - other.licenseFindings.toSet()).takeUnless { it.isEmpty() },
licenseFindingsB = (other.licenseFindings - licenseFindings.toSet()).takeUnless { it.isEmpty() }
)
}

private fun LicenseChoices.diff(other: LicenseChoices): LicenseChoicesDiff? =
if (this == other) {
null
} else {
LicenseChoicesDiff(
repositoryLicenseChoicesA = (repositoryLicenseChoices - other.repositoryLicenseChoices.toSet())
.takeUnless { it.isEmpty() },
repositoryLicenseChoicesB = (other.repositoryLicenseChoices - repositoryLicenseChoices.toSet())
.takeUnless { it.isEmpty() },
packageLicenseChoicesA = (packageLicenseChoices - other.packageLicenseChoices.toSet())
.takeUnless { it.isEmpty() },
packageLicenseChoicesB = (other.packageLicenseChoices - packageLicenseChoices.toSet())
.takeUnless { it.isEmpty() }
)
}

private fun RepositoryAnalyzerConfiguration?.diff(other: RepositoryAnalyzerConfiguration?): AnalyzerConfigurationDiff? {
if (this == other) return null

return if (this == null) {
AnalyzerConfigurationDiff(
allowDynamicVersionsB = other?.allowDynamicVersions,
enabledPackageManagersB = other?.enabledPackageManagers,
disabledPackageManagersB = other?.disabledPackageManagers,
packageManagersB = other?.packageManagers,
skipExcludedB = other?.skipExcluded
)
} else if (other == null) {
AnalyzerConfigurationDiff(
allowDynamicVersionsA = allowDynamicVersions,
enabledPackageManagersA = enabledPackageManagers,
disabledPackageManagersA = disabledPackageManagers,
packageManagersA = packageManagers,
skipExcludedA = skipExcluded
)
} else {
AnalyzerConfigurationDiff(
allowDynamicVersionsA = allowDynamicVersions.takeIf { it != other.allowDynamicVersions },
allowDynamicVersionsB = other.allowDynamicVersions.takeIf { it != allowDynamicVersions },
enabledPackageManagersA = enabledPackageManagers.takeIf { it != other.enabledPackageManagers },
enabledPackageManagersB = other.enabledPackageManagers.takeIf { it != enabledPackageManagers },
disabledPackageManagersA = disabledPackageManagers.takeIf { it != other.disabledPackageManagers },
disabledPackageManagersB = other.disabledPackageManagers.takeIf { it != disabledPackageManagers },
packageManagersA = packageManagers.takeIf { it != other.packageManagers },
packageManagersB = other.packageManagers.takeIf { it != packageManagers },
skipExcludedA = skipExcluded.takeIf { it != other.skipExcluded },
skipExcludedB = other.skipExcluded.takeIf { it != skipExcluded }
)
}
}

private enum class CompareMethod {
TEXT_DIFF,
SEMANTIC_DIFF
Expand Down Expand Up @@ -204,3 +353,70 @@ private fun Map<Regex, String>.replaceIn(text: String) =
entries.fold(text) { currentText, (from, to) ->
currentText.replace(from, to)
}

private data class OrtResultDiff(
val repositoryDiff: RepositoryDiff? = null
)

private data class RepositoryDiff(
val vcsA: VcsInfo? = null,
val vcsB: VcsInfo? = null,
val vcsProcessedA: VcsInfo? = null,
val vcsProcessedB: VcsInfo? = null,
val nestedRepositoriesA: Map<String, VcsInfo>? = null,
val nestedRepositoriesB: Map<String, VcsInfo>? = null,
val configDiff: RepositoryConfigurationDiff? = null
)

private data class RepositoryConfigurationDiff(
val analyzerConfigDiff: AnalyzerConfigurationDiff? = null,
val excludeDiff: ExcludesDiff? = null,
val resolutionsDiff: ResolutionsDiff? = null,
val curationsDiff: CurationsDiff? = null,
val packageConfigurationsA: List<PackageConfiguration>? = null,
val packageConfigurationsB: List<PackageConfiguration>? = null,
val licenseChoicesDiff: LicenseChoicesDiff? = null
)

private data class ExcludesDiff(
val pathsA: List<PathExclude>? = null,
val pathsB: List<PathExclude>? = null,
val scopesA: List<ScopeExclude>? = null,
val scopesB: List<ScopeExclude>? = null
)

private data class ResolutionsDiff(
val issuesA: List<IssueResolution>? = null,
val issuesB: List<IssueResolution>? = null,
val ruleViolationsA: List<RuleViolationResolution>? = null,
val ruleViolationsB: List<RuleViolationResolution>? = null,
val vulnerabilitiesA: List<VulnerabilityResolution>? = null,
val vulnerabilitiesB: List<VulnerabilityResolution>? = null
)

private data class CurationsDiff(
val packagesA: List<PackageCuration>? = null,
val packagesB: List<PackageCuration>? = null,
val licenseFindingsA: List<LicenseFindingCuration>? = null,
val licenseFindingsB: List<LicenseFindingCuration>? = null
)

private data class LicenseChoicesDiff(
val repositoryLicenseChoicesA: List<SpdxLicenseChoice>? = null,
val repositoryLicenseChoicesB: List<SpdxLicenseChoice>? = null,
val packageLicenseChoicesA: List<PackageLicenseChoice>? = null,
val packageLicenseChoicesB: List<PackageLicenseChoice>? = null
)

private data class AnalyzerConfigurationDiff(
val allowDynamicVersionsA: Boolean? = null,
val allowDynamicVersionsB: Boolean? = null,
val enabledPackageManagersA: List<String>? = null,
val enabledPackageManagersB: List<String>? = null,
val disabledPackageManagersA: List<String>? = null,
val disabledPackageManagersB: List<String>? = null,
val packageManagersA: Map<String, PackageManagerConfiguration>? = null,
val packageManagersB: Map<String, PackageManagerConfiguration>? = null,
val skipExcludedA: Boolean? = false,
val skipExcludedB: Boolean? = false
)

0 comments on commit 816be38

Please sign in to comment.