diff options
author | Mathieu Cartaud | 2015-10-22 14:33:35 +0000 |
---|---|---|
committer | Laurent Goubet | 2017-09-05 09:07:56 +0000 |
commit | 93ee76a711336009235b3c726c363cd874bc7577 (patch) | |
tree | 1fff6c1cb2c89f74529614bef21935b7ab6327c6 | |
parent | eefca4ff471b5521ec1eab57286678d9294c68d7 (diff) | |
download | org.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>
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); } } |