IDEA-216114 Filter history by HEAD

Our index may contain commits which were removed by git gc, so "bad object" error may occur. To avoid this error, we can filter the commits by HEAD

GitOrigin-RevId: 6a77848d41c4af0db0a484084f63770033356e50
This commit is contained in:
Nikolay.Rykunov
2019-07-02 06:52:16 +03:00
committed by intellij-monorepo-bot
parent ba4dd580a3
commit 0feb2dc602
3 changed files with 35 additions and 5 deletions
@@ -11,6 +11,7 @@
<orderEntry type="module" module-name="intellij.platform.vcs" />
<orderEntry type="module" module-name="intellij.platform.vcs.impl" />
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
<orderEntry type="module" module-name="intellij.platform.vcs.log.graph.impl" />
<orderEntry type="module" module-name="intellij.platform.vcs.log.impl" />
<orderEntry type="module" module-name="intellij.platform.vcs.log" />
<orderEntry type="module" module-name="intellij.vcs.git" />
@@ -100,7 +100,7 @@ class PredictionService(val project: Project,
dataManager.addDataPackChangeListener(dataPackChangeListener)
dataManager.index.addListener(indexingFinishedListener)
val filesHistoryProvider = dataManager.index.dataGetter?.let { FilesHistoryProvider(project, it) } ?: return
val filesHistoryProvider = dataManager.index.dataGetter?.let { FilesHistoryProvider(project, dataManager, it) } ?: return
predictionRequirements = PredictionRequirements(dataManager, filesHistoryProvider)
calculatePrediction()
}
@@ -1,18 +1,26 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.changeReminder.repository
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vcs.FilePath
import com.intellij.openapi.vcs.changes.ChangesUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.vcs.log.data.VcsLogData
import com.intellij.vcs.log.data.index.IndexDataGetter
import com.intellij.vcs.log.graph.impl.facade.PermanentGraphImpl
import com.intellij.vcs.log.graph.utils.DfsWalk
import com.intellij.vcs.log.util.VcsLogUtil
import com.intellij.vcs.log.visible.filters.VcsLogFilterObject
import com.jetbrains.changeReminder.processCommitsFromHashes
import com.jetbrains.changeReminder.retainAll
import gnu.trove.TIntHashSet
data class Commit(val id: Int, val time: Long, val author: String, val files: Set<FilePath>)
internal class FilesHistoryProvider(private val project: Project, private val dataGetter: IndexDataGetter) {
internal class FilesHistoryProvider(private val project: Project,
private val dataManager: VcsLogData,
private val dataGetter: IndexDataGetter) {
private val filesHistoryCache = HashMap<FilePath, Collection<Int>>()
private fun getCommitHashesWithFile(file: FilePath): Collection<Int> {
@@ -42,11 +50,32 @@ internal class FilesHistoryProvider(private val project: Project, private val da
return commitsData
}
private fun getCommitsFromHead(root: VirtualFile): TIntHashSet {
val dataPack = dataManager.dataPack
val branchName = dataManager.getLogProvider(root).getCurrentBranch(root) ?: return TIntHashSet()
val branchRef = VcsLogUtil.findBranch(dataPack.refsModel, root, branchName) ?: return TIntHashSet()
val branchIndex = dataManager.getCommitIndex(branchRef.commitHash, branchRef.root)
val permanentGraph = dataPack.permanentGraph as? PermanentGraphImpl<Int> ?: return TIntHashSet()
val branchNodeId = permanentGraph.permanentCommitsInfo.getNodeId(branchIndex)
val commitsFromHead = TIntHashSet()
DfsWalk(listOf(branchNodeId), permanentGraph.linearGraph).walk(true) {
ProgressManager.checkCanceled()
commitsFromHead.add(permanentGraph.permanentCommitsInfo.getCommitId(it))
true
}
return commitsFromHead
}
fun getFilesHistory(root: VirtualFile, files: Collection<FilePath>): Collection<Commit> {
filesHistoryCache.retainAll(files)
filesHistoryCache.putAll(files.filter { it !in filesHistoryCache }
.associateWith { getCommitHashesWithFile(it) })
val commitsFromHead = getCommitsFromHead(root)
filesHistoryCache.putAll(files
.filter { it !in filesHistoryCache }
.associateWith { file ->
getCommitHashesWithFile(file).filter { it in commitsFromHead }
})
val commits = files.mapNotNull { filesHistoryCache[it] }.flatten()
return getCommitsData(root, commits)