[vcs-log] fix filtering by other than root files and generally make more clear what is going on inside vcs log file filter

This commit is contained in:
Julia Beliaeva
2014-12-05 18:58:04 +03:00
parent 98dc9e2de7
commit f467332b8f
4 changed files with 56 additions and 65 deletions
@@ -19,15 +19,17 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.MultiMap;
import com.intellij.vcs.log.VcsLogFilter;
import com.intellij.vcs.log.VcsLogFilterCollection;
import com.intellij.vcs.log.VcsLogRootFilter;
import com.intellij.vcs.log.VcsLogStructureFilter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class VcsLogFileFilter implements VcsLogFilter {
@@ -39,9 +41,19 @@ public class VcsLogFileFilter implements VcsLogFilter {
myRootFilter = rootFilter;
}
@Nullable
public VcsLogStructureFilter getStructureFilter() {
return myStructureFilter;
}
@Nullable
public VcsLogRootFilter getRootFilter() {
return myRootFilter;
}
@NotNull
static Pair<Set<VirtualFile>, MultiMap<VirtualFile, VirtualFile>> collectRoots(@NotNull Collection<VirtualFile> files,
@NotNull Set<VirtualFile> roots) {
private static Pair<Set<VirtualFile>, MultiMap<VirtualFile, VirtualFile>> collectRoots(@NotNull Collection<VirtualFile> files,
@NotNull Set<VirtualFile> roots) {
Set<VirtualFile> selectedRoots = new HashSet<VirtualFile>();
MultiMap<VirtualFile, VirtualFile> selectedFiles = new MultiMap<VirtualFile, VirtualFile>();
@@ -71,40 +83,46 @@ public class VcsLogFileFilter implements VcsLogFilter {
return Pair.create(selectedRoots, selectedFiles);
}
// collect "nu voobche vse" (there is no english translation for this expression =) ) roots that might be visible
// if filters unset returns just all roots
@NotNull
public static Pair<Set<VirtualFile>, MultiMap<VirtualFile, VirtualFile>> collectRootsAndFiles(@NotNull Set<VirtualFile> roots,
@Nullable VcsLogRootFilter rootFilter,
@Nullable VcsLogStructureFilter structureFilter) {
if (rootFilter == null && structureFilter == null) return Pair.create(roots, MultiMap.<VirtualFile, VirtualFile>create());
public static Set<VirtualFile> getAllVisibleRoots(@NotNull Collection<VirtualFile> roots, @NotNull VcsLogFilterCollection filters) {
return getAllVisibleRoots(roots, filters.getRootFilter(), filters.getStructureFilter());
}
if (structureFilter == null) {
return Pair.create((Set<VirtualFile>)new HashSet<VirtualFile>(rootFilter.getRoots()), MultiMap.<VirtualFile, VirtualFile>create());
// same as other getAllVisibleRoots
@NotNull
public static Set<VirtualFile> getAllVisibleRoots(@NotNull Collection<VirtualFile> roots, @NotNull VcsLogFileFilter filter) {
return getAllVisibleRoots(roots, filter.getRootFilter(), filter.getStructureFilter());
}
private static Set<VirtualFile> getAllVisibleRoots(@NotNull Collection<VirtualFile> roots, @Nullable VcsLogRootFilter rootFilter, @Nullable VcsLogStructureFilter structureFilter) {
if (rootFilter == null && structureFilter == null) return new HashSet<VirtualFile>(roots);
// should not we, like, intersect here?
Set<VirtualFile> result = new HashSet<VirtualFile>();
if (rootFilter != null) {
result.addAll(rootFilter.getRoots());
}
Pair<Set<VirtualFile>, MultiMap<VirtualFile, VirtualFile>> selectedRootsAndFiles = collectRoots(structureFilter.getFiles(), roots);
if (rootFilter == null) {
return selectedRootsAndFiles;
if (structureFilter != null) {
Pair<Set<VirtualFile>, MultiMap<VirtualFile, VirtualFile>> rootsAndFiles = collectRoots(structureFilter.getFiles(), new HashSet<VirtualFile>(roots));
result.addAll(ContainerUtil.union(rootsAndFiles.first, rootsAndFiles.second.keySet()));
}
return Pair.create(ContainerUtil.union(new HashSet<VirtualFile>(rootFilter.getRoots()), selectedRootsAndFiles.first),
selectedRootsAndFiles.second);
return result;
}
@Nullable
public static Set<VirtualFile> collectRoots(@NotNull Set<VirtualFile> roots,
@Nullable VcsLogRootFilter rootFilter,
@Nullable VcsLogStructureFilter structureFilter) {
if (rootFilter == null && structureFilter == null) return null;
// for given root returns files that are selected in it
// if a root is visible as a whole returns empty set
// same if root is invisible as a whole
// so check that before calling this method
@NotNull
public static Set<VirtualFile> getFilteredFilesForRoot(@NotNull VirtualFile root, VcsLogFilterCollection filterCollection) {
if (filterCollection.getStructureFilter() == null) return Collections.emptySet();
Pair<Set<VirtualFile>, MultiMap<VirtualFile, VirtualFile>> rootsAndFiles = collectRootsAndFiles(roots, rootFilter, structureFilter);
return ContainerUtil.union(rootsAndFiles.first, rootsAndFiles.second.keySet());
}
Pair<Set<VirtualFile>, MultiMap<VirtualFile, VirtualFile>> rootsAndFiles =
collectRoots(filterCollection.getStructureFilter().getFiles(), Collections.singleton(root));
@Nullable
public VcsLogStructureFilter getStructureFilter() {
return myStructureFilter;
}
@Nullable
public VcsLogRootFilter getRootFilter() {
return myRootFilter;
return new HashSet<VirtualFile>(rootsAndFiles.second.get(root));
}
}
@@ -24,7 +24,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.ui.UIUtil;
import com.intellij.vcs.log.*;
import com.intellij.vcs.log.graph.GraphCommit;
@@ -133,23 +132,13 @@ class VisiblePackBuilder {
if (branchFilter == null && rootFilter == null && structureFilter == null) return null;
Set<Integer> filteredByFile = null;
Set<Integer> filteredByBranch = null;
if (branchFilter != null) {
filteredByBranch = getMatchingHeads(refs, branchFilter);
}
if (rootFilter != null) {
filteredByFile = getMatchingHeads(refs, rootFilter);
}
if (structureFilter != null) {
if (filteredByFile == null) {
filteredByFile = getMatchingHeads(refs, roots, structureFilter);
}
else {
filteredByFile = ContainerUtil.union(filteredByFile, getMatchingHeads(refs, roots, structureFilter));
}
}
Set<Integer> filteredByFile = getMatchingHeads(refs, VcsLogFileFilter.getAllVisibleRoots(roots, filters));
if (filteredByBranch == null) return filteredByFile;
if (filteredByFile == null) return filteredByBranch;
@@ -170,11 +159,6 @@ class VisiblePackBuilder {
}));
}
private Set<Integer> getMatchingHeads(@NotNull VcsLogRefs refs, @NotNull VcsLogRootFilter filter) {
Collection<VirtualFile> roots = filter.getRoots();
return getMatchingHeads(refs, roots);
}
private Set<Integer> getMatchingHeads(@NotNull VcsLogRefs refs, @NotNull Collection<VirtualFile> roots) {
Set<Integer> result = new HashSet<Integer>();
for (VcsRef branch : refs.getBranches()) {
@@ -185,13 +169,6 @@ class VisiblePackBuilder {
return result;
}
private Set<Integer> getMatchingHeads(@NotNull VcsLogRefs refs,
@NotNull Set<VirtualFile> vcsRoots,
@NotNull VcsLogStructureFilter filter) {
Pair<Set<VirtualFile>, MultiMap<VirtualFile, VirtualFile>> roots = VcsLogFileFilter.collectRoots(filter.getFiles(), vcsRoots);
return getMatchingHeads(refs, ContainerUtil.union(roots.first, roots.second.keySet()));
}
@NotNull
private List<Hash> filterInMemory(@NotNull PermanentGraph<Integer> permanentGraph,
@NotNull List<VcsLogDetailsFilter> detailsFilters,
@@ -253,25 +230,21 @@ class VisiblePackBuilder {
private static List<Hash> getFilteredDetailsFromTheVcs(@NotNull Map<VirtualFile, VcsLogProvider> providers,
@NotNull VcsLogFilterCollection filterCollection,
int maxCount) throws VcsException {
VcsLogRootFilter rootFilter = filterCollection.getRootFilter();
VcsLogStructureFilter structureFilter = filterCollection.getStructureFilter();
Pair<Set<VirtualFile>, MultiMap<VirtualFile, VirtualFile>> selectedRootsAndFiles =
VcsLogFileFilter.collectRootsAndFiles(providers.keySet(), rootFilter, structureFilter);
Set<VirtualFile> visibleRoots = VcsLogFileFilter.getAllVisibleRoots(providers.keySet(), filterCollection);
Collection<List<TimedVcsCommit>> logs = ContainerUtil.newArrayList();
for (Map.Entry<VirtualFile, VcsLogProvider> entry : providers.entrySet()) {
VirtualFile root = entry.getKey();
if (!selectedRootsAndFiles.first.contains(root) ||
filterCollection.getUserFilter() != null && filterCollection.getUserFilter().getUserNames(root).isEmpty()) {
if (!visibleRoots.contains(root) ||
(filterCollection.getUserFilter() != null && filterCollection.getUserFilter().getUserNames(root).isEmpty())) {
// there is a structure or user filter, but it doesn't match this root
continue;
}
VcsLogFilterCollection rootSpecificCollection = filterCollection;
if (rootSpecificCollection.getStructureFilter() != null) {
rootSpecificCollection = replaceStructureFilter(filterCollection, new HashSet<VirtualFile>(selectedRootsAndFiles.second.get(root)));
rootSpecificCollection = replaceStructureFilter(filterCollection, new HashSet<VirtualFile>(VcsLogFileFilter.getFilteredFilesForRoot(root, filterCollection)));
}
List<TimedVcsCommit> matchingCommits = entry.getValue().getCommitsMatchingFilter(root, rootSpecificCollection, maxCount);
@@ -286,7 +286,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
if (filter == null) {
myVisibleRoots = null;
} else {
myVisibleRoots = VcsLogFileFilter.collectRoots(roots, filter.getRootFilter(), filter.getStructureFilter());
myVisibleRoots = VcsLogFileFilter.getAllVisibleRoots(roots, filter);
}
}
@@ -157,7 +157,7 @@ public class BranchesPanel extends JPanel {
}
public void onFiltersChange(@NotNull VcsLogFilterCollection filters) {
myRoots = VcsLogFileFilter.collectRoots(new HashSet<VirtualFile>(myDataHolder.getRoots()), filters.getRootFilter(), filters.getStructureFilter());
myRoots = VcsLogFileFilter.getAllVisibleRoots(myDataHolder.getRoots(), filters);
getParent().repaint();
}