diff options
6 files changed, 869 insertions, 0 deletions
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest.java new file mode 100755 index 0000000000..d1788301be --- /dev/null +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest.java @@ -0,0 +1,214 @@ +/******************************************************************************* + * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.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.core.synchronize; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +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.jgit.lib.Constants; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.PathFilter; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.variants.IResourceVariant; +import org.eclipse.team.core.variants.IResourceVariantTree; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +public class GitResourceVariantTreeSubscriberTest extends GitTestCase { + + private Repository repo; + + private IProject iProject; + + private TestRepository testRepo; + + @Before + public void setUp() throws Exception { + super.setUp(); + iProject = project.getProject(); + testRepo = new TestRepository(gitDir); + testRepo.connect(iProject); + repo = RepositoryMapping.getMapping(iProject).getRepository(); + } + + @After + public void clearGitResources() throws Exception { + testRepo.disconnect(iProject); + testRepo.dispose(); + repo = null; + super.tearDown(); + } + + /** + * This test simulates that user work and made some changes on branch 'test' + * and then try to synchronize "test" and 'master' branch. + * + * @throws Exception + */ + @Test + public void shouldReturnSrcBranchAsBase() throws Exception { + // when + String fileName = "Main.java"; + File file = testRepo.createFile(iProject, fileName); + RevCommit commit = testRepo.appendContentAndCommit(iProject, file, + "class Main {}", "initial commit"); + IFile mainJava = testRepo.getIFile(iProject, file); + testRepo.createAndCheckoutBranch(Constants.HEAD, Constants.R_HEADS + + "test"); + testRepo.appendContentAndCommit(iProject, file, "// test1", + "secont commit"); + + // given + GitResourceVariantTreeSubscriber grvts = createGitResourceVariantTreeSubscriber( + Constants.HEAD, Constants.R_HEADS + Constants.MASTER); + grvts.getBaseTree(); + IResourceVariantTree baseTree = grvts.getBaseTree(); + + // then + IResourceVariant actual = commonAssertionsForBaseTree(baseTree, + mainJava); + assertEquals(commit.abbreviate(7).name() + "...", + actual.getContentIdentifier()); + } + + /** + * Both source and destination branches has some different commits but they + * has also common ancestor. This situation is described more detailed in + * bug #317934 + * + * This test passes when it is run as a stand alone test case, but it fails + * when it is run as part of test suite. It throws NPE when it try's to + * checkout master branch. + * + * @throws Exception + */ + @Test + @Ignore + public void shouldReturnCommonAncestorAsBase() throws Exception { + // when + String fileName = "Main.java"; + File file = testRepo.createFile(iProject, fileName); + RevCommit commit = testRepo.appendContentAndCommit(iProject, file, + "class Main {}", "initial commit"); + IFile mainJava = testRepo.getIFile(iProject, file); + // this should be our common ancestor + ObjectId fileId = findFileId(commit, mainJava); + + testRepo.createAndCheckoutBranch(Constants.HEAD, Constants.R_HEADS + + "test"); + testRepo.appendContentAndCommit(iProject, file, "// test 1", + "second commit"); + + testRepo.checkoutBranch(Constants.R_HEADS + Constants.MASTER); + testRepo.appendContentAndCommit(iProject, file, "// test 2", + "third commit"); + + // given + GitResourceVariantTreeSubscriber grvts = createGitResourceVariantTreeSubscriber( + Constants.HEAD, Constants.R_HEADS + "test"); + grvts.getBaseTree(); + IResourceVariantTree baseTree = grvts.getBaseTree(); + + // then + IResourceVariant actual = commonAssertionsForBaseTree(baseTree, + mainJava); + assertEquals(fileId.getName(), actual.getContentIdentifier()); + } + + /** + * This test passes when it is run as a stand alone test case, but it fails + * when it is run as part of test suite. It throws NPE when it try's to + * checkout master branch. + * + * @throws Exception + */ + @Test + @Ignore + public void shouldReturnRemoteTree() throws Exception { + // when + String fileName = "Main.java"; + File file = testRepo.createFile(iProject, fileName); + testRepo.appendContentAndCommit(iProject, file, + "class Main {}", "initial commit"); + IFile mainJava = testRepo.getIFile(iProject, file); + + testRepo.createAndCheckoutBranch(Constants.HEAD, Constants.R_HEADS + + "test"); + RevCommit commit = testRepo.appendContentAndCommit(iProject, file, "// test 1", + "second commit"); + ObjectId fileId = findFileId(commit, mainJava); + + // given + GitResourceVariantTreeSubscriber grvts = createGitResourceVariantTreeSubscriber( + Constants.HEAD, "test"); + grvts.getBaseTree(); + IResourceVariantTree remoteTree = grvts.getRemoteTree(); + + // then + assertNotNull(remoteTree); + assertTrue(remoteTree instanceof GitRemoteResourceVariantTree); + IResourceVariant resourceVariant = remoteTree + .getResourceVariant(mainJava); + assertNotNull(resourceVariant); + assertTrue(resourceVariant instanceof GitResourceVariant); + assertEquals(fileId.getName(), resourceVariant.getContentIdentifier()); + } + + private GitResourceVariantTreeSubscriber createGitResourceVariantTreeSubscriber( + String src, String dst) throws IOException { + GitSynchronizeData gsd = new GitSynchronizeData(repo, src, dst, false); + GitSynchronizeDataSet gsds = new GitSynchronizeDataSet(gsd); + new GitResourceVariantTreeSubscriber(gsds); + return new GitResourceVariantTreeSubscriber(gsds); + } + + private ObjectId findFileId(RevCommit commit, IFile mainJava) + throws Exception { + TreeWalk tw = new TreeWalk(repo); + tw.reset(); + tw.setRecursive(true); + String path = Repository.stripWorkDir(repo.getWorkTree(), mainJava + .getLocation().toFile()); + tw.setFilter(PathFilter.create(path)); + int nth = tw.addTree(commit.getTree()); + tw.next(); + + return tw.getObjectId(nth); + } + + private IResourceVariant commonAssertionsForBaseTree( + IResourceVariantTree baseTree, IResource resource) + throws TeamException { + assertNotNull(baseTree); + assertTrue(baseTree instanceof GitBaseResourceVariantTree); + IResourceVariant resourceVariant = baseTree + .getResourceVariant(resource); + assertNotNull(resourceVariant); + assertTrue(resourceVariant instanceof GitResourceVariant); + return resourceVariant; + } + +} diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest1.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest1.java new file mode 100755 index 0000000000..cdc722a90b --- /dev/null +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest1.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.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.core.synchronize; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +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.jgit.lib.Constants; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.variants.IResourceVariant; +import org.eclipse.team.core.variants.IResourceVariantTree; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class GitResourceVariantTreeSubscriberTest1 extends GitTestCase { + + private Repository repo; + + private IProject iProject; + + private TestRepository testRepo; + + @Before + public void setUp() throws Exception { + super.setUp(); + iProject = project.getProject(); + testRepo = new TestRepository(gitDir); + testRepo.connect(iProject); + repo = RepositoryMapping.getMapping(iProject).getRepository(); + } + + @After + public void clearGitResources() throws Exception { + testRepo.disconnect(iProject); + testRepo.dispose(); + repo = null; + super.tearDown(); + } + + /** + * This test simulates that user work and made some changes on branch 'test' + * and then try to synchronize "test" and 'master' branch. + * + * @throws Exception + */ + @Test + public void shouldReturnSrcBranchAsBase() throws Exception { + // when + String fileName = "Main.java"; + File file = testRepo.createFile(iProject, fileName); + RevCommit commit = testRepo.appendContentAndCommit(iProject, file, + "class Main {}", "initial commit"); + IFile mainJava = testRepo.getIFile(iProject, file); + testRepo.createAndCheckoutBranch(Constants.HEAD, Constants.R_HEADS + + "test"); + testRepo.appendContentAndCommit(iProject, file, "// test1", + "secont commit"); + + // given + GitResourceVariantTreeSubscriber grvts = createGitResourceVariantTreeSubscriber( + Constants.HEAD, Constants.R_HEADS + Constants.MASTER); + grvts.getBaseTree(); + IResourceVariantTree baseTree = grvts.getBaseTree(); + + // then + IResourceVariant actual = commonAssertionsForBaseTree(baseTree, + mainJava); + assertEquals(commit.abbreviate(7).name() + "...", + actual.getContentIdentifier()); + } + + private GitResourceVariantTreeSubscriber createGitResourceVariantTreeSubscriber( + String src, String dst) throws IOException { + GitSynchronizeData gsd = new GitSynchronizeData(repo, src, dst, false); + GitSynchronizeDataSet gsds = new GitSynchronizeDataSet(gsd); + new GitResourceVariantTreeSubscriber(gsds); + return new GitResourceVariantTreeSubscriber(gsds); + } + + private IResourceVariant commonAssertionsForBaseTree( + IResourceVariantTree baseTree, IResource resource) + throws TeamException { + assertNotNull(baseTree); + assertTrue(baseTree instanceof GitBaseResourceVariantTree); + IResourceVariant resourceVariant = baseTree + .getResourceVariant(resource); + assertNotNull(resourceVariant); + assertTrue(resourceVariant instanceof GitResourceVariant); + return resourceVariant; + } + +} diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest2.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest2.java new file mode 100755 index 0000000000..50c6d369d6 --- /dev/null +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest2.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.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.core.synchronize; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +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.jgit.lib.Constants; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.variants.IResourceVariant; +import org.eclipse.team.core.variants.IResourceVariantTree; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class GitResourceVariantTreeSubscriberTest2 extends GitTestCase { + + private Repository repo; + + private IProject iProject; + + private TestRepository testRepo; + + @Before + public void setUp() throws Exception { + super.setUp(); + iProject = project.getProject(); + testRepo = new TestRepository(gitDir); + testRepo.connect(iProject); + repo = RepositoryMapping.getMapping(iProject).getRepository(); + } + + @After + public void clearGitResources() throws Exception { + testRepo.disconnect(iProject); + testRepo.dispose(); + repo = null; + super.tearDown(); + } + + /** + * Both source and destination branches has some different commits but they + * has also common ancestor. This situation is described more detailed in + * bug #317934 + * + * This test passes when it is run as a stand alone test case, but it fails + * when it is run as part of test suite. It throws NPE when it try's to + * checkout master branch. + * + * @throws Exception + */ + @Test + public void shouldReturnCommonAncestorAsBase() throws Exception { + // when + String fileName = "Main.java"; + File file = testRepo.createFile(iProject, fileName); + RevCommit commit = testRepo.appendContentAndCommit(iProject, file, + "class Main {}", "initial commit"); + IFile mainJava = testRepo.getIFile(iProject, file); + // this should be our common ancestor + + testRepo.createAndCheckoutBranch(Constants.HEAD, Constants.R_HEADS + + "test"); + testRepo.appendContentAndCommit(iProject, file, "// test 1", + "second commit"); + + testRepo.checkoutBranch(Constants.R_HEADS + Constants.MASTER); + testRepo.appendContentAndCommit(iProject, file, "// test 2", + "third commit"); + + // given + GitResourceVariantTreeSubscriber grvts = createGitResourceVariantTreeSubscriber( + Constants.HEAD, Constants.R_HEADS + "test"); + grvts.getBaseTree(); + IResourceVariantTree baseTree = grvts.getBaseTree(); + + // then + IResourceVariant actual = commonAssertionsForBaseTree(baseTree, + mainJava); + assertEquals(commit.abbreviate(7).name() + "...", + actual.getContentIdentifier()); + } + + private GitResourceVariantTreeSubscriber createGitResourceVariantTreeSubscriber( + String src, String dst) throws IOException { + GitSynchronizeData gsd = new GitSynchronizeData(repo, src, dst, false); + GitSynchronizeDataSet gsds = new GitSynchronizeDataSet(gsd); + new GitResourceVariantTreeSubscriber(gsds); + return new GitResourceVariantTreeSubscriber(gsds); + } + + private IResourceVariant commonAssertionsForBaseTree( + IResourceVariantTree baseTree, IResource resource) + throws TeamException { + assertNotNull(baseTree); + assertTrue(baseTree instanceof GitBaseResourceVariantTree); + IResourceVariant resourceVariant = baseTree + .getResourceVariant(resource); + assertNotNull(resourceVariant); + assertTrue(resourceVariant instanceof GitResourceVariant); + return resourceVariant; + } + +} diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeTest.java new file mode 100644 index 0000000000..ccbff67fdc --- /dev/null +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeTest.java @@ -0,0 +1,275 @@ +/******************************************************************************* + * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.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.core.synchronize; + +import static org.eclipse.jgit.lib.Constants.HEAD; +import static org.eclipse.jgit.lib.Constants.MASTER; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Comparator; + +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.op.ConnectProviderOperation; +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.TestProject; +import org.eclipse.egit.core.test.TestRepository; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IType; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.team.core.variants.IResourceVariant; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class GitResourceVariantTreeTest extends GitTestCase { + + private Repository repo; + + private IProject iProject; + + private TestRepository testRepo; + + @Before + public void createGitRepository() throws Exception { + iProject = project.project; + testRepo = new TestRepository(gitDir); + testRepo.connect(iProject); + repo = RepositoryMapping.getMapping(iProject).getRepository(); + } + + @After + public void clearGitResources() throws Exception { + testRepo.disconnect(iProject); + testRepo.dispose(); + repo = null; + super.tearDown(); + } + + /** + * roots() method should return list of projects that are associated with + * given repository. In this case there is only one project associated with + * this repository therefore only one root should be returned. + * + * @throws Exception + */ + @Test + public void shouldReturnOneRoot() throws Exception { + // when + new Git(repo).commit().setAuthor("JUnit", "junit@egit.org") + .setMessage("Initial commit").call(); + GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, HEAD, false); + GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data); + + // given + GitResourceVariantTree grvt = new GitTestResourceVariantTree(dataSet, + null); + + // then + assertEquals(1, grvt.roots().length); + IResource actualProject = grvt.roots()[0]; + assertEquals(this.project.getProject(), actualProject); + } + + /** + * When we have two or more project associated with repository, roots() + * method should return list of project. In this case we have two project + * associated with particular repository, therefore '2' value is expected. + * + * @throws Exception + */ + @Test + public void shouldReturnTwoRoots() throws Exception { + // when + // create second project + TestProject secondProject = new TestProject(true, "Project-2"); + IProject secondIProject = secondProject.project; + // add connect project with repository + new ConnectProviderOperation(secondIProject, gitDir).execute(null); + new Git(repo).commit().setAuthor("JUnit", "junit@egit.org") + .setMessage("Initial commit").call(); + GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, HEAD, false); + GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data); + + // given + GitResourceVariantTree grvt = new GitTestResourceVariantTree(dataSet, + null); + + // then + IResource[] roots = grvt.roots(); + // sort in order to be able to assert the project instances + Arrays.sort(roots, new Comparator<IResource>() { + public int compare(IResource r1, IResource r2) { + String path1 = r1.getFullPath().toString(); + String path2 = r2.getFullPath().toString(); + return path1.compareTo(path2); + } + }); + assertEquals(2, roots.length); + IResource actualProject = roots[0]; + assertEquals(this.project.project, actualProject); + IResource actualProject1 = roots[1]; + assertEquals(secondIProject, actualProject1); + } + + /** + * Checks that getResourceVariant will not throw NPE for null argument. This + * method is called with null argument when local or remote resource does + * not exist. + * + * @throws Exception + */ + @Test + public void shouldReturnNullResourceVariant() throws Exception { + // when + new Git(repo).commit().setAuthor("JUnit", "junit@egit.org") + .setMessage("Initial commit").call(); + GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, MASTER, + false); + GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data); + + // given + GitResourceVariantTree grvt = new GitRemoteResourceVariantTree(dataSet); + + // then + assertNull(grvt.getResourceVariant(null)); + } + + /** + * getResourceVariant() should return null when given resource doesn't exist + * in repository. + * + * @throws Exception + */ + @Test + public void shouldReturnNullResourceVariant2() throws Exception { + // when + IPackageFragment iPackage = project.createPackage("org.egit.test"); + IType mainJava = project.createType(iPackage, "Main.java", + "class Main {}"); + new Git(repo).commit().setAuthor("JUnit", "junit@egit.org") + .setMessage("Initial commit").call(); + GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, MASTER, + false); + GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data); + + // given + GitResourceVariantTree grvt = new GitRemoteResourceVariantTree(dataSet); + + // then + assertNull(grvt.getResourceVariant(mainJava.getResource())); + } + + /** + * Check if getResourceVariant() does return the same resource that was + * committed. Passes only when it is run as a single test, not as a part of + * largest test suite + * + * @throws Exception + */ + @Test + public void shoulReturnSameResourceVariant() throws Exception { + // when + String fileName = "Main.java"; + File file = testRepo.createFile(iProject, fileName); + testRepo.appendContentAndCommit(iProject, file, "class Main {}", + "initial commit"); + IFile mainJava = testRepo.getIFile(iProject, file); + GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, MASTER, + false); + GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data); + + // given + GitResourceVariantTree grvt = new GitRemoteResourceVariantTree(dataSet); + + // then + IResourceVariant actual = grvt.getResourceVariant(mainJava); + assertNotNull(actual); + assertEquals(fileName, actual.getName()); + + InputStream actualIn = actual.getStorage(new NullProgressMonitor()) + .getContents(); + byte[] actualByte = getBytesAndCloseStream(actualIn); + InputStream expectedIn = mainJava.getContents(); + byte[] expectedByte = getBytesAndCloseStream(expectedIn); + assertArrayEquals(expectedByte, actualByte); + } + + /** + * Create and commit Main.java file in master branch, then create branch + * "test" checkout nearly created branch and modify Main.java file. + * getResourceVariant() should obtain Main.java file content from "master" + * branch. Passes only when it is run as a single test, not as a part of + * largest test suite + * + * @throws Exception + */ + @Test + public void shouldReturnDifferentResourceVariant() throws Exception { + // when + String fileName = "Main.java"; + File file = testRepo.createFile(iProject, fileName); + testRepo.appendContentAndCommit(iProject, file, "class Main {}", + "initial commit"); + IFile mainJava = testRepo.getIFile(iProject, file); + + testRepo.createAndCheckoutBranch(Constants.R_HEADS + Constants.MASTER, + Constants.R_HEADS + "test"); + testRepo.appendContentAndCommit(iProject, file, "// test", + "first commit"); + GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, MASTER, + false); + GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data); + + // given + GitResourceVariantTree grvt = new GitRemoteResourceVariantTree(dataSet); + + // then + IResourceVariant actual = grvt.getResourceVariant(mainJava); + assertNotNull(actual); + assertEquals(fileName, actual.getName()); + + InputStream actualIn = actual.getStorage(new NullProgressMonitor()) + .getContents(); + byte[] actualByte = getBytesAndCloseStream(actualIn); + InputStream expectedIn = mainJava.getContents(); + byte[] expectedByte = getBytesAndCloseStream(expectedIn); + + // assert arrays not equals + if (Arrays.equals(expectedByte, actualByte)) + fail(); + else + assertTrue(true); + } + + private byte[] getBytesAndCloseStream(InputStream stream) throws Exception { + try { + byte[] actualByte = new byte[stream.available()]; + stream.read(actualByte); + return actualByte; + } finally { + stream.close(); + } + } +} diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitTestResourceVariantTree.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitTestResourceVariantTree.java new file mode 100644 index 0000000000..fbbd67bd84 --- /dev/null +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitTestResourceVariantTree.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.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.core.synchronize; + +import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData; +import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.variants.ResourceVariantByteStore; + +/** + * Implementation of abstract {@link GitResourceVariantTree} class. It is only + * used in {@link GitResourceVariantTreeTest} for testing public methods that + * are implemented in base class. + */ +class GitTestResourceVariantTree extends GitResourceVariantTree { + + GitTestResourceVariantTree(GitSynchronizeDataSet data, + ResourceVariantByteStore store) { + super(store, data); + } + + @Override + protected RevCommit getRevCommit(GitSynchronizeData gsd) + throws TeamException { + return null; + } + +} diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariantTree.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariantTree.java index 5003b1bfdb..3cbbaadbaf 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariantTree.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariantTree.java @@ -11,17 +11,30 @@ *******************************************************************************/ package org.eclipse.egit.core.synchronize; +import static org.eclipse.jgit.lib.ObjectId.zeroId; + import java.io.IOException; import java.util.HashSet; import java.util.Set; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.egit.core.CoreText; import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData; import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet; +import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevTree; +import org.eclipse.jgit.treewalk.FileTreeIterator; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.AndTreeFilter; +import org.eclipse.jgit.treewalk.filter.NotIgnoredFilter; +import org.eclipse.jgit.treewalk.filter.PathFilter; +import org.eclipse.jgit.treewalk.filter.TreeFilter; import org.eclipse.osgi.util.NLS; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.variants.IResourceVariant; @@ -49,6 +62,69 @@ abstract class GitResourceVariantTree extends ResourceVariantTree { @Override protected IResourceVariant fetchVariant(IResource resource, int depth, IProgressMonitor monitor) throws TeamException { + SubMonitor subMonitor = SubMonitor.convert(monitor); + if (resource == null || resource.getLocation() == null) { + subMonitor.done(); + return null; + } + + subMonitor.beginTask(NLS.bind( + CoreText.GitResourceVariantTree_fetchingVariant, + resource.getName()), IProgressMonitor.UNKNOWN); + try { + return fetchVariant(resource, subMonitor); + } finally { + subMonitor.done(); + } + } + + private IResourceVariant fetchVariant(IResource resource, + IProgressMonitor monitor) throws TeamException { + GitSynchronizeData gsd = gsds.getData(resource.getProject()); + if (gsd == null) + return null; + + Repository repo = gsd.getRepository(); + String path = getPath(resource, repo); + RevCommit revCommit = getRevCommit(gsd); + if (revCommit == null) + return null; + + if (path.length() == 0) + return handleRepositoryRoot(resource, repo, revCommit); + + try { + if (monitor.isCanceled()) + throw new OperationCanceledException(); + + TreeWalk tw = initializeTreeWalk(repo, path); + + int nth = tw.addTree(revCommit.getTree()); + if (resource.getType() == IResource.FILE) { + tw.setRecursive(true); + if (tw.next() && !tw.getObjectId(nth).equals(zeroId())) + return new GitBlobResourceVariant(repo, revCommit, + tw.getObjectId(nth), path); + } else { + while (tw.next() && !path.equals(tw.getPathString())) { + if (monitor.isCanceled()) + throw new OperationCanceledException(); + + if (tw.isSubtree()) + tw.enterSubtree(); + } + + ObjectId objectId = tw.getObjectId(nth); + if (!objectId.equals(zeroId())) + return new GitFolderResourceVariant(repo, revCommit, objectId, path); + } + } catch (IOException e) { + throw new TeamException( + NLS.bind( + CoreText.GitResourceVariantTree_couldNotFindResourceVariant, + resource), e); + } + return null; } @@ -83,4 +159,36 @@ abstract class GitResourceVariantTree extends ResourceVariantTree { */ protected abstract RevCommit getRevCommit(GitSynchronizeData gsd) throws TeamException; + + private IResourceVariant handleRepositoryRoot(final IResource resource, + Repository repo, RevCommit revCommit) throws TeamException { + try { + return new GitFolderResourceVariant(repo, revCommit, + revCommit.getTree(), resource.getLocation().toString()); + } catch (IOException e) { + throw new TeamException( + NLS.bind( + CoreText.GitResourceVariantTree_couldNotFindResourceVariant, + resource), e); + } + } + + private TreeWalk initializeTreeWalk(Repository repo, String path) + throws CorruptObjectException { + TreeWalk tw = new TreeWalk(repo); + tw.reset(); + int ignoreNth = tw.addTree(new FileTreeIterator(repo)); + + TreeFilter pathFilter = PathFilter.create(path); + TreeFilter ignoreFilter = new NotIgnoredFilter(ignoreNth); + tw.setFilter(AndTreeFilter.create(pathFilter, ignoreFilter)); + + return tw; + } + + private String getPath(final IResource resource, Repository repo) { + return Repository.stripWorkDir(repo.getWorkTree(), resource + .getLocation().toFile()); + } + } |