Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [egit-dev] Logical model support for merge operations

Hi Travis,

The changes needed into JGit for this support have now been merged, but all changes regarding EGit are still pending.

On that matter, I was working on unit tests to try and demonstrate what we are doing, and what some of these are needed. However, even though I can now write them (had quite a lot of trouble with maven getting in the way), they depend on unrelated changes.

Namely, to demonstrate why failing the process as a whole when the auto-staging hook cannot lock the index https://git.eclipse.org/r/22670 , I also need the changes introduced by https://git.eclipse.org/r/22671 and https://git.eclipse.org/r/22674 since I cannot otherwise show the complete use case.

Should i make the two latter dependent on the otherwise unrelated first in order to push the unit tests for review? For the record, I'm attaching here one such unit test, that will fail if commited atop 22671 and 22674, but work if 22670 is also merged beforehand. (i.e. it fails because the auto-staging hook crashes.)

Regards,

Laurent Goubet
Obeo

On 16/07/2014 17:58, Travis London wrote:
Hello all,

What is the current status for logical model support?

Did the latest changes get promoted?

Kind regards,
Travis London

-----Original Message-----
From: egit-dev-bounces@xxxxxxxxxxx [mailto:egit-dev-bounces@xxxxxxxxxxx] On Behalf Of Laurent Goubet
Sent: Tuesday, May 06, 2014 3:44 AM
To: Matthias Sohn
Cc: egit-dev@xxxxxxxxxxx
Subject: Re: [egit-dev] Logical model support for merge operations

Unfortunately, the last time I tried to add tests, it ended up working locally on both windows and linux, but failing when ran from maven :
https://git.eclipse.org/r/#/c/14966/

I'll try and get to debugging that.

On 05/05/2014 18:17, Matthias Sohn wrote:
could you add tests for the EGit changes and provide a description how
to test this manually and an example model (I am not really using
models ;-) ?

--
Matthias

_______________________________________________
egit-dev mailing list
egit-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/egit-dev


>From dfc6d7c5d51a8b32f97dc0f2fcab3ed73150608d Mon Sep 17 00:00:00 2001
From: Laurent Goubet <laurent.goubet@xxxxxxx>
Date: Fri, 18 Jul 2014 17:02:28 +0200
Subject: [PATCH] Introduce tests for the "model-merging" strategy

Signed-off-by: Laurent Goubet <laurent.goubet@xxxxxxx>
---
 org.eclipse.egit.core.test/META-INF/MANIFEST.MF    |   2 +-
 org.eclipse.egit.core.test/build.properties        |   3 +-
 org.eclipse.egit.core.test/fragment.xml            |  38 +++
 .../internal/merge/StrategyRecursiveModelTest.java | 114 +++++++
 .../synchronize/GitSubscriberMergeContextTest.java | 345 +++------------------
 .../egit/core/test/models/ModelTestCase.java       | 187 +++++++++++
 .../test/models/SampleModelAdapterFactory.java     |  28 ++
 .../egit/core/test/models/SampleModelProvider.java |  40 +++
 .../core/test/models/SampleResourceMapping.java    |  68 ++++
 .../test/models/SampleResourceMappingMerger.java   |  25 ++
 10 files changed, 553 insertions(+), 297 deletions(-)
 create mode 100644 org.eclipse.egit.core.test/fragment.xml
 create mode 100644 org.eclipse.egit.core.test/src/org/eclipse/egit/core/internal/merge/StrategyRecursiveModelTest.java
 create mode 100644 org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/ModelTestCase.java
 create mode 100644 org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleModelAdapterFactory.java
 create mode 100644 org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleModelProvider.java
 create mode 100644 org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleResourceMapping.java
 create mode 100644 org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleResourceMappingMerger.java

diff --git a/org.eclipse.egit.core.test/META-INF/MANIFEST.MF b/org.eclipse.egit.core.test/META-INF/MANIFEST.MF
index 9c08c04..1fffa48 100644
--- a/org.eclipse.egit.core.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.egit.core.test/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: Git Team Provider Core Test Plug-in
 Bundle-Vendor: Eclipse.org
-Bundle-SymbolicName: org.eclipse.egit.core.test
+Bundle-SymbolicName: org.eclipse.egit.core.test;singleton:=true
 Fragment-Host: org.eclipse.egit.core
 Bundle-Version: 3.5.0.qualifier
 Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
diff --git a/org.eclipse.egit.core.test/build.properties b/org.eclipse.egit.core.test/build.properties
index 69abd4d..e3ad4f4 100644
--- a/org.eclipse.egit.core.test/build.properties
+++ b/org.eclipse.egit.core.test/build.properties
@@ -1,5 +1,6 @@
 source.. = src/
 output.. = bin/
 bin.includes = META-INF/,\
-               .
+               .,\
+               fragment.xml
 extra.. = platform:/fragment/org.eclipse.jgit.java7
