diff options
21 files changed, 638 insertions, 735 deletions
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties index e55b417f1..55fef4983 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties @@ -123,3 +123,5 @@ SubscriberEventHandler.10=An internal error occurred processing subscriber event SubscriberEventHandler.11=An internal error occurred processing resource {0}: {1} CachedResourceVariant.0=There is no cached contents for resource {0}. SyncInfoTree.0=Sync info is missing for resource {0}. +ResourceVariantTreeSubscriber.1=Errors occurred during refresh of {0} +ResourceVariantTreeSubscriber.2=An error occurred refreshing {0}: {1} diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/AbstractResourceVariantTree.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/AbstractResourceVariantTree.java index c2a47c453..09a9e5387 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/AbstractResourceVariantTree.java +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/AbstractResourceVariantTree.java @@ -34,8 +34,16 @@ import org.eclipse.team.internal.core.Policy; /** - * This class provides the logic for refreshing and collecting the changes in - * a resource variant tree. + * An implemenation of <code>IResourceVariantTree</code> that provides the logic for + * refreshing the tree and collecting the results so they can be cached locally. + * This class does not perform the caching but relies on subclasses to do that by + * overriding the <code>setVariant</code> method. The subclass + * {@link ResourceVariantTree} does provide caching. + * + * @see IResourceVariantTree + * @see ResourceVariantTree + * + * @since 3.0 */ public abstract class AbstractResourceVariantTree implements IResourceVariantTree { @@ -168,36 +176,18 @@ public abstract class AbstractResourceVariantTree implements IResourceVariantTre * @return the resource variant corresponding to the given local resource */ protected abstract IResourceVariant fetchVariant(IResource resource, int depth, IProgressMonitor monitor) throws TeamException; - - private void collectChanges(IResource local, IResourceVariant remote, Collection changedResources, int depth, IProgressMonitor monitor) throws TeamException { - boolean changed = setVariant(local, remote); - if (changed) { - changedResources.add(local); - } - if (depth == IResource.DEPTH_ZERO) return; - Map children = mergedMembers(local, remote, monitor); - for (Iterator it = children.keySet().iterator(); it.hasNext();) { - IResource localChild = (IResource) it.next(); - IResourceVariant remoteChild = (IResourceVariant)children.get(localChild); - collectChanges(localChild, remoteChild, changedResources, - depth == IResource.DEPTH_INFINITE ? IResource.DEPTH_INFINITE : IResource.DEPTH_ZERO, - monitor); - } - - IResource[] cleared = collectedMembers(local, (IResource[]) children.keySet().toArray(new IResource[children.keySet().size()])); - changedResources.addAll(Arrays.asList(cleared)); - } - /** - * Method that is invoked during collection to let subclasses know which memebers + * Method that is invoked during collection to let subclasses know which members * were collected for the given resource. Implementors should purge any cached - * state for children of the local resource that are no longer members. any such resources + * state for children of the local resource that are no longer members. Any such resources * should be returned. * @param local the local resource * @param members the collected members * @return any resources that were previously collected whose state has been flushed */ - protected abstract IResource[] collectedMembers(IResource local, IResource[] members) throws TeamException; + protected IResource[] collectedMembers(IResource local, IResource[] members) throws TeamException { + return new IResource[0]; + } /** * Set the variant associated with the local resource to the newly fetched resource @@ -211,6 +201,25 @@ public abstract class AbstractResourceVariantTree implements IResourceVariantTre */ protected abstract boolean setVariant(IResource local, IResourceVariant remote) throws TeamException; + private void collectChanges(IResource local, IResourceVariant remote, Collection changedResources, int depth, IProgressMonitor monitor) throws TeamException { + boolean changed = setVariant(local, remote); + if (changed) { + changedResources.add(local); + } + if (depth == IResource.DEPTH_ZERO) return; + Map children = mergedMembers(local, remote, monitor); + for (Iterator it = children.keySet().iterator(); it.hasNext();) { + IResource localChild = (IResource) it.next(); + IResourceVariant remoteChild = (IResourceVariant)children.get(localChild); + collectChanges(localChild, remoteChild, changedResources, + depth == IResource.DEPTH_INFINITE ? IResource.DEPTH_INFINITE : IResource.DEPTH_ZERO, + monitor); + } + + IResource[] cleared = collectedMembers(local, (IResource[]) children.keySet().toArray(new IResource[children.keySet().size()])); + changedResources.addAll(Arrays.asList(cleared)); + } + private Map mergedMembers(IResource local, IResourceVariant remote, IProgressMonitor progress) throws TeamException { // {IResource -> IResourceVariant} diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantByteStore.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantByteStore.java index b24be5964..0e3e6a79e 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantByteStore.java +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantByteStore.java @@ -30,14 +30,16 @@ import org.eclipse.team.core.TeamException; * This is necessary because it is possible for the base tree to change in ways that * invalidate the stored remote variants. For example, if the local resources are moved * from the main trunck to a branch, any cached remote resource variants would be stale. - + * + * @since 3.0 */ public abstract class DescendantResourceVariantByteStore extends ResourceVariantByteStore { - ResourceVariantByteStore baseCache, remoteCache; + + ResourceVariantByteStore baseStore, remoteStore; public DescendantResourceVariantByteStore(ResourceVariantByteStore baseCache, ResourceVariantByteStore remoteCache) { - this.baseCache = baseCache; - this.remoteCache = remoteCache; + this.baseStore = baseCache; + this.remoteStore = remoteCache; } /** @@ -45,15 +47,15 @@ public abstract class DescendantResourceVariantByteStore extends ResourceVariant * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#dispose() */ public void dispose() { - remoteCache.dispose(); + remoteStore.dispose(); } /* (non-Javadoc) * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#getBytes(org.eclipse.core.resources.IResource) */ public byte[] getBytes(IResource resource) throws TeamException { - byte[] remoteBytes = remoteCache.getBytes(resource); - byte[] baseBytes = baseCache.getBytes(resource); + byte[] remoteBytes = remoteStore.getBytes(resource); + byte[] baseBytes = baseStore.getBytes(resource); if (baseBytes == null) { // There is no base so use the remote bytes return remoteBytes; @@ -82,12 +84,12 @@ public abstract class DescendantResourceVariantByteStore extends ResourceVariant * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#setBytes(org.eclipse.core.resources.IResource, byte[]) */ public boolean setBytes(IResource resource, byte[] bytes) throws TeamException { - byte[] baseBytes = baseCache.getBytes(resource); + byte[] baseBytes = baseStore.getBytes(resource); if (baseBytes != null && equals(baseBytes, bytes)) { // Remove the existing bytes so the base will be used (thus saving space) - return remoteCache.flushBytes(resource, IResource.DEPTH_ZERO); + return remoteStore.flushBytes(resource, IResource.DEPTH_ZERO); } else { - return remoteCache.setBytes(resource, bytes); + return remoteStore.setBytes(resource, bytes); } } @@ -95,7 +97,7 @@ public abstract class DescendantResourceVariantByteStore extends ResourceVariant * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#removeBytes(org.eclipse.core.resources.IResource, int) */ public boolean flushBytes(IResource resource, int depth) throws TeamException { - return remoteCache.flushBytes(resource, depth); + return remoteStore.flushBytes(resource, depth); } /** @@ -128,15 +130,15 @@ public abstract class DescendantResourceVariantByteStore extends ResourceVariant * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#setVariantDoesNotExist(org.eclipse.core.resources.IResource) */ public boolean deleteBytes(IResource resource) throws TeamException { - return remoteCache.deleteBytes(resource); + return remoteStore.deleteBytes(resource); } /** * Return the base tree from which the remote is descendant. * @return Returns the base tree. */ - protected ResourceVariantByteStore getBaseTree() { - return baseCache; + protected ResourceVariantByteStore getBaseStore() { + return baseStore; } /** @@ -144,23 +146,23 @@ public abstract class DescendantResourceVariantByteStore extends ResourceVariant * that differ from those in the base tree. * @return Returns the remote tree. */ - protected ResourceVariantByteStore getRemoteTree() { - return remoteCache; + protected ResourceVariantByteStore getRemoteStore() { + return remoteStore; } /* (non-Javadoc) * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#members(org.eclipse.core.resources.IResource) */ public IResource[] members(IResource resource) throws TeamException { - IResource[] remoteMembers = getRemoteTree().members(resource); - IResource[] baseMembers = getBaseTree().members(resource); + IResource[] remoteMembers = getRemoteStore().members(resource); + IResource[] baseMembers = getBaseStore().members(resource); Set members = new HashSet(); for (int i = 0; i < remoteMembers.length; i++) { members.add(remoteMembers[i]); } for (int i = 0; i < baseMembers.length; i++) { IResource member = baseMembers[i]; - // Add the base only inf the remote does not know about it + // Add the base only if the remote does not know about it // (i.e. hasn't marked it as deleted if (!isVariantKnown(member)) { members.add(member); @@ -168,5 +170,4 @@ public abstract class DescendantResourceVariantByteStore extends ResourceVariant } return (IResource[]) members.toArray(new IResource[members.size()]); } - } diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/IResourceVariantTree.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/IResourceVariantTree.java index cf8c6fcfe..3270c0048 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/IResourceVariantTree.java +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/IResourceVariantTree.java @@ -17,10 +17,21 @@ import org.eclipse.team.core.synchronize.IResourceVariant; /** * A handle that provides access to locally cached resource variants that * represent a resource line-up such as a project version or branch. + * <p> + * This interface is not intended to be implemented by clients. However, + * clients may subclass {@link AbstractResourceVariantTree} or {@link ResourceVariantTree}. + * </p> + * + * @since 3.0 */ public interface IResourceVariantTree { - public abstract IResource[] getRoots(); + /** + * Returns the list of root resources for which this tree may have resource + * variants. + * @return the list of root resources. + */ + public abstract IResource[] roots(); /** * Returns the members of the local resource that have resource variants in this tree. @@ -32,8 +43,21 @@ public interface IResourceVariantTree { */ public abstract IResource[] members(IResource resource) throws TeamException; + /** + * Return the resource variant corresponding to the local resource. Return + * <code>null</code> if there is no variant for the resource. + * @param resource the local resource + * @return the resource's variant in this tree + * @throws TeamException + */ public abstract IResourceVariant getResourceVariant(IResource resource) throws TeamException; + /** + * Return whether the local resource has a variant in this tree. + * @param resource the local resource + * @return <code>true</code> if the tree contains a variant for the resource + * @throws TeamException + */ public boolean hasResourceVariant(IResource resource) throws TeamException; /** @@ -47,8 +71,17 @@ public interface IResourceVariantTree { * as a result of the refresh * @throws TeamException */ - public abstract IResource[] refresh( + public IResource[] refresh( IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException; + + /** + * Flush any variants in the tree for the given resource to the depth + * specified. + * @param resource the resource + * @param depth the flush depth (one of <code>IResource.DEPTH_ZERO</code>, + * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>) + */ + public void flushVariants(IResource resource, int depth) throws TeamException; }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantByteStore.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantByteStore.java index 0ea8d7739..4c0f94356 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantByteStore.java +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantByteStore.java @@ -23,6 +23,10 @@ import org.eclipse.team.internal.core.Assert; * A <code>ResourceVariantByteStore</code> that caches the variant bytes using * the <code>org.eclipse.core.resources.ISynchronizer</code> so that * the tree is cached accross workbench invocations. + * <p> + * This class is not intended to be subclassed by clients + * + * @since 3.0 */ public class PersistantResourceVariantByteStore extends ResourceVariantByteStore { @@ -50,13 +54,6 @@ public class PersistantResourceVariantByteStore extends ResourceVariantByteStore } /** - * Convenience method that returns the Core <code>ISynchronizer</code>. - */ - protected ISynchronizer getSynchronizer() { - return ResourcesPlugin.getWorkspace().getSynchronizer(); - } - - /** * Return the qualified name that uniquely identifies this tree. * @return the qwualified name that uniquely identifies this tree. */ @@ -75,14 +72,6 @@ public class PersistantResourceVariantByteStore extends ResourceVariantByteStore } return syncBytes; } - - private byte[] internalGetSyncBytes(IResource resource) throws TeamException { - try { - return getSynchronizer().getSyncInfo(getSyncName(), resource); - } catch (CoreException e) { - throw TeamException.asTeamException(e); - } - } /* (non-Javadoc) * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#setBytes(org.eclipse.core.resources.IResource, byte[]) @@ -157,4 +146,15 @@ public class PersistantResourceVariantByteStore extends ResourceVariantByteStore } } + private ISynchronizer getSynchronizer() { + return ResourcesPlugin.getWorkspace().getSynchronizer(); + } + + private byte[] internalGetSyncBytes(IResource resource) throws TeamException { + try { + return getSynchronizer().getSyncInfo(getSyncName(), resource); + } catch (CoreException e) { + throw TeamException.asTeamException(e); + } + } } diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantByteStore.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantByteStore.java index bf51f5a6a..8d2d8e8e5 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantByteStore.java +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantByteStore.java @@ -27,6 +27,8 @@ import org.eclipse.team.core.TeamException; * The potential children of a resource variant are also accessed * by using the local handle that corresponds to the resource variant * (using the <code>members</code> method). + * + * @since 3.0 */ public abstract class ResourceVariantByteStore { diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTree.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTree.java index e9747b065..177a9d2ad 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTree.java +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTree.java @@ -10,26 +10,27 @@ *******************************************************************************/ package org.eclipse.team.internal.core.subscribers.caches; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.synchronize.IResourceVariant; /** - * This class provides the logic for refreshing a resource variant tree that - * is cached in a byte store. - * It provides the logic to traverse the local resource and variant resource trees in - * order to update the bytes stored in - * a <code>ResourceVariantByteStore</code>. It also accumulates and returns all local resources - * for which the corresponding resource variant has changed. + * Provides caching for a {@link AbstractResourceVariantTree} using a + * {@link ResourceVariantByteStore}. + * + * @see IResourceVariantTree + * @see AbstractResourceVariantTree + * @see ResourceVariantByteStore + * @since 3.0 */ public abstract class ResourceVariantTree extends AbstractResourceVariantTree { + private ResourceVariantByteStore store; + + protected ResourceVariantTree(ResourceVariantByteStore store) { + this.store = store; + } + /* (non-Javadoc) * @see org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree#members(org.eclipse.core.resources.IResource) */ @@ -44,6 +45,16 @@ public abstract class ResourceVariantTree extends AbstractResourceVariantTree { return getByteStore().getBytes(resource) != null; } + /** + * Flush any variants for the given resource to the depth specified. + * @param resource the local resource + * @param depth the depth of the flush + * @throws TeamException + */ + public void flushVariants(IResource resource, int depth) throws TeamException { + getByteStore().flushBytes(resource, depth); + } + /* (non-Javadoc) * @see org.eclipse.team.internal.core.subscribers.caches.AbstractResourceVariantTree#setVariant(org.eclipse.core.resources.IResource, org.eclipse.team.core.synchronize.IResourceVariant) */ @@ -59,74 +70,7 @@ public abstract class ResourceVariantTree extends AbstractResourceVariantTree { return changed; } - /** - * Get the bytes to be stored in the <code>ResourceVariantByteStore</code> - * from the given resource variant. - * @param local the local resource - * @param remote the corresponding resource variant handle - * @return the bytes for the resource variant. - */ - protected abstract byte[] getBytes(IResource local, IResourceVariant remote) throws TeamException; - /* (non-Javadoc) - * @see org.eclipse.team.internal.core.subscribers.caches.AbstractResourceVariantTree#collectedMembers(org.eclipse.core.resources.IResource, org.eclipse.core.resources.IResource[]) - */ - protected IResource[] collectedMembers(IResource local, IResource[] members) throws TeamException { - // Look for resources that have sync bytes but are not in the resources we care about - IResource[] resources = getStoredMembers(local); - List children = new ArrayList(); - List changedResources = new ArrayList(); - children.addAll(Arrays.asList(members)); - for (int i = 0; i < resources.length; i++) { - IResource resource = resources[i]; - if (!children.contains(resource)) { - // These sync bytes are stale. Purge them - flushVariants(resource, IResource.DEPTH_INFINITE); - changedResources.add(resource); - } - } - return (IResource[]) changedResources.toArray(new IResource[changedResources.size()]); - } - - /** - * Flush any variants for the given resource to the depth specified - * @param resource the local resource - * @param depth the depth of the flush - * @throws TeamException - */ - private void flushVariants(IResource resource, int depth) throws TeamException { - getByteStore().flushBytes(resource, depth); - } - - /** - * Return all the members of that have resource variant information associated with them, - * such as members that are explicitly flagged as not having a resource variant. This list - * is used by the collection algorithm to flush variants for which there is no local and - * no remote. - * @param local the locla resource - * @return the local children that have resource variant information cached - * @throws TeamException - */ - private IResource[] getStoredMembers(IResource local) throws TeamException { - try { - if (local.getType() != IResource.FILE && (local.exists() || local.isPhantom())) { - // TODO: Not very generic! - IResource[] allChildren = ((IContainer)local).members(true /* include phantoms */); - List childrenWithSyncBytes = new ArrayList(); - for (int i = 0; i < allChildren.length; i++) { - IResource resource = allChildren[i]; - if (getByteStore().getBytes(resource) != null) { - childrenWithSyncBytes.add(resource); - } - } - return (IResource[]) childrenWithSyncBytes.toArray( - new IResource[childrenWithSyncBytes.size()]); - } - } catch (CoreException e) { - throw TeamException.asTeamException(e); - } - return new IResource[0]; - } /** * Get the byte store that is used to cache the serialization bytes @@ -134,12 +78,16 @@ public abstract class ResourceVariantTree extends AbstractResourceVariantTree { * to reduce the memory footprint of the tree. * @return the resource variant tree that is being refreshed. */ - protected abstract ResourceVariantByteStore getByteStore(); + protected ResourceVariantByteStore getByteStore() { + return store; + } /** - * @param project + * Get the bytes to be stored in the <code>ResourceVariantByteStore</code> + * from the given resource variant. + * @param local the local resource + * @param remote the corresponding resource variant handle + * @return the bytes for the resource variant. */ - public void removeRoot(IResource resource) throws TeamException { - getByteStore().flushBytes(resource, IResource.DEPTH_INFINITE); - } + protected abstract byte[] getBytes(IResource local, IResourceVariant remote) throws TeamException; } diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTreeSubscriber.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTreeSubscriber.java new file mode 100644 index 000000000..cac2b09a6 --- /dev/null +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTreeSubscriber.java @@ -0,0 +1,181 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.internal.core.subscribers.caches; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.TeamStatus; +import org.eclipse.team.core.subscribers.Subscriber; +import org.eclipse.team.core.subscribers.SubscriberChangeEvent; +import org.eclipse.team.core.synchronize.IResourceVariant; +import org.eclipse.team.core.synchronize.SyncInfo; +import org.eclipse.team.internal.core.Policy; +import org.eclipse.team.internal.core.TeamPlugin; + +/** + * A specialization of Subscriber that provides some additional logic for creating + * <code>SyncInfo</code> from <code>IResourceVariant</code> instances. + * The <code>members()</code> also assumes that remote + * instances are stored in the <code>ISynchronizer</code>. + */ +public abstract class ResourceVariantTreeSubscriber extends Subscriber { + + /* (non-Javadoc) + * @see org.eclipse.team.core.subscribers.Subscriber#getSyncInfo(org.eclipse.core.resources.IResource) + */ + public SyncInfo getSyncInfo(IResource resource) throws TeamException { + if (!isSupervised(resource)) return null; + IResourceVariant remoteResource = getRemoteTree().getResourceVariant(resource); + IResourceVariant baseResource; + if (getResourceComparator().isThreeWay()) { + baseResource= getBaseTree().getResourceVariant(resource); + } else { + baseResource = null; + } + return getSyncInfo(resource, baseResource, remoteResource); + } + + /** + * Method that creates an instance of SyncInfo for the provider local, base and remote + * resource variants. + * Can be overiden by subclasses. + * @param local the local resource + * @param base the base resource variant or <code>null</code> + * @param remote the remote resource variant or <code>null</code> + * @return the <code>SyncInfo</code> containing the provided resources + */ + protected SyncInfo getSyncInfo(IResource local, IResourceVariant base, IResourceVariant remote) throws TeamException { + SyncInfo info = new SyncInfo(local, base, remote, this.getResourceComparator()); + info.init(); + return info; + } + + public IResource[] members(IResource resource) throws TeamException { + if(resource.getType() == IResource.FILE) { + return new IResource[0]; + } + try { + Set allMembers = new HashSet(); + try { + allMembers.addAll(Arrays.asList(((IContainer)resource).members())); + } catch (CoreException e) { + if (e.getStatus().getCode() == IResourceStatus.RESOURCE_NOT_FOUND) { + // The resource is no longer exists so ignore the exception + } else { + throw e; + } + } + allMembers.addAll(Arrays.asList(internalMembers(getRemoteTree(), resource))); + if (getResourceComparator().isThreeWay()) { + allMembers.addAll(Arrays.asList(internalMembers(getBaseTree(), resource))); + } + for (Iterator iterator = allMembers.iterator(); iterator.hasNext();) { + IResource member = (IResource) iterator.next(); + if(!member.exists() && !getRemoteTree().hasResourceVariant(member)) { + // Remove deletion conflicts + iterator.remove(); + } else if (!isSupervised(resource)) { + // Remove unsupervised resources + iterator.remove(); + } + } + return (IResource[]) allMembers.toArray(new IResource[allMembers.size()]); + } catch (CoreException e) { + throw TeamException.asTeamException(e); + } + } + + /* (non-Javadoc) + * @see org.eclipse.team.core.sync.ISyncTreeSubscriber#refresh(org.eclipse.core.resources.IResource[], int, org.eclipse.core.runtime.IProgressMonitor) + */ + public void refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { + monitor = Policy.monitorFor(monitor); + List errors = new ArrayList(); + try { + monitor.beginTask(null, 100 * resources.length); + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + IStatus status = refresh(resource, depth, Policy.subMonitorFor(monitor, 100)); + if (!status.isOK()) { + errors.add(status); + } + } + } finally { + monitor.done(); + } + if (!errors.isEmpty()) { + throw new TeamException(new MultiStatus(TeamPlugin.ID, 0, + (IStatus[]) errors.toArray(new IStatus[errors.size()]), + Policy.bind("ResourceVariantTreeSubscriber.1", getName()), null)); //$NON-NLS-1$ + } + } + + protected IStatus refresh(IResource resource, int depth, IProgressMonitor monitor) { + monitor = Policy.monitorFor(monitor); + try { + monitor.beginTask(null, IProgressMonitor.UNKNOWN); + Set allChanges = new HashSet(); + IResource[] remoteChanges = getRemoteTree().refresh(new IResource[] {resource}, depth, Policy.subMonitorFor(monitor, IProgressMonitor.UNKNOWN)); + allChanges.addAll(Arrays.asList(remoteChanges)); + if (getResourceComparator().isThreeWay()) { + IResource[] baseChanges = getBaseTree().refresh(new IResource[] {resource}, depth, Policy.subMonitorFor(monitor, IProgressMonitor.UNKNOWN)); + allChanges.addAll(Arrays.asList(baseChanges)); + } + IResource[] changedResources = (IResource[]) allChanges.toArray(new IResource[allChanges.size()]); + fireTeamResourceChange(SubscriberChangeEvent.asSyncChangedDeltas(this, changedResources)); + return Status.OK_STATUS; + } catch (TeamException e) { + return new TeamStatus(IStatus.ERROR, TeamPlugin.ID, 0, Policy.bind("ResourceVariantTreeSubscriber.2", resource.getFullPath().toString(), e.getMessage()), e, resource); //$NON-NLS-1$ + } finally { + monitor.done(); + } + } + + /** + * Return the base resource variant tree. + */ + protected abstract IResourceVariantTree getBaseTree(); + + /** + * Return the remote resource variant tree. + */ + protected abstract IResourceVariantTree getRemoteTree(); + + private IResource[] internalMembers(IResourceVariantTree tree, IResource resource) throws TeamException, CoreException { + // Filter and return only phantoms associated with the remote synchronizer. + IResource[] members; + try { + members = tree.members(resource); + } catch (CoreException e) { + if (!isSupervised(resource) || e.getStatus().getCode() == IResourceStatus.RESOURCE_NOT_FOUND) { + // The resource is no longer supervised or doesn't exist in any form + // so ignore the exception and return that there are no members + return new IResource[0]; + } + throw e; + } + return members; + } +} diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantByteStore.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantByteStore.java index cc32236cc..4aa20c7b2 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantByteStore.java +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantByteStore.java @@ -20,47 +20,23 @@ import org.eclipse.team.internal.core.Assert; /** * A <code>ResourceVariantByteStore</code> that caches the variant bytes in memory * and does not persist them over workbench invocations. + * <p> + * This class is not intended to be subclassed by clients. + * + * @since 3.0 */ public class SessionResourceVariantByteStore extends ResourceVariantByteStore { private static final byte[] NO_REMOTE = new byte[0]; - - private Map syncBytesCache = new HashMap(); private Map membersCache = new HashMap(); - - private Map getSyncBytesCache() { - return syncBytesCache; - } - - private byte[] internalGetSyncBytes(IResource resource) { - return (byte[])getSyncBytesCache().get(resource); - } - private void internalAddToParent(IResource resource) { - IContainer parent = resource.getParent(); - if (parent == null) return; - List members = (List)membersCache.get(parent); - if (members == null) { - members = new ArrayList(); - membersCache.put(parent, members); - } - members.add(resource); - } - - private void internalSetSyncInfo(IResource resource, byte[] bytes) { - getSyncBytesCache().put(resource, bytes); - internalAddToParent(resource); - } + private Map syncBytesCache = new HashMap(); - private void internalRemoveFromParent(IResource resource) { - IContainer parent = resource.getParent(); - List members = (List)membersCache.get(parent); - if (members != null) { - members.remove(resource); - if (members.isEmpty()) { - membersCache.remove(parent); - } - } + /* (non-Javadoc) + * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#setVariantDoesNotExist(org.eclipse.core.resources.IResource) + */ + public boolean deleteBytes(IResource resource) throws TeamException { + return flushBytes(resource, IResource.DEPTH_ZERO); } /* (non-Javadoc) @@ -72,30 +48,6 @@ public class SessionResourceVariantByteStore extends ResourceVariantByteStore { } /* (non-Javadoc) - * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#getBytes(org.eclipse.core.resources.IResource) - */ - public byte[] getBytes(IResource resource) throws TeamException { - byte[] syncBytes = internalGetSyncBytes(resource); - if (syncBytes != null && equals(syncBytes, NO_REMOTE)) { - // If it is known that there is no remote, return null - return null; - } - return syncBytes; - } - - /* - * (non-Javadoc) - * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#setBytes(org.eclipse.core.resources.IResource, byte[]) - */ - public boolean setBytes(IResource resource, byte[] bytes) throws TeamException { - Assert.isNotNull(bytes); - byte[] oldBytes = internalGetSyncBytes(resource); - if (oldBytes != null && equals(oldBytes, bytes)) return false; - internalSetSyncInfo(resource, bytes); - return true; - } - - /* (non-Javadoc) * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#removeBytes(org.eclipse.core.resources.IResource, int) */ public boolean flushBytes(IResource resource, int depth) throws TeamException { @@ -115,6 +67,26 @@ public class SessionResourceVariantByteStore extends ResourceVariantByteStore { } /* (non-Javadoc) + * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#getBytes(org.eclipse.core.resources.IResource) + */ + public byte[] getBytes(IResource resource) throws TeamException { + byte[] syncBytes = internalGetSyncBytes(resource); + if (syncBytes != null && equals(syncBytes, NO_REMOTE)) { + // If it is known that there is no remote, return null + return null; + } + return syncBytes; + } + + /** + * Return <code>true</code> if no bytes are contained in this tree. + * @return <code>true</code> if no bytes are contained in this tree. + */ + public boolean isEmpty() { + return syncBytesCache.isEmpty(); + } + + /* (non-Javadoc) * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#members(org.eclipse.core.resources.IResource) */ public IResource[] members(IResource resource) { @@ -125,18 +97,50 @@ public class SessionResourceVariantByteStore extends ResourceVariantByteStore { return (IResource[]) members.toArray(new IResource[members.size()]); } - /* (non-Javadoc) - * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#setVariantDoesNotExist(org.eclipse.core.resources.IResource) + /* + * (non-Javadoc) + * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#setBytes(org.eclipse.core.resources.IResource, byte[]) */ - public boolean deleteBytes(IResource resource) throws TeamException { - return flushBytes(resource, IResource.DEPTH_ZERO); + public boolean setBytes(IResource resource, byte[] bytes) throws TeamException { + Assert.isNotNull(bytes); + byte[] oldBytes = internalGetSyncBytes(resource); + if (oldBytes != null && equals(oldBytes, bytes)) return false; + internalSetSyncInfo(resource, bytes); + return true; + } + + private Map getSyncBytesCache() { + return syncBytesCache; + } + + private void internalAddToParent(IResource resource) { + IContainer parent = resource.getParent(); + if (parent == null) return; + List members = (List)membersCache.get(parent); + if (members == null) { + members = new ArrayList(); + membersCache.put(parent, members); + } + members.add(resource); + } + + private byte[] internalGetSyncBytes(IResource resource) { + return (byte[])getSyncBytesCache().get(resource); } - /** - * Return <code>true</code> if no bytes are contained in this tree. - * @return <code>true</code> if no bytes are contained in this tree. - */ - public boolean isEmpty() { - return syncBytesCache.isEmpty(); + private void internalRemoveFromParent(IResource resource) { + IContainer parent = resource.getParent(); + List members = (List)membersCache.get(parent); + if (members != null) { + members.remove(resource); + if (members.isEmpty()) { + membersCache.remove(parent); + } + } + } + + private void internalSetSyncInfo(IResource resource, byte[] bytes) { + getSyncBytesCache().put(resource, bytes); + internalAddToParent(resource); } } diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SyncTreeSubscriber.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SyncTreeSubscriber.java deleted file mode 100644 index 6b68087d9..000000000 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SyncTreeSubscriber.java +++ /dev/null @@ -1,112 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2003 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.team.internal.core.subscribers.caches; - -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.core.resources.*; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.team.core.TeamException; -import org.eclipse.team.core.subscribers.Subscriber; -import org.eclipse.team.core.synchronize.*; - -/** - * A specialization of Subscriber that provides some additional logic for creating - * <code>SyncInfo</code> from <code>IResourceVariant</code> instances. - * The <code>members()</code> also assumes that remote - * instances are stored in the <code>ISynchronizer</code>. - */ -public abstract class SyncTreeSubscriber extends Subscriber { - - public abstract IResourceVariant getRemoteResource(IResource resource) throws TeamException; - - public abstract IResourceVariant getBaseResource(IResource resource) throws TeamException; - - /** - * Return whether the given local resource has a corresponding remote resource - * @param resource the local resource - * @return <code>true</code> if the locla resource has a corresponding remote - */ - protected abstract boolean hasRemote(IResource resource) throws TeamException; - - public SyncInfo getSyncInfo(IResource resource) throws TeamException { - if (!isSupervised(resource)) return null; - IResourceVariant remoteResource = getRemoteResource(resource); - IResourceVariant baseResource; - if (getResourceComparator().isThreeWay()) { - baseResource= getBaseResource(resource); - } else { - baseResource = null; - } - return getSyncInfo(resource, baseResource, remoteResource); - } - - /** - * @return - */ - public abstract IResourceVariantComparator getResourceComparator(); - - /** - * Method that creates an instance of SyncInfo for the provider local, base and remote. - * Can be overiden by subclasses. - * @param local - * @param base - * @param remote - * @param monitor - * @return - */ - protected SyncInfo getSyncInfo(IResource local, IResourceVariant base, IResourceVariant remote) throws TeamException { - SyncInfo info = new SyncInfo(local, base, remote, this.getResourceComparator()); - info.init(); - return info; - } - - public IResource[] members(IResource resource) throws TeamException { - if(resource.getType() == IResource.FILE) { - return new IResource[0]; - } - try { - // Filter and return only phantoms associated with the remote synchronizer. - IResource[] members; - try { - members = ((IContainer)resource).members(true /* include phantoms */); - } catch (CoreException e) { - if (!isSupervised(resource) || e.getStatus().getCode() == IResourceStatus.RESOURCE_NOT_FOUND) { - // The resource is no longer supervised or doesn't exist in any form - // so ignore the exception and return that there are no members - return new IResource[0]; - } - throw e; - } - List filteredMembers = new ArrayList(members.length); - for (int i = 0; i < members.length; i++) { - IResource member = members[i]; - - // TODO: consider that there may be several sync states on this resource. There - // should instead be a method to check for the existance of a set of sync types on - // a resource. - if(member.isPhantom() && !hasRemote(member)) { - continue; - } - - // TODO: Is this a valid use of isSupervised - if (isSupervised(resource)) { - filteredMembers.add(member); - } - } - return (IResource[]) filteredMembers.toArray(new IResource[filteredMembers.size()]); - } catch (CoreException e) { - throw TeamException.asTeamException(e); - } - } - -} diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCompareSubscriber.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCompareSubscriber.java index 9612ed6c1..19839be0a 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCompareSubscriber.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCompareSubscriber.java @@ -25,7 +25,7 @@ import org.eclipse.team.core.subscribers.ISubscriberChangeListener; import org.eclipse.team.core.subscribers.SubscriberChangeEvent; import org.eclipse.team.internal.ccvs.core.syncinfo.CVSResourceVariantTree; import org.eclipse.team.internal.ccvs.core.syncinfo.MultiTagResourceVariantTree; -import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree; +import org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree; import org.eclipse.team.internal.core.subscribers.caches.SessionResourceVariantByteStore; /** @@ -75,7 +75,7 @@ public class CVSCompareSubscriber extends CVSSyncTreeSubscriber implements ISubs /* (non-Javadoc) * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getBaseSynchronizationCache() */ - protected ResourceVariantTree getBaseTree() { + protected IResourceVariantTree getBaseTree() { // No base cache needed since it's a two way compare return null; } @@ -83,7 +83,7 @@ public class CVSCompareSubscriber extends CVSSyncTreeSubscriber implements ISubs /* (non-Javadoc) * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getRemoteSynchronizationCache() */ - protected ResourceVariantTree getRemoteTree() { + protected IResourceVariantTree getRemoteTree() { return tree; } @@ -136,7 +136,7 @@ public class CVSCompareSubscriber extends CVSSyncTreeSubscriber implements ISubs // The root is no longer managed by CVS removals.add(root); try { - tree.removeRoot(root); + tree.flushVariants(root, IResource.DEPTH_INFINITE); } catch (TeamException e) { CVSProviderPlugin.log(e); } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java index b26d2e9ed..2d8cd74b7 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java @@ -38,8 +38,8 @@ import org.eclipse.team.internal.ccvs.core.resources.RemoteFile; import org.eclipse.team.internal.ccvs.core.syncinfo.CVSResourceVariantTree; import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; import org.eclipse.team.internal.ccvs.core.util.Util; +import org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree; import org.eclipse.team.internal.core.subscribers.caches.PersistantResourceVariantByteStore; -import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree; /** * A CVSMergeSubscriber is responsible for maintaining the remote trees for a merge into @@ -90,9 +90,54 @@ public class CVSMergeSubscriber extends CVSSyncTreeSubscriber implements IResour QualifiedName id = getId(); String syncKeyPrefix = id.getLocalName(); PersistantResourceVariantByteStore remoteSynchronizer = new PersistantResourceVariantByteStore(new QualifiedName(SYNC_KEY_QUALIFIER, syncKeyPrefix + end.getName())); - remoteTree = new CVSResourceVariantTree(remoteSynchronizer, getRemoteTag(), getCacheFileContentsHint()); + remoteTree = new CVSResourceVariantTree(remoteSynchronizer, getEndTag(), getCacheFileContentsHint()) { + public IResource[] refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { + // Override refresh to compare file contents + monitor.beginTask(null, 100); + try { + IResource[] refreshed = super.refresh(resources, depth, monitor); + compareWithRemote(refreshed, Policy.subMonitorFor(monitor, 50)); + return refreshed; + } finally { + monitor.done(); + } + } + }; PersistantResourceVariantByteStore baseSynchronizer = new PersistantResourceVariantByteStore(new QualifiedName(SYNC_KEY_QUALIFIER, syncKeyPrefix + start.getName())); - baseTree = new CVSResourceVariantTree(baseSynchronizer, getBaseTag(), getCacheFileContentsHint()); + baseTree = new CVSResourceVariantTree(baseSynchronizer, getStartTag(), getCacheFileContentsHint()) { + public IResource[] refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { + // Only refresh the base of a resource once as it should not change + List unrefreshed = new ArrayList(); + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + if (!getBaseByteStore().isVariantKnown(resource)) { + unrefreshed.add(resource); + } + } + if (unrefreshed.isEmpty()) { + monitor.done(); + return new IResource[0]; + } + IResource[] refreshed = super.refresh((IResource[]) unrefreshed.toArray(new IResource[unrefreshed.size()]), depth, monitor); + return refreshed; + } + public IResourceVariant getResourceVariant(IResource resource) throws TeamException { + // Use the merged bytes for the base if there are some + byte[] mergedBytes = mergedSynchronizer.getBytes(resource); + if (mergedBytes != null) { + byte[] parentBytes = getBaseByteStore().getBytes(resource.getParent()); + if (parentBytes != null) { + return RemoteFile.fromBytes(resource, mergedBytes, parentBytes); + } + } else { + // A deletion was merged so return null for the base + if (mergedSynchronizer.isVariantKnown(resource)) { + return null; + } + } + return super.getResourceVariant(resource); + } + }; mergedSynchronizer = new PersistantResourceVariantByteStore(new QualifiedName(SYNC_KEY_QUALIFIER, syncKeyPrefix + "0merged")); //$NON-NLS-1$ ResourcesPlugin.getWorkspace().addResourceChangeListener(this); @@ -238,30 +283,16 @@ public class CVSMergeSubscriber extends CVSSyncTreeSubscriber implements IResour } /* (non-Javadoc) - * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getRemoteTag() - */ - protected CVSTag getRemoteTag() { - return getEndTag(); - } - - /* (non-Javadoc) - * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getBaseTag() - */ - protected CVSTag getBaseTag() { - return getStartTag(); - } - - /* (non-Javadoc) * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getBaseSynchronizationCache() */ - protected ResourceVariantTree getBaseTree() { + protected IResourceVariantTree getBaseTree() { return baseTree; } /* (non-Javadoc) * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getRemoteSynchronizationCache() */ - protected ResourceVariantTree getRemoteTree() { + protected IResourceVariantTree getRemoteTree() { return remoteTree; } @@ -269,40 +300,6 @@ public class CVSMergeSubscriber extends CVSSyncTreeSubscriber implements IResour return true; } - /* (non-Javadoc) - * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#refreshBase(org.eclipse.core.resources.IResource[], int, org.eclipse.core.runtime.IProgressMonitor) - */ - protected IResource[] refreshBase(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { - // Only refresh the base of a resource once as it should not change - List unrefreshed = new ArrayList(); - for (int i = 0; i < resources.length; i++) { - IResource resource = resources[i]; - if (!getBaseByteStore().isVariantKnown(resource)) { - unrefreshed.add(resource); - } - } - if (unrefreshed.isEmpty()) { - monitor.done(); - return new IResource[0]; - } - IResource[] refreshed = super.refreshBase((IResource[]) unrefreshed.toArray(new IResource[unrefreshed.size()]), depth, monitor); - return refreshed; - } - - /* (non-Javadoc) - * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#refreshRemote(org.eclipse.core.resources.IResource[], int, org.eclipse.core.runtime.IProgressMonitor) - */ - protected IResource[] refreshRemote(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { - monitor.beginTask(null, 100); - try { - IResource[] refreshed = super.refreshRemote(resources, depth, Policy.subMonitorFor(monitor, 50)); - compareWithRemote(refreshed, Policy.subMonitorFor(monitor, 50)); - return refreshed; - } finally { - monitor.done(); - } - } - /* * Mark as merged any local resources whose contents match that of the remote resource. */ @@ -331,26 +328,6 @@ public class CVSMergeSubscriber extends CVSSyncTreeSubscriber implements IResour monitor.done(); } - /* (non-Javadoc) - * @see org.eclipse.team.core.subscribers.utils.SyncTreeSubscriber#getBaseResource(org.eclipse.core.resources.IResource) - */ - public IResourceVariant getBaseResource(IResource resource) throws TeamException { - // Use the merged bytes for the base if there are some - byte[] mergedBytes = mergedSynchronizer.getBytes(resource); - if (mergedBytes != null) { - byte[] parentBytes = getBaseByteStore().getBytes(resource.getParent()); - if (parentBytes != null) { - return RemoteFile.fromBytes(resource, mergedBytes, parentBytes); - } - } else { - // A deletion was merged so return null for the base - if (mergedSynchronizer.isVariantKnown(resource)) { - return null; - } - } - return super.getBaseResource(resource); - } - /* * TODO: Should not need to access this here */ @@ -372,7 +349,7 @@ public class CVSMergeSubscriber extends CVSSyncTreeSubscriber implements IResour if(this == other) return true; if(! (other instanceof CVSMergeSubscriber)) return false; CVSMergeSubscriber s = (CVSMergeSubscriber)other; - return getRemoteTag().equals(s.getRemoteTag()) && - getBaseTag().equals(s.getBaseTag()) && rootsEqual(s); + return getEndTag().equals(s.getEndTag()) && + getStartTag().equals(s.getStartTag()) && rootsEqual(s); } }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSRevisionNumberCompareCriteria.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSRevisionNumberCompareCriteria.java index 519be9459..23ef83af0 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSRevisionNumberCompareCriteria.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSRevisionNumberCompareCriteria.java @@ -22,10 +22,10 @@ import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; */ public class CVSRevisionNumberCompareCriteria implements IResourceVariantComparator { - private CVSSyncTreeSubscriber subscriber; + private boolean isThreeWay; - public CVSRevisionNumberCompareCriteria(CVSSyncTreeSubscriber subscriber) { - this.subscriber = subscriber; + public CVSRevisionNumberCompareCriteria(boolean isThreeWay) { + this.isThreeWay = isThreeWay; } /* (non-Javadoc) @@ -99,6 +99,6 @@ import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; * @see org.eclipse.team.core.subscribers.ISubscriberResourceComparator#isThreeWay() */ public boolean isThreeWay() { - return subscriber.isThreeWay(); + return isThreeWay; } } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncInfo.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncInfo.java index 5f06cdb1e..a603c7950 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncInfo.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncInfo.java @@ -22,7 +22,7 @@ import org.eclipse.team.internal.ccvs.core.resources.*; import org.eclipse.team.internal.ccvs.core.syncinfo.*; import org.eclipse.team.internal.ccvs.core.util.Assert; import org.eclipse.team.internal.ccvs.core.Policy; -import org.eclipse.team.internal.core.subscribers.caches.SyncTreeSubscriber; +import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTreeSubscriber; /** * CVSSyncInfo @@ -40,7 +40,7 @@ public class CVSSyncInfo extends SyncInfo { private Subscriber subscriber; public CVSSyncInfo(IResource local, IResourceVariant base, IResourceVariant remote, Subscriber subscriber) { - super(local, base, remote, ((SyncTreeSubscriber)subscriber).getResourceComparator()); + super(local, base, remote, ((ResourceVariantTreeSubscriber)subscriber).getResourceComparator()); this.subscriber = subscriber; } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java index 9bcba4395..1cbbca7a5 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java @@ -10,40 +10,27 @@ *******************************************************************************/ package org.eclipse.team.internal.ccvs.core; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; -import java.util.Iterator; -import java.util.List; import java.util.Set; -import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceStatus; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.QualifiedName; -import org.eclipse.core.runtime.Status; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.subscribers.Subscriber; -import org.eclipse.team.core.subscribers.SubscriberChangeEvent; import org.eclipse.team.core.synchronize.IResourceVariant; import org.eclipse.team.core.synchronize.IResourceVariantComparator; import org.eclipse.team.core.synchronize.SyncInfo; import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; -import org.eclipse.team.internal.core.subscribers.caches.PersistantResourceVariantByteStore; -import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore; -import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree; -import org.eclipse.team.internal.core.subscribers.caches.SyncTreeSubscriber; +import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTreeSubscriber; /** * This class provides common funtionality for three way sychronizing * for CVS. */ -public abstract class CVSSyncTreeSubscriber extends SyncTreeSubscriber { +public abstract class CVSSyncTreeSubscriber extends ResourceVariantTreeSubscriber { public static final String SYNC_KEY_QUALIFIER = "org.eclipse.team.cvs"; //$NON-NLS-1$ @@ -57,7 +44,7 @@ public abstract class CVSSyncTreeSubscriber extends SyncTreeSubscriber { this.id = id; this.name = name; this.description = description; - this.comparisonCriteria = new CVSRevisionNumberCompareCriteria(this); + this.comparisonCriteria = new CVSRevisionNumberCompareCriteria(isThreeWay()); } /* (non-Javadoc) @@ -90,94 +77,11 @@ public abstract class CVSSyncTreeSubscriber extends SyncTreeSubscriber { return super.getSyncInfo(resource); } else { // In CVS, folders do not have a base. Hence, the remote is used as the base. - IResourceVariant remoteResource = getRemoteResource(resource); + IResourceVariant remoteResource = getRemoteTree().getResourceVariant(resource); return getSyncInfo(resource, remoteResource, remoteResource); } } - protected boolean isThreeWay() { - return true; - } - - /** - * Method that creates an instance of SyncInfo for the provider local, base and remote. - * Can be overiden by subclasses. - * @param local - * @param base - * @param remote - * @param monitor - * @return - */ - protected SyncInfo getSyncInfo(IResource local, IResourceVariant base, IResourceVariant remote) throws TeamException { - CVSSyncInfo info = new CVSSyncInfo(local, base, remote, this); - info.init(); - return info; - } - - /* (non-Javadoc) - * @see org.eclipse.team.core.sync.ISyncTreeSubscriber#refresh(org.eclipse.core.resources.IResource[], int, org.eclipse.core.runtime.IProgressMonitor) - */ - public void refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { - monitor = Policy.monitorFor(monitor); - List errors = new ArrayList(); - try { - monitor.beginTask(null, 100 * resources.length); - for (int i = 0; i < resources.length; i++) { - IResource resource = resources[i]; - IStatus status = refresh(resource, depth, Policy.subMonitorFor(monitor, 100)); - if (!status.isOK()) { - errors.add(status); - } - } - } finally { - monitor.done(); - } - if (!errors.isEmpty()) { - throw new CVSException(new MultiStatus(CVSProviderPlugin.ID, 0, - (IStatus[]) errors.toArray(new IStatus[errors.size()]), - Policy.bind("CVSSyncTreeSubscriber.1", getName()), null)); //$NON-NLS-1$ - } - } - - public IStatus refresh(IResource resource, int depth, IProgressMonitor monitor) { - monitor = Policy.monitorFor(monitor); - try { - // Take a guess at the work involved for refreshing the base and remote tree - int baseWork = isThreeWay() ? (getCacheFileContentsHint() ? 30 : 10) : 0; - int remoteWork = 100; - monitor.beginTask(null, baseWork + remoteWork); - IResource[] baseChanges = refreshBase(new IResource[] {resource}, depth, Policy.subMonitorFor(monitor, baseWork)); - IResource[] remoteChanges = refreshRemote(new IResource[] {resource}, depth, Policy.subMonitorFor(monitor, remoteWork)); - - Set allChanges = new HashSet(); - allChanges.addAll(Arrays.asList(remoteChanges)); - allChanges.addAll(Arrays.asList(baseChanges)); - IResource[] changedResources = (IResource[]) allChanges.toArray(new IResource[allChanges.size()]); - fireTeamResourceChange(SubscriberChangeEvent.asSyncChangedDeltas(this, changedResources)); - return Status.OK_STATUS; - } catch (TeamException e) { - return new CVSStatus(IStatus.ERROR, Policy.bind("CVSSyncTreeSubscriber.2", resource.getFullPath().toString(), e.getMessage()), e); //$NON-NLS-1$ - } finally { - monitor.done(); - } - } - - protected boolean getCacheFileContentsHint() { - return false; - } - - protected IResource[] refreshBase(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { - if (isThreeWay()) { - return getBaseTree().refresh(resources, depth, monitor); - } else { - return new IResource[0]; - } - } - - protected IResource[] refreshRemote(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { - return getRemoteTree().refresh(resources, depth, monitor); - } - /* (non-Javadoc) * @see org.eclipse.team.core.sync.ISyncTreeSubscriber#isSupervised(org.eclipse.core.resources.IResource) */ @@ -190,7 +94,7 @@ public abstract class CVSSyncTreeSubscriber extends SyncTreeSubscriber { ICVSResource cvsThing = CVSWorkspaceRoot.getCVSResourceFor(resource); if (cvsThing.isIgnored()) { // An ignored resource could have an incoming addition (conflict) - return hasRemote(resource); + return getRemoteTree().hasResourceVariant(resource); } return true; } catch (TeamException e) { @@ -202,99 +106,35 @@ public abstract class CVSSyncTreeSubscriber extends SyncTreeSubscriber { throw e; } } - - public IResourceVariant getRemoteResource(IResource resource) throws TeamException { - return getRemoteTree().getResourceVariant(resource); - } - - public IResourceVariant getBaseResource(IResource resource) throws TeamException { - if (isThreeWay()) { - return getBaseTree().getResourceVariant(resource); - } else { - return null; - } - } - - /** - * Return the base resource variant tree. - */ - protected abstract ResourceVariantTree getBaseTree(); - - /** - * Return the remote resource variant tree. - */ - protected abstract ResourceVariantTree getRemoteTree(); - - private String getSyncName(ResourceVariantByteStore cache) { - if (cache instanceof PersistantResourceVariantByteStore) { - return ((PersistantResourceVariantByteStore)cache).getSyncName().toString(); - } - return cache.getClass().getName(); - } /* (non-Javadoc) - * @see org.eclipse.team.core.subscribers.helpers.SyncTreeSubscriber#hasRemote(org.eclipse.core.resources.IResource) + * @see org.eclipse.team.core.subscribers.TeamSubscriber#getDefaultComparisonCriteria() */ - protected boolean hasRemote(IResource resource) throws TeamException { - return getRemoteTree().hasResourceVariant(resource); + public IResourceVariantComparator getResourceComparator() { + return comparisonCriteria; } /* (non-Javadoc) - * @see org.eclipse.team.core.subscribers.TeamSubscriber#getDefaultComparisonCriteria() + * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTreeSubscriber#getSyncInfo(org.eclipse.core.resources.IResource, org.eclipse.team.core.synchronize.IResourceVariant, org.eclipse.team.core.synchronize.IResourceVariant) */ - public IResourceVariantComparator getResourceComparator() { - return comparisonCriteria; + protected SyncInfo getSyncInfo(IResource local, IResourceVariant base, IResourceVariant remote) throws TeamException { + CVSSyncInfo info = new CVSSyncInfo(local, base, remote, this); + info.init(); + return info; } - public IResource[] members(IResource resource) throws TeamException { - if(resource.getType() == IResource.FILE) { - return new IResource[0]; - } - try { - Set allMembers = new HashSet(); - try { - allMembers.addAll(Arrays.asList(((IContainer)resource).members())); - } catch (CoreException e) { - if (e.getStatus().getCode() == IResourceStatus.RESOURCE_NOT_FOUND) { - // The resource is no longer exists so ignore the exception - } else { - throw e; - } - } - allMembers.addAll(Arrays.asList(getMembers(getRemoteTree(), resource))); - if (isThreeWay()) { - allMembers.addAll(Arrays.asList(getMembers(getBaseTree(), resource))); - } - for (Iterator iterator = allMembers.iterator(); iterator.hasNext();) { - IResource member = (IResource) iterator.next(); - if(!member.exists() && !hasRemote(member)) { - // Remove deletion conflicts - iterator.remove(); - } else if (!isSupervised(resource)) { - // Remove unsupervised resources - iterator.remove(); - } - } - return (IResource[]) allMembers.toArray(new IResource[allMembers.size()]); - } catch (CoreException e) { - throw TeamException.asTeamException(e); - } + /* + * Indicate whether file contents should be cached on a refresh + */ + protected boolean getCacheFileContentsHint() { + return false; } - - private IResource[] getMembers(ResourceVariantTree tree, IResource resource) throws TeamException, CoreException { - // Filter and return only phantoms associated with the remote synchronizer. - IResource[] members; - try { - members = tree.members(resource); - } catch (CoreException e) { - if (!isSupervised(resource) || e.getStatus().getCode() == IResourceStatus.RESOURCE_NOT_FOUND) { - // The resource is no longer supervised or doesn't exist in any form - // so ignore the exception and return that there are no members - return new IResource[0]; - } - throw e; - } - return members; + + /* + * Indicate whether the subscriber is two-way or three-way + */ + protected boolean isThreeWay() { + return true; } protected boolean rootsEqual(Subscriber other) { diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSWorkspaceSubscriber.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSWorkspaceSubscriber.java index 83c67a659..2473d0929 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSWorkspaceSubscriber.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSWorkspaceSubscriber.java @@ -32,14 +32,12 @@ import org.eclipse.team.core.synchronize.SyncInfo; import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; import org.eclipse.team.internal.ccvs.core.resources.EclipseSynchronizer; import org.eclipse.team.internal.ccvs.core.syncinfo.CVSBaseResourceVariantTree; -import org.eclipse.team.internal.ccvs.core.syncinfo.CVSDescendantResourceVariantTree; +import org.eclipse.team.internal.ccvs.core.syncinfo.CVSDescendantResourceVariantByteStore; import org.eclipse.team.internal.ccvs.core.syncinfo.CVSResourceVariantTree; -import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; import org.eclipse.team.internal.ccvs.core.util.ResourceStateChangeListeners; -import org.eclipse.team.internal.core.subscribers.caches.DescendantResourceVariantByteStore; +import org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree; import org.eclipse.team.internal.core.subscribers.caches.PersistantResourceVariantByteStore; import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore; -import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree; /** * CVSWorkspaceSubscriber @@ -56,11 +54,21 @@ public class CVSWorkspaceSubscriber extends CVSSyncTreeSubscriber implements IRe // install sync info participant ResourceVariantByteStore baseSynchronizer = new CVSBaseResourceVariantTree(); - baseTree = new CVSResourceVariantTree(baseSynchronizer, getBaseTag(), getCacheFileContentsHint()); - CVSDescendantResourceVariantTree remoteSynchronizer = new CVSDescendantResourceVariantTree( + baseTree = new CVSResourceVariantTree(baseSynchronizer, null, getCacheFileContentsHint()) { + public IResource[] refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { + // TODO Ensure that file contents are cached for modified local files + try { + monitor.beginTask(null, 100); + return new IResource[0]; + } finally { + monitor.done(); + } + } + }; + CVSDescendantResourceVariantByteStore remoteSynchronizer = new CVSDescendantResourceVariantByteStore( baseSynchronizer, new PersistantResourceVariantByteStore(new QualifiedName(SYNC_KEY_QUALIFIER, REMOTE_RESOURCE_KEY))); - remoteTree = new CVSResourceVariantTree(remoteSynchronizer, getRemoteTag(), getCacheFileContentsHint()); + remoteTree = new CVSResourceVariantTree(remoteSynchronizer, null, getCacheFileContentsHint()); ResourceStateChangeListeners.getListener().addResourceStateChangeListener(this); } @@ -96,60 +104,10 @@ public class CVSWorkspaceSubscriber extends CVSSyncTreeSubscriber implements IRe } private void internalResourceSyncInfoChanged(IResource[] changedResources, boolean canModifyWorkspace) { - // IMPORTANT NOTE: This will throw exceptions if performed during the POST_CHANGE delta phase!!! - DescendantResourceVariantByteStore remoteByteStore = getRemoteByteStore(); - for (int i = 0; i < changedResources.length; i++) { - IResource resource = changedResources[i]; - try { - if (resource.getType() == IResource.FILE - && (resource.exists() || resource.isPhantom())) { - byte[] remoteBytes = remoteByteStore.getBytes(resource); - if (remoteBytes == null) { - if (remoteByteStore.isVariantKnown(resource)) { - // The remote is known not to exist. If the local resource is - // managed then this information is stale - if (getBaseTree().hasResourceVariant(resource)) { - if (canModifyWorkspace) { - remoteByteStore.flushBytes(resource, IResource.DEPTH_ZERO); - } else { - // The revision comparison will handle the stale sync bytes - // TODO: Unless the remote is known not to exist (see bug 52936) - } - } - } - } else { - byte[] localBytes = getBaseByteStore().getBytes(resource); - if (localBytes == null || !isLaterRevision(remoteBytes, localBytes)) { - if (canModifyWorkspace) { - remoteByteStore.flushBytes(resource, IResource.DEPTH_ZERO); - } else { - // The remote byte store handles the stale sync bytes - } - } - } - } else if (resource.getType() == IResource.FOLDER) { - // If the base has sync info for the folder, purge the remote bytes - if (getBaseTree().hasResourceVariant(resource) && canModifyWorkspace) { - remoteByteStore.flushBytes(resource, IResource.DEPTH_ZERO); - } - } - } catch (TeamException e) { - CVSProviderPlugin.log(e); - } - } - + getRemoteByteStore().handleResourceChanges(changedResources, canModifyWorkspace); fireTeamResourceChange(SubscriberChangeEvent.asSyncChangedDeltas(this, changedResources)); } - private boolean isLaterRevision(byte[] remoteBytes, byte[] localBytes) { - try { - return ResourceSyncInfo.isLaterRevisionOnSameBranch(remoteBytes, localBytes); - } catch (CVSException e) { - CVSProviderPlugin.log(e); - return false; - } - } - /* (non-Javadoc) * @see org.eclipse.team.internal.ccvs.core.IResourceStateChangeListener#externalSyncInfoChange(org.eclipse.core.resources.IResource[]) */ @@ -182,7 +140,7 @@ public class CVSWorkspaceSubscriber extends CVSSyncTreeSubscriber implements IRe */ public void projectDeconfigured(IProject project) { try { - getRemoteTree().removeRoot(project); + getRemoteTree().flushVariants(project, IResource.DEPTH_INFINITE); } catch (TeamException e) { CVSProviderPlugin.log(e); } @@ -198,42 +156,18 @@ public class CVSWorkspaceSubscriber extends CVSSyncTreeSubscriber implements IRe fireTeamResourceChange(SubscriberChangeEvent.asSyncChangedDeltas(this, changedResources)); } } - - protected IResource[] refreshBase(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { - // TODO Ensure that file contents are cached for modified local files - try { - monitor.beginTask(null, 100); - return new IResource[0]; - } finally { - monitor.done(); - } - } - - /* (non-Javadoc) - * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getRemoteTag() - */ - protected CVSTag getRemoteTag() { - return null; - } - - /* (non-Javadoc) - * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getBaseTag() - */ - protected CVSTag getBaseTag() { - return null; - } /* (non-Javadoc) * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getBaseSynchronizationCache() */ - protected ResourceVariantTree getBaseTree() { + protected IResourceVariantTree getBaseTree() { return baseTree; } /* (non-Javadoc) * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getRemoteSynchronizationCache() */ - protected ResourceVariantTree getRemoteTree() { + protected IResourceVariantTree getRemoteTree() { return remoteTree; } @@ -312,14 +246,8 @@ public class CVSWorkspaceSubscriber extends CVSSyncTreeSubscriber implements IRe /* * TODO: Should not need to access this here */ - private CVSDescendantResourceVariantTree getRemoteByteStore() { - return (CVSDescendantResourceVariantTree)((CVSResourceVariantTree)getRemoteTree()).getByteStore(); + private CVSDescendantResourceVariantByteStore getRemoteByteStore() { + return (CVSDescendantResourceVariantByteStore)((CVSResourceVariantTree)getRemoteTree()).getByteStore(); } - /* - * TODO: Should not need to access this here - */ - private ResourceVariantByteStore getBaseByteStore() { - return ((CVSResourceVariantTree)getBaseTree()).getByteStore(); - } } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties index 227267940..148968d82 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties @@ -320,7 +320,6 @@ CVSMergeSubscriber.21=Ignoring root resource {0} because it does not exist in th CVSMergeSubscriber.22=Error restoring merge subscriber {0}: There are no existing roots in the save context. CVSProviderPlugin.20=CVS Workspace CVSProviderPlugin.21=Synchronizes the CVS managed resources in your workspace with their associated remote location -CVSSyncTreeSubscriber.0={0} is not a valid comparison criteria for subscriber {1} CVSRevisionNumberCompareCriteria.1=Comparing revision numbers ReentrantLock.9=An error occurred writting CVS synchronization information to disk. Some information may be lost. CRLFDetectInputStream.0=CVS file {0} either contains invalid line endings on the server (CR/LF instead of just LF) or is a binary file that is not marked as -kb. @@ -332,8 +331,6 @@ RemoveEntryHandler.2=Remove-entry received and ignored from CVS server for exist ServerMessageLineMatcher.5=Variable in template is not of the correct format: {0} ServerMessageLineMatcher.6=There are additional groups above those defining variables in template: {0} ServerMessageLineMatcher.7=Expected variable {0} in {1} but it is not present. -CVSSyncTreeSubscriber.1=Errors occurred during refresh of {0} -CVSSyncTreeSubscriber.2=An error occurred refreshing {0}: {1} CVSSyncInfo.7=Invalid attempt to make file {0} in-sync. This operation can only be sed on folders. CVSSyncInfo.8=Invalid attempt to make outgoing resource {0} in-sync. This operation only applies to incoming or conflicting changes. CVSSyncInfo.9=Cannot make {0} in-sync because its parent is not under CVS control. diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantResourceVariantTree.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantResourceVariantByteStore.java index 3cc2ae128..469a65835 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantResourceVariantTree.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantResourceVariantByteStore.java @@ -10,7 +10,13 @@ *******************************************************************************/ package org.eclipse.team.internal.ccvs.core.syncinfo; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.team.core.TeamException; import org.eclipse.team.internal.core.subscribers.caches.*; import org.eclipse.team.internal.ccvs.core.*; @@ -18,9 +24,9 @@ import org.eclipse.team.internal.ccvs.core.*; /** * CVS sycnrhonization cache that ignores stale remote bytes */ -public class CVSDescendantResourceVariantTree extends DescendantResourceVariantByteStore { +public class CVSDescendantResourceVariantByteStore extends DescendantResourceVariantByteStore { - public CVSDescendantResourceVariantTree(ResourceVariantByteStore baseCache, PersistantResourceVariantByteStore remoteCache) { + public CVSDescendantResourceVariantByteStore(ResourceVariantByteStore baseCache, PersistantResourceVariantByteStore remoteCache) { super(baseCache, remoteCache); } @@ -44,7 +50,7 @@ public class CVSDescendantResourceVariantTree extends DescendantResourceVariantB if (resource.getType() == IResource.FILE && getBytes(resource) != null && !parentHasSyncBytes(resource)) { // Log a warning if there is no sync bytes available for the resource's // parent but there is valid sync bytes for the child - CVSProviderPlugin.log(new TeamException(Policy.bind("ResourceSynchronizer.missingParentBytesOnSet", ((PersistantResourceVariantByteStore)getRemoteTree()).getSyncName().toString(), resource.getFullPath().toString()))); //$NON-NLS-1$ + CVSProviderPlugin.log(new TeamException(Policy.bind("ResourceSynchronizer.missingParentBytesOnSet", ((PersistantResourceVariantByteStore)getRemoteStore()).getSyncName().toString(), resource.getFullPath().toString()))); //$NON-NLS-1$ } return changed; } @@ -63,6 +69,58 @@ public class CVSDescendantResourceVariantTree extends DescendantResourceVariantB * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#isVariantKnown(org.eclipse.core.resources.IResource) */ public boolean isVariantKnown(IResource resource) throws TeamException { - return ((PersistantResourceVariantByteStore)getRemoteTree()).isVariantKnown(resource); + return ((PersistantResourceVariantByteStore)getRemoteStore()).isVariantKnown(resource); + } + + /* + * TODO: Could possibly be generalized and moved up + */ + public IStatus handleResourceChanges(IResource[] changedResources, boolean canModifyWorkspace) { + // IMPORTANT NOTE: This will throw exceptions if performed during the POST_CHANGE delta phase!!! + List errors = new ArrayList(); + for (int i = 0; i < changedResources.length; i++) { + IResource resource = changedResources[i]; + try { + if (resource.getType() == IResource.FILE + && (resource.exists() || resource.isPhantom())) { + byte[] remoteBytes = getBytes(resource); + if (remoteBytes == null) { + if (isVariantKnown(resource)) { + // The remote is known not to exist. If the local resource is + // managed then this information is stale + if (getBaseStore().getBytes(resource) != null) { + if (canModifyWorkspace) { + flushBytes(resource, IResource.DEPTH_ZERO); + } else { + // The revision comparison will handle the stale sync bytes + // TODO: Unless the remote is known not to exist (see bug 52936) + } + } + } + } else { + byte[] localBytes = getBaseStore().getBytes(resource); + if (localBytes == null || !isDescendant(resource, localBytes, remoteBytes)) { + if (canModifyWorkspace) { + flushBytes(resource, IResource.DEPTH_ZERO); + } else { + // The remote byte store handles the stale sync bytes + } + } + } + } else if (resource.getType() == IResource.FOLDER) { + // If the base has sync info for the folder, purge the remote bytes + if (getBaseStore().getBytes(resource) != null && canModifyWorkspace) { + flushBytes(resource, IResource.DEPTH_ZERO); + } + } + } catch (TeamException e) { + errors.add(e); + } + } + for (Iterator iter = errors.iterator(); iter.hasNext();) { + TeamException e = (TeamException) iter.next(); + CVSProviderPlugin.log(e); + } + return Status.OK_STATUS; // TODO } } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSResourceVariantTree.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSResourceVariantTree.java index d0ced506a..786b73cc1 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSResourceVariantTree.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSResourceVariantTree.java @@ -10,9 +10,14 @@ *******************************************************************************/ package org.eclipse.team.internal.ccvs.core.syncinfo; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.core.TeamException; @@ -37,14 +42,13 @@ import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree; */ public class CVSResourceVariantTree extends ResourceVariantTree { - private ResourceVariantByteStore cache; private CVSTag tag; private boolean cacheFileContentsHint; private CVSSyncTreeSubscriber subscriber; public CVSResourceVariantTree(ResourceVariantByteStore cache, CVSTag tag, boolean cacheFileContentsHint) { + super(cache); this.tag = tag; - this.cache = cache; this.cacheFileContentsHint = cacheFileContentsHint; } @@ -52,7 +56,7 @@ public class CVSResourceVariantTree extends ResourceVariantTree { * @see org.eclipse.team.core.subscribers.RefreshOperation#getSynchronizationCache() */ public ResourceVariantByteStore getByteStore() { - return cache; + return super.getByteStore(); } /* (non-Javadoc) @@ -101,9 +105,9 @@ public class CVSResourceVariantTree extends ResourceVariantTree { } /* (non-Javadoc) - * @see org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree#getRoots() + * @see org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree#roots() */ - public IResource[] getRoots() { + public IResource[] roots() { return subscriber.roots(); } @@ -111,7 +115,7 @@ public class CVSResourceVariantTree extends ResourceVariantTree { * @see org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree#getResourceVariant(org.eclipse.core.resources.IResource) */ public IResourceVariant getResourceVariant(IResource resource) throws TeamException { - byte[] remoteBytes = cache.getBytes(resource); + byte[] remoteBytes = getByteStore().getBytes(resource); if (remoteBytes == null) { // There is no remote handle for this resource return null; @@ -122,7 +126,7 @@ public class CVSResourceVariantTree extends ResourceVariantTree { IProject project = resource.getProject(); if (project.exists() && RepositoryProvider.getProvider(project, CVSProviderPlugin.getTypeId()) != null) { CVSProviderPlugin.log(new CVSException( - Policy.bind("ResourceSynchronizer.missingParentBytesOnGet", getSyncName(cache).toString(), resource.getFullPath().toString()))); //$NON-NLS-1$ + Policy.bind("ResourceSynchronizer.missingParentBytesOnGet", getSyncName(getByteStore()).toString(), resource.getFullPath().toString()))); //$NON-NLS-1$ // Assume there is no remote and the problem is a programming error } return null; @@ -144,7 +148,7 @@ public class CVSResourceVariantTree extends ResourceVariantTree { private byte[] getParentBytes(IResource resource) throws TeamException { IContainer parent = resource.getParent(); - byte[] bytes = cache.getBytes(parent); + byte[] bytes = getByteStore().getBytes(parent); if (bytes == null ) { bytes = getBaseBytes(parent, getTag(resource)); } @@ -194,4 +198,54 @@ public class CVSResourceVariantTree extends ResourceVariantTree { if (resource.getType() == IResource.PROJECT) return true; return getParentBytes(resource) != null; } + + /* (non-Javadoc) + * @see org.eclipse.team.internal.core.subscribers.caches.AbstractResourceVariantTree#collectedMembers(org.eclipse.core.resources.IResource, org.eclipse.core.resources.IResource[]) + */ + protected IResource[] collectedMembers(IResource local, IResource[] members) throws TeamException { + // Look for resources that have sync bytes but are not in the resources we care about + IResource[] resources = getStoredMembers(local); + List children = new ArrayList(); + List changedResources = new ArrayList(); + children.addAll(Arrays.asList(members)); + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + if (!children.contains(resource)) { + // These sync bytes are stale. Purge them + flushVariants(resource, IResource.DEPTH_INFINITE); + changedResources.add(resource); + } + } + return (IResource[]) changedResources.toArray(new IResource[changedResources.size()]); + } + + /** + * Return all the members of that have resource variant information associated with them, + * such as members that are explicitly flagged as not having a resource variant. This list + * is used by the collection algorithm to flush variants for which there is no local and + * no remote. + * @param local the locla resource + * @return the local children that have resource variant information cached + * @throws TeamException + */ + private IResource[] getStoredMembers(IResource local) throws TeamException { + try { + if (local.getType() != IResource.FILE && (local.exists() || local.isPhantom())) { + // TODO: Not very generic! + IResource[] allChildren = ((IContainer)local).members(true /* include phantoms */); + List childrenWithSyncBytes = new ArrayList(); + for (int i = 0; i < allChildren.length; i++) { + IResource resource = allChildren[i]; + if (getByteStore().getBytes(resource) != null) { + childrenWithSyncBytes.add(resource); + } + } + return (IResource[]) childrenWithSyncBytes.toArray( + new IResource[childrenWithSyncBytes.size()]); + } + } catch (CoreException e) { + throw TeamException.asTeamException(e); + } + return new IResource[0]; + } } diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareWithTagAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareWithTagAction.java index 7927b5855..34393d71d 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareWithTagAction.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareWithTagAction.java @@ -15,13 +15,10 @@ import java.lang.reflect.InvocationTargetException; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.jface.action.IAction; -import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.team.internal.ccvs.core.CVSCompareSubscriber; import org.eclipse.team.internal.ccvs.core.CVSTag; import org.eclipse.team.internal.ccvs.ui.TagSelectionDialog; import org.eclipse.team.internal.ccvs.ui.subscriber.CompareParticipant; -import org.eclipse.team.ui.TeamUI; -import org.eclipse.team.ui.synchronize.ISynchronizeParticipant; import org.eclipse.team.ui.synchronize.subscriber.SubscriberParticipant; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; diff --git a/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemSubscriber.java b/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemSubscriber.java index 50ab30efb..81de667bb 100644 --- a/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemSubscriber.java +++ b/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemSubscriber.java @@ -11,43 +11,25 @@ package org.eclipse.team.examples.filesystem; import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.core.TeamException; -import org.eclipse.team.core.synchronize.IResourceVariant; import org.eclipse.team.core.synchronize.IResourceVariantComparator; -import org.eclipse.team.internal.core.subscribers.caches.SyncTreeSubscriber; +import org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree; +import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTreeSubscriber; - -public class FileSystemSubscriber extends SyncTreeSubscriber { +public class FileSystemSubscriber extends ResourceVariantTreeSubscriber { /* (non-Javadoc) - * @see org.eclipse.team.internal.core.subscribers.caches.SyncTreeSubscriber#getRemoteResource(org.eclipse.core.resources.IResource) + * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTreeSubscriber#getBaseTree() */ - public IResourceVariant getRemoteResource(IResource resource) throws TeamException { + protected IResourceVariantTree getBaseTree() { // TODO Auto-generated method stub return null; } /* (non-Javadoc) - * @see org.eclipse.team.internal.core.subscribers.caches.SyncTreeSubscriber#getBaseResource(org.eclipse.core.resources.IResource) + * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTreeSubscriber#getRemoteTree() */ - public IResourceVariant getBaseResource(IResource resource) throws TeamException { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see org.eclipse.team.internal.core.subscribers.caches.SyncTreeSubscriber#hasRemote(org.eclipse.core.resources.IResource) - */ - protected boolean hasRemote(IResource resource) throws TeamException { - // TODO Auto-generated method stub - return false; - } - - /* (non-Javadoc) - * @see org.eclipse.team.internal.core.subscribers.caches.SyncTreeSubscriber#getResourceComparator() - */ - public IResourceVariantComparator getResourceComparator() { + protected IResourceVariantTree getRemoteTree() { // TODO Auto-generated method stub return null; } @@ -77,10 +59,12 @@ public class FileSystemSubscriber extends SyncTreeSubscriber { } /* (non-Javadoc) - * @see org.eclipse.team.core.subscribers.Subscriber#refresh(org.eclipse.core.resources.IResource[], int, org.eclipse.core.runtime.IProgressMonitor) + * @see org.eclipse.team.core.subscribers.Subscriber#getResourceComparator() */ - public void refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { + public IResourceVariantComparator getResourceComparator() { // TODO Auto-generated method stub - - } + return null; + } + + } |