Skip to main content

This CGIT instance is deprecated, and repositories have been moved to Gitlab or Github. See the repository descriptions for specific locations.

summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathieu Cartaud2015-10-22 14:33:35 +0000
committerLaurent Goubet2017-09-05 09:07:56 +0000
commit93ee76a711336009235b3c726c363cd874bc7577 (patch)
tree1fff6c1cb2c89f74529614bef21935b7ab6327c6
parenteefca4ff471b5521ec1eab57286678d9294c68d7 (diff)
downloadorg.eclipse.emf.compare-93ee76a711336009235b3c726c363cd874bc7577.tar.gz
org.eclipse.emf.compare-93ee76a711336009235b3c726c363cd874bc7577.tar.xz
org.eclipse.emf.compare-93ee76a711336009235b3c726c363cd874bc7577.zip
[462863] Staging Prompt after Resolving Conflicts
This change is a revised version of change 52072, which was reverted due to undetected issues. The issues included the fact that the dialog was shown despite the fact that no conflicts were involved, and also that files to be staged were listed multiple times. The changes w.r.t. change 52072 were done in the following files: * MergeResolutionManager.java (lines 76-79, an if block was added) * PostMergeStager.java (line 58, a set is used instead of a list) Following is the original change content: After resolving conflicts in the (Compare) Merge Tool, the user is now prompted with a dialog stating that all conflicts in the model have been resolved, and asking whether the files containing the changes should be staged. This is not only an improvement saving some users' clicks, it also helps to avoid staging so far still unmerged model resources. From a user-perspective, it is not obvious which model resources are part of the logical model being currently merged in the merge tool. So if there is a conflicting merge that needs manual resolution, the user opens a conflicting resource in the merge tool. After conflicts have been resolved, users want to stage all model resources that have been resolved currently in the merge session, but it is hard to identify those that they can safely stage already. So users are inclined to stage not merged models, which basically leads to omitting all changes on the remote side. Bug: 462863 Change-Id: Ice31ce3dde4b6f45de0f7cf8d90be00806341a55 Signed-off-by: Mathieu Cartaud <mathieu.cartaud@obeo.fr> Also-by: Michael Borkowski <mborkowski@eclipsesource.com>
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/META-INF/MANIFEST.MF6
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/egit/mergeresolution/MergeResolutionManagerTest.java145
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/suite/PapyrusGitTests.java4
-rwxr-xr-xplugins/org.eclipse.emf.compare.egit.ui/META-INF/MANIFEST.MF4
-rwxr-xr-xplugins/org.eclipse.emf.compare.egit.ui/plugin.xml7
-rw-r--r--plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/merge/ModelGitMergeEditorInput.java8
-rw-r--r--plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/mergeresolution/PostMergeDialog.java161
-rw-r--r--plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/mergeresolution/PostMergeStager.java142
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/mergeresolution/MergeResolutionManager.java14
9 files changed, 482 insertions, 9 deletions
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/META-INF/MANIFEST.MF
index 252b06600..f4d251b83 100644
--- a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/META-INF/MANIFEST.MF
@@ -17,4 +17,8 @@ Require-Bundle: org.eclipse.emf.compare.egit;bundle-version="1.1.0",
org.eclipse.papyrus.uml.tools,
org.eclipse.emf.compare.rcp,
org.eclipse.emf.compare.ide.ui.tests.git.framework,
- org.eclipse.emf.compare.ide.ui.tests.framework
+ org.eclipse.emf.compare.ide.ui.tests.framework,
+ org.mockito;bundle-version="1.8.0",
+ org.hamcrest;bundle-version="1.1.0",
+ org.eclipse.emf.common;bundle-version="2.11.0"
+Import-Package: org.eclipse.emf.compare.ide.ui.tests
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/egit/mergeresolution/MergeResolutionManagerTest.java b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/egit/mergeresolution/MergeResolutionManagerTest.java
new file mode 100644
index 000000000..e6089d0e3
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/egit/mergeresolution/MergeResolutionManagerTest.java
@@ -0,0 +1,145 @@
+package org.eclipse.emf.compare.diagram.papyrus.tests.egit.mergeresolution;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.Conflict;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.DifferenceState;
+import org.eclipse.emf.compare.Match;
+import org.eclipse.emf.compare.ide.ui.internal.mergeresolution.MergeResolutionListenerRegistry;
+import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.provider.TreeNodeCompareInput;
+import org.eclipse.emf.compare.ide.ui.mergeresolution.MergeResolutionManager;
+import org.junit.Before;
+import org.junit.Test;
+
+@SuppressWarnings("restriction")
+public class MergeResolutionManagerTest {
+ MergeResolutionManager sut;
+
+ MergeResolutionListenerRegistry registry;
+
+ @Before
+ public void setUp() {
+ registry = mock(MergeResolutionListenerRegistry.class);
+
+ sut = new MergeResolutionManager(registry);
+ }
+
+ @Test
+ public void testInvalidInput() {
+ sut.handleFlush(null);
+ sut.handleFlush("not a valid input");
+
+ verifyNoMoreInteractions(registry);
+ }
+
+ @Test
+ public void testNoConflicts() {
+ EList<Conflict> conflicts = new BasicEList<Conflict>();
+
+ Comparison comparison = mock(Comparison.class);
+ when(comparison.getConflicts()).thenReturn(conflicts);
+
+ sut.handleFlush(pack(comparison));
+ verify(comparison).getConflicts();
+ verifyNoMoreInteractions(registry);
+ }
+
+ @Test
+ public void testOnlyUnresolvedConflicts() {
+ EList<Conflict> conflicts = new BasicEList<Conflict>();
+
+ Conflict c1 = mock(Conflict.class);
+ EList<Diff> c1d = new BasicEList<Diff>();
+ c1d.add((Diff) when(mock(Diff.class).getState()).thenReturn(DifferenceState.UNRESOLVED).getMock());
+ c1d.add((Diff) when(mock(Diff.class).getState()).thenReturn(DifferenceState.UNRESOLVED).getMock());
+ when(c1.getDifferences()).thenReturn(c1d);
+ conflicts.add(c1);
+
+ Conflict c2 = mock(Conflict.class);
+ EList<Diff> c2d = new BasicEList<Diff>();
+ c1d.add((Diff) when(mock(Diff.class).getState()).thenReturn(DifferenceState.UNRESOLVED).getMock());
+ c1d.add((Diff) when(mock(Diff.class).getState()).thenReturn(DifferenceState.UNRESOLVED).getMock());
+ when(c2.getDifferences()).thenReturn(c2d);
+ conflicts.add(c2);
+
+ Comparison comparison = mock(Comparison.class);
+ when(comparison.getConflicts()).thenReturn(conflicts);
+
+ sut.handleFlush(pack(comparison));
+ verify(comparison, atLeastOnce()).getConflicts();
+ verifyNoMoreInteractions(registry);
+ }
+
+ @Test
+ public void testMixedConflicts() {
+ EList<Conflict> conflicts = new BasicEList<Conflict>();
+
+ Conflict c1 = mock(Conflict.class);
+ EList<Diff> c1d = new BasicEList<Diff>();
+ c1d.add((Diff) when(mock(Diff.class).getState()).thenReturn(DifferenceState.UNRESOLVED).getMock());
+ c1d.add((Diff) when(mock(Diff.class).getState()).thenReturn(DifferenceState.UNRESOLVED).getMock());
+ when(c1.getDifferences()).thenReturn(c1d);
+ conflicts.add(c1);
+
+ Conflict c2 = mock(Conflict.class);
+ EList<Diff> c2d = new BasicEList<Diff>();
+ c2d.add((Diff) when(mock(Diff.class).getState()).thenReturn(DifferenceState.MERGED).getMock());
+ c2d.add((Diff) when(mock(Diff.class).getState()).thenReturn(DifferenceState.DISCARDED).getMock());
+ when(c2.getDifferences()).thenReturn(c2d);
+ conflicts.add(c2);
+
+ Comparison comparison = mock(Comparison.class);
+ when(comparison.getConflicts()).thenReturn(conflicts);
+
+ sut.handleFlush(pack(comparison));
+ verify(comparison, atLeastOnce()).getConflicts();
+ verifyNoMoreInteractions(registry);
+ }
+
+ @Test
+ public void testOnlyResolvedConflicts() {
+ EList<Conflict> conflicts = new BasicEList<Conflict>();
+
+ Conflict c1 = mock(Conflict.class);
+ EList<Diff> c1d = new BasicEList<Diff>();
+ c1d.add((Diff) when(mock(Diff.class).getState()).thenReturn(DifferenceState.DISCARDED).getMock());
+ c1d.add((Diff) when(mock(Diff.class).getState()).thenReturn(DifferenceState.MERGED).getMock());
+ when(c1.getDifferences()).thenReturn(c1d);
+ conflicts.add(c1);
+
+ Conflict c2 = mock(Conflict.class);
+ EList<Diff> c2d = new BasicEList<Diff>();
+ c2d.add((Diff) when(mock(Diff.class).getState()).thenReturn(DifferenceState.MERGED).getMock());
+ c2d.add((Diff) when(mock(Diff.class).getState()).thenReturn(DifferenceState.DISCARDED).getMock());
+ when(c2.getDifferences()).thenReturn(c2d);
+ conflicts.add(c2);
+
+ Comparison comparison = mock(Comparison.class);
+ when(comparison.getConflicts()).thenReturn(conflicts);
+
+ sut.handleFlush(pack(comparison));
+ verify(comparison, atLeastOnce()).getConflicts();
+ verify(registry).mergeResolutionCompleted(comparison);
+ verifyNoMoreInteractions(registry);
+ }
+
+ private Object pack(Comparison comparison) {
+ Match match = mock(Match.class);
+ when(match.getComparison()).thenReturn(comparison).getMock();
+
+ TreeNodeCompareInput treeNodeCompareInput = mock(TreeNodeCompareInput.class);
+ when(treeNodeCompareInput.getComparisonObject()).thenReturn(match);
+
+ return treeNodeCompareInput;
+
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/suite/PapyrusGitTests.java b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/suite/PapyrusGitTests.java
index bad00d1ca..c6c1630e1 100644
--- a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/suite/PapyrusGitTests.java
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/suite/PapyrusGitTests.java
@@ -21,6 +21,7 @@ import org.eclipse.emf.compare.diagram.papyrus.tests.egit.ResourceAttachmentChan
import org.eclipse.emf.compare.diagram.papyrus.tests.egit.ResourceAttachmentChangeDelete1GitMergeTest;
import org.eclipse.emf.compare.diagram.papyrus.tests.egit.ResourceAttachmentChangeDelete2GitMergeTest;
import org.eclipse.emf.compare.diagram.papyrus.tests.egit.StereotypeConflictTest;
+import org.eclipse.emf.compare.diagram.papyrus.tests.egit.mergeresolution.MergeResolutionManagerTest;
import org.eclipse.emf.compare.diagram.papyrus.tests.merge.AdditiveMergeDiagramTests;
import org.eclipse.emf.compare.diagram.papyrus.tests.resourceattachmentchange.implication.AttachmentChangeImplicationTest;
import org.eclipse.emf.compare.diagram.papyrus.tests.resourceattachmentchange.move.ResourceAttachmentChangeMoveConflictTests;
@@ -50,7 +51,8 @@ import junit.textui.TestRunner;
ResourceAttachmentChangeDelete2GitMergeTest.class, ResourceAttachmentChangeMoveConflictTests.class,
ResourceAttachmentChangeMoveNoConflictTests.class, ResourceAttachmentChangeMoveOrderTests.class,
StereotypeConflictTest.class, IgnoreDiFileChangesInGitMergeTest.class,
- MoveOfDiagramConflictDetectionTest.class, AdditiveMergeDiagramTests.class, })
+ MoveOfDiagramConflictDetectionTest.class, AdditiveMergeDiagramTests.class,
+ MergeResolutionManagerTest.class, })
public class PapyrusGitTests {
/**
* Launches the test with the given arguments.
diff --git a/plugins/org.eclipse.emf.compare.egit.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.compare.egit.ui/META-INF/MANIFEST.MF
index 3901b7472..3e51fd608 100755
--- a/plugins/org.eclipse.emf.compare.egit.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.compare.egit.ui/META-INF/MANIFEST.MF
@@ -16,8 +16,10 @@ Require-Bundle: org.eclipse.emf.compare.egit,
org.eclipse.team.ui,
org.eclipse.egit.core,
org.eclipse.ui.ide,
+ org.eclipse.emf.compare,
org.eclipse.emf.compare.ide.ui,
- org.eclipse.emf.compare.ide
+ org.eclipse.emf.compare.ide,
+ org.eclipse.egit
Bundle-Vendor: %providerName
Export-Package: org.eclipse.emf.compare.egit.ui.internal;x-internal:=true,
org.eclipse.emf.compare.egit.ui.internal.actions;x-internal:=true,
diff --git a/plugins/org.eclipse.emf.compare.egit.ui/plugin.xml b/plugins/org.eclipse.emf.compare.egit.ui/plugin.xml
index a7a6986d4..8edd4d268 100755
--- a/plugins/org.eclipse.emf.compare.egit.ui/plugin.xml
+++ b/plugins/org.eclipse.emf.compare.egit.ui/plugin.xml
@@ -11,6 +11,7 @@
Contributors:
Obeo - initial API and implementation
+ Michael Borkowski - bug 462863 (Automatic staging of changes after merge resolution)
-->
@@ -38,4 +39,10 @@
class="org.eclipse.emf.compare.egit.ui.internal.logical.SingleRepositoryMinimizer">
</modelMinimizer>
</extension>
+ <extension
+ point="org.eclipse.emf.compare.ide.ui.mergeResolutionListener">
+ <listener
+ class="org.eclipse.emf.compare.egit.ui.internal.mergeresolution.PostMergeStager">
+ </listener>
+ </extension>
</plugin>
diff --git a/plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/merge/ModelGitMergeEditorInput.java b/plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/merge/ModelGitMergeEditorInput.java
index 9a62bd975..e3a7ab045 100644
--- a/plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/merge/ModelGitMergeEditorInput.java
+++ b/plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/merge/ModelGitMergeEditorInput.java
@@ -5,6 +5,9 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Michael Borkowski - initial API and implementation
*******************************************************************************/
package org.eclipse.emf.compare.egit.ui.internal.merge;
@@ -732,5 +735,10 @@ public class ModelGitMergeEditorInput extends CompareEditorInput {
// Won't be used as a merging context
}
}
+
+ @Override
+ protected void flushViewers(IProgressMonitor monitor) {
+ super.flushViewers(monitor);
+ }
}
// CHECKSTYLE:ON
diff --git a/plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/mergeresolution/PostMergeDialog.java b/plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/mergeresolution/PostMergeDialog.java
new file mode 100644
index 000000000..cf097938a
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/mergeresolution/PostMergeDialog.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2015 EclipseSource GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Michael Borkowski - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.egit.ui.internal.mergeresolution;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.emf.compare.egit.ui.internal.EMFCompareEGitUIMessages;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
+import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.StyledString;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+/**
+ * Dialog for displaying a dialog after resolving a merge conflict.
+ *
+ * @author Michael Borkowski <mborkowski@eclipsesource.com>
+ */
+public class PostMergeDialog extends Dialog {
+ /**
+ * UI margin for left and right of dialog.
+ */
+ private static final int MARGIN_WIDTH = 15;
+
+ /**
+ * UI margin for top for dialog.
+ */
+ private static final int MARGIN_TOP = 15;
+
+ /**
+ * UI vertical margin between label and list.
+ */
+ private static final int VERTICAL_SPACING = 10;
+
+ /**
+ * The resources to be staged.
+ */
+ private final IResource[] resources;
+
+ /**
+ * Creates a new {@link PostMergeDialog}.
+ *
+ * @param parentShell
+ * the parent shell
+ * @param resources
+ * the resources to be staged
+ */
+ public PostMergeDialog(Shell parentShell, IResource[] resources) {
+ super(parentShell);
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ setBlockOnOpen(true);
+ this.resources = resources;
+ }
+
+ @Override
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ shell.setText(EMFCompareEGitUIMessages.getString("post.merge.dialog.title")); //$NON-NLS-1$
+ }
+
+ @Override
+ public Control createDialogArea(final Composite parent) {
+ final Composite composite = (Composite)super.createDialogArea(parent);
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ gridLayout.verticalSpacing = VERTICAL_SPACING;
+ gridLayout.marginWidth = MARGIN_WIDTH;
+ gridLayout.marginTop = MARGIN_TOP;
+ composite.setLayout(gridLayout);
+ // result
+ Label resultLabel = new Label(composite, SWT.NONE);
+ resultLabel.setText(EMFCompareEGitUIMessages.getString("post.merge.dialog.text")); //$NON-NLS-1$
+ resultLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
+
+ TableViewer viewer = new TableViewer(composite);
+
+ viewer.setContentProvider(ArrayContentProvider.getInstance());
+
+ final IStyledLabelProvider styleProvider = new ListStyleProvider();
+ viewer.setLabelProvider(new DelegatingStyledCellLabelProvider(styleProvider));
+ applyDialogFont(composite);
+ GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL)
+ .applyTo(viewer.getControl());
+ viewer.setInput(resources);
+
+ return composite;
+ }
+
+ /**
+ * Helper class for styling items.
+ *
+ * @author <mborkowski@eclipsesource.com>
+ */
+ public class ListStyleProvider implements IStyledLabelProvider {
+ /**
+ * The label provider.
+ */
+ private final WorkbenchLabelProvider wrapped = new WorkbenchLabelProvider();
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeListener(ILabelProviderListener listener) {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dispose() {
+ wrapped.dispose();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StyledString getStyledText(Object element) {
+ IResource resource = (IResource)element;
+ return new StyledString(resource.getProjectRelativePath().toString());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Image getImage(Object element) {
+ return wrapped.getImage(element);
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/mergeresolution/PostMergeStager.java b/plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/mergeresolution/PostMergeStager.java
new file mode 100644
index 000000000..d180589e1
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.egit.ui/src/org/eclipse/emf/compare/egit/ui/internal/mergeresolution/PostMergeStager.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2015 EclipseSource GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Michael Borkowski - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.egit.ui.internal.mergeresolution;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.MatchResource;
+import org.eclipse.emf.compare.ide.ui.internal.logical.resolver.DefaultImplicitDependencies;
+import org.eclipse.emf.compare.ide.ui.mergeresolution.IMergeResolutionListener;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jgit.api.AddCommand;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.NoFilepatternException;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Responsible for prompting the user about staging files after merge conflict resolution.
+ *
+ * @author Michael Borkowski <mborkowski@eclipsesource.com>
+ */
+@SuppressWarnings({"restriction" })
+public class PostMergeStager implements IMergeResolutionListener {
+
+ /**
+ * The default dependency resolver.
+ */
+ private final DefaultImplicitDependencies dependencies = new DefaultImplicitDependencies();
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see IMergeResolutionListener#mergeResolutionCompleted(Comparison)
+ */
+ public void mergeResolutionCompleted(Comparison comparison) {
+ EList<MatchResource> matchResources = comparison.getMatchedResources();
+ final List<IResource> resources = new ArrayList<IResource>();
+ for (MatchResource matchResource : matchResources) {
+ Resource left = matchResource.getLeft();
+ if (left != null) {
+ URI matchUri = left.getURI();
+ Set<URI> dependencyUris = dependencies.of(matchUri, left.getResourceSet().getURIConverter());
+
+ for (URI uri : dependencyUris) {
+ // FIXME: this feature will fail with resources that are not in the workspace (bug 478513)
+ IResource resource = getResourceFromURI(uri);
+ if (!resources.contains(resource)) {
+ resources.add(resource);
+ }
+ }
+ }
+ }
+
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ promptUser(resources.toArray(new IResource[resources.size()]));
+ }
+ });
+ }
+
+ /**
+ * Prompt the user about the specified resources.
+ *
+ * @param resources
+ * the resources to be staged
+ */
+ private void promptUser(IResource[] resources) {
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ int result = new PostMergeDialog(shell, resources).open();
+ if (IDialogConstants.OK_ID == result) {
+ for (IResource resource : resources) {
+ RepositoryMapping repoMapping = RepositoryMapping.getMapping(resource);
+ @SuppressWarnings("resource")
+ Repository repo = repoMapping.getRepository();
+ Git git = new Git(repo);
+ AddCommand gitAdd = git.add();
+ String filepattern = repoMapping.getRepoRelativePath(resource);
+ if ("".equals(filepattern)) { //$NON-NLS-1$
+ filepattern = "."; //$NON-NLS-1$
+ }
+ gitAdd.addFilepattern(filepattern);
+ try {
+ gitAdd.call();
+ } catch (NoFilepatternException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (GitAPIException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } finally {
+ git.close();
+ }
+ }
+ }
+ }
+
+ /**
+ * Retrieves an IResource from URI.
+ *
+ * @param uri
+ * the URI to resolve
+ * @return the IResource representing the URI (it doesn't necessarily have to exist)
+ */
+ // TODO: remove when change 51657 is accepted and replace by reference to ResourceUtil.getResourceFromURI
+ private IResource getResourceFromURI(final URI uri) {
+ final IResource targetFile;
+ if (uri.isPlatform()) {
+ IPath platformString = new Path(uri.trimFragment().toPlatformString(true));
+ targetFile = ResourcesPlugin.getWorkspace().getRoot().getFile(platformString);
+ } else {
+ /*
+ * FIXME Deresolve the URI against the workspace root, if it cannot be done, delegate to
+ * super.createInputStream()
+ */
+ targetFile = ResourcesPlugin.getWorkspace().getRoot().getFile(
+ new Path(uri.trimFragment().toString()));
+ }
+ return targetFile;
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/mergeresolution/MergeResolutionManager.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/mergeresolution/MergeResolutionManager.java
index 69137fd96..5af78652d 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/mergeresolution/MergeResolutionManager.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/mergeresolution/MergeResolutionManager.java
@@ -16,10 +16,7 @@ import com.google.common.collect.Iterables;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Conflict;
import org.eclipse.emf.compare.ConflictKind;
-import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceState;
-import org.eclipse.emf.compare.Match;
-import org.eclipse.emf.compare.MatchResource;
import org.eclipse.emf.compare.ide.ui.internal.mergeresolution.MergeResolutionListenerRegistry;
import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.provider.TreeNodeCompareInput;
import org.eclipse.emf.compare.internal.utils.ComparisonUtil;
@@ -31,6 +28,7 @@ import org.eclipse.emf.ecore.EObject;
* merge conflicts are resolved and the users saves the merge result.
*
* @author Michael Borkowski <mborkowski@eclipsesource.com>
+ * @since 4.2
*/
public class MergeResolutionManager {
@@ -59,8 +57,8 @@ public class MergeResolutionManager {
* contents, but does not necessarily mean that all conflicts are resolved.
*
* @param input
- * The content of the merge resolution being flushed. This can either be a {@link Match}, a
- * {@link Diff} or a {@link MatchResource} object.
+ * The content of the merge resolution being flushed. This must be a
+ * {@link TreeNodeCompareInput} object.
*/
public void handleFlush(Object input) {
// We only know how to handle TreeNodeCompareInput
@@ -77,13 +75,17 @@ public class MergeResolutionManager {
return;
}
+ if (comparison.getConflicts().size() == 0) {
+ return;
+ }
+
Predicate<Conflict> unresolvedConflict = new Predicate<Conflict>() {
public boolean apply(Conflict conflict) {
return conflict != null && conflict.getKind() != ConflictKind.PSEUDO && Iterables.any(
conflict.getDifferences(), EMFComparePredicates.hasState(DifferenceState.UNRESOLVED));
}
};
- if (Iterables.any(comparison.getConflicts(), unresolvedConflict)) {
+ if (!Iterables.any(comparison.getConflicts(), unresolvedConflict)) {
mergeResolutionListenerRegistry.mergeResolutionCompleted(comparison);
}
}

Back to the top