[github] Fix exception thrown with non-linear history in RiE (IDEA-346042)

#IDEA-346042 Fixed

Exception was thrown in the case of non-linear history because SinglePatchFileHistory
cannot compare refs.

The real solution would be to make `git4idea.changes.MutableLinearGitFileHistory` resilient
to merge commits.

GitOrigin-RevId: 4c5df96e0884a4f49227ad1c0d07a0358d77403f
This commit is contained in:
Chris Lemaire
2024-03-25 12:51:47 +00:00
committed by intellij-monorepo-bot
parent 651938574a
commit 9b9c772d8c
2 changed files with 23 additions and 52 deletions
@@ -30,20 +30,8 @@ internal class GitBranchComparisonResultImpl(private val project: Project,
override val patchesByChange: Map<RefComparisonChange, GitTextFilePatchWithHistory> = Collections.unmodifiableMap(_diffDataByChange)
init {
val commitsHashes = commits.mapTo(mutableSetOf()) { it.sha }
// One or more merge commit for changes that are included into PR (master merges are ignored)
val linearHistory = commits.all { commit ->
commit.parents.count { commitsHashes.contains(it) } <= 1
}
try {
if (linearHistory) {
initForLinearHistory(commits)
}
else {
initForHistoryWithMerges(commits)
}
initForLinearHistory(commits)
}
catch (e: Exception) {
throw RuntimeException("Unable to build branch comparison result between $baseSha and $headSha via $mergeBaseSha - ${e.message}", e)
@@ -57,31 +45,33 @@ internal class GitBranchComparisonResultImpl(private val project: Project,
val commitsHashes = listOf(mergeBaseSha) + commits.map { it.sha }
for (commitWithPatches in commits) {
val commitSha = commitWithPatches.sha
val commitChanges = mutableListOf<RefComparisonChange>()
for (patch in commitWithPatches.patches) {
val change = createChangeFromPatch(previousCommitSha, commitSha, patch)
commitChanges.add(change)
if (commitWithPatches.parents.count { commitsHashes.contains(it) } <= 1) {
for (patch in commitWithPatches.patches) {
val change = createChangeFromPatch(previousCommitSha, commitSha, patch)
commitChanges.add(change)
if (patch is TextFilePatch) {
val beforePath = patch.beforeName
val afterPath = patch.afterName
if (patch is TextFilePatch) {
val beforePath = patch.beforeName
val afterPath = patch.afterName
val historyBefore = beforePath?.let { fileHistoriesByLastKnownFilePath.remove(it) }
val fileHistory = (historyBefore ?: MutableLinearGitFileHistory(commitsHashes)).apply {
append(previousCommitSha, beforePath)
append(commitSha, patch)
val historyBefore = beforePath?.let { fileHistoriesByLastKnownFilePath.remove(it) }
val fileHistory = (historyBefore ?: MutableLinearGitFileHistory(commitsHashes)).apply {
append(previousCommitSha, beforePath)
append(commitSha, patch)
}
val path = (afterPath ?: beforePath)!!
fileHistoriesByLastKnownFilePath[path] = fileHistory
patch.beforeVersionId = previousCommitSha
patch.afterVersionId = commitSha
_diffDataByChange[change] = GitTextFilePatchWithHistory(patch, false, fileHistory)
}
val path = (afterPath ?: beforePath)!!
fileHistoriesByLastKnownFilePath[path] = fileHistory
patch.beforeVersionId = previousCommitSha
patch.afterVersionId = commitSha
_diffDataByChange[change] = GitTextFilePatchWithHistory(patch, false, fileHistory)
}
}
_changesByCommits[commitWithPatches.sha] = commitChanges
previousCommitSha = commitSha
}
@@ -109,27 +99,6 @@ internal class GitBranchComparisonResultImpl(private val project: Project,
}
}
private fun initForHistoryWithMerges(commits: List<GitCommitShaWithPatches>) {
val commitsHashes = commits.mapTo(mutableSetOf()) { it.sha }
for (commitWithPatches in commits) {
val previousCommitSha = commitWithPatches.parents.find { commitsHashes.contains(it) } ?: mergeBaseSha
val commitSha = commitWithPatches.sha
val commitChanges = commitWithPatches.patches.map { createChangeFromPatch(previousCommitSha, commitSha, it) }
_changesByCommits[commitWithPatches.sha] = commitChanges
}
for (patch in headPatches) {
val change = createChangeFromPatch(mergeBaseSha, headSha, patch)
_changes.add(change)
if (patch is TextFilePatch) {
patch.beforeVersionId = baseSha
patch.afterVersionId = headSha
_diffDataByChange[change] = GitTextFilePatchWithHistory(patch, true, SinglePatchGitFileHistory(patch))
}
}
}
private fun createChangeFromPatch(beforeRef: String, afterRef: String, patch: FilePatch): RefComparisonChange {
val beforePath = if (patch.isNewFile) null else VcsUtil.getFilePath(vcsRoot, patch.beforeName)
val afterPath = if (patch.isDeletedFile) null else VcsUtil.getFilePath(vcsRoot, patch.afterName)
@@ -1,8 +1,10 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package git4idea.changes
import com.intellij.openapi.diff.impl.patch.TextFilePatch
// Still used by a plugin
@Suppress("unused")
internal class SinglePatchGitFileHistory(private val patch: TextFilePatch) : GitFileHistory {
override fun findStartCommit(): String? = patch.beforeVersionId