Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Delaigue2016-08-11 13:08:29 +0000
committerMatthias Sohn2016-08-30 23:39:05 +0000
commit218f8cec2b7ceb5b9b6d64bb037e8f875521e27a (patch)
tree84d8735531a84c20415ffc9d5025cb3c1ba798b7 /org.eclipse.egit.ui.test/src/org/eclipse/egit/ui
parent92a2bac76cfcb7dbf0242d6f61d6ef54e1de51c2 (diff)
downloadegit-218f8cec2b7ceb5b9b6d64bb037e8f875521e27a.tar.gz
egit-218f8cec2b7ceb5b9b6d64bb037e8f875521e27a.tar.xz
egit-218f8cec2b7ceb5b9b6d64bb037e8f875521e27a.zip
Provide a remote mapping context to ModelProviders
Allow model providers to use remote information when trying to determine whether a file is a part of a logical model or not. When a file has been deleted locally, or when a file has been created on one of the remote sides, the local side is not sufficient to compute a full model. ModelProviders will need access to the remote file data to take these locally unknown files into account. Add an interface to allow ModelProviders to be ignored in synchronizations has been added. Change-Id: I956dfb13093781accca36142cd87cf01b479fe1a Also-by: Laurent Goubet <laurent.goubet@obeo.fr> Also-by: Axel Richard <axel.richard@obeo.fr> Also-by: Alexandra Buzila <abuzila@eclipsesource.com> Signed-off-by: Laurent Delaigue <laurent.delaigue@obeo.fr> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.egit.ui.test/src/org/eclipse/egit/ui')
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/synchronize/MockLogicalModelProvider.java40
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/synchronize/MockLogicalResourceMapping.java136
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/synchronize/SynchronizeViewRemoteAwareChangeSetModelTest.java187
3 files changed, 363 insertions, 0 deletions
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/synchronize/MockLogicalModelProvider.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/synchronize/MockLogicalModelProvider.java
new file mode 100644
index 0000000000..1b0b56a4b7
--- /dev/null
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/synchronize/MockLogicalModelProvider.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Obeo.
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.egit.ui.view.synchronize;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.mapping.ModelProvider;
+import org.eclipse.core.resources.mapping.RemoteResourceMappingContext;
+import org.eclipse.core.resources.mapping.ResourceMapping;
+import org.eclipse.core.resources.mapping.ResourceMappingContext;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Mock Model Provider that requires a {@link RemoteResourceMappingContext} to
+ * perform correctly in synchronizations.
+ */
+public class MockLogicalModelProvider extends ModelProvider {
+ public static final String ID = "org.eclipse.egit.ui.test.mockLogicalModelProvider";
+
+ public static final String MOCK_LOGICAL_FILE_EXTENSION = "mocklogical";
+
+ @Override
+ public ResourceMapping[] getMappings(IResource resource,
+ ResourceMappingContext context, IProgressMonitor monitor)
+ throws CoreException {
+ if (resource instanceof IFile && MOCK_LOGICAL_FILE_EXTENSION
+ .equals(resource.getFileExtension())) {
+ return new ResourceMapping[] { new MockLogicalResourceMapping(
+ (IFile) resource, ID), };
+ }
+ return super.getMappings(resource, context, monitor);
+ }
+}
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/synchronize/MockLogicalResourceMapping.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/synchronize/MockLogicalResourceMapping.java
new file mode 100644
index 0000000000..3473291644
--- /dev/null
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/synchronize/MockLogicalResourceMapping.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Obeo.
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.egit.ui.view.synchronize;
+
+import static org.eclipse.egit.ui.view.synchronize.MockLogicalModelProvider.MOCK_LOGICAL_FILE_EXTENSION;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.resources.mapping.RemoteResourceMappingContext;
+import org.eclipse.core.resources.mapping.ResourceMapping;
+import org.eclipse.core.resources.mapping.ResourceMappingContext;
+import org.eclipse.core.resources.mapping.ResourceTraversal;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+
+/**
+ * This resource mapping requires a remote context to get the logical model. It
+ * will parse the content of its file which is supposed to be a list of files in
+ * the same folder and aggregate all these files in its logical model. It does
+ * that for every side, remote and base included.
+ */
+public class MockLogicalResourceMapping extends ResourceMapping {
+ private final IFile file;
+
+ private final String providerId;
+
+ public MockLogicalResourceMapping(IFile file, String providerId) {
+ this.file = file;
+ this.providerId = providerId;
+ }
+
+ @Override
+ public Object getModelObject() {
+ return file;
+ }
+
+ @Override
+ public String getModelProviderId() {
+ return providerId;
+ }
+
+ @Override
+ public ResourceTraversal[] getTraversals(ResourceMappingContext context,
+ IProgressMonitor monitor) throws CoreException {
+ SubMonitor sm = SubMonitor.convert(monitor, 3);
+ Set<IFile> result = new LinkedHashSet<IFile>();
+ result.add(file);
+ try {
+ List<IFile> dependencies = getDependencies(file, file.getParent());
+ result.addAll(dependencies);
+ sm.worked(1);
+ if (context instanceof RemoteResourceMappingContext) {
+ RemoteResourceMappingContext rmc = (RemoteResourceMappingContext) context;
+ IStorage baseContents = rmc.fetchBaseContents(file,
+ sm.newChild(1));
+ if (baseContents != null) {
+ result.addAll(
+ getDependencies(baseContents, file.getParent()));
+ }
+ IStorage remoteContents = rmc.fetchRemoteContents(file,
+ sm.newChild(1));
+ if (remoteContents != null) {
+ result.addAll(
+ getDependencies(remoteContents, file.getParent()));
+ }
+ }
+ } catch (IOException e) {
+ throw new CoreException(
+ new Status(IStatus.ERROR, "org.eclipse.egit.ui.test",
+ "Exception while computing logical model", e));
+ }
+ final IResource[] resourceArray = result
+ .toArray(new IResource[result.size()]);
+ return new ResourceTraversal[] { new ResourceTraversal(resourceArray,
+ IResource.DEPTH_ONE, IResource.NONE), };
+ }
+
+ private List<IFile> getDependencies(IStorage storage, IContainer c)
+ throws CoreException, IOException {
+ List<IFile> result = new ArrayList<>();
+ try (InputStream contents = storage.getContents();) {
+ BufferedReader r = new BufferedReader(
+ new InputStreamReader(contents));
+ try {
+ while (true) {
+ String line = r.readLine();
+ IFile dep = c.getFile(new Path(line));
+ result.add(dep);
+ }
+ } catch (Exception e) {
+ // over
+ }
+ }
+ return result;
+ }
+
+ protected void addLogicalModelFiles(IResource[] resources,
+ Set<IFile> sampleSiblings) {
+ if (resources == null) {
+ return;
+ }
+ for (IResource res : resources) {
+ if (res instanceof IFile && MOCK_LOGICAL_FILE_EXTENSION
+ .equals(res.getFileExtension())) {
+ sampleSiblings.add((IFile) res);
+ }
+ }
+ }
+
+ @Override
+ public IProject[] getProjects() {
+ return new IProject[] { file.getProject(), };
+ }
+}
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/synchronize/SynchronizeViewRemoteAwareChangeSetModelTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/synchronize/SynchronizeViewRemoteAwareChangeSetModelTest.java
new file mode 100644
index 0000000000..f1be6c5825
--- /dev/null
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/synchronize/SynchronizeViewRemoteAwareChangeSetModelTest.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Obeo.
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.egit.ui.view.synchronize;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.egit.core.op.CommitOperation;
+import org.eclipse.egit.core.op.ConnectProviderOperation;
+import org.eclipse.egit.core.op.CreateLocalBranchOperation;
+import org.eclipse.egit.ui.Activator;
+import org.eclipse.egit.ui.test.ContextMenuHelper;
+import org.eclipse.egit.ui.test.TestUtil;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
+import org.eclipse.team.ui.synchronize.ISynchronizeView;
+import org.junit.Test;
+
+public class SynchronizeViewRemoteAwareChangeSetModelTest
+ extends AbstractSynchronizeViewTest {
+
+ private IFile mockLogicalFile;
+
+ private static final String MOCK_LOGICAL_PROJECT = "MockLogical";
+
+ /**
+ * Make sure that files that are not part of the logical model because of
+ * remote file content will be taken into account in the comparison.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void shouldShowRemoteFilesInSynchronization() throws Exception {
+ // given
+ createMockLogicalRepository();
+
+ // when comparing file 'index.mocklogical' with branch 'stable'
+ String compareWithBranchActionLabel = util
+ .getPluginLocalizedValue("ReplaceWithRefAction_label");
+ clickCompareWith(compareWithBranchActionLabel);
+ SWTBotShell compareShell = bot.shell("Compare");
+ SWTBotTree tree = compareShell.bot().tree();
+ for (SWTBotTreeItem item : tree.getTreeItem("Local").getItems()) {
+ if (item.getText().contains("stable")) {
+ tree.select(item);
+ break;
+ }
+ }
+ bot.button("Compare").click();
+
+ // then
+ SWTBotTree syncViewTree = bot.viewById(ISynchronizeView.VIEW_ID).bot()
+ .tree();
+ SWTBotTreeItem mockLogicalProjectItem = waitForNodeWithText(
+ syncViewTree, MOCK_LOGICAL_PROJECT);
+ SWTBotTreeItem[] items = mockLogicalProjectItem.getItems();
+ assertEquals(4, items.length);
+
+ SWTBotTreeItem fileTree = items[0];
+ assertEquals("file1.txt", fileTree.getText());
+ fileTree = items[1];
+ assertEquals("file2.txt", fileTree.getText());
+ fileTree = items[2];
+ assertEquals("file3.txt", fileTree.getText());
+ fileTree = items[3];
+ assertEquals("index.mocklogical", fileTree.getText());
+ }
+
+ private void clickCompareWith(String menuLabel) {
+ SWTBotTree projectExplorerTree = selectMockLogicalItem();
+ ContextMenuHelper.clickContextMenu(projectExplorerTree, "Compare With",
+ menuLabel);
+ }
+
+ private SWTBotTree selectMockLogicalItem() {
+ SWTBotTree projectExplorerTree = TestUtil.getExplorerTree();
+ SWTBotTreeItem projectItem = getProjectItem(projectExplorerTree,
+ MOCK_LOGICAL_PROJECT);
+ projectItem.expand();
+ for (SWTBotTreeItem item : projectItem.getItems()) {
+ if (item.getText().contains("index.mocklogical")) {
+ item.select();
+ }
+ }
+ return projectExplorerTree;
+ }
+
+ protected void createMockLogicalRepository() throws Exception {
+ File gitDir = new File(
+ new File(getTestDirectory(), MOCK_LOGICAL_PROJECT),
+ Constants.DOT_GIT);
+ Repository repo = FileRepositoryBuilder.create(gitDir);
+ repo.create();
+
+ // we need to commit into master first
+ IProject project = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject(MOCK_LOGICAL_PROJECT);
+
+ if (project.exists()) {
+ project.delete(true, null);
+ TestUtil.waitForJobs(100, 5000);
+ }
+ IProjectDescription desc = ResourcesPlugin.getWorkspace()
+ .newProjectDescription(MOCK_LOGICAL_PROJECT);
+ desc.setLocation(new Path(
+ new File(repo.getWorkTree(), MOCK_LOGICAL_PROJECT).getPath()));
+ project.create(desc, null);
+ project.open(null);
+ assertTrue("Project is not accessible: " + project,
+ project.isAccessible());
+
+ TestUtil.waitForJobs(50, 5000);
+ try {
+ new ConnectProviderOperation(project, gitDir).execute(null);
+ } catch (Exception e) {
+ Activator.logError("Failed to connect project to repository", e);
+ }
+ assertConnected(project);
+
+ mockLogicalFile = project.getFile("index.mocklogical");
+ mockLogicalFile.create(new ByteArrayInputStream(
+ "file1.txt\nfile2.txt".getBytes(project.getDefaultCharset())),
+ false, null);
+ IFile file1 = project.getFile("file1.txt");
+ file1.create(
+ new ByteArrayInputStream(
+ "Content 1".getBytes(project.getDefaultCharset())),
+ false, null);
+ IFile file2 = project.getFile("file2.txt");
+ file2.create(
+ new ByteArrayInputStream(
+ "Content 2".getBytes(project.getDefaultCharset())),
+ false, null);
+
+ IFile[] commitables = new IFile[] { mockLogicalFile, file1, file2 };
+ List<IFile> untracked = new ArrayList<>();
+ untracked.addAll(Arrays.asList(commitables));
+ CommitOperation op = new CommitOperation(commitables, untracked,
+ TestUtil.TESTAUTHOR, TestUtil.TESTCOMMITTER, "Initial commit");
+ op.execute(null);
+ RevCommit firstCommit = op.getCommit();
+
+ CreateLocalBranchOperation createBranchOp = new CreateLocalBranchOperation(
+ repo, "refs/heads/stable", firstCommit);
+ createBranchOp.execute(null);
+
+ // Delete file2.txt from logical model and add file3
+ mockLogicalFile = touch(MOCK_LOGICAL_PROJECT, "index.mocklogical",
+ "file1.txt\nfile3.txt");
+ file2.delete(true, null);
+ touch(MOCK_LOGICAL_PROJECT, "file1.txt", "Content 1 modified");
+ IFile file3 = project.getFile("file3.txt");
+ file3.create(
+ new ByteArrayInputStream(
+ "Content 3".getBytes(project.getDefaultCharset())),
+ false, null);
+ commitables = new IFile[] { mockLogicalFile, file2, file3 };
+ untracked = new ArrayList<>();
+ untracked.add(file3);
+ op = new CommitOperation(commitables, untracked, TestUtil.TESTAUTHOR,
+ TestUtil.TESTCOMMITTER, "Second commit");
+ op.execute(null);
+ }
+
+}

Back to the top