diff options
6 files changed, 230 insertions, 78 deletions
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java index a9984d6b71..22c2784ef4 100644 --- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java +++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java @@ -236,13 +236,23 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase { protected File createProjectAndCommitToRepository(String repoName) throws Exception { + return createProjectAndCommitToRepository(repoName, PROJ1, PROJ2); + } + + protected File createProjectAndCommitToRepository(String repoName, + String projectName) throws Exception { + return createProjectAndCommitToRepository(repoName, projectName, null); + } + + protected File createProjectAndCommitToRepository(String repoName, + String project1Name, String project2Name) throws Exception { Repository myRepository = createLocalTestRepository(repoName); File gitDir = myRepository.getDirectory(); // we need to commit into master first IProject firstProject = createStandardTestProjectInRepository( - myRepository, PROJ1); + myRepository, project1Name); try { new ConnectProviderOperation(firstProject, gitDir).execute(null); @@ -251,20 +261,25 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase { } assertConnected(firstProject); - IProject secondProject = createStandardTestProjectInRepository( - myRepository, PROJ2); - - // TODO we should be able to hide the .project - // IFile gitignore = secondPoject.getFile(".gitignore"); - // gitignore.create(new ByteArrayInputStream("/.project\n" - // .getBytes(firstProject.getDefaultCharset())), false, null); - - try { - new ConnectProviderOperation(secondProject, gitDir).execute(null); - } catch (Exception e) { - Activator.logError("Failed to connect project to repository", e); + IProject secondProject = null; + if (project2Name != null) { + secondProject = createStandardTestProjectInRepository(myRepository, + project2Name); + + // TODO we should be able to hide the .project + // IFile gitignore = secondPoject.getFile(".gitignore"); + // gitignore.create(new ByteArrayInputStream("/.project\n" + // .getBytes(firstProject.getDefaultCharset())), false, null); + + try { + new ConnectProviderOperation(secondProject, gitDir) + .execute(null); + } catch (Exception e) { + Activator.logError("Failed to connect project to repository", + e); + } + assertConnected(secondProject); } - assertConnected(secondProject); IFile dotProject = firstProject.getFile(".project"); assertTrue(".project is not accessible: " + dotProject, @@ -272,12 +287,17 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase { IFolder folder = firstProject.getFolder(FOLDER); IFile textFile = folder.getFile(FILE1); IFile textFile2 = folder.getFile(FILE2); - folder = secondProject.getFolder(FOLDER); - IFile secondtextFile = folder.getFile(FILE1); - IFile secondtextFile2 = folder.getFile(FILE2); - - IFile[] commitables = new IFile[] { dotProject, - textFile, textFile2, secondtextFile, secondtextFile2 }; + IFile[] commitables = null; + if (secondProject != null) { + folder = secondProject.getFolder(FOLDER); + IFile secondtextFile = folder.getFile(FILE1); + IFile secondtextFile2 = folder.getFile(FILE2); + + commitables = new IFile[] { dotProject, textFile, textFile2, + secondtextFile, secondtextFile2 }; + } else { + commitables = new IFile[] { dotProject, textFile, textFile2 }; + } ArrayList<IFile> untracked = new ArrayList<IFile>(); untracked.addAll(Arrays.asList(commitables)); // commit to stable @@ -289,7 +309,10 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase { // now create a stable branch (from master) createStableBranch(myRepository); // and check in some stuff into master again - touchAndSubmit(null); + String newContent = "Touched at " + System.currentTimeMillis(); + IFile file = touch(firstProject.getName(), FOLDER + '/' + FILE1, + newContent); + addAndCommit(file, newContent); // Make sure cache entry is already listening for changes IndexDiffCache cache = Activator.getDefault().getIndexDiffCache(); diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/StageUnstageActionTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/StageUnstageActionTest.java new file mode 100644 index 0000000000..5f28c01d31 --- /dev/null +++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/StageUnstageActionTest.java @@ -0,0 +1,163 @@ +/******************************************************************************* + * Copyright (c) 2016 Thomas Wolf <thomas.wolf@paranor.ch> + * 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.test.team.actions; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.egit.core.JobFamilies; +import org.eclipse.egit.ui.common.LocalRepositoryTestCase; +import org.eclipse.egit.ui.internal.resources.IResourceState; +import org.eclipse.egit.ui.internal.resources.ResourceStateFactory; +import org.eclipse.egit.ui.test.ContextMenuHelper; +import org.eclipse.egit.ui.test.TestUtil; +import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Tests for the Team->Add To Index/Remove From Index actions. + */ +@RunWith(SWTBotJunit4ClassRunner.class) +public class StageUnstageActionTest extends LocalRepositoryTestCase { + + private static final String REPO_A = "repoA"; + + private static final String REPO_B = "repoB"; + + private static final String PROJ_A = "FirstProject"; + + private static final String PROJ_B = "SecondProject"; + + private String addToIndexLabel; + + private String removeFromIndexLabel; + + @Before + public void setup() throws Exception { + createProjectAndCommitToRepository(REPO_A, PROJ_A); + createProjectAndCommitToRepository(REPO_B, PROJ_B); + addToIndexLabel = util + .getPluginLocalizedValue("AddToIndexAction_label"); + removeFromIndexLabel = util + .getPluginLocalizedValue("RemoveFromIndexAction_label"); + } + + @Test + public void testActionsInitiallyNotPresent() { + // Verify that neither add to index nor remove from index are available. + SWTBotTree projectExplorerTree = TestUtil.getExplorerTree(); + util.getProjectItems(projectExplorerTree, PROJ_A)[0].select(); + assertFalse("Add To Index should not be present", + ContextMenuHelper.contextMenuItemExists(projectExplorerTree, + "Team", addToIndexLabel)); + assertFalse("Remove From Index should not be present", + ContextMenuHelper.contextMenuItemExists(projectExplorerTree, + "Team", removeFromIndexLabel)); + util.getProjectItems(projectExplorerTree, PROJ_B)[0].select(); + assertFalse("Add To Index should not be present", + ContextMenuHelper.contextMenuItemExists(projectExplorerTree, + "Team", addToIndexLabel)); + assertFalse("Remove From Index should not be present", + ContextMenuHelper.contextMenuItemExists(projectExplorerTree, + "Team", removeFromIndexLabel)); + projectExplorerTree.select(projectExplorerTree.getAllItems()); + assertFalse("Add To Index should not be present", + ContextMenuHelper.contextMenuItemExists(projectExplorerTree, + "Team", addToIndexLabel)); + assertFalse("Remove From Index should not be present", + ContextMenuHelper.contextMenuItemExists(projectExplorerTree, + "Team", removeFromIndexLabel)); + } + + @Test + public void testSingleProject() throws Exception { + // Change something in first project + String filePath = FOLDER + '/' + FILE1; + touch(PROJ_A, filePath, "Changed content"); + // Select other project + SWTBotTree projectExplorerTree = TestUtil.getExplorerTree(); + util.getProjectItems(projectExplorerTree, PROJ_B)[0].select(); + // Verify that Add to index is not present + assertFalse("Add To Index should not be present", + ContextMenuHelper.contextMenuItemExists(projectExplorerTree, + "Team", addToIndexLabel)); + assertFalse("Remove From Index should not be present", + ContextMenuHelper.contextMenuItemExists(projectExplorerTree, + "Team", removeFromIndexLabel)); + // Select first project; add to index + util.getProjectItems(projectExplorerTree, PROJ_A)[0].select(); + ContextMenuHelper.clickContextMenuSync(projectExplorerTree, "Team", + addToIndexLabel); + TestUtil.joinJobs(JobFamilies.INDEX_DIFF_CACHE_UPDATE); + // Verify file got staged + verifyStaging(PROJ_A, filePath, true); + // Remove from index + util.getProjectItems(projectExplorerTree, PROJ_A)[0].select(); + assertFalse("Add To Index should not be present", + ContextMenuHelper.contextMenuItemExists(projectExplorerTree, + "Team", addToIndexLabel)); + ContextMenuHelper.clickContextMenuSync(projectExplorerTree, "Team", + removeFromIndexLabel); + TestUtil.joinJobs(JobFamilies.INDEX_DIFF_CACHE_UPDATE); + // Verify file is unstaged again + verifyStaging(PROJ_A, filePath, false); + } + + @Test + public void testBothProjects() throws Exception { + // Change something in both + String filePath = FOLDER + '/' + FILE1; + touch(PROJ_A, filePath, "Changed content"); + touch(PROJ_B, filePath, "Changed content"); + // Select both projects + SWTBotTree projectExplorerTree = TestUtil.getExplorerTree(); + projectExplorerTree.select(projectExplorerTree.getAllItems()); + assertFalse("Remove From Index should not be present", + ContextMenuHelper.contextMenuItemExists(projectExplorerTree, + "Team", removeFromIndexLabel)); + // Add to index + ContextMenuHelper.clickContextMenuSync(projectExplorerTree, "Team", + addToIndexLabel); + TestUtil.joinJobs(JobFamilies.INDEX_DIFF_CACHE_UPDATE); + // Verify both files got staged + verifyStaging(PROJ_A, filePath, true); + verifyStaging(PROJ_B, filePath, true); + // Select both projects + projectExplorerTree.select(projectExplorerTree.getAllItems()); + // Remove from index + ContextMenuHelper.clickContextMenuSync(projectExplorerTree, "Team", + removeFromIndexLabel); + TestUtil.joinJobs(JobFamilies.INDEX_DIFF_CACHE_UPDATE); + // Verify both files got unstaged + verifyStaging(PROJ_A, filePath, false); + verifyStaging(PROJ_B, filePath, false); + } + + private void verifyStaging(String projectName, String filePath, + boolean expected) { + IProject project = ResourcesPlugin.getWorkspace().getRoot() + .getProject(projectName); + IResource resource = project.findMember(filePath); + assertNotNull(filePath + " should exist", resource); + IResourceState state = ResourceStateFactory.getInstance().get(resource); + if (expected) { + assertTrue(projectName + '/' + filePath + " should be staged", + state.isStaged()); + } else { + assertFalse(projectName + '/' + filePath + " should be unstaged", + state.isStaged()); + } + } +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AddToIndexActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AddToIndexActionHandler.java index aff158f335..119c98ebb0 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AddToIndexActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AddToIndexActionHandler.java @@ -78,7 +78,7 @@ public class AddToIndexActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return getProjectsInRepositoryOfSelectedResources().length > 0; + return haveSelectedResourcesWithRepository(); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RemoveFromIndexActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RemoveFromIndexActionHandler.java index d8dca1cdef..987371d044 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RemoveFromIndexActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RemoveFromIndexActionHandler.java @@ -70,7 +70,7 @@ public class RemoveFromIndexActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return getProjectsInRepositoryOfSelectedResources().length > 0; + return haveSelectedResourcesWithRepository(); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryActionHandler.java index 6c5add780e..041cbd0bbc 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryActionHandler.java @@ -31,7 +31,6 @@ import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.expressions.IEvaluationContext; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.runtime.IPath; import org.eclipse.egit.core.AdapterUtils; @@ -173,39 +172,28 @@ abstract class RepositoryActionHandler extends AbstractHandler { } /** - * List the projects with selected resources, if all projects are connected - * to a Git repository. + * Determines whether the selection contains only resources that are in some + * git repository. * - * @return the tracked projects affected by the current resource selection + * @return {@code true} if all resources in the selection belong to a git + * repository known to EGit. */ - protected IProject[] getProjectsInRepositoryOfSelectedResources() { + protected boolean haveSelectedResourcesWithRepository() { IStructuredSelection selection = getSelection(); - return getProjectsInRepositoryOfSelectedResources(selection); - } - - /** - * List the projects with selected resources, if all projects are connected - * to a Git repository. - * - * @param selection - * - * @return the tracked projects affected by the current resource selection - */ - private IProject[] getProjectsInRepositoryOfSelectedResources( - IStructuredSelection selection) { - Set<IProject> ret = new LinkedHashSet<IProject>(); - Repository[] repositories = getRepositoriesFor(getProjectsForSelectedResources(selection)); - final IProject[] projects = ResourcesPlugin.getWorkspace().getRoot() - .getProjects(); - for (IProject project : projects) { - RepositoryMapping mapping = RepositoryMapping.getMapping(project); - for (Repository repository : repositories) - if (mapping != null && mapping.getRepository() == repository) { - ret.add(project); - break; + if (selection != null) { + IResource[] resources = SelectionUtils + .getSelectedResources(selection); + if (resources.length > 0) { + for (IResource resource : resources) { + if (resource == null + || RepositoryMapping.getMapping(resource) == null) { + return false; + } } + return true; + } } - return ret.toArray(new IProject[ret.size()]); + return false; } /** diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/resources/ResourceStatePropertyTester.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/resources/ResourceStatePropertyTester.java index 85ce354485..743f670b0b 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/resources/ResourceStatePropertyTester.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/resources/ResourceStatePropertyTester.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2015, Thomas Wolf <thomas.wolf@paranor.ch> + * Copyright (C) 2015, 2016 Thomas Wolf <thomas.wolf@paranor.ch> * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -10,21 +10,15 @@ package org.eclipse.egit.ui.internal.resources; import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; import org.eclipse.core.expressions.PropertyTester; import org.eclipse.core.resources.IResource; -import org.eclipse.egit.core.Activator; -import org.eclipse.egit.core.AdapterUtils; -import org.eclipse.egit.core.internal.indexdiff.IndexDiffCacheEntry; -import org.eclipse.egit.core.internal.indexdiff.IndexDiffData; import org.eclipse.egit.ui.internal.selection.SelectionUtils; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.annotations.Nullable; -import org.eclipse.jgit.lib.Repository; /** * A property tester testing the {@IResourceState} of a file under EGit control. @@ -83,29 +77,13 @@ public class ResourceStatePropertyTester extends PropertyTester { } else { selection = new StructuredSelection(new ArrayList<>(collection)); } - Repository repository = SelectionUtils.getRepository(selection); - if (repository == null || repository.isBare()) { - return false; - } - IndexDiffCacheEntry diffCacheEntry = Activator.getDefault() - .getIndexDiffCache().getIndexDiffCacheEntry(repository); - if (diffCacheEntry == null) { - return false; - } - IndexDiffData indexDiffData = diffCacheEntry.getIndexDiff(); - if (indexDiffData == null) { - return false; - } - - Iterator<?> iterator = selection.iterator(); - while (iterator.hasNext()) { - IResource resource = AdapterUtils.adapt(iterator.next(), - IResource.class); + for (IResource resource : SelectionUtils + .getSelectedResources(selection)) { if (resource == null || !resource.isAccessible()) { continue; } IResourceState state = ResourceStateFactory.getInstance() - .get(indexDiffData, resource); + .get(resource); switch (property) { case HAS_STAGED_CHANGES: if (state.isStaged()) { |