mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[vcs-log] extract root filter from structure filter
This commit is contained in:
@@ -45,6 +45,9 @@ public interface VcsLogFilterCollection {
|
||||
@Nullable
|
||||
VcsLogStructureFilter getStructureFilter();
|
||||
|
||||
@Nullable
|
||||
VcsLogRootFilter getRootFilter();
|
||||
|
||||
/**
|
||||
* Returns true if there are no filters in this collection.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.log;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Tells the log to filter by vcs roots.
|
||||
*/
|
||||
public interface VcsLogRootFilter extends VcsLogFilter {
|
||||
|
||||
/**
|
||||
* <p>Returns vcs roots that are visible.</p>
|
||||
*/
|
||||
@NotNull
|
||||
Collection<VirtualFile> getRoots();
|
||||
}
|
||||
@@ -26,14 +26,11 @@ import java.util.Collection;
|
||||
public interface VcsLogStructureFilter extends VcsLogDetailsFilter {
|
||||
|
||||
/**
|
||||
* <p>Returns files from the given VCS root, which are affected by matching commits, and folders containing such files.</p>
|
||||
* <p>Returns files which are affected by matching commits, and folders containing such files.</p>
|
||||
*
|
||||
* <p>That is: the commit A (made in the given VCS root) modifying file f.txt matches this filter,
|
||||
* if this method returns a set which includes a folder containing f.txt, or the file f.txt itself.</p>
|
||||
*/
|
||||
@NotNull
|
||||
Collection<VirtualFile> getFiles(@NotNull VirtualFile root);
|
||||
|
||||
Collection<VirtualFile> getRoots();
|
||||
|
||||
Collection<VirtualFile> getFiles();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.log;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class VcsLogRootFilterImpl implements VcsLogRootFilter {
|
||||
@NotNull private final Collection<VirtualFile> myRoots;
|
||||
|
||||
public VcsLogRootFilterImpl(@NotNull Collection<VirtualFile> roots) {
|
||||
myRoots = roots;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<VirtualFile> getRoots() {
|
||||
return myRoots;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.log.data;
|
||||
|
||||
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.VcsLogRootFilter;
|
||||
import com.intellij.vcs.log.VcsLogStructureFilter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
public class VcsLogFileFilterUtil {
|
||||
@NotNull
|
||||
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>();
|
||||
|
||||
for (VirtualFile file : files) {
|
||||
if (roots.contains(file)) {
|
||||
selectedRoots.add(file);
|
||||
}
|
||||
else {
|
||||
VirtualFile candidateAncestorRoot = null;
|
||||
for (VirtualFile root : roots) {
|
||||
if (VfsUtilCore.isAncestor(root, file, false)) {
|
||||
if (candidateAncestorRoot == null || VfsUtilCore.isAncestor(candidateAncestorRoot, root, false)) {
|
||||
candidateAncestorRoot = root;
|
||||
}
|
||||
}
|
||||
else if (VfsUtilCore.isAncestor(file, root, false)) {
|
||||
selectedRoots.add(root);
|
||||
}
|
||||
}
|
||||
|
||||
if (candidateAncestorRoot != null) {
|
||||
selectedFiles.putValue(candidateAncestorRoot, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Pair.create(selectedRoots, selectedFiles);
|
||||
}
|
||||
|
||||
@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());
|
||||
|
||||
if (structureFilter == null) {
|
||||
return Pair.create((Set<VirtualFile>)new HashSet<VirtualFile>(rootFilter.getRoots()), MultiMap.<VirtualFile, VirtualFile>create());
|
||||
}
|
||||
Pair<Set<VirtualFile>, MultiMap<VirtualFile, VirtualFile>> selectedRootsAndFiles = collectRoots(structureFilter.getFiles(), roots);
|
||||
if (rootFilter == null) {
|
||||
return selectedRootsAndFiles;
|
||||
}
|
||||
return Pair.create(ContainerUtil.union(new HashSet<VirtualFile>(rootFilter.getRoots()), selectedRootsAndFiles.first),
|
||||
selectedRootsAndFiles.second);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Set<VirtualFile> collectRoots(@NotNull Set<VirtualFile> roots,
|
||||
@Nullable VcsLogRootFilter rootFilter,
|
||||
@Nullable VcsLogStructureFilter structureFilter) {
|
||||
if (rootFilter == null && structureFilter == null) return null;
|
||||
|
||||
Pair<Set<VirtualFile>, MultiMap<VirtualFile, VirtualFile>> rootsAndFiles = collectRootsAndFiles(roots, rootFilter, structureFilter);
|
||||
return ContainerUtil.union(rootsAndFiles.first, rootsAndFiles.second.keySet());
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ public class VcsLogFiltererImpl implements VcsLogFilterer {
|
||||
@NotNull final PermanentGraph.SortType initialSortType,
|
||||
@NotNull final Consumer<VisiblePack> visiblePackConsumer) {
|
||||
myVisiblePackBuilder = new VisiblePackBuilder(providers, hashMap, topCommitsDetailsCache, detailsGetter);
|
||||
myFilters = new VcsLogFilterCollectionImpl(null, null, null, null, null, null);
|
||||
myFilters = new VcsLogFilterCollectionImpl(null, null, null, null, null, null, null);
|
||||
mySortType = initialSortType;
|
||||
|
||||
myTaskController = new SingleTaskController<Request, VisiblePack>(visiblePackConsumer) {
|
||||
|
||||
@@ -32,38 +32,28 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class VcsLogStructureFilterImpl implements VcsLogDetailsFilter, VcsLogStructureFilter {
|
||||
@NotNull private final Set<VirtualFile> myRoots;
|
||||
@NotNull private final MultiMap<VirtualFile, VirtualFile> myRootToFiles;
|
||||
@NotNull private final Set<VirtualFile> myFiles;
|
||||
|
||||
public VcsLogStructureFilterImpl(@NotNull Set<VirtualFile> roots,
|
||||
@NotNull MultiMap<VirtualFile, VirtualFile> rootToFiles) {
|
||||
myRoots = roots;
|
||||
myRootToFiles = rootToFiles;
|
||||
public VcsLogStructureFilterImpl(@NotNull Set<VirtualFile> files) {
|
||||
myFiles = files;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<VirtualFile> getFiles(@NotNull VirtualFile root) {
|
||||
return myRootToFiles.get(root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<VirtualFile> getRoots() {
|
||||
return ContainerUtil.union(myRoots, myRootToFiles.keySet());
|
||||
public Collection<VirtualFile> getFiles() {
|
||||
return myFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(@NotNull VcsCommitMetadata details) {
|
||||
if (myRoots.contains(details.getRoot())) return true;
|
||||
|
||||
if ((details instanceof VcsFullCommitDetails)) {
|
||||
for (Change change : ((VcsFullCommitDetails)details).getChanges()) {
|
||||
ContentRevision before = change.getBeforeRevision();
|
||||
if (before != null && matches(before.getFile().getPath(), myRootToFiles.get(details.getRoot()))) {
|
||||
if (before != null && matches(before.getFile().getPath())) {
|
||||
return true;
|
||||
}
|
||||
ContentRevision after = change.getAfterRevision();
|
||||
if (after != null && matches(after.getFile().getPath(), myRootToFiles.get(details.getRoot()))) {
|
||||
if (after != null && matches(after.getFile().getPath())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -74,47 +64,12 @@ public class VcsLogStructureFilterImpl implements VcsLogDetailsFilter, VcsLogStr
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matches(@NotNull final String path, @NotNull Collection<VirtualFile> files) {
|
||||
return ContainerUtil.find(files, new Condition<VirtualFile>() {
|
||||
private boolean matches(@NotNull final String path) {
|
||||
return ContainerUtil.find(myFiles, new Condition<VirtualFile>() {
|
||||
@Override
|
||||
public boolean value(VirtualFile file) {
|
||||
return FileUtil.isAncestor(file.getPath(), path, false);
|
||||
}
|
||||
}) != null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static VcsLogStructureFilterImpl build(@NotNull Collection<VirtualFile> files,
|
||||
@NotNull VcsLogDataPack dataPack) {
|
||||
Set<VirtualFile> roots = dataPack.getLogProviders().keySet();
|
||||
|
||||
Set<VirtualFile> selectedRoots = new HashSet<VirtualFile>();
|
||||
MultiMap<VirtualFile, VirtualFile> selectedFiles = new MultiMap<VirtualFile, VirtualFile>();
|
||||
|
||||
for (VirtualFile file : files) {
|
||||
if (roots.contains(file)) {
|
||||
// no need in details filter
|
||||
selectedRoots.add(file);
|
||||
}
|
||||
else {
|
||||
VirtualFile candidateAncestorRoot = null;
|
||||
for (VirtualFile root : roots) {
|
||||
if (VfsUtilCore.isAncestor(root, file, false)) {
|
||||
if (candidateAncestorRoot == null || VfsUtilCore.isAncestor(candidateAncestorRoot, root, false)) {
|
||||
candidateAncestorRoot = root;
|
||||
}
|
||||
}
|
||||
else if (VfsUtilCore.isAncestor(file, root, false)) {
|
||||
selectedRoots.add(root);
|
||||
}
|
||||
}
|
||||
|
||||
if (candidateAncestorRoot != null) {
|
||||
selectedFiles.putValue(candidateAncestorRoot, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new VcsLogStructureFilterImpl(selectedRoots, selectedFiles);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,13 @@ 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;
|
||||
import com.intellij.vcs.log.graph.PermanentGraph;
|
||||
import com.intellij.vcs.log.graph.VisibleGraph;
|
||||
import com.intellij.vcs.log.impl.VcsLogFilterCollectionImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -63,7 +65,7 @@ class VisiblePackBuilder {
|
||||
return Pair.create(applyHashFilter(dataPack, hashFilter.getHashes(), sortType), commitCount);
|
||||
}
|
||||
|
||||
Set<Integer> matchingHeads = getMatchingHeads(dataPack.getRefs(), filters);
|
||||
Set<Integer> matchingHeads = getMatchingHeads(dataPack.getRefs(), dataPack.getLogProviders().keySet(), filters);
|
||||
List<VcsLogDetailsFilter> detailsFilters = filters.getDetailsFilters();
|
||||
List<Hash> matchingCommits = null;
|
||||
boolean canRequestMore = false;
|
||||
@@ -105,8 +107,8 @@ class VisiblePackBuilder {
|
||||
}
|
||||
|
||||
private VisiblePack applyHashFilter(@NotNull DataPack dataPack,
|
||||
@NotNull Collection<String> hashes,
|
||||
@NotNull PermanentGraph.SortType sortType) {
|
||||
@NotNull Collection<String> hashes,
|
||||
@NotNull PermanentGraph.SortType sortType) {
|
||||
final Set<Integer> indices = ContainerUtil.map2SetNotNull(hashes, new Function<String, Integer>() {
|
||||
@Override
|
||||
public Integer fun(String partOfHash) {
|
||||
@@ -124,13 +126,39 @@ class VisiblePackBuilder {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Set<Integer> getMatchingHeads(@NotNull VcsLogRefs refs, @NotNull VcsLogFilterCollection filters) {
|
||||
private Set<Integer> getMatchingHeads(@NotNull VcsLogRefs refs, Set<VirtualFile> roots, @NotNull VcsLogFilterCollection filters) {
|
||||
VcsLogBranchFilter branchFilter = filters.getBranchFilter();
|
||||
if (branchFilter == null) {
|
||||
return null;
|
||||
VcsLogRootFilter rootFilter = filters.getRootFilter();
|
||||
VcsLogStructureFilter structureFilter = filters.getStructureFilter();
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
final Collection<String> branchNames = new HashSet<String>(branchFilter.getBranchNames());
|
||||
if (filteredByBranch == null) return filteredByFile;
|
||||
if (filteredByFile == null) return filteredByBranch;
|
||||
|
||||
return new HashSet<Integer>(ContainerUtil.intersection(filteredByBranch, filteredByFile));
|
||||
}
|
||||
|
||||
private Set<Integer> getMatchingHeads(@NotNull VcsLogRefs refs, @NotNull VcsLogBranchFilter filter) {
|
||||
final Collection<String> branchNames = new HashSet<String>(filter.getBranchNames());
|
||||
return new HashSet<Integer>(ContainerUtil.mapNotNull(refs.getBranches(), new Function<VcsRef, Integer>() {
|
||||
@Override
|
||||
public Integer fun(VcsRef ref) {
|
||||
@@ -142,6 +170,28 @@ 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()) {
|
||||
if (roots.contains(branch.getRoot())) {
|
||||
result.add(myHashMap.getCommitIndex(branch.getCommitHash()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Set<Integer> getMatchingHeads(@NotNull VcsLogRefs refs,
|
||||
@NotNull Set<VirtualFile> vcsRoots,
|
||||
@NotNull VcsLogStructureFilter filter) {
|
||||
Pair<Set<VirtualFile>, MultiMap<VirtualFile, VirtualFile>> roots = VcsLogFileFilterUtil.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,
|
||||
@@ -203,17 +253,28 @@ 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 =
|
||||
VcsLogFileFilterUtil.collectRootsAndFiles(providers.keySet(), rootFilter, structureFilter);
|
||||
|
||||
Collection<List<TimedVcsCommit>> logs = ContainerUtil.newArrayList();
|
||||
for (Map.Entry<VirtualFile, VcsLogProvider> entry : providers.entrySet()) {
|
||||
VirtualFile root = entry.getKey();
|
||||
|
||||
if (filterCollection.getStructureFilter() != null && !filterCollection.getStructureFilter().getRoots().contains(root)
|
||||
|| filterCollection.getUserFilter() != null && filterCollection.getUserFilter().getUserNames(root).isEmpty()) {
|
||||
if (!selectedRootsAndFiles.first.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;
|
||||
}
|
||||
|
||||
List<TimedVcsCommit> matchingCommits = entry.getValue().getCommitsMatchingFilter(root, filterCollection, maxCount);
|
||||
VcsLogFilterCollection rootSpecificCollection = filterCollection;
|
||||
if (rootSpecificCollection.getStructureFilter() != null) {
|
||||
rootSpecificCollection = replaceStructureFilter(filterCollection, new HashSet<VirtualFile>(selectedRootsAndFiles.second.get(root)));
|
||||
}
|
||||
|
||||
List<TimedVcsCommit> matchingCommits = entry.getValue().getCommitsMatchingFilter(root, rootSpecificCollection, maxCount);
|
||||
logs.add(matchingCommits);
|
||||
}
|
||||
|
||||
@@ -226,6 +287,15 @@ class VisiblePackBuilder {
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static VcsLogFilterCollection replaceStructureFilter(@NotNull VcsLogFilterCollection filterCollection,
|
||||
@NotNull Set<VirtualFile> files) {
|
||||
return new VcsLogFilterCollectionImpl(filterCollection.getBranchFilter(), filterCollection.getUserFilter(),
|
||||
filterCollection.getHashFilter(), filterCollection.getDateFilter(),
|
||||
filterCollection.getTextFilter(), new VcsLogStructureFilterImpl(files),
|
||||
filterCollection.getRootFilter());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Condition<Integer> getFilterFromCommits(@Nullable List<Hash> filteredCommits) {
|
||||
if (filteredCommits == null) {
|
||||
|
||||
+11
-1
@@ -31,19 +31,22 @@ public class VcsLogFilterCollectionImpl implements VcsLogFilterCollection {
|
||||
@Nullable private final VcsLogDateFilter myDateFilter;
|
||||
@Nullable private final VcsLogTextFilter myTextFilter;
|
||||
@Nullable private final VcsLogStructureFilter myStructureFilter;
|
||||
@Nullable private final VcsLogRootFilter myRootFilter;
|
||||
|
||||
public VcsLogFilterCollectionImpl(@Nullable VcsLogBranchFilter branchFilter,
|
||||
@Nullable VcsLogUserFilter userFilter,
|
||||
@Nullable VcsLogHashFilter hashFilter,
|
||||
@Nullable VcsLogDateFilter dateFilter,
|
||||
@Nullable VcsLogTextFilter textFilter,
|
||||
@Nullable VcsLogStructureFilter structureFilter) {
|
||||
@Nullable VcsLogStructureFilter structureFilter,
|
||||
@Nullable VcsLogRootFilter rootFilter) {
|
||||
myBranchFilter = branchFilter;
|
||||
myUserFilter = userFilter;
|
||||
myHashFilter = hashFilter;
|
||||
myDateFilter = dateFilter;
|
||||
myTextFilter = textFilter;
|
||||
myStructureFilter = structureFilter;
|
||||
myRootFilter = rootFilter;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -82,6 +85,13 @@ public class VcsLogFilterCollectionImpl implements VcsLogFilterCollection {
|
||||
return myStructureFilter;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public VcsLogRootFilter getRootFilter() {
|
||||
return myRootFilter;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return myBranchFilter == null && getDetailsFilters().isEmpty();
|
||||
|
||||
@@ -47,6 +47,11 @@ class FilterModel<Filter extends VcsLogFilter> {
|
||||
return myFilter;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Computable<VcsLogDataPack> getDataPackProvider() {
|
||||
return myDataPackProvider;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
VcsLogDataPack getDataPack() {
|
||||
return myDataPackProvider.compute();
|
||||
|
||||
+24
-28
@@ -23,8 +23,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcs.log.VcsLogDataPack;
|
||||
import com.intellij.vcs.log.VcsLogStructureFilter;
|
||||
import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.data.VcsLogStructureFilterImpl;
|
||||
import com.intellij.vcs.log.ui.VcsStructureChooser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -32,18 +31,17 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogStructureFilter> {
|
||||
|
||||
class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogFileFilter> {
|
||||
private static final int FILTER_LABEL_LENGTH = 20;
|
||||
|
||||
public StructureFilterPopupComponent(@NotNull FilterModel<VcsLogStructureFilter> filterModel) {
|
||||
public StructureFilterPopupComponent(@NotNull FilterModel<VcsLogFileFilter> filterModel) {
|
||||
super("Structure", filterModel);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getText(@NotNull VcsLogStructureFilter filter) {
|
||||
Collection<VirtualFile> files = getAllFiles(myFilterModel.getDataPack(), filter);
|
||||
protected String getText(@NotNull VcsLogFileFilter filter) {
|
||||
Collection<VirtualFile> files = getAllFiles(filter);
|
||||
if (files.size() == 0) {
|
||||
return ALL;
|
||||
}
|
||||
@@ -58,20 +56,15 @@ class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogStructure
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected String getToolTip(@NotNull VcsLogStructureFilter filter) {
|
||||
return getToolTip(getAllFiles(myFilterModel.getDataPack(), filter));
|
||||
protected String getToolTip(@NotNull VcsLogFileFilter filter) {
|
||||
return getToolTip(getAllFiles(filter));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Collection<VirtualFile> getAllFiles(@NotNull VcsLogDataPack dataPack, @NotNull VcsLogStructureFilter filter) {
|
||||
private static Collection<VirtualFile> getAllFiles(@NotNull VcsLogFileFilter filter) {
|
||||
Collection<VirtualFile> result = ContainerUtil.newArrayList();
|
||||
for (VirtualFile root : dataPack.getLogProviders().keySet()) {
|
||||
Collection<VirtualFile> files = filter.getFiles(root);
|
||||
result.addAll(files);
|
||||
if (files.isEmpty() && filter.getRoots().contains(root)) {
|
||||
result.add(root);
|
||||
}
|
||||
}
|
||||
if (filter.getRootFilter() != null) result.addAll(filter.getRootFilter().getRoots());
|
||||
if (filter.getStructureFilter() != null) result.addAll(filter.getStructureFilter().getFiles());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -90,8 +83,9 @@ class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogStructure
|
||||
}
|
||||
|
||||
private boolean isVisible(@NotNull VirtualFile root) {
|
||||
if (myFilterModel.getFilter() != null) {
|
||||
return myFilterModel.getFilter().getRoots().contains(root);
|
||||
VcsLogFileFilter filter = myFilterModel.getFilter();
|
||||
if (filter != null && filter.getRootFilter() != null) {
|
||||
return filter.getRootFilter().getRoots().contains(root);
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
@@ -101,9 +95,11 @@ class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogStructure
|
||||
private void setVisible(@NotNull VirtualFile root, boolean visible) {
|
||||
Set<VirtualFile> roots = myFilterModel.getDataPack().getLogProviders().keySet();
|
||||
|
||||
VcsLogFileFilter previousFilter = myFilterModel.getFilter();
|
||||
VcsLogRootFilter rootFilter = previousFilter != null ? previousFilter.getRootFilter() : null;
|
||||
|
||||
Collection<VirtualFile> visibleRoots;
|
||||
VcsLogStructureFilter previousFilter = myFilterModel.getFilter();
|
||||
if (previousFilter == null) {
|
||||
if (rootFilter == null) {
|
||||
if (visible) {
|
||||
visibleRoots = roots;
|
||||
}
|
||||
@@ -113,14 +109,13 @@ class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogStructure
|
||||
}
|
||||
else {
|
||||
if (visible) {
|
||||
visibleRoots = ContainerUtil.union(new HashSet<VirtualFile>(myFilterModel.getFilter().getRoots()), Collections.singleton(root));
|
||||
visibleRoots = ContainerUtil.union(new HashSet<VirtualFile>(rootFilter.getRoots()), Collections.singleton(root));
|
||||
}
|
||||
else {
|
||||
visibleRoots = ContainerUtil.subtract(myFilterModel.getFilter().getRoots(), Collections.singleton(root));
|
||||
visibleRoots = ContainerUtil.subtract(rootFilter.getRoots(), Collections.singleton(root));
|
||||
}
|
||||
}
|
||||
myFilterModel.setFilter(VcsLogStructureFilterImpl.build(visibleRoots, myFilterModel.getDataPack()));
|
||||
// todo if there are some non-roots in structure filter they will get lost
|
||||
myFilterModel.setFilter(new VcsLogFileFilter(previousFilter != null ? previousFilter.getStructureFilter() : null, new VcsLogRootFilterImpl(visibleRoots)));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -169,12 +164,13 @@ class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogStructure
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
Project project = e.getRequiredData(CommonDataKeys.PROJECT);
|
||||
VcsLogDataPack dataPack = myFilterModel.getDataPack();
|
||||
VcsLogStructureFilter filter = myFilterModel.getFilter();
|
||||
Collection<VirtualFile> files = filter == null ? Collections.<VirtualFile>emptySet() : getAllFiles(dataPack, filter);
|
||||
VcsLogFileFilter filter = myFilterModel.getFilter();
|
||||
VcsLogRootFilter rootFilter = filter == null ? null : filter.getRootFilter();
|
||||
Collection<VirtualFile> files = filter == null ? Collections.<VirtualFile>emptySet() : getAllFiles(filter);
|
||||
VcsStructureChooser chooser = new VcsStructureChooser(project, "Select Files or Folders to Filter", files,
|
||||
new ArrayList<VirtualFile>(dataPack.getLogProviders().keySet()));
|
||||
if (chooser.showAndGet()) {
|
||||
myFilterModel.setFilter(VcsLogStructureFilterImpl.build(chooser.getSelectedFiles(), dataPack));
|
||||
myFilterModel.setFilter(new VcsLogFileFilter(new VcsLogStructureFilterImpl(new HashSet<VirtualFile>(chooser.getSelectedFiles())), rootFilter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-9
@@ -31,11 +31,10 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import com.intellij.ui.SearchTextFieldWithStoredHistory;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.data.VcsLogStructureFilterImpl;
|
||||
import com.intellij.vcs.log.data.VcsLogUiProperties;
|
||||
import com.intellij.vcs.log.data.*;
|
||||
import com.intellij.vcs.log.impl.VcsLogFilterCollectionImpl;
|
||||
import com.intellij.vcs.log.impl.VcsLogHashFilterImpl;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
@@ -49,7 +48,9 @@ import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*/
|
||||
@@ -68,7 +69,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
|
||||
@NotNull private final BranchFilterModel myBranchFilterModel;
|
||||
@NotNull private final FilterModel<VcsLogUserFilter> myUserFilterModel;
|
||||
@NotNull private final FilterModel<VcsLogDateFilter> myDateFilterModel;
|
||||
@NotNull private final FilterModel<VcsLogStructureFilter> myStructureFilterModel;
|
||||
@NotNull private final FilterModel<VcsLogFileFilter> myStructureFilterModel;
|
||||
@NotNull private final TextFilterModel myTextFilterModel;
|
||||
|
||||
public VcsLogClassicFilterUi(@NotNull VcsLogUiImpl ui,
|
||||
@@ -90,7 +91,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
|
||||
myBranchFilterModel = new BranchFilterModel(dataPackGetter);
|
||||
myUserFilterModel = new FilterModel<VcsLogUserFilter>(dataPackGetter);
|
||||
myDateFilterModel = new FilterModel<VcsLogDateFilter>(dataPackGetter);
|
||||
myStructureFilterModel = new FilterModel<VcsLogStructureFilter>(dataPackGetter);
|
||||
myStructureFilterModel = new FilterModel<VcsLogFileFilter>(dataPackGetter);
|
||||
myTextFilterModel = new TextFilterModel(dataPackGetter);
|
||||
|
||||
updateUiOnFilterChange();
|
||||
@@ -103,7 +104,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
|
||||
@Override
|
||||
public void run() {
|
||||
myUi.applyFiltersAndUpdateUi();
|
||||
myBranchFilterModel.onStructureFilterChanged(myStructureFilterModel.getFilter());
|
||||
myBranchFilterModel.onStructureFilterChanged(new HashSet<VirtualFile>(myLogDataHolder.getRoots()), myStructureFilterModel.getFilter());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -157,7 +158,8 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
|
||||
filtersFromText.second,
|
||||
myDateFilterModel.getFilter(),
|
||||
filtersFromText.first,
|
||||
myStructureFilterModel.getFilter());
|
||||
myStructureFilterModel.getFilter() == null ? null : myStructureFilterModel.getFilter().getStructureFilter(),
|
||||
myStructureFilterModel.getFilter() == null ? null : myStructureFilterModel.getFilter().getRootFilter());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -281,11 +283,11 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
public void onStructureFilterChanged(@Nullable VcsLogStructureFilter filter) {
|
||||
public void onStructureFilterChanged(@NotNull Set<VirtualFile> roots, @Nullable VcsLogFileFilter filter) {
|
||||
if (filter == null) {
|
||||
myVisibleRoots = null;
|
||||
} else {
|
||||
myVisibleRoots = filter.getRoots();
|
||||
myVisibleRoots = VcsLogFileFilterUtil.collectRoots(roots, filter.getRootFilter(), filter.getStructureFilter());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.log.ui.filter;
|
||||
|
||||
import com.intellij.vcs.log.VcsLogFilter;
|
||||
import com.intellij.vcs.log.VcsLogRootFilter;
|
||||
import com.intellij.vcs.log.VcsLogStructureFilter;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class VcsLogFileFilter implements VcsLogFilter {
|
||||
@Nullable private final VcsLogStructureFilter myStructureFilter;
|
||||
@Nullable private final VcsLogRootFilter myRootFilter;
|
||||
|
||||
public VcsLogFileFilter(@Nullable VcsLogStructureFilter structureFilter, @Nullable VcsLogRootFilter rootFilter) {
|
||||
myStructureFilter = structureFilter;
|
||||
myRootFilter = rootFilter;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VcsLogStructureFilter getStructureFilter() {
|
||||
return myStructureFilter;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VcsLogRootFilter getRootFilter() {
|
||||
return myRootFilter;
|
||||
}
|
||||
}
|
||||
@@ -158,9 +158,9 @@ public class BranchesPanel extends JPanel {
|
||||
}
|
||||
|
||||
public void onFiltersChange(@NotNull VcsLogFilterCollection filters) {
|
||||
VcsLogStructureFilter structureFilter = filters.getStructureFilter();
|
||||
if (structureFilter != null) {
|
||||
myRoots = structureFilter.getRoots();
|
||||
VcsLogRootFilter rootFilter = filters.getRootFilter();
|
||||
if (rootFilter != null) {
|
||||
myRoots = rootFilter.getRoots();
|
||||
}
|
||||
else {
|
||||
myRoots = null;
|
||||
|
||||
@@ -136,6 +136,12 @@ class GitBekParentFixer {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public VcsLogRootFilter getRootFilter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
|
||||
@@ -440,7 +440,7 @@ public class GitLogProvider implements VcsLogProvider {
|
||||
|
||||
// note: structure filter must be the last parameter, because it uses "--" which separates parameters from paths
|
||||
if (filterCollection.getStructureFilter() != null) {
|
||||
Collection<VirtualFile> files = filterCollection.getStructureFilter().getFiles(root);
|
||||
Collection<VirtualFile> files = filterCollection.getStructureFilter().getFiles();
|
||||
if (!files.isEmpty()) {
|
||||
filterParameters.add("--simplify-merges");
|
||||
filterParameters.add("--");
|
||||
|
||||
@@ -233,7 +233,7 @@ public class HgLogProvider implements VcsLogProvider {
|
||||
}
|
||||
|
||||
if (filterCollection.getStructureFilter() != null) {
|
||||
for (VirtualFile file : filterCollection.getStructureFilter().getFiles(root)) {
|
||||
for (VirtualFile file : filterCollection.getStructureFilter().getFiles()) {
|
||||
filterParameters.add(file.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user