Show node in Changes view for merge conflicts (IDEA-66051)

This commit is contained in:
Dmitry Jemerov
2018-05-08 11:07:23 +02:00
parent a3368e5f69
commit 602e6fff97
9 changed files with 83 additions and 81 deletions
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2009 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.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.vcs.merge;
import com.intellij.openapi.vcs.VcsException;
@@ -20,6 +6,8 @@ import com.intellij.openapi.vcs.VcsProviderMarker;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public interface MergeProvider extends VcsProviderMarker {
@NotNull
@@ -31,4 +19,10 @@ public interface MergeProvider extends VcsProviderMarker {
void conflictResolvedForFile(@NotNull VirtualFile file);
boolean isBinary(@NotNull VirtualFile file);
/**
* Called after a multiple file merge operation with the specified list of files has been completed.
*/
default void mergeDone(@NotNull List<VirtualFile> files) {
}
}
@@ -0,0 +1,22 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.vcs.changes.ui
import com.intellij.openapi.project.Project
import com.intellij.openapi.vcs.AbstractVcsHelper
import com.intellij.openapi.vcs.changes.ChangesUtil
import com.intellij.ui.SimpleTextAttributes
import java.util.stream.Collectors
/**
* @author yole
*/
class ChangesBrowserConflictsNode(val project: Project) : ChangesBrowserNode<Unit>(Unit) {
override fun render(renderer: ChangesBrowserNodeRenderer, selected: Boolean, expanded: Boolean, hasFocus: Boolean) {
renderer.append("Merge Conflicts ", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES)
renderer.append("Resolve", SimpleTextAttributes.LINK_BOLD_ATTRIBUTES, Runnable { showResolveConflictsDialog() })
}
private fun showResolveConflictsDialog() {
AbstractVcsHelper.getInstance(project).showMergeDialog(ChangesUtil.getFiles(allChangesUnder.stream()).collect(Collectors.toList()))
}
}
@@ -10,7 +10,7 @@ import javax.swing.tree.DefaultTreeModel
private val PREDEFINED_PRIORITIES = mapOf("directory" to 10, "module" to 20, "repository" to 30)
class ChangesGroupingSupport(project: Project, source: Any) {
class ChangesGroupingSupport(val project: Project, source: Any) {
private val changeSupport = PropertyChangeSupport(source)
private val groupingFactories = collectFactories(project)
private val groupingConfig = groupingFactories.allKeys.associateBy({ it }, { false }).toMutableMap()
@@ -37,7 +37,7 @@ class ChangesGroupingSupport(project: Project, source: Any) {
val grouping
get() = object : ChangesGroupingPolicyFactory() {
override fun createGroupingPolicy(model: DefaultTreeModel): ChangesGroupingPolicy {
var result: ChangesGroupingPolicy = NoneChangesGroupingPolicy.Factory().createGroupingPolicy(model)
var result: ChangesGroupingPolicy = DefaultChangesGroupingPolicy.Factory(project).createGroupingPolicy(model)
groupingConfig.filterValues { it }.keys.sortedByDescending { PREDEFINED_PRIORITIES[it] }.forEach {
result = groupingFactories.getByKey(it)!!.createGroupingPolicy(model).apply { setNextGroupingPolicy(result) }
}
@@ -0,0 +1,37 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.vcs.changes.ui
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.openapi.vcs.FileStatus
import com.intellij.openapi.vcs.FileStatusManager
import javax.swing.tree.DefaultTreeModel
class DefaultChangesGroupingPolicy(val project: Project, val model: DefaultTreeModel) : BaseChangesGroupingPolicy() {
override fun getParentNodeFor(nodePath: StaticFilePath, subtreeRoot: ChangesBrowserNode<*>): ChangesBrowserNode<*>? {
val vFile = nodePath.resolve() ?: return null
val status = FileStatusManager.getInstance(project).getStatus(vFile)
if (status == FileStatus.MERGED_WITH_CONFLICTS) {
val cachingRoot = getCachingRoot(subtreeRoot, subtreeRoot)
CONFLICTS_NODE_CACHE[cachingRoot]?.let { return it }
return ChangesBrowserConflictsNode(project).also {
it.markAsHelperNode()
model.insertNodeInto(it, subtreeRoot, subtreeRoot.childCount)
CONFLICTS_NODE_CACHE[subtreeRoot] = it
TreeModelBuilder.IS_CACHING_ROOT.set(it, true)
}
}
return null
}
companion object {
val CONFLICTS_NODE_CACHE = Key.create<ChangesBrowserNode<*>>("ChangesTree.ConflictsNodeCache")
}
class Factory(val project: Project) : ChangesGroupingPolicyFactory() {
override fun createGroupingPolicy(model: DefaultTreeModel) = DefaultChangesGroupingPolicy(project, model)
}
}
@@ -1,12 +0,0 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.vcs.changes.ui
import javax.swing.tree.DefaultTreeModel
class NoneChangesGroupingPolicy : ChangesGroupingPolicy {
override fun getParentNodeFor(nodePath: StaticFilePath, subtreeRoot: ChangesBrowserNode<*>): ChangesBrowserNode<*>? = null
class Factory : ChangesGroupingPolicyFactory() {
override fun createGroupingPolicy(model: DefaultTreeModel) = NoneChangesGroupingPolicy()
}
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2015 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.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.vcs.impl;
import com.intellij.ide.actions.CloseTabToolbarAction;
@@ -511,6 +497,7 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper {
final MultipleFileMergeDialog fileMergeDialog = new MultipleFileMergeDialog(myProject, files, provider, mergeDialogCustomizer);
AppIcon.getInstance().requestAttention(myProject, true);
fileMergeDialog.show();
provider.mergeDone(files);
return fileMergeDialog.getProcessedFiles();
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2009 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.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package git4idea.actions;
import com.intellij.openapi.actionSystem.ActionPlaces;
@@ -25,9 +11,7 @@ import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ObjectUtils;
import git4idea.GitUtil;
import git4idea.GitVcs;
import git4idea.repo.GitRepository;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
@@ -68,9 +52,6 @@ public class GitResolveConflictsAction extends GitAction {
}
AbstractVcsHelper.getInstance(project).showMergeDialog(newArrayList(conflictedFiles), vcs.getMergeProvider());
for (GitRepository repository : GitUtil.getRepositoriesForFiles(project, conflictedFiles)) {
repository.update();
}
}
@Override
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2009 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.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package git4idea.merge;
import com.intellij.dvcs.DvcsUtil;
@@ -405,6 +391,13 @@ public class GitMergeProvider implements MergeProvider2 {
return new MyMergeSession(files);
}
@Override
public void mergeDone(@NotNull List<VirtualFile> files) {
for (GitRepository repository : GitUtil.getRepositoriesForFiles(myProject, files)) {
repository.update();
}
}
/**
* The conflict descriptor
*/
@@ -11,7 +11,7 @@ import com.intellij.openapi.util.BooleanGetter;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNode;
import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNodeRenderer;
import com.intellij.openapi.vcs.changes.ui.NoneChangesGroupingPolicy;
import com.intellij.openapi.vcs.changes.ui.DefaultChangesGroupingPolicy;
import com.intellij.openapi.vcs.changes.ui.TreeModelBuilder;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowId;
@@ -75,7 +75,7 @@ public class IntersectingLocalChangesPanel {
@NotNull
private SimpleTree createTree() {
SimpleTree tree = new SimpleTree(TreeModelBuilder.buildFromFilePaths(myProject, new NoneChangesGroupingPolicy.Factory(), myFiles)) {
SimpleTree tree = new SimpleTree(TreeModelBuilder.buildFromFilePaths(myProject, new DefaultChangesGroupingPolicy.Factory(myProject), myFiles)) {
@Override
protected void configureUiHelper(@NotNull TreeUIHelper helper) {
super.configureUiHelper(helper);