[vcs-log] structure filter better understand nature of vcs roots and interacts with branches filter about them

This commit is contained in:
Julia Beliaeva
2014-12-05 18:58:00 +03:00
parent 9542937753
commit f210fe94bf
5 changed files with 72 additions and 50 deletions
@@ -34,4 +34,6 @@ public interface VcsLogStructureFilter extends VcsLogDetailsFilter {
@NotNull
Collection<VirtualFile> getFiles(@NotNull VirtualFile root);
Collection<VirtualFile> getRoots();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* 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.
@@ -23,61 +23,47 @@ import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.vcs.log.VcsCommitMetadata;
import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.VcsLogDetailsFilter;
import com.intellij.vcs.log.VcsLogStructureFilter;
import com.intellij.vcs.log.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
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 Collection<VirtualFile> myFiles;
@NotNull private final MultiMap<VirtualFile, VirtualFile> myFilesByRoots;
public VcsLogStructureFilterImpl(@NotNull Collection<VirtualFile> files, @NotNull Collection<VirtualFile> roots) {
myFiles = files;
myFilesByRoots = groupFilesByVcsRoots(files, roots);
public VcsLogStructureFilterImpl(@NotNull Set<VirtualFile> roots,
@NotNull MultiMap<VirtualFile, VirtualFile> rootToFiles) {
myRoots = roots;
myRootToFiles = rootToFiles;
}
@NotNull
private static MultiMap<VirtualFile, VirtualFile> groupFilesByVcsRoots(@NotNull Collection<VirtualFile> files,
@NotNull Collection<VirtualFile> roots) {
MultiMap<VirtualFile, VirtualFile> grouped = MultiMap.create();
for (VirtualFile file : files) {
VirtualFile root = findBestRoot(file, roots);
if (root != null) {
grouped.putValue(root, file);
}
}
return grouped;
@Override
public Collection<VirtualFile> getFiles(@NotNull VirtualFile root) {
return myRootToFiles.get(root);
}
@Nullable
private static VirtualFile findBestRoot(@NotNull VirtualFile file, @NotNull Collection<VirtualFile> roots) {
VirtualFile candidate = null;
for (VirtualFile root : roots) {
if (VfsUtilCore.isAncestor(root, file, false)) {
if (candidate == null || VfsUtilCore.isAncestor(candidate, root, true)) {
candidate = root;
}
}
}
return candidate;
@Override
public Collection<VirtualFile> getRoots() {
return ContainerUtil.union(myRoots, myRootToFiles.keySet());
}
@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())) {
if (before != null && matches(before.getFile().getPath(), myRootToFiles.get(details.getRoot()))) {
return true;
}
ContentRevision after = change.getAfterRevision();
if (after != null && matches(after.getFile().getPath())) {
if (after != null && matches(after.getFile().getPath(), myRootToFiles.get(details.getRoot()))) {
return true;
}
}
@@ -88,8 +74,8 @@ public class VcsLogStructureFilterImpl implements VcsLogDetailsFilter, VcsLogStr
}
}
private boolean matches(@NotNull final String path) {
return ContainerUtil.find(myFiles, new Condition<VirtualFile>() {
private boolean matches(@NotNull final String path, @NotNull Collection<VirtualFile> files) {
return ContainerUtil.find(files, new Condition<VirtualFile>() {
@Override
public boolean value(VirtualFile file) {
return FileUtil.isAncestor(file.getPath(), path, false);
@@ -97,10 +83,38 @@ public class VcsLogStructureFilterImpl implements VcsLogDetailsFilter, VcsLogStr
}) != null;
}
@Override
@NotNull
public Collection<VirtualFile> getFiles(@NotNull VirtualFile root) {
return myFilesByRoots.get(root);
}
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);
}
}
@@ -207,7 +207,7 @@ class VisiblePackBuilder {
for (Map.Entry<VirtualFile, VcsLogProvider> entry : providers.entrySet()) {
VirtualFile root = entry.getKey();
if (filterCollection.getStructureFilter() != null && filterCollection.getStructureFilter().getFiles(root).isEmpty()
if (filterCollection.getStructureFilter() != null && !filterCollection.getStructureFilter().getRoots().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;
@@ -68,7 +68,11 @@ class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogStructure
private static Collection<VirtualFile> getAllFiles(@NotNull VcsLogDataPack dataPack, @NotNull VcsLogStructureFilter filter) {
Collection<VirtualFile> result = ContainerUtil.newArrayList();
for (VirtualFile root : dataPack.getLogProviders().keySet()) {
result.addAll(filter.getFiles(root));
Collection<VirtualFile> files = filter.getFiles(root);
result.addAll(files);
if (files.isEmpty() && filter.getRoots().contains(root)) {
result.add(root);
}
}
return result;
}
@@ -107,11 +111,10 @@ class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogStructure
VcsLogDataPack dataPack = myFilterModel.getDataPack();
VcsLogStructureFilter filter = myFilterModel.getFilter();
Collection<VirtualFile> files = filter == null ? Collections.<VirtualFile>emptySet() : getAllFiles(dataPack, filter);
Set<VirtualFile> roots = dataPack.getLogProviders().keySet();
VcsStructureChooser chooser = new VcsStructureChooser(project, "Select Files or Folders to Filter", files,
new ArrayList<VirtualFile>(roots));
new ArrayList<VirtualFile>(dataPack.getLogProviders().keySet()));
if (chooser.showAndGet()) {
myFilterModel.setFilter(new VcsLogStructureFilterImpl(chooser.getSelectedFiles(), roots));
myFilterModel.setFilter(VcsLogStructureFilterImpl.build(chooser.getSelectedFiles(), dataPack));
}
}
}
@@ -440,10 +440,13 @@ 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) {
filterParameters.add("--simplify-merges");
filterParameters.add("--");
for (VirtualFile file : filterCollection.getStructureFilter().getFiles(root)) {
filterParameters.add(file.getPath());
Collection<VirtualFile> files = filterCollection.getStructureFilter().getFiles(root);
if (!files.isEmpty()) {
filterParameters.add("--simplify-merges");
filterParameters.add("--");
for (VirtualFile file : files) {
filterParameters.add(file.getPath());
}
}
}