mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[file-history] convert FileHistoryFilterer to kotlin
This commit is contained in:
@@ -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<VirtualFile, VcsLogProvider> 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<VisiblePack, CommitCountStage> {
|
||||
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<VisiblePack, CommitCountStage> 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<VcsLogDetailsFilter> detailsFilters = filters.getDetailsFilters();
|
||||
if (detailsFilters.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
fun filter(dataPack: DataPack,
|
||||
sortType: PermanentGraph.SortType,
|
||||
filters: VcsLogFilterCollection,
|
||||
commitCount: CommitCountStage): Pair<VisiblePack, CommitCountStage> {
|
||||
val start = System.currentTimeMillis()
|
||||
|
||||
VcsLogDetailsFilter filter = notNull(getFirstItem(detailsFilters));
|
||||
if (!(filter instanceof VcsLogStructureFilter)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Collection<FilePath> 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<CommitId> 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<VisiblePack, CommitCountStage> 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<VcsFileRevision> 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<Integer, FilePath> pathsMap = ContainerUtil.newHashMap();
|
||||
VisibleGraph<Integer> visibleGraph;
|
||||
val pathsMap = ContainerUtil.newHashMap<Int, FilePath>()
|
||||
val visibleGraph: VisibleGraph<Int>
|
||||
|
||||
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<GraphCommit<Integer>> commits = ContainerUtil.newArrayListWithCapacity(revisions.size());
|
||||
val commits = ContainerUtil.newArrayListWithCapacity<GraphCommit<Int>>(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<VirtualFile, CompressedRefs> refs = getFilteredRefs(dataPack);
|
||||
Map<VirtualFile, VcsLogProvider> providers = ContainerUtil.newHashMap(Pair.create(myRoot, myLogProviders.get(myRoot)));
|
||||
val refs = getFilteredRefs(dataPack)
|
||||
val providers = ContainerUtil.newHashMap(Pair.create<VirtualFile, VcsLogProvider>(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<VirtualFile, CompressedRefs> getFilteredRefs(@NotNull DataPack dataPack) {
|
||||
Map<VirtualFile, CompressedRefs> refs = ContainerUtil.newHashMap();
|
||||
CompressedRefs compressedRefs = dataPack.getRefsModel().getAllRefsByRoot().get(myRoot);
|
||||
private fun getFilteredRefs(dataPack: DataPack): Map<VirtualFile, CompressedRefs> {
|
||||
val refs = ContainerUtil.newHashMap<VirtualFile, CompressedRefs>()
|
||||
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<Integer> matchingHeads = myVcsLogFilterer.getMatchingHeads(dataPack.getRefsModel(), Collections.singleton(myRoot), filters);
|
||||
IndexDataGetter.FileNamesData data = myIndexDataGetter.buildFileNamesData(myFilePath);
|
||||
VisibleGraph<Integer> 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<Integer, FilePath> pathsMap = null;
|
||||
if (visibleGraph.getVisibleCommitCount() > 0) {
|
||||
if (visibleGraph instanceof VisibleGraphImpl) {
|
||||
int row = getCurrentRow(dataPack, visibleGraph, data);
|
||||
var pathsMap: Map<Int, FilePath>? = null
|
||||
if (visibleGraph.visibleCommitCount > 0) {
|
||||
if (visibleGraph is VisibleGraphImpl<*>) {
|
||||
val row = getCurrentRow(dataPack, visibleGraph, data)
|
||||
if (row >= 0) {
|
||||
FileHistoryRefiner refiner = new FileHistoryRefiner((VisibleGraphImpl<Integer>)visibleGraph, data);
|
||||
if (refiner.refine(row, myFilePath)) {
|
||||
val refiner = FileHistoryRefiner(visibleGraph as VisibleGraphImpl<Int>, 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<Integer> graph) {
|
||||
private fun reindexFirstCommitsIfNeeded(graph: VisibleGraph<Int>) {
|
||||
// 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<Integer> visibleGraph,
|
||||
@NotNull IndexDataGetter.FileNamesData fileIndexData) {
|
||||
PermanentGraph<Integer> permanentGraph = pack.getPermanentGraph();
|
||||
if (permanentGraph instanceof PermanentGraphImpl) {
|
||||
Hash hash = myHash != null ? myHash : getHead(pack);
|
||||
private fun getCurrentRow(pack: DataPack,
|
||||
visibleGraph: VisibleGraph<Int>,
|
||||
fileIndexData: IndexDataGetter.FileNamesData): Int {
|
||||
val permanentGraph = pack.permanentGraph
|
||||
if (permanentGraph is PermanentGraphImpl<*>) {
|
||||
val hash = hash ?: getHead(pack)
|
||||
if (hash != null) {
|
||||
return findAncestorRowAffectingFile((PermanentGraphImpl<Integer>)permanentGraph, hash, visibleGraph, fileIndexData);
|
||||
return findAncestorRowAffectingFile(permanentGraph as PermanentGraphImpl<Int>, hash, visibleGraph, fileIndexData)
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Hash getHead(@NotNull DataPack pack) {
|
||||
CompressedRefs refs = pack.getRefsModel().getAllRefsByRoot().get(myRoot);
|
||||
Optional<VcsRef> 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<Integer> permanentGraph,
|
||||
@NotNull Hash hash,
|
||||
@NotNull VisibleGraph<Integer> visibleGraph,
|
||||
@NotNull IndexDataGetter.FileNamesData fileNamesData) {
|
||||
Ref<Integer> result = new Ref<>();
|
||||
private fun findAncestorRowAffectingFile(permanentGraph: PermanentGraphImpl<Int>,
|
||||
hash: Hash,
|
||||
visibleGraph: VisibleGraph<Int>,
|
||||
fileNamesData: IndexDataGetter.FileNamesData): Int {
|
||||
val result = Ref<Int>()
|
||||
|
||||
PermanentCommitsInfoImpl<Integer> 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user