diff --git a/platform/vcs-log/impl/src/META-INF/vcs-log.xml b/platform/vcs-log/impl/src/META-INF/vcs-log.xml
index d935605aea2b..679c6b8d983f 100644
--- a/platform/vcs-log/impl/src/META-INF/vcs-log.xml
+++ b/platform/vcs-log/impl/src/META-INF/vcs-log.xml
@@ -85,6 +85,7 @@
+
@@ -154,6 +155,7 @@
+
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryUtil.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryUtil.java
index e1a851835c79..e0519cbaa44f 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryUtil.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryUtil.java
@@ -58,7 +58,7 @@ public class FileHistoryUtil {
return Collections.emptyList();
}
- static boolean affectsFile(@NotNull Change change, @NotNull FilePath file, boolean isDeleted) {
+ public static boolean affectsFile(@NotNull Change change, @NotNull FilePath file, boolean isDeleted) {
ContentRevision revision = isDeleted ? change.getBeforeRevision() : change.getAfterRevision();
if (revision == null) return false;
return file.equals(revision.getFile());
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/VcsLogFileHistoryProviderImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/VcsLogFileHistoryProviderImpl.java
index cce449bce610..4d018880c0fe 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/VcsLogFileHistoryProviderImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/VcsLogFileHistoryProviderImpl.java
@@ -8,10 +8,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.*;
import com.intellij.vcs.log.data.VcsLogData;
-import com.intellij.vcs.log.impl.HashImpl;
-import com.intellij.vcs.log.impl.VcsLogContentUtil;
-import com.intellij.vcs.log.impl.VcsLogManager;
-import com.intellij.vcs.log.impl.VcsProjectLog;
+import com.intellij.vcs.log.impl.*;
import com.intellij.vcs.log.ui.AbstractVcsLogUi;
import com.intellij.vcs.log.ui.VcsLogUiImpl;
import com.intellij.vcs.log.util.VcsLogUtil;
@@ -94,6 +91,7 @@ public class VcsLogFileHistoryProviderImpl implements VcsLogFileHistoryProvider
if (firstTime) {
VcsLogFilterCollection filters = createFilters(path, hash, root);
ui = VcsProjectLog.getInstance(project).getTabsManager().openAnotherLogTab(logManager, filters);
+ ui.getProperties().set(MainVcsLogUiProperties.SHOW_ONLY_AFFECTED_CHANGES, true);
}
consumer.accept(ui, firstTime);
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/MainVcsLogUiProperties.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/MainVcsLogUiProperties.java
index 4580d55125ff..e3a726976b6b 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/MainVcsLogUiProperties.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/MainVcsLogUiProperties.java
@@ -33,6 +33,7 @@ public interface MainVcsLogUiProperties extends VcsLogUiProperties {
VcsLogUiProperty TEXT_FILTER_MATCH_CASE = new VcsLogUiProperty<>("TextFilter.MatchCase");
VcsLogUiProperty TEXT_FILTER_REGEX = new VcsLogUiProperty<>("TextFilter.Regex");
VcsLogUiProperty SHOW_CHANGES_FROM_PARENTS = new VcsLogUiProperty<>("Changes.ShowChangesFromParents");
+ VcsLogUiProperty SHOW_ONLY_AFFECTED_CHANGES = new VcsLogUiProperty<>("Changes.ShowOnlyAffected");
void addRecentlyFilteredGroup(@NotNull String filterName, @NotNull Collection values);
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUiPropertiesImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUiPropertiesImpl.java
index 613785e90135..a5670c207a97 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUiPropertiesImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUiPropertiesImpl.java
@@ -33,6 +33,7 @@ public abstract class VcsLogUiPropertiesImpl RECENTLY_FILTERED_USER_GROUPS = new ArrayDeque<>();
@Deprecated
@@ -80,6 +82,9 @@ public abstract class VcsLogUiPropertiesImpl getProperty() {
+ return MainVcsLogUiProperties.SHOW_ONLY_AFFECTED_CHANGES;
+ }
+
+ @Override
+ public void update(@NotNull AnActionEvent e) {
+ if (!Registry.is("vcs.folder.history.in.log")) {
+ e.getPresentation().setEnabledAndVisible(false);
+ } else {
+ super.update(e);
+ }
+ }
+}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java
index 29178c9888d6..9f9623464aab 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java
@@ -169,6 +169,8 @@ public class MainFrame extends JPanel implements DataProvider, Disposable {
public void updateDataPack(@NotNull VisiblePack dataPack, boolean permGraphChanged) {
myFilterUi.updateDataPack(dataPack);
myGraphTable.updateDataPack(dataPack, permGraphChanged);
+ VcsLogStructureFilter structureFilter = dataPack.getFilters().get(VcsLogFilterCollection.STRUCTURE_FILTER);
+ myChangesBrowser.setAffectedPaths(structureFilter != null ? structureFilter.getFiles() : null);
}
@NotNull
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogChangesBrowser.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogChangesBrowser.java
index f8709b03c258..45039b966e31 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogChangesBrowser.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogChangesBrowser.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SideBorder;
+import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
@@ -30,6 +31,7 @@ import com.intellij.vcs.log.VcsShortCommitDetails;
import com.intellij.vcs.log.data.LoadingDetails;
import com.intellij.vcs.log.data.index.IndexedDetails;
import com.intellij.vcs.log.history.FileHistoryKt;
+import com.intellij.vcs.log.history.FileHistoryUtil;
import com.intellij.vcs.log.impl.MainVcsLogUiProperties;
import com.intellij.vcs.log.impl.MergedChange;
import com.intellij.vcs.log.impl.MergedChangeDiffRequestProvider;
@@ -51,6 +53,7 @@ import static com.intellij.diff.util.DiffUserDataKeysEx.*;
import static com.intellij.util.ObjectUtils.notNull;
import static com.intellij.util.containers.ContainerUtil.getFirstItem;
import static com.intellij.vcs.log.impl.MainVcsLogUiProperties.SHOW_CHANGES_FROM_PARENTS;
+import static com.intellij.vcs.log.impl.MainVcsLogUiProperties.SHOW_ONLY_AFFECTED_CHANGES;
/**
* Change browser for commits in the Log. For merge commits, can display changes to commits parents in separate groups.
@@ -66,6 +69,7 @@ public class VcsLogChangesBrowser extends ChangesBrowserBase implements Disposab
@NotNull private final Set myRoots = ContainerUtil.newHashSet();
@NotNull private final List myChanges = ContainerUtil.newArrayList();
@NotNull private final Map> myChangesToParents = ContainerUtil.newHashMap();
+ @Nullable private Collection myAffectedPaths;
@NotNull private final Wrapper myToolbarWrapper;
@Nullable private Runnable myModelUpdateListener;
@@ -81,7 +85,7 @@ public class VcsLogChangesBrowser extends ChangesBrowserBase implements Disposab
myListener = new VcsLogUiProperties.PropertiesChangeListener() {
@Override
public void onPropertyChanged(@NotNull VcsLogUiProperties.VcsLogUiProperty property) {
- if (SHOW_CHANGES_FROM_PARENTS.equals(property)) {
+ if (SHOW_CHANGES_FROM_PARENTS.equals(property) || SHOW_ONLY_AFFECTED_CHANGES.equals(property)) {
myViewer.rebuildTree();
}
}
@@ -150,6 +154,11 @@ public class VcsLogChangesBrowser extends ChangesBrowserBase implements Disposab
if (myModelUpdateListener != null) myModelUpdateListener.run();
}
+ public void setAffectedPaths(@Nullable Collection paths) {
+ myAffectedPaths = paths;
+ myViewer.rebuildTree();
+ }
+
public void setSelectedDetails(@NotNull List extends VcsFullCommitDetails> detailsList) {
myChanges.clear();
myChangesToParents.clear();
@@ -192,15 +201,21 @@ public class VcsLogChangesBrowser extends ChangesBrowserBase implements Disposab
@NotNull
@Override
protected DefaultTreeModel buildTreeModel() {
- MyTreeModelBuilder builder = new MyTreeModelBuilder();
- builder.setChanges(myChanges, null);
+ Collection changes = collectAffectedChanges(myChanges);
+ Map> changesToParents = ContainerUtil.newHashMap();
+ for (Map.Entry> entry : myChangesToParents.entrySet()) {
+ changesToParents.put(entry.getKey(), collectAffectedChanges(entry.getValue()));
+ }
- if (isShowChangesFromParents() && !myChangesToParents.isEmpty()) {
- if (myChanges.isEmpty()) {
+ MyTreeModelBuilder builder = new MyTreeModelBuilder();
+ builder.setChanges(changes, null);
+
+ if (isShowChangesFromParents() && !changesToParents.isEmpty()) {
+ if (changes.isEmpty()) {
builder.addEmptyTextNode("No merged conflicts");
}
- for (CommitId commitId : myChangesToParents.keySet()) {
- Collection changesFromParent = myChangesToParents.get(commitId);
+ for (CommitId commitId : changesToParents.keySet()) {
+ Collection changesFromParent = changesToParents.get(commitId);
if (!changesFromParent.isEmpty()) {
builder.addChangesFromParentNode(changesFromParent, commitId);
}
@@ -210,11 +225,30 @@ public class VcsLogChangesBrowser extends ChangesBrowserBase implements Disposab
return builder.build();
}
+ @NotNull
+ private Collection collectAffectedChanges(@NotNull Collection changes) {
+ if (!isShowOnlyAffected() || myAffectedPaths == null) return changes;
+ return ContainerUtil.filter(changes, change -> ContainerUtil.or(myAffectedPaths, filePath -> {
+ if (filePath.isDirectory()) {
+ return FileHistoryUtil.affectsDirectory(change, filePath);
+ }
+ else {
+ return FileHistoryUtil.affectsFile(change, filePath, false) ||
+ FileHistoryUtil.affectsFile(change, filePath, true);
+ }
+ }));
+ }
+
private boolean isShowChangesFromParents() {
return myUiProperties.exists(SHOW_CHANGES_FROM_PARENTS) &&
myUiProperties.get(SHOW_CHANGES_FROM_PARENTS);
}
+ private boolean isShowOnlyAffected() {
+ return myUiProperties.exists(SHOW_ONLY_AFFECTED_CHANGES) &&
+ myUiProperties.get(SHOW_ONLY_AFFECTED_CHANGES);
+ }
+
@NotNull
public List getDirectChanges() {
return myChanges;