/*******************************************************************************
 * 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
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
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;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.treewalk.WorkingTreeIterator;

/**
 * IteratorService is a utility class for providing the right
 * {@link WorkingTreeIterator} iterator for a given folder.
 *
 */
public class IteratorService {

	/**
	 * Creates a {@link WorkingTreeIterator} for a tree walk starting on the
	 * repository work tree folder.
	 *
	 * @param repository
	 * @return <li>a {@link ContainerTreeIterator} if the work tree folder of
	 *         the given repository resides in a project shared with Git <li>an
	 *         {@link AdaptableFileTreeIterator} otherwise <li>{@code null} if the
	 *         workspace is closed.
	 */
	public static WorkingTreeIterator createInitialIterator(
			Repository repository) {
		IWorkspaceRoot root;
		try {
			root = ResourcesPlugin.getWorkspace().getRoot();
		} catch (IllegalStateException e) {
			// workspace is closed
			return null;
		}
		IContainer container = findContainer(root, repository.getWorkTree());
		if (container != null)
			return new ContainerTreeIterator(repository, container);
		return new AdaptableFileTreeIterator(repository, root);
	}

	/**
	 * The method searches a container resource related to the given file. The
	 * container must reside in a project that is shared with Git. Linked folders
	 * are ignored.
	 *
	 * @param root
	 *            the workspace root
	 * @param file
	 * @return a container that matches the description above or null if such a
	 *         container does not exist
	 */
	public static IContainer findContainer(IWorkspaceRoot root, File file) {
		if (!file.isDirectory())
			throw new IllegalArgumentException(
					"file " + file.getAbsolutePath() + " is no directory"); //$NON-NLS-1$//$NON-NLS-2$
		final IContainer[] containers = root.findContainersForLocationURI(file
				.toURI());
		for (IContainer container : containers)
			if (container.isAccessible()
					&& !container.isLinked(IResource.CHECK_ANCESTORS)
					&& isProjectSharedWithGit(container))
				return container;
		return null;
	}

	private static boolean isProjectSharedWithGit(IContainer container) {
		return RepositoryMapping.getMapping(container) != null;
	}

}

@@ -729,16 +729,54 @@
 Plugin;%0A
+import org.eclipse.core.runtime.Path;%0A
 import o
@@ -2561,145 +2561,976 @@
 -2$%0A
-%09%09final IContainer%5B%5D containers = root.findContainersForLocationURI(file%0A%09%09%09%09.toURI());%0A%09%09for (IContainer container : containers)%0A%09%09%09if (
+%0A%09%09// fast path to get desired container%0A%09%09IContainer resource = root.getContainerForLocation(new Path(file%0A%09%09%09%09.getAbsolutePath()));%0A%0A%09%09// Eclipse has no mappings for this path%0A%09%09if (resource == null)%0A%09%09%09return null;%0A%0A%09%09if (isValid(resource))%0A%09%09%09return resource;%0A%0A%09%09// the case where the project is either closed or resource is linked:%0A%09%09// try to find *all* possible candidates (hello overlapping projects!)%0A%09%09// The code below performs exceptionally slow because it tries to find%0A%09%09// all linked resources too%0A%09%09final IContainer%5B%5D containers = root.findContainersForLocationURI(file%0A%09%09%09%09.toURI());%0A%09%09for (IContainer container : containers)%0A%09%09%09if (isValid(container))%0A%09%09%09%09return container;%0A%09%09return null;%0A%09%7D%0A%0A%09/**%0A%09 * sort out closed, linked or not shared directories%0A%09 *%0A%09 * @param container%0A%09 * @return true if the container is shared with git, not a link and%0A%09 *         accessible in Eclipse%0A%09 */%0A%09private static boolean isValid(IContainer container) %7B%0A%09%09return 
 cont
@@ -3550,17 +3550,16 @@
 sible()%0A
-%09
 %09%09%09%09&& !
@@ -3608,17 +3608,16 @@
 RS)%0A%09%09%09%09
-%09
 && isPro
@@ -3648,45 +3648,8 @@
 ner)
-)%0A%09%09%09%09return container;%0A%09%09return null
 ;%0A%09%7D

Fix IteratorService performance on big repositories/workspaces