diff options
author | François Rey | 2012-11-24 17:55:48 +0000 |
---|---|---|
committer | Matthias Sohn | 2013-01-31 22:54:01 +0000 |
commit | 199f7e89afbd2149c1809138204c7ac539a17b7e (patch) | |
tree | f3c0a822325c04723660e349377bf83319f7d512 | |
parent | c41773cc4218d407dd81ee423c8e0aaca2910051 (diff) | |
download | egit-199f7e89afbd2149c1809138204c7ac539a17b7e.tar.gz egit-199f7e89afbd2149c1809138204c7ac539a17b7e.tar.xz egit-199f7e89afbd2149c1809138204c7ac539a17b7e.zip |
Gracefully ignore linked resources
A project may contain resources that are not located within the
project's directory in the local file system. These resources are
referred to as linked resources. This patch adds a few checks to
gracefully ignore them in a few functional cases: iterator, handlers,
actions, etc.
Bug: 333338
CQ: 6965
Change-Id: I5005ed46cdfab47fc6913dbd46fc1291b2ac79ab
Signed-off-by: François Rey <eclipse.org@francois.rey.name>
Signed-off-by: Chris Aniszczyk <zx@twitter.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
42 files changed, 550 insertions, 218 deletions
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/GitResourceDeltaTestHelper.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/GitResourceDeltaTestHelper.java new file mode 100644 index 0000000000..464897c388 --- /dev/null +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/GitResourceDeltaTestHelper.java @@ -0,0 +1,142 @@ +/******************************************************************************* + * Copyright (C) 2013, François Rey <eclipse.org_@_francois_._rey_._name> + * + * 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 + * + * Contributors: + * François Rey - First implementation as part of handling linked resources + *******************************************************************************/ +package org.eclipse.egit.core.test; + +import static org.hamcrest.Matchers.hasItem; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.util.Collection; +import java.util.HashSet; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.egit.core.Activator; +import org.eclipse.egit.core.internal.indexdiff.GitResourceDeltaVisitor; +import org.eclipse.egit.core.project.RepositoryMapping; +import org.eclipse.jgit.lib.Repository; + +/** + * Helper class for test cases that need to know what workspace changes egit + * will detect. Changes to files within the git repository folder are ignored + * by default, however this behavior can be changed by a constructor parameter. + * Usage: create one instance per test case and call {@link #setUp()} and + * {@link #tearDown()} before and after the test case. Use other functions + * to test and assert what changed resources are expected. + * Implementation is mainly an {@link IResourceChangeListener} which calls + * a {@link GitResourceDeltaVisitor} for each change that occurs in a project + * that uses egit. + */ +public class GitResourceDeltaTestHelper { + private Repository repository; + + private IResourceChangeListener resourceChangeListener; + + private final Collection<IResource> changedResources; + + private final boolean ignoreTeamPrivateMember; + + public GitResourceDeltaTestHelper(Repository repository) { + this(repository, true); + } + + public GitResourceDeltaTestHelper(Repository repository, + boolean ignoreTeamPrivateMember) { + this.repository = repository; + this.changedResources = new HashSet<IResource>(); + this.ignoreTeamPrivateMember = ignoreTeamPrivateMember; + } + + public void setUp() { + resourceChangeListener = new IResourceChangeListener() { + public void resourceChanged(final IResourceChangeEvent event) { + try { + event.getDelta().accept(new IResourceDeltaVisitor() { + public boolean visit(IResourceDelta delta) + throws CoreException { + final IResource resource = delta.getResource(); + IProject project = resource.getProject(); + if (project == null) + return true; + RepositoryMapping mapping = RepositoryMapping + .getMapping(resource); + if (mapping == null) + return true; + if (mapping.getRepository() != repository) + return false; + GitResourceDeltaVisitor visitor = new GitResourceDeltaVisitor( + repository); + try { + event.getDelta().accept(visitor); + } catch (CoreException e) { + Activator.logError(e.getMessage(), e); + return false; + } + IPath gitDirAbsolutePath = mapping + .getGitDirAbsolutePath(); + for (IResource res : visitor.getResourcesToUpdate()) { + if (ignoreTeamPrivateMember + && (res.isTeamPrivateMember() || gitDirAbsolutePath + .isPrefixOf(res + .getRawLocation() + .makeAbsolute()))) + continue; + changedResources.add(res); + } + return false; + } + }); + } catch (CoreException e) { + Activator.logError(e.getMessage(), e); + return; + } + } + }; + ResourcesPlugin.getWorkspace().addResourceChangeListener( + resourceChangeListener, IResourceChangeEvent.POST_CHANGE); + } + + public void tearDown() { + if (resourceChangeListener != null) { + ResourcesPlugin.getWorkspace().removeResourceChangeListener( + resourceChangeListener); + resourceChangeListener = null; + } + } + + public Collection<IResource> getChangedResources() { + return changedResources; + } + + public boolean noChangedResources() { + return changedResources.isEmpty(); + } + + public boolean anyChangedResources() { + return !changedResources.isEmpty(); + } + + public void assertChangedResources(String[] expected) { + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + for (String file : expected) + assertThat(changedResources, hasItem(root.findMember(file))); + assertEquals(expected.length, changedResources.size()); + } +}
\ No newline at end of file diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/LinkedResourcesTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/LinkedResourcesTest.java new file mode 100644 index 0000000000..d17453e0f4 --- /dev/null +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/LinkedResourcesTest.java @@ -0,0 +1,187 @@ +/******************************************************************************* + * Copyright (C) 2013, François Rey <eclipse.org_@_francois_._rey_._name> + * + * 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 + * + * Contributors: + * François Rey - First implementation as part of handling linked resources + *******************************************************************************/ +package org.eclipse.egit.core.test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.egit.core.Activator; +import org.eclipse.egit.core.ContainerTreeIterator; +import org.eclipse.egit.core.GitProvider; +import org.eclipse.egit.core.IteratorService; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.treewalk.WorkingTreeIterator; +import org.eclipse.team.core.RepositoryProvider; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class LinkedResourcesTest { + + TestUtils testUtils; + + File project1Dir; + + File project2Dir; + + TestRepository repository1; + + TestRepository repository2; + + String project1Name = "project1"; + + String project2Name = "project2"; + + IProject project1; + + IProject project2; + + GitResourceDeltaTestHelper resourceDeltaTestHelper1; + + GitResourceDeltaTestHelper resourceDeltaTestHelper2; + + @Before + public void setUp() throws Exception { + testUtils = new TestUtils(); + // Create first repo and project + project1 = testUtils.createProjectInLocalFileSystem(project1Name); + project1Dir = project1.getRawLocation().toFile(); + repository1 = new TestRepository(new File(project1Dir, + Constants.DOT_GIT)); + testUtils.addFileToProject(project1, + "project1folder1/project1folder1file1.txt", "Hello world"); + repository1.connect(project1); + repository1.trackAllFiles(project1); + repository1.commit("Initial commit"); + // Create 2nd repo and project + project2 = testUtils.createProjectInLocalFileSystem(project2Name); + project2Dir = project2.getRawLocation().toFile(); + repository2 = new TestRepository(new File(project2Dir, + Constants.DOT_GIT)); + testUtils.addFileToProject(project2, + "project2folder1/project2folder1file1.txt", "Hello world"); + repository2.connect(project2); + repository2.trackAllFiles(project2); + repository2.commit("Initial commit"); + // Set up git delta listener + resourceDeltaTestHelper1 = new GitResourceDeltaTestHelper( + repository1.getRepository()); + resourceDeltaTestHelper1.setUp(); + resourceDeltaTestHelper2 = new GitResourceDeltaTestHelper( + repository2.getRepository()); + resourceDeltaTestHelper2.setUp(); + } + + @After + public void tearDown() throws Exception { + if (resourceDeltaTestHelper1 != null) + resourceDeltaTestHelper1.tearDown(); + if (resourceDeltaTestHelper2 != null) + resourceDeltaTestHelper2.tearDown(); + project1.delete(true, null); + project2.delete(true, null); + project1 = null; + project2 = null; + repository1.dispose(); + repository2.dispose(); + repository1 = null; + repository2 = null; + testUtils.deleteTempDirs(); + testUtils = null; + Activator.getDefault().getRepositoryCache().clear(); + } + + @Test + public void testGitProviderCanHandleLinkedResources() throws Exception { + GitProvider provider = (GitProvider) RepositoryProvider + .getProvider(project1); + assertTrue(provider.canHandleLinkedResourceURI()); + } + + @Test + public void testLinkedResourcesIgnoredByGitResourceDeltaVisitor() + throws Exception { + // Create linked folder in project1 that points to project2 + IFolder folder = project1.getFolder("link2project2"); + folder.createLink(project2.getLocation(), + IResource.ALLOW_MISSING_LOCAL, null); + // Create linked file in project1 that points to a file in project2 + IFile file = project1.getFile("link2project2folder1file1.txt"); + file.createLink( + project2.getFile("project2folder1/project2folder1file1.txt") + .getLocation(), IResource.ALLOW_MISSING_LOCAL, null); + // Add file to project2 + testUtils.addFileToProject(project2, + "project2folder1/project2folder1file2.txt", "Hello world"); + // Links are written to the .project file + resourceDeltaTestHelper1 + .assertChangedResources(new String[] { "/project1/.project" }); + // Changes to linked resources are reported against their repository + resourceDeltaTestHelper2.assertChangedResources(new String[] { + "/project1/link2project2/project2folder1", + "/project1/link2project2/project2folder1/project2folder1file2.txt", + "/project1/link2project2/.project", + "/project1/link2project2/project2folder1/project2folder1file1.txt", + "/project1/link2project2", + "/project2/project2folder1/project2folder1file2.txt" }); + } + + @Test + public void testLinkedResourcesIgnoredByIteratorService() throws Exception { + // Create linked folder in project1 that points to project2 + IFolder folder = project1.getFolder("link2project2"); + folder.createLink(project2.getLocation(), + IResource.ALLOW_MISSING_LOCAL, null); + // Linked resources are ignored when searching the container of a folder + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + IContainer container = IteratorService.findContainer(root, folder + .getRawLocation().makeAbsolute().toFile()); + assertTrue(project2.equals(container)); + // Also test when the only project left is the one linking to the folder + repository2.disconnect(project2); + container = IteratorService.findContainer(root, folder.getRawLocation() + .makeAbsolute().toFile()); + assertNull(container); + } + + @Test + public void testLinkedResourcesIgnoredByContainerTreeIterator() + throws Exception { + // Create linked folder in project1 that points to project2 + IFolder folder = project1.getFolder("link2project2"); + folder.createLink(project2.getLocation(), + IResource.ALLOW_MISSING_LOCAL, null); + // Create linked file in project1 that points to a file in project2 + IFile file = project1.getFile("link2project2folder1file1.txt"); + file.createLink( + project2.getFile("project2folder1/project2folder1file1.txt") + .getLocation(), IResource.ALLOW_MISSING_LOCAL, null); + // Test iterator + WorkingTreeIterator iterator = IteratorService + .createInitialIterator(repository1.repository); + assertTrue(iterator instanceof ContainerTreeIterator); + while (!iterator.eof()) { + assertFalse(iterator.getEntryPathString().startsWith("link2")); + iterator.next(1); + } + } +} diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestRepository.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestRepository.java index 39619e2c4b..78f8625bf4 100644 --- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestRepository.java +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestRepository.java @@ -2,6 +2,7 @@ * Copyright (C) 2011, Mathias Kinzler <mathias.kinzler@sap.com> * Copyright (C) 2010, Jens Baumgart <jens.baumgart@sap.com> * Copyright (C) 2012, Robin Stocker <robin@nibor.org> + * Copyright (C) 2012, François Rey <eclipse.org_@_francois_._rey_._name> * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -18,9 +19,11 @@ import java.util.Collection; import java.util.Collections; import java.util.regex.Pattern; +import org.eclipse.core.filesystem.EFS; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Path; import org.eclipse.egit.core.Activator; @@ -245,6 +248,31 @@ public class TestRepository { .toString()); new Git(repository).add().addFilepattern(repoPath).call(); } + + /** + * Adds all project files to version control + * + * @param project + * @throws CoreException + */ + public void trackAllFiles(IProject project) throws CoreException { + project.accept(new IResourceVisitor() { + + public boolean visit(IResource resource) throws CoreException { + if (resource instanceof IFile) { + try { + track(EFS.getStore(resource.getLocationURI()) + .toLocalFile(0, null)); + } catch (Exception e) { + throw new CoreException(Activator.error(e.getMessage(), + e)); + } + } + return true; + } + }); + } + /** * Removes file from version control * diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestUtils.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestUtils.java index 702675260b..a0f34b9345 100644 --- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestUtils.java +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestUtils.java @@ -2,6 +2,7 @@ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com> * Copyright (C) 2010, Jens Baumgart <jens.baumgart@sap.com> * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com> + * Copyright (C) 2012, François Rey <eclipse.org_@_francois_._rey_._name> * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -44,6 +45,19 @@ public class TestUtils { public final static String COMMITTER = "The Commiter <The.committer@some.com>"; /** + * Return the base directory in which temporary directories are created. + * Current implementation returns a "temporary" folder in the user home. + * + * @return a "temporary" folder in the user home that may not exist. + * @throws IOException + */ + public File getBaseTempDir() throws IOException { + File userHome = FS.DETECTED.userHome(); + File rootDir = new File(userHome, "EGitCoreTestTempDir"); + return rootDir; + } + + /** * Create a "temporary" directory * * @param name @@ -53,9 +67,7 @@ public class TestUtils { * @throws IOException */ public File createTempDir(String name) throws IOException { - File userHome = FS.DETECTED.userHome(); - File rootDir = new File(userHome, "EGitCoreTestTempDir"); - File result = new File(rootDir, name); + File result = new File(getBaseTempDir(), name); if (result.exists()) FileUtils.delete(result, FileUtils.RECURSIVE | FileUtils.RETRY); return result; @@ -67,8 +79,7 @@ public class TestUtils { * @throws IOException */ public void deleteTempDirs() throws IOException { - File userHome = FS.DETECTED.userHome(); - File rootDir = new File(userHome, "EGitCoreTestTempDir"); + File rootDir = getBaseTempDir(); if (rootDir.exists()) FileUtils.delete(rootDir, FileUtils.RECURSIVE | FileUtils.RETRY); } @@ -142,10 +153,23 @@ public class TestUtils { } /** + * Create a project in the base directory of temp dirs + * + * @param projectName + * project name + * @return the project with a location pointing to the local file system + * @throws Exception + */ + public IProject createProjectInLocalFileSystem( + String projectName) throws Exception { + return createProjectInLocalFileSystem(getBaseTempDir(), projectName); + } + + /** * Create a project in the local file system * * @param parentFile - * the parent + * the parent directory * @param projectName * project name * @return the project with a location pointing to the local file system diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/DiscardChangesOperationTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/DiscardChangesOperationTest.java index c9683562ba..c5e6792673 100644 --- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/DiscardChangesOperationTest.java +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/DiscardChangesOperationTest.java @@ -1,6 +1,7 @@ /******************************************************************************* * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com> * Copyright (C) 2012, Robin Stocker <robin@nibor.org> + * Copyright (C) 2012, François Rey <eclipse.org_@_francois_._rey_._name> * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -14,15 +15,11 @@ import static org.junit.Assert.assertEquals; import java.io.ByteArrayInputStream; import java.io.File; -import org.eclipse.core.filesystem.EFS; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceVisitor; -import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; -import org.eclipse.egit.core.Activator; import org.eclipse.egit.core.op.DiscardChangesOperation; import org.eclipse.egit.core.test.DualRepositoryTestCase; import org.eclipse.egit.core.test.TestRepository; @@ -54,8 +51,7 @@ public class DiscardChangesOperationTest extends DualRepositoryTestCase { testUtils.addFileToProject(project, "folder1/file2.txt", "Hello world 2"); repository1.connect(project); - - trackAllFiles(project, repository1); + repository1.trackAllFiles(project); repository1.commit("Initial commit"); File workdir2 = testUtils.createTempDir("Project2"); @@ -64,8 +60,7 @@ public class DiscardChangesOperationTest extends DualRepositoryTestCase { testUtils.addFileToProject(project2, "file.txt", "initial"); repository2 = new TestRepository(new File(workdir2, Constants.DOT_GIT)); repository2.connect(project2); - - trackAllFiles(project2, repository2); + repository2.trackAllFiles(project2); repository2.commit("Initial commit"); } @@ -119,25 +114,6 @@ public class DiscardChangesOperationTest extends DualRepositoryTestCase { assertEquals("initial", replacedContents); } - private static void trackAllFiles(IProject project, final TestRepository testRepository) throws CoreException { - project.accept(new IResourceVisitor() { - - public boolean visit(IResource resource) throws CoreException { - if (resource instanceof IFile) { - try { - testRepository - .track(EFS.getStore(resource.getLocationURI()) - .toLocalFile(0, null)); - } catch (Exception e) { - throw new CoreException(Activator.error(e.getMessage(), - e)); - } - } - return true; - } - }); - } - private void setNewFileContent(IFile file, String content) throws Exception { file.setContents( new ByteArrayInputStream(content.getBytes(project diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/ListRemoteOperationTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/ListRemoteOperationTest.java index 1a5d472caa..ad3d5721e8 100644 --- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/ListRemoteOperationTest.java +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/ListRemoteOperationTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com> + * Copyright (C) 2010, 2012 Mathias Kinzler <mathias.kinzler@sap.com> and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -15,12 +15,7 @@ import static org.junit.Assert.fail; import java.io.File; import java.lang.reflect.InvocationTargetException; -import org.eclipse.core.filesystem.EFS; -import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceVisitor; -import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.egit.core.Activator; import org.eclipse.egit.core.op.CloneOperation; @@ -64,24 +59,7 @@ public class ListRemoteOperationTest extends DualRepositoryTestCase { testUtils.addFileToProject(project, "folder1/file1.txt", "Hello world"); repository1.connect(project); - - project.accept(new IResourceVisitor() { - - public boolean visit(IResource resource) throws CoreException { - if (resource instanceof IFile) { - try { - repository1 - .track(EFS.getStore(resource.getLocationURI()) - .toLocalFile(0, null)); - } catch (Exception e) { - throw new CoreException(Activator.error(e.getMessage(), - e)); - } - } - return true; - } - }); - + repository1.trackAllFiles(project); repository1.commit("Initial commit"); // let's get rid of the project diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/PushOperationTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/PushOperationTest.java index 0c6e6cde84..743cdd61f3 100644 --- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/PushOperationTest.java +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/PushOperationTest.java @@ -20,12 +20,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.eclipse.core.filesystem.EFS; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceVisitor; -import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.ILogListener; import org.eclipse.core.runtime.IStatus; @@ -86,24 +82,7 @@ public class PushOperationTest extends DualRepositoryTestCase { testUtils.addFileToProject(project, "folder1/file1.txt", "Hello world"); repository1.connect(project); - - project.accept(new IResourceVisitor() { - - public boolean visit(IResource resource) throws CoreException { - if (resource instanceof IFile) { - try { - repository1 - .track(EFS.getStore(resource.getLocationURI()) - .toLocalFile(0, null)); - } catch (Exception e) { - throw new CoreException(Activator.error(e.getMessage(), - e)); - } - } - return true; - } - }); - + repository1.trackAllFiles(project); repository1.commit("Initial commit"); // let's get rid of the project diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/TagOperationTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/TagOperationTest.java index 8118a3b73c..e5f633e3b1 100644 --- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/TagOperationTest.java +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/TagOperationTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com> + * Copyright (C) 2010, 2012 Chris Aniszczyk <caniszczyk@gmail.com> and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -14,14 +14,9 @@ import static org.junit.Assert.fail; import java.io.File; -import org.eclipse.core.filesystem.EFS; -import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.egit.core.Activator; import org.eclipse.egit.core.op.TagOperation; import org.eclipse.egit.core.test.DualRepositoryTestCase; import org.eclipse.egit.core.test.TestRepository; @@ -56,24 +51,7 @@ public class TagOperationTest extends DualRepositoryTestCase { testUtils.addFileToProject(project, "folder1/file1.txt", "Hello world"); repository1.connect(project); - - project.accept(new IResourceVisitor() { - - public boolean visit(IResource resource) throws CoreException { - if (resource instanceof IFile) { - try { - repository1 - .track(EFS.getStore(resource.getLocationURI()) - .toLocalFile(0, null)); - } catch (Exception e) { - throw new CoreException(Activator.error(e.getMessage(), - e)); - } - } - return true; - } - }); - + repository1.trackAllFiles(project); repository1.commit("Initial commit"); } diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/Activator.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/Activator.java index 8117237fc5..d37f450f89 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/Activator.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/Activator.java @@ -248,7 +248,8 @@ public class Activator extends Plugin implements DebugOptionsListener { && (delta.getFlags() & INTERESTING_CHANGES) == 0) return true; final IResource resource = delta.getResource(); - if (!resource.exists() || !resource.isAccessible()) + if (!resource.exists() || !resource.isAccessible() || + resource.isLinked(IResource.CHECK_ANCESTORS)) return false; if (resource.getType() != IResource.PROJECT) return true; diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java index c171de5258..f9a574285b 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2008, Google Inc. + * Copyright (C) 2008, 2012 Google Inc. and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -179,7 +179,8 @@ public class ContainerTreeIterator extends WorkingTreeIterator { hasInheritedResourceFilters, resources, entries); for (IResource resource : resources) - entries.add(new ResourceEntry(resource, inheritableResourceFilter)); + if (!resource.isLinked()) + entries.add(new ResourceEntry(resource, inheritableResourceFilter)); return entries.toArray(new Entry[entries.size()]); } @@ -221,11 +222,17 @@ public class ContainerTreeIterator extends WorkingTreeIterator { } Set<File> resourceEntries = new HashSet<File>(); - for (IResource resource : memberResources) { - IPath location = resource.getLocation(); - if (location != null) - resourceEntries.add(location.toFile()); - } + for (IResource resource : memberResources) + // Make sure linked resources are ignored here. + // This is particularly important in the case of a linked + // resource which targets a normally filtered/hidden file + // within the same location. In such case, ignoring it here + // ensures the actual target gets included in the code below. + if (!resource.isLinked()) { + IPath location = resource.getLocation(); + if (location != null) + resourceEntries.add(location.toFile()); + } IPath containerLocation = node.getLocation(); if (containerLocation != null) { @@ -233,8 +240,7 @@ public class ContainerTreeIterator extends WorkingTreeIterator { File[] children = folder.listFiles(); for (File child : children) { if (resourceEntries.contains(child)) - continue; - + continue; // ok if linked resources are ignored earlier on IPath childLocation = new Path(child.getAbsolutePath()); IWorkspaceRoot root = node.getWorkspace().getRoot(); IContainer container = root.getContainerForLocation(childLocation); diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java index 62b60ffe00..081c48297b 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java @@ -110,9 +110,6 @@ public class CoreText extends NLS { public static String DiscardChangesOperation_refreshFailed; /** */ - public static String DiscardChangesOperation_repoNotFound; - - /** */ public static String DeleteResourcesOperation_deletingResources; /** */ diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/IteratorService.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/IteratorService.java index 6f695ca9f3..99557a3cfe 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/IteratorService.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/IteratorService.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2010, Jens Baumgart <jens.baumgart@sap.com> + * Copyright (C) 2010, 2012 Jens Baumgart <jens.baumgart@sap.com> and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -11,6 +11,7 @@ package org.eclipse.egit.core; import java.io.File; import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.egit.core.project.RepositoryMapping; @@ -51,7 +52,8 @@ public class IteratorService { /** * The method searches a container resource related to the given file. The - * container must reside in a project that is shared with Git + * container must reside in a project that is shared with Git. Linked folders + * are ignored. * * @param root * the workspace root @@ -66,7 +68,9 @@ public class IteratorService { final IContainer[] containers = root.findContainersForLocationURI(file .toURI()); for (IContainer container : containers) - if (container.isAccessible() && isProjectSharedWithGit(container)) + if (container.isAccessible() + && !container.isLinked(IResource.CHECK_ANCESTORS) + && isProjectSharedWithGit(container)) return container; return null; } diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties b/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties index f7a3a25a5d..95959483f3 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties @@ -27,7 +27,6 @@ DiscardChangesOperation_discardFailed=Discarding changes of {0} failed DiscardChangesOperation_discardFailedSeeLog=Discarding changes failed. See log for details DiscardChangesOperation_discardingChanges=Discarding changes DiscardChangesOperation_refreshFailed=Refreshing resources failed -DiscardChangesOperation_repoNotFound=Repository not found DeleteResourcesOperation_deletingResources=Deleting resources DeleteResourcesOperation_deleteFailed=Deleting resource {0} failed. DeleteResourcesOperation_deleteFailedSeeLog=Deleting resources failed. See log for details diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/DiscardChangesOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/DiscardChangesOperation.java index e3b7316f04..d1e4ab5120 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/DiscardChangesOperation.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/DiscardChangesOperation.java @@ -19,7 +19,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceRuleFactory; import org.eclipse.core.resources.IWorkspace; @@ -37,7 +36,6 @@ import org.eclipse.egit.core.CoreText; import org.eclipse.egit.core.internal.job.RuleUtil; import org.eclipse.egit.core.internal.util.ProjectUtil; import org.eclipse.egit.core.internal.util.ResourceUtil; -import org.eclipse.egit.core.project.RepositoryMapping; import org.eclipse.jgit.api.CheckoutCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; @@ -121,14 +119,6 @@ public class DiscardChangesOperation implements IEGitOperation { private void discardChanges(IProgressMonitor monitor) throws CoreException { monitor.beginTask(CoreText.DiscardChangesOperation_discardingChanges, 2); boolean errorOccurred = false; - for (IResource res : files) { - Repository repo = getRepository(res); - if (repo == null) { - IStatus status = Activator.error( - CoreText.DiscardChangesOperation_repoNotFound, null); - throw new CoreException(status); - } - } try { discardChanges(); } catch (GitAPIException e) { @@ -153,16 +143,6 @@ public class DiscardChangesOperation implements IEGitOperation { } } - private static Repository getRepository(IResource resource) { - IProject project = resource.getProject(); - RepositoryMapping repositoryMapping = RepositoryMapping - .getMapping(project); - if (repositoryMapping != null) - return repositoryMapping.getRepository(); - else - return null; - } - private void discardChanges() throws GitAPIException { Map<Repository, Collection<String>> pathsByRepository = ResourceUtil .splitResourcesByRepository(files); diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/IgnoreOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/IgnoreOperation.java index 593ab51392..9b64564f0b 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/IgnoreOperation.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/IgnoreOperation.java @@ -111,6 +111,8 @@ public class IgnoreOperation implements IEGitOperation { private boolean isIgnored(IPath path) throws IOException { RepositoryMapping mapping = RepositoryMapping.getMapping(path); + if (mapping == null) + return true; // Linked resources may not be mapped Repository repository = mapping.getRepository(); String repoRelativePath = mapping.getRepoRelativePath(path); TreeWalk walk = new TreeWalk(repository); diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryFinder.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryFinder.java index 6caae3dce4..cc5cc01704 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryFinder.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryFinder.java @@ -2,6 +2,7 @@ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com> * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org> * Copyright (C) 2008, Google Inc. + * Copyright (C) 2012, François Rey <eclipse.org_@_francois_._rey_._name> * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -35,19 +36,16 @@ import org.eclipse.jgit.util.SystemReader; * <p> * This finder algorithm searches a project's contained files to see if any of * them are located within the working directory of an existing Git repository. - * The finder searches through linked resources, as the EGit core is capable of - * dealing with linked directories spanning multiple repositories in the same - * project. + * By default linked resources are ignored and not included in the search. * </p> * <p> * The search algorithm is exhaustive, it will find all matching repositories. - * For the project itself as well as for each linked container within the + * For the project itself and possibly for each linked container within the * project it scans down the local filesystem trees to locate any Git * repositories which may be found there. It also scans up the local filesystem * tree to locate any Git repository which may be outside of Eclipse's - * workspace-view of the world, but which contains the project or a linked - * resource within the project. In short, if there is a Git repository - * associated, it finds it. + * workspace-view of the world. + * In short, if there is a Git repository associated, it finds it. * </p> */ public class RepositoryFinder { @@ -76,7 +74,7 @@ public class RepositoryFinder { } /** - * Run the search algorithm. + * Run the search algorithm, ignoring linked resources. * * @param m * a progress monitor to report feedback to; may be null. @@ -88,17 +86,38 @@ public class RepositoryFinder { */ public Collection<RepositoryMapping> find(IProgressMonitor m) throws CoreException { + return find(m, false); + } + + /** + * Run the search algorithm. + * + * @param m + * a progress monitor to report feedback to; may be null. + * @param searchLinkedFolders + * specify if linked folders should be included in the search + * @return all found {@link RepositoryMapping} instances associated with the + * project supplied to this instance's constructor. + * @throws CoreException + * Eclipse was unable to access its workspace, and threw up on + * us. We're throwing it back at the caller. + * @since 2.3 + */ + public Collection<RepositoryMapping> find(IProgressMonitor m, boolean searchLinkedFolders) + throws CoreException { IProgressMonitor monitor; if (m == null) monitor = new NullProgressMonitor(); else monitor = m; - find(monitor, proj); + find(monitor, proj, searchLinkedFolders); return results; } - private void find(final IProgressMonitor m, final IContainer c) - throws CoreException { + private void find(final IProgressMonitor m, final IContainer c, boolean searchLinkedFolders) + throws CoreException { + if (!searchLinkedFolders && c.isLinked()) + return; // Ignore linked folders final IPath loc = c.getLocation(); m.beginTask("", 101); //$NON-NLS-1$ @@ -113,7 +132,7 @@ public class RepositoryFinder { if (ownCfg.isFile()) { register(c, ownCfg.getParentFile()); } - if (c.isLinked() || c instanceof IProject) { + if (c instanceof IProject) { File p = fsLoc.getParentFile(); while (p != null) { // TODO is this the right location? @@ -141,7 +160,7 @@ public class RepositoryFinder { if (o instanceof IContainer && !o.getName().equals(Constants.DOT_GIT)) { find(new SubProgressMonitor(m, scale), - (IContainer) o); + (IContainer) o, searchLinkedFolders); } else { m.worked(scale); } diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryMapping.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryMapping.java index 4bdaac33b8..587024e914 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryMapping.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryMapping.java @@ -5,6 +5,7 @@ * Copyright (C) 2008, Shunichi Fuji <palglowr@gmail.com> * Copyright (C) 2008, Google Inc. * Copyright (C) 2012, Robin Stocker <robin@nibor.org> + * Copyright (C) 2013, François Rey <eclipse.org_@_francois_._rey_._name> * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -236,16 +237,21 @@ public class RepositoryMapping { } /** - * Get the repository mapping for a resource + * Get the repository mapping for a resource. If the given resource is a + * linked resource, the raw location of the resource will be used to + * determine a repository mapping. * * @param resource - * @return the RepositoryMapping for this resource, - * or null for non GitProvider. + * @return the RepositoryMapping for this resource, or null for non + * GitProvider. */ public static RepositoryMapping getMapping(final IResource resource) { if (isNonWorkspace(resource)) return null; + if (resource.isLinked(IResource.CHECK_ANCESTORS)) + return getMapping(resource.getLocation()); + IProject project = resource.getProject(); if (project == null) return null; diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriber.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriber.java index 39e4dd9c14..dee4c3db27 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriber.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriber.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2011 IBM Corporation and others. + * Copyright (c) 2010-2012 IBM Corporation 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 @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Dariusz Luksza <dariusz@luksza.org> + * François Rey - gracefully ignore linked resources *******************************************************************************/ package org.eclipse.egit.core.synchronize; @@ -255,7 +256,7 @@ public class GitResourceVariantTreeSubscriber extends } private boolean shouldBeIncluded(IResource res) { - if (res == null) + if (res == null || res.isLinked(IResource.CHECK_ANCESTORS)) return false; final IProject proj = res.getProject(); if (proj == null) diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java index c721716b56..800cb018fc 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java @@ -39,9 +39,6 @@ public class UIText extends NLS { public static String AbstractHistoryCommanndHandler_NoInputMessage; /** */ - public static String AbstractHistoryCommanndHandler_NoUniqueRepository; - - /** */ public static String AbstractRebaseCommand_DialogTitle; /** */ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitActionHandler.java index 3e160b4403..453589a67e 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitActionHandler.java @@ -7,6 +7,7 @@ * Copyright (C) 2010, Stefan Lay <stefan.lay@sap.com> * Copyright (C) 2011, Jens Baumgart <jens.baumgart@sap.com> * Copyright (C) 2011, Benjamin Muskalla <benjamin.muskalla@tasktop.com> + * Copyright (C) 2012, François Rey <eclipse.org_@_francois_._rey_._name> * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -30,10 +31,9 @@ import org.eclipse.ui.IWorkbenchPart; public class CommitActionHandler extends RepositoryActionHandler { public Object execute(final ExecutionEvent event) throws ExecutionException { - final Repository[] repos = getRepositories(event); - if (repos.length == 0) + final Repository repo = getRepository(true, event); + if (repo == null) return null; - final Shell shell = getShell(event); IResource[] resourcesInScope; try { @@ -49,7 +49,7 @@ public class CommitActionHandler extends RepositoryActionHandler { // cancels the scope operation return null; } - CommitUI commitUi = new CommitUI(shell, repos[0], resourcesInScope, + CommitUI commitUi = new CommitUI(shell, repo, resourcesInScope, false); commitUi.commit(); return null; @@ -57,7 +57,7 @@ public class CommitActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return getRepositories().length > 0; + return selectionMapsToSingleRepository(); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithCommitActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithCommitActionHandler.java index a477e2d248..aeea16a022 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithCommitActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithCommitActionHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2011, Mathias Kinzler <mathias.kinzler@sap.com> + * Copyright (C) 2011, 2012 Mathias Kinzler <mathias.kinzler@sap.com> and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -43,9 +43,9 @@ public class CompareWithCommitActionHandler extends RepositoryActionHandler { public Object execute(ExecutionEvent event) throws ExecutionException { final Repository repo = getRepository(true, event); - IResource[] resources = getSelectedResources(event); if (repo == null) return null; + IResource[] resources = getSelectedResources(event); CommitSelectionDialog dlg = new CommitSelectionDialog(getShell(event), repo, resources); @@ -106,6 +106,6 @@ public class CompareWithCommitActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return getRepository() != null; + return selectionMapsToSingleRepository(); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithHeadActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithHeadActionHandler.java index aeb047e9c4..3854ed7caf 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithHeadActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithHeadActionHandler.java @@ -91,6 +91,6 @@ public class CompareWithHeadActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return getRepository() != null; + return selectionMapsToSingleRepository(); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexActionHandler.java index 522ef9a231..785e3f76b6 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexActionHandler.java @@ -78,7 +78,7 @@ public class CompareWithIndexActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return getRepository() != null; + return selectionMapsToSingleRepository(); } private ITypedElement getBaseTypeElement(final IPath baseLocation) { diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithPreviousActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithPreviousActionHandler.java index a6565ab73b..25788e821e 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithPreviousActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithPreviousActionHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 GitHub Inc. + * Copyright (c) 2011, 2012 GitHub Inc. 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 @@ -7,6 +7,7 @@ * * Contributors: * Kevin Sawicki (GitHub Inc.) - initial API and implementation + * François Rey - gracefully ignore linked resources *******************************************************************************/ package org.eclipse.egit.ui.internal.actions; @@ -173,6 +174,8 @@ public class CompareWithPreviousActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return super.isEnabled() && getSelectedResources().length == 1; + IResource[] selectedResources = getSelectedResources(); + return super.isEnabled() && selectedResources.length == 1 && + selectionMapsToSingleRepository(); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithRefActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithRefActionHandler.java index e590fadffa..d5ec2c56d0 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithRefActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithRefActionHandler.java @@ -124,6 +124,6 @@ public class CompareWithRefActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return getRepository() != null; + return selectionMapsToSingleRepository(); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ConfigureFetchActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ConfigureFetchActionHandler.java index f0eba3ab3b..06b83ffec0 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ConfigureFetchActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ConfigureFetchActionHandler.java @@ -28,9 +28,10 @@ public class ConfigureFetchActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return getRepository() != null + Repository repository = getRepository(); + return repository != null && SimpleConfigureFetchDialog - .getConfiguredRemote(getRepository()) != null; + .getConfiguredRemote(repository) != null; } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ConfigurePushActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ConfigurePushActionHandler.java index c018cd5f8a..587aea1018 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ConfigurePushActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ConfigurePushActionHandler.java @@ -28,9 +28,10 @@ public class ConfigurePushActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return getRepository() != null + Repository repository = getRepository(); + return repository != null && SimpleConfigurePushDialog - .getConfiguredRemote(getRepository()) != null; + .getConfiguredRemote(repository) != null; } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CreatePatchActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CreatePatchActionHandler.java index 9f4caf63fc..281dcbacab 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CreatePatchActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CreatePatchActionHandler.java @@ -34,6 +34,6 @@ public class CreatePatchActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return getRepository() != null; + return selectionMapsToSingleRepository(); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/FetchActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/FetchActionHandler.java index d712d582d5..e6b03f76d9 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/FetchActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/FetchActionHandler.java @@ -50,6 +50,6 @@ public class FetchActionHandler extends RepositoryActionHandler { } public boolean isEnabled() { - return getRepository() != null; + return selectionMapsToSingleRepository(); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PushActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PushActionHandler.java index 46482d551a..bf1a80ae22 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PushActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PushActionHandler.java @@ -54,8 +54,9 @@ public class PushActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { try { - return getRepository() != null - && getRepository().getRef(Constants.HEAD).getObjectId() != null; + Repository repository = getRepository(); + return repository != null + && repository.getRef(Constants.HEAD).getObjectId() != null; } catch (IOException e) { Activator.handleError(e.getMessage(), e, false); return false; diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ReplaceWithPreviousActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ReplaceWithPreviousActionHandler.java index 31ee66a896..47214feb6e 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ReplaceWithPreviousActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ReplaceWithPreviousActionHandler.java @@ -68,6 +68,8 @@ public class ReplaceWithPreviousActionHandler extends @Override public boolean isEnabled() { - return super.isEnabled() && getSelectedResources().length == 1; + IResource[] selectedResources = getSelectedResources(); + return super.isEnabled() && selectedResources.length == 1 && + selectionMapsToSingleRepository(); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryAction.java index e91ea2456c..3d8fb7e8c3 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryAction.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryAction.java @@ -145,8 +145,8 @@ public abstract class RepositoryAction extends AbstractHandler implements } /** - * By default always return true. Allow implementers decide does given - * action should be run or not + * By default always return true. Allow implementers to decide whether + * the action should be run or not * * @return {@code true} when action should be executed, {@code false} * otherwise 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 6fe0ab5d47..86140254c0 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 @@ -491,6 +491,13 @@ abstract class RepositoryActionHandler extends AbstractHandler { } /** + * @return true if all selected items map to the same repository, false otherwise. + */ + protected boolean selectionMapsToSingleRepository() { + return getRepository() != null; + } + + /** * @param selection * @return the resources in the selection */ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowBlameActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowBlameActionHandler.java index f72e96e93b..e2c515d6db 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowBlameActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowBlameActionHandler.java @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) 2011 GitHub Inc. + * Copyright (c) 2011, 2012 GitHub Inc. 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 @@ -7,6 +7,7 @@ * * Contributors: * Kevin Sawicki (GitHub Inc.) - initial API and implementation + * François Rey - gracefully ignore linked resources *****************************************************************************/ package org.eclipse.egit.ui.internal.actions; @@ -53,4 +54,11 @@ public class ShowBlameActionHandler extends RepositoryActionHandler { JobFamilies.BLAME); return null; } + + @Override + public boolean isEnabled() { + IResource[] selectedResources = getSelectedResources(); + return selectedResources.length == 1 && + selectionMapsToSingleRepository(); + } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowHistoryActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowHistoryActionHandler.java index e13d230a39..8a0315c101 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowHistoryActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowHistoryActionHandler.java @@ -1,18 +1,20 @@ /******************************************************************************* - * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com> + * Copyright (C) 2010, 2012 Mathias Kinzler <mathias.kinzler@sap.com> 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 + * + * Contributors: + * Mathias Kinzler - initial version + * François Rey - refactoring as part of gracefully ignoring linked resources *******************************************************************************/ package org.eclipse.egit.ui.internal.actions; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IResource; -import org.eclipse.egit.core.project.RepositoryMapping; -import org.eclipse.egit.ui.UIText; import org.eclipse.egit.ui.internal.history.HistoryPageInput; import org.eclipse.jgit.lib.Repository; import org.eclipse.team.ui.history.IHistoryView; @@ -24,6 +26,10 @@ import org.eclipse.ui.PlatformUI; */ public class ShowHistoryActionHandler extends RepositoryActionHandler { public Object execute(ExecutionEvent event) throws ExecutionException { + final Repository repo = getRepository(true, event); + // assert all resources map to the same repository + if (repo == null) + return null; IHistoryView view; try { view = (IHistoryView) PlatformUI.getWorkbench() @@ -34,19 +40,6 @@ public class ShowHistoryActionHandler extends RepositoryActionHandler { view.showHistoryFor(resources[0]); return null; } - - Repository repo = null; - for (IResource res : resources) { - RepositoryMapping map = RepositoryMapping.getMapping(res); - if (repo == null) - repo = map.getRepository(); - if (repo != map.getRepository()) - // we need to make sure are resources are from the same - // Repository - throw new ExecutionException( - UIText.AbstractHistoryCommanndHandler_NoUniqueRepository); - - } HistoryPageInput list = new HistoryPageInput(repo, resources); view.showHistoryFor(list); } catch (PartInitException e) { @@ -57,6 +50,6 @@ public class ShowHistoryActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return !getSelection().isEmpty(); + return selectionMapsToSingleRepository(); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowRepositoriesViewActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowRepositoriesViewActionHandler.java index 9fa45e70ae..a8278c2eff 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowRepositoriesViewActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowRepositoriesViewActionHandler.java @@ -1,10 +1,14 @@ /******************************************************************************* - * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com> + * Copyright (C) 2010, 2012 Mathias Kinzler <mathias.kinzler@sap.com> 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 + * + * Contributors: + * Mathias Kinzler - initial version + * François Rey - gracefully ignore linked resources *******************************************************************************/ package org.eclipse.egit.ui.internal.actions; @@ -37,6 +41,6 @@ public class ShowRepositoriesViewActionHandler extends RepositoryActionHandler { @Override public boolean isEnabled() { - return getSelection().size() == 1; + return getSelection().size() == 1 && selectionMapsToSingleRepository(); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SynchronizeWithMenu.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SynchronizeWithMenu.java index 19175f4aa3..b98c3ad169 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SynchronizeWithMenu.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SynchronizeWithMenu.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org> + * Copyright (C) 2011, 2012 Dariusz Luksza <dariusz@luksza.org> and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -89,7 +89,7 @@ public class SynchronizeWithMenu extends ContributionItem implements if (srv == null) return; final IResource selectedResource = getSelection(); - if (selectedResource == null) + if (selectedResource == null || selectedResource.isLinked(IResource.CHECK_ANCESTORS)) return; RepositoryMapping mapping = RepositoryMapping diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SynchronizeWorkspaceActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SynchronizeWorkspaceActionHandler.java index af798fc862..5328faa453 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SynchronizeWorkspaceActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SynchronizeWorkspaceActionHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org> + * Copyright (C) 2011, 2012 Dariusz Luksza <dariusz@luksza.org> and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -83,6 +83,8 @@ public class SynchronizeWorkspaceActionHandler extends RepositoryActionHandler { for (IResource resource : resources) { RepositoryMapping rm = RepositoryMapping.getMapping(resource); + if (rm == null) + continue; // Linked resources may not be in a repo if (resource instanceof IProject) result.put(rm.getRepository(), new HashSet<IContainer>()); else if (resource instanceof IContainer) { diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CompareTreeView.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CompareTreeView.java index 2dac6835ff..8684da791a 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CompareTreeView.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CompareTreeView.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2012 SAP AG and others. + * Copyright (c) 2011-2013 SAP AG and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Mathias Kinzler (SAP AG) - initial implementation + * Robin Stocker <robin@nibor.org> - ignore linked resources *******************************************************************************/ package org.eclipse.egit.ui.internal.dialogs; @@ -115,7 +116,8 @@ import org.eclipse.ui.part.ViewPart; * If the input is an {@link IContainer}, the tree is similar to the tree shown * by the PackageExplorer (based on {@link WorkbenchLabelProvider} and * {@link WorkbenchContentProvider}, otherwise a simple tree representing files - * and folders is used based on {@link PathNode} instances. + * and folders is used based on {@link PathNode} instances. Linked resources + * however are ignored and not listed as content. * <p> * The tree nodes are shown with icons for "Added", "Deleted", and * "Same Contents" for files. Files with same content can be hidden using a @@ -123,6 +125,7 @@ import org.eclipse.ui.part.ViewPart; * <p> * This view can also show files and folders outside the Eclipse workspace when * a {@link Repository} is used as input. + * <p> */ public class CompareTreeView extends ViewPart implements IMenuListener, IShowInSource { /** The "magic" compare version to compare with the index */ @@ -932,9 +935,12 @@ public class CompareTreeView extends ViewPart implements IMenuListener, IShowInS children = super.getChildren(element); List<Object> childList = new ArrayList<Object>(children.length); for (Object child : children) { - IPath path = new Path(repositoryMapping - .getRepoRelativePath((IResource) child)); - boolean isFile = ((IResource) child).getType() == IResource.FILE; + IResource childResource = (IResource) child; + if (childResource.isLinked()) + continue; + IPath path = new Path( + repositoryMapping.getRepoRelativePath(childResource)); + boolean isFile = childResource.getType() == IResource.FILE; // each path that is not ignored creates an entry in either // compareVersionMap or addedPaths, so we can check if a path diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java index e210a59fdd..55315a243f 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java @@ -6,6 +6,7 @@ * Copyright (C) 2010-2012, Matthias Sohn <matthias.sohn@sap.com> * Copyright (C) 2012, Daniel megert <daniel_megert@ch.ibm.com> * Copyright (C) 2012, Robin Stocker <robin@nibor.org> + * Copyright (C) 2012, François Rey <eclipse.org_@_francois_._rey_._name> * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -1614,7 +1615,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, continue; if (db != map.getRepository()) throw new IllegalStateException( - UIText.AbstractHistoryCommanndHandler_NoUniqueRepository); + UIText.RepositoryAction_multiRepoSelection); if (showAllFilter == ShowFilter.SHOWALLFOLDER) { final String path; diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/merge/GitMergeEditorInput.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/merge/GitMergeEditorInput.java index db0d846150..0cbcca4c41 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/merge/GitMergeEditorInput.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/merge/GitMergeEditorInput.java @@ -115,7 +115,7 @@ public class GitMergeEditorInput extends CompareEditorInput { if (repo != null && repo != map.getRepository()) throw new InvocationTargetException( new IllegalStateException( - UIText.AbstractHistoryCommanndHandler_NoUniqueRepository)); + UIText.RepositoryAction_multiRepoSelection)); filterPaths.add(map.getRepoRelativePath(resource)); repo = map.getRepository(); } @@ -123,7 +123,7 @@ public class GitMergeEditorInput extends CompareEditorInput { if (repo == null) throw new InvocationTargetException( new IllegalStateException( - UIText.AbstractHistoryCommanndHandler_NoUniqueRepository)); + UIText.RepositoryAction_multiRepoSelection)); if (monitor.isCanceled()) throw new InterruptedException(); diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties index 8be628f36c..9057973121 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties @@ -18,7 +18,6 @@ AbortRebaseCommand_CancelDialogMessage=The abort operation was canceled AbortRebaseCommand_JobName=Aborting Rebase AbstractHistoryCommanndHandler_CouldNotGetRepositoryMessage=Could not get the repository from the history view AbstractHistoryCommanndHandler_NoInputMessage=Could not get the current input from the history view -AbstractHistoryCommanndHandler_NoUniqueRepository=Resources belong to different repositories AbstractRebaseCommand_DialogTitle=Action Canceled AbstractReflogCommandHandler_NoInput=Could not get the current input from the Reflog View Activator_DefaultRepoFolderIsFile=The location {0} of the default repository folder is already used by a file @@ -1089,7 +1088,7 @@ DialogsPreferencePage_GitPrefixWarning=&Git prefix warning (Windows typically) DialogsPreferencePage_RebaseCheckbox=&Rebase confirmation DialogsPreferencePage_ShowDialog=Prompt DialogsPreferencePage_ShowInitialConfigCheckbox=&Initial configuration -DialogsPreferencePage_ShowCloneFailedDialog=Clone failed error +DialogsPreferencePage_ShowCloneFailedDialog=Clone failed error DiffEditorPage_TaskGeneratingDiff=Generating diff DiffEditorPage_TaskUpdatingViewer=Updating diff viewer DiffEditorPage_Title=Diff |