/******************************************************************************* * Copyright (C) 2011, 2015 Tasktop Technologies Inc. and others. * Copyright (C) 2015, Obeo. * * 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.SubMonitor; import org.eclipse.egit.core.AdapterUtils; 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.jgit.annotations.Nullable; 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 * @param monitor * @return {@link SubscriberScopeManager} */ private static SubscriberScopeManager createScopeManager( final IResource[] resources, IProgressMonitor monitor) { ResourceMapping[] mappings = GitScopeUtil .getResourceMappings(resources); GitSynchronizeDataSet set = new GitSynchronizeDataSet(); final GitResourceVariantTreeSubscriber subscriber = new GitResourceVariantTreeSubscriber( set); monitor.setTaskName(UIText.GitModelSynchronize_fetchGitDataJobName); subscriber.init(monitor); SubscriberScopeManager manager = new SubscriberScopeManager( UIText.GitScopeOperation_GitScopeManager, mappings, subscriber, true); return manager; } @Nullable private static ResourceMapping getResourceMapping(Object o) { ResourceMapping mapping = AdapterUtils.adapt(o, ResourceMapping.class); if (mapping != null) { return mapping; } if (o instanceof IAdaptable) { IContributorResourceAdapter adapted = AdapterUtils.adapt(o, IContributorResourceAdapter.class); if (adapted instanceof IContributorResourceAdapter2) { IContributorResourceAdapter2 cra = (IContributorResourceAdapter2) adapted; return cra.getAdaptedResourceMapping((IAdaptable) o); } } 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<>(); 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<>(); IRunnableWithProgress runnable = new IRunnableWithProgress() { @Override 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 { SubMonitor progress = SubMonitor.convert(monitor, 2); SubscriberScopeManager manager = GitScopeUtil.createScopeManager( selectedResources, progress.newChild(1)); GitScopeOperation buildScopeOperation = GitScopeOperationFactory .getFactory().createGitScopeOperation(part, manager); buildScopeOperation.run(progress.newChild(1)); return buildScopeOperation.getRelevantResources(); } }