diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryFilterer.kt b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryFilterer.kt index 94cca6746c82..a19bf4000df5 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryFilterer.kt +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryFilterer.kt @@ -13,354 +13,314 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.vcs.log.history; +package com.intellij.vcs.log.history -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.vcs.AbstractVcs; -import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.history.VcsCachingHistory; -import com.intellij.openapi.vcs.history.VcsFileRevision; -import com.intellij.openapi.vcs.history.VcsFileRevisionEx; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.vcs.log.*; -import com.intellij.vcs.log.data.*; -import com.intellij.vcs.log.data.index.IndexDataGetter; -import com.intellij.vcs.log.data.index.VcsLogIndex; -import com.intellij.vcs.log.graph.GraphCommit; -import com.intellij.vcs.log.graph.GraphCommitImpl; -import com.intellij.vcs.log.graph.PermanentGraph; -import com.intellij.vcs.log.graph.VisibleGraph; -import com.intellij.vcs.log.graph.api.LiteLinearGraph; -import com.intellij.vcs.log.graph.impl.facade.PermanentGraphImpl; -import com.intellij.vcs.log.graph.impl.facade.ReachableNodes; -import com.intellij.vcs.log.graph.impl.facade.VisibleGraphImpl; -import com.intellij.vcs.log.graph.impl.permanent.PermanentCommitsInfoImpl; -import com.intellij.vcs.log.graph.utils.LinearGraphUtils; -import com.intellij.vcs.log.impl.HashImpl; -import com.intellij.vcs.log.impl.VcsLogFilterCollectionImpl; -import com.intellij.vcs.log.impl.VcsLogRevisionFilterImpl; -import com.intellij.vcs.log.util.StopWatch; -import com.intellij.vcs.log.util.VcsLogUtil; -import com.intellij.vcs.log.visible.CommitCountStage; -import com.intellij.vcs.log.visible.VcsLogFilterer; -import com.intellij.vcs.log.visible.VcsLogFiltererImpl; -import com.intellij.vcs.log.visible.VisiblePack; -import com.intellij.vcsUtil.VcsUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.util.Pair +import com.intellij.openapi.util.Ref +import com.intellij.openapi.vcs.AbstractVcs +import com.intellij.openapi.vcs.FilePath +import com.intellij.openapi.vcs.ProjectLevelVcsManager +import com.intellij.openapi.vcs.VcsException +import com.intellij.openapi.vcs.history.VcsCachingHistory +import com.intellij.openapi.vcs.history.VcsFileRevision +import com.intellij.openapi.vcs.history.VcsFileRevisionEx +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.util.ObjectUtils.assertNotNull +import com.intellij.util.ObjectUtils.notNull +import com.intellij.util.containers.ContainerUtil +import com.intellij.util.containers.ContainerUtil.getFirstItem +import com.intellij.vcs.log.* +import com.intellij.vcs.log.data.* +import com.intellij.vcs.log.data.index.IndexDataGetter +import com.intellij.vcs.log.graph.GraphCommit +import com.intellij.vcs.log.graph.GraphCommitImpl +import com.intellij.vcs.log.graph.PermanentGraph +import com.intellij.vcs.log.graph.VisibleGraph +import com.intellij.vcs.log.graph.api.LiteLinearGraph +import com.intellij.vcs.log.graph.impl.facade.PermanentGraphImpl +import com.intellij.vcs.log.graph.impl.facade.ReachableNodes +import com.intellij.vcs.log.graph.impl.facade.VisibleGraphImpl +import com.intellij.vcs.log.graph.utils.LinearGraphUtils +import com.intellij.vcs.log.impl.HashImpl +import com.intellij.vcs.log.impl.VcsLogFilterCollectionImpl +import com.intellij.vcs.log.impl.VcsLogRevisionFilterImpl +import com.intellij.vcs.log.util.StopWatch +import com.intellij.vcs.log.util.VcsLogUtil +import com.intellij.vcs.log.visible.CommitCountStage +import com.intellij.vcs.log.visible.VcsLogFilterer +import com.intellij.vcs.log.visible.VcsLogFiltererImpl +import com.intellij.vcs.log.visible.VisiblePack +import com.intellij.vcsUtil.VcsUtil -import java.util.*; +internal class FileHistoryFilterer(logData: VcsLogData) : VcsLogFilterer { + private val project = logData.project + private val logProviders = logData.logProviders + private val storage = logData.storage + private val index = logData.index + private val indexDataGetter = index.dataGetter!! + private val vcsLogFilterer = VcsLogFiltererImpl(logProviders, storage, logData.topCommitsCache, + logData.commitDetailsGetter, index) -import static com.intellij.util.ObjectUtils.assertNotNull; -import static com.intellij.util.ObjectUtils.notNull; -import static com.intellij.util.containers.ContainerUtil.getFirstItem; - -class FileHistoryFilterer implements VcsLogFilterer { - private static final Logger LOG = Logger.getInstance(FileHistoryFilterer.class); - - @NotNull private final Project myProject; - @NotNull private final Map myLogProviders; - @NotNull private final VcsLogStorage myStorage; - @NotNull private final VcsLogIndex myIndex; - @NotNull private final IndexDataGetter myIndexDataGetter; - @NotNull private final VcsLogFiltererImpl myVcsLogFilterer; - - public FileHistoryFilterer(@NotNull VcsLogData logData) { - myProject = logData.getProject(); - myLogProviders = logData.getLogProviders(); - myStorage = logData.getStorage(); - myIndex = logData.getIndex(); - myIndexDataGetter = assertNotNull(myIndex.getDataGetter()); - - myVcsLogFilterer = new VcsLogFiltererImpl(myLogProviders, myStorage, logData.getTopCommitsCache(), - logData.getCommitDetailsGetter(), myIndex); + override fun filter(dataPack: DataPack, + sortType: PermanentGraph.SortType, + filters: VcsLogFilterCollection, + commitCount: CommitCountStage): Pair { + val filePath = getFilePath(filters) ?: return vcsLogFilterer.filter(dataPack, sortType, filters, commitCount) + val root = notNull(VcsUtil.getVcsRootFor(project, filePath)) + return MyWorker(root, filePath, getHash(filters)).filter(dataPack, sortType, filters, commitCount) } - @NotNull - @Override - public Pair filter(@NotNull DataPack dataPack, - @NotNull PermanentGraph.SortType sortType, - @NotNull VcsLogFilterCollection filters, - @NotNull CommitCountStage commitCount) { - FilePath filePath = getFilePath(filters); - if (filePath == null) { - return myVcsLogFilterer.filter(dataPack, sortType, filters, commitCount); - } - VirtualFile root = notNull(VcsUtil.getVcsRootFor(myProject, filePath)); - return new MyWorker(root, filePath, getHash(filters)).filter(dataPack, sortType, filters, commitCount); + override fun canFilterEmptyPack(filters: VcsLogFilterCollection): Boolean { + val filePath = getFilePath(filters) + return filePath != null && !filePath.isDirectory } - @Override - public boolean canFilterEmptyPack(@NotNull VcsLogFilterCollection filters) { - FilePath filePath = getFilePath(filters); - return filePath != null && !filePath.isDirectory(); - } + private inner class MyWorker constructor(private val root: VirtualFile, + private val filePath: FilePath, + private val hash: Hash?) { - @Nullable - private static FilePath getFilePath(@NotNull VcsLogFilterCollection filters) { - List detailsFilters = filters.getDetailsFilters(); - if (detailsFilters.size() != 1) { - return null; - } + fun filter(dataPack: DataPack, + sortType: PermanentGraph.SortType, + filters: VcsLogFilterCollection, + commitCount: CommitCountStage): Pair { + val start = System.currentTimeMillis() - VcsLogDetailsFilter filter = notNull(getFirstItem(detailsFilters)); - if (!(filter instanceof VcsLogStructureFilter)) { - return null; - } - - Collection files = ((VcsLogStructureFilter)filter).getFiles(); - if (files.size() != 1) { - return null; - } - - return notNull(getFirstItem(files)); - } - - @Nullable - private static Hash getHash(@NotNull VcsLogFilterCollection filters) { - VcsLogRevisionFilter revisionFilter = filters.get(VcsLogFilterCollection.REVISION_FILTER); - if (revisionFilter == null) { - return null; - } - - Collection heads = revisionFilter.getHeads(); - if (heads.size() != 1) { - return null; - } - - return notNull(getFirstItem(heads)).getHash(); - } - - @NotNull - public static VcsLogFilterCollection createFilters(@NotNull FilePath path, - @Nullable Hash revision, - @NotNull VirtualFile root, - boolean showAllBranches) { - VcsLogStructureFilterImpl fileFilter = new VcsLogStructureFilterImpl(Collections.singleton(path)); - - if (revision != null) { - VcsLogRevisionFilterImpl revisionFilter = VcsLogRevisionFilterImpl.fromCommit(new CommitId(revision, root)); - return new VcsLogFilterCollectionImpl.VcsLogFilterCollectionBuilder(fileFilter, revisionFilter).build(); - } - - VcsLogBranchFilterImpl branchFilter = showAllBranches ? null : VcsLogBranchFilterImpl.fromBranch("HEAD"); - return new VcsLogFilterCollectionImpl.VcsLogFilterCollectionBuilder(fileFilter, branchFilter).build(); - } - - private class MyWorker { - @NotNull private final VirtualFile myRoot; - @NotNull private final FilePath myFilePath; - @Nullable private final Hash myHash; - - private MyWorker(@NotNull VirtualFile root, @NotNull FilePath path, @Nullable Hash hash) { - myRoot = root; - myFilePath = path; - myHash = hash; - } - - @NotNull - public Pair filter(@NotNull DataPack dataPack, - @NotNull PermanentGraph.SortType sortType, - @NotNull VcsLogFilterCollection filters, - @NotNull CommitCountStage commitCount) { - long start = System.currentTimeMillis(); - - if (myIndex.isIndexed(myRoot) && (dataPack.isFull() || myFilePath.isDirectory())) { - VisiblePack visiblePack = filterWithIndex(dataPack, sortType, filters); - LOG.debug(StopWatch.formatTime(System.currentTimeMillis() - start) + " for computing history for " + myFilePath + " with index"); - checkNotEmpty(dataPack, visiblePack, true); - return Pair.create(visiblePack, commitCount); + if (index.isIndexed(root) && (dataPack.isFull || filePath.isDirectory)) { + val visiblePack = filterWithIndex(dataPack, sortType, filters) + LOG.debug(StopWatch.formatTime(System.currentTimeMillis() - start) + " for computing history for " + filePath + " with index") + checkNotEmpty(dataPack, visiblePack, true) + return Pair.create(visiblePack, commitCount) } - if (myFilePath.isDirectory()) { - return myVcsLogFilterer.filter(dataPack, sortType, filters, commitCount); + if (filePath.isDirectory) { + return vcsLogFilterer.filter(dataPack, sortType, filters, commitCount) } - AbstractVcs vcs = ProjectLevelVcsManager.getInstance(myProject).getVcsFor(myRoot); - if (vcs != null && vcs.getVcsHistoryProvider() != null) { - try { - VisiblePack visiblePack = filterWithProvider(vcs, dataPack, sortType, filters); + val vcs = ProjectLevelVcsManager.getInstance(project).getVcsFor(root) + if (vcs != null && vcs.vcsHistoryProvider != null) { + return try { + val visiblePack = filterWithProvider(vcs, dataPack, sortType, filters) LOG.debug(StopWatch.formatTime(System.currentTimeMillis() - start) + " for computing history for " + - myFilePath + - " with history provider"); - checkNotEmpty(dataPack, visiblePack, false); - return Pair.create(visiblePack, commitCount); + filePath + + " with history provider") + checkNotEmpty(dataPack, visiblePack, false) + Pair.create(visiblePack, commitCount) } - catch (VcsException e) { - LOG.error(e); - return myVcsLogFilterer.filter(dataPack, sortType, filters, commitCount); + catch (e: VcsException) { + LOG.error(e) + vcsLogFilterer.filter(dataPack, sortType, filters, commitCount) } + } - LOG.warn("Could not find vcs or history provider for file " + myFilePath); - return myVcsLogFilterer.filter(dataPack, sortType, filters, commitCount); + LOG.warn("Could not find vcs or history provider for file $filePath") + return vcsLogFilterer.filter(dataPack, sortType, filters, commitCount) } - private void checkNotEmpty(@NotNull DataPack dataPack, @NotNull VisiblePack visiblePack, boolean withIndex) { - if (!dataPack.isFull()) { - LOG.debug("Data pack is not full while computing file history for " + myFilePath + "\n" + - "Found " + visiblePack.getVisibleGraph().getVisibleCommitCount() + " commits"); + private fun checkNotEmpty(dataPack: DataPack, visiblePack: VisiblePack, withIndex: Boolean) { + if (!dataPack.isFull) { + LOG.debug("Data pack is not full while computing file history for " + filePath + "\n" + + "Found " + visiblePack.visibleGraph.visibleCommitCount + " commits") } - else if (visiblePack.getVisibleGraph().getVisibleCommitCount() == 0) { - LOG.warn("Empty file history from " + (withIndex ? "index" : "provider") + " for " + myFilePath); + else if (visiblePack.visibleGraph.visibleCommitCount == 0) { + LOG.warn("Empty file history from " + (if (withIndex) "index" else "provider") + " for " + filePath) } } - @NotNull - private VisiblePack filterWithProvider(@NotNull AbstractVcs vcs, - @NotNull DataPack dataPack, - @NotNull PermanentGraph.SortType sortType, - @NotNull VcsLogFilterCollection filters) throws VcsException { - VcsRevisionNumber revisionNumber = myHash != null ? VcsLogUtil.convertToRevisionNumber(myHash) : null; - List revisions = VcsCachingHistory.collect(vcs, myFilePath, revisionNumber); + @Throws(VcsException::class) + private fun filterWithProvider(vcs: AbstractVcs<*>, + dataPack: DataPack, + sortType: PermanentGraph.SortType, + filters: VcsLogFilterCollection): VisiblePack { + var dataPack = dataPack + val revisionNumber = if (hash != null) VcsLogUtil.convertToRevisionNumber(hash) else null + val revisions = VcsCachingHistory.collect(vcs, filePath, revisionNumber) - if (revisions.isEmpty()) return VisiblePack.EMPTY; + if (revisions.isEmpty()) return VisiblePack.EMPTY - Map pathsMap = ContainerUtil.newHashMap(); - VisibleGraph visibleGraph; + val pathsMap = ContainerUtil.newHashMap() + val visibleGraph: VisibleGraph - if (dataPack.isFull()) { - for (VcsFileRevision revision : revisions) { - pathsMap.put(getIndex(revision), ((VcsFileRevisionEx)revision).getPath()); + if (dataPack.isFull) { + for (revision in revisions) { + pathsMap[getIndex(revision)] = (revision as VcsFileRevisionEx).path } - visibleGraph = myVcsLogFilterer.createVisibleGraph(dataPack, sortType, null, pathsMap.keySet()); + visibleGraph = vcsLogFilterer.createVisibleGraph(dataPack, sortType, null, pathsMap.keys) } else { - List> commits = ContainerUtil.newArrayListWithCapacity(revisions.size()); + val commits = ContainerUtil.newArrayListWithCapacity>(revisions.size) - for (VcsFileRevision revision : revisions) { - int index = getIndex(revision); - pathsMap.put(index, ((VcsFileRevisionEx)revision).getPath()); - commits.add(GraphCommitImpl.createCommit(index, Collections.emptyList(), revision.getRevisionDate().getTime())); + for (revision in revisions) { + val index = getIndex(revision) + pathsMap[index] = (revision as VcsFileRevisionEx).path + commits.add(GraphCommitImpl.createCommit(index, emptyList(), revision.getRevisionDate().time)) } - Map refs = getFilteredRefs(dataPack); - Map providers = ContainerUtil.newHashMap(Pair.create(myRoot, myLogProviders.get(myRoot))); + val refs = getFilteredRefs(dataPack) + val providers = ContainerUtil.newHashMap(Pair.create(root, logProviders[root])) - dataPack = DataPack.build(commits, refs, providers, myStorage, false); - visibleGraph = myVcsLogFilterer.createVisibleGraph(dataPack, sortType, null, - null/*no need to filter here, since we do not have any extra commits in this pack*/); + dataPack = DataPack.build(commits, refs, providers, storage, false) + visibleGraph = vcsLogFilterer.createVisibleGraph(dataPack, sortType, null, + null/*no need to filter here, since we do not have any extra commits in this pack*/) } - return new FileHistoryVisiblePack(dataPack, visibleGraph, false, filters, pathsMap); + return FileHistoryVisiblePack(dataPack, visibleGraph, false, filters, pathsMap) } - @NotNull - private Map getFilteredRefs(@NotNull DataPack dataPack) { - Map refs = ContainerUtil.newHashMap(); - CompressedRefs compressedRefs = dataPack.getRefsModel().getAllRefsByRoot().get(myRoot); + private fun getFilteredRefs(dataPack: DataPack): Map { + val refs = ContainerUtil.newHashMap() + var compressedRefs: CompressedRefs? = dataPack.refsModel.allRefsByRoot[root] if (compressedRefs == null) { - compressedRefs = new CompressedRefs(ContainerUtil.newHashSet(), myStorage); + compressedRefs = CompressedRefs(ContainerUtil.newHashSet(), storage) } - refs.put(myRoot, compressedRefs); - return refs; + refs[root] = compressedRefs + return refs } - private int getIndex(@NotNull VcsFileRevision revision) { - return myStorage.getCommitIndex(HashImpl.build(revision.getRevisionNumber().asString()), myRoot); + private fun getIndex(revision: VcsFileRevision): Int { + return storage.getCommitIndex(HashImpl.build(revision.revisionNumber.asString()), root) } - @NotNull - private VisiblePack filterWithIndex(@NotNull DataPack dataPack, - @NotNull PermanentGraph.SortType sortType, - @NotNull VcsLogFilterCollection filters) { - Set matchingHeads = myVcsLogFilterer.getMatchingHeads(dataPack.getRefsModel(), Collections.singleton(myRoot), filters); - IndexDataGetter.FileNamesData data = myIndexDataGetter.buildFileNamesData(myFilePath); - VisibleGraph visibleGraph = myVcsLogFilterer.createVisibleGraph(dataPack, sortType, matchingHeads, data.getCommits()); + private fun filterWithIndex(dataPack: DataPack, + sortType: PermanentGraph.SortType, + filters: VcsLogFilterCollection): VisiblePack { + val matchingHeads = vcsLogFilterer.getMatchingHeads(dataPack.refsModel, setOf(root), filters) + val data = indexDataGetter.buildFileNamesData(filePath) + var visibleGraph = vcsLogFilterer.createVisibleGraph(dataPack, sortType, matchingHeads, data.commits) - Map pathsMap = null; - if (visibleGraph.getVisibleCommitCount() > 0) { - if (visibleGraph instanceof VisibleGraphImpl) { - int row = getCurrentRow(dataPack, visibleGraph, data); + var pathsMap: Map? = null + if (visibleGraph.visibleCommitCount > 0) { + if (visibleGraph is VisibleGraphImpl<*>) { + val row = getCurrentRow(dataPack, visibleGraph, data) if (row >= 0) { - FileHistoryRefiner refiner = new FileHistoryRefiner((VisibleGraphImpl)visibleGraph, data); - if (refiner.refine(row, myFilePath)) { + val refiner = FileHistoryRefiner(visibleGraph as VisibleGraphImpl, data) + if (refiner.refine(row, filePath)) { // creating a vg is the most expensive task, so trying to avoid that when unnecessary - visibleGraph = myVcsLogFilterer.createVisibleGraph(dataPack, sortType, matchingHeads, refiner.getPathsForCommits().keySet()); - pathsMap = refiner.getPathsForCommits(); + visibleGraph = vcsLogFilterer.createVisibleGraph(dataPack, sortType, matchingHeads, refiner.pathsForCommits.keys) + pathsMap = refiner.pathsForCommits } } } } if (pathsMap == null) { - pathsMap = data.buildPathsMap(); + pathsMap = data.buildPathsMap() } - if (!myFilePath.isDirectory()) reindexFirstCommitsIfNeeded(visibleGraph); - return new FileHistoryVisiblePack(dataPack, visibleGraph, false, filters, pathsMap); + if (!filePath.isDirectory) reindexFirstCommitsIfNeeded(visibleGraph) + return FileHistoryVisiblePack(dataPack, visibleGraph, false, filters, pathsMap) } - private void reindexFirstCommitsIfNeeded(@NotNull VisibleGraph graph) { + private fun reindexFirstCommitsIfNeeded(graph: VisibleGraph) { // we may not have renames big commits, may need to reindex them - if (graph instanceof VisibleGraphImpl) { - LiteLinearGraph liteLinearGraph = LinearGraphUtils.asLiteLinearGraph(((VisibleGraphImpl)graph).getLinearGraph()); - for (int row = 0; row < liteLinearGraph.nodesCount(); row++) { + if (graph is VisibleGraphImpl<*>) { + val liteLinearGraph = LinearGraphUtils.asLiteLinearGraph((graph as VisibleGraphImpl<*>).linearGraph) + for (row in 0 until liteLinearGraph.nodesCount()) { // checking if commit is a root commit (which means file was added or renamed there) if (liteLinearGraph.getNodes(row, LiteLinearGraph.NodeFilter.DOWN).isEmpty()) { - myIndex.reindexWithRenames(graph.getRowInfo(row).getCommit(), myRoot); + index.reindexWithRenames(graph.getRowInfo(row).commit, root) } } } } - private int getCurrentRow(@NotNull DataPack pack, - @NotNull VisibleGraph visibleGraph, - @NotNull IndexDataGetter.FileNamesData fileIndexData) { - PermanentGraph permanentGraph = pack.getPermanentGraph(); - if (permanentGraph instanceof PermanentGraphImpl) { - Hash hash = myHash != null ? myHash : getHead(pack); + private fun getCurrentRow(pack: DataPack, + visibleGraph: VisibleGraph, + fileIndexData: IndexDataGetter.FileNamesData): Int { + val permanentGraph = pack.permanentGraph + if (permanentGraph is PermanentGraphImpl<*>) { + val hash = hash ?: getHead(pack) if (hash != null) { - return findAncestorRowAffectingFile((PermanentGraphImpl)permanentGraph, hash, visibleGraph, fileIndexData); + return findAncestorRowAffectingFile(permanentGraph as PermanentGraphImpl, hash, visibleGraph, fileIndexData) } } - return 0; + return 0 } - @Nullable - private Hash getHead(@NotNull DataPack pack) { - CompressedRefs refs = pack.getRefsModel().getAllRefsByRoot().get(myRoot); - Optional headOptional = refs.streamBranches().filter(br -> br.getName().equals("HEAD")).findFirst(); - if (headOptional.isPresent()) { - VcsRef head = headOptional.get(); - assert head.getRoot().equals(myRoot); - return head.getCommitHash(); + private fun getHead(pack: DataPack): Hash? { + val refs = pack.refsModel.allRefsByRoot[root] + val headOptional = refs!!.streamBranches().filter { br -> br.name == "HEAD" }.findFirst() + if (headOptional.isPresent) { + val head = headOptional.get() + assert(head.root == root) + return head.commitHash } - return null; + return null } - private int findAncestorRowAffectingFile(@NotNull PermanentGraphImpl permanentGraph, - @NotNull Hash hash, - @NotNull VisibleGraph visibleGraph, - @NotNull IndexDataGetter.FileNamesData fileNamesData) { - Ref result = new Ref<>(); + private fun findAncestorRowAffectingFile(permanentGraph: PermanentGraphImpl, + hash: Hash, + visibleGraph: VisibleGraph, + fileNamesData: IndexDataGetter.FileNamesData): Int { + val result = Ref() - PermanentCommitsInfoImpl commitsInfo = permanentGraph.getPermanentCommitsInfo(); - ReachableNodes reachableNodes = new ReachableNodes(LinearGraphUtils.asLiteLinearGraph(permanentGraph.getLinearGraph())); - reachableNodes.walk(Collections.singleton(commitsInfo.getNodeId(myStorage.getCommitIndex(hash, myRoot))), true, - currentNode -> { - int id = commitsInfo.getCommitId(currentNode); - if (fileNamesData.affects(id, myFilePath)) { - result.set(currentNode); - return false; // stop walk, we have found it - } - return true; // continue walk - }); - - if (!result.isNull()) { - Integer rowIndex = visibleGraph.getVisibleRowIndex(commitsInfo.getCommitId(result.get())); - return assertNotNull(rowIndex); + val commitsInfo = permanentGraph.permanentCommitsInfo + val reachableNodes = ReachableNodes(LinearGraphUtils.asLiteLinearGraph(permanentGraph.linearGraph)) + reachableNodes.walk(setOf(commitsInfo.getNodeId(storage.getCommitIndex(hash, root))), true) { currentNode -> + val id = commitsInfo.getCommitId(currentNode) + if (fileNamesData.affects(id, filePath)) { + result.set(currentNode) + false // stop walk, we have found it + } + else { + true // continue walk + } } - return -1; + if (!result.isNull) { + val rowIndex = visibleGraph.getVisibleRowIndex(commitsInfo.getCommitId(result.get())) + return assertNotNull(rowIndex) + } + + return -1 + } + } + + companion object { + private val LOG = Logger.getInstance(FileHistoryFilterer::class.java) + + private fun getFilePath(filters: VcsLogFilterCollection): FilePath? { + val detailsFilters = filters.detailsFilters + if (detailsFilters.size != 1) { + return null + } + + val filter = notNull(getFirstItem(detailsFilters)) as? VcsLogStructureFilter ?: return null + + val files = filter.files + return if (files.size != 1) { + null + } + else notNull(getFirstItem(files)) + + } + + private fun getHash(filters: VcsLogFilterCollection): Hash? { + val revisionFilter = filters.get(VcsLogFilterCollection.REVISION_FILTER) ?: return null + + val heads = revisionFilter.heads + return if (heads.size != 1) { + null + } + else notNull(getFirstItem(heads)).hash + } + + @JvmStatic + fun createFilters(path: FilePath, + revision: Hash?, + root: VirtualFile, + showAllBranches: Boolean): VcsLogFilterCollection { + val fileFilter = VcsLogStructureFilterImpl(setOf(path)) + + if (revision != null) { + val revisionFilter = VcsLogRevisionFilterImpl.fromCommit(CommitId(revision, root)) + return VcsLogFilterCollectionImpl.VcsLogFilterCollectionBuilder(fileFilter, revisionFilter).build() + } + + val branchFilter = if (showAllBranches) null else VcsLogBranchFilterImpl.fromBranch("HEAD") + return VcsLogFilterCollectionImpl.VcsLogFilterCollectionBuilder(fileFilter, branchFilter).build() } } }