diff options
5 files changed, 133 insertions, 38 deletions
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/GitResourceDeltaVisitor.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/GitResourceDeltaVisitor.java index b938c32396..17c38bec58 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/GitResourceDeltaVisitor.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/GitResourceDeltaVisitor.java @@ -12,10 +12,12 @@ *******************************************************************************/ package org.eclipse.egit.core.internal.indexdiff; +import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; @@ -45,7 +47,7 @@ public class GitResourceDeltaVisitor implements IResourceDeltaVisitor { private final Collection<String> filesToUpdate; - private final Collection<IFile> fileResourcesToUpdate; + private final Collection<IResource> resourcesToUpdate; private boolean gitIgnoreChanged = false; @@ -60,7 +62,7 @@ public class GitResourceDeltaVisitor implements IResourceDeltaVisitor { this.repository = repository; filesToUpdate = new HashSet<String>(); - fileResourcesToUpdate = new HashSet<IFile>(); + resourcesToUpdate = new HashSet<IResource>(); } public boolean visit(IResourceDelta delta) throws CoreException { @@ -68,6 +70,20 @@ public class GitResourceDeltaVisitor implements IResourceDeltaVisitor { // Don't include ignored resources if (Team.isIgnoredHint(resource)) return false; + // If the resource is not part of a project under + // Git revision control + final RepositoryMapping mapping = RepositoryMapping + .getMapping(resource); + if (mapping == null || mapping.getRepository() != repository) + // Ignore the change + return true; + + if (resource instanceof IFolder + && delta.getKind() == IResourceDelta.ADDED) { + filesToUpdate.add(mapping.getRepoRelativePath(resource) + "/"); //$NON-NLS-1$ + resourcesToUpdate.add(resource); + return true; + } // If the file has changed but not in a way that we // care about (e.g. marker changes to files) then @@ -80,14 +96,6 @@ public class GitResourceDeltaVisitor implements IResourceDeltaVisitor { if (resource.getType() != IResource.FILE) return true; - // If the resource is not part of a project under - // Git revision control - final RepositoryMapping mapping = RepositoryMapping - .getMapping(resource); - if (mapping == null || mapping.getRepository() != repository) - // Ignore the change - return true; - if (resource.getName().equals(GITIGNORE_NAME)) { gitIgnoreChanged = true; return false; @@ -95,20 +103,31 @@ public class GitResourceDeltaVisitor implements IResourceDeltaVisitor { String repoRelativePath = mapping.getRepoRelativePath(resource); filesToUpdate.add(repoRelativePath); - fileResourcesToUpdate.add((IFile) resource); + resourcesToUpdate.add(resource); return true; } /** - * @return collection of resources to update + * @return collection of files to update */ public Collection<IFile> getFileResourcesToUpdate() { - return fileResourcesToUpdate; + Collection<IFile> result = new ArrayList<IFile>(); + for (IResource resource : resourcesToUpdate) + if (resource instanceof IFile) + result.add((IFile) resource); + return result; } /** - * @return collection of files to update + * @return collection of resources to update + */ + public Collection<IResource> getResourcesToUpdate() { + return resourcesToUpdate; + } + + /** + * @return collection of files / folders to update. Folder paths end with / */ public Collection<String> getFilesToUpdate() { return filesToUpdate; diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffCacheEntry.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffCacheEntry.java index bc6e6b3de6..873dc625b8 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffCacheEntry.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffCacheEntry.java @@ -15,7 +15,7 @@ import java.util.HashSet; import java.util.Set; import java.util.concurrent.locks.ReentrantLock; -import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IWorkspaceRunnable; @@ -212,7 +212,7 @@ public class IndexDiffCacheEntry { } private void scheduleUpdateJob(final Collection<String> filesToUpdate, - final Collection<IFile> fileResourcesToUpdate) { + final Collection<IResource> resourcesToUpdate) { if (!checkRepository()) return; Job job = new Job(getReloadJobName()) { @@ -225,7 +225,7 @@ public class IndexDiffCacheEntry { try { long startTime = System.currentTimeMillis(); IndexDiffData result = calcIndexDiffData(monitor, - getName(), filesToUpdate, fileResourcesToUpdate); + getName(), filesToUpdate, resourcesToUpdate); if (monitor.isCanceled()) return Status.CANCEL_STATUS; indexDiffData = result; @@ -234,7 +234,7 @@ public class IndexDiffCacheEntry { StringBuilder message = new StringBuilder( NLS.bind( "Updated IndexDiffData based on resource list (length = {0}) in {1} ms\n", //$NON-NLS-1$ - Integer.valueOf(fileResourcesToUpdate + Integer.valueOf(resourcesToUpdate .size()), Long.valueOf(time))); GitTraceLocation.getTrace().trace( GitTraceLocation.INDEXDIFFCACHE.getLocation(), @@ -268,7 +268,7 @@ public class IndexDiffCacheEntry { private IndexDiffData calcIndexDiffData(IProgressMonitor monitor, String jobName, Collection<String> filesToUpdate, - Collection<IFile> fileResourcesToUpdate) { + Collection<IResource> resourcesToUpdate) { EclipseGitProgressTransformer jgitMonitor = new EclipseGitProgressTransformer( monitor); final IndexDiff diffForChangedResources; @@ -284,7 +284,7 @@ public class IndexDiffCacheEntry { throw new RuntimeException(e); } return new IndexDiffData(indexDiffData, filesToUpdate, - fileResourcesToUpdate, diffForChangedResources); + resourcesToUpdate, diffForChangedResources); } private void notifyListeners() { @@ -329,7 +329,6 @@ public class IndexDiffCacheEntry { Activator.logError(e.getMessage(), e); return; } - Collection<String> filesToUpdate = visitor.getFilesToUpdate(); if (visitor.getGitIgnoreChanged()) scheduleReloadJob("A .gitignore changed"); //$NON-NLS-1$ @@ -337,7 +336,7 @@ public class IndexDiffCacheEntry { scheduleReloadJob("Resource changed, no diff available"); //$NON-NLS-1$ else if (!filesToUpdate.isEmpty()) if (filesToUpdate.size() < RESOURCE_LIST_UPDATE_LIMIT) - scheduleUpdateJob(filesToUpdate, visitor.getFileResourcesToUpdate()); + scheduleUpdateJob(filesToUpdate, visitor.getResourcesToUpdate()); else // Calculate new IndexDiff if too many resources changed // This happens e.g. when a project is opened diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffData.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffData.java index 8fe1fc93c4..5e04f48eca 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffData.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffData.java @@ -13,7 +13,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; import org.eclipse.jgit.lib.IndexDiff; /** @@ -37,11 +37,13 @@ public class IndexDiffData { private final Set<String> untracked; + private final Set<String> untrackedFolders; + private final Set<String> conflicts; private final Set<String> ignored; - private final Collection<IFile> changedFileResources; + private final Collection<IResource> changedResources; /** * @param indexDiff @@ -59,11 +61,19 @@ public class IndexDiffData { .getModified())); untracked = Collections.unmodifiableSet(new HashSet<String>(indexDiff .getUntracked())); + untrackedFolders = Collections.unmodifiableSet(getUntrackedFolders(indexDiff)); conflicts = Collections.unmodifiableSet(new HashSet<String>(indexDiff .getConflicting())); ignored = Collections.unmodifiableSet(new HashSet<String>(indexDiff .getIgnoredNotInIndex())); - changedFileResources = null; + changedResources = null; + } + + private Set<String> getUntrackedFolders(IndexDiff indexDiff) { + HashSet<String> result = new HashSet<String>(); + for (String folder:indexDiff.getUntrackedFolders()) + result.add(folder + "/"); //$NON-NLS-1$ + return result; } /** @@ -73,21 +83,23 @@ public class IndexDiffData { * * @param baseDiff * @param changedFiles - * @param changedFileResources + * collection of changed files / folders. folders must end with / + * @param changedResources * @param diffForChangedFiles */ public IndexDiffData(IndexDiffData baseDiff, Collection<String> changedFiles, - Collection<IFile> changedFileResources, + Collection<IResource> changedResources, IndexDiff diffForChangedFiles) { - this.changedFileResources = Collections - .unmodifiableCollection(new HashSet<IFile>(changedFileResources)); + this.changedResources = Collections + .unmodifiableCollection(new HashSet<IResource>(changedResources)); Set<String> added2 = new HashSet<String>(baseDiff.getAdded()); Set<String> changed2 = new HashSet<String>(baseDiff.getChanged()); Set<String> removed2 = new HashSet<String>(baseDiff.getRemoved()); Set<String> missing2 = new HashSet<String>(baseDiff.getMissing()); Set<String> modified2 = new HashSet<String>(baseDiff.getModified()); Set<String> untracked2 = new HashSet<String>(baseDiff.getUntracked()); + Set<String> untrackedFolders2 = new HashSet<String>(baseDiff.getUntrackedFolders()); Set<String> conflicts2 = new HashSet<String>(baseDiff.getConflicting()); Set<String> ignored2 = new HashSet<String>(baseDiff.getIgnoredNotInIndex()); @@ -97,6 +109,7 @@ public class IndexDiffData { mergeList(missing2, changedFiles, diffForChangedFiles.getMissing()); mergeList(modified2, changedFiles, diffForChangedFiles.getModified()); mergeList(untracked2, changedFiles, diffForChangedFiles.getUntracked()); + mergeList(untrackedFolders2, changedFiles, getUntrackedFolders(diffForChangedFiles)); mergeList(conflicts2, changedFiles, diffForChangedFiles.getConflicting()); mergeList(ignored2, changedFiles, @@ -108,6 +121,7 @@ public class IndexDiffData { missing = Collections.unmodifiableSet(missing2); modified = Collections.unmodifiableSet(modified2); untracked = Collections.unmodifiableSet(untracked2); + untrackedFolders = Collections.unmodifiableSet(untrackedFolders2); conflicts = Collections.unmodifiableSet(conflicts2); ignored = Collections.unmodifiableSet(ignored2); } @@ -168,6 +182,14 @@ public class IndexDiffData { } /** + * @return list of folders containing only untracked files/folders + * The folder paths end with / + */ + public Set<String> getUntrackedFolders() { + return untrackedFolders; + } + + /** * @return list of files that are in conflict */ public Set<String> getConflicting() { @@ -185,8 +207,8 @@ public class IndexDiffData { /** * @return the changed files */ - public Collection<IFile> getChangedFileResources() { - return changedFileResources; + public Collection<IResource> getChangedResources() { + return changedResources; } @Override @@ -198,10 +220,11 @@ public class IndexDiffData { dumpList(builder, "missing", missing); //$NON-NLS-1$ dumpList(builder, "modified", modified); //$NON-NLS-1$ dumpList(builder, "untracked", untracked); //$NON-NLS-1$ + dumpList(builder, "untrackedFolders", untrackedFolders); //$NON-NLS-1$ dumpList(builder, "conflicts", conflicts); //$NON-NLS-1$ dumpList(builder, "ignored", ignored); //$NON-NLS-1$ - dumpFileResourceList(builder, - "changedFileResources", changedFileResources); //$NON-NLS-1$ + dumpResourceList(builder, + "changedResources", changedResources); //$NON-NLS-1$ return builder.toString(); } @@ -216,13 +239,13 @@ public class IndexDiffData { builder.append(NEW_LINE); } - private void dumpFileResourceList(StringBuilder builder, String listName, - Collection<IFile> list) { + private void dumpResourceList(StringBuilder builder, String listName, + Collection<IResource> list) { if (list == null) return; builder.append(listName); builder.append(NEW_LINE); - for (IFile file : list) { + for (IResource file : list) { builder.append(file.getFullPath().toOSString()); builder.append(NEW_LINE); } diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/nonswt/decoration/DecoratableResourceHelperTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/nonswt/decoration/DecoratableResourceHelperTest.java index 88afe49170..8691ce0b85 100644 --- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/nonswt/decoration/DecoratableResourceHelperTest.java +++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/nonswt/decoration/DecoratableResourceHelperTest.java @@ -12,9 +12,12 @@ package org.eclipse.egit.ui.test.nonswt.decoration; import static org.junit.Assert.assertTrue; +import java.io.ByteArrayInputStream; import java.io.File; import java.util.Collections; +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; @@ -48,6 +51,14 @@ public class DecoratableResourceHelperTest extends LocalDiskRepositoryTestCase { private static final String TEST_FILE = "TestFile"; + private static final String TEST_FILE2 = "TestFolder2/TestFile2"; + + private static final String TEST_FOLDER = "TestFolder"; + + private static final String TEST_FOLDER2 = "TestFolder2"; + + private static final String SUB_FOLDER = "SubFolder"; + private File gitDir; private Repository repository; @@ -75,6 +86,10 @@ public class DecoratableResourceHelperTest extends LocalDiskRepositoryTestCase { project.create(null); project.open(null); + project.getFolder(TEST_FOLDER2).create(true, true, null); + IFile testFile2 = project.getFile(TEST_FILE2); + testFile2.create(new ByteArrayInputStream("content".getBytes()), true, null); + RepositoryMapping mapping = new RepositoryMapping(project, gitDir); GitProjectData projectData = new GitProjectData(project); @@ -131,6 +146,45 @@ public class DecoratableResourceHelperTest extends LocalDiskRepositoryTestCase { } @Test + public void testDecorationNewFolder() throws Exception { + // Create new folder with sub folder + IFolder folder = project.getFolder(TEST_FOLDER); + folder.create(true, true, null); + IFolder subFolder = folder.getFolder(SUB_FOLDER); + subFolder.create(true, true, null); + + IDecoratableResource[] expectedDRs = new IDecoratableResource[] { + new TestDecoratableResource(project, true, false, false, false, + Staged.NOT_STAGED), + new TestDecoratableResource(folder, false, false, false, false, + Staged.NOT_STAGED), + new TestDecoratableResource(subFolder, false, false, false, false, + Staged.NOT_STAGED) }; + + waitForIndexDiffUpdate(true); + IDecoratableResource[] actualDRs = DecoratableResourceHelper + .createDecoratableResources(new IResource[] { project, folder, subFolder }); + + for (int i = 0; i < expectedDRs.length; i++) + assertTrue(expectedDRs[i].equals(actualDRs[i])); + } + + @Test + public void testDecorationFolderPrefixOfOtherFolder() throws Exception { + project.getFolder(TEST_FOLDER).create(true, true, null); + IFolder testFolder2 = project.getFolder(TEST_FOLDER2); + + IDecoratableResource[] expectedDRs = new IDecoratableResource[] { new TestDecoratableResource( + testFolder2, true, false, false, false, Staged.NOT_STAGED) }; + waitForIndexDiffUpdate(true); + IDecoratableResource[] actualDRs = DecoratableResourceHelper + .createDecoratableResources(new IResource[] { testFolder2 }); + + for (int i = 0; i < expectedDRs.length; i++) + assertTrue(expectedDRs[i].equals(actualDRs[i])); + } + + @Test public void testDecorationNewFile() throws Exception { // Create new file write(new File(project.getLocation().toFile(), TEST_FILE), "Something"); diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceAdapter.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceAdapter.java index ea78d21658..838be51cbf 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceAdapter.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceAdapter.java @@ -121,13 +121,13 @@ class DecoratableResourceAdapter extends DecoratableResource { String repoRelativePath = makeRepoRelative(resource) + "/"; //$NON-NLS-1$ Set<String> ignoredFiles = indexDiffData.getIgnoredNotInIndex(); + Set<String> untrackedFolders = indexDiffData.getUntrackedFolders(); ignored = containsPrefixPath(ignoredFiles, repoRelativePath); - // only file can be not tracked. if (ignored) tracked = false; else - tracked = true; // TODO: implement decoration for untracked folders + tracked = !containsPrefixPath(untrackedFolders, repoRelativePath); // containers are marked as staged whenever file was added, removed or // changed |