diff --git a/org.eclipse.egit.core.test/fragment.xml b/org.eclipse.egit.core.test/fragment.xml
new file mode 100644
index 0000000..e1f93e1
--- /dev/null
+++ b/org.eclipse.egit.core.test/fragment.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<fragment>
+   <extension
+         id="org.eclipse.egit.core.tests.sampleModelProvider"
+         name="Sample Test Model"
+         point="org.eclipse.core.resources.modelProviders">
+      <modelProvider
+            class="org.eclipse.egit.core.test.models.SampleModelProvider">
+      </modelProvider>
+      <enablement>
+         <and>
+            <adapt
+                  type="org.eclipse.core.resources.IFile">
+               <test
+                     forcePluginActivation="true"
+                     property="org.eclipse.core.resources.name"
+                     value="*.sample">
+               </test>
+            </adapt>
+         </and>
+      </enablement>
+      <extends-model
+            id="org.eclipse.core.resources.modelProvider">
+      </extends-model>
+   </extension>
+   <extension
+         point="org.eclipse.core.runtime.adapters">
+      <factory
+            adaptableType="org.eclipse.egit.core.test.models.SampleModelProvider"
+            class="org.eclipse.egit.core.test.models.SampleModelAdapterFactory">
+         <adapter
+               type="org.eclipse.team.core.mapping.IResourceMappingMerger">
+         </adapter>
+      </factory>
+   </extension>
+
+</fragment>
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/internal/merge/StrategyRecursiveModelTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/internal/merge/StrategyRecursiveModelTest.java
new file mode 100644
index 0000000..95092eb
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/internal/merge/StrategyRecursiveModelTest.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (C) 2014 Obeo and others.
+ *
+ * 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.core.internal.merge;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.egit.core.test.TestRepository;
+import org.eclipse.egit.core.test.models.ModelTestCase;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.Status;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class StrategyRecursiveModelTest extends ModelTestCase {
+	private static final String MASTER = Constants.R_HEADS + Constants.MASTER;
+
+	private static final String BRANCH = Constants.R_HEADS + "branch";
+
+	private Repository repo;
+
+	private IProject iProject;
+
+	private TestRepository testRepo;
+
+	@Before
+	public void setUp() throws Exception {
+		super.setUp();
+
+		iProject = project.project;
+		testRepo = new TestRepository(gitDir);
+		testRepo.connect(iProject);
+		repo = RepositoryMapping.getMapping(iProject).getRepository();
+
+		// make initial commit
+		new Git(repo).commit().setAuthor("JUnit", "junit@xxxxxxxx")
+				.setMessage("Initial commit").call();
+	}
+
+	@After
+	public void clearGitResources() throws Exception {
+		testRepo.disconnect(iProject);
+		testRepo.dispose();
+		repo = null;
+
+		super.tearDown();
+	}
+
+	@Test
+	public void mergeModelWithDeletedFileNoConflict() throws Exception {
+		File file1 = testRepo.createFile(iProject, "file1."
+				+ SAMPLE_FILE_EXTENSION);
+		File file2 = testRepo.createFile(iProject, "file2."
+				+ SAMPLE_FILE_EXTENSION);
+
+		String initialContent1 = "some content for the first file";
+		String initialContent2 = "some content for the second file";
+		testRepo.appendContentAndCommit(iProject, file1, initialContent1,
+				"first file - initial commit");
+		testRepo.appendContentAndCommit(iProject, file2, initialContent2,
+				"second file - initial commit");
+
+		IFile iFile1 = testRepo.getIFile(iProject, file1);
+		IFile iFile2 = testRepo.getIFile(iProject, file2);
+		String repoRelativePath1 = testRepo.getRepoRelativePath(iFile1
+				.getLocation().toPortableString());
+		testRepo.getRepoRelativePath(iFile2
+				.getLocation().toPortableString());
+
+		testRepo.createAndCheckoutBranch(MASTER, BRANCH);
+
+		final String branchChanges = "branch changes\n";
+		setContentsAndCommit(testRepo, repoRelativePath1, iFile1, branchChanges
+				+ initialContent1, "branch commit");
+		iFile2.delete(true, new NullProgressMonitor());
+		testRepo.addAndCommit(iProject, file2, "branch commit - deleted file2."
+				+ SAMPLE_FILE_EXTENSION);
+
+		testRepo.checkoutBranch(MASTER);
+
+		final String masterChanges = "some changes\n";
+		setContentsAndCommit(testRepo, repoRelativePath1, iFile1,
+				initialContent1 + masterChanges, "master commit");
+		iProject.refreshLocal(IResource.DEPTH_INFINITE,
+				new NullProgressMonitor());
+		// end setup
+
+		merge(repo, BRANCH);
+
+		final Status status = status(repo);
+		assertFalse(status.hasUncommittedChanges());
+		assertTrue(status.getConflicting().isEmpty());
+
+		assertContentEquals(iFile1, branchChanges + initialContent1
+				+ masterChanges);
+		assertFalse(iFile2.exists());
+	}
+}
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitSubscriberMergeContextTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitSubscriberMergeContextTest.java
index bad9645..7f184a1 100644
--- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitSubscriberMergeContextTest.java
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitSubscriberMergeContextTest.java
@@ -15,62 +15,38 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
 import java.io.File;
-import java.io.InputStreamReader;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.mapping.ModelProvider;
 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.NullProgressMonitor;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.content.IContentType;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.egit.core.AdapterUtils;
 import org.eclipse.egit.core.project.RepositoryMapping;
-import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData;
-import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet;
-import org.eclipse.egit.core.test.GitTestCase;
 import org.eclipse.egit.core.test.TestRepository;
+import org.eclipse.egit.core.test.models.ModelTestCase;
+import org.eclipse.egit.core.test.models.SampleResourceMapping;
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.Status;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.team.core.diff.IDiff;
 import org.eclipse.team.core.mapping.IMergeContext;
 import org.eclipse.team.core.mapping.IMergeStatus;
 import org.eclipse.team.core.mapping.IResourceMappingMerger;
