/*******************************************************************************
* Copyright (C) 2011, Tasktop Technologies Inc.
*
* 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:
* Benjamin Muskalla (benjamin.muskalla@tasktop.com) - initial implementation
*******************************************************************************/
package org.eclipse.egit.ui.internal.operations;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.egit.core.synchronize.GitResourceVariantTreeSubscriber;
import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.internal.CommonUtils;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.team.core.subscribers.Subscriber;
import org.eclipse.team.core.subscribers.SubscriberScopeManager;
import org.eclipse.ui.IContributorResourceAdapter;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.ide.IContributorResourceAdapter2;
import org.eclipse.ui.progress.IProgressService;
/**
* Utilities to handle {@link ResourceMapping}s and {@link GitScopeOperation}
*/
public class GitScopeUtil {
/**
* Returns the set of {@link IResource}s that need to be operated on to have
* a consistent model. Model providers will be asked which resources are
* relevant. The user will be informed which resources are not in the scope
* of the current operation and will be added to the current.
*
* @param part
* the active workbench part
* @param resources
* the resources to operate on
* @return returns the set of resources to operate on
* @throws ExecutionException
* @throws InterruptedException
*/
public static IResource[] getRelatedChanges(IWorkbenchPart part,
IResource[] resources) throws ExecutionException,
InterruptedException {
if (part == null)
throw new IllegalArgumentException();
if (resources == null)
return new IResource[0];
IResource[] resourcesInScope;
// Only builds the logical model if the preference holds true
if (Activator.getDefault().getPreferenceStore()
.getBoolean(UIPreferences.USE_LOGICAL_MODEL)) {
try {
resourcesInScope = findRelatedChanges(part, resources);
} catch (InvocationTargetException e) {
Activator.handleError(
UIText.CommitActionHandler_errorBuildingScope,
e.getCause(), true);
// fallback to initial resource set
resourcesInScope = resources;
}
} else {
resourcesInScope = resources;
}
return resourcesInScope;
}
/**
* Creates a new {@link SubscriberScopeManager} for the given set of
* {@link IResource}s
*
* @param resources
* @return {@link SubscriberScopeManager}
*/
private static SubscriberScopeManager createScopeManager(
final IResource[] resources) {
ResourceMapping[] mappings = GitScopeUtil
.getResourceMappings(resources);
GitSynchronizeDataSet set = new GitSynchronizeDataSet();
Subscriber subscriber = new GitResourceVariantTreeSubscriber(set);
SubscriberScopeManager manager = new SubscriberScopeManager(
UIText.GitScopeOperation_GitScopeManager, mappings, subscriber,
true);
return manager;
}
private static ResourceMapping getResourceMapping(Object o) {
if (o instanceof ResourceMapping)
return (ResourceMapping) o;
if (o instanceof IAdaptable) {
IAdaptable adaptable = (IAdaptable) o;
Object adapted = adaptable.getAdapter(ResourceMapping.class);
if (adapted instanceof ResourceMapping)
return (ResourceMapping) adapted;
adapted = adaptable.getAdapter(IContributorResourceAdapter.class);
if (adapted instanceof IContributorResourceAdapter2) {
IContributorResourceAdapter2 cra = (IContributorResourceAdapter2) adapted;
return cra.getAdaptedResourceMapping(adaptable);
}
} else {
Object adapted = Platform.getAdapterManager().getAdapter(o,
ResourceMapping.class);
if (adapted instanceof ResourceMapping)
return (ResourceMapping) adapted;
}
return null;
}
/**
* Returns all resource mappings for the given resources
*
* @param resources
* @return ResourceMappings
*/
private static ResourceMapping[] getResourceMappings(IResource[] resources) {
List<ResourceMapping> result = new ArrayList<ResourceMapping>();
for (IResource resource : resources)
result.add(getResourceMapping(resource));
return result.toArray(new ResourceMapping[result.size()]);
}
private static IResource[] findRelatedChanges(final IWorkbenchPart part,
final IResource[] selectedResources)
throws InvocationTargetException, InterruptedException {
final List<IResource> relatedChanges = new ArrayList<IResource>();
IRunnableWithProgress runnable = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
try {
monitor.beginTask(
UIText.CommitActionHandler_lookingForChanges, 100);
List<IResource> collectedResources = collectRelatedChanges(
selectedResources, part, monitor);
relatedChanges.addAll(collectedResources);
} finally {
monitor.done();
}
}
};
IProgressService progressService = CommonUtils.getService(part.getSite(), IProgressService.class);
progressService.run(true, true, runnable);
return relatedChanges.toArray(new IResource[relatedChanges.size()]);
}
private static List<IResource> collectRelatedChanges(
IResource[] selectedResources, IWorkbenchPart part,
IProgressMonitor monitor) throws InterruptedException,
InvocationTargetException {
SubscriberScopeManager manager = GitScopeUtil
.createScopeManager(selectedResources);
GitScopeOperation buildScopeOperation = GitScopeOperationFactory
.getFactory().createGitScopeOperation(part, manager);
buildScopeOperation.run(new SubProgressMonitor(monitor, 50));
return buildScopeOperation.getRelevantResources();
}
}