diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterCollection.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterCollection.java
index 65b999f4c4db..365d9968010d 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterCollection.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterCollection.java
@@ -45,6 +45,9 @@ public interface VcsLogFilterCollection {
@Nullable
VcsLogStructureFilter getStructureFilter();
+ @Nullable
+ VcsLogRootFilter getRootFilter();
+
/**
* Returns true if there are no filters in this collection.
*/
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogRootFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogRootFilter.java
new file mode 100644
index 000000000000..7720d812ea71
--- /dev/null
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogRootFilter.java
@@ -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 {
+
+ /**
+ *
Returns vcs roots that are visible.
+ */
+ @NotNull
+ Collection getRoots();
+}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogStructureFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogStructureFilter.java
index bdfd0d1701a4..44adc30a925e 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogStructureFilter.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogStructureFilter.java
@@ -26,14 +26,11 @@ import java.util.Collection;
public interface VcsLogStructureFilter extends VcsLogDetailsFilter {
/**
- * Returns files from the given VCS root, which are affected by matching commits, and folders containing such files.
+ * Returns files which are affected by matching commits, and folders containing such files.
*
* 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.
*/
@NotNull
- Collection getFiles(@NotNull VirtualFile root);
-
- Collection getRoots();
-
+ Collection getFiles();
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/VcsLogRootFilterImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/VcsLogRootFilterImpl.java
new file mode 100644
index 000000000000..82abf2fc3f32
--- /dev/null
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/VcsLogRootFilterImpl.java
@@ -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 myRoots;
+
+ public VcsLogRootFilterImpl(@NotNull Collection roots) {
+ myRoots = roots;
+ }
+
+ @NotNull
+ @Override
+ public Collection getRoots() {
+ return myRoots;
+ }
+}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFileFilterUtil.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFileFilterUtil.java
new file mode 100644
index 000000000000..d73ae9c935a0
--- /dev/null
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFileFilterUtil.java
@@ -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, MultiMap> collectRoots(@NotNull Collection files,
+ @NotNull Set roots) {
+ Set selectedRoots = new HashSet();
+ MultiMap selectedFiles = new MultiMap();
+
+ 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, MultiMap> collectRootsAndFiles(@NotNull Set roots,
+ @Nullable VcsLogRootFilter rootFilter,
+ @Nullable VcsLogStructureFilter structureFilter) {
+ if (rootFilter == null && structureFilter == null) return Pair.create(roots, MultiMap.create());
+
+ if (structureFilter == null) {
+ return Pair.create((Set)new HashSet(rootFilter.getRoots()), MultiMap.create());
+ }
+ Pair, MultiMap> selectedRootsAndFiles = collectRoots(structureFilter.getFiles(), roots);
+ if (rootFilter == null) {
+ return selectedRootsAndFiles;
+ }
+ return Pair.create(ContainerUtil.union(new HashSet(rootFilter.getRoots()), selectedRootsAndFiles.first),
+ selectedRootsAndFiles.second);
+ }
+
+ @Nullable
+ public static Set collectRoots(@NotNull Set roots,
+ @Nullable VcsLogRootFilter rootFilter,
+ @Nullable VcsLogStructureFilter structureFilter) {
+ if (rootFilter == null && structureFilter == null) return null;
+
+ Pair, MultiMap> rootsAndFiles = collectRootsAndFiles(roots, rootFilter, structureFilter);
+ return ContainerUtil.union(rootsAndFiles.first, rootsAndFiles.second.keySet());
+ }
+}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFiltererImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFiltererImpl.java
index 2248cb7b31e7..1f106c001754 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFiltererImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFiltererImpl.java
@@ -55,7 +55,7 @@ public class VcsLogFiltererImpl implements VcsLogFilterer {
@NotNull final PermanentGraph.SortType initialSortType,
@NotNull final Consumer 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(visiblePackConsumer) {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java
index 39fe1c8dc1cb..8c14a22b4895 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java
@@ -32,38 +32,28 @@ import java.util.HashSet;
import java.util.Set;
public class VcsLogStructureFilterImpl implements VcsLogDetailsFilter, VcsLogStructureFilter {
- @NotNull private final Set myRoots;
- @NotNull private final MultiMap myRootToFiles;
+ @NotNull private final Set myFiles;
- public VcsLogStructureFilterImpl(@NotNull Set roots,
- @NotNull MultiMap rootToFiles) {
- myRoots = roots;
- myRootToFiles = rootToFiles;
+ public VcsLogStructureFilterImpl(@NotNull Set files) {
+ myFiles = files;
}
@NotNull
@Override
- public Collection getFiles(@NotNull VirtualFile root) {
- return myRootToFiles.get(root);
- }
-
- @Override
- public Collection getRoots() {
- return ContainerUtil.union(myRoots, myRootToFiles.keySet());
+ public Collection 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 files) {
- return ContainerUtil.find(files, new Condition() {
+ private boolean matches(@NotNull final String path) {
+ return ContainerUtil.find(myFiles, new Condition() {
@Override
public boolean value(VirtualFile file) {
return FileUtil.isAncestor(file.getPath(), path, false);
}
}) != null;
}
-
- @NotNull
- public static VcsLogStructureFilterImpl build(@NotNull Collection files,
- @NotNull VcsLogDataPack dataPack) {
- Set roots = dataPack.getLogProviders().keySet();
-
- Set selectedRoots = new HashSet();
- MultiMap selectedFiles = new MultiMap();
-
- 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);
- }
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VisiblePackBuilder.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VisiblePackBuilder.java
index 31489526f59f..e2c2a9ce332d 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VisiblePackBuilder.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VisiblePackBuilder.java
@@ -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 matchingHeads = getMatchingHeads(dataPack.getRefs(), filters);
+ Set matchingHeads = getMatchingHeads(dataPack.getRefs(), dataPack.getLogProviders().keySet(), filters);
List detailsFilters = filters.getDetailsFilters();
List matchingCommits = null;
boolean canRequestMore = false;
@@ -105,8 +107,8 @@ class VisiblePackBuilder {
}
private VisiblePack applyHashFilter(@NotNull DataPack dataPack,
- @NotNull Collection hashes,
- @NotNull PermanentGraph.SortType sortType) {
+ @NotNull Collection hashes,
+ @NotNull PermanentGraph.SortType sortType) {
final Set indices = ContainerUtil.map2SetNotNull(hashes, new Function() {
@Override
public Integer fun(String partOfHash) {
@@ -124,13 +126,39 @@ class VisiblePackBuilder {
}
@Nullable
- private Set getMatchingHeads(@NotNull VcsLogRefs refs, @NotNull VcsLogFilterCollection filters) {
+ private Set getMatchingHeads(@NotNull VcsLogRefs refs, Set 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 filteredByFile = null;
+ Set 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 branchNames = new HashSet(branchFilter.getBranchNames());
+ if (filteredByBranch == null) return filteredByFile;
+ if (filteredByFile == null) return filteredByBranch;
+
+ return new HashSet(ContainerUtil.intersection(filteredByBranch, filteredByFile));
+ }
+
+ private Set getMatchingHeads(@NotNull VcsLogRefs refs, @NotNull VcsLogBranchFilter filter) {
+ final Collection branchNames = new HashSet(filter.getBranchNames());
return new HashSet(ContainerUtil.mapNotNull(refs.getBranches(), new Function() {
@Override
public Integer fun(VcsRef ref) {
@@ -142,6 +170,28 @@ class VisiblePackBuilder {
}));
}
+ private Set getMatchingHeads(@NotNull VcsLogRefs refs, @NotNull VcsLogRootFilter filter) {
+ Collection roots = filter.getRoots();
+ return getMatchingHeads(refs, roots);
+ }
+
+ private Set getMatchingHeads(@NotNull VcsLogRefs refs, @NotNull Collection roots) {
+ Set result = new HashSet();
+ for (VcsRef branch : refs.getBranches()) {
+ if (roots.contains(branch.getRoot())) {
+ result.add(myHashMap.getCommitIndex(branch.getCommitHash()));
+ }
+ }
+ return result;
+ }
+
+ private Set getMatchingHeads(@NotNull VcsLogRefs refs,
+ @NotNull Set vcsRoots,
+ @NotNull VcsLogStructureFilter filter) {
+ Pair, MultiMap> roots = VcsLogFileFilterUtil.collectRoots(filter.getFiles(), vcsRoots);
+ return getMatchingHeads(refs, ContainerUtil.union(roots.first, roots.second.keySet()));
+ }
+
@NotNull
private List filterInMemory(@NotNull PermanentGraph permanentGraph,
@NotNull List detailsFilters,
@@ -203,17 +253,28 @@ class VisiblePackBuilder {
private static List getFilteredDetailsFromTheVcs(@NotNull Map providers,
@NotNull VcsLogFilterCollection filterCollection,
int maxCount) throws VcsException {
+ VcsLogRootFilter rootFilter = filterCollection.getRootFilter();
+ VcsLogStructureFilter structureFilter = filterCollection.getStructureFilter();
+
+ Pair, MultiMap> selectedRootsAndFiles =
+ VcsLogFileFilterUtil.collectRootsAndFiles(providers.keySet(), rootFilter, structureFilter);
+
Collection> logs = ContainerUtil.newArrayList();
for (Map.Entry 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 matchingCommits = entry.getValue().getCommitsMatchingFilter(root, filterCollection, maxCount);
+ VcsLogFilterCollection rootSpecificCollection = filterCollection;
+ if (rootSpecificCollection.getStructureFilter() != null) {
+ rootSpecificCollection = replaceStructureFilter(filterCollection, new HashSet(selectedRootsAndFiles.second.get(root)));
+ }
+
+ List 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 files) {
+ return new VcsLogFilterCollectionImpl(filterCollection.getBranchFilter(), filterCollection.getUserFilter(),
+ filterCollection.getHashFilter(), filterCollection.getDateFilter(),
+ filterCollection.getTextFilter(), new VcsLogStructureFilterImpl(files),
+ filterCollection.getRootFilter());
+ }
+
@Nullable
private Condition getFilterFromCommits(@Nullable List filteredCommits) {
if (filteredCommits == null) {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogFilterCollectionImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogFilterCollectionImpl.java
index 3fbb7cb7b82f..d973face890d 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogFilterCollectionImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogFilterCollectionImpl.java
@@ -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();
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterModel.java
index 88c8a8d0011c..a6ebaf6ad5b4 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterModel.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterModel.java
@@ -47,6 +47,11 @@ class FilterModel {
return myFilter;
}
+ @NotNull
+ public Computable getDataPackProvider() {
+ return myDataPackProvider;
+ }
+
@NotNull
VcsLogDataPack getDataPack() {
return myDataPackProvider.compute();
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java
index 2b849e1de8fe..2b72113d2de4 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java
@@ -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 {
-
+class StructureFilterPopupComponent extends FilterPopupComponent {
private static final int FILTER_LABEL_LENGTH = 20;
- public StructureFilterPopupComponent(@NotNull FilterModel filterModel) {
+ public StructureFilterPopupComponent(@NotNull FilterModel filterModel) {
super("Structure", filterModel);
}
@NotNull
@Override
- protected String getText(@NotNull VcsLogStructureFilter filter) {
- Collection files = getAllFiles(myFilterModel.getDataPack(), filter);
+ protected String getText(@NotNull VcsLogFileFilter filter) {
+ Collection files = getAllFiles(filter);
if (files.size() == 0) {
return ALL;
}
@@ -58,20 +56,15 @@ class StructureFilterPopupComponent extends FilterPopupComponent getAllFiles(@NotNull VcsLogDataPack dataPack, @NotNull VcsLogStructureFilter filter) {
+ private static Collection getAllFiles(@NotNull VcsLogFileFilter filter) {
Collection result = ContainerUtil.newArrayList();
- for (VirtualFile root : dataPack.getLogProviders().keySet()) {
- Collection 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 roots = myFilterModel.getDataPack().getLogProviders().keySet();
+ VcsLogFileFilter previousFilter = myFilterModel.getFilter();
+ VcsLogRootFilter rootFilter = previousFilter != null ? previousFilter.getRootFilter() : null;
+
Collection visibleRoots;
- VcsLogStructureFilter previousFilter = myFilterModel.getFilter();
- if (previousFilter == null) {
+ if (rootFilter == null) {
if (visible) {
visibleRoots = roots;
}
@@ -113,14 +109,13 @@ class StructureFilterPopupComponent extends FilterPopupComponent(myFilterModel.getFilter().getRoots()), Collections.singleton(root));
+ visibleRoots = ContainerUtil.union(new HashSet(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 files = filter == null ? Collections.emptySet() : getAllFiles(dataPack, filter);
+ VcsLogFileFilter filter = myFilterModel.getFilter();
+ VcsLogRootFilter rootFilter = filter == null ? null : filter.getRootFilter();
+ Collection files = filter == null ? Collections.emptySet() : getAllFiles(filter);
VcsStructureChooser chooser = new VcsStructureChooser(project, "Select Files or Folders to Filter", files,
new ArrayList(dataPack.getLogProviders().keySet()));
if (chooser.showAndGet()) {
- myFilterModel.setFilter(VcsLogStructureFilterImpl.build(chooser.getSelectedFiles(), dataPack));
+ myFilterModel.setFilter(new VcsLogFileFilter(new VcsLogStructureFilterImpl(new HashSet(chooser.getSelectedFiles())), rootFilter));
}
}
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java
index 771811222de9..937ca7ff12b3 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java
@@ -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 myUserFilterModel;
@NotNull private final FilterModel myDateFilterModel;
- @NotNull private final FilterModel myStructureFilterModel;
+ @NotNull private final FilterModel 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(dataPackGetter);
myDateFilterModel = new FilterModel(dataPackGetter);
- myStructureFilterModel = new FilterModel(dataPackGetter);
+ myStructureFilterModel = new FilterModel(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(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 roots, @Nullable VcsLogFileFilter filter) {
if (filter == null) {
myVisibleRoots = null;
} else {
- myVisibleRoots = filter.getRoots();
+ myVisibleRoots = VcsLogFileFilterUtil.collectRoots(roots, filter.getRootFilter(), filter.getStructureFilter());
}
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogFileFilter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogFileFilter.java
new file mode 100644
index 000000000000..b4b5411c4c7c
--- /dev/null
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogFileFilter.java
@@ -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;
+ }
+}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java
index ac6765b8dbf9..7762b2fd4ea0 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java
@@ -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;
diff --git a/plugins/git4idea/src/git4idea/log/GitBekParentFixer.java b/plugins/git4idea/src/git4idea/log/GitBekParentFixer.java
index 4bcfade3cfa8..7778b23e2327 100644
--- a/plugins/git4idea/src/git4idea/log/GitBekParentFixer.java
+++ b/plugins/git4idea/src/git4idea/log/GitBekParentFixer.java
@@ -136,6 +136,12 @@ class GitBekParentFixer {
return null;
}
+ @Nullable
+ @Override
+ public VcsLogRootFilter getRootFilter() {
+ return null;
+ }
+
@Override
public boolean isEmpty() {
return false;
diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java
index 1abb59c5476f..88ab9a892f53 100644
--- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java
+++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java
@@ -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 files = filterCollection.getStructureFilter().getFiles(root);
+ Collection files = filterCollection.getStructureFilter().getFiles();
if (!files.isEmpty()) {
filterParameters.add("--simplify-merges");
filterParameters.add("--");
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
index 842e415a8476..5f9e2cea2071 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
@@ -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());
}
}