1 /*******************************************************************************
2 * Copyright (C) 2013, Laurent Goubet <laurent.goubet@obeo.fr> and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *******************************************************************************/
8 package org
.eclipse
.egit
.core
.synchronize
;
10 import static org
.junit
.Assert
.assertEquals
;
11 import static org
.junit
.Assert
.assertFalse
;
12 import static org
.junit
.Assert
.assertTrue
;
14 import java
.io
.ByteArrayInputStream
;
16 import java
.io
.UnsupportedEncodingException
;
18 import org
.eclipse
.core
.resources
.IContainer
;
19 import org
.eclipse
.core
.resources
.IFile
;
20 import org
.eclipse
.core
.resources
.IFolder
;
21 import org
.eclipse
.core
.resources
.IProject
;
22 import org
.eclipse
.core
.resources
.IResource
;
23 import org
.eclipse
.core
.resources
.mapping
.RemoteResourceMappingContext
;
24 import org
.eclipse
.core
.resources
.mapping
.ResourceTraversal
;
25 import org
.eclipse
.core
.runtime
.CoreException
;
26 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
27 import org
.eclipse
.egit
.core
.project
.RepositoryMapping
;
28 import org
.eclipse
.egit
.core
.synchronize
.dto
.GitSynchronizeData
;
29 import org
.eclipse
.egit
.core
.synchronize
.dto
.GitSynchronizeDataSet
;
30 import org
.eclipse
.egit
.core
.test
.GitTestCase
;
31 import org
.eclipse
.egit
.core
.test
.TestRepository
;
32 import org
.eclipse
.jgit
.api
.Git
;
33 import org
.eclipse
.jgit
.junit
.JGitTestUtil
;
34 import org
.eclipse
.jgit
.lib
.Constants
;
35 import org
.eclipse
.jgit
.lib
.Repository
;
36 import org
.eclipse
.jgit
.revwalk
.RevCommit
;
37 import org
.junit
.Before
;
38 import org
.junit
.Test
;
40 public class GitSubscriberResourceMappingContextTest
extends GitTestCase
{
42 private static final String MASTER
= Constants
.R_HEADS
+ Constants
.MASTER
;
44 private static final String BRANCH
= Constants
.R_HEADS
+ "branch";
46 private Repository repo
;
48 private IProject iProject
;
50 private TestRepository testRepo
;
54 public void setUp() throws Exception
{
57 iProject
= project
.project
;
58 testRepo
= new TestRepository(gitDir
);
59 testRepo
.connect(iProject
);
60 repo
= RepositoryMapping
.getMapping(iProject
).getRepository();
62 // make initial commit
63 try (Git git
= new Git(repo
)) {
64 git
.commit().setAuthor("JUnit", "junit@jgit.org")
65 .setMessage("Initial commit").call();
70 public void hasLocalChange() throws Exception
{
71 File file1
= testRepo
.createFile(iProject
, "a.txt");
72 File file2
= testRepo
.createFile(iProject
, "b.txt");
73 testRepo
.appendContentAndCommit(iProject
, file1
, "content a",
75 testRepo
.appendContentAndCommit(iProject
, file2
, "content b",
78 IFile iFile1
= testRepo
.getIFile(iProject
, file1
);
79 IFile iFile2
= testRepo
.getIFile(iProject
, file2
);
81 RemoteResourceMappingContext context
= prepareContext(MASTER
, MASTER
);
82 assertFalse(context
.hasLocalChange(iFile1
, new NullProgressMonitor()));
83 assertFalse(context
.hasLocalChange(iFile2
, new NullProgressMonitor()));
85 JGitTestUtil
.write(file1
, "changed content a");
86 JGitTestUtil
.write(file2
, "changed content b");
88 refresh(context
, iFile1
, iFile2
);
89 assertTrue(context
.hasLocalChange(iFile1
, new NullProgressMonitor()));
90 assertTrue(context
.hasLocalChange(iFile2
, new NullProgressMonitor()));
92 JGitTestUtil
.write(file2
, "content b");
94 refresh(context
, iFile2
);
95 assertTrue(context
.hasLocalChange(iFile1
, new NullProgressMonitor()));
96 assertFalse(context
.hasLocalChange(iFile2
, new NullProgressMonitor()));
100 public void hasLocalChangeWithFileRemoval() throws Exception
{
101 File file1
= testRepo
.createFile(iProject
, "a.txt");
102 File file2
= testRepo
.createFile(iProject
, "b.txt");
103 File file3
= testRepo
.createFile(iProject
, "c.txt");
105 IFile iFile1
= testRepo
.getIFile(iProject
, file1
);
106 IFile iFile2
= testRepo
.getIFile(iProject
, file2
);
107 IFile iFile3
= testRepo
.getIFile(iProject
, file3
);
109 RemoteResourceMappingContext context
= prepareContext(MASTER
, MASTER
);
110 assertTrue(context
.hasLocalChange(iFile1
, new NullProgressMonitor()));
111 assertTrue(context
.hasLocalChange(iFile2
, new NullProgressMonitor()));
112 assertTrue(context
.hasLocalChange(iFile3
, new NullProgressMonitor()));
114 iFile1
.delete(false, null);
115 refresh(context
, iFile1
, iFile2
, iFile3
);
116 assertTrue(context
.hasLocalChange(iFile2
, new NullProgressMonitor()));
117 assertTrue(context
.hasLocalChange(iFile3
, new NullProgressMonitor()));
121 public void hasLocalChangeInNewFolder() throws Exception
{
122 iProject
.getFolder("folder").create(false, true, null);
123 RemoteResourceMappingContext context
= prepareContext(MASTER
, MASTER
);
124 // Folder is now known, but not yet file in it
126 File file
= testRepo
.createFile(iProject
, "folder/b.txt");
127 IFile iFile
= testRepo
.getIFile(iProject
, file
);
128 refresh(context
, iFile
);
129 assertTrue(context
.hasLocalChange(iFile
, new NullProgressMonitor()));
131 testRepo
.addToIndex(iProject
, file
);
132 refresh(context
, iFile
);
133 assertTrue(context
.hasLocalChange(iFile
, new NullProgressMonitor()));
135 JGitTestUtil
.write(file
, "changed content b");
136 refresh(context
, iFile
);
137 assertTrue(context
.hasLocalChange(iFile
, new NullProgressMonitor()));
141 public void hasRemoteChanges() throws Exception
{
142 File file1
= testRepo
.createFile(iProject
, "file1.sample");
143 File file2
= testRepo
.createFile(iProject
, "file2.sample");
145 testRepo
.appendContentAndCommit(iProject
, file1
,
146 "initial content - file 1",
147 "first file - initial commit MASTER");
148 testRepo
.appendContentAndCommit(iProject
, file2
,
149 "initial content - file 2",
150 "second file - initial commit MASTER");
152 IFile iFile1
= testRepo
.getIFile(iProject
, file1
);
153 IFile iFile2
= testRepo
.getIFile(iProject
, file2
);
155 testRepo
.createAndCheckoutBranch(MASTER
, BRANCH
);
157 setContentsAndCommit(iFile1
, "change in branch - file 1",
158 "branch commit - file1");
159 setContentsAndCommit(iFile2
, "change in branch - file 2",
160 "branch commit - file2");
162 testRepo
.checkoutBranch(MASTER
);
164 RemoteResourceMappingContext context
= prepareContext(MASTER
, BRANCH
);
165 assertFalse(context
.hasLocalChange(iFile1
, new NullProgressMonitor()));
166 assertTrue(context
.hasRemoteChange(iFile1
, new NullProgressMonitor()));
167 assertFalse(context
.hasLocalChange(iFile2
, new NullProgressMonitor()));
168 assertTrue(context
.hasRemoteChange(iFile2
, new NullProgressMonitor()));
170 setContents(iFile1
, "change in master - file 1");
171 refresh(context
, iFile1
);
172 assertTrue(context
.hasLocalChange(iFile1
, new NullProgressMonitor()));
173 assertTrue(context
.hasRemoteChange(iFile1
, new NullProgressMonitor()));
175 setContents(iFile2
, "change in branch - file 2");
176 refresh(context
, iFile2
);
177 assertTrue(context
.hasLocalChange(iFile2
, new NullProgressMonitor()));
178 assertTrue(context
.hasRemoteChange(iFile2
, new NullProgressMonitor()));
180 setContentsAndCommit(iFile1
, "change in branch - file 1",
181 "change in master (same as in branch) - file 2");
182 refresh(context
, iFile1
);
183 assertTrue(context
.hasLocalChange(iFile1
, new NullProgressMonitor()));
184 assertTrue(context
.hasRemoteChange(iFile1
, new NullProgressMonitor()));
188 public void hasRemoteChangeInNewFile() throws Exception
{
189 File file1
= testRepo
.createFile(iProject
, "file1.sample");
190 String initialContent1
= "some content for the first file";
191 testRepo
.appendContentAndCommit(iProject
, file1
, initialContent1
,
192 "first file - initial commit");
193 IFile iFile1
= testRepo
.getIFile(iProject
, file1
);
195 testRepo
.createAndCheckoutBranch(MASTER
, BRANCH
);
197 File file2
= testRepo
.createFile(iProject
, "file2.sample");
198 String initialContent2
= "some content for the second file";
199 testRepo
.appendContentAndCommit(iProject
, file2
, initialContent2
,
200 "second file - initial commit");
201 IFile iFile2
= testRepo
.getIFile(iProject
, file2
);
203 testRepo
.checkoutBranch(MASTER
);
205 RemoteResourceMappingContext context
= prepareContext(MASTER
, BRANCH
);
206 assertFalse(context
.hasRemoteChange(iFile1
, new NullProgressMonitor()));
207 assertTrue(context
.hasRemoteChange(iFile2
, new NullProgressMonitor()));
211 public void hasRemoteChangeInNewFolder() throws Exception
{
212 File file1
= testRepo
.createFile(iProject
, "file1.sample");
213 String initialContent1
= "some content for the first file";
214 testRepo
.appendContentAndCommit(iProject
, file1
, initialContent1
,
215 "first file - initial commit");
216 IFile iFile1
= testRepo
.getIFile(iProject
, file1
);
218 testRepo
.createAndCheckoutBranch(MASTER
, BRANCH
);
220 iProject
.getFolder("folder").create(true, true,
221 new NullProgressMonitor());
222 File file2
= testRepo
.createFile(iProject
, "folder/file2.sample");
223 String initialContent2
= "some content for the second file";
224 testRepo
.appendContentAndCommit(iProject
, file2
, initialContent2
,
225 "second file - initial commit");
226 IFile iFile2
= testRepo
.getIFile(iProject
, file2
);
228 testRepo
.checkoutBranch(MASTER
);
230 RemoteResourceMappingContext context
= prepareContext(MASTER
, BRANCH
);
231 assertFalse(context
.hasRemoteChange(iFile1
, new NullProgressMonitor()));
232 assertTrue(context
.hasRemoteChange(iFile2
, new NullProgressMonitor()));
236 public void hasLocalAndRemoteChange() throws Exception
{
237 File file1
= testRepo
.createFile(iProject
, "file1.sample");
238 testRepo
.appendContentAndCommit(iProject
, file1
, "initial content",
239 "first commit in master");
240 IFile iFile1
= testRepo
.getIFile(iProject
, file1
);
242 testRepo
.createAndCheckoutBranch(MASTER
, BRANCH
);
243 setContentsAndCommit(iFile1
, "changed content in branch",
244 "first commit in BRANCH");
246 testRepo
.checkoutBranch(MASTER
);
247 setContentsAndCommit(iFile1
, "changed content in master",
248 "second commit in MASTER");
250 RemoteResourceMappingContext context
= prepareContext(MASTER
, BRANCH
);
251 assertTrue(context
.hasRemoteChange(iFile1
, new NullProgressMonitor()));
252 assertTrue(context
.hasLocalChange(iFile1
, new NullProgressMonitor()));
256 public void hasLocalAndRemoteChangeInSubFolder() throws Exception
{
257 File file1
= testRepo
.createFile(iProject
, "folder/file1.sample");
258 testRepo
.appendContentAndCommit(iProject
, file1
, "initial content",
259 "first commit in master");
260 IFile iFile1
= testRepo
.getIFile(iProject
, file1
);
262 testRepo
.createAndCheckoutBranch(MASTER
, BRANCH
);
263 setContentsAndCommit(iFile1
, "changed content in branch",
264 "first commit in BRANCH");
266 testRepo
.checkoutBranch(MASTER
);
267 setContentsAndCommit(iFile1
, "changed content in master",
268 "second commit in MASTER");
270 RemoteResourceMappingContext context
= prepareContext(MASTER
, BRANCH
);
271 assertTrue(context
.hasRemoteChange(iFile1
, new NullProgressMonitor()));
272 assertTrue(context
.hasLocalChange(iFile1
, new NullProgressMonitor()));
276 public void hasLocalChangeWhenRefreshingParentFolder() throws Exception
{
277 IFolder folder
= iProject
.getFolder("newfolder");
278 folder
.create(false, true, null);
280 IFile file
= folder
.getFile("a.txt");
281 file
.create(new ByteArrayInputStream("a".getBytes("UTF-8")), false,
284 RemoteResourceMappingContext context
= prepareContext(MASTER
, MASTER
);
285 refresh(context
, file
);
287 assertTrue(context
.hasLocalChange(file
, new NullProgressMonitor()));
289 file
.delete(false, null);
291 // Refresh of folder, not file directly
292 refresh(context
, folder
);
294 assertFalse(context
.hasLocalChange(file
, new NullProgressMonitor()));
298 public void hasDeletion() throws Exception
{
299 File file1
= testRepo
.createFile(iProject
, "file1.sample");
300 testRepo
.appendContentAndCommit(iProject
, file1
, "initial content",
301 "first commit in master");
303 IFile iFile1
= testRepo
.getIFile(iProject
, file1
);
305 testRepo
.createAndCheckoutBranch(MASTER
, BRANCH
);
306 iFile1
.delete(true, new NullProgressMonitor());
307 try (Git git
= new Git(testRepo
.getRepository())) {
309 .addFilepattern(iProject
.getName() + '/' + iFile1
.getName())
313 testRepo
.commit("Deleted file1.sample");
315 RemoteResourceMappingContext context
= prepareContext(BRANCH
, MASTER
);
316 boolean hasFile1
= false;
317 for (IResource member
: context
.fetchMembers(iProject
,
318 new NullProgressMonitor())) {
319 if (iFile1
.getName().equals(member
.getName())) {
324 assertTrue(hasFile1
);
325 assertFalse(context
.hasRemoteChange(iFile1
, new NullProgressMonitor()));
326 assertTrue(context
.hasLocalChange(iFile1
, new NullProgressMonitor()));
330 public void hasNestedDeletion() throws Exception
{
331 File file1
= testRepo
.createFile(iProject
,
332 "sub/subfolder/file1.sample");
333 testRepo
.appendContentAndCommit(iProject
, file1
, "initial content",
334 "first commit in master");
336 IFile iFile1
= testRepo
.getIFile(iProject
, file1
);
338 assertTrue(iFile1
.exists());
340 IContainer subfolder
= iFile1
.getParent();
342 assertTrue(subfolder
instanceof IFolder
);
343 assertEquals("subfolder", subfolder
.getName());
345 IContainer sub
= subfolder
.getParent();
347 assertTrue(sub
instanceof IFolder
);
348 assertEquals("sub", sub
.getName());
350 testRepo
.createAndCheckoutBranch(MASTER
, BRANCH
);
351 iFile1
.delete(true, new NullProgressMonitor());
352 subfolder
.delete(true, new NullProgressMonitor());
353 sub
.delete(true, new NullProgressMonitor());
354 try (Git git
= new Git(testRepo
.getRepository())) {
357 iProject
.getName() + "/sub/subfolder/file1.sample")
358 .setUpdate(true).call();
360 testRepo
.commit("Deleted sub/subfolder/file1.sample");
362 assertFalse(iFile1
.exists());
363 assertFalse(subfolder
.exists());
364 assertFalse(sub
.exists());
366 RemoteResourceMappingContext context
= prepareContext(BRANCH
, MASTER
);
367 boolean hasFile1
= false;
368 for (IResource member
: context
.fetchMembers(iProject
,
369 new NullProgressMonitor())) {
370 if (sub
.getName().equals(member
.getName())) {
371 for (IResource child
: context
.fetchMembers(sub
,
372 new NullProgressMonitor())) {
373 if (subfolder
.getName().equals(child
.getName())) {
374 for (IResource grandchild
: context
.fetchMembers(
375 subfolder
, new NullProgressMonitor())) {
376 if (iFile1
.getName().equals(grandchild
.getName())) {
387 assertTrue(hasFile1
);
388 assertFalse(context
.hasRemoteChange(iFile1
, new NullProgressMonitor()));
389 assertTrue(context
.hasLocalChange(iFile1
, new NullProgressMonitor()));
391 context
.hasLocalChange(subfolder
, new NullProgressMonitor()));
392 assertTrue(context
.hasLocalChange(sub
, new NullProgressMonitor()));
395 private RevCommit
setContentsAndCommit(IFile targetFile
,
396 String newContents
, String commitMessage
)
398 setContents(targetFile
, newContents
);
399 return addAndCommit(targetFile
, commitMessage
);
402 private RevCommit
addAndCommit(IFile targetFile
, String commitMessage
) throws Exception
{
403 testRepo
.addToIndex(targetFile
);
404 return testRepo
.commit(commitMessage
);
407 private void setContents(IFile targetFile
, String newContents
)
408 throws CoreException
, UnsupportedEncodingException
{
409 targetFile
.setContents(
410 new ByteArrayInputStream(newContents
.getBytes("UTF-8")),
411 IResource
.FORCE
, new NullProgressMonitor());
414 private RemoteResourceMappingContext
prepareContext(String srcRev
,
415 String dstRev
) throws Exception
{
416 GitSynchronizeData gsd
= new GitSynchronizeData(repo
, srcRev
, dstRev
,
418 GitSynchronizeDataSet gsds
= new GitSynchronizeDataSet(gsd
);
419 GitResourceVariantTreeSubscriber subscriber
= new GitResourceVariantTreeSubscriber(
421 subscriber
.init(new NullProgressMonitor());
423 return new GitSubscriberResourceMappingContext(subscriber
, gsds
);
426 private void refresh(RemoteResourceMappingContext context
,
427 IResource
... resources
) throws Exception
{
428 context
.refresh(new ResourceTraversal
[] { new ResourceTraversal(
429 resources
, IResource
.DEPTH_INFINITE
, 0) }, 0,
430 new NullProgressMonitor());