-import org.eclipse.team.core.mapping.ResourceMappingMerger;
-import org.eclipse.team.core.mapping.provider.MergeStatus;
-import org.eclipse.team.core.subscribers.SubscriberScopeManager;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
-public class GitSubscriberMergeContextTest extends GitTestCase {
+public class GitSubscriberMergeContextTest extends ModelTestCase {
 
 	private static final String MASTER = Constants.R_HEADS + Constants.MASTER;
 
 	private static final String BRANCH = Constants.R_HEADS + "branch";
 
-	private static final String SAMPLE_FILE_EXTENSION = "sample";
-
-	private static final String SAMPLE_PROVIDER_ID = "egit.test.sample.provider";
-
 	private Repository repo;
 
 	private IProject iProject;
@@ -89,11 +65,6 @@ public void setUp() throws Exception {
 		// make initial commit
 		new Git(repo).commit().setAuthor("JUnit", "junit@xxxxxxxx")
 				.setMessage("Initial commit").call();
-
-		IContentType textType = Platform.getContentTypeManager()
-				.getContentType("org.eclipse.core.runtime.text");
-		textType.addFileSpec(SAMPLE_FILE_EXTENSION,
-				IContentType.FILE_EXTENSION_SPEC);
 	}
 
 	@After
@@ -117,7 +88,7 @@ public void markAsMerged() throws Exception {
 		IFile workspaceFile = testRepo.getIFile(iProject, file);
 
 		testRepo.appendFileContent(file, "some changes");
-		Status status = new Git(repo).status().call();
+		Status status = status(repo);
 		assertEquals(0, status.getAdded().size());
 		assertEquals(1, status.getModified().size());
 		String repoRelativePath = testRepo.getRepoRelativePath(workspaceFile
@@ -127,7 +98,8 @@ public void markAsMerged() throws Exception {
 		iProject.refreshLocal(IResource.DEPTH_INFINITE,
 				new NullProgressMonitor());
 
-		IMergeContext mergeContext = prepareContext(workspaceFile, HEAD, HEAD);
+		IMergeContext mergeContext = prepareContext(repo, workspaceFile, HEAD,
+				HEAD);
 		IDiff node = mergeContext.getDiffTree().getDiff(workspaceFile);
 		assertNotNull(node);
 		// First of all, "markAsMerged" is not supposed to have any effect on a
@@ -136,7 +108,7 @@ public void markAsMerged() throws Exception {
 		// not created for the occasion.
 		mergeContext.markAsMerged(node, true, null);
 
-		status = new Git(repo).status().call();
+		status = status(repo);
 		assertEquals(1, status.getChanged().size());
 		assertEquals(0, status.getModified().size());
 		assertTrue(status.getChanged().contains(repoRelativePath));
@@ -160,20 +132,20 @@ public void mergeNoConflict() throws Exception {
 		testRepo.createAndCheckoutBranch(MASTER, BRANCH);
 
 		final String branchChanges = "branch changes\n";
-		setContentsAndCommit(repoRelativePath, workspaceFile, branchChanges
-				+ initialContent,
-				"branch commit");
+		setContentsAndCommit(testRepo, repoRelativePath, workspaceFile,
+				branchChanges + initialContent, "branch commit");
 
 		testRepo.checkoutBranch(MASTER);
 
 		final String masterChanges = "some changes\n";
-		setContentsAndCommit(repoRelativePath, workspaceFile, initialContent
-				+ masterChanges, "master commit");
+		setContentsAndCommit(testRepo, repoRelativePath, workspaceFile,
+				initialContent + masterChanges, "master commit");
 		iProject.refreshLocal(IResource.DEPTH_INFINITE,
 				new NullProgressMonitor());
 		// end setup
 
-		IMergeContext mergeContext = prepareContext(workspaceFile, MASTER,
+		IMergeContext mergeContext = prepareContext(repo, workspaceFile,
+				MASTER,
 				BRANCH);
 		IDiff node = mergeContext.getDiffTree().getDiff(workspaceFile);
 		assertNotNull(node);
@@ -184,7 +156,7 @@ public void mergeNoConflict() throws Exception {
 		assertContentEquals(workspaceFile, branchChanges + initialContent
 				+ masterChanges);
 
-		Status status = new Git(repo).status().call();
+		Status status = status(repo);
 		assertEquals(1, status.getChanged().size());
 		assertEquals(0, status.getModified().size());
 		assertTrue(status.getChanged().contains(repoRelativePath));
@@ -214,30 +186,30 @@ public void mergeModelNoConflict() throws Exception {
 		testRepo.createAndCheckoutBranch(MASTER, BRANCH);
 
 		final String branchChanges = "branch changes\n";
-		setContentsAndCommit(repoRelativePath1, iFile1, branchChanges
+		setContentsAndCommit(testRepo, repoRelativePath1, iFile1, branchChanges
 				+ initialContent1, "branch commit");
-		setContentsAndCommit(repoRelativePath2, iFile2, branchChanges
+		setContentsAndCommit(testRepo, repoRelativePath2, iFile2, branchChanges
 				+ initialContent2, "branch commit");
 
 		testRepo.checkoutBranch(MASTER);
 
 		final String masterChanges = "some changes\n";
-		setContentsAndCommit(repoRelativePath1, iFile1, initialContent1
-				+ masterChanges, "master commit");
-		setContentsAndCommit(repoRelativePath2, iFile2, initialContent2
-				+ masterChanges, "master commit");
+		setContentsAndCommit(testRepo, repoRelativePath1, iFile1,
+				initialContent1 + masterChanges, "master commit");
+		setContentsAndCommit(testRepo, repoRelativePath2, iFile2,
+				initialContent2 + masterChanges, "master commit");
 		iProject.refreshLocal(IResource.DEPTH_INFINITE,
 				new NullProgressMonitor());
 		// end setup
 
-		IMergeContext mergeContext = prepareModelContext(iFile1, MASTER, BRANCH);
+		IMergeContext mergeContext = prepareModelContext(repo, iFile1, MASTER,
+				BRANCH);
 		IDiff node = mergeContext.getDiffTree().getDiff(iFile1);
 		assertNotNull(node);
 		node = mergeContext.getDiffTree().getDiff(iFile2);
 		assertNotNull(node);
 
-		IResourceMappingMerger merger = new SampleModelMerger(
-				SAMPLE_PROVIDER_ID);
+		IResourceMappingMerger merger = createMerger();
 		IStatus mergeStatus = merger.merge(mergeContext,
 				new NullProgressMonitor());
 		assertEquals(IStatus.OK, mergeStatus.getSeverity());
@@ -246,7 +218,7 @@ public void mergeModelNoConflict() throws Exception {
 		assertContentEquals(iFile2, branchChanges + initialContent2
 				+ masterChanges);
 
-		Status status = new Git(repo).status().call();
+		Status status = status(repo);
 		assertEquals(2, status.getChanged().size());
 		assertEquals(0, status.getModified().size());
 		assertTrue(status.getChanged().contains(repoRelativePath1));
@@ -271,19 +243,20 @@ public void mergeWithConflict() throws Exception {
 		testRepo.createAndCheckoutBranch(MASTER, BRANCH);
 
 		final String branchChanges = "branch changes\n";
-		setContentsAndCommit(repoRelativePath, workspaceFile, initialContent
-				+ branchChanges, "branch commit");
+		setContentsAndCommit(testRepo, repoRelativePath, workspaceFile,
+				initialContent + branchChanges, "branch commit");
 
 		testRepo.checkoutBranch(MASTER);
 
 		final String masterChanges = "some changes\n";
-		setContentsAndCommit(repoRelativePath, workspaceFile, initialContent
-				+ masterChanges, "master commit");
+		setContentsAndCommit(testRepo, repoRelativePath, workspaceFile,
+				initialContent + masterChanges, "master commit");
 		iProject.refreshLocal(IResource.DEPTH_INFINITE,
 				new NullProgressMonitor());
 		// end setup
 
-		IMergeContext mergeContext = prepareContext(workspaceFile, MASTER,
+		IMergeContext mergeContext = prepareContext(repo, workspaceFile,
+				MASTER,
 				BRANCH);
 		IDiff node = mergeContext.getDiffTree().getDiff(workspaceFile);
 		assertNotNull(node);
@@ -293,7 +266,7 @@ public void mergeWithConflict() throws Exception {
 		assertEquals(IStatus.ERROR, mergeStatus.getSeverity());
 		assertContentEquals(workspaceFile, initialContent + masterChanges);
 
-		Status status = new Git(repo).status().call();
+		Status status = status(repo);
 		assertEquals(0, status.getChanged().size());
 		assertEquals(0, status.getModified().size());
 		assertFalse(status.getChanged().contains(repoRelativePath));
@@ -323,30 +296,30 @@ public void mergeModelWithConflict() throws Exception {
 		testRepo.createAndCheckoutBranch(MASTER, BRANCH);
 
 		final String branchChanges = "branch changes\n";
-		setContentsAndCommit(repoRelativePath1, iFile1, initialContent1
-				+ branchChanges, "branch commit");
-		setContentsAndCommit(repoRelativePath2, iFile2, initialContent2
-				+ branchChanges, "branch commit");
+		setContentsAndCommit(testRepo, repoRelativePath1, iFile1,
+				initialContent1 + branchChanges, "branch commit");
+		setContentsAndCommit(testRepo, repoRelativePath2, iFile2,
+				initialContent2 + branchChanges, "branch commit");
 
 		testRepo.checkoutBranch(MASTER);
 
 		final String masterChanges = "some changes\n";
-		setContentsAndCommit(repoRelativePath1, iFile1, initialContent1
-				+ masterChanges, "master commit");
-		setContentsAndCommit(repoRelativePath2, iFile2, initialContent2
-				+ masterChanges, "master commit");
+		setContentsAndCommit(testRepo, repoRelativePath1, iFile1,
+				initialContent1 + masterChanges, "master commit");
+		setContentsAndCommit(testRepo, repoRelativePath2, iFile2,
+				initialContent2 + masterChanges, "master commit");
 		iProject.refreshLocal(IResource.DEPTH_INFINITE,
 				new NullProgressMonitor());
 		// end setup
 
-		IMergeContext mergeContext = prepareModelContext(iFile1, MASTER, BRANCH);
+		IMergeContext mergeContext = prepareModelContext(repo, iFile1, MASTER,
+				BRANCH);
 		IDiff node = mergeContext.getDiffTree().getDiff(iFile1);
 		assertNotNull(node);
 		node = mergeContext.getDiffTree().getDiff(iFile2);
 		assertNotNull(node);
 
-		IResourceMappingMerger merger = new SampleModelMerger(
-				SAMPLE_PROVIDER_ID);
+		IResourceMappingMerger merger = createMerger();
 		IStatus mergeStatus = merger.merge(mergeContext,
 				new NullProgressMonitor());
 		assertEquals(IStatus.ERROR, mergeStatus.getSeverity());
@@ -367,7 +340,7 @@ public void mergeModelWithConflict() throws Exception {
 		assertContentEquals(iFile1, initialContent1 + masterChanges);
 		assertContentEquals(iFile2, initialContent2 + masterChanges);
 
-		Status status = new Git(repo).status().call();
+		Status status = status(repo);
 		assertEquals(0, status.getChanged().size());
 		assertEquals(0, status.getModified().size());
 	}
@@ -396,7 +369,7 @@ public void mergeModelWithDeletedFileNoConflict() throws Exception {
 		testRepo.createAndCheckoutBranch(MASTER, BRANCH);
 
 		final String branchChanges = "branch changes\n";
-		setContentsAndCommit(repoRelativePath1, iFile1, branchChanges
+		setContentsAndCommit(testRepo, repoRelativePath1, iFile1, branchChanges
 				+ initialContent1, "branch commit");
 		iFile2.delete(true, new NullProgressMonitor());
 		testRepo.addAndCommit(iProject, file2, "branch commit - deleted file2."
@@ -405,20 +378,20 @@ public void mergeModelWithDeletedFileNoConflict() throws Exception {
 		testRepo.checkoutBranch(MASTER);
 
 		final String masterChanges = "some changes\n";
-		setContentsAndCommit(repoRelativePath1, iFile1, initialContent1
-				+ masterChanges, "master commit");
+		setContentsAndCommit(testRepo, repoRelativePath1, iFile1,
+				initialContent1 + masterChanges, "master commit");
 		iProject.refreshLocal(IResource.DEPTH_INFINITE,
 				new NullProgressMonitor());
 		// end setup
 
-		IMergeContext mergeContext = prepareModelContext(iFile1, MASTER, BRANCH);
+		IMergeContext mergeContext = prepareModelContext(repo, iFile1, MASTER,
+				BRANCH);
 		IDiff node = mergeContext.getDiffTree().getDiff(iFile1);
 		assertNotNull(node);
 		node = mergeContext.getDiffTree().getDiff(iFile2);
 		assertNotNull(node);
 
-		IResourceMappingMerger merger = new SampleModelMerger(
-				SAMPLE_PROVIDER_ID);
+		IResourceMappingMerger merger = createMerger();
 		IStatus mergeStatus = merger.merge(mergeContext,
 				new NullProgressMonitor());
 		assertEquals(IStatus.OK, mergeStatus.getSeverity());
@@ -426,229 +399,11 @@ public void mergeModelWithDeletedFileNoConflict() throws Exception {
 				+ masterChanges);
 		assertFalse(iFile2.exists());
 
-		Status status = new Git(repo).status().call();
+		Status status = status(repo);
 		assertEquals(1, status.getChanged().size());
 		assertEquals(1, status.getRemoved().size());
 		assertEquals(0, status.getModified().size());
 		assertTrue(status.getChanged().contains(repoRelativePath1));
 		assertTrue(status.getRemoved().contains(repoRelativePath2));
 	}
-
-	private RevCommit setContentsAndCommit(String repoRelativePath,
-			IFile targetFile,
-			String newContents, String commitMessage) throws Exception {
-		targetFile.setContents(
-				new ByteArrayInputStream(newContents.getBytes()),
-				IResource.FORCE, new NullProgressMonitor());
-		new Git(testRepo.getRepository()).add()
-				.addFilepattern(repoRelativePath).call();
-		testRepo.addToIndex(targetFile);
-		return testRepo.commit(commitMessage);
-	}
-
-	private void assertContentEquals(IFile file, String expectedContents)
-			throws Exception {
-		BufferedReader reader = new BufferedReader(new InputStreamReader(
-				file.getContents()));
-		StringBuilder contentsBuilder = new StringBuilder();
-		String line = reader.readLine();
-		while (line != null) {
-			contentsBuilder.append(line);
-			contentsBuilder.append('\n');
-			line = reader.readLine();
-		}
-		reader.close();
-		assertEquals(expectedContents, contentsBuilder.toString());
-	}
-
-	private IMergeContext prepareContext(IFile workspaceFile, String srcRev,
-			String dstRev) throws Exception {
-		GitSynchronizeData gsd = new GitSynchronizeData(repo, srcRev, dstRev,
-				true, Collections.<IResource> singleton(workspaceFile));
-		GitSynchronizeDataSet gsds = new GitSynchronizeDataSet(gsd);
-		GitResourceVariantTreeSubscriber subscriber = new GitResourceVariantTreeSubscriber(
-				gsds);
-		subscriber.init(new NullProgressMonitor());
-
-		ResourceMapping mapping = AdapterUtils.adapt(workspaceFile,
-				ResourceMapping.class);
-		SubscriberScopeManager manager = new SubscriberScopeManager(
-				subscriber.getName(), new ResourceMapping[] { mapping, },
-				subscriber, true);
-		manager.initialize(new NullProgressMonitor());
-
-		GitSubscriberMergeContext mergeContext = new GitSubscriberMergeContext(
-				subscriber, manager, gsds);
-		// Wait for asynchronous update of the diff tree to end
-		Job.getJobManager().join(mergeContext, new NullProgressMonitor());
-		return mergeContext;
-	}
-
-	private IMergeContext prepareModelContext(IFile workspaceFile,
-			String srcRev,
-			String dstRev) throws Exception {
-		Set<IResource> includedResources = new HashSet<IResource>(
-				Arrays.asList(workspaceFile));
-		Set<IResource> newResources = new HashSet<IResource>(includedResources);
-		Set<ResourceMapping> allMappings = new HashSet<ResourceMapping>();
-		ResourceMappingContext mappingContext = ResourceMappingContext.LOCAL_CONTEXT;
-		ModelProvider provider = new SampleProvider();
-		do {
-			Set<IResource> copy = newResources;
-			newResources = new HashSet<IResource>();
-			for (IResource resource : copy) {
-				ResourceMapping[] mappings = provider.getMappings(resource,
-						mappingContext, new NullProgressMonitor());
-				allMappings.addAll(Arrays.asList(mappings));
-
-				newResources.addAll(collectResources(mappings, mappingContext));
-			}
-		} while (includedResources.addAll(newResources));
-		ResourceMapping[] mappings = allMappings
-				.toArray(new ResourceMapping[allMappings.size()]);
-
-		GitSynchronizeData gsd = new GitSynchronizeData(repo, srcRev, dstRev,
-				true, includedResources);
-		GitSynchronizeDataSet gsds = new GitSynchronizeDataSet(gsd);
-		GitResourceVariantTreeSubscriber subscriber = new GitResourceVariantTreeSubscriber(
-				gsds);
-		subscriber.init(new NullProgressMonitor());
-
-		GitSubscriberResourceMappingContext resourceMappingContext = new GitSubscriberResourceMappingContext(
-				subscriber, gsds);
-		SubscriberScopeManager manager = new SubscriberScopeManager(
-				subscriber.getName(), mappings, subscriber,
-				resourceMappingContext, true);
-		manager.initialize(new NullProgressMonitor());
-
-		GitSubscriberMergeContext mergeContext = new GitSubscriberMergeContext(
-				subscriber, manager, gsds);
-		// Wait for asynchronous update of the diff tree to end
-		Job.getJobManager().join(mergeContext, new NullProgressMonitor());
-		return mergeContext;
-	}
-
-	private static Set<IResource> collectResources(ResourceMapping[] mappings,
-			ResourceMappingContext mappingContext) throws Exception {
-		final Set<IResource> resources = new HashSet<IResource>();
-		for (ResourceMapping mapping : mappings) {
-			ResourceTraversal[] traversals = mapping.getTraversals(
-					mappingContext, new NullProgressMonitor());
-			for (ResourceTraversal traversal : traversals)
-				resources.addAll(Arrays.asList(traversal.getResources()));
-		}
-		return resources;
-	}
-
-	/**
-	 * This model provider can be used to make all files of a given extension to
-	 * be part of the same model. In this test, this will be used on files with
-	 * extension {@link #SAMPLE_FILE_EXTENSION}.
-	 */
-	private static class SampleProvider extends ModelProvider {
-		@Override
-		public ResourceMapping[] getMappings(IResource resource,
-				ResourceMappingContext context, IProgressMonitor monitor)
-				throws CoreException {
-			if (resource instanceof IFile
-					&& SAMPLE_FILE_EXTENSION
-							.equals(resource.getFileExtension())) {
-				return new ResourceMapping[] { new SampleResourceMapping(
-						(IFile) resource, SAMPLE_PROVIDER_ID), };
-			}
-			return super.getMappings(resource, context, monitor);
-		}
-	}
-
-	/**
-	 * This resource mapping will consider all files of extension
-	 * {@link #SAMPLE_FILE_EXTENSION} in a given folder to be part of the same
-	 * model.
-	 */
-	private static class SampleResourceMapping extends ResourceMapping {
-		private final IFile file;
-
-		private final String providerId;
-
-		public SampleResourceMapping(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 {
-			Set<IFile> sampleSiblings = new LinkedHashSet<IFile>();
-			for (IResource res : file.getParent().members()) {
-				if (res instanceof IFile
-						&& SAMPLE_FILE_EXTENSION.equals(res.getFileExtension())) {
-					sampleSiblings.add((IFile) res);
-				}
-			}
-			final IResource[] resourceArray = sampleSiblings
-					.toArray(new IResource[sampleSiblings.size()]);
-			return new ResourceTraversal[] { new ResourceTraversal(
-					resourceArray, IResource.DEPTH_ONE, IResource.NONE), };
-		}
-
-		@Override
-		public IProject[] getProjects() {
-			return new IProject[] { file.getProject(), };
-		}
-	}
-
-	/**
-	 * Since we do not register our model provider the plugin way, we won't have
-	 * a descriptor for it, and the default implementation would fail. This will
-	 * avoid all the useless calls to provider.getDescriptor().
-	 */
-	private static class SampleModelMerger extends ResourceMappingMerger {
-		private final String providerID;
-
-		public SampleModelMerger(String providerID) {
-			this.providerID = providerID;
-		}
-
-		@Override
-		protected ModelProvider getModelProvider() {
-			return null;
-		}
-
-		@Override
-		public IStatus merge(IMergeContext mergeContext,
-				IProgressMonitor monitor) throws CoreException {
-			IDiff[] deltas = getSetToMerge(mergeContext);
-			IStatus status = mergeContext.merge(deltas, false /* don't force */,
-					monitor);
-			if (status.getCode() == IMergeStatus.CONFLICTS) {
-				return new MergeStatus(status.getPlugin(), status.getMessage(),
-						mergeContext.getScope().getMappings(providerID));
-			}
-			return status;
-		}
-
-		private IDiff[] getSetToMerge(IMergeContext mergeContext) {
-			ResourceMapping[] mappings = mergeContext.getScope().getMappings(
-					providerID);
-			Set<IDiff> deltas = new HashSet<IDiff>();
-			for (int i = 0; i < mappings.length; i++) {
-				ResourceTraversal[] traversals = mergeContext.getScope()
-						.getTraversals(mappings[i]);
-				deltas.addAll(Arrays.asList(mergeContext.getDiffTree()
-						.getDiffs(traversals)));
-			}
-			return deltas.toArray(new IDiff[deltas.size()]);
-		}
-	}
 }
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/ModelTestCase.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/ModelTestCase.java
new file mode 100644
index 0000000..8fe0a17
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/ModelTestCase.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (C) 2014 Obeo and others.
+ *
+ * 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.core.test.models;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+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.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.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.egit.core.AdapterUtils;
+import org.eclipse.egit.core.op.MergeOperation;
+import org.eclipse.egit.core.synchronize.GitResourceVariantTreeSubscriber;
+import org.eclipse.egit.core.synchronize.GitSubscriberMergeContext;
+import org.eclipse.egit.core.synchronize.GitSubscriberResourceMappingContext;
+import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData;
+import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet;
+import org.eclipse.egit.core.test.GitTestCase;
+import org.eclipse.egit.core.test.TestRepository;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.Status;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.team.core.mapping.IMergeContext;
+import org.eclipse.team.core.mapping.IResourceMappingMerger;
+import org.eclipse.team.core.mapping.ResourceMappingMerger;
+import org.eclipse.team.core.subscribers.SubscriberScopeManager;
+import org.junit.Before;
+
+public class ModelTestCase extends GitTestCase {
+	protected static final String SAMPLE_FILE_EXTENSION = SampleModelProvider.SAMPLE_FILE_EXTENSION;
+
+	@Before
+	public void setUp() throws Exception {
+		super.setUp();
+
+		IContentType textType = Platform.getContentTypeManager()
+				.getContentType("org.eclipse.core.runtime.text");
+		textType.addFileSpec(SAMPLE_FILE_EXTENSION,
+				IContentType.FILE_EXTENSION_SPEC);
+	}
+
+	protected RevCommit setContentsAndCommit(TestRepository testRepository,
+			String repoRelativePath, IFile targetFile, String newContents,
+			String commitMessage) throws Exception {
+		targetFile.setContents(
+				new ByteArrayInputStream(newContents.getBytes()),
+				IResource.FORCE, new NullProgressMonitor());
+		new Git(testRepository.getRepository()).add()
+				.addFilepattern(repoRelativePath).call();
+		testRepository.addToIndex(targetFile);
+		return testRepository.commit(commitMessage);
+	}
+
+	protected void assertContentEquals(IFile file, String expectedContents)
+			throws Exception {
+		BufferedReader reader = new BufferedReader(new InputStreamReader(
+				file.getContents()));
+		StringBuilder contentsBuilder = new StringBuilder();
+		String line = reader.readLine();
+		while (line != null) {
+			contentsBuilder.append(line);
+			contentsBuilder.append('\n');
+			line = reader.readLine();
+		}
+		reader.close();
+		assertEquals(expectedContents, contentsBuilder.toString());
+	}
+
+	protected void merge(Repository repository, String refName)
+			throws CoreException {
+		new MergeOperation(repository, refName).execute(null);
+	}
+
+	protected Status status(Repository repository) throws Exception {
+		return new Git(repository).status().call();
+	}
+
+	protected IResourceMappingMerger createMerger() throws CoreException {
+		final ModelProvider provider = ModelProvider
+				.getModelProviderDescriptor(
+						SampleModelProvider.SAMPLE_PROVIDER_ID)
+				.getModelProvider();
+		return (ResourceMappingMerger) Platform.getAdapterManager().getAdapter(
+				provider, IResourceMappingMerger.class);
+	}
+
+	protected IMergeContext prepareContext(Repository repository,
+			IFile workspaceFile, String srcRev, String dstRev) throws Exception {
+		GitSynchronizeData gsd = new GitSynchronizeData(repository, srcRev,
+				dstRev, true, Collections.<IResource> singleton(workspaceFile));
+		GitSynchronizeDataSet gsds = new GitSynchronizeDataSet(gsd);
+		GitResourceVariantTreeSubscriber subscriber = new GitResourceVariantTreeSubscriber(
+				gsds);
+		subscriber.init(new NullProgressMonitor());
+
+		ResourceMapping mapping = AdapterUtils.adapt(workspaceFile,
+				ResourceMapping.class);
+		SubscriberScopeManager manager = new SubscriberScopeManager(
+				subscriber.getName(), new ResourceMapping[] { mapping, },
+				subscriber, true);
+		manager.initialize(new NullProgressMonitor());
+
+		GitSubscriberMergeContext mergeContext = new GitSubscriberMergeContext(
+				subscriber, manager, gsds);
+		// Wait for asynchronous update of the diff tree to end
+		Job.getJobManager().join(mergeContext, new NullProgressMonitor());
+		return mergeContext;
+	}
+
+	protected IMergeContext prepareModelContext(Repository repository,
+			IFile workspaceFile, String srcRev, String dstRev) throws Exception {
+		Set<IResource> includedResources = new HashSet<IResource>(
+				Arrays.asList(workspaceFile));
+		Set<IResource> newResources = new HashSet<IResource>(includedResources);
+		Set<ResourceMapping> allMappings = new HashSet<ResourceMapping>();
+		ResourceMappingContext mappingContext = ResourceMappingContext.LOCAL_CONTEXT;
+		ModelProvider provider = ModelProvider.getModelProviderDescriptor(
+				SampleModelProvider.SAMPLE_PROVIDER_ID).getModelProvider();
+		do {
+			Set<IResource> copy = newResources;
+			newResources = new HashSet<IResource>();
+			for (IResource resource : copy) {
+				ResourceMapping[] mappings = provider.getMappings(resource,
+						mappingContext, new NullProgressMonitor());
+				allMappings.addAll(Arrays.asList(mappings));
+
+				newResources.addAll(collectResources(mappings, mappingContext));
+			}
+		} while (includedResources.addAll(newResources));
+		ResourceMapping[] mappings = allMappings
+				.toArray(new ResourceMapping[allMappings.size()]);
+
+		GitSynchronizeData gsd = new GitSynchronizeData(repository, srcRev,
+				dstRev, true, includedResources);
+		GitSynchronizeDataSet gsds = new GitSynchronizeDataSet(gsd);
+		GitResourceVariantTreeSubscriber subscriber = new GitResourceVariantTreeSubscriber(
+				gsds);
+		subscriber.init(new NullProgressMonitor());
+
+		GitSubscriberResourceMappingContext resourceMappingContext = new GitSubscriberResourceMappingContext(
+				subscriber, gsds);
+		SubscriberScopeManager manager = new SubscriberScopeManager(
+				subscriber.getName(), mappings, subscriber,
+				resourceMappingContext, true);
+		manager.initialize(new NullProgressMonitor());
+
+		GitSubscriberMergeContext mergeContext = new GitSubscriberMergeContext(
+				subscriber, manager, gsds);
+		// Wait for asynchronous update of the diff tree to end
+		Job.getJobManager().join(mergeContext, new NullProgressMonitor());
+		return mergeContext;
+	}
+
+	private static Set<IResource> collectResources(ResourceMapping[] mappings,
+			ResourceMappingContext mappingContext) throws Exception {
+		final Set<IResource> resources = new HashSet<IResource>();
+		for (ResourceMapping mapping : mappings) {
+			ResourceTraversal[] traversals = mapping.getTraversals(
+					mappingContext, new NullProgressMonitor());
+			for (ResourceTraversal traversal : traversals)
+				resources.addAll(Arrays.asList(traversal.getResources()));
+		}
+		return resources;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleModelAdapterFactory.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleModelAdapterFactory.java
new file mode 100644
index 0000000..f429191
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleModelAdapterFactory.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (C) 2014 Obeo and others.
+ *
+ * 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.core.test.models;
+
+import org.eclipse.core.resources.mapping.ModelProvider;
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.team.core.mapping.IResourceMappingMerger;
+
+public class SampleModelAdapterFactory implements IAdapterFactory {
+	public Object getAdapter(Object adaptableObject, Class adapterType) {
+		if (adaptableObject instanceof SampleModelProvider
+				&& IResourceMappingMerger.class.isAssignableFrom(adapterType)) {
+			return new SampleResourceMappingMerger(
+					(ModelProvider) adaptableObject);
+		}
+		return null;
+	}
+
+	public Class[] getAdapterList() {
+		return new Class[] { IResourceMappingMerger.class, };
+	}
+}
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleModelProvider.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleModelProvider.java
new file mode 100644
index 0000000..af7c2c3
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleModelProvider.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (C) 2014 Obeo and others.
+ *
+ * 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.core.test.models;
+
+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.ResourceMapping;
+import org.eclipse.core.resources.mapping.ResourceMappingContext;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * This model provider will make all files of a given extension to be part of
+ * the same model. In this test, this will be used on files with extension
+ * {@link #SAMPLE_FILE_EXTENSION}.
+ */
+public class SampleModelProvider extends ModelProvider {
+	public static final String SAMPLE_PROVIDER_ID = "org.eclipse.egit.core.tests.sampleModelProvider";
+
+	public static final String SAMPLE_FILE_EXTENSION = "sample";
+
+	@Override
+	public ResourceMapping[] getMappings(IResource resource,
+			ResourceMappingContext context, IProgressMonitor monitor)
+			throws CoreException {
+		if (resource instanceof IFile
+				&& SAMPLE_FILE_EXTENSION.equals(resource.getFileExtension())) {
+			return new ResourceMapping[] { new SampleResourceMapping(
+					(IFile) resource, SAMPLE_PROVIDER_ID), };
+		}
+		return super.getMappings(resource, context, monitor);
+	}
+}
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleResourceMapping.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleResourceMapping.java
new file mode 100644
index 0000000..caabc18
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleResourceMapping.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (C) 2014 Obeo and others.
+ *
+ * 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.core.test.models;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+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;
+
+/**
+ * This resource mapping will consider all files of extension
+ * {@link SampleModelProvider#SAMPLE_FILE_EXTENSION} in a given folder to be
+ * part of the same model.
+ */
+public class SampleResourceMapping extends ResourceMapping {
+	private final IFile file;
+
+	private final String providerId;
+
+	public SampleResourceMapping(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 {
+		Set<IFile> sampleSiblings = new LinkedHashSet<IFile>();
+		for (IResource res : file.getParent().members()) {
+			if (res instanceof IFile && SampleModelProvider.SAMPLE_FILE_EXTENSION.equals(res.getFileExtension())) {
+				sampleSiblings.add((IFile) res);
+			}
+		}
+		final IResource[] resourceArray = sampleSiblings
+				.toArray(new IResource[sampleSiblings.size()]);
+		return new ResourceTraversal[] { new ResourceTraversal(
+				resourceArray, IResource.DEPTH_ONE, IResource.NONE), };
+	}
+
+	@Override
+	public IProject[] getProjects() {
+		return new IProject[] { file.getProject(), };
+	}
+}
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleResourceMappingMerger.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleResourceMappingMerger.java
new file mode 100644
index 0000000..dcd5b7a
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/models/SampleResourceMappingMerger.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (C) 2014 Obeo and others.
+ *
+ * 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.core.test.models;
+
+import org.eclipse.core.resources.mapping.ModelProvider;
+import org.eclipse.team.core.mapping.ResourceMappingMerger;
+
+public class SampleResourceMappingMerger extends ResourceMappingMerger {
+	private final ModelProvider provider;
+
+	public SampleResourceMappingMerger(ModelProvider provider) {
+		this.provider = provider;
+	}
+
+	@Override
+	protected ModelProvider getModelProvider() {
+		return provider;
+	}
+}
-- 
1.8.4.msysgit.0

begin:vcard
fn:Laurent Goubet
n:Goubet;Laurent
org:<a href="http://www.obeo.fr";>Obeo</a>
email;internet:laurent.goubet@xxxxxxx
url:http://www.obeo.fr
version:2.1
end:vcard


Back to the top