mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Delete old implementation of multiple file merge dialog
This commit is contained in:
@@ -521,9 +521,6 @@ vcs.enable.partial.changelists.redo.restartRequired=true
|
|||||||
vcs.skip.single.default.changelist=false
|
vcs.skip.single.default.changelist=false
|
||||||
vcs.skip.single.default.changelist.description=Don't show changelist node in Local Changes view when only the Default changelist exists
|
vcs.skip.single.default.changelist.description=Don't show changelist node in Local Changes view when only the Default changelist exists
|
||||||
|
|
||||||
vcs.new.multiple.file.merge=true
|
|
||||||
vcs.new.multiple.file.merge.description=Use new implementation of multiple files merge dialog
|
|
||||||
|
|
||||||
psi.incremental.reparse.depth.limit=1000
|
psi.incremental.reparse.depth.limit=1000
|
||||||
psi.deferIconLoading=true
|
psi.deferIconLoading=true
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import com.intellij.openapi.util.Disposer;
|
|||||||
import com.intellij.openapi.util.Getter;
|
import com.intellij.openapi.util.Getter;
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
import com.intellij.openapi.util.registry.Registry;
|
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import com.intellij.openapi.vcs.*;
|
import com.intellij.openapi.vcs.*;
|
||||||
import com.intellij.openapi.vcs.actions.AnnotateToggleAction;
|
import com.intellij.openapi.vcs.actions.AnnotateToggleAction;
|
||||||
@@ -47,7 +46,6 @@ import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
|||||||
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer;
|
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer;
|
||||||
import com.intellij.openapi.vcs.merge.MergeProvider;
|
import com.intellij.openapi.vcs.merge.MergeProvider;
|
||||||
import com.intellij.openapi.vcs.merge.MultipleFileMergeDialog;
|
import com.intellij.openapi.vcs.merge.MultipleFileMergeDialog;
|
||||||
import com.intellij.openapi.vcs.merge.MultipleFileMergeDialog2;
|
|
||||||
import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
|
import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
|
||||||
import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor;
|
import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor;
|
||||||
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
|
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
|
||||||
@@ -498,18 +496,10 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper {
|
|||||||
@NotNull MergeDialogCustomizer mergeDialogCustomizer) {
|
@NotNull MergeDialogCustomizer mergeDialogCustomizer) {
|
||||||
if (files.isEmpty()) return Collections.emptyList();
|
if (files.isEmpty()) return Collections.emptyList();
|
||||||
VfsUtil.markDirtyAndRefresh(false, false, false, ArrayUtil.toObjectArray(files, VirtualFile.class));
|
VfsUtil.markDirtyAndRefresh(false, false, false, ArrayUtil.toObjectArray(files, VirtualFile.class));
|
||||||
if (Registry.is("vcs.new.multiple.file.merge")) {
|
final MultipleFileMergeDialog fileMergeDialog = new MultipleFileMergeDialog(myProject, files, provider, mergeDialogCustomizer);
|
||||||
final MultipleFileMergeDialog2 fileMergeDialog = new MultipleFileMergeDialog2(myProject, files, provider, mergeDialogCustomizer);
|
AppIcon.getInstance().requestAttention(myProject, true);
|
||||||
AppIcon.getInstance().requestAttention(myProject, true);
|
fileMergeDialog.show();
|
||||||
fileMergeDialog.show();
|
return fileMergeDialog.getProcessedFiles();
|
||||||
return fileMergeDialog.getProcessedFiles();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final MultipleFileMergeDialog fileMergeDialog = new MultipleFileMergeDialog(myProject, files, provider, mergeDialogCustomizer);
|
|
||||||
AppIcon.getInstance().requestAttention(myProject, true);
|
|
||||||
fileMergeDialog.show();
|
|
||||||
return fileMergeDialog.getProcessedFiles();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openCommittedChangesTab(final AbstractVcs vcs,
|
public void openCommittedChangesTab(final AbstractVcs vcs,
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.vcs.merge.MultipleFileMergeDialog">
|
|
||||||
<grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
|
||||||
<constraints>
|
|
||||||
<xy x="20" y="20" width="500" height="400"/>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
<border type="none"/>
|
|
||||||
<children>
|
|
||||||
<grid id="5c044" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
|
||||||
<constraints>
|
|
||||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
<border type="none"/>
|
|
||||||
<children>
|
|
||||||
<component id="464d7" class="javax.swing.JButton" binding="myAcceptYoursButton" default-binding="true">
|
|
||||||
<constraints>
|
|
||||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
<properties>
|
|
||||||
<text resource-bundle="messages/VcsBundle" key="multiple.file.merge.accept.yours"/>
|
|
||||||
</properties>
|
|
||||||
</component>
|
|
||||||
<vspacer id="da536">
|
|
||||||
<constraints>
|
|
||||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
</vspacer>
|
|
||||||
<component id="7d4c7" class="javax.swing.JButton" binding="myAcceptTheirsButton" default-binding="true">
|
|
||||||
<constraints>
|
|
||||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
<properties>
|
|
||||||
<text resource-bundle="messages/VcsBundle" key="multiple.file.merge.accept.theirs"/>
|
|
||||||
</properties>
|
|
||||||
</component>
|
|
||||||
<component id="39393" class="javax.swing.JButton" binding="myMergeButton" custom-create="true" default-binding="true">
|
|
||||||
<constraints>
|
|
||||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
<properties>
|
|
||||||
<text resource-bundle="messages/VcsBundle" key="multiple.file.merge.merge"/>
|
|
||||||
</properties>
|
|
||||||
</component>
|
|
||||||
</children>
|
|
||||||
</grid>
|
|
||||||
<scrollpane id="9f9b5" class="com.intellij.ui.components.JBScrollPane">
|
|
||||||
<constraints>
|
|
||||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
<border type="none"/>
|
|
||||||
<children>
|
|
||||||
<component id="466f6" class="com.intellij.ui.table.TableView" binding="myTable">
|
|
||||||
<constraints/>
|
|
||||||
<properties/>
|
|
||||||
</component>
|
|
||||||
</children>
|
|
||||||
</scrollpane>
|
|
||||||
<grid id="b4733" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
|
||||||
<margin top="5" left="5" bottom="5" right="5"/>
|
|
||||||
<constraints>
|
|
||||||
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
<border type="none"/>
|
|
||||||
<children>
|
|
||||||
<component id="f8ecf" class="com.intellij.ui.components.JBLabel" binding="myDescriptionLabel">
|
|
||||||
<constraints>
|
|
||||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
</component>
|
|
||||||
</children>
|
|
||||||
</grid>
|
|
||||||
</children>
|
|
||||||
</grid>
|
|
||||||
</form>
|
|
||||||
@@ -1,459 +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.merge;
|
|
||||||
|
|
||||||
import com.intellij.CommonBundle;
|
|
||||||
import com.intellij.diff.DiffManager;
|
|
||||||
import com.intellij.diff.DiffRequestFactory;
|
|
||||||
import com.intellij.diff.InvalidDiffRequestException;
|
|
||||||
import com.intellij.diff.merge.MergeRequest;
|
|
||||||
import com.intellij.diff.merge.MergeResult;
|
|
||||||
import com.intellij.diff.merge.MergeUtil;
|
|
||||||
import com.intellij.diff.util.DiffUtil;
|
|
||||||
import com.intellij.ide.presentation.VirtualFilePresentation;
|
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
|
||||||
import com.intellij.openapi.command.CommandProcessor;
|
|
||||||
import com.intellij.openapi.diagnostic.Logger;
|
|
||||||
import com.intellij.openapi.diff.impl.mergeTool.MergeVersion;
|
|
||||||
import com.intellij.openapi.editor.Document;
|
|
||||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
|
||||||
import com.intellij.openapi.project.Project;
|
|
||||||
import com.intellij.openapi.project.ex.ProjectManagerEx;
|
|
||||||
import com.intellij.openapi.ui.DialogWrapper;
|
|
||||||
import com.intellij.openapi.ui.Messages;
|
|
||||||
import com.intellij.openapi.util.Ref;
|
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
|
||||||
import com.intellij.openapi.vcs.VcsBundle;
|
|
||||||
import com.intellij.openapi.vcs.VcsException;
|
|
||||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
|
||||||
import com.intellij.ui.ColoredTableCellRenderer;
|
|
||||||
import com.intellij.ui.DoubleClickListener;
|
|
||||||
import com.intellij.ui.SimpleTextAttributes;
|
|
||||||
import com.intellij.ui.TableSpeedSearch;
|
|
||||||
import com.intellij.ui.components.JBLabel;
|
|
||||||
import com.intellij.ui.speedSearch.SpeedSearchUtil;
|
|
||||||
import com.intellij.ui.table.TableView;
|
|
||||||
import com.intellij.util.Consumer;
|
|
||||||
import com.intellij.util.SmartList;
|
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
|
||||||
import com.intellij.util.ui.ColumnInfo;
|
|
||||||
import com.intellij.util.ui.ListTableModel;
|
|
||||||
import com.intellij.util.ui.UIUtil;
|
|
||||||
import org.jetbrains.annotations.NonNls;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import javax.swing.event.ListSelectionEvent;
|
|
||||||
import javax.swing.event.ListSelectionListener;
|
|
||||||
import javax.swing.table.TableCellRenderer;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yole
|
|
||||||
*/
|
|
||||||
public class MultipleFileMergeDialog extends DialogWrapper {
|
|
||||||
private static final Logger LOG = Logger.getInstance(MultipleFileMergeDialog.class);
|
|
||||||
|
|
||||||
private JPanel myRootPanel;
|
|
||||||
private JButton myAcceptYoursButton;
|
|
||||||
private JButton myAcceptTheirsButton;
|
|
||||||
private JButton myMergeButton;
|
|
||||||
private TableView<VirtualFile> myTable;
|
|
||||||
private JBLabel myDescriptionLabel;
|
|
||||||
private final MergeProvider myProvider;
|
|
||||||
@Nullable private final MergeSession myMergeSession;
|
|
||||||
private final List<VirtualFile> myFiles;
|
|
||||||
private final ListTableModel<VirtualFile> myModel;
|
|
||||||
@Nullable
|
|
||||||
private final Project myProject;
|
|
||||||
private final ProjectManagerEx myProjectManager;
|
|
||||||
private final List<VirtualFile> myProcessedFiles = new SmartList<>();
|
|
||||||
private final Set<VirtualFile> myBinaryFiles = new HashSet<>();
|
|
||||||
private final MergeDialogCustomizer myMergeDialogCustomizer;
|
|
||||||
|
|
||||||
private final VirtualFileRenderer myVirtualFileRenderer = new VirtualFileRenderer();
|
|
||||||
|
|
||||||
public MultipleFileMergeDialog(@Nullable Project project, @NotNull final List<VirtualFile> files, @NotNull final MergeProvider provider,
|
|
||||||
@NotNull MergeDialogCustomizer mergeDialogCustomizer) {
|
|
||||||
super(project);
|
|
||||||
|
|
||||||
myProject = project;
|
|
||||||
myProjectManager = ProjectManagerEx.getInstanceEx();
|
|
||||||
myProjectManager.blockReloadingProjectOnExternalChanges();
|
|
||||||
myFiles = new ArrayList<>(files);
|
|
||||||
myProvider = provider;
|
|
||||||
myMergeDialogCustomizer = mergeDialogCustomizer;
|
|
||||||
|
|
||||||
final String description = myMergeDialogCustomizer.getMultipleFileMergeDescription(files);
|
|
||||||
if (!StringUtil.isEmptyOrSpaces(description)) {
|
|
||||||
myDescriptionLabel.setText(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ColumnInfo> columns = new ArrayList<>();
|
|
||||||
columns.add(new ColumnInfo<VirtualFile, VirtualFile>(VcsBundle.message("multiple.file.merge.column.name")) {
|
|
||||||
@Override
|
|
||||||
public VirtualFile valueOf(final VirtualFile virtualFile) {
|
|
||||||
return virtualFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TableCellRenderer getRenderer(final VirtualFile virtualFile) {
|
|
||||||
return myVirtualFileRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public Comparator<VirtualFile> getComparator() {
|
|
||||||
return VirtualFileComparator.INSTANCE;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
columns.add(new ColumnInfo<VirtualFile, String>(VcsBundle.message("multiple.file.merge.column.type")) {
|
|
||||||
@Override
|
|
||||||
public String valueOf(final VirtualFile virtualFile) {
|
|
||||||
return myBinaryFiles.contains(virtualFile)
|
|
||||||
? VcsBundle.message("multiple.file.merge.type.binary")
|
|
||||||
: VcsBundle.message("multiple.file.merge.type.text");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMaxStringValue() {
|
|
||||||
return VcsBundle.message("multiple.file.merge.type.binary");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getAdditionalWidth() {
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (myProvider instanceof MergeProvider2) {
|
|
||||||
myMergeSession = ((MergeProvider2)myProvider).createMergeSession(files);
|
|
||||||
Collections.addAll(columns, myMergeSession.getMergeInfoColumns());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myMergeSession = null;
|
|
||||||
}
|
|
||||||
myModel = new ListTableModel<>(columns.toArray(ColumnInfo.EMPTY_ARRAY));
|
|
||||||
myModel.setItems(new ArrayList<>(myFiles));
|
|
||||||
myTable.setModelAndUpdateColumns(myModel);
|
|
||||||
myVirtualFileRenderer.setFont(UIUtil.getListFont());
|
|
||||||
myTable.setRowHeight(myVirtualFileRenderer.getPreferredSize().height);
|
|
||||||
setTitle(myMergeDialogCustomizer.getMultipleFileDialogTitle());
|
|
||||||
init();
|
|
||||||
myAcceptYoursButton.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(@NotNull ActionEvent e) {
|
|
||||||
acceptRevision(MergeSession.Resolution.AcceptedYours);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
myAcceptTheirsButton.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(@NotNull ActionEvent e) {
|
|
||||||
acceptRevision(MergeSession.Resolution.AcceptedTheirs);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
|
||||||
@Override
|
|
||||||
public void valueChanged(@NotNull final ListSelectionEvent e) {
|
|
||||||
updateButtonState();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
for (VirtualFile file : files) {
|
|
||||||
if (file.getFileType().isBinary() || provider.isBinary(file)) {
|
|
||||||
myBinaryFiles.add(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
myTable.getSelectionModel().setSelectionInterval(0, 0);
|
|
||||||
new DoubleClickListener() {
|
|
||||||
@Override
|
|
||||||
protected boolean onDoubleClick(MouseEvent event) {
|
|
||||||
showMergeDialog();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}.installOn(myTable);
|
|
||||||
new TableSpeedSearch(myTable, o -> {
|
|
||||||
if (o instanceof VirtualFile) {
|
|
||||||
return ((VirtualFile)o).getName();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doCancelAction() {
|
|
||||||
if (!myProcessedFiles.isEmpty()) {
|
|
||||||
myProvider.mergeDone(myProcessedFiles);
|
|
||||||
}
|
|
||||||
super.doCancelAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateButtonState() {
|
|
||||||
boolean haveSelection = myTable.getSelectedRowCount() > 0;
|
|
||||||
boolean haveUnmergeableFiles = false;
|
|
||||||
for (VirtualFile file : myTable.getSelection()) {
|
|
||||||
if (myMergeSession != null) {
|
|
||||||
boolean canMerge = myMergeSession.canMerge(file);
|
|
||||||
if (!canMerge) {
|
|
||||||
haveUnmergeableFiles = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
myAcceptYoursButton.setEnabled(haveSelection);
|
|
||||||
myAcceptTheirsButton.setEnabled(haveSelection);
|
|
||||||
myMergeButton.setEnabled(haveSelection && !haveUnmergeableFiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
protected JComponent createCenterPanel() {
|
|
||||||
return myRootPanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
protected Action[] createActions() {
|
|
||||||
return new Action[]{getCancelAction()};
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
protected Action getCancelAction() {
|
|
||||||
Action action = super.getCancelAction();
|
|
||||||
action.putValue(Action.NAME, CommonBundle.getCloseButtonText());
|
|
||||||
return action;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void dispose() {
|
|
||||||
myProjectManager.unblockReloadingProjectOnExternalChanges();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean beforeResolve(Collection<VirtualFile> files) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@NonNls
|
|
||||||
protected String getDimensionServiceKey() {
|
|
||||||
return "MultipleFileMergeDialog";
|
|
||||||
}
|
|
||||||
|
|
||||||
private void acceptRevision(@NotNull MergeSession.Resolution resolution) {
|
|
||||||
FileDocumentManager.getInstance().saveAllDocuments();
|
|
||||||
final Collection<VirtualFile> files = myTable.getSelection();
|
|
||||||
if (!beforeResolve(files)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (VirtualFile file : files) {
|
|
||||||
acceptFileRevision(file, resolution);
|
|
||||||
checkMarkModifiedProject(file);
|
|
||||||
markFileProcessed(file, resolution);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
LOG.warn(e);
|
|
||||||
Messages.showErrorDialog(myRootPanel, "Error saving merged data: " + e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
updateModelFromFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void acceptFileRevision(@NotNull VirtualFile file, @NotNull MergeSession.Resolution resolution) throws Exception {
|
|
||||||
if (myMergeSession != null && !myMergeSession.canMerge(file)) return;
|
|
||||||
|
|
||||||
if (!DiffUtil.makeWritable(myProject, file)) {
|
|
||||||
throw new IOException("File is read-only: " + file.getPresentableName());
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isCurrent = resolution == MergeSession.Resolution.AcceptedYours;
|
|
||||||
MergeData data = myProvider.loadRevisions(file);
|
|
||||||
|
|
||||||
Ref<Exception> ex = new Ref<>();
|
|
||||||
CommandProcessor.getInstance().executeCommand(myProject, () -> {
|
|
||||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
|
||||||
try {
|
|
||||||
if (isCurrent) {
|
|
||||||
file.setBinaryContent(data.CURRENT);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
file.setBinaryContent(data.LAST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
ex.set(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, "Accept " + (isCurrent ? "Yours" : "Theirs"), null);
|
|
||||||
|
|
||||||
if (!ex.isNull()) throw ex.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void markFileProcessed(@NotNull VirtualFile file, @NotNull MergeSession.Resolution resolution) {
|
|
||||||
myFiles.remove(file);
|
|
||||||
if (myMergeSession != null) {
|
|
||||||
myMergeSession.conflictResolvedForFile(file, resolution);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myProvider.conflictResolvedForFile(file);
|
|
||||||
}
|
|
||||||
myProcessedFiles.add(file);
|
|
||||||
if (myProject != null) {
|
|
||||||
VcsDirtyScopeManager.getInstance(myProject).fileDirty(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateModelFromFiles() {
|
|
||||||
if (myFiles.isEmpty()) {
|
|
||||||
doCancelAction();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int selIndex = myTable.getSelectionModel().getMinSelectionIndex();
|
|
||||||
myModel.setItems(new ArrayList<>(myFiles));
|
|
||||||
if (selIndex >= myFiles.size()) {
|
|
||||||
selIndex = myFiles.size() - 1;
|
|
||||||
}
|
|
||||||
myTable.getSelectionModel().setSelectionInterval(selIndex, selIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showMergeDialog() {
|
|
||||||
DiffRequestFactory requestFactory = DiffRequestFactory.getInstance();
|
|
||||||
Collection<VirtualFile> files = myTable.getSelection();
|
|
||||||
if (!beforeResolve(files)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final VirtualFile file : files) {
|
|
||||||
final MergeData mergeData;
|
|
||||||
try {
|
|
||||||
mergeData = myProvider.loadRevisions(file);
|
|
||||||
}
|
|
||||||
catch (VcsException ex) {
|
|
||||||
Messages.showErrorDialog(myRootPanel, "Error loading revisions to merge: " + ex.getMessage());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mergeData.CURRENT == null || mergeData.LAST == null || mergeData.ORIGINAL == null) {
|
|
||||||
Messages.showErrorDialog(myRootPanel, "Error loading revisions to merge");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
String leftTitle = myMergeDialogCustomizer.getLeftPanelTitle(file);
|
|
||||||
String baseTitle = myMergeDialogCustomizer.getCenterPanelTitle(file);
|
|
||||||
String rightTitle = myMergeDialogCustomizer.getRightPanelTitle(file, mergeData.LAST_REVISION_NUMBER);
|
|
||||||
String title = myMergeDialogCustomizer.getMergeWindowTitle(file);
|
|
||||||
|
|
||||||
final List<byte[]> byteContents = ContainerUtil.list(mergeData.CURRENT, mergeData.ORIGINAL, mergeData.LAST);
|
|
||||||
List<String> contentTitles = ContainerUtil.list(leftTitle, baseTitle, rightTitle);
|
|
||||||
|
|
||||||
Consumer<MergeResult> callback = result -> {
|
|
||||||
Document document = FileDocumentManager.getInstance().getCachedDocument(file);
|
|
||||||
if (document != null) FileDocumentManager.getInstance().saveDocument(document);
|
|
||||||
checkMarkModifiedProject(file);
|
|
||||||
|
|
||||||
if (result != MergeResult.CANCEL) {
|
|
||||||
markFileProcessed(file, getSessionResolution(result));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MergeRequest request;
|
|
||||||
try {
|
|
||||||
if (myProvider.isBinary(file)) { // respect MIME-types in svn
|
|
||||||
request = requestFactory.createBinaryMergeRequest(myProject, file, byteContents, title, contentTitles, callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
request = requestFactory.createMergeRequest(myProject, file, byteContents, title, contentTitles, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
MergeUtil.putRevisionInfos(request, mergeData);
|
|
||||||
}
|
|
||||||
catch (InvalidDiffRequestException e) {
|
|
||||||
LOG.error(e);
|
|
||||||
Messages.showErrorDialog(myRootPanel, "Can't show merge dialog");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DiffManager.getInstance().showMerge(myProject, request);
|
|
||||||
}
|
|
||||||
updateModelFromFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static MergeSession.Resolution getSessionResolution(@NotNull MergeResult result) {
|
|
||||||
switch (result) {
|
|
||||||
case LEFT:
|
|
||||||
return MergeSession.Resolution.AcceptedYours;
|
|
||||||
case RIGHT:
|
|
||||||
return MergeSession.Resolution.AcceptedTheirs;
|
|
||||||
case RESOLVED:
|
|
||||||
return MergeSession.Resolution.Merged;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException(result.name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkMarkModifiedProject(@NotNull VirtualFile file) {
|
|
||||||
MergeVersion.MergeDocumentVersion.reportProjectFileChangeIfNeeded(myProject, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createUIComponents() {
|
|
||||||
Action mergeAction = new AbstractAction() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(@NotNull ActionEvent e) {
|
|
||||||
showMergeDialog();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mergeAction.putValue(DEFAULT_ACTION, Boolean.TRUE);
|
|
||||||
myMergeButton = createJButtonForAction(mergeAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JComponent getPreferredFocusedComponent() {
|
|
||||||
return myTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public List<VirtualFile> getProcessedFiles() {
|
|
||||||
return myProcessedFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class VirtualFileRenderer extends ColoredTableCellRenderer {
|
|
||||||
@Override
|
|
||||||
protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) {
|
|
||||||
VirtualFile vf = (VirtualFile)value;
|
|
||||||
setIcon(VirtualFilePresentation.getIcon(vf));
|
|
||||||
append(vf.getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
|
||||||
final VirtualFile parent = vf.getParent();
|
|
||||||
if (parent != null) {
|
|
||||||
append(" (" + FileUtil.toSystemDependentName(parent.getPresentableUrl()) + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
|
||||||
}
|
|
||||||
SpeedSearchUtil.applySpeedSearchHighlighting(myTable, this, true, selected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class VirtualFileComparator implements Comparator<VirtualFile> {
|
|
||||||
public static final VirtualFileComparator INSTANCE = new VirtualFileComparator();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(VirtualFile file1, VirtualFile file2) {
|
|
||||||
int delta = StringUtil.naturalCompare(file1.getName(), file2.getName());
|
|
||||||
if (delta != 0) return delta;
|
|
||||||
|
|
||||||
VirtualFile parent1 = file1.getParent();
|
|
||||||
VirtualFile parent2 = file2.getParent();
|
|
||||||
String path1 = parent1 != null ? parent1.getPath() : null;
|
|
||||||
String path2 = parent2 != null ? parent2.getPath() : null;
|
|
||||||
return StringUtil.naturalCompare(path1, path2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+12
-3
@@ -52,7 +52,7 @@ import javax.swing.tree.TreeNode
|
|||||||
/**
|
/**
|
||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
open class MultipleFileMergeDialog2(
|
open class MultipleFileMergeDialog(
|
||||||
private val project: Project,
|
private val project: Project,
|
||||||
files: List<VirtualFile>,
|
files: List<VirtualFile>,
|
||||||
private val mergeProvider: MergeProvider,
|
private val mergeProvider: MergeProvider,
|
||||||
@@ -71,7 +71,7 @@ open class MultipleFileMergeDialog2(
|
|||||||
private var groupByDirectory = VcsConfiguration.getInstance(project).GROUP_MULTIFILE_MERGE_BY_DIRECTORY
|
private var groupByDirectory = VcsConfiguration.getInstance(project).GROUP_MULTIFILE_MERGE_BY_DIRECTORY
|
||||||
|
|
||||||
private val virtualFileRenderer = object : ChangesBrowserNodeRenderer(project, { !groupByDirectory }, false) {
|
private val virtualFileRenderer = object : ChangesBrowserNodeRenderer(project, { !groupByDirectory }, false) {
|
||||||
override fun calcFocusedState() = UIUtil.isAncestor(this@MultipleFileMergeDialog2.peer.window, IdeFocusManager.getInstance(project).focusOwner)
|
override fun calcFocusedState() = UIUtil.isAncestor(this@MultipleFileMergeDialog.peer.window, IdeFocusManager.getInstance(project).focusOwner)
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -232,12 +232,21 @@ open class MultipleFileMergeDialog2(
|
|||||||
@NonNls
|
@NonNls
|
||||||
override fun getDimensionServiceKey(): String = "MultipleFileMergeDialog"
|
override fun getDimensionServiceKey(): String = "MultipleFileMergeDialog"
|
||||||
|
|
||||||
|
@JvmSuppressWildcards
|
||||||
|
protected open fun beforeResolve(files: Collection<VirtualFile>): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
private fun acceptRevision(resolution: MergeSession.Resolution) {
|
private fun acceptRevision(resolution: MergeSession.Resolution) {
|
||||||
assert(resolution == MergeSession.Resolution.AcceptedYours || resolution == MergeSession.Resolution.AcceptedTheirs)
|
assert(resolution == MergeSession.Resolution.AcceptedYours || resolution == MergeSession.Resolution.AcceptedTheirs)
|
||||||
|
|
||||||
FileDocumentManager.getInstance().saveAllDocuments()
|
FileDocumentManager.getInstance().saveAllDocuments()
|
||||||
val files = getSelectedFiles()
|
val files = getSelectedFiles()
|
||||||
|
|
||||||
|
if (!beforeResolve(files)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (mergeSession is MergeSessionEx) {
|
if (mergeSession is MergeSessionEx) {
|
||||||
val supportedFiles = files.filter { file -> mergeSession.canMerge(file) }
|
val supportedFiles = files.filter { file -> mergeSession.canMerge(file) }
|
||||||
@@ -399,7 +408,7 @@ open class MultipleFileMergeDialog2(
|
|||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val LOG = Logger.getInstance(MultipleFileMergeDialog2::class.java)
|
private val LOG = Logger.getInstance(MultipleFileMergeDialog::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.application.invokeAndWaitIfNeed
|
|||||||
import com.intellij.openapi.diagnostic.debug
|
import com.intellij.openapi.diagnostic.debug
|
||||||
import com.intellij.openapi.diagnostic.runAndLogException
|
import com.intellij.openapi.diagnostic.runAndLogException
|
||||||
import com.intellij.openapi.fileTypes.StdFileTypes
|
import com.intellij.openapi.fileTypes.StdFileTypes
|
||||||
|
import com.intellij.openapi.project.ProjectManager
|
||||||
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer
|
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer
|
||||||
import com.intellij.openapi.vcs.merge.MergeProvider2
|
import com.intellij.openapi.vcs.merge.MergeProvider2
|
||||||
import com.intellij.openapi.vcs.merge.MultipleFileMergeDialog
|
import com.intellij.openapi.vcs.merge.MultipleFileMergeDialog
|
||||||
@@ -167,7 +168,7 @@ fun resolveConflicts(files: List<VirtualFile>, mergeProvider: MergeProvider2): L
|
|||||||
|
|
||||||
var processedFiles: List<VirtualFile>? = null
|
var processedFiles: List<VirtualFile>? = null
|
||||||
invokeAndWaitIfNeed {
|
invokeAndWaitIfNeed {
|
||||||
val fileMergeDialog = MultipleFileMergeDialog(null, files, mergeProvider, object : MergeDialogCustomizer() {
|
val fileMergeDialog = MultipleFileMergeDialog(ProjectManager.getInstance().defaultProject, files, mergeProvider, object : MergeDialogCustomizer() {
|
||||||
override fun getMultipleFileDialogTitle() = "Settings Repository: Files Merged with Conflicts"
|
override fun getMultipleFileDialogTitle() = "Settings Repository: Files Merged with Conflicts"
|
||||||
})
|
})
|
||||||
fileMergeDialog.show()
|
fileMergeDialog.show()
|
||||||
|
|||||||
Reference in New Issue
Block a user