Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Valenta2006-02-03 19:45:28 +0000
committerMichael Valenta2006-02-03 19:45:28 +0000
commitfbcec19eae86e0404938bdf8f030711aedd45e7c (patch)
tree6b966fa99072de3e955aead841c1e6536d2a4347
parentfab31f63f009dbf7f2ee619b9c13c27924727f5c (diff)
downloadeclipse.platform.team-fbcec19eae86e0404938bdf8f030711aedd45e7c.tar.gz
eclipse.platform.team-fbcec19eae86e0404938bdf8f030711aedd45e7c.tar.xz
eclipse.platform.team-fbcec19eae86e0404938bdf8f030711aedd45e7c.zip
Refactored Merge operation to better support concurrency
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/IResourceMappingScopeManager.java53
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/IResourceMappingScopeParticipantFactory.java51
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/ResourceMappingScopeParticipant.java (renamed from bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/IScopeContextChangeListener.java)27
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/IResourceMappingScopeParticipant.java45
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/ResourceMappingScopeManager.java170
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/SynchronizationContext.java13
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberMergeContext.java18
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberResourceMappingContext.java3
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberScopeManager.java174
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/mapping/ResourceMappingScope.java11
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SubscriberDiffTreeEventHandler.java60
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SubscriberEventHandler.java17
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/OutgoingChangesDialog.java27
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/ReplaceWithRemoteAction.java31
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/ReplaceWithTagAction.java4
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/SyncAction.java2
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/TagLocalAction.java2
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/UpdateSilentAction.java2
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/AbstractModelMergeOperation.java41
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/CVSSubscriberMergeContext.java6
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/MergeSubscriberContext.java10
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelMergeOperation.java37
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelReplaceOperation.java6
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelUpdateOperation.java33
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/WorkspaceModelParticipant.java27
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/WorkspaceSubscriberContext.java10
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RepositoryProviderOperation.java53
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/wizards/CommitWizard.java33
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/CommonViewerAdvisor.java15
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/MergeIncomingChangesAction.java16
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ModelParticipantPageDialog.java123
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ModelSynchronizePage.java6
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ResourceTeamAwareContentProvider.java9
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/SaveablePartDialog.java8
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationContentProvider.java10
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationLabelProvider.java3
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationOperation.java6
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/MergeActionGroup.java3
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelMergeOperation.java446
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelOperation.java132
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelParticipantMergeOperation.java236
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelSynchronizeParticipant.java36
-rw-r--r--tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/mapping/ScopeBuildingTests.java61
-rw-r--r--tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java31
44 files changed, 1230 insertions, 877 deletions
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/IResourceMappingScopeManager.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/IResourceMappingScopeManager.java
index 757da230d..9914e35c3 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/IResourceMappingScopeManager.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/IResourceMappingScopeManager.java
@@ -12,6 +12,8 @@ package org.eclipse.team.core.mapping;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.mapping.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.team.core.mapping.provider.IResourceMappingScopeParticipant;
import org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager;
@@ -49,6 +51,11 @@ public interface IResourceMappingScopeManager {
/**
* Return the projects that apply to this manager.
+ * The projects returned will depend on the type of context used
+ * to generate this scope. If the context is a local context,
+ * all workspace projects are returned. If it is a remote context,
+ * the projects are the same as those returned from
+ * {@link RemoteResourceMappingContext#getProjects()}
* @return the projects that apply to this manager
*/
IProject[] getProjects();
@@ -64,28 +71,44 @@ public interface IResourceMappingScopeManager {
* uses to obtain traversals from resource mappings
*/
ResourceMappingContext getContext();
+
+ /**
+ * Return whether the scope has been initialized.
+ * @return whether the scope has been initialized.
+ */
+ boolean isInitialized();
/**
- * Add a listener to this scope. Listeners will be notified whenever the
- * list of projects that apply to this scope change. Events will also be
- * issued if the resource mapping context of this manager is a
- * {@link RemoteResourceMappingContext} and the remote state of a resource
- * that is a child of the projects.
+ * Build the scope that is used to determine the complete set of resource
+ * mappings, and hence resources, that an operation should be performed on.
* <p>
- * Participants that wich toknow if the contents of the scope chaneg can add
- * a property change listener to the scope using
- * {@link ISynchronizationScope#addPropertyChangeListener(IPropertyChangeListener)}.
+ * This method obtaines a lock on the workspace root to avoid workspace
+ * changes while calculating the scope.
+ * @param monitor a progress monitor
+ * when building the scope
*
- * @param listener
- * a change listener
+ * @throws CoreException
*/
- void addListener(IScopeContextChangeListener listener);
+ void initialize(IProgressMonitor monitor) throws CoreException;
/**
- * Remov the listener from the manager. Removing a listener that
- * is not present has no effect.
- * @param listener the listener
+ * Refresh the scope of this manager for the given mappings.
+ * Changes in the scope will be reported as a property change
+ * event fired from the scope. Clients should call this method
+ * when a change in the workspace or a change issued from this
+ * manager have resulted in a change in the resources that
+ * should be included in the scope.
+ * @param mappings the mappings to be refreshed
+ * @param monitor a progress monitor
+ * @return a set of traversals that cover the given mappings
+ * @throws CoreException
+ */
+ ResourceTraversal[] refresh(ResourceMapping[] mappings, IProgressMonitor monitor) throws CoreException;
+
+ /**
+ * Method to be invoked when the scope of this
+ * manager is no longer needed.
*/
- void removeListener(IScopeContextChangeListener listener);
+ void dispose();
}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/IResourceMappingScopeParticipantFactory.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/IResourceMappingScopeParticipantFactory.java
new file mode 100644
index 000000000..a21b1c60a
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/IResourceMappingScopeParticipantFactory.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.core.mapping;
+
+import org.eclipse.core.resources.mapping.ModelProvider;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IAdapterManager;
+import org.eclipse.team.core.mapping.provider.IResourceMappingScopeParticipant;
+import org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager;
+
+/**
+ * Factory interface for creating a participant for use with an
+ * {@link IResourceMappingScopeManager}. This factory should be
+ * assocated with a {@link ModelProvider} using the {@link IAdaptable}
+ * mechanism.
+ * <p>
+ * This interface may be implemented by clients.
+ *
+ * @see ModelProvider
+ * @see IAdaptable
+ * @see IAdapterManager
+ * @see IResourceMappingScopeManager
+ * @see IResourceMappingScopeParticipant
+ * @see ResourceMappingScopeParticipant
+ * <p>
+ * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
+ * part of a work in progress. There is a guarantee neither that this API will
+ * work nor that it will remain the same. Please do not use this API without
+ * consulting with the Platform/Team team.
+ * </p>
+ * @since 3.2
+ */
+public interface IResourceMappingScopeParticipantFactory {
+
+ /**
+ * Create a participant in the scope management process for the given model provider.
+ * @param provider the model provider
+ * @param manager the scope manager
+ * @return a participant in the scope management process
+ */
+ IResourceMappingScopeParticipant createParticipant(ModelProvider provider, ResourceMappingScopeManager manager);
+
+}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/IScopeContextChangeListener.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/ResourceMappingScopeParticipant.java
index d88930b1b..a276797d1 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/IScopeContextChangeListener.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/ResourceMappingScopeParticipant.java
@@ -10,29 +10,28 @@
*******************************************************************************/
package org.eclipse.team.core.mapping;
-import org.eclipse.core.resources.mapping.RemoteResourceMappingContext;
-
+import org.eclipse.team.core.mapping.provider.IResourceMappingScopeParticipant;
/**
- * A litener that will be notified whenever the list of projects that apply to
- * this scope change. Events will also be issued if the resource mapping context
- * of this manager is a {@link RemoteResourceMappingContext} and the remot state
- * of a resource that is a child of the projects.
- * <p>
- * This interface may be implemented by clients.
+ * Implementation of the {@link IResourceMappingScopeParticipant} class.
+ *
+ * @see IResourceMappingScopeParticipantFactory
* <p>
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as
* part of a work in progress. There is a guarantee neither that this API will
* work nor that it will remain the same. Please do not use this API without
* consulting with the Platform/Team team.
* </p>
- *
- * @see IResourceMappingScopeManager#addListener(IScopeContextChangeListener)
- *
* @since 3.2
*/
-public interface IScopeContextChangeListener {
-
-
+public abstract class ResourceMappingScopeParticipant implements
+ IResourceMappingScopeParticipant {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.mapping.provider.IResourceMappingScopeParticipant#dispose()
+ */
+ public void dispose() {
+ // Do nothing, by default
+ }
}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/IResourceMappingScopeParticipant.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/IResourceMappingScopeParticipant.java
index 296e39a4e..a2597ba6e 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/IResourceMappingScopeParticipant.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/IResourceMappingScopeParticipant.java
@@ -10,19 +10,20 @@
*******************************************************************************/
package org.eclipse.team.core.mapping.provider;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.resources.mapping.RemoteResourceMappingContext;
import org.eclipse.core.resources.mapping.ResourceMapping;
-import org.eclipse.team.core.mapping.IResourceMappingScope;
-import org.eclipse.team.core.mapping.IResourceMappingScopeManager;
+import org.eclipse.team.core.mapping.*;
/**
- * A scope participant is responsible for ensuring that the resources
- * contained within an {@link IResourceMappingScope} that overlap with the
- * participant's model provider stay up-to-date
- * with the model elements (represented as {@link ResourceMapping} instances)
- * contained in the scope.
+ * A scope participant is responsible for ensuring that the resources contained
+ * within an {@link IResourceMappingScope} that overlap with the participant's
+ * model provider stay up-to-date with the model elements (represented as
+ * {@link ResourceMapping} instances) contained in the scope.
*
* <p>
- * This interface is not intended to be implemented by clients.
+ * This interface is not intended to be implemented by clients. CLients should instead subclass
+ * {@link ResourceMappingScopeParticipant}.
* <p>
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as
* part of a work in progress. There is a guarantee neither that this API will
@@ -37,4 +38,32 @@ import org.eclipse.team.core.mapping.IResourceMappingScopeManager;
*/
public interface IResourceMappingScopeParticipant {
+ /**
+ * Callback that the manager makes to participants when the state of
+ * resources that are contained in the resource mapping context of the
+ * manager change. This method will only be invoked when the context of the
+ * manager is a {@link RemoteResourceMappingContext} and the state of one or
+ * more resources changes w.r.t. the context. It is the responsibility of the
+ * participant to react to local changes that affect the resources in the
+ * scope by calling
+ * {@link IResourceMappingScopeManager#refresh(ResourceMapping[], org.eclipse.core.runtime.IProgressMonitor)}.
+ *
+ * @param manager
+ * the scope manager
+ * @param resources
+ * the changed resources
+ * @param projects
+ * projects that were either added or removed
+ * @return the resource mappings that need to be refreshed.
+ */
+ ResourceMapping[] handleContextChange(
+ IResourceMappingScopeManager manager, IResource[] resources, IProject[] projects);
+
+ /**
+ * Callback from the scope manager when the scope is no longer needed.
+ * This si done to give participants a chance to remove a
+ * registered {@link IResourceChangeListener} or any other listeners.
+ */
+ void dispose();
+
}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/ResourceMappingScopeManager.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/ResourceMappingScopeManager.java
index d38651bcb..75b2fb30b 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/ResourceMappingScopeManager.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/ResourceMappingScopeManager.java
@@ -14,9 +14,10 @@ import java.util.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.resources.mapping.*;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.team.core.mapping.*;
+import org.eclipse.team.core.subscribers.SubscriberScopeManager;
import org.eclipse.team.internal.core.Policy;
import org.eclipse.team.internal.core.mapping.*;
@@ -28,20 +29,24 @@ import org.eclipse.team.internal.core.mapping.*;
* Here's a summary of the scope generation algorithm:
* <ol>
* <li>Obtain selected mappings
- * <li>Project mappings onto resources using the appropriate
- * context(s) in order to obtain a set of ResourceTraverals
+ * <li>Project mappings onto resources using the appropriate context(s) in
+ * order to obtain a set of ResourceTraverals
* <li>Determine what model providers are interested in the targeted resources
* <li>From those model providers, obtain the set of affected resource mappings
* <li>If the original set is the same as the new set, we are done.
- * <li>if the set differs from the original selection, rerun the mapping process
- * for any new mappings
- * <ul>
- * <li>Only need to query model providers for mappings for new resources
- * <li>If new mappings are obtained,
- * ask model provider to compress the mappings?
- * <li>keep repeating until no new mappings or resources are added
- * </ul>
- * </ol>
+ * <li>if the set differs from the original selection, rerun the mapping
+ * process for any new mappings
+ * <ul>
+ * <li>Only need to query model providers for mappings for new resources
+ * <li>keep repeating until no new mappings or resources are added
+ * </ul>
+ * </ol>
+ * <p>
+ * This implementation does not involve participants in the scope management
+ * process. It is up to subclasses that wish to support a longer life cycle for
+ * scopes to provide for participation. For example, the
+ * {@link SubscriberScopeManager} class includes participates in the scope
+ * management process.
* <p>
* This class is can be subclasses by clients.
*
@@ -53,6 +58,7 @@ import org.eclipse.team.internal.core.mapping.*;
* </p>
*
* @see org.eclipse.core.resources.mapping.ResourceMapping
+ * @see SubscriberScopeManager
*
* @since 3.2
*/
@@ -62,6 +68,7 @@ public class ResourceMappingScopeManager implements IResourceMappingScopeManager
private final ResourceMappingContext context;
private final boolean consultModels;
private IResourceMappingScope scope;
+ private boolean initialized;
/**
* Convenience method for obtaining the set of resource
@@ -104,48 +111,73 @@ public class ResourceMappingScopeManager implements IResourceMappingScopeManager
* If <code>consultModels</code> is <code>true</code> then
* the moel providers will be queried in order to determine if
* additional mappings should be included in the scope
+ * @param inputMappings the input mappings
* @param resourceMappingContext a resource mapping context
* @param consultModels whether modle providers should be consulted
*/
- public ResourceMappingScopeManager(ResourceMappingContext resourceMappingContext, boolean consultModels) {
+ public ResourceMappingScopeManager(ResourceMapping[] inputMappings, ResourceMappingContext resourceMappingContext, boolean consultModels) {
this.context = resourceMappingContext;
this.consultModels = consultModels;
+ scope = createScope(inputMappings);
}
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.mapping.IResourceMappingScopeManager#isInitialized()
+ */
+ public boolean isInitialized() {
+ return initialized;
+ }
+
/**
- * Build the scope that is used to determine the complete set of resource
- * mappings, and hence resources, that an operation should be performed on.
- * If <code>useLocalContext</code> is <code>true</code> then the
- * {@link ResourceMappingContext#LOCAL_CONTEXT} is used to prepare the scope instead
- * of the context associatd with the manager. Clients may wish to do this
- * when long running operations should not occur.
- *
- * @param selectedMappings the selected set of resource mappings
- * @param useLocalContext indicates that the localcontext should be used
- * when building the scope
- * @param monitor a progress monitor
- * @return a scope that defines the complete set of resources to be operated
- * on
- * @throws CoreException
+ * Return the scheduling rule that is used when initializing
+ * and refreshing the scope. By default, it is the
+ * workspace root.
+ * @return the scheduling rule that is used when initializing
+ * and refreshing the scope
+ */
+ public ISchedulingRule getSchedulingRule() {
+ return ResourcesPlugin.getWorkspace().getRoot();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.mapping.IResourceMappingScopeManager#initialize(org.eclipse.core.runtime.IProgressMonitor)
*/
- public IResourceMappingScope prepareScope(
- ResourceMapping[] selectedMappings,
- boolean useLocalContext,
+ public void initialize(
IProgressMonitor monitor) throws CoreException {
+ ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ internalPrepareContext(monitor);
+ }
+ }, getSchedulingRule(), IResource.NONE, monitor);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.mapping.IResourceMappingScopeManager#refresh(org.eclipse.core.resources.mapping.ResourceMapping[], org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public ResourceTraversal[] refresh(final ResourceMapping[] mappings, IProgressMonitor monitor) throws CoreException {
+ // We need to lock the workspace when building the scope
+ final ResourceTraversal[][] traversals = new ResourceTraversal[][] { new ResourceTraversal[0] };
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ workspace.run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ traversals[0] = internalRefreshScope(mappings, monitor);
+ }
+ }, getSchedulingRule(), IResource.NONE, monitor);
+ return traversals[0];
+ }
+
+ private void internalPrepareContext(IProgressMonitor monitor) throws CoreException {
+ if (initialized)
+ return;
monitor.beginTask(null, IProgressMonitor.UNKNOWN);
-
- // Create the scope
- scope = createScope(selectedMappings);
-
// Accumulate the initial set of mappings we need traversals for
- ResourceMapping[] targetMappings = selectedMappings;
+ ResourceMapping[] targetMappings = scope.getInputMappings();
ResourceTraversal[] newTraversals;
boolean firstTime = true;
boolean hasAdditionalResources = false;
int count = 0;
do {
- newTraversals = addMappingsToScope(targetMappings, useLocalContext,
+ newTraversals = addMappingsToScope(targetMappings,
Policy.subMonitorFor(monitor, IProgressMonitor.UNKNOWN));
if (newTraversals.length > 0 && consultModels) {
ResourceTraversal[] adjusted = adjustInputTraversals(newTraversals);
@@ -161,26 +193,8 @@ public class ResourceMappingScopeManager implements IResourceMappingScopeManager
} while (consultModels & newTraversals.length != 0 && count++ < MAX_ITERATION);
setHasAdditionalMappings(scope, consultModels && internalHasAdditionalMappings());
setHasAdditionalResources(consultModels && hasAdditionalResources);
- return scope;
- }
-
- /**
- * Refresh the scope of this manager for the given mappings.
- * @param mappings the mappings to be refreshed
- * @param monitor a progress monitor
- * @return a set of traversals that cover the given mappings
- * @throws CoreException
- */
- public ResourceTraversal[] refreshScope(final ResourceMapping[] mappings, IProgressMonitor monitor) throws CoreException {
- // We need to lock the workspace when building the scope
- final ResourceTraversal[][] traversals = new ResourceTraversal[][] { new ResourceTraversal[0] };
- IWorkspace workspace = ResourcesPlugin.getWorkspace();
- workspace.run(new IWorkspaceRunnable() {
- public void run(IProgressMonitor monitor) throws CoreException {
- traversals[0] = internalRefreshScope(mappings, monitor);
- }
- }, workspace.getRoot(), IResource.NONE, monitor);
- return traversals[0];
+ monitor.done();
+ initialized = true;
}
private ResourceTraversal[] internalRefreshScope(ResourceMapping[] mappings, IProgressMonitor monitor) throws CoreException {
@@ -254,7 +268,7 @@ public class ResourceMappingScopeManager implements IResourceMappingScopeManager
ResourceTraversal[] adjusted = adjustInputTraversals(newTraversals);
targetMappings = getMappingsFromProviders(adjusted,
context, Policy.subMonitorFor(monitor, IProgressMonitor.UNKNOWN));
- newTraversals = addMappingsToScope(targetMappings, false,
+ newTraversals = addMappingsToScope(targetMappings,
Policy.subMonitorFor(monitor, IProgressMonitor.UNKNOWN));
} while (newTraversals.length != 0 && count++ < MAX_ITERATION);
if (!scope.hasAdditionalMappings()) {
@@ -315,7 +329,7 @@ public class ResourceMappingScopeManager implements IResourceMappingScopeManager
*/
protected final IResourceMappingScope createScope(
ResourceMapping[] inputMappings) {
- return new ResourceMappingScope(this, inputMappings);
+ return new ResourceMappingScope(inputMappings);
}
/**
@@ -338,11 +352,9 @@ public class ResourceMappingScopeManager implements IResourceMappingScopeManager
private ResourceTraversal[] addMappingsToScope(
ResourceMapping[] targetMappings,
- boolean useLocalContext, IProgressMonitor monitor) throws CoreException {
+ IProgressMonitor monitor) throws CoreException {
CompoundResourceTraversal result = new CompoundResourceTraversal();
ResourceMappingContext context = this.context;
- if (useLocalContext)
- context = ResourceMappingContext.LOCAL_CONTEXT;
for (int i = 0; i < targetMappings.length; i++) {
ResourceMapping mapping = targetMappings[i];
if (scope.getTraversals(mapping) == null) {
@@ -389,21 +401,8 @@ public class ResourceMappingScopeManager implements IResourceMappingScopeManager
return true;
}
- /**
- * Return whether the model providers should be consulted in
- * order to see if the scope needs to be expanded.
- * @return whether the model providers should be consulted
- */
- public boolean isConsultModels() {
- return consultModels;
- }
-
- /**
- * Return the resource mapping context used during the scope
- * generation process in order to determine what resources
- * are to be included in the scope.
- * @return the resource mapping context used during the scope
- * generation process
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.mapping.IResourceMappingScopeManager#getContext()
*/
public ResourceMappingContext getContext() {
return context;
@@ -415,16 +414,6 @@ public class ResourceMappingScopeManager implements IResourceMappingScopeManager
public IResourceMappingScope getScope() {
return scope;
}
-
- public void addListener(IScopeContextChangeListener listener) {
- // TODO Auto-generated method stub
-
- }
-
- public void removeListener(IScopeContextChangeListener listener) {
- // TODO Auto-generated method stub
-
- }
/* (non-Javadoc)
* @see org.eclipse.team.core.mapping.IResourceMappingScopeManager#getProjects()
@@ -436,4 +425,11 @@ public class ResourceMappingScopeManager implements IResourceMappingScopeManager
}
return ResourcesPlugin.getWorkspace().getRoot().getProjects();
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.mapping.IResourceMappingScopeManager#dispose()
+ */
+ public void dispose() {
+ // Do nothing, by default
+ }
}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/SynchronizationContext.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/SynchronizationContext.java
index 5356572e2..ae500a434 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/SynchronizationContext.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/mapping/provider/SynchronizationContext.java
@@ -18,7 +18,6 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.team.core.mapping.*;
import org.eclipse.team.internal.core.Policy;
import org.eclipse.team.internal.core.mapping.DiffCache;
-import org.eclipse.team.internal.core.mapping.ResourceMappingScope;
/**
* Abstract implementation of the {@link ISynchronizationContext} interface.
@@ -98,24 +97,16 @@ public abstract class SynchronizationContext implements ISynchronizationContext
*/
public void refresh(ResourceMapping[] mappings, IProgressMonitor monitor) throws CoreException {
monitor.beginTask(null, 100);
- ResourceMappingScopeManager manager = getScopeManager();
+ ResourceMappingScopeManager manager = null; //getScopeManager();
if (manager == null) {
// The scope manager is missing so just refresh everything
refresh(scope.getTraversals(), IResource.NONE, Policy.subMonitorFor(monitor, 50));
} else {
- ResourceTraversal[] traversals = manager.refreshScope(mappings, Policy.subMonitorFor(monitor, 50));
+ ResourceTraversal[] traversals = manager.refresh(mappings, Policy.subMonitorFor(monitor, 50));
if (traversals.length > 0)
refresh(traversals, IResource.NONE, Policy.subMonitorFor(monitor, 50));
}
monitor.done();
}
- private ResourceMappingScopeManager getScopeManager() {
- if (scope instanceof ResourceMappingScope) {
- ResourceMappingScope rms = (ResourceMappingScope) scope;
- rms.getManager();
- }
- return null;
- }
-
}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberMergeContext.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberMergeContext.java
index 4397be33b..77c363f30 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberMergeContext.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberMergeContext.java
@@ -14,7 +14,7 @@ import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.mapping.ResourceTraversal;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.team.core.mapping.IResourceMappingScope;
+import org.eclipse.team.core.mapping.IResourceMappingScopeManager;
import org.eclipse.team.core.mapping.provider.MergeContext;
import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
import org.eclipse.team.core.synchronize.SyncInfo;
@@ -39,10 +39,12 @@ public abstract class SubscriberMergeContext extends MergeContext {
private Subscriber subscriber;
private SubscriberDiffTreeEventHandler handler;
+ private final IResourceMappingScopeManager manager;
- protected SubscriberMergeContext(Subscriber subscriber, IResourceMappingScope scope) {
- super(scope, getType(subscriber), new ResourceDiffTree());
+ protected SubscriberMergeContext(Subscriber subscriber, IResourceMappingScopeManager manager) {
+ super(manager.getScope(), getType(subscriber), new ResourceDiffTree());
this.subscriber = subscriber;
+ this.manager = manager;
}
private static int getType(Subscriber subscriber) {
@@ -53,17 +55,12 @@ public abstract class SubscriberMergeContext extends MergeContext {
/**
* Initialize the diff tree of this context. This method must
* be called before the context is given to clients.
- * @param monitor a progress monitor
- * @param refresh indicate whether the subscriber should be refreshed
* @throws CoreException
*/
- protected void initialize(IProgressMonitor monitor, boolean refresh) throws CoreException {
- handler = new SubscriberDiffTreeEventHandler(subscriber, getScope(), (ResourceDiffTree)getDiffTree());
+ protected void initialize() {
+ handler = new SubscriberDiffTreeEventHandler(subscriber, manager, (ResourceDiffTree)getDiffTree());
handler.setJobFamily(this);
handler.start();
- if (refresh) {
- refresh(getScope().getTraversals(), IResource.NONE, monitor);
- }
}
/* (non-Javadoc)
@@ -72,7 +69,6 @@ public abstract class SubscriberMergeContext extends MergeContext {
public void refresh(ResourceTraversal[] traversals, int flags,
IProgressMonitor monitor) throws CoreException {
subscriber.refresh(traversals, monitor);
- handler.waitUntilIdle(monitor);
}
/* (non-Javadoc)
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberResourceMappingContext.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberResourceMappingContext.java
index 7116811ff..2a11803a6 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberResourceMappingContext.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberResourceMappingContext.java
@@ -10,8 +10,7 @@
*******************************************************************************/
package org.eclipse.team.core.subscribers;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.resources.mapping.RemoteResourceMappingContext;
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberScopeManager.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberScopeManager.java
new file mode 100644
index 000000000..3aa46e75d
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/SubscriberScopeManager.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.core.subscribers;
+
+import java.util.*;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.resources.mapping.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.team.core.mapping.IResourceMappingScopeManager;
+import org.eclipse.team.core.mapping.IResourceMappingScopeParticipantFactory;
+import org.eclipse.team.core.mapping.provider.IResourceMappingScopeParticipant;
+import org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager;
+
+/**
+ * A {@link IResourceMappingScopeManager} that uses a {@link Subscriber} to provide
+ * a {@link RemoteResourceMappingContext} and to notify participants when the
+ * remote state of resources change.
+ * <p>
+ * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
+ * part of a work in progress. There is a guarantee neither that this API will
+ * work nor that it will remain the same. Please do not use this API without
+ * consulting with the Platform/Team team.
+ * </p>
+ * @since 3.2
+ */
+public class SubscriberScopeManager extends ResourceMappingScopeManager implements ISubscriberChangeListener {
+
+ private final Subscriber subscriber;
+ private Map participants = new HashMap();
+
+ /**
+ * Create a manager for the given subscriber and input.
+ * @param inputMappings the input mappings
+ * @param subscriber the subscriber
+ * @param consultModels whether models should be consulted when calculating the scope
+ */
+ public SubscriberScopeManager(ResourceMapping[] inputMappings, Subscriber subscriber, boolean consultModels) {
+ this(inputMappings, subscriber, SubscriberResourceMappingContext.createContext(subscriber), consultModels);
+ }
+
+ /**
+ * Create a manager for the given subscriber and input.
+ * @param inputMappings the input mappings
+ * @param subscriber the subscriber
+ * @param context a remote resource mapping conext for the subscriber
+ * @param consultModels whether models should be consulted when calculating the scope
+ */
+ public SubscriberScopeManager(ResourceMapping[] inputMappings, Subscriber subscriber, RemoteResourceMappingContext context, boolean consultModels) {
+ super(inputMappings, context, consultModels);
+ this.subscriber = subscriber;
+ }
+
+ /**
+ * Return the subscriber for this manager.
+ * @return the subscriber for this manager
+ */
+ protected Subscriber getSubscriber() {
+ return subscriber;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.mapping.IResourceMappingScopeManager#dispose()
+ */
+ public void dispose() {
+ for (Iterator iter = participants.values().iterator(); iter.hasNext();) {
+ IResourceMappingScopeParticipant p = (IResourceMappingScopeParticipant) iter.next();
+ p.dispose();
+ }
+ super.dispose();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager#initialize(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void initialize(IProgressMonitor monitor) throws CoreException {
+ ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ SubscriberScopeManager.super.initialize(monitor);
+ hookupParticipants();
+ getSubscriber().addListener(SubscriberScopeManager.this);
+ }
+ }, getSchedulingRule(), IResource.NONE, monitor);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager#refresh(org.eclipse.core.resources.mapping.ResourceMapping[], org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public ResourceTraversal[] refresh(final ResourceMapping[] mappings, IProgressMonitor monitor) throws CoreException {
+ final List result = new ArrayList(1);
+ ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ result.add(SubscriberScopeManager.super.refresh(mappings, monitor));
+ hookupParticipants();
+ }
+ }, getSchedulingRule(), IResource.NONE, monitor);
+ if (result.isEmpty())
+ return new ResourceTraversal[0];
+ return (ResourceTraversal[])result.get(0);
+ }
+
+ /*
+ * Hookup the participants for the participating models.
+ * This is done to ensure that future local and remote changes to
+ * resources will update the resources contained in the scope
+ * appropriately
+ */
+ /* private */ void hookupParticipants() {
+ ModelProvider[] providers = getScope().getModelProviders();
+ for (int i = 0; i < providers.length; i++) {
+ ModelProvider provider = providers[i];
+ if (!participants.containsKey(provider)) {
+ IResourceMappingScopeParticipant p = createParticipant(provider);
+ if (p != null) {
+ participants.put(provider, p);
+ }
+ }
+ }
+ }
+
+ /*
+ * Obtain a participant through the factory which is obtained using IAdaptable
+ */
+ private IResourceMappingScopeParticipant createParticipant(ModelProvider provider) {
+ Object factoryObject = provider.getAdapter(IResourceMappingScopeParticipantFactory.class);
+ if (factoryObject instanceof IResourceMappingScopeParticipantFactory) {
+ IResourceMappingScopeParticipantFactory factory = (IResourceMappingScopeParticipantFactory) factoryObject;
+ return factory.createParticipant(provider, this);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.subscribers.ISubscriberChangeListener#subscriberResourceChanged(org.eclipse.team.core.subscribers.ISubscriberChangeEvent[])
+ */
+ public void subscriberResourceChanged(ISubscriberChangeEvent[] deltas) {
+ List changedResources = new ArrayList();
+ List changedProjects = new ArrayList();
+ for (int i = 0; i < deltas.length; i++) {
+ ISubscriberChangeEvent event = deltas[i];
+ if ((event.getFlags() & (ISubscriberChangeEvent.ROOT_ADDED | ISubscriberChangeEvent.ROOT_REMOVED)) != 0) {
+ changedProjects.add(event.getResource().getProject());
+ }
+ if ((event.getFlags() & ISubscriberChangeEvent.SYNC_CHANGED) != 0) {
+ changedResources.add(event.getResource());
+ }
+ }
+ fireChange((IResource[]) changedResources.toArray(new IResource[changedResources.size()]), (IProject[]) changedProjects.toArray(new IProject[changedProjects.size()]));
+ }
+
+ private void fireChange(final IResource[] resources, final IProject[] projects) {
+ IResourceMappingScopeParticipant[] handlers = (IResourceMappingScopeParticipant[]) participants.values().toArray(new IResourceMappingScopeParticipant[participants.size()]);
+ for (int i = 0; i < handlers.length; i++) {
+ final IResourceMappingScopeParticipant participant = handlers[i];
+ Platform.run(new ISafeRunnable() {
+ public void run() throws Exception {
+ participant.handleContextChange(SubscriberScopeManager.this, resources, projects);
+ }
+ public void handleException(Throwable exception) {
+ // Handled by platform
+ }
+ });
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/mapping/ResourceMappingScope.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/mapping/ResourceMappingScope.java
index c20f21d85..7d4e46ee2 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/mapping/ResourceMappingScope.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/mapping/ResourceMappingScope.java
@@ -17,7 +17,6 @@ import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.resources.mapping.ResourceTraversal;
import org.eclipse.team.core.mapping.IResourceMappingScope;
import org.eclipse.team.core.mapping.PropertyChangeEvent;
-import org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager;
/**
* Concrete implementation of the {@link IResourceMappingScope}
@@ -42,7 +41,6 @@ public class ResourceMappingScope extends AbstractResourceMappingScope {
private final Map mappingsToTraversals = new HashMap();
private boolean hasAdditionalMappings;
private boolean hasAdditionalResources;
- private final ResourceMappingScopeManager manager;
private final CompoundResourceTraversal compoundTraversal = new CompoundResourceTraversal();
public static ResourceTraversal[] combineTraversals(ResourceTraversal[] allTraversals) {
@@ -76,8 +74,7 @@ public class ResourceMappingScope extends AbstractResourceMappingScope {
return (ResourceTraversal[]) result.toArray(new ResourceTraversal[result.size()]);
}
- public ResourceMappingScope(ResourceMappingScopeManager manager, ResourceMapping[] selectedMappings) {
- this.manager = manager;
+ public ResourceMappingScope(ResourceMapping[] selectedMappings) {
inputMappings = selectedMappings;
}
@@ -105,6 +102,8 @@ public class ResourceMappingScope extends AbstractResourceMappingScope {
* @see org.eclipse.team.ui.mapping.IResourceMappingOperationScope#getMappings()
*/
public ResourceMapping[] getMappings() {
+ if (mappingsToTraversals.isEmpty())
+ return inputMappings;
return (ResourceMapping[]) mappingsToTraversals.keySet().toArray(new ResourceMapping[mappingsToTraversals.size()]);
}
@@ -153,10 +152,6 @@ public class ResourceMappingScope extends AbstractResourceMappingScope {
public boolean hasAdditonalResources() {
return hasAdditionalResources;
}
-
- public ResourceMappingScopeManager getManager() {
- return manager;
- }
public void fireTraversalsChangedEvent(ResourceTraversal[] oldTraversals) {
firePropertyChangedEvent(new PropertyChangeEvent(this, IResourceMappingScope.TRAVERSALS, oldTraversals, getTraversals()));
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SubscriberDiffTreeEventHandler.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SubscriberDiffTreeEventHandler.java
index 983926c30..a8449e11c 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SubscriberDiffTreeEventHandler.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SubscriberDiffTreeEventHandler.java
@@ -11,18 +11,16 @@
package org.eclipse.team.internal.core.subscribers;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.mapping.ResourceTraversal;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.team.core.ITeamStatus;
import org.eclipse.team.core.diff.IDiff;
import org.eclipse.team.core.diff.IDiffVisitor;
-import org.eclipse.team.core.mapping.IResourceDiffTree;
-import org.eclipse.team.core.mapping.ISynchronizationScope;
-import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
+import org.eclipse.team.core.mapping.*;
+import org.eclipse.team.core.mapping.provider.*;
import org.eclipse.team.core.subscribers.Subscriber;
-import org.eclipse.team.internal.core.Policy;
/**
* A subscriber event handler whose output is a diff tree
@@ -31,6 +29,7 @@ public class SubscriberDiffTreeEventHandler extends SubscriberEventHandler {
private ResourceDiffTree tree;
private SubscriberDiffCollector collector;
+ private IResourceMappingScopeManager manager;
private Object family;
/*
@@ -85,12 +84,37 @@ public class SubscriberDiffTreeEventHandler extends SubscriberEventHandler {
* @param scope the scope of the handler
* @param tree the tree to be populated by this handler
*/
- public SubscriberDiffTreeEventHandler(Subscriber subscriber, ISynchronizationScope scope, ResourceDiffTree tree) {
- super(subscriber, scope);
+ public SubscriberDiffTreeEventHandler(Subscriber subscriber, IResourceMappingScopeManager manager, ResourceDiffTree tree) {
+ super(subscriber, manager.getScope());
+ this.manager = manager;
this.tree = tree;
this.collector = new SubscriberDiffCollector(subscriber);
}
+ protected void reset(ResourceTraversal[] traversals, int type) {
+ if (type == SubscriberEvent.INITIALIZE && traversals.length == 0) {
+ // This means the scope has not been initialized
+ queueEvent(new RunnableEvent(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ prepareScope(monitor);
+ }
+ }, true), true);
+ } else {
+ super.reset(traversals, type);
+ }
+ }
+
+ protected void prepareScope(IProgressMonitor monitor) {
+ try {
+ manager.initialize(monitor);
+ } catch (CoreException e) {
+ handleException(e);
+ }
+ ResourceTraversal[] traversals = manager.getScope().getTraversals();
+ if (traversals.length > 0)
+ reset(traversals, SubscriberEvent.INITIALIZE);
+ }
+
/* (non-Javadoc)
* @see org.eclipse.team.internal.core.subscribers.SubscriberEventHandler#handleChange(org.eclipse.core.resources.IResource)
*/
@@ -172,20 +196,6 @@ public class SubscriberDiffTreeEventHandler extends SubscriberEventHandler {
return tree;
}
- public void waitUntilIdle(IProgressMonitor monitor) {
- monitor.worked(1);
- // wait for the event handler to process changes.
- while(getEventHandlerJob().getState() != Job.NONE) {
- monitor.worked(1);
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- }
- Policy.checkCanceled(monitor);
- }
- monitor.worked(1);
- }
-
/* (non-Javadoc)
* @see org.eclipse.team.internal.core.subscribers.SubscriberEventHandler#getSubscriber()
*/
@@ -201,9 +211,17 @@ public class SubscriberDiffTreeEventHandler extends SubscriberEventHandler {
super.shutdown();
}
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.core.BackgroundEventHandler#getJobFamiliy()
+ */
protected Object getJobFamiliy() {
return family;
}
+
+ /**
+ * Set the family of this handler to the given object
+ * @param family the family of the handler's job
+ */
public void setJobFamily(Object family) {
this.family = family;
}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SubscriberEventHandler.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SubscriberEventHandler.java
index 4d6f73333..dc69b0e0b 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SubscriberEventHandler.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SubscriberEventHandler.java
@@ -130,7 +130,7 @@ public abstract class SubscriberEventHandler extends BackgroundEventHandler {
* @param newTraversals the new traversals
*/
protected synchronized void reset(ResourceTraversal[] oldTraversals, ResourceTraversal[] newTraversals) {
- reset(scope.getRoots(), SubscriberEvent.CHANGE);
+ reset(newTraversals, SubscriberEvent.CHANGE);
}
/**
@@ -141,8 +141,8 @@ public abstract class SubscriberEventHandler extends BackgroundEventHandler {
// Set the started flag to enable event queuing.
// We are guaranteed to be the first since this method is synchronized.
started = true;
- IResource[] resources = scope.getRoots();
- reset(resources, SubscriberEvent.INITIALIZE);
+ ResourceTraversal[] traversals = scope.getTraversals();
+ reset(traversals, SubscriberEvent.INITIALIZE);
initializing = false;
}
@@ -302,10 +302,13 @@ public abstract class SubscriberEventHandler extends BackgroundEventHandler {
* @param type can be Event.CHANGE to recalculate all states or Event.INITIALIZE to perform the
* optimized recalculation if supported by the subscriber.
*/
- protected void reset(IResource[] roots, int type) {
- IResource[] resources = roots;
- for (int i = 0; i < resources.length; i++) {
- queueEvent(new SubscriberEvent(resources[i], type, IResource.DEPTH_INFINITE), false);
+ protected void reset(ResourceTraversal[] traversals, int type) {
+ for (int i = 0; i < traversals.length; i++) {
+ ResourceTraversal traversal = traversals[i];
+ IResource[] resources = traversal.getResources();
+ for (int j = 0; j < resources.length; j++) {
+ queueEvent(new SubscriberEvent(resources[j], type, traversal.getDepth()), false);
+ }
}
}
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/OutgoingChangesDialog.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/OutgoingChangesDialog.java
index 4e34262e6..cc77d73ae 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/OutgoingChangesDialog.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/OutgoingChangesDialog.java
@@ -12,17 +12,15 @@ package org.eclipse.team.internal.ccvs.ui.actions;
import java.lang.reflect.InvocationTargetException;
-import org.eclipse.core.runtime.*;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
-import org.eclipse.team.core.mapping.IResourceMappingScope;
+import org.eclipse.team.core.mapping.IResourceMappingScopeManager;
import org.eclipse.team.core.mapping.ISynchronizationContext;
import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
import org.eclipse.team.internal.ccvs.ui.mappings.WorkspaceSubscriberContext;
@@ -31,20 +29,19 @@ import org.eclipse.team.internal.ui.dialogs.DetailsDialog;
import org.eclipse.team.ui.operations.ModelSynchronizeParticipant;
import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration;
import org.eclipse.team.ui.synchronize.ParticipantPagePane;
-import org.eclipse.ui.PlatformUI;
public class OutgoingChangesDialog extends DetailsDialog {
private final String message;
private ParticipantPagePane pane;
- private final IResourceMappingScope scope;
private ModelSynchronizeParticipant participant;
private final String title;
private final String detailsMessage;
+ private final IResourceMappingScopeManager manager;
- public OutgoingChangesDialog(Shell parentShell, IResourceMappingScope scope, String title, String message, String detailsMessage) {
+ public OutgoingChangesDialog(Shell parentShell, IResourceMappingScopeManager manager, String title, String message, String detailsMessage) {
super(parentShell, title);
- this.scope = scope;
+ this.manager = manager;
this.title = title;
this.message = message;
this.detailsMessage = detailsMessage;
@@ -109,23 +106,15 @@ public class OutgoingChangesDialog extends DetailsDialog {
}
private ModelSynchronizeParticipant createParticipant() throws InvocationTargetException, InterruptedException {
- ISynchronizationContext context = createSynchronizationContext(scope);
- ModelSynchronizeParticipant participant = ModelSynchronizeParticipant.createParticipant(context, title);
+ ISynchronizationContext context = createSynchronizationContext(manager);
+ ModelSynchronizeParticipant participant = ModelSynchronizeParticipant.createParticipant(manager, context, title);
participant.setMergingEnabled(false);
return participant;
}
- private ISynchronizationContext createSynchronizationContext(final IResourceMappingScope scope) throws InvocationTargetException, InterruptedException {
+ private ISynchronizationContext createSynchronizationContext(final IResourceMappingScopeManager manager) throws InvocationTargetException, InterruptedException {
final ISynchronizationContext[] context = new ISynchronizationContext[] { null };
- PlatformUI.getWorkbench().getProgressService().run(true, true, new IRunnableWithProgress() {
- public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
- try {
- context[0] = WorkspaceSubscriberContext.createContext(scope, false, ISynchronizationContext.THREE_WAY, monitor);
- } catch (CoreException e) {
- throw new InvocationTargetException(e);
- }
- }
- });
+ context[0] = WorkspaceSubscriberContext.createContext(manager, ISynchronizationContext.THREE_WAY);
return context[0];
}
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/ReplaceWithRemoteAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/ReplaceWithRemoteAction.java
index 3c953f0d7..9a88deec2 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/ReplaceWithRemoteAction.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/ReplaceWithRemoteAction.java
@@ -13,18 +13,37 @@ package org.eclipse.team.internal.ccvs.ui.actions;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.team.internal.ccvs.core.*;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.team.internal.ccvs.core.CVSException;
+import org.eclipse.team.internal.ccvs.core.ICVSResource;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
import org.eclipse.team.internal.ccvs.ui.CVSUIMessages;
-import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
-import org.eclipse.team.internal.ccvs.ui.mappings.ModelReplaceOperation;
+import org.eclipse.team.internal.ccvs.ui.operations.ReplaceOperation;
public class ReplaceWithRemoteAction extends WorkspaceTraversalAction {
public void execute(IAction action) throws InvocationTargetException, InterruptedException {
- IPreferenceStore store = CVSUIPlugin.getPlugin().getPreferenceStore();
- new ModelReplaceOperation(getTargetPart(), getSelectedResourceMappings(CVSProviderPlugin.getTypeId()), getResourceMappingContext()).run();
+
+ final ReplaceOperation replaceOperation = new ReplaceOperation(getTargetPart(), getCVSResourceMappings(), null);
+ if (hasOutgoingChanges(replaceOperation)) {
+ final boolean[] keepGoing = new boolean[] { true };
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ OutgoingChangesDialog dialog = new OutgoingChangesDialog(getShell(), replaceOperation.getScopeManager(),
+ CVSUIMessages.ReplaceWithTagAction_2,
+ CVSUIMessages.ReplaceWithTagAction_0,
+ CVSUIMessages.ReplaceWithTagAction_1);
+ int result = dialog.open();
+ keepGoing[0] = result == Window.OK;
+ }
+ });
+ if (!keepGoing[0])
+ return;
+ }
+ replaceOperation.run();
+ // TODO: Involve models in the replace
+ //new ModelReplaceOperation(getTargetPart(), getSelectedResourceMappings(CVSProviderPlugin.getTypeId()), getResourceMappingContext()).run();
}
/**
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/ReplaceWithTagAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/ReplaceWithTagAction.java
index 24682b1b1..db9933ca2 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/ReplaceWithTagAction.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/ReplaceWithTagAction.java
@@ -42,7 +42,7 @@ public class ReplaceWithTagAction extends WorkspaceTraversalAction {
final boolean[] keepGoing = new boolean[] { true };
Display.getDefault().syncExec(new Runnable() {
public void run() {
- OutgoingChangesDialog dialog = new OutgoingChangesDialog(getShell(), replaceOperation.getScope(),
+ OutgoingChangesDialog dialog = new OutgoingChangesDialog(getShell(), replaceOperation.getScopeManager(),
CVSUIMessages.ReplaceWithTagAction_2,
CVSUIMessages.ReplaceWithTagAction_0,
CVSUIMessages.ReplaceWithTagAction_1);
@@ -101,7 +101,7 @@ public class ReplaceWithTagAction extends WorkspaceTraversalAction {
final boolean[] keepGoing = new boolean[] { true };
Display.getDefault().syncExec(new Runnable() {
public void run() {
- OutgoingChangesDialog dialog = new OutgoingChangesDialog(getShell(), tagOperation.getScope(),
+ OutgoingChangesDialog dialog = new OutgoingChangesDialog(getShell(), tagOperation.getScopeManager(),
CVSUIMessages.TagLocalAction_2,
CVSUIMessages.TagLocalAction_0,
CVSUIMessages.TagLocalAction_1);
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/SyncAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/SyncAction.java
index 1596ceeee..0da85305a 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/SyncAction.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/SyncAction.java
@@ -47,7 +47,7 @@ public class SyncAction extends WorkspaceTraversalAction {
showSingleFileComparison(getShell(), CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber(), resources[0], getTargetPage());
}else if (isShowModelSync()) {
try {
- new ModelUpdateOperation(getTargetPart(), getCVSResourceMappings(), getResourceMappingContext()) {
+ new ModelUpdateOperation(getTargetPart(), getCVSResourceMappings()) {
protected boolean isAttemptHeadlessMerge() {
return false;
}
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/TagLocalAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/TagLocalAction.java
index bd5746115..c38ca2d8b 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/TagLocalAction.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/TagLocalAction.java
@@ -35,7 +35,7 @@ public class TagLocalAction extends TagAction {
final boolean[] keepGoing = new boolean[] { true };
Display.getDefault().syncExec(new Runnable() {
public void run() {
- OutgoingChangesDialog dialog = new OutgoingChangesDialog(getShell(), tagOperation.getScope(),
+ OutgoingChangesDialog dialog = new OutgoingChangesDialog(getShell(), tagOperation.getScopeManager(),
CVSUIMessages.TagLocalAction_2,
CVSUIMessages.TagLocalAction_0,
CVSUIMessages.TagLocalAction_1);
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/UpdateSilentAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/UpdateSilentAction.java
index c7a477777..58a27b78b 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/UpdateSilentAction.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/UpdateSilentAction.java
@@ -48,7 +48,7 @@ public class UpdateSilentAction extends WorkspaceTraversalAction {
if (CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_UPDATE_HANDLING).equals(ICVSUIConstants.PREF_UPDATE_HANDLING_TRADITIONAL)) {
new UpdateOperation(getTargetPart(), getCVSResourceMappings(), Command.NO_LOCAL_OPTIONS, null /* no tag */).run();
} else {
- new ModelUpdateOperation(getTargetPart(), getSelectedResourceMappings(CVSProviderPlugin.getTypeId()), getResourceMappingContext()).run();
+ new ModelUpdateOperation(getTargetPart(), getSelectedResourceMappings(CVSProviderPlugin.getTypeId())).run();
}
}
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/AbstractModelMergeOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/AbstractModelMergeOperation.java
index 839adfac7..1fbc4fa0c 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/AbstractModelMergeOperation.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/AbstractModelMergeOperation.java
@@ -10,27 +10,21 @@
*******************************************************************************/
package org.eclipse.team.internal.ccvs.ui.mappings;
-import org.eclipse.core.resources.mapping.ResourceMapping;
-import org.eclipse.core.resources.mapping.ResourceMappingContext;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.mapping.IResourceMappingScopeManager;
import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
import org.eclipse.team.internal.ccvs.ui.ICVSUIConstants;
-import org.eclipse.team.ui.operations.ModelMergeOperation;
+import org.eclipse.team.ui.operations.ModelParticipantMergeOperation;
+import org.eclipse.team.ui.operations.ModelSynchronizeParticipant;
import org.eclipse.ui.IWorkbenchPart;
-public abstract class AbstractModelMergeOperation extends ModelMergeOperation {
-
- private ResourceMappingContext context;
+public abstract class AbstractModelMergeOperation extends ModelParticipantMergeOperation {
- public AbstractModelMergeOperation(IWorkbenchPart part, ResourceMapping[] selectedMappings, ResourceMappingContext resourceMappingContext) {
- super(part, selectedMappings);
- this.context = resourceMappingContext;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.team.ui.operations.ResourceMappingOperation#getResourceMappingContext()
- */
- protected ResourceMappingContext getResourceMappingContext() {;
- return context;
+ private boolean ownsManager = false;
+
+ public AbstractModelMergeOperation(IWorkbenchPart part, IResourceMappingScopeManager manager, boolean ownsManager) {
+ super(part, manager);
+ this.ownsManager = ownsManager;
}
/* (non-Javadoc)
@@ -46,5 +40,20 @@ public abstract class AbstractModelMergeOperation extends ModelMergeOperation {
protected boolean isPreviewInDialog() {
return CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_UPDATE_PREVIEW).equals(ICVSUIConstants.PREF_UPDATE_PREVIEW_IN_DIALOG);
}
+
+ protected void endOperation(IProgressMonitor monitor) {
+ if (ownsManager) {
+ IResourceMappingScopeManager manager = getScopeManager();
+ manager.dispose();
+ }
+ super.endOperation(monitor);
+ }
+
+ protected ModelSynchronizeParticipant createParticipant() {
+ ModelSynchronizeParticipant participant = super.createParticipant();
+ // Transfer ownership of the manager to the participant
+ ownsManager = false;
+ return participant;
+ }
}
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/CVSSubscriberMergeContext.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/CVSSubscriberMergeContext.java
index 6bdf963e5..65e04afdf 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/CVSSubscriberMergeContext.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/CVSSubscriberMergeContext.java
@@ -15,7 +15,7 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.team.core.diff.IDiff;
-import org.eclipse.team.core.mapping.IResourceMappingScope;
+import org.eclipse.team.core.mapping.IResourceMappingScopeManager;
import org.eclipse.team.core.subscribers.Subscriber;
import org.eclipse.team.core.subscribers.SubscriberMergeContext;
import org.eclipse.team.internal.ccvs.core.CVSException;
@@ -24,8 +24,8 @@ import org.eclipse.team.internal.ccvs.core.resources.EclipseSynchronizer;
public abstract class CVSSubscriberMergeContext extends SubscriberMergeContext {
- protected CVSSubscriberMergeContext(Subscriber subscriber, IResourceMappingScope scope) {
- super(subscriber, scope);
+ protected CVSSubscriberMergeContext(Subscriber subscriber, IResourceMappingScopeManager manager) {
+ super(subscriber, manager);
}
/* (non-Javadoc)
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/MergeSubscriberContext.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/MergeSubscriberContext.java
index d2cd52e9a..82cbf93d1 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/MergeSubscriberContext.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/MergeSubscriberContext.java
@@ -24,14 +24,14 @@ import org.eclipse.team.internal.ccvs.core.CVSMergeSubscriber;
public class MergeSubscriberContext extends CVSSubscriberMergeContext {
- public static IMergeContext createContext(IResourceMappingScope scope, Subscriber subscriber, IProgressMonitor monitor) throws CoreException {
- MergeSubscriberContext mergeContext = new MergeSubscriberContext(subscriber, scope);
- mergeContext.initialize(monitor, true);
+ public static IMergeContext createContext(IResourceMappingScopeManager manager, Subscriber subscriber) {
+ MergeSubscriberContext mergeContext = new MergeSubscriberContext(subscriber, manager);
+ mergeContext.initialize();
return mergeContext;
}
- public MergeSubscriberContext(Subscriber subscriber, IResourceMappingScope scope) {
- super(subscriber, scope);
+ public MergeSubscriberContext(Subscriber subscriber, IResourceMappingScopeManager manager) {
+ super(subscriber, manager);
}
/* (non-Javadoc)
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelMergeOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelMergeOperation.java
index 67386692d..8f473c674 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelMergeOperation.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelMergeOperation.java
@@ -11,30 +11,39 @@
package org.eclipse.team.internal.ccvs.ui.mappings;
import org.eclipse.core.resources.mapping.ResourceMapping;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.team.core.mapping.IMergeContext;
+import org.eclipse.team.core.mapping.ISynchronizationContext;
import org.eclipse.team.core.subscribers.Subscriber;
-import org.eclipse.team.core.subscribers.SubscriberResourceMappingContext;
+import org.eclipse.team.core.subscribers.SubscriberScopeManager;
+import org.eclipse.team.internal.ccvs.core.CVSMergeSubscriber;
import org.eclipse.team.internal.ccvs.ui.CVSUIMessages;
-import org.eclipse.team.internal.ccvs.ui.Policy;
import org.eclipse.ui.IWorkbenchPart;
public class ModelMergeOperation extends AbstractModelMergeOperation {
private final Subscriber subscriber;
-
- public ModelMergeOperation(IWorkbenchPart part, ResourceMapping[] selectedMappings, Subscriber subscriber) {
- super(part, selectedMappings, SubscriberResourceMappingContext.createContext(subscriber));
+
+ /**
+ * Create a merge operation for the given subscriber. The merge operation will cancel the subscriber
+ * when it is no longer needed.
+ * @param part the part
+ * @param mappings the mappings
+ * @param subscriber the subscriber
+ */
+ public ModelMergeOperation(IWorkbenchPart part, ResourceMapping[] mappings, final CVSMergeSubscriber subscriber) {
+ super(part, new SubscriberScopeManager(mappings, subscriber, true){
+ public void dispose() {
+ subscriber.cancel();
+ super.dispose();
+ }
+ }, true);
this.subscriber = subscriber;
}
- protected IMergeContext buildMergeContext(IProgressMonitor monitor)
- throws CoreException {
- monitor.beginTask(null, 100);
- IMergeContext context = MergeSubscriberContext.createContext(getScope(), subscriber, Policy.subMonitorFor(monitor, 50));
- monitor.done();
- return context;
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.operations.ModelParticipantMergeOperation#createMergeContext()
+ */
+ protected ISynchronizationContext createMergeContext() {
+ return MergeSubscriberContext.createContext(getScopeManager(), subscriber);
}
/* (non-Javadoc)
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelReplaceOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelReplaceOperation.java
index f2c5e7ed2..f73dc04de 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelReplaceOperation.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelReplaceOperation.java
@@ -11,7 +11,6 @@
package org.eclipse.team.internal.ccvs.ui.mappings;
import org.eclipse.core.resources.mapping.ResourceMapping;
-import org.eclipse.core.resources.mapping.ResourceMappingContext;
import org.eclipse.core.runtime.*;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
@@ -27,8 +26,8 @@ public class ModelReplaceOperation extends ModelUpdateOperation {
boolean hasPrompted = false;
- public ModelReplaceOperation(IWorkbenchPart part, ResourceMapping[] selectedMappings, ResourceMappingContext context) {
- super(part, selectedMappings, context);
+ public ModelReplaceOperation(IWorkbenchPart part, ResourceMapping[] selectedMappings, boolean consultModels) {
+ super(part, selectedMappings, consultModels);
}
/* (non-Javadoc)
@@ -64,7 +63,6 @@ public class ModelReplaceOperation extends ModelUpdateOperation {
* @see org.eclipse.team.ui.operations.ResourceMappingMergeOperation#performMerge(org.eclipse.core.runtime.IProgressMonitor)
*/
protected IStatus performMerge(IProgressMonitor monitor) throws CoreException {
- // TODO: cancel must free context to avoid leaking
if (!hasLocalChanges() || promptForOverwrite()) {
return super.performMerge(monitor);
}
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelUpdateOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelUpdateOperation.java
index 8a558614f..f552b6b02 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelUpdateOperation.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ModelUpdateOperation.java
@@ -11,21 +11,23 @@
package org.eclipse.team.internal.ccvs.ui.mappings;
import org.eclipse.core.resources.mapping.ResourceMapping;
-import org.eclipse.core.resources.mapping.ResourceMappingContext;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.team.core.mapping.IMergeContext;
import org.eclipse.team.core.mapping.ISynchronizationContext;
+import org.eclipse.team.core.subscribers.SubscriberScopeManager;
+import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.internal.ccvs.ui.*;
import org.eclipse.team.ui.operations.ModelSynchronizeParticipant;
import org.eclipse.ui.IWorkbenchPart;
public class ModelUpdateOperation extends AbstractModelMergeOperation {
- public ModelUpdateOperation(IWorkbenchPart part, ResourceMapping[] selectedMappings, ResourceMappingContext context) {
- super(part, selectedMappings, context);
+ public ModelUpdateOperation(IWorkbenchPart targetPart, ResourceMapping[] selectedResourceMappings, boolean consultModels) {
+ super(targetPart, new SubscriberScopeManager(selectedResourceMappings, CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber(), consultModels), true);
}
+ public ModelUpdateOperation(IWorkbenchPart targetPart, ResourceMapping[] resourceMappings) {
+ this(targetPart, resourceMappings, true);
+ }
+
/* (non-Javadoc)
* @see org.eclipse.team.ui.TeamOperation#getJobName()
*/
@@ -43,16 +45,6 @@ public class ModelUpdateOperation extends AbstractModelMergeOperation {
protected boolean isAttemptHeadlessMerge() {
return CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_UPDATE_HANDLING).equals(ICVSUIConstants.PREF_UPDATE_HANDLING_PERFORM);
}
-
- /* (non-Javadoc)
- * @see org.eclipse.team.ui.operations.ResourceMappingMergeOperation#buildMergeContext(org.eclipse.core.runtime.IProgressMonitor)
- */
- protected IMergeContext buildMergeContext(IProgressMonitor monitor) throws CoreException {
- monitor.beginTask(null, 100);
- IMergeContext context = WorkspaceSubscriberContext.createContext(getScope(), true /* refresh */, getMergeType(), Policy.subMonitorFor(monitor, 50));
- monitor.done();
- return context;
- }
/**
* Return the merge type associated with this operation.
@@ -66,6 +58,13 @@ public class ModelUpdateOperation extends AbstractModelMergeOperation {
* @see org.eclipse.team.ui.operations.ResourceMappingMergeOperation#createParticipant()
*/
protected ModelSynchronizeParticipant createParticipant() {
- return new WorkspaceModelParticipant(getContext(), getJobName());
+ return new WorkspaceModelParticipant(getScopeManager(), createMergeContext(), getJobName());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.operations.ModelParticipantMergeOperation#createMergeContext()
+ */
+ protected ISynchronizationContext createMergeContext() {
+ return WorkspaceSubscriberContext.createContext(getScopeManager(), getMergeType());
}
}
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/WorkspaceModelParticipant.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/WorkspaceModelParticipant.java
index 776171e39..87d77e4d4 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/WorkspaceModelParticipant.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/WorkspaceModelParticipant.java
@@ -10,12 +10,11 @@
*******************************************************************************/
package org.eclipse.team.internal.ccvs.ui.mappings;
+import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.*;
import org.eclipse.team.core.mapping.*;
-import org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager;
-import org.eclipse.team.core.subscribers.SubscriberResourceMappingContext;
+import org.eclipse.team.core.subscribers.SubscriberScopeManager;
import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.internal.ccvs.ui.Policy;
import org.eclipse.team.internal.ccvs.ui.actions.*;
@@ -28,6 +27,14 @@ import org.eclipse.team.ui.operations.MergeActionGroup;
import org.eclipse.team.ui.operations.ModelSynchronizeParticipant;
import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration;
+/**
+ * @author MValenta
+ *
+ */
+/**
+ * @author MValenta
+ *
+ */
public class WorkspaceModelParticipant extends
ModelSynchronizeParticipant {
@@ -137,8 +144,8 @@ public class WorkspaceModelParticipant extends
public WorkspaceModelParticipant() {
}
- public WorkspaceModelParticipant(ISynchronizationContext context, String name) {
- super(context);
+ public WorkspaceModelParticipant(IResourceMappingScopeManager manager, ISynchronizationContext context, String name) {
+ super(manager, context);
try {
setInitializationData(TeamUI.getSynchronizeManager().getParticipantDescriptor("org.eclipse.team.cvs.ui.workspace-participant")); //$NON-NLS-1$
} catch (CoreException e) {
@@ -165,15 +172,15 @@ public class WorkspaceModelParticipant extends
/* (non-Javadoc)
* @see org.eclipse.team.ui.operations.ModelSynchronizeParticipant#restoreContext(org.eclipse.team.core.mapping.IResourceMappingScope, org.eclipse.core.runtime.IProgressMonitor)
*/
- protected IMergeContext restoreContext(IResourceMappingScope scope, IProgressMonitor monitor) throws CoreException {
- return WorkspaceSubscriberContext.createContext(scope, false /* refresh */, ISynchronizationContext.THREE_WAY, monitor);
+ protected IMergeContext restoreContext(IResourceMappingScopeManager manager) {
+ return WorkspaceSubscriberContext.createContext(manager, ISynchronizationContext.THREE_WAY);
}
/* (non-Javadoc)
- * @see org.eclipse.team.ui.operations.ModelSynchronizeParticipant#createScopeGenerator()
+ * @see org.eclipse.team.ui.operations.ModelSynchronizeParticipant#createScopeManager(org.eclipse.core.resources.mapping.ResourceMapping[])
*/
- protected ResourceMappingScopeManager createScopeManager() {
- return new ResourceMappingScopeManager(new SubscriberResourceMappingContext(CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber(), true), true);
+ protected IResourceMappingScopeManager createScopeManager(ResourceMapping[] mappings) {
+ return new SubscriberScopeManager(mappings, CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber(), true);
}
}
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/WorkspaceSubscriberContext.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/WorkspaceSubscriberContext.java
index 506dd6e9e..394768e1b 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/WorkspaceSubscriberContext.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/WorkspaceSubscriberContext.java
@@ -38,15 +38,15 @@ public class WorkspaceSubscriberContext extends CVSSubscriberMergeContext {
private final int type;
- public static IMergeContext createContext(IResourceMappingScope scope, boolean refresh, int type, IProgressMonitor monitor) throws CoreException {
+ public static IMergeContext createContext(IResourceMappingScopeManager manager, int type) {
Subscriber subscriber = CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber();
- WorkspaceSubscriberContext mergeContext = new WorkspaceSubscriberContext(subscriber, scope, type);
- mergeContext.initialize(monitor, refresh);
+ WorkspaceSubscriberContext mergeContext = new WorkspaceSubscriberContext(subscriber, manager, type);
+ mergeContext.initialize();
return mergeContext;
}
- protected WorkspaceSubscriberContext(Subscriber subscriber, IResourceMappingScope scope, int type) {
- super(subscriber, scope);
+ protected WorkspaceSubscriberContext(Subscriber subscriber, IResourceMappingScopeManager manager, int type) {
+ super(subscriber, manager);
this.type = type;
}
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RepositoryProviderOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RepositoryProviderOperation.java
index f87da3d7d..804d950e9 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RepositoryProviderOperation.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RepositoryProviderOperation.java
@@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.team.internal.ccvs.ui.operations;
-import java.lang.reflect.InvocationTargetException;
import java.util.*;
import org.eclipse.core.resources.IProject;
@@ -22,6 +21,8 @@ import org.eclipse.jface.action.IAction;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.mapping.IResourceMappingScope;
+import org.eclipse.team.core.mapping.IResourceMappingScopeManager;
+import org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.Command;
import org.eclipse.team.internal.ccvs.core.client.Session;
@@ -29,7 +30,6 @@ import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
import org.eclipse.team.internal.ccvs.ui.Policy;
-import org.eclipse.team.ui.operations.ModelOperation;
import org.eclipse.ui.IWorkbenchPart;
/**
@@ -44,7 +44,7 @@ public abstract class RepositoryProviderOperation extends CVSOperation {
*/
public static boolean consultModelsWhenBuildingScope = true;
- private IResourceMappingScope scope;
+ private IResourceMappingScopeManager manager;
private final ResourceMapping[] selectedMappings;
/**
@@ -203,41 +203,24 @@ public abstract class RepositoryProviderOperation extends CVSOperation {
} catch (CoreException e) {
throw CVSException.wrapException(e);
} finally {
+ if (manager != null) {
+ manager.dispose();
+ manager = null;
+ }
monitor.done();
}
}
public IResourceMappingScope buildScope(IProgressMonitor monitor) throws InterruptedException, CVSException {
- if (scope == null) {
- ModelOperation op = new ModelOperation(getPart(), selectedMappings) {
- /* (non-Javadoc)
- * @see org.eclipse.team.ui.operations.ResourceMappingOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
- */
- protected void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
- // No need to do anything. We just wanted to build the scope
- }
- /* (non-Javadoc)
- * @see org.eclipse.team.ui.operations.ResourceMappingOperation#consultModelsWhenGeneratingScope()
- */
- protected boolean consultModelsWhenGeneratingScope() {
- if (!consultModelsWhenBuildingScope)
- return false;
- return RepositoryProviderOperation.this.consultModelsForMappings();
- }
-
- protected ResourceMappingContext getResourceMappingContext() {
- return RepositoryProviderOperation.this.getResourceMappingContext();
- }
- };
- // Run the operation to build the scope
+ if (manager == null) {
+ manager = new ResourceMappingScopeManager(selectedMappings, getResourceMappingContext(), consultModelsWhenBuildingScope && consultModelsForMappings());
try {
- op.run(monitor);
- } catch (InvocationTargetException e) {
+ manager.initialize(monitor);
+ } catch (CoreException e) {
throw CVSException.wrapException(e);
}
- scope = op.getScope();
}
- return scope;
+ return manager.getScope();
}
private void execute(Map providerTraversal, IProgressMonitor monitor) throws CVSException, InterruptedException {
@@ -317,11 +300,11 @@ public abstract class RepositoryProviderOperation extends CVSOperation {
*/
private Map getProviderTraversalMapping(IProgressMonitor monitor) throws CoreException {
Map result = new HashMap();
- ResourceMapping[] mappings = scope.getMappings();
+ ResourceMapping[] mappings = getScope().getMappings();
for (int j = 0; j < mappings.length; j++) {
ResourceMapping mapping = mappings[j];
IProject[] projects = mapping.getProjects();
- ResourceTraversal[] traversals = scope.getTraversals(mapping);
+ ResourceTraversal[] traversals = getScope().getTraversals(mapping);
for (int k = 0; k < projects.length; k++) {
IProject project = projects[k];
RepositoryProvider provider = RepositoryProvider.getProvider(project, CVSProviderPlugin.getTypeId());
@@ -473,7 +456,7 @@ public abstract class RepositoryProviderOperation extends CVSOperation {
* @throws CoreException
*/
public ResourceTraversal[] getTraversals() {
- return scope.getTraversals();
+ return getScope().getTraversals();
}
public boolean consultModelsForMappings() {
@@ -485,6 +468,10 @@ public abstract class RepositoryProviderOperation extends CVSOperation {
}
public IResourceMappingScope getScope() {
- return scope;
+ return manager.getScope();
+ }
+
+ public IResourceMappingScopeManager getScopeManager() {
+ return manager;
}
}
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/wizards/CommitWizard.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/wizards/CommitWizard.java
index 8e17514c5..4d04e85a5 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/wizards/CommitWizard.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/wizards/CommitWizard.java
@@ -17,9 +17,7 @@ import java.util.*;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.mapping.ResourceMapping;
-import org.eclipse.core.resources.mapping.ResourceMappingContext;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.jface.dialogs.MessageDialog;
@@ -29,6 +27,8 @@ import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.core.IFileContentManager;
import org.eclipse.team.core.Team;
import org.eclipse.team.core.mapping.IResourceMappingScope;
+import org.eclipse.team.core.mapping.IResourceMappingScopeManager;
+import org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager;
import org.eclipse.team.core.subscribers.SubscriberResourceMappingContext;
import org.eclipse.team.core.synchronize.*;
import org.eclipse.team.internal.ccvs.core.*;
@@ -37,7 +37,6 @@ import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.ui.*;
import org.eclipse.team.internal.ccvs.ui.operations.*;
import org.eclipse.team.internal.core.subscribers.SubscriberSyncInfoCollector;
-import org.eclipse.team.ui.operations.ModelOperation;
import org.eclipse.team.ui.synchronize.ResourceScope;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
@@ -333,26 +332,18 @@ public class CommitWizard extends ResizableWizard {
}
public static IResourceMappingScope buildScope(IWorkbenchPart part, ResourceMapping[] mappings, IProgressMonitor monitor) throws InterruptedException, CVSException {
- ModelOperation op = new ModelOperation(part, mappings) {
- /* (non-Javadoc)
- * @see org.eclipse.team.ui.operations.ResourceMappingOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
- */
- protected void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
- // No need to do anything. We just wanted to build the scope
- }
-
- protected ResourceMappingContext getResourceMappingContext() {
- // TODO: Could use a context built using the source sync-context
- return SubscriberResourceMappingContext.createContext(CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber());
- }
- };
- // Run the operation to build the scope
+ IResourceMappingScopeManager manager = new ResourceMappingScopeManager(mappings,
+ SubscriberResourceMappingContext.createContext(CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber()),
+ true);
try {
- op.run(monitor);
- } catch (InvocationTargetException e) {
+ manager.initialize(monitor);
+ return manager.getScope();
+ } catch (CoreException e) {
throw CVSException.wrapException(e);
+ } finally {
+ if (manager != null)
+ manager.dispose();
}
- return op.getScope();
}
private IWorkbenchPart getPart() {
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/CommonViewerAdvisor.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/CommonViewerAdvisor.java
index 7ed90c9e3..68990d583 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/CommonViewerAdvisor.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/CommonViewerAdvisor.java
@@ -114,7 +114,7 @@ public class CommonViewerAdvisor extends AbstractTreeViewerAdvisor implements IN
* @return a newly created common viewer
*/
private static CommonViewer createViewer(Composite parent, ISynchronizePageConfiguration configuration, IEmptyTreeListener listener) {
- CommonViewer v = new NavigableCommonViewer(configuration.getViewerId(), parent, SWT.NONE, listener);
+ CommonViewer v = new NavigableCommonViewer(configuration.getViewerId(), parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL, listener);
v.getNavigatorContentService().bindExtensions(TeamContentProviderManager.getInstance().getContentProviderIds(), true);
v.getNavigatorContentService().activateExtensions(TeamContentProviderManager.getInstance().getContentProviderIds(), true);
configuration.getSite().setSelectionProvider(v);
@@ -204,19 +204,6 @@ public class CommonViewerAdvisor extends AbstractTreeViewerAdvisor implements IN
private ModelSynchronizeParticipant getParticipant() {
return (ModelSynchronizeParticipant)getConfiguration().getParticipant();
}
-
- /**
- * Set the given property for all active extensions.
- * @param property the property
- * @param value the value
- */
- public void setExtentionProperty(String property, int value) {
- properties.put(property, new Integer(value));
- for (Iterator iter = extensions.iterator(); iter.hasNext();) {
- INavigatorContentExtension extension = (INavigatorContentExtension) iter.next();
- extension.getStateModel().setIntProperty(property, value);
- }
- }
/* (non-Javadoc)
* @see org.eclipse.team.internal.ui.synchronize.StructuredViewerAdvisor#getContextMenuId(org.eclipse.jface.viewers.StructuredViewer)
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/MergeIncomingChangesAction.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/MergeIncomingChangesAction.java
index ecf3f681c..72147bef9 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/MergeIncomingChangesAction.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/MergeIncomingChangesAction.java
@@ -18,6 +18,7 @@ import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.team.core.diff.*;
import org.eclipse.team.core.mapping.IMergeContext;
+import org.eclipse.team.core.mapping.ISynchronizationContext;
import org.eclipse.team.internal.ui.Utils;
import org.eclipse.team.ui.mapping.ISaveableCompareModel;
import org.eclipse.team.ui.mapping.SynchronizationOperation;
@@ -53,18 +54,21 @@ public class MergeIncomingChangesAction extends ModelProviderAction {
new SynchronizationOperation(getConfiguration(), getContext().getScope().getMappings()) {
public void execute(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
- new ModelMergeOperation(getPart(), context) {
- protected IMergeContext buildMergeContext(IProgressMonitor monitor) throws CoreException {
- return context;
- }
+ new ModelMergeOperation(getPart(), ((ModelSynchronizeParticipant)getConfiguration().getParticipant()).getScopeManager()) {
public boolean isPreviewRequested() {
return false;
}
- protected void showPreview(IProgressMonitor monitor) {
- // Do nothing since this action was launched from a preview
+ protected void initializeContext(IProgressMonitor monitor) throws CoreException {
+ // Context is already initialized
+ }
+ protected ISynchronizationContext getContext() {
+ return context;
}
}.run(monitor);
}
+ protected boolean canRunAsJob() {
+ return true;
+ }
}.run();
} catch (InvocationTargetException e) {
Utils.handle(e);
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ModelParticipantPageDialog.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ModelParticipantPageDialog.java
new file mode 100644
index 000000000..5bfca0cca
--- /dev/null
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ModelParticipantPageDialog.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.internal.ui.mapping;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.team.core.mapping.IMergeContext;
+import org.eclipse.team.core.mapping.ISynchronizationContext;
+import org.eclipse.team.internal.ui.TeamUIMessages;
+import org.eclipse.team.ui.SaveablePartAdapter;
+import org.eclipse.team.ui.operations.ModelSynchronizeParticipant;
+import org.eclipse.team.ui.synchronize.*;
+
+public final class ModelParticipantPageDialog extends ParticipantPageDialog {
+
+ /*
+ * Ids for custom buttons when previewing a merge/replace
+ */
+ private static final int DONE_ID = IDialogConstants.CLIENT_ID + 1;
+ private static final int REPLACE_ID = IDialogConstants.CLIENT_ID + 2;
+
+ private final ModelSynchronizeParticipant participant;
+ private Button doneButton;
+ private Button replaceButton;
+
+ public ModelParticipantPageDialog(Shell shell, ModelSynchronizeParticipant participant, CompareConfiguration cc, ISynchronizePageConfiguration pc) {
+ super(shell, createInput(shell, participant, cc, pc), participant);
+ this.participant = participant;
+ }
+
+ private static SaveablePartAdapter createInput(Shell shell, ModelSynchronizeParticipant participant, CompareConfiguration cc, ISynchronizePageConfiguration pc) {
+ ParticipantPageSaveablePart input = new ParticipantPageSaveablePart(shell, cc, pc, participant);
+ return input;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.SaveablePartDialog#close()
+ */
+ public boolean close() {
+ boolean close = super.close();
+ if (super.close()) {
+ getInput().dispose();
+ }
+ return close;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.synchronize.ParticipantPageDialog#isOfferToRememberParticipant()
+ */
+ protected boolean isOfferToRememberParticipant() {
+ boolean isReplace = ((IMergeContext)participant.getContext()).getMergeType() == ISynchronizationContext.TWO_WAY;
+ if (isReplace)
+ return false;
+ return super.isOfferToRememberParticipant();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.SaveablePartDialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
+ */
+ protected void createButtonsForButtonBar(Composite parent) {
+ boolean isReplace = ((IMergeContext)participant.getContext()).getMergeType() == ISynchronizationContext.TWO_WAY;
+ isReplace = false; // TODO: Disbled for now
+ if (isReplace) {
+ replaceButton = createButton(parent, REPLACE_ID, "&Replace", true);
+ replaceButton.setEnabled(true);
+ }
+ doneButton = createButton(parent, DONE_ID, TeamUIMessages.ResourceMappingMergeOperation_2, !isReplace);
+ doneButton.setEnabled(true);
+ // Don't call super because we don't want the OK button to appear
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.synchronize.ParticipantPageDialog#buttonPressed(int)
+ */
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == DONE_ID) {
+ super.buttonPressed(IDialogConstants.OK_ID);
+ } else if (buttonId == REPLACE_ID) {
+ // TODO: Disabled for now
+// try {
+// // Do this inline so we don't have to manage disposing of the context
+// PlatformUI.getWorkbench().getProgressService().run(true, true, new IRunnableWithProgress() {
+// public void run(IProgressMonitor monitor) throws InvocationTargetException,
+// InterruptedException {
+// try {
+//
+// ModelParticipantPageDialog.this.operation.performMerge(monitor);
+// } catch (CoreException e) {
+// throw new InvocationTargetException(e);
+// }
+// }
+// });
+// } catch (InvocationTargetException e) {
+// Throwable t = e.getTargetException();
+// IStatus status;
+// if (t instanceof CoreException) {
+// CoreException ce = (CoreException) t;
+// status = ce.getStatus();
+// } else {
+// status = new Status(IStatus.ERROR, TeamUIPlugin.ID, 0, TeamUIMessages.internal, t);
+// TeamUIPlugin.log(status);
+// }
+// ErrorDialog.openError(getShell(), null, null, status);
+// return;
+// } catch (InterruptedException e) {
+// // Operation was cancelled. Leave the dialog open
+// return;
+// }
+ super.buttonPressed(IDialogConstants.OK_ID);
+ } else {
+ super.buttonPressed(buttonId);
+ }
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ModelSynchronizePage.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ModelSynchronizePage.java
index 1c6c3abb3..3740b9957 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ModelSynchronizePage.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ModelSynchronizePage.java
@@ -61,11 +61,7 @@ public class ModelSynchronizePage extends AbstractSynchronizePage {
* @see org.eclipse.team.internal.ui.synchronize.AbstractSynchronizePage#updateMode(int)
*/
protected void updateMode(int mode) {
- if (isThreeWay()) {
- CommonViewerAdvisor advisor = (CommonViewerAdvisor)getConfiguration().getProperty(SynchronizePageConfiguration.P_ADVISOR);
- if (advisor != null)
- advisor.setExtentionProperty(ISynchronizePageConfiguration.P_MODE, mode);
- }
+ // Nothing to do
}
/**
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ResourceTeamAwareContentProvider.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ResourceTeamAwareContentProvider.java
index 5d70fda9a..283bf98c2 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ResourceTeamAwareContentProvider.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ResourceTeamAwareContentProvider.java
@@ -101,13 +101,12 @@ public class ResourceTeamAwareContentProvider extends SynchronizationContentProv
* @see org.eclipse.team.ui.mapping.SynchronizationContentProvider#getChildrenInContext(org.eclipse.team.core.mapping.ISynchronizationContext, java.lang.Object, java.lang.Object[])
*/
protected Object[] getChildrenInContext(ISynchronizationContext context, Object parent, Object[] children) {
- Object[] objects = super.getChildrenInContext(context, parent, children);
if (parent instanceof IResource) {
IResource resource = (IResource) parent;
Set result = new HashSet();
- for (int i = 0; i < objects.length; i++) {
- Object object = objects[i];
+ for (int i = 0; i < children.length; i++) {
+ Object object = children[i];
result.add(object);
}
IPath[] childPaths = context.getDiffTree().getChildren(resource.getFullPath());
@@ -129,9 +128,9 @@ public class ResourceTeamAwareContentProvider extends SynchronizationContentProv
result.add(child);
}
}
- return result.toArray(new Object[result.size()]);
+ return super.getChildrenInContext(context, parent, result.toArray(new Object[result.size()]));
}
- return children;
+ return super.getChildrenInContext(context, parent, children);
}
protected ResourceTraversal[] getTraversals(ISynchronizationContext context, Object object) {
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/SaveablePartDialog.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/SaveablePartDialog.java
index 1b62ac634..ba184c932 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/SaveablePartDialog.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/SaveablePartDialog.java
@@ -88,4 +88,12 @@ public class SaveablePartDialog extends ResizableDialog {
});
}
}
+
+ /**
+ * Return the input to the dialog.
+ * @return the input to the dialog
+ */
+ protected ISaveableWorkbenchPart getInput() {
+ return input;
+ }
}
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationContentProvider.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationContentProvider.java
index 700ff9deb..af60a0311 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationContentProvider.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationContentProvider.java
@@ -126,7 +126,7 @@ public abstract class SynchronizationContentProvider implements ICommonContentPr
return new Object[0];
}
if (parent == getModelProvider()) {
- if (!isInitialized(context)) {
+ if (context != null && !isInitialized(context)) {
return new Object[0];
}
parent = getModelRoot();
@@ -266,6 +266,9 @@ public abstract class SynchronizationContentProvider implements ICommonContentPr
stateModel.removePropertyChangeListener(this);
if (context != null)
context.getDiffTree().removeDiffChangeListener(this);
+ ISynchronizePageConfiguration configuration = getConfiguration();
+ if (configuration != null)
+ configuration.removePropertyChangeListener(this);
}
/* (non-Javadoc)
@@ -282,6 +285,9 @@ public abstract class SynchronizationContentProvider implements ICommonContentPr
public void init(IExtensionStateModel aStateModel, IMemento aMemento) {
stateModel = aStateModel;
stateModel.addPropertyChangeListener(this);
+ ISynchronizePageConfiguration configuration = getConfiguration();
+ if (configuration != null)
+ configuration.addPropertyChangeListener(this);
scope = (IResourceMappingScope)aStateModel.getProperty(ISynchronizationConstants.P_RESOURCE_MAPPING_SCOPE);
context = (ISynchronizationContext)aStateModel.getProperty(ISynchronizationConstants.P_SYNCHRONIZATION_CONTEXT);
ITreeContentProvider provider = getDelegateContentProvider();
@@ -317,7 +323,7 @@ public abstract class SynchronizationContentProvider implements ICommonContentPr
* included in the contents
*/
protected boolean includeDirection(int direction) {
- int mode = stateModel.getIntProperty(ISynchronizePageConfiguration.P_MODE);
+ int mode = getConfiguration().getMode();
switch (mode) {
case ISynchronizePageConfiguration.BOTH_MODE:
return true;
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationLabelProvider.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationLabelProvider.java
index b60b46400..3cbfad8d3 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationLabelProvider.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationLabelProvider.java
@@ -150,7 +150,8 @@ public abstract class SynchronizationLabelProvider extends AbstractSynchronizeLa
String text = super.getText(element);
if (contentProvider instanceof SynchronizationContentProvider) {
SynchronizationContentProvider scp = (SynchronizationContentProvider) contentProvider;
- if (!scp.isInitialized(getContext())) {
+ ISynchronizationContext context = getContext();
+ if (context != null && !scp.isInitialized(context)) {
return NLS.bind("{0} Initializing", text);
}
}
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationOperation.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationOperation.java
index 20c7aa354..3931cbde3 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationOperation.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationOperation.java
@@ -105,12 +105,6 @@ public abstract class SynchronizationOperation extends TeamOperation {
public boolean shouldRun() {
return super.shouldRun();
}
-
- public boolean belongsTo(Object family) {
- if (family == getContext())
- return true;
- return super.belongsTo(family);
- }
/**
* Return the buffer that this operation will write its results
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/MergeActionGroup.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/MergeActionGroup.java
index 38d82adf6..6dca754a8 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/MergeActionGroup.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/MergeActionGroup.java
@@ -191,7 +191,8 @@ public class MergeActionGroup extends SynchronizePageActionGroup {
}
public void dispose() {
- modelPicker.dispose();
+ if (modelPicker != null)
+ modelPicker.dispose();
super.dispose();
}
} \ No newline at end of file
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelMergeOperation.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelMergeOperation.java
index d10a99a62..244944efd 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelMergeOperation.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelMergeOperation.java
@@ -1,12 +1,12 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2006 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
* http://www.eclipse.org/legal/epl-v10.html
- *
+ *
* Contributors:
- * IBM Corporation - initial API and implementation
+ * IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.team.ui.operations;
@@ -14,85 +14,21 @@ import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
-import org.eclipse.compare.CompareConfiguration;
import org.eclipse.core.resources.*;
import org.eclipse.core.resources.mapping.ModelProvider;
-import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.runtime.*;
-import org.eclipse.jface.dialogs.*;
-import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.swt.widgets.*;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Display;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.diff.*;
import org.eclipse.team.core.mapping.*;
import org.eclipse.team.internal.ui.*;
-import org.eclipse.team.internal.ui.mapping.DefaultResourceMappingMerger;
-import org.eclipse.team.ui.TeamUI;
-import org.eclipse.team.ui.mapping.ICompareAdapter;
-import org.eclipse.team.ui.synchronize.*;
import org.eclipse.ui.IWorkbenchPart;
-import org.eclipse.ui.PlatformUI;
/**
- * The steps of an optimistic merge operation are:
- * <ol>
- * <li>Obtain the selection to be operated on.
- * <li>Determine the projection of the selection onto resources
- * using resource mappings and traversals.
- * <ul>
- * <li>this will require traversals using both the ancestor and remote
- * for three-way merges.
- * <li>for model providers with registered merger, mapping set need
- * not be expanded (this is tricky if one of the model providers doesn't
- * have a merge but all others do).
- * <li>if the model does not have a custom merger, ensure that additional
- * mappings are included (i.e. for many model elements to one resource case)
- * </ul>
- * <li>Create a MergeContext for the merge
- * <ul>
- * <li>Determine the synchronization state of all resources
- * covered by the input.
- * <li>Pre-fetch the required contents.
- * </ul>
- * <li>Obtain and invoke the merger for each provider
- * <ul>
- * <li>This will auto-merge as much as possible
- * <li>If everything was merged, cleanup and stop
- * <li>Otherwise, a set of un-merged resource mappings is returned
- * </ul>
- * <li>Delegate manual merge to the model provider
- * <ul>
- * <li>This hands off the context to the manual merge
- * <li>Once completed, the manual merge must clean up
- * </ul>
- * </ol>
- *
- * <p>
- * Handle multiple model providers where one extends all others by using
- * the top-most model provider. The assumption is that the model provider
- * will delegate to lower level model providers when appropriate.
- * <p>
- * Special case to support sub-file merges.
- * <ul>
- * <li>Restrict when sub-file merging is supported
- * <ul>
- * <li>Only one provider involved (i.e. consulting participants results
- * in participants that are from the model provider or below).
- * <li>The provider has a custom auto and manual merger.
- * </ul>
- * <li>Prompt to warn when sub-file merging is not possible.
- * <li>Need to display the additional elements that will be affected.
- * This could be done in a diff tree or some other view. It needs to
- * consider incoming changes including additions.
- * </ul>
- * <p>
- * Special case to handle conflicting model providers.
- * <ul>
- * <li>Prompt user to indicate the conflict
- * <li>Allow user to exclude one of the models?
- * <li>Allow use to choose order of evaluation?
- * <li>Support tabbed sync view
- * </ul>
+ * A model operation that executes a merge according to the merge lifecycle
+ * associated with an {@link IMergeContext} and {@link IResourceMappingMerger}
+ * instances obtained from the model providers involved.
*
* <p>
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as
@@ -104,22 +40,6 @@ import org.eclipse.ui.PlatformUI;
* @since 3.2
*/
public abstract class ModelMergeOperation extends ModelOperation {
-
- /**
- * Status code that can be returned from the {@link #performMerge(IProgressMonitor)}
- * method to indicate that a subclass would liek to force a preview of the merge.
- * The message of such a status should be ignored.
- */
- public static final int REQUEST_PREVIEW = 1024;
-
- /*
- * Ids for custom buttons when previewing a merge/replace
- */
- private static final int DONE_ID = IDialogConstants.CLIENT_ID + 1;
- private static final int REPLACE_ID = IDialogConstants.CLIENT_ID + 2;
-
- private IMergeContext context;
- private boolean ownsContext = true;
/**
* Validate the merge context with the model providers that have mappings in
@@ -161,10 +81,12 @@ public abstract class ModelMergeOperation extends ModelOperation {
*/
private static IStatus validateMerge(ModelProvider provider, IMergeContext context, IProgressMonitor monitor) {
IResourceMappingMerger merger = getMerger(provider);
+ if (merger == null)
+ return Status.OK_STATUS;
return merger.validateMerge(context, monitor);
}
- /**
+ /*
* Return the auto-merger associated with the given model provider using the
* adaptable mechanism. If the model provider does not have a merger
* associated with it, a default merger that performs the merge at the file
@@ -175,251 +97,109 @@ public abstract class ModelMergeOperation extends ModelOperation {
* <code>null</code>)
* @return a merger
*/
- public static IResourceMappingMerger getMerger(ModelProvider provider) {
+ private static IResourceMappingMerger getMerger(ModelProvider provider) {
Assert.isNotNull(provider);
- IResourceMappingMerger merger = (IResourceMappingMerger)Utils.getAdapter(provider, IResourceMappingMerger.class);
- if (merger != null)
- return merger;
- return new DefaultResourceMappingMerger(provider);
+ return (IResourceMappingMerger)Utils.getAdapter(provider, IResourceMappingMerger.class);
}
/**
- * Create a merge operation
- * @param part the workbench part from which the merge was launched or <code>null</code>
- * @param selectedMappings the selected mappings
- */
- protected ModelMergeOperation(IWorkbenchPart part, ResourceMapping[] selectedMappings) {
- super(part, selectedMappings);
- }
-
- /**
- * Create the model merge operation for the given context.
- * The merge will be performed for the given context but
- * the context will not be disposed by this operation
- * (i.e. it is considered to be owned by the client).
- * @param part the workbench part from which the merge was launched or <code>null</code>
- * @param context the merge context to be merged
+ * Create a model merge operation.
+ * @param part the workbench part from which the operation was requested or <code>null</code>
+ * @param manager the scope manager
*/
- public ModelMergeOperation(IWorkbenchPart part, IMergeContext context) {
- super(part, context.getScope());
- this.context = context;
- ownsContext = false;
+ protected ModelMergeOperation(IWorkbenchPart part, IResourceMappingScopeManager manager) {
+ super(part, manager);
}
-
- /* (non-Javadoc)
- * @see org.eclipse.team.ui.mapping.ResourceMappingOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
- */
- protected void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+
+ protected void execute(IProgressMonitor monitor)
+ throws InvocationTargetException, InterruptedException {
try {
monitor.beginTask(null, 100);
- if (context == null)
- context = buildMergeContext(Policy.subMonitorFor(monitor, 75));
+ initializeContext(Policy.subMonitorFor(monitor, 75));
if (!hasChangesOfInterest()) {
- promptForNoChanges();
- return;
- }
- if (!isPreviewRequested()) {
- IStatus status = validateMerge(context, Policy.subMonitorFor(monitor, 5));
- if (status.isOK()) {
- status = performMerge(Policy.subMonitorFor(monitor, 20));
- if (status.isOK()) {
- // The merge was sucessful so we can just return
- return;
- } else {
- if (status.getCode() == IMergeStatus.CONFLICTS) {
- promptForMergeFailure(status);
- }
- }
- } else {
- // TODO prompt with validation message
+ handleNoChanges();
+ } else if (isPreviewRequested()) {
+ handlePreviewRequest();
+ } else {
+ IStatus status = ModelMergeOperation.validateMerge(getMergeContext(), Policy.subMonitorFor(monitor, 5));
+ if (!status.isOK()) {
+ handleValidationFailure(status);
+ }
+ status = performMerge(Policy.subMonitorFor(monitor, 20));
+ if (!status.isOK()) {
+ handleMergeFailure(status);
}
}
- // Either auto-merging was not attemped or it was not 100% sucessful
- showPreview(Policy.subMonitorFor(monitor, 25));
} catch (CoreException e) {
throw new InvocationTargetException(e);
} finally {
- if (ownsContext && context != null)
- context.dispose();
monitor.done();
}
}
-
- /**
- * Prompt for a failure to auto-merge
- * @param status the status returned from the merger that reported the conflict
- */
- protected void promptForMergeFailure(IStatus status) {
- Display.getDefault().syncExec(new Runnable() {
- public void run() {
- MessageDialog.openInformation(getShell(), TeamUIMessages.MergeIncomingChangesAction_0, TeamUIMessages.MergeIncomingChangesAction_1);
- };
- });
- }
/**
- * Return whether the context of this operation has changes that are
- * of interest to the operation. Sublcasses may override.
- * @return whether the context of this operation has changes that are
- * of interest to the operation
+ * A preview of the merge has been requested. By default, this method does
+ * nothing. Subclasses that wish to support previewing must override this
+ * method to preview the merge and the {@link #getPreviewRequestMessage()}
+ * to have the option presented to the user if the scope changes.
*/
- protected boolean hasChangesOfInterest() {
- return !context.getDiffTree().isEmpty() && hasIncomingChanges(context.getDiffTree());
+ protected void handlePreviewRequest() {
+ // Do nothing
}
- private boolean hasIncomingChanges(IDiffTree tree) {
- return hasChangesMatching(tree, new FastDiffFilter() {
- public boolean select(IDiff node) {
- if (node instanceof IThreeWayDiff) {
- IThreeWayDiff twd = (IThreeWayDiff) node;
- int direction = twd.getDirection();
- if (direction == IThreeWayDiff.INCOMING || direction == IThreeWayDiff.CONFLICTING) {
- return true;
- }
- } else {
- // Return true for any two-way change
- return true;
- }
- return false;
- }
- });
- }
+ /**
+ * Initialize the merge context for this merge operation.
+ * After this method is invoked, the {@link #getContext()}
+ * method must return an instance of {@link IMergeContext}
+ * that is fully initialized.
+ * @param monitor a progress monitor
+ * @throws CoreException
+ */
+ protected abstract void initializeContext(IProgressMonitor monitor) throws CoreException;
/**
- * Method invoked when the context contains no changes so that the user
- * can be informed.
+ * Method invoked when the context contains changes that failed validation
+ * by at least one {@link IResourceMappingMerger}.
+ * By default, the user is prompted to inform them that unmergeable changes were found
+ * and the {@link #handlePreviewRequest()} method is invoked.
+ * Subclasses may override.
+ * @param status the status returned from the mergers that reported the validation failures
*/
- protected void promptForNoChanges() {
+ protected void handleValidationFailure(IStatus status) {
Display.getDefault().syncExec(new Runnable() {
public void run() {
- MessageDialog.openInformation(getShell(), TeamUIMessages.ResourceMappingMergeOperation_0, TeamUIMessages.ResourceMappingMergeOperation_1);
+ MessageDialog.openInformation(getShell(), "Validation Failure", "Better message to come.");
};
});
+ handlePreviewRequest();
}
/**
- * Preview the merge so the user can perform the merge manually.
- * @param monitor a progress monitor
+ * Method invoked when the context contains unmergable changes.
+ * By default, the user is promted to inform them that unmergeable changes were found.
+ * Subclasses may override.
+ * @param status the status returned from the merger that reported the conflict
*/
- protected void showPreview(IProgressMonitor monitor) {
- calculateStates(context, Policy.subMonitorFor(monitor, 5));
- // TODO Ownership of the context is being transferred to the participant
- final ModelSynchronizeParticipant participant = createParticipant();
- ownsContext = false;
- Display.getDefault().asyncExec(new Runnable() {
+ protected void handleMergeFailure(IStatus status) {
+ Display.getDefault().syncExec(new Runnable() {
public void run() {
- if (isPreviewInDialog()) {
- CompareConfiguration cc = new CompareConfiguration();
- ISynchronizePageConfiguration pageConfiguration = participant.createPageConfiguration();
- // Restrict preview page to only support incomign and conflict modes
- if (pageConfiguration.getComparisonType() == ISynchronizePageConfiguration.THREE_WAY) {
- pageConfiguration.setSupportedModes(ISynchronizePageConfiguration.INCOMING_MODE | ISynchronizePageConfiguration.CONFLICTING_MODE);
- pageConfiguration.setMode(ISynchronizePageConfiguration.INCOMING_MODE);
- }
- ParticipantPageSaveablePart input = new ParticipantPageSaveablePart(getShell(), cc, pageConfiguration, participant);
- ParticipantPageDialog dialog = new ParticipantPageDialog(getShell(), input, participant) {
- private Button doneButton;
- private Button replaceButton;
-
- protected boolean isOfferToRememberParticipant() {
- boolean isReplace = context.getMergeType() == ISynchronizationContext.TWO_WAY;
- if (isReplace)
- return false;
- return super.isOfferToRememberParticipant();
- }
-
- protected void createButtonsForButtonBar(Composite parent) {
- boolean isReplace = context.getMergeType() == ISynchronizationContext.TWO_WAY;
- if (isReplace) {
- replaceButton = createButton(parent, REPLACE_ID, "&Replace", true);
- replaceButton.setEnabled(true);
- }
- doneButton = createButton(parent, DONE_ID, TeamUIMessages.ResourceMappingMergeOperation_2, !isReplace);
- doneButton.setEnabled(true);
- // Don't call super because we don't want the OK button to appear
- }
- protected void buttonPressed(int buttonId) {
- if (buttonId == DONE_ID) {
- super.buttonPressed(IDialogConstants.OK_ID);
- } else if (buttonId == REPLACE_ID) {
- try {
- // Do this inline so we don't have to manage disposing of the context
- PlatformUI.getWorkbench().getProgressService().run(true, true, new IRunnableWithProgress() {
- public void run(IProgressMonitor monitor) throws InvocationTargetException,
- InterruptedException {
- try {
- performMerge(monitor);
- } catch (CoreException e) {
- throw new InvocationTargetException(e);
- }
- }
-
- });
- } catch (InvocationTargetException e) {
- Throwable t = e.getTargetException();
- IStatus status;
- if (t instanceof CoreException) {
- CoreException ce = (CoreException) t;
- status = ce.getStatus();
- } else {
- status = new Status(IStatus.ERROR, TeamUIPlugin.ID, 0, TeamUIMessages.internal, t);
- TeamUIPlugin.log(status);
- }
- ErrorDialog.openError(getShell(), null, null, status);
- return;
- } catch (InterruptedException e) {
- // Operation was cancelled. Leave the dialog open
- return;
- }
- super.buttonPressed(IDialogConstants.OK_ID);
- } else {
- super.buttonPressed(buttonId);
- }
- }
- };
- int result = dialog.open();
- input.dispose();
- if (TeamUI.getSynchronizeManager().get(participant.getId(), participant.getSecondaryId()) == null)
- participant.dispose();
- } else {
- ISynchronizeManager mgr = TeamUI.getSynchronizeManager();
- ISynchronizeView view = mgr.showSynchronizeViewInActivePage();
- mgr.addSynchronizeParticipants(new ISynchronizeParticipant[] {participant});
- view.display(participant);
- }
- }
+ MessageDialog.openInformation(getShell(), TeamUIMessages.MergeIncomingChangesAction_0, TeamUIMessages.MergeIncomingChangesAction_1);
+ };
});
+ handlePreviewRequest();
}
/**
- * Return whether previews should occur in a dialog or in the synchronize view.
- * @return whether previews should occur in a dialog or in the synchronize view
+ * Method invoked when the context contains no changes.
+ * By default, the user is promted to inform them that no changes were found.
+ * Subclasses may override.
*/
- protected boolean isPreviewInDialog() {
- return true;
- }
-
- private void calculateStates(ISynchronizationContext context, IProgressMonitor monitor) {
- monitor.beginTask(null, IProgressMonitor.UNKNOWN);
- ModelProvider[] providers = getScope().getModelProviders();
- for (int i = 0; i < providers.length; i++) {
- ModelProvider provider = providers[i];
- calculateStates(context, provider, Policy.subMonitorFor(monitor, IProgressMonitor.UNKNOWN));
- }
- monitor.done();
- }
-
- private void calculateStates(ISynchronizationContext context, ModelProvider provider, IProgressMonitor monitor) {
- Object o = provider.getAdapter(ICompareAdapter.class);
- if (o instanceof ICompareAdapter) {
- ICompareAdapter calculator = (ICompareAdapter) o;
- try {
- calculator.prepareContext(context, monitor);
- } catch (CoreException e) {
- TeamUIPlugin.log(e);
- }
- }
- monitor.done();
+ protected void handleNoChanges() {
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ MessageDialog.openInformation(getShell(), TeamUIMessages.ResourceMappingMergeOperation_0, TeamUIMessages.ResourceMappingMergeOperation_1);
+ };
+ });
}
/**
@@ -497,43 +277,32 @@ public abstract class ModelMergeOperation extends ModelOperation {
if (sc instanceof IMergeContext) {
IMergeContext context = (IMergeContext) sc;
IResourceMappingMerger merger = getMerger(provider);
- IStatus status = merger.merge(context, monitor);
- if (status.isOK() || status.getCode() == IMergeStatus.CONFLICTS) {
- return status;
+ if (merger != null) {
+ IStatus status = merger.merge(context, monitor);
+ if (status.isOK() || status.getCode() == IMergeStatus.CONFLICTS) {
+ return status;
+ }
+ throw new TeamException(status);
}
- throw new TeamException(status);
+ return Status.OK_STATUS;
}
return noMergeContextAvailable();
}
-
+
private IStatus noMergeContextAvailable() {
throw new IllegalStateException("Merges should only be attemped for operations that have a merge context");
}
/**
- * Build and initialize a merge context for the input of this operation.
- * @param monitor a progress monitor
- * @return a merge context for merging the mappings of the input
- */
- protected abstract IMergeContext buildMergeContext(IProgressMonitor monitor) throws CoreException;
-
- /* (non-Javadoc)
- * @see org.eclipse.team.ui.operations.ResourceMappingOperation#getContext()
- */
- protected ISynchronizationContext getContext() {
- return context;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.team.ui.operations.ResourceMappingOperation#getPreviewRequestMessage()
+ * Return whether the context of this operation has changes that are
+ * of interest to the operation. Sublcasses may override.
+ * @return whether the context of this operation has changes that are
+ * of interest to the operation
*/
- protected String getPreviewRequestMessage() {
- if (!isPreviewRequested()) {
- return TeamUIMessages.ResourceMappingMergeOperation_4;
- }
- return super.getPreviewRequestMessage();
+ protected boolean hasChangesOfInterest() {
+ return !getContext().getDiffTree().isEmpty() && hasIncomingChanges(getContext().getDiffTree());
}
-
+
/**
* Return whether the given diff tree contains any deltas that match the given filter.
* @param tree the diff tree
@@ -559,19 +328,26 @@ public abstract class ModelMergeOperation extends ModelOperation {
}
return false;
}
-
- /**
- * Create the synchronize pariticipant to be used by this operation
- * to preview changes. By default, a {@link ModelSynchronizeParticipant}
- * is created using he context ({@link #getContext()}) and job name ({@link #getJobName()})
- * of this operation. Subclasses may override this method.
- * <p>
- * Once created, it is the responsibility of the participant to dispose of the
- * synchronization context when it is no longer needed.
- * @return a newly created synchronize pariticipant to be used by this operation
- */
- protected ModelSynchronizeParticipant createParticipant() {
- return ModelSynchronizeParticipant.createParticipant(getContext(), getJobName());
+
+ private boolean hasIncomingChanges(IDiffTree tree) {
+ return hasChangesMatching(tree, new FastDiffFilter() {
+ public boolean select(IDiff node) {
+ if (node instanceof IThreeWayDiff) {
+ IThreeWayDiff twd = (IThreeWayDiff) node;
+ int direction = twd.getDirection();
+ if (direction == IThreeWayDiff.INCOMING || direction == IThreeWayDiff.CONFLICTING) {
+ return true;
+ }
+ } else {
+ // Return true for any two-way change
+ return true;
+ }
+ return false;
+ }
+ });
+ }
+
+ private IMergeContext getMergeContext() {
+ return (IMergeContext)getContext();
}
-
}
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelOperation.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelOperation.java
index 668d4f38b..8ef1959c7 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelOperation.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelOperation.java
@@ -18,9 +18,7 @@ import org.eclipse.core.resources.mapping.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
-import org.eclipse.team.core.mapping.IResourceMappingScope;
-import org.eclipse.team.core.mapping.ISynchronizationContext;
-import org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager;
+import org.eclipse.team.core.mapping.*;
import org.eclipse.team.internal.core.mapping.ResourceMappingScope;
import org.eclipse.team.internal.ui.TeamUIMessages;
import org.eclipse.team.internal.ui.dialogs.AdditionalMappingsDialog;
@@ -45,9 +43,8 @@ import org.eclipse.ui.IWorkbenchPart;
*/
public abstract class ModelOperation extends TeamOperation {
- private final ResourceMapping[] selectedMappings;
- private IResourceMappingScope scope;
private boolean previewRequested;
+ private IResourceMappingScopeManager manager;
/**
* Return the list of provides sorted by their extends relationship.
@@ -87,37 +84,38 @@ public abstract class ModelOperation extends TeamOperation {
}
/**
- * Create a model operation for the given selected mappings.
- * The scope will be generated when the operation is executed.
- * @param part the workbench part from which the merge was launched or <code>null</code>
- * @param selectedMappings the selected mappings
- */
- protected ModelOperation(IWorkbenchPart part, ResourceMapping[] selectedMappings) {
- super(part);
- this.selectedMappings = selectedMappings;
- }
-
- /**
* Create a model operation that operates on the given scope.
* @param part the workbench part from which the merge was launched or <code>null</code>
- * @param scope the scope of this operation
+ * @param manager the scope manager for this operation
*/
- protected ModelOperation(IWorkbenchPart part, IResourceMappingScope scope) {
- this(part, scope.getInputMappings());
- this.scope = scope;
+ protected ModelOperation(IWorkbenchPart part, IResourceMappingScopeManager manager) {
+ super(part);
+ this.manager = manager;
}
/**
* Run the operation. This method first ensures that the scope is built
- * by calling {@link #prepareScope(IProgressMonitor)} and then invokes the
+ * by calling {@link #initializeScope(IProgressMonitor)} and then invokes the
* {@link #execute(IProgressMonitor)} method.
* @param monitor a progress monitor
* @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
*/
- public void run(IProgressMonitor monitor) throws InvocationTargetException,
+ public final void run(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
- prepareScope(monitor);
- execute(monitor);
+ try {
+ beginOperation(monitor);
+ execute(monitor);
+ } finally {
+ endOperation(monitor);
+ }
+ }
+
+ protected void beginOperation(IProgressMonitor monitor) throws InvocationTargetException {
+ initializeScope(monitor);
+ }
+
+ protected void endOperation(IProgressMonitor monitor) {
+ // Do nothing by deafult
}
/**
@@ -139,35 +137,34 @@ public abstract class ModelOperation extends TeamOperation {
* the {@link #getScopeManager()} to return a custom scope manager.
* @param monitor a progress monitor
*/
- protected final void prepareScope(IProgressMonitor monitor) throws InvocationTargetException {
- if (scope == null) {
- try {
- ResourceMappingScopeManager manager = getScopeManager();
- scope = manager.prepareScope(selectedMappings, isUseLocalContext(), monitor);
+ protected final void initializeScope(IProgressMonitor monitor) throws InvocationTargetException {
+ try {
+ if (!manager.isInitialized()) {
+ manager.initialize(monitor);
promptIfInputChange(monitor);
- } catch (CoreException e) {
- throw new InvocationTargetException(e);
}
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
}
}
/**
* Prompt the user by calling {@link #promptForInputChange(String, IProgressMonitor)}
* if the scope of the operation was expanded (as described in
- * {@link #prepareScope(IProgressMonitor)}).
+ * {@link #initializeScope(IProgressMonitor)}).
* @param monitor a progress monitor
*/
protected void promptIfInputChange(IProgressMonitor monitor) {
IResourceMappingScope inputScope = getScope().asInputScope();
- if (scope.hasAdditionalMappings()) {
+ if (getScope().hasAdditionalMappings()) {
boolean prompt = false;
// There are additional mappings so we may need to prompt
ModelProvider[] inputModelProviders = inputScope.getModelProviders();
- if (hasAdditionalMappingsFromIndependantModel(inputModelProviders, scope.getModelProviders())) {
+ if (hasAdditionalMappingsFromIndependantModel(inputModelProviders, getScope().getModelProviders())) {
// Prompt if the is a new model provider in the scope that is independant
// of any of the input mappings
prompt = true;
- } else if (scope.hasAdditonalResources()) {
+ } else if (getScope().hasAdditonalResources()) {
// We definitely need to prompt to indicate that additional resources
prompt = true;
} else if (inputModelProviders.length == 1) {
@@ -175,7 +172,7 @@ public abstract class ModelOperation extends TeamOperation {
// We need to prompt if the additional mappings are from the same model as
// the input or if they are from a model that has no relationship to the input model
String modelProviderId = inputModelProviders[0].getDescriptor().getId();
- ResourceMapping[] mappings = scope.getMappings();
+ ResourceMapping[] mappings = getScope().getMappings();
for (int i = 0; i < mappings.length; i++) {
ResourceMapping mapping = mappings[i];
if (inputScope.getTraversals(mapping) == null) {
@@ -197,7 +194,7 @@ public abstract class ModelOperation extends TeamOperation {
ModelProvider provider = inputModelProviders[i];
String id = provider.getDescriptor().getId();
ResourceMapping[] inputMappings = inputScope.getMappings(id);
- ResourceMapping[] scopeMappings = scope.getMappings(id);
+ ResourceMapping[] scopeMappings = getScope().getMappings(id);
if (inputMappings.length != scopeMappings.length) {
// There are more mappings for this provider.
// We need to see if any of the new ones overlap the old ones.
@@ -209,7 +206,7 @@ public abstract class ModelOperation extends TeamOperation {
// We need to prompt if the traversal for this mapping overlaps with
// the input mappings for the model provider
// TODO could check for project overlap first
- ResourceTraversal[] scopeTraversals = scope.getTraversals(mapping);
+ ResourceTraversal[] scopeTraversals = getScope().getTraversals(mapping);
ResourceTraversal[] inputModelTraversals = getTraversals(inputScope, inputMappings);
if (overlaps(scopeTraversals, inputModelTraversals)) {
prompt = true;
@@ -228,17 +225,6 @@ public abstract class ModelOperation extends TeamOperation {
}
/**
- * Indicate whether the local context should be used when preparing the scope.
- * Subclasses may wish to do this when initial creation of the
- * scope cannot be log running but they will perform future refreshes on the
- * scope that can be.
- * @return whether the local context should be used when preparing the scope
- */
- protected boolean isUseLocalContext() {
- return false;
- }
-
- /**
* Return a string to be used in the preview request on the scope prompt
* or <code>null</code> if a preview of the operation results is not possible.
* By default, <code>null</code> is returned but subclasses may override.
@@ -364,23 +350,6 @@ public abstract class ModelOperation extends TeamOperation {
}
/**
- * Return the scope manager used to build the scope of this
- * operation from the input mappings. By default, this method passes
- * the resource mapping context and the result of {@link #consultModelsWhenGeneratingScope()}
- * to the scope builder constructor.
- * <p>
- * This method can be overridden by subclasses.
- *
- * @return the scope builder used to build the scope of this
- * operation from the input mappings.
- */
- protected ResourceMappingScopeManager getScopeManager() {
- if (scope != null)
- return ((ResourceMappingScope)scope).getManager();
- return new ResourceMappingScopeManager(getResourceMappingContext(), consultModelsWhenGeneratingScope());
- }
-
- /**
* Prompt the user to inform them that additional resource mappings
* have been included in the operations.
* @param requestPreviewMessage message to be displayed for the option to force a preview
@@ -439,7 +408,7 @@ public abstract class ModelOperation extends TeamOperation {
* @return the scope of this operation
*/
public IResourceMappingScope getScope() {
- return scope;
+ return manager.getScope();
}
/**
@@ -451,32 +420,13 @@ public abstract class ModelOperation extends TeamOperation {
public boolean isPreviewRequested() {
return previewRequested;
}
-
- /**
- * Return whether the model providers should be consulted
- * when generating the scope. When <code>true</code>, the scope
- * generation process will consult any model providers to determine
- * if additional mappings, and hence additional resources, need to
- * be included in the operation. If <code>false</code>, the models
- * are not consulted and only the input mappings are included in the
- * scope. a value of <code>true</code> is returned by default.
- * @return whether the model providers should be consulted
- * when generating the scope
- */
- protected boolean consultModelsWhenGeneratingScope() {
- return true;
- }
-
+
/**
- * Return the resource mapping context used during the
- * scope generation and refresh process to determine
- * what resources are to be included in the resulting
- * synchronization context.
- * Subclasses may override.
- * @return the resource mapping context
+ * Return the scope manager for this operation.
+ * @return the scope manager for this operation.
*/
- protected ResourceMappingContext getResourceMappingContext() {
- return ResourceMappingContext.LOCAL_CONTEXT;
+ public IResourceMappingScopeManager getScopeManager() {
+ return manager;
}
}
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelParticipantMergeOperation.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelParticipantMergeOperation.java
new file mode 100644
index 000000000..86aa17c72
--- /dev/null
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelParticipantMergeOperation.java
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.ui.operations;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.core.resources.mapping.RemoteResourceMappingContext;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.jobs.*;
+import org.eclipse.team.core.mapping.*;
+import org.eclipse.team.internal.ui.TeamUIMessages;
+import org.eclipse.team.internal.ui.mapping.ModelParticipantPageDialog;
+import org.eclipse.team.ui.TeamUI;
+import org.eclipse.team.ui.synchronize.*;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.progress.WorkbenchJob;
+
+/**
+ * The steps of an optimistic merge operation are:
+ * <ol>
+ * <li>Obtain the selection to be operated on.
+ * <li>Determine the projection of the selection onto resources
+ * using resource mappings and traversals.
+ * <ul>
+ * <li>this will require traversals using both the ancestor and remote
+ * for three-way merges.
+ * <li>for model providers with registered merger, mapping set need
+ * not be expanded (this is tricky if one of the model providers doesn't
+ * have a merge but all others do).
+ * <li>if the model does not have a custom merger, ensure that additional
+ * mappings are included (i.e. for many model elements to one resource case)
+ * </ul>
+ * <li>Create a MergeContext for the merge
+ * <ul>
+ * <li>Determine the synchronization state of all resources
+ * covered by the input.
+ * <li>Pre-fetch the required contents.
+ * </ul>
+ * <li>Obtain and invoke the merger for each provider
+ * <ul>
+ * <li>This will auto-merge as much as possible
+ * <li>If everything was merged, cleanup and stop
+ * <li>Otherwise, a set of un-merged resource mappings is returned
+ * </ul>
+ * <li>Delegate manual merge to the model provider
+ * <ul>
+ * <li>This hands off the context to the manual merge
+ * <li>Once completed, the manual merge must clean up
+ * </ul>
+ * </ol>
+ *
+ * <p>
+ * Handle multiple model providers where one extends all others by using
+ * the top-most model provider. The assumption is that the model provider
+ * will delegate to lower level model providers when appropriate.
+ * <p>
+ * Special case to support sub-file merges.
+ * <ul>
+ * <li>Restrict when sub-file merging is supported
+ * <ul>
+ * <li>Only one provider involved (i.e. consulting participants results
+ * in participants that are from the model provider or below).
+ * <li>The provider has a custom auto and manual merger.
+ * </ul>
+ * <li>Prompt to warn when sub-file merging is not possible.
+ * <li>Need to display the additional elements that will be affected.
+ * This could be done in a diff tree or some other view. It needs to
+ * consider incoming changes including additions.
+ * </ul>
+ * <p>
+ * Special case to handle conflicting model providers.
+ * <ul>
+ * <li>Prompt user to indicate the conflict
+ * <li>Allow user to exclude one of the models?
+ * <li>Allow use to choose order of evaluation?
+ * <li>Support tabbed sync view
+ * </ul>
+ *
+ * <p>
+ * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
+ * part of a work in progress. There is a guarantee neither that this API will
+ * work nor that it will remain the same. Please do not use this API without
+ * consulting with the Platform/Team team.
+ * </p>
+ *
+ * @since 3.2
+ */
+public abstract class ModelParticipantMergeOperation extends ModelMergeOperation {
+
+ /**
+ * Status code that can be returned from the {@link #performMerge(IProgressMonitor)}
+ * method to indicate that a subclass would like to force a preview of the merge.
+ * The message of such a status should be ignored.
+ */
+ public static final int REQUEST_PREVIEW = 1024;
+
+ private ModelSynchronizeParticipant participant;
+ private boolean ownsParticipant = true;
+
+ /**
+ * Create a merge participant operation for the scope of the given manager.
+ * @param part the workbench part from which the merge was launched or <code>null</code>
+ * @param manager the scope manager
+ */
+ protected ModelParticipantMergeOperation(IWorkbenchPart part, IResourceMappingScopeManager manager) {
+ super(part, manager);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.operations.ModelMergeOperation#initializeContext(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected void initializeContext(IProgressMonitor monitor) throws CoreException {
+ if (participant == null) {
+ participant = createParticipant();
+ participant.getContext().refresh(getScope().getTraversals(),
+ RemoteResourceMappingContext.FILE_CONTENTS_REQUIRED, monitor);
+ try {
+ Platform.getJobManager().join(participant.getContext(), monitor);
+ } catch (InterruptedException e) {
+ throw new OperationCanceledException();
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.operations.ModelMergeOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ try {
+ super.execute(monitor);
+ } finally {
+ if (ownsParticipant && participant != null)
+ participant.dispose();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.operations.ModelMergeOperation#handlePreviewRequest()
+ */
+ protected void handlePreviewRequest() {
+ Job job = new WorkbenchJob(getJobName()) {
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ if (isPreviewInDialog()) {
+ CompareConfiguration cc = new CompareConfiguration();
+ ISynchronizePageConfiguration pageConfiguration = participant.createPageConfiguration();
+ // Restrict preview page to only support incomign and conflict modes
+ if (pageConfiguration.getComparisonType() == ISynchronizePageConfiguration.THREE_WAY) {
+ pageConfiguration.setSupportedModes(ISynchronizePageConfiguration.INCOMING_MODE | ISynchronizePageConfiguration.CONFLICTING_MODE);
+ pageConfiguration.setMode(ISynchronizePageConfiguration.INCOMING_MODE);
+ }
+ ParticipantPageDialog dialog = new ModelParticipantPageDialog(getShell(), participant, cc, pageConfiguration);
+ dialog.open();
+ } else {
+ ISynchronizeManager mgr = TeamUI.getSynchronizeManager();
+ ISynchronizeView view = mgr.showSynchronizeViewInActivePage();
+ mgr.addSynchronizeParticipants(new ISynchronizeParticipant[] {participant});
+ view.display(participant);
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.addJobChangeListener(new JobChangeAdapter() {
+ public void done(IJobChangeEvent event) {
+ // Ensure that the participant is disposed it it didn't go to the sync view
+ if (TeamUI.getSynchronizeManager().get(participant.getId(), participant.getSecondaryId()) == null)
+ participant.dispose();
+ }
+
+ });
+ ownsParticipant = false;
+ job.schedule();
+ }
+
+ /**
+ * Return whether previews should occur in a dialog or in the synchronize view.
+ * @return whether previews should occur in a dialog or in the synchronize view
+ */
+ protected boolean isPreviewInDialog() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.operations.ResourceMappingOperation#getContext()
+ */
+ protected ISynchronizationContext getContext() {
+ if (participant != null)
+ return participant.getContext();
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.operations.ResourceMappingOperation#getPreviewRequestMessage()
+ */
+ protected String getPreviewRequestMessage() {
+ if (!isPreviewRequested()) {
+ return TeamUIMessages.ResourceMappingMergeOperation_4;
+ }
+ return super.getPreviewRequestMessage();
+ }
+
+ /**
+ * Create the synchronize pariticipant to be used by this operation
+ * to preview changes. By default, a {@link ModelSynchronizeParticipant}
+ * is created using the scope manager ({@link #getScopeManager()}) context
+ * from ({@link #createMergeContext()}) and job name ({@link #getJobName()})
+ * of this operation. Subclasses may override this method.
+ * <p>
+ * Once created, it is the responsibility of the participant to dispose of the
+ * synchronization context when it is no longer needed.
+ * @return a newly created synchronize pariticipant to be used by this operation
+ */
+ protected ModelSynchronizeParticipant createParticipant() {
+ return ModelSynchronizeParticipant.createParticipant(getScopeManager(), createMergeContext(), getJobName());
+ }
+
+ /**
+ * Create a merge context for use by this operation. This method
+ * is not long running so the operation should not refresh the
+ * context or perform other long running operations in this thread.
+ * However the context may start initializing in another thread as long
+ * as the job used to perform the initialization belongs to the
+ * family that matches the context.
+ * @return a merge context for use by this operation
+ */
+ protected abstract ISynchronizationContext createMergeContext();
+
+}
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelSynchronizeParticipant.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelSynchronizeParticipant.java
index 3f81e313d..cb7e2986d 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelSynchronizeParticipant.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelSynchronizeParticipant.java
@@ -83,6 +83,7 @@ public class ModelSynchronizeParticipant extends
private final static String CTX_RESOURCE_PATH = "resource_path"; //$NON-NLS-1$
private ISynchronizationContext context;
+ private IResourceMappingScopeManager manager;
private boolean mergingEnabled = true;
protected SubscriberRefreshSchedule refreshSchedule;
private String description;
@@ -100,11 +101,12 @@ public class ModelSynchronizeParticipant extends
/**
* Create a participant for the given context
+ * @param manager the scope manager
* @param context the synchronization context
* @param name the name of the participant
*/
- public static ModelSynchronizeParticipant createParticipant(ISynchronizationContext context, String name) {
- return new ModelSynchronizeParticipant(context, name);
+ public static ModelSynchronizeParticipant createParticipant(IResourceMappingScopeManager manager, ISynchronizationContext context, String name) {
+ return new ModelSynchronizeParticipant(manager, context, name);
}
/*
@@ -112,7 +114,8 @@ public class ModelSynchronizeParticipant extends
* @param context the synchronization context
* @param name the name of the participant
*/
- private ModelSynchronizeParticipant(ISynchronizationContext context, String name) {
+ private ModelSynchronizeParticipant(IResourceMappingScopeManager manager, ISynchronizationContext context, String name) {
+ this.manager = manager;
initializeContext(context);
try {
setInitializationData(TeamUI.getSynchronizeManager().getParticipantDescriptor("org.eclipse.team.ui.synchronization_context_synchronize_participant")); //$NON-NLS-1$
@@ -128,7 +131,8 @@ public class ModelSynchronizeParticipant extends
* Create a participant for the given context
* @param context the synchronization context
*/
- public ModelSynchronizeParticipant(ISynchronizationContext context) {
+ public ModelSynchronizeParticipant(IResourceMappingScopeManager manager, ISynchronizationContext context) {
+ this.manager = manager;
initializeContext(context);
refreshSchedule = new SubscriberRefreshSchedule(createRefreshable());
}
@@ -221,6 +225,7 @@ public class ModelSynchronizeParticipant extends
* @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#dispose()
*/
public void dispose() {
+ manager.dispose();
context.dispose();
Platform.getJobManager().cancel(this);
refreshSchedule.dispose();
@@ -475,11 +480,10 @@ public class ModelSynchronizeParticipant extends
CompoundResourceTraversal traversal = new CompoundResourceTraversal();
traversal.addTraversals(traversals);
try {
- // When restoring, we can't do anything long running so we'll need to use the local content for everything
- NullProgressMonitor monitor = new NullProgressMonitor();
- ResourceMapping[] mappings = ResourceMappingScopeManager.getMappingsFromProviders(traversal.asTraversals(), ResourceMappingContext.LOCAL_CONTEXT, monitor);
- IResourceMappingScope scope = createScopeManager().prepareScope(mappings, true, monitor);
- IMergeContext context = restoreContext(scope, monitor);
+ // TODO: Need to restore mappings another way
+ ResourceMapping[] mappings = ResourceMappingScopeManager.getMappingsFromProviders(traversal.asTraversals(), ResourceMappingContext.LOCAL_CONTEXT, new NullProgressMonitor());
+ manager = createScopeManager(mappings);
+ IMergeContext context = restoreContext(manager);
initializeContext(context);
} catch (CoreException e) {
TeamUIPlugin.log(e);
@@ -491,12 +495,11 @@ public class ModelSynchronizeParticipant extends
* Recreate the context for this participant. This method is invoked when
* the participant is restored after a restart. Although it is provided
* with a progress monitor, long running operations should be avoided.
- * @param scope the restored scope
- * @param monitor a progress monitor
+ * @param manager the restored scope
* @return the context for this participant
* @throws CoreException
*/
- protected IMergeContext restoreContext(IResourceMappingScope scope, IProgressMonitor monitor) throws CoreException {
+ protected IMergeContext restoreContext(IResourceMappingScopeManager manager) throws CoreException {
throw new PartInitException(NLS.bind("Participant {0} is not capable of restoring its context", getId()));
}
@@ -506,11 +509,12 @@ public class ModelSynchronizeParticipant extends
* returns a scope manager that uses the local content.
* This method can be overridden by subclasses.
*
+ * @param mappings the restored mappings
* @return a scope manager that can be used to build the scope of this
* participant when it is restored after a restart
*/
- protected ResourceMappingScopeManager createScopeManager() {
- return new ResourceMappingScopeManager(ResourceMappingContext.LOCAL_CONTEXT, true);
+ protected IResourceMappingScopeManager createScopeManager(ResourceMapping[] mappings) {
+ return new ResourceMappingScopeManager(mappings, ResourceMappingContext.LOCAL_CONTEXT, true);
}
/* private */ void setRefreshSchedule(SubscriberRefreshSchedule schedule) {
@@ -573,5 +577,9 @@ public class ModelSynchronizeParticipant extends
setCurrentModel(targetBuffer);
return true;
}
+
+ public IResourceMappingScopeManager getScopeManager() {
+ return manager;
+ }
}
diff --git a/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/mapping/ScopeBuildingTests.java b/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/mapping/ScopeBuildingTests.java
index 5b4a00575..afd5e9bd9 100644
--- a/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/mapping/ScopeBuildingTests.java
+++ b/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/mapping/ScopeBuildingTests.java
@@ -14,14 +14,11 @@ import java.lang.reflect.InvocationTargetException;
import junit.framework.Test;
-import org.eclipse.core.resources.*;
-import org.eclipse.core.resources.mapping.ResourceMapping;
-import org.eclipse.core.resources.mapping.ResourceMappingContext;
-import org.eclipse.core.resources.mapping.ResourceTraversal;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.team.core.mapping.IResourceMappingScope;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.mapping.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.team.core.mapping.IResourceMappingScopeManager;
import org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager;
import org.eclipse.team.internal.core.mapping.ResourceMappingScope;
import org.eclipse.team.tests.core.TeamTest;
@@ -33,45 +30,39 @@ public class ScopeBuildingTests extends TeamTest {
protected static final String TEST_MODEL_PROVIDER_ID = "id1";
private class TestResourceMappingOperation extends ModelOperation {
-
- private ResourceMapping[] additionalMappings;
-
- protected TestResourceMappingOperation(ResourceMapping[] selectedMappings, ResourceMapping[] additionalMappings) {
- super(null, selectedMappings);
- this.additionalMappings = additionalMappings;
- }
- protected void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
- // Do nothing since we're just testing the scope build
- }
-
- protected void promptForInputChange(IProgressMonitor monitor) {
- // Throw an exception to indicate that a prompt was requested
- throw PROMPT_EXCEPTION;
- }
-
- protected ResourceMappingScopeManager getScopeManager() {
- return new ResourceMappingScopeManager(getResourceMappingContext(), false) {
- public IResourceMappingScope prepareScope(
- ResourceMapping[] selectedMappings,
- boolean useLocalContext,
+ protected TestResourceMappingOperation(ResourceMapping[] selectedMappings, final ResourceMapping[] additionalMappings) {
+ super(null, new ResourceMappingScopeManager(selectedMappings, ResourceMappingContext.LOCAL_CONTEXT, false) {
+ public void initialize(
IProgressMonitor monitor) throws CoreException {
-
- IResourceMappingScope resourceMappingScope = super.prepareScope(selectedMappings, useLocalContext, monitor);
+ super.initialize(monitor);
// Add the additional test mappings to the scope
for (int i = 0; i < additionalMappings.length; i++) {
ResourceMapping mapping = additionalMappings[i];
ResourceTraversal[] traversals = mapping.getTraversals(getContext(), monitor);
- ((ResourceMappingScope)resourceMappingScope).addMapping(mapping, traversals);
+ ((ResourceMappingScope)getScope()).addMapping(mapping, traversals);
// TODO: The additional mappings and additional resources boolean will not be set
// TODO: This may bring in mappings from the resources modle provider
}
- return resourceMappingScope;
}
- };
+ });
+ }
+ protected void endOperation(IProgressMonitor monitor) {
+ IResourceMappingScopeManager manager= getScopeManager();
+ manager.dispose();
+ super.endOperation(monitor);
+ }
+
+ protected void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ // Do nothing since we're just testing the scope build
}
+ protected void promptForInputChange(IProgressMonitor monitor) {
+ // Throw an exception to indicate that a prompt was requested
+ throw PROMPT_EXCEPTION;
+ }
}
+
public static Test suite() {
return suite(ScopeBuildingTests.class);
}
@@ -118,7 +109,7 @@ public class ScopeBuildingTests extends TeamTest {
public String getModelProviderId() {
return TEST_MODEL_PROVIDER_ID;
}
- public boolean isAncestorOf(ResourceMapping mapping) {
+ public boolean contains(ResourceMapping mapping) {
return false;
}
diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java
index ca5c66d8b..0a9095ad4 100644
--- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java
+++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java
@@ -23,7 +23,6 @@ import org.eclipse.core.tests.resources.ResourceTest;
import org.eclipse.swt.widgets.Display;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.subscribers.SubscriberResourceMappingContext;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.*;
import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
@@ -248,22 +247,18 @@ public class EclipseTest extends ResourceTest {
if (options == null)
options = Command.NO_LOCAL_OPTIONS;
if (options == Command.NO_LOCAL_OPTIONS) {
- executeHeadless(new ModelUpdateOperation(null, mappings, SubscriberResourceMappingContext.createContext(CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber())) {
+ executeHeadless(new ModelUpdateOperation(null, mappings, false) {
protected boolean isAttemptHeadlessMerge() {
return true;
}
- protected void showPreview(IProgressMonitor monitor) {
+ protected void handlePreviewRequest() {
// Don't preview anything
- getContext().dispose();
}
- protected void promptForNoChanges() {
+ protected void handleNoChanges() {
// Do nothing
}
- protected boolean consultModelsWhenGeneratingScope() {
- return false;
- }
- protected void promptForMergeFailure(IStatus status) {
- // Don't prompt
+ protected void handleValidationFailure(IStatus status) {
+ // Do nothing
}
});
} else {
@@ -282,21 +277,17 @@ public class EclipseTest extends ResourceTest {
}
protected void replace(ResourceMapping[] mappings) throws CVSException {
- executeHeadless(new ModelReplaceOperation(null, mappings, SubscriberResourceMappingContext.createContext(CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber())) {
+ executeHeadless(new ModelReplaceOperation(null, mappings, false) {
protected boolean promptForOverwrite() {
return true;
}
- protected void showPreview(IProgressMonitor monitor) {
- // Don't show a preview. If the repalce failed, the sync tests will detect the failure
- getContext().dispose();
- }
- protected void promptForNoChanges() {
- // Do nothing
+ protected void handlePreviewRequest() {
+ // Don't prompt
}
- protected boolean consultModelsWhenGeneratingScope() {
- return false;
+ protected void handleMergeFailure(IStatus status) {
+ // Don't prompt
}
- protected void promptForMergeFailure(IStatus status) {
+ protected void handleValidationFailure(IStatus status) {
// Don't prompt
}
});

Back to the top