/*******************************************************************************
* Copyright (C) 2011, Philipp Thun <philipp.thun@sap.com>
* Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org>
* Copyright (C) 2011, Christian Halstrick <christian.halstrick@sap.com>
* Copyright (C) 2011, Jens Baumgart <jens.baumgart@sap.com>
* Copyright (C) 2013, Robin Stocker <robin@nibor.org>
*
* 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.internal.decorators;
import static org.eclipse.jgit.junit.JGitTestUtil.write;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.egit.core.Activator;
import org.eclipse.egit.core.JobFamilies;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffCacheEntry;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffData;
import org.eclipse.egit.ui.common.LocalRepositoryTestCase;
import org.eclipse.egit.ui.test.TestUtil;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.MergeResult.MergeStatus;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.util.FileUtils;
import org.junit.Before;
import org.junit.Test;
public class DecoratableResourceAdapterTest extends LocalRepositoryTestCase {
private static final String TEST_FILE = "TestFile";
private static final String TEST_FILE2 = "TestFolder2/TestFile2";
private static final String TEST_FOLDER = "TestFolder";
private static final String TEST_FOLDER2 = "TestFolder2";
private static final String SUB_FOLDER = "SubFolder";
private static final String SUB_FOLDER2 = "SubFolder2";
private File gitDir;
private IProject project;
private Git git;
private IndexDiffCacheEntry indexDiffCacheEntry;
@Before
public void setUp() throws Exception {
gitDir = createProjectAndCommitToRepository();
project = ResourcesPlugin.getWorkspace().getRoot().getProject(PROJ1);
Repository repo = lookupRepository(gitDir);
git = new Git(repo);
indexDiffCacheEntry = Activator.getDefault().getIndexDiffCache()
.getIndexDiffCacheEntry(repo);
waitForIndexDiffUpdate(false);
}
private void waitForIndexDiffUpdate(final boolean refreshCache)
throws Exception {
if (refreshCache)
indexDiffCacheEntry.refresh();
TestUtil.joinJobs(JobFamilies.INDEX_DIFF_CACHE_UPDATE);
}
private void assertHasUnstagedChanges(boolean expected,
IDecoratableResource... decoratableResources) {
for (IDecoratableResource d : decoratableResources) {
assertTrue(d.hasUnstagedChanges() == expected);
}
}
@Test
public void testDecorationEmptyProject() throws Exception {
IDecoratableResource[] expectedDRs = new IDecoratableResource[] { new TestDecoratableResource(
project).tracked() };
IDecoratableResource[] actualDRs = { new DecoratableResourceAdapter(
indexDiffCacheEntry.getIndexDiff(), project) };
assertArrayEquals(expectedDRs, actualDRs);
}
@Test
public void testDecorationNewEmptyFolder() throws Exception {
// Create new folder with sub folder
IFolder folder = project.getFolder(TEST_FOLDER);
folder.create(true, true, null);
IFolder subFolder = folder.getFolder(SUB_FOLDER);
subFolder.create(true, true, null);
IDecoratableResource[] expectedDRs = new IDecoratableResource[] {
new TestDecoratableResource(project).tracked(),
new TestDecoratableResource(folder).ignored(),
new TestDecoratableResource(subFolder).ignored() };
waitForIndexDiffUpdate(true);
IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
IDecoratableResource[] actualDRs = {
new DecoratableResourceAdapter(indexDiffData, project),
new DecoratableResourceAdapter(indexDiffData, folder),
new DecoratableResourceAdapter(indexDiffData, subFolder) };
assertArrayEquals(expectedDRs, actualDRs);
}
@Test
public void testDecorationFolderPrefixOfOtherFolder() throws Exception {
project.getFolder(TEST_FOLDER).create(true, true, null);
IFolder testFolder2 = project.getFolder(TEST_FOLDER2);
IDecoratableResource[] expectedDRs = new IDecoratableResource[] { new TestDecoratableResource(
testFolder2).tracked() };
waitForIndexDiffUpdate(true);
IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
IDecoratableResource[] actualDRs = { new DecoratableResourceAdapter(
indexDiffData, testFolder2) };
assertArrayEquals(expectedDRs, actualDRs);
}
@Test
public void testDecorationNewFile() throws Exception {
// Create new file
write(new File(project.getLocation().toFile(), TEST_FILE), "Something");
project.refreshLocal(IResource.DEPTH_INFINITE, null);
IResource file = project.findMember(TEST_FILE);
IDecoratableResource[] expectedDRs = new IDecoratableResource[] {
new TestDecoratableResource(project).tracked().dirty(),
new TestDecoratableResource(file) };
waitForIndexDiffUpdate(true);
IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
IDecoratableResource[] actualDRs = {
new DecoratableResourceAdapter(indexDiffData, project),
new DecoratableResourceAdapter(indexDiffData, file) };
assertArrayEquals(expectedDRs, actualDRs);
}
@Test
public void testDecorationIgnoredFile() throws Exception {
// Create new file
write(new File(project.getLocation().toFile(), "Test.dat"), "Something");
write(new File(project.getLocation().toFile(), TEST_FILE2), "Something");
write(new File(project.getLocation().toFile(), "Test"), "Something");
// Test is prefix of TestFile
write(new File(project.getLocation().toFile(), ".gitignore"), "Test");
project.refreshLocal(IResource.DEPTH_INFINITE, null);
IResource file = project.findMember("Test.dat");
IResource gitignore = project.findMember(".gitignore");
IResource test = project.findMember("Test");
IDecoratableResource[] expectedDRs = new IDecoratableResource[] {
new TestDecoratableResource(project).tracked().dirty(),
new TestDecoratableResource(gitignore),
new TestDecoratableResource(file),
new TestDecoratableResource(test).ignored() };
waitForIndexDiffUpdate(true);
IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
IDecoratableResource[] actualDRs = {
new DecoratableResourceAdapter(indexDiffData, project),
new DecoratableResourceAdapter(indexDiffData, gitignore),
new DecoratableResourceAdapter(indexDiffData, file),
new DecoratableResourceAdapter(indexDiffData, test) };
assertArrayEquals(expectedDRs, actualDRs);
}
@Test
public void testDecorationFileInIgnoredFolder() throws Exception {
// Create new file
FileUtils.mkdir(new File(project.getLocation().toFile(), "dir"));
write(new File(project.getLocation().toFile(), "dir/file"), "Something");
write(new File(project.getLocation().toFile(), ".gitignore"), "dir");
project.refreshLocal(IResource.DEPTH_INFINITE, null);
IResource dir = project.findMember("dir");
IResource file = project.findMember("dir/file");
IResource gitignore = project.findMember(".gitignore");
IDecoratableResource[] expectedDRs = new IDecoratableResource[] {
new TestDecoratableResource(project).tracked().dirty(),
new TestDecoratableResource(gitignore),
new TestDecoratableResource(file).ignored(),
new TestDecoratableResource(dir).ignored() };
waitForIndexDiffUpdate(true);
IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
IDecoratableResource[] actualDRs = {
new DecoratableResourceAdapter(indexDiffData, project),
new DecoratableResourceAdapter(indexDiffData, gitignore),
new DecoratableResourceAdapter(indexDiffData, file),
new DecoratableResourceAdapter(indexDiffData, dir) };
assertArrayEquals(expectedDRs, actualDRs);
}
@Test
public void testDecorationNewFileInSubfolder() throws Exception {
// Create new folder with sub folder
IFolder folder = project.getFolder(TEST_FOLDER);
folder.create(true, true, null);
IFolder subFolder = folder.getFolder(SUB_FOLDER);
subFolder.create(true, true, null);
// Create new file
write(new File(subFolder.getLocation().toFile().getAbsolutePath(),
TEST_FILE), "Something");
project.refreshLocal(IResource.DEPTH_INFINITE, null);
IResource file = subFolder.findMember(TEST_FILE);
IDecoratableResource[] expectedDRs = new IDecoratableResource[] {
new TestDecoratableResource(project).tracked().dirty(),
new TestDecoratableResource(folder).dirty(),
new TestDecoratableResource(subFolder).dirty(),
new TestDecoratableResource(file) };
waitForIndexDiffUpdate(true);
IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
IDecoratableResource[] actualDRs = {
new DecoratableResourceAdapter(indexDiffData, project),
new DecoratableResourceAdapter(indexDiffData, folder),
new DecoratableResourceAdapter(indexDiffData, subFolder),
new DecoratableResourceAdapter(indexDiffData, file) };
for (int i = 0; i < expectedDRs.length; i++)
assert (expectedDRs[i].equals(actualDRs[i]));
}
@Test
public void testDecorationAddedFile() throws Exception {
// Create new file
write(new File(project.getLocation().toFile(), TEST_FILE), "Something");
project.refreshLocal(IResource.DEPTH_INFINITE, null);
IResource file = project.findMember(TEST_FILE);
// Add file
git.add().addFilepattern(".").call();
IDecoratableResource[] expectedDRs = new IDecoratableResource[] {
new TestDecoratableResource(project).tracked().modified(),
new TestDecoratableResource(file).tracked().added() };
waitForIndexDiffUpdate(true);
IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
IDecoratableResource[] actualDRs = {
new DecoratableResourceAdapter(indexDiffData, project),
new DecoratableResourceAdapter(indexDiffData, file) };
assertArrayEquals(expectedDRs, actualDRs);
}
@Test
public void testDecorationCommittedFile() throws Exception {
// Create new file
write(new File(project.getLocation().toFile(), TEST_FILE), "Something");
project.refreshLocal(IResource.DEPTH_INFINITE, null);
IResource file = project.findMember(TEST_FILE);
// Add and commit file
git.add().addFilepattern(".").call();
git.commit().setMessage("First commit").call();
IDecoratableResource[] expectedDRs = new IDecoratableResource[] {
new TestDecoratableResource(project).tracked(),
new TestDecoratableResource(file).tracked() };
waitForIndexDiffUpdate(true);
IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
IDecoratableResource[] actualDRs = {
new DecoratableResourceAdapter(indexDiffData, project),
new DecoratableResourceAdapter(indexDiffData, file) };
assertArrayEquals(expectedDRs, actualDRs);
assertHasUnstagedChanges(false, actualDRs);
}
@Test
public void testDecorationModifiedFile() throws Exception {
// Create new file
File f = new File(project.getLocation().toFile(), TEST_FILE);
write(f, "Something");
project.refreshLocal(IResource.DEPTH_INFINITE, null);
IResource file = project.findMember(TEST_FILE);
// Add and commit file
git.add().addFilepattern(".").call();
git.commit().setMessage("First commit").call();
// Change file content
write(f, "SomethingElse");
IDecoratableResource[] expectedDRs = new IDecoratableResource[] {
new TestDecoratableResource(project).tracked().dirty(),
new TestDecoratableResource(file).tracked().dirty() };
waitForIndexDiffUpdate(true);
IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
IDecoratableResource[] actualDRs = {
new DecoratableResourceAdapter(indexDiffData, project),
new DecoratableResourceAdapter(indexDiffData, file) };
assertArrayEquals(expectedDRs, actualDRs);
assertHasUnstagedChanges(true, actualDRs);
}
@Test
public void testDecorationConflictingFile() throws Exception {
// Create new file
File f = new File(project.getLocation().toFile(), TEST_FILE);
write(f, "Something");
project.refreshLocal(IResource.DEPTH_INFINITE, null);
IResource file = project.findMember(TEST_FILE);
// Add and commit file
git.add().addFilepattern(".").call();
git.commit().setMessage("Commit on master branch").call();
// Create and checkout new branch, change file content, add and commit
// file
git.checkout().setCreateBranch(true).setName("first_topic").call();
write(f, "SomethingElse");
project.refreshLocal(IResource.DEPTH_INFINITE, null);
git.add().addFilepattern(".").call();
RevCommit commitOnFirstTopicBranch = git.commit()
.setMessage("Commit on first topic branch").call();
// Create and checkout new branch (from master), change file content,
// add and commit file
git.checkout().setName("master").call();
git.checkout().setCreateBranch(true).setName("second_topic").call();
write(f, "SomethingDifferent");
project.refreshLocal(IResource.DEPTH_INFINITE, null);
git.add().addFilepattern(".").call();
git.commit().setMessage("Commit on second topic branch").call();
// Merge HEAD ('Commit on second topic branch') with 'Commit on first
// topic branch' to create a conflict
assertTrue(git.merge().include(commitOnFirstTopicBranch).call()
.getMergeStatus() == MergeStatus.CONFLICTING);
IDecoratableResource[] expectedDRs = new IDecoratableResource[] {
new TestDecoratableResource(project).tracked().conflicts(),
new TestDecoratableResource(file).tracked().conflicts() };
waitForIndexDiffUpdate(true);
IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
IDecoratableResource[] actualDRs = {
new DecoratableResourceAdapter(indexDiffData, project),
new DecoratableResourceAdapter(indexDiffData, file) };
assertArrayEquals(expectedDRs, actualDRs);
assertHasUnstagedChanges(true, actualDRs);
}
@Test
public void testDecorationDeletedFile() throws Exception {
// Create new file
File f = new File(project.getLocation().toFile(), TEST_FILE);
write(f, "Something");
project.refreshLocal(IResource.DEPTH_INFINITE, null);
// Add and commit file
git.add().addFilepattern(".").call();
git.commit().setMessage("First commit").call();
// Delete file
FileUtils.delete(f);
IDecoratableResource expectedDR = new TestDecoratableResource(project)
.tracked().dirty();
waitForIndexDiffUpdate(true);
IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
IDecoratableResource actualDR = new DecoratableResourceAdapter(
indexDiffData, project);
assertEquals(expectedDR, actualDR);
assertHasUnstagedChanges(true, actualDR);
}
@Test
public void testDecorationNewFileInOneSubfolder() throws Exception {
IFolder folder = project.getFolder(TEST_FOLDER);
folder.create(true, true, null);
IFolder subFolder = folder.getFolder(SUB_FOLDER);
subFolder.create(true, true, null);
IFolder subFolder2 = folder.getFolder(SUB_FOLDER2);
subFolder2.create(true, true, null);
write(new File(subFolder2.getLocation().toFile().getAbsolutePath(),
TEST_FILE), "Something");
project.refreshLocal(IResource.DEPTH_INFINITE, null);
IResource file = subFolder2.findMember(TEST_FILE);
IDecoratableResource[] expectedDRs = new IDecoratableResource[] {
new TestDecoratableResource(project).tracked().dirty(),
new TestDecoratableResource(folder).dirty(),
new TestDecoratableResource(subFolder).ignored(),
new TestDecoratableResource(subFolder2).dirty(),
new TestDecoratableResource(file) };
waitForIndexDiffUpdate(true);
IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
IDecoratableResource[] actualDRs = {
new DecoratableResourceAdapter(indexDiffData, project),
new DecoratableResourceAdapter(indexDiffData, folder),
new DecoratableResourceAdapter(indexDiffData, subFolder),
new DecoratableResourceAdapter(indexDiffData, subFolder2),
new DecoratableResourceAdapter(indexDiffData, file) };
assertArrayEquals(expectedDRs, actualDRs);
}
}
class TestDecoratableResource extends DecoratableResource {
public TestDecoratableResource(IResource resource) {
super(resource);
}
public TestDecoratableResource tracked() {
setTracked(true);
return this;
}
public TestDecoratableResource ignored() {
setIgnored(true);
return this;
}
public TestDecoratableResource dirty() {
setDirty(true);
return this;
}
public TestDecoratableResource conflicts() {
setConflicts(true);
return this;
}
public TestDecoratableResource added() {
setStagingState(StagingState.ADDED);
return this;
}
public IDecoratableResource modified() {
setStagingState(StagingState.MODIFIED);
return this;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof IDecoratableResource))
return false;
IDecoratableResource decoratableResource = (IDecoratableResource) obj;
if (!(decoratableResource.getType() == getType()))
return false;
if (!decoratableResource.getName().equals(getName()))
return false;
if (!(decoratableResource.isTracked() == isTracked()))
return false;
if (!(decoratableResource.isIgnored() == isIgnored()))
return false;
if (!(decoratableResource.isDirty() == isDirty()))
return false;
if (!(decoratableResource.hasConflicts() == hasConflicts()))
return false;
if (!decoratableResource.getStagingState().equals(getStagingState()))
return false;
return true;
}
@Override
public int hashCode() {
// this appeases FindBugs
return super.hashCode();
}
@Override
public String toString() {
return "TestDecoratableResourceAdapter[" + getName() + (isTracked() ? ", tracked" : "") + (isIgnored() ? ", ignored" : "") + (isDirty() ? ", dirty" : "") + (hasConflicts() ? ",conflicts" : "") + ", staged=" + getStagingState() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$//$NON-NLS-7$//$NON-NLS-8$//$NON-NLS-9$//$NON-NLS-10$//$NON-NLS-11$
}
}