*** empty log message ***
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantTree.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantByteStore.java
similarity index 65%
rename from bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantTree.java
rename to bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantByteStore.java
index e3653f9..b24be59 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantTree.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantByteStore.java
@@ -10,11 +10,14 @@
  *******************************************************************************/
 package org.eclipse.team.internal.core.subscribers.caches;
 
+import java.util.HashSet;
+import java.util.Set;
+
 import org.eclipse.core.resources.IResource;
 import org.eclipse.team.core.TeamException;
 
 /**
- * A <code>ResourceVariantTree</code> that optimizes the memory footprint
+ * A <code>ResourceVariantByteStore</code> that optimizes the memory footprint
  * of a remote resource variant tree by only storing those bytes that
  * differ from a base resource variant tree. This class should only be used 
  * for cases where the base and remote are on the same line-of-descent. 
@@ -29,24 +32,24 @@
  * from the main trunck to a branch, any cached remote resource variants would be stale.
 
  */
-public abstract class DescendantResourceVariantTree extends ResourceVariantTree {
-	ResourceVariantTree baseCache, remoteCache;
+public abstract class DescendantResourceVariantByteStore extends ResourceVariantByteStore {
+	ResourceVariantByteStore baseCache, remoteCache;
 
-	public DescendantResourceVariantTree(ResourceVariantTree baseCache, ResourceVariantTree remoteCache) {
+	public DescendantResourceVariantByteStore(ResourceVariantByteStore baseCache, ResourceVariantByteStore remoteCache) {
 		this.baseCache = baseCache;
 		this.remoteCache = remoteCache;
 	}
 	
 	/**
 	 * This method will dispose the remote cache but not the base cache.
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#dispose()
+	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#dispose()
 	 */
 	public void dispose() {
 		remoteCache.dispose();
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#getBytes(org.eclipse.core.resources.IResource)
+	 * @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);
@@ -76,31 +79,38 @@
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#setBytes(org.eclipse.core.resources.IResource, byte[])
+	 * @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);
 		if (baseBytes != null && equals(baseBytes, bytes)) {
 			// Remove the existing bytes so the base will be used (thus saving space)
-			return remoteCache.removeBytes(resource, IResource.DEPTH_ZERO);
+			return remoteCache.flushBytes(resource, IResource.DEPTH_ZERO);
 		} else {
 			return remoteCache.setBytes(resource, bytes);
 		}	
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#removeBytes(org.eclipse.core.resources.IResource, int)
+	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#removeBytes(org.eclipse.core.resources.IResource, int)
 	 */
-	public boolean removeBytes(IResource resource, int depth) throws TeamException {
-		return remoteCache.removeBytes(resource, depth);
+	public boolean flushBytes(IResource resource, int depth) throws TeamException {
+		return remoteCache.flushBytes(resource, depth);
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#isVariantKnown(org.eclipse.core.resources.IResource)
+	/**
+	 * Return <code>true</code> if the variant associated with the given local 
+	 * resource has been cached. This method is useful for those cases when
+	 * there are no bytes for a resource variant and the client wants to
+	 * know if this means that the remote does exist (i.e. this method returns
+	 * <code>true</code>) or the remote has not been fetched (i.e. this method returns
+	 * <code>false</code>).
+	 * @param resource the local resource
+	 * @return <code>true</code> if the variant associated with the given local 
+	 * resource has been cached.
+	 * @throws TeamException
 	 */
-	public boolean isVariantKnown(IResource resource) throws TeamException {
-		return remoteCache.isVariantKnown(resource);
-	}
+	public abstract boolean isVariantKnown(IResource resource) throws TeamException;
 
 	/**
 	 * This method indicates whether the remote bytes are a later revision or version
@@ -115,17 +125,17 @@
 	protected abstract boolean isDescendant(IResource resource, byte[] baseBytes, byte[] remoteBytes) throws TeamException;
 	
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#setVariantDoesNotExist(org.eclipse.core.resources.IResource)
+	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#setVariantDoesNotExist(org.eclipse.core.resources.IResource)
 	 */
-	public boolean setVariantDoesNotExist(IResource resource) throws TeamException {
-		return remoteCache.setVariantDoesNotExist(resource);
+	public boolean deleteBytes(IResource resource) throws TeamException {
+		return remoteCache.deleteBytes(resource);
 	}
 
 	/**
 	 * Return the base tree from which the remote is descendant.
 	 * @return Returns the base tree.
 	 */
-	protected ResourceVariantTree getBaseTree() {
+	protected ResourceVariantByteStore getBaseTree() {
 		return baseCache;
 	}
 
@@ -134,15 +144,29 @@
 	 * that differ from those in the base tree.
 	 * @return Returns the remote tree.
 	 */
-	protected ResourceVariantTree getRemoteTree() {
+	protected ResourceVariantByteStore getRemoteTree() {
 		return remoteCache;
 	}
 	
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#members(org.eclipse.core.resources.IResource)
+	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#members(org.eclipse.core.resources.IResource)
 	 */
 	public IResource[] members(IResource resource) throws TeamException {
-		return getRemoteTree().members(resource);
+		IResource[] remoteMembers = getRemoteTree().members(resource);
+		IResource[] baseMembers = getBaseTree().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
+			// (i.e. hasn't marked it as deleted
+			if (!isVariantKnown(member)) {
+				members.add(member);
+			}
+		}
+		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
new file mode 100644
index 0000000..5bbfbd1
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/IResourceVariantTree.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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 org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.TeamException;
+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.
+ */
+public interface IResourceVariantTree {
+	
+	public abstract IResource[] getRoots();
+	
+	/**
+	 * Returns the members of the local resource that have resource variants in this tree.
+	 * The members may or may not exist locally. The resource variants corresponding to the
+	 * memebers can be retrieved using <code>getResourceVariant(IResource)</code>.
+	 * @param resource the local resource
+	 * @return the members of the local resource for which this tree contains resource variants
+	 * @throws TeamException
+	 */
+	public abstract IResource[] members(IResource resource) throws TeamException;
+	
+	public abstract IResourceVariant getResourceVariant(IResource resource) throws TeamException;
+	
+	/**
+	 * Refreshes the resource variant tree for the specified resources and possibly 
+	 * their descendants, depending on the depth.
+	 * @param resources the resources whose variants should be refreshed
+	 * @param depth the depth of the refresh (one of <code>IResource.DEPTH_ZERO</code>,
+	 * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>)
+	 * @param monitor a progress monitor
+	 * @return the array of resources whose corresponding variants have changed
+	 * as a result of the refresh
+	 * @throws TeamException
+	 */
+	public abstract IResource[] refresh(
+			IResource[] resources, 
+			int depth,
+			IProgressMonitor monitor) throws TeamException;
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantTree.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantByteStore.java
similarity index 86%
rename from bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantTree.java
rename to bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantByteStore.java
index d998c9c..0ea8d77 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantTree.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantByteStore.java
@@ -20,11 +20,11 @@
 import org.eclipse.team.internal.core.Assert;
 
 /**
- * A <code>ResourceVariantTree</code> that caches the variant bytes using 
+ * 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.
  */
-public class PersistantResourceVariantTree extends ResourceVariantTree {
+public class PersistantResourceVariantByteStore extends ResourceVariantByteStore {
 
 	private static final byte[] NO_REMOTE = new byte[0];
 	
@@ -37,13 +37,13 @@
 	 * and a unique id within the plugin as the qualifier name.
 	 * @param name the key used in the Core synchronizer
 	 */
-	public PersistantResourceVariantTree(QualifiedName name) {
+	public PersistantResourceVariantByteStore(QualifiedName name) {
 		syncName = name;
 		getSynchronizer().add(syncName);
 	}
 	
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#dispose()
+	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#dispose()
 	 */
 	public void dispose() {
 		getSynchronizer().remove(getSyncName());
@@ -65,7 +65,7 @@
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#getBytes(org.eclipse.core.resources.IResource)
+	 * @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);
@@ -85,7 +85,7 @@
 	}
 	
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#setBytes(org.eclipse.core.resources.IResource, byte[])
+	 * @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);
@@ -100,9 +100,9 @@
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#removeBytes(org.eclipse.core.resources.IResource, int)
+	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#removeBytes(org.eclipse.core.resources.IResource, int)
 	 */
-	public boolean removeBytes(IResource resource, int depth) throws TeamException {
+	public boolean flushBytes(IResource resource, int depth) throws TeamException {
 		if (resource.exists() || resource.isPhantom()) {
 			try {
 				if (depth != IResource.DEPTH_ZERO || internalGetSyncBytes(resource) != null) {
@@ -117,7 +117,7 @@
 	}
 	
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#isVariantKnown(org.eclipse.core.resources.IResource)
+	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#isVariantKnown(org.eclipse.core.resources.IResource)
 	 */
 	public boolean isVariantKnown(IResource resource) throws TeamException {
 		return internalGetSyncBytes(resource) != null;
@@ -130,12 +130,12 @@
 	 * <code>getSyncBytes(resource)</code> will return <code>null</code>.
 	 * @return <code>true</code> if this changes the remote sync bytes
 	 */
-	public boolean setVariantDoesNotExist(IResource resource) throws TeamException {
+	public boolean deleteBytes(IResource resource) throws TeamException {
 		return setBytes(resource, NO_REMOTE);
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#members(org.eclipse.core.resources.IResource)
+	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#members(org.eclipse.core.resources.IResource)
 	 */
 	public IResource[] members(IResource resource) throws TeamException {
 		if(resource.getType() == IResource.FILE) {
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
new file mode 100644
index 0000000..bf51f5a
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantByteStore.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * 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 org.eclipse.core.resources.IResource;
+import org.eclipse.team.core.TeamException;
+
+/**
+ * The purpose of a <code>ResourceVariantByteStore</code> is to support the caching of
+ * the synchronization bytes for the resource variants that represent
+ * a resource line-up of interest such as a version, baseline or branch. The
+ * cache stores bytes in order to minimize the memory footprint of the tree. It is the
+ * reponsibility of the client of this API to cache enough bytes to meaningfully identify
+ * a resource variant (and possibly create an {@link IResourceVariant} handle from them).
+ * <p>
+ * The bytes for
+ * a resource variant are accessed using the local handle that corresponds to the 
+ * resource variant (using the <code>getSyncInfo</code> method). 
+ * 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).
+ */
+public abstract class ResourceVariantByteStore {
+
+	/**
+	 * Dispose of any cached sync bytes when this cache is no longer needed.
+	 */
+	public abstract void dispose();
+	
+	/**
+	 * Return the bytes for the variant corresponding the given local resource.
+	 * A return value of <code>null</code> means that no bytes have been stored
+	 * for the resource variant. It is up to the client to determine whether
+	 * this means that the resource variant does not exist or that it has not been
+	 * fetched or otherwise determined yet.
+	 * @param resource the local resource
+	 * @return the bytes that represent the resource's variant
+	 * @throws TeamException
+	 */
+	public abstract byte[] getBytes(IResource resource) throws TeamException;
+	
+	/**
+	 * Set the bytes for the variant corresponding the given local resource. 
+	 * The bytes should never be <code>null</code>. If it is known that the remote 
+	 * does not exist, <code>deleteBytes(IResource)</code> should be used instead. 
+	 * If the sync bytes for the remote are stale and should be removed, 
+	 * <code>flushBytes(IResouce, int)</code> should be called.
+	 * @param resource the local resource
+	 * @param bytes the bytes that represent the resource's variant
+	 * @return <code>true</code> if the bytes changed
+	 * @throws TeamException
+	 */
+	public abstract boolean setBytes(IResource resource, byte[] bytes) throws TeamException;
+	
+	/**
+	 * Remove the bytes from the tree for the resource variants corresponding to the 
+	 * given local resource and its descendants to the given depth.
+	 * After the bytes are removed, <code>getBytes(resource)</code> will 
+	 * return <code>null</code> for the affected resources.
+	 * @param resource the local resource
+	 * @param depth the depth of the operation (one of <code>IResource.DEPTH_ZERO</code>,
+	 * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>)
+	 * @return <code>true</code> if there were bytes present which were removed
+	 * @throws TeamException
+	 */
+	public abstract boolean flushBytes(IResource resource, int depth) throws TeamException;
+	
+	/**
+	 * Method called to indicate that it is known that there is no variant associated 
+	 * with the local resource. Subclasses may handle this information in different ways.
+	 * The <code>flush(IResource, int)</code> method should be used in the cases
+	 * where a client wishes to remove bytes for other reason.
+	 * @param resource the local resource
+	 * @return <code>true</code> if this changes the bytes for the variant
+	 */
+	public abstract boolean deleteBytes(IResource resource) throws TeamException;
+	
+	/**
+	 * Return the children of the given resource that have resource variants in this tree.
+	 * @param resource the parent resource
+	 * @return the members who have resource variants in this tree.
+	 */
+	public abstract IResource[] members(IResource resource) throws TeamException;
+	
+	/**
+	 * Helper method to compare two byte arrays for equality
+	 * @param syncBytes1 the first byte array or <code>null</code>
+	 * @param syncBytes2 the second byte array or <code>null</code>
+	 * @return whetehr the two arrays are equal (i.e. same content)
+	 */
+	protected boolean equals(byte[] syncBytes1, byte[] syncBytes2) {
+		if (syncBytes1 == null) {
+			return syncBytes2 == null;
+		} else if (syncBytes2 == null) {
+			return false;
+		}
+		if (syncBytes1.length != syncBytes2.length) return false;
+		for (int i = 0; i < syncBytes1.length; i++) {
+			if (syncBytes1[i] != syncBytes2[i]) return false;
+		}
+		return true;
+	}
+}
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 36404a5..13c6566 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,120 +10,333 @@
  *******************************************************************************/
 package org.eclipse.team.internal.core.subscribers.caches;
 
+import java.util.*;
+
+import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
 import org.eclipse.team.core.TeamException;
+import org.eclipse.team.core.synchronize.IResourceVariant;
+import org.eclipse.team.internal.core.Assert;
+import org.eclipse.team.internal.core.Policy;
 
 /**
- * The purpose of a <code>ResourceVariantTree</code> is to support the caching of
- * the synchronization bytes for the resource variants that represent
- * a resource line-up of interest such as a version, baseline or branch. The
- * cache stores bytes in order to minimize the memory footprint of the tree. It is the
- * reponsibility of the client of this API to cache enough bytes to meaningfully identify
- * a resource variant (and possibly create an {@link IResourceVariant} handle from them).
- * <p>
- * The bytes for
- * a resource variant are accessed using the local handle that corresponds to the 
- * resource variant (using the <code>getSyncInfo</code> method). 
- * 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).
- * TODO: Does the isRemoteKnown/setRemoteDoesNotExist make sense?
+ * This class provides the logic for refreshing a resource variant tree. 
+ * 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.
  */
-public abstract class ResourceVariantTree {
+public abstract class ResourceVariantTree implements IResourceVariantTree {
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree#members(org.eclipse.core.resources.IResource)
+	 */
+	public IResource[] members(IResource resource) throws TeamException {
+		return getByteStore().members(resource);
+	}
+	
+	/**
+	 * Refreshes the resource variant tree for the specified resources and possibly their descendants,
+	 * depending on the depth. The default implementation of this method invokes
+	 * <code>refresh(IResource, int, IProgressMonitor)</code> for each resource.
+	 * Subclasses may override but should either invoke the above mentioned refresh or 
+	 * <code>collectChanges</code> in order to reconcile the resource variant tree.
+	 * @param resources the resources whose variants should be refreshed
+	 * @param depth the depth of the refresh (one of <code>IResource.DEPTH_ZERO</code>,
+	 * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>)
+	 * @param monitor a progress monitor
+	 * @return the array of resources whose corresponding varianst have changed
+	 * @throws TeamException
+	 */
+	public IResource[] refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException {
+		List changedResources = new ArrayList();
+		monitor.beginTask(null, 100 * resources.length);
+		for (int i = 0; i < resources.length; i++) {
+			IResource resource = resources[i];
+			IResource[] changed = refresh(resource, depth, Policy.subMonitorFor(monitor, 100));
+			changedResources.addAll(Arrays.asList(changed));
+		}
+		monitor.done();
+		if (changedResources == null) return new IResource[0];
+		return (IResource[]) changedResources.toArray(new IResource[changedResources.size()]);
+	}
 
 	/**
-	 * Dispose of any cached sync bytes when this cache is no longer needed.
-	 */
-	public abstract void dispose();
-	
-	/**
-	 * Return the bytes for the variant corresponding the given local resource.
-	 * A return value of <code>null</code> can mean either that the
-	 * variant has never been fetched or that it doesn't exist. The method
-	 * <code>isVariantKnown(IResource)</code> should be used to differentiate
-	 * these two cases.
-	 * @param resource the local resource
-	 * @return the bytes that represent the resource's variant
-	 * @throws TeamException
-	 */
-	public abstract byte[] getBytes(IResource resource) throws TeamException;
-	
-	/**
-	 * Set the bytes for the variant corresponding the given local resource. 
-	 * The bytes should never be
-	 * <code>null</code>. If it is known that the remote does not exist, 
-	 * <code>setVariantDoesNotExist(IResource)</code> should be used instead. If the sync
-	 * bytes for the remote are stale and should be removed, <code>removeBytes()</code>
-	 * should be called.
-	 * @param resource the local resource
-	 * @param bytes the bytes that represent the resource's variant
-	 * @return <code>true</code> if the bytes changed
-	 * @throws TeamException
-	 */
-	public abstract boolean setBytes(IResource resource, byte[] bytes) throws TeamException;
-	
-	/**
-	 * Remove the bytes from the tree for the resource variants corresponding to the 
-	 * local resources that are descendants of the giben locla resource to the given depth.
-	 * After the bytes are removed, the operation <code>isVariantKnown(resource)</code> 
-	 * will return <code>false</code> 
-	 * and <code>getBytes(resource)</code> will return <code>null</code> for the
-	 * affected resources.
-	 * @param resource the local resource
-	 * @parem depth the depth of the operation (one of <code>IResource.DEPTH_ZERO</code>,
+	 * Helper method invoked from <code>refresh(IResource[], int, IProgressMonitor monitor)</code>
+	 * for each resource. The default implementation performs the following steps:
+	 * <ol>
+	 * <li>obtaine the scheduling rule for the resource
+	 * as returned from <code>getSchedulingRule(IResource)</code>. 
+	 * <li>get the resource variant handle corresponding to the local resource by calling
+	 * <code>getRemoteTree</code>.
+	 * <li>pass the local resource and the resource variant handle to <code>collectChanges</code>
+	 * </ol>
+	 * Subclasses may override but should perform roughly the same steps.
+	 * @param resource the resoure being refreshed
+	 * @param depth the depth of the refresh  (one of <code>IResource.DEPTH_ZERO</code>,
 	 * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>)
-	 * @return <code>true</code> if there were bytes present which were removed
+	 * @param monitor a progress monitor
+	 * @return the resource's whose variants have changed
 	 * @throws TeamException
 	 */
-	public abstract boolean removeBytes(IResource resource, int depth) throws TeamException;
+	protected IResource[] refresh(IResource resource, int depth, IProgressMonitor monitor) throws TeamException {
+		IResource[] changedResources = null;
+		monitor.beginTask(null, 100);
+		ISchedulingRule rule = getSchedulingRule(resource);
+		try {
+			Platform.getJobManager().beginRule(rule, monitor);
+			if (!resource.getProject().isAccessible()) {
+				// The project is closed so silently skip it
+				return new IResource[0];
+			}
+			
+			monitor.setTaskName(Policy.bind("SynchronizationCacheRefreshOperation.0", resource.getFullPath().makeRelative().toString())); //$NON-NLS-1$
+			
+			// build the remote tree only if an initial tree hasn't been provided
+			IResourceVariant tree = fetchVariant(resource, depth, Policy.subMonitorFor(monitor, 70));
+			
+			// update the known remote handles 
+			IProgressMonitor sub = Policy.infiniteSubMonitorFor(monitor, 30);
+			try {
+				sub.beginTask(null, 64);
+				changedResources = collectChanges(resource, tree, depth, sub);
+			} finally {
+				sub.done();	 
+			}
+		} finally {
+			Platform.getJobManager().endRule(rule);
+			monitor.done();
+		}
+		if (changedResources == null) return new IResource[0];
+		return changedResources;
+	}
+
+	/**
+	 * Return the scheduling rule that should be obtained for the given resource.
+	 * This method is invoked from <code>refresh(IResource, int, IProgressMonitor)</code>.
+	 * By default, the resource's project is returned. Subclasses may override.
+	 * @param resource the resource being refreshed
+	 * @return a scheduling rule or <code>null</code>
+	 */
+	protected ISchedulingRule getSchedulingRule(IResource resource) {
+		return resource.getProject();
+	}
 	
 	/**
-	 * Return <code>true</code> if the variant associated with the given local 
-	 * resource has been cached. This method is useful for those cases when
-	 * there are no bytes for a resource variant and the client wants to
-	 * know if this means that the remote does exist (i.e. this method returns
-	 * <code>true</code>) or the remote has not been fetched (i.e. this method returns
-	 * <code>false</code>).
-	 * @param resource the local resource
-	 * @return <code>true</code> if the variant associated with the given local 
-	 * resource has been cached.
+	 * Collect the changes in the remote tree to the specified depth.
+	 * @param local the local resource being refreshed
+	 * @param remote the corresponding resource variant
+	 * @param depth the depth of the refresh  (one of <code>IResource.DEPTH_ZERO</code>,
+	 * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>)
+	 * @param monitor a progress monitor
+	 * @return the resource's whose variants have changed
 	 * @throws TeamException
 	 */
-	public abstract boolean isVariantKnown(IResource resource) throws TeamException;
+	protected IResource[] collectChanges(IResource local, IResourceVariant remote, int depth, IProgressMonitor monitor) throws TeamException {
+		List changedResources = new ArrayList();
+		collectChanges(local, remote, changedResources, depth, monitor);
+		return (IResource[]) changedResources.toArray(new IResource[changedResources.size()]);
+	}
 	
 	/**
-	 * This method should be invoked by a client to indicate that it is known that 
-	 * there is no variant associated with the local resource. After this method
-	 * is invoked, <code>isVariantKnown(resource)</code> will return <code>true</code> and
-	 * <code>getBytes(resource)</code> will return <code>null</code>.
+	 * Get the byte store that is used to cache the serialization bytes
+	 * for the resource variants of this tree. A byte store is used
+	 * to reduce the memory footprint of the tree.
+	 * @return the resource variant tree that is being refreshed.
+	 */
+	protected abstract ResourceVariantByteStore getByteStore();
+	
+	/**
+	 * 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;
+	
+	/**
+	 * Fetch the members of the given resource variant handle. This method may
+	 * return members that were fetched when <code>getRemoteTree</code> was called or
+	 * may fetch the children directly. 
+	 * @param variant the resource variant
+	 * @param progress a progress monitor
+	 * @return the members of the resource variant.
+	 */
+	protected abstract IResourceVariant[] fetchMembers(IResourceVariant variant, IProgressMonitor progress) throws TeamException;
+
+	/**
+	 * Fetch the resource variant corresponding to the given resource.
+	 * The depth
+	 * parameter indicates the depth of the refresh operation and also indicates the
+	 * depth to which the resource variant's desendants will be traversed. 
+	 * This method may prefetch the descendants to the provided depth
+	 * or may just return the variant handle corresponding to the given 
+	 * local resource, in which case
+	 * the descendant variants will be fetched by <code>fecthMembers(IResourceVariant, IProgressMonitor)</code>.
 	 * @param resource the local resource
-	 * @return <code>true</code> if this changes the bytes for the variant
+	 * @param depth the depth of the refresh  (one of <code>IResource.DEPTH_ZERO</code>,
+	 * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>)
+	 * @param monitor a progress monitor
+	 * @return the resource variant corresponding to the given local resource
 	 */
-	public abstract boolean setVariantDoesNotExist(IResource resource) throws TeamException;
+	protected abstract IResourceVariant fetchVariant(IResource resource, int depth, IProgressMonitor monitor) throws TeamException;
 	
-	/**
-	 * Return the children of the given resource that have resource variants in this tree.
-	 * @param resource the parent resource
-	 * @return the members who have resource variants in this tree.
+	private void collectChanges(IResource local, IResourceVariant remote, Collection changedResources, int depth, IProgressMonitor monitor) throws TeamException {
+		ResourceVariantByteStore cache = getByteStore();
+		byte[] newRemoteBytes = getBytes(local, remote);
+		boolean changed;
+		if (newRemoteBytes == null) {
+			changed = cache.deleteBytes(local);
+		} else {
+			changed = cache.setBytes(local, newRemoteBytes);
+		}
+		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);
+		}
+		
+		removeStaleBytes(local, children, changedResources);
+	}
+
+	private void removeStaleBytes(IResource local, Map children, Collection changedResources) throws TeamException {
+		// Look for resources that have sync bytes but are not in the resources we care about
+		ResourceVariantByteStore cache = getByteStore();
+		IResource[] resources = getChildrenWithBytes(local);
+		for (int i = 0; i < resources.length; i++) {
+			IResource resource = resources[i];
+			if (!children.containsKey(resource)) {
+				// These sync bytes are stale. Purge them
+				cache.flushBytes(resource, IResource.DEPTH_INFINITE);
+				changedResources.add(resource);
+			}
+		}
+	}
+
+	/*
+	 * Return all the children of the local resource, including phantoms, that have bytes 
+	 * associated with them in the resource varant tree of this operation. 
+	 * @param local the local resource
+	 * @return all children that have bytes stored in the tree.
+	 * @throws TeamException
 	 */
-	public abstract IResource[] members(IResource resource) throws TeamException;
+	private IResource[] getChildrenWithBytes(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];
+	}
 	
-	/**
-	 * Helper method to compare two byte arrays for equality
-	 * @param syncBytes1 the first byte array or <code>null</code>
-	 * @param syncBytes2 the second byte array or <code>null</code>
-	 * @return whetehr the two arrays are equal (i.e. same content)
+	private Map mergedMembers(IResource local, IResourceVariant remote, IProgressMonitor progress) throws TeamException {
+		
+		// {IResource -> IResourceVariant}
+		Map mergedResources = new HashMap();
+		
+		IResourceVariant[] remoteChildren;
+		if (remote == null) {
+			remoteChildren = new IResourceVariant[0];
+		} else {
+			remoteChildren = fetchMembers(remote, progress);
+		}
+		
+		
+		IResource[] localChildren = members(local);		
+
+		if (remoteChildren.length > 0 || localChildren.length > 0) {
+			Set allSet = new HashSet(20);
+			Map localSet = null;
+			Map remoteSet = null;
+
+			if (localChildren.length > 0) {
+				localSet = new HashMap(10);
+				for (int i = 0; i < localChildren.length; i++) {
+					IResource localChild = localChildren[i];
+					String name = localChild.getName();
+					localSet.put(name, localChild);
+					allSet.add(name);
+				}
+			}
+
+			if (remoteChildren.length > 0) {
+				remoteSet = new HashMap(10);
+				for (int i = 0; i < remoteChildren.length; i++) {
+					IResourceVariant remoteChild = remoteChildren[i];
+					String name = remoteChild.getName();
+					remoteSet.put(name, remoteChild);
+					allSet.add(name);
+				}
+			}
+			
+			Iterator e = allSet.iterator();
+			while (e.hasNext()) {
+				String keyChildName = (String) e.next();
+
+				if (progress != null) {
+					if (progress.isCanceled()) {
+						throw new OperationCanceledException();
+					}
+					// XXX show some progress?
+				}
+
+				IResource localChild =
+					localSet != null ? (IResource) localSet.get(keyChildName) : null;
+
+					IResourceVariant remoteChild =
+						remoteSet != null ? (IResourceVariant) remoteSet.get(keyChildName) : null;
+						
+					if (localChild == null) {
+						// there has to be a remote resource available if we got this far
+						Assert.isTrue(remoteChild != null);
+						boolean isContainer = remoteChild.isContainer();				
+						localChild = getResourceChild(local /* parent */, keyChildName, isContainer);
+					}
+					mergedResources.put(localChild, remoteChild);				
+			}
+		}
+		return mergedResources;
+	}
+	
+	/*
+	 * Create a local resource handle for a resource variant whose
+	 * corresponding local resource was not previously a member of the tree.
+	 * The resource may or may not exist locally.
+	 * @param parent the local parent
+	 * @param childName the name of the local resource
+	 * @param isContainer the type of resource (file or folder)
+	 * @return a local resource handle
 	 */
-	protected boolean equals(byte[] syncBytes1, byte[] syncBytes2) {
-		if (syncBytes1 == null) {
-			return syncBytes2 == null;
-		} else if (syncBytes2 == null) {
-			return false;
+	private IResource getResourceChild(IResource parent, String childName, boolean isContainer) {
+		if (parent.getType() == IResource.FILE) {
+			return null;
 		}
-		if (syncBytes1.length != syncBytes2.length) return false;
-		for (int i = 0; i < syncBytes1.length; i++) {
-			if (syncBytes1[i] != syncBytes2[i]) return false;
+		if (isContainer) {
+			return ((IContainer) parent).getFolder(new Path(childName));
+		} else {
+			return ((IContainer) parent).getFile(new Path(childName));
 		}
-		return true;
 	}
 }
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTreeRefresh.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTreeRefresh.java
deleted file mode 100644
index 1c7395c..0000000
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTreeRefresh.java
+++ /dev/null
@@ -1,339 +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.*;
-
-import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.*;
-import org.eclipse.core.runtime.jobs.ISchedulingRule;
-import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariant;
-import org.eclipse.team.internal.core.Assert;
-import org.eclipse.team.internal.core.Policy;
-
-/**
- * This class provides the logic for refreshing a resource variant tree. 
- * It provides the logic to traverse the local resource and variant resource trees in 
- * order to update the bytes stored in
- * a <code>ResourceVariantTree</code>. It also accumulates and returns all local resources 
- * for which the corresponding resource variant has changed.
- */
-public abstract class ResourceVariantTreeRefresh {
-	
-	/**
-	 * Refreshes the resource variant tree for the specified resources and possibly their descendants,
-	 * depending on the depth. The default implementation of this method invokes
-	 * <code>refresh(IResource, int, IProgressMonitor)</code> for each resource.
-	 * Subclasses may override but should either invoke the above mentioned refresh or 
-	 * <code>collectChanges</code> in order to reconcile the resource variant tree.
-	 * @param resources the resources whose variants should be refreshed
-	 * @param depth the depth of the refresh (one of <code>IResource.DEPTH_ZERO</code>,
-	 * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>)
-	 * @param monitor a progress monitor
-	 * @return the array of resources whose corresponding varianst have changed
-	 * @throws TeamException
-	 */
-	public IResource[] refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException {
-		List changedResources = new ArrayList();
-		monitor.beginTask(null, 100 * resources.length);
-		for (int i = 0; i < resources.length; i++) {
-			IResource resource = resources[i];
-			IResource[] changed = refresh(resource, depth, Policy.subMonitorFor(monitor, 100));
-			changedResources.addAll(Arrays.asList(changed));
-		}
-		monitor.done();
-		if (changedResources == null) return new IResource[0];
-		return (IResource[]) changedResources.toArray(new IResource[changedResources.size()]);
-	}
-
-	/**
-	 * Helper method invoked from <code>refresh(IResource[], int, IProgressMonitor monitor)</code>
-	 * for each resource. The default implementation performs the following steps:
-	 * <ol>
-	 * <li>obtaine the scheduling rule for the resource
-	 * as returned from <code>getSchedulingRule(IResource)</code>. 
-	 * <li>get the resource variant handle corresponding to the local resource by calling
-	 * <code>getRemoteTree</code>.
-	 * <li>pass the local resource and the resource variant handle to <code>collectChanges</code>
-	 * </ol>
-	 * Subclasses may override but should perform roughly the same steps.
-	 * @param resource the resoure being refreshed
-	 * @param depth the depth of the refresh  (one of <code>IResource.DEPTH_ZERO</code>,
-	 * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>)
-	 * @param monitor a progress monitor
-	 * @return the resource's whose variants have changed
-	 * @throws TeamException
-	 */
-	protected IResource[] refresh(IResource resource, int depth, IProgressMonitor monitor) throws TeamException {
-		IResource[] changedResources = null;
-		monitor.beginTask(null, 100);
-		ISchedulingRule rule = getSchedulingRule(resource);
-		try {
-			Platform.getJobManager().beginRule(rule, monitor);
-			if (!resource.getProject().isAccessible()) {
-				// The project is closed so silently skip it
-				return new IResource[0];
-			}
-			
-			monitor.setTaskName(Policy.bind("SynchronizationCacheRefreshOperation.0", resource.getFullPath().makeRelative().toString())); //$NON-NLS-1$
-			
-			// build the remote tree only if an initial tree hasn't been provided
-			IResourceVariant tree = fetchVariant(resource, depth, Policy.subMonitorFor(monitor, 70));
-			
-			// update the known remote handles 
-			IProgressMonitor sub = Policy.infiniteSubMonitorFor(monitor, 30);
-			try {
-				sub.beginTask(null, 64);
-				changedResources = collectChanges(resource, tree, depth, sub);
-			} finally {
-				sub.done();	 
-			}
-		} finally {
-			Platform.getJobManager().endRule(rule);
-			monitor.done();
-		}
-		if (changedResources == null) return new IResource[0];
-		return changedResources;
-	}
-
-	/**
-	 * Collect the changes in the remote tree to the specified depth.
-	 * @param local the local resource being refreshed
-	 * @param remote the corresponding resource variant
-	 * @param depth the depth of the refresh  (one of <code>IResource.DEPTH_ZERO</code>,
-	 * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>)
-	 * @param monitor a progress monitor
-	 * @return the resource's whose variants have changed
-	 * @throws TeamException
-	 */
-	protected IResource[] collectChanges(IResource local, IResourceVariant remote, int depth, IProgressMonitor monitor) throws TeamException {
-		List changedResources = new ArrayList();
-		collectChanges(local, remote, changedResources, depth, monitor);
-		return (IResource[]) changedResources.toArray(new IResource[changedResources.size()]);
-	}
-	
-	/**
-	 * Returns the resource variant tree that is being refreshed.
-	 * @return the resource variant tree that is being refreshed.
-	 */
-	protected abstract ResourceVariantTree getResourceVariantTree();
-	
-	/**
-	 * Get the bytes to be stored in the <code>ResourceVariantTree</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;
-	
-	/**
-	 * Fetch the members of the given resource variant handle. This method may
-	 * return members that were fetched when <code>getRemoteTree</code> was called or
-	 * may fetch the children directly. 
-	 * @param variant the resource variant
-	 * @param progress a progress monitor
-	 * @return the members of the resource variant.
-	 */
-	protected abstract IResourceVariant[] fetchMembers(IResourceVariant variant, IProgressMonitor progress) throws TeamException;
-
-	/**
-	 * Returns the members of the local resource. This may include all the members of
-	 * the local resource or a subset that is of ineterest to the implementor.
-	 * @param parent the local resource
-	 * @return the members of the local resource
-	 */
-	protected abstract IResource[] members(IResource parent) throws TeamException;
-
-	/**
-	 * Fetch the resource variant corresponding to the given resource.
-	 * The depth
-	 * parameter indicates the depth of the refresh operation and also indicates the
-	 * depth to which the resource variant's desendants will be traversed. 
-	 * This method may prefetch the descendants to the provided depth
-	 * or may just return the variant handle corresponding to the given 
-	 * local resource, in which case
-	 * the descendant variants will be fetched by <code>fecthMembers(IResourceVariant, IProgressMonitor)</code>.
-	 * @param resource the local resource
-	 * @param depth the depth of the refresh  (one of <code>IResource.DEPTH_ZERO</code>,
-	 * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>)
-	 * @param monitor a progress monitor
-	 * @return the resource variant corresponding to the given local resource
-	 */
-	protected abstract IResourceVariant fetchVariant(IResource resource, int depth, IProgressMonitor monitor) throws TeamException;
-	
-	/**
-	 * Return the scheduling rule that should be obtained for the given resource.
-	 * This method is invoked from <code>refresh(IResource, int, IProgressMonitor)</code>.
-	 * By default, the resource's project is returned. Subclasses may override.
-	 * @param resource the resource being refreshed
-	 * @return a scheduling rule or <code>null</code>
-	 */
-	protected ISchedulingRule getSchedulingRule(IResource resource) {
-		return resource.getProject();
-	}
-	
-	private void collectChanges(IResource local, IResourceVariant remote, Collection changedResources, int depth, IProgressMonitor monitor) throws TeamException {
-		ResourceVariantTree cache = getResourceVariantTree();
-		byte[] newRemoteBytes = getBytes(local, remote);
-		boolean changed;
-		if (newRemoteBytes == null) {
-			changed = cache.setVariantDoesNotExist(local);
-		} else {
-			changed = cache.setBytes(local, newRemoteBytes);
-		}
-		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);
-		}
-		
-		removeStaleBytes(local, children, changedResources);
-	}
-
-	private void removeStaleBytes(IResource local, Map children, Collection changedResources) throws TeamException {
-		// Look for resources that have sync bytes but are not in the resources we care about
-		ResourceVariantTree cache = getResourceVariantTree();
-		IResource[] resources = getChildrenWithBytes(local);
-		for (int i = 0; i < resources.length; i++) {
-			IResource resource = resources[i];
-			if (!children.containsKey(resource)) {
-				// These sync bytes are stale. Purge them
-				cache.removeBytes(resource, IResource.DEPTH_INFINITE);
-				changedResources.add(resource);
-			}
-		}
-	}
-
-	/*
-	 * Return all the children of the local resource, including phantoms, that have bytes 
-	 * associated with them in the resource varant tree of this operation. 
-	 * @param local the local resource
-	 * @return all children that have bytes stored in the tree.
-	 * @throws TeamException
-	 */
-	private IResource[] getChildrenWithBytes(IResource local) throws TeamException {			
-		try {
-			if (local.getType() != IResource.FILE && (local.exists() || local.isPhantom())) {
-				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 (getResourceVariantTree().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];
-	}
-	
-	private Map mergedMembers(IResource local, IResourceVariant remote, IProgressMonitor progress) throws TeamException {
-		
-		// {IResource -> IRemoteResource}
-		Map mergedResources = new HashMap();
-		
-		IResourceVariant[] remoteChildren;
-		if (remote == null) {
-			remoteChildren = new IResourceVariant[0];
-		} else {
-			remoteChildren = fetchMembers(remote, progress);
-		}
-		
-		
-		IResource[] localChildren = members(local);		
-
-		if (remoteChildren.length > 0 || localChildren.length > 0) {
-			Set allSet = new HashSet(20);
-			Map localSet = null;
-			Map remoteSet = null;
-
-			if (localChildren.length > 0) {
-				localSet = new HashMap(10);
-				for (int i = 0; i < localChildren.length; i++) {
-					IResource localChild = localChildren[i];
-					String name = localChild.getName();
-					localSet.put(name, localChild);
-					allSet.add(name);
-				}
-			}
-
-			if (remoteChildren.length > 0) {
-				remoteSet = new HashMap(10);
-				for (int i = 0; i < remoteChildren.length; i++) {
-					IResourceVariant remoteChild = remoteChildren[i];
-					String name = remoteChild.getName();
-					remoteSet.put(name, remoteChild);
-					allSet.add(name);
-				}
-			}
-			
-			Iterator e = allSet.iterator();
-			while (e.hasNext()) {
-				String keyChildName = (String) e.next();
-
-				if (progress != null) {
-					if (progress.isCanceled()) {
-						throw new OperationCanceledException();
-					}
-					// XXX show some progress?
-				}
-
-				IResource localChild =
-					localSet != null ? (IResource) localSet.get(keyChildName) : null;
-
-					IResourceVariant remoteChild =
-						remoteSet != null ? (IResourceVariant) remoteSet.get(keyChildName) : null;
-						
-						if (localChild == null) {
-							// there has to be a remote resource available if we got this far
-							Assert.isTrue(remoteChild != null);
-							boolean isContainer = remoteChild.isContainer();				
-							localChild = getResourceChild(local /* parent */, keyChildName, isContainer);
-						}
-						mergedResources.put(localChild, remoteChild);				
-			}
-		}
-		return mergedResources;
-	}
-	
-	/*
-	 * Create a local resource handle for a resource variant whose
-	 * corresponding local resource does not exist.
-	 * @param parent the local parent
-	 * @param childName the name of the local resource
-	 * @param isContainer the type of resource (file or folder)
-	 * @return a local resource handle
-	 */
-	private IResource getResourceChild(IResource parent, String childName, boolean isContainer) {
-		if (parent.getType() == IResource.FILE) {
-			return null;
-		}
-		if (isContainer) {
-			return ((IContainer) parent).getFolder(new Path(childName));
-		} else {
-			return ((IContainer) parent).getFile(new Path(childName));
-		}
-	}
-}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantTree.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantByteStore.java
similarity index 77%
rename from bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantTree.java
rename to bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantByteStore.java
index 59dacc2..cc32236 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantTree.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantByteStore.java
@@ -18,10 +18,10 @@
 import org.eclipse.team.internal.core.Assert;
 
 /**
- * A <code>ResourceVariantTree</code> that caches the variant bytes in memory 
+ * A <code>ResourceVariantByteStore</code> that caches the variant bytes in memory 
  * and does not persist them over workbench invocations.
  */
-public class SessionResourceVariantTree extends ResourceVariantTree {
+public class SessionResourceVariantByteStore extends ResourceVariantByteStore {
 
 	private static final byte[] NO_REMOTE = new byte[0];
 	
@@ -64,7 +64,7 @@
 	}
 	
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#dispose()
+	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#dispose()
 	 */
 	public void dispose() {
 		syncBytesCache.clear();
@@ -72,7 +72,7 @@
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#getBytes(org.eclipse.core.resources.IResource)
+	 * @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);
@@ -85,7 +85,7 @@
 
 	/*
 	 *  (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#setBytes(org.eclipse.core.resources.IResource, byte[])
+	 * @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);
@@ -96,15 +96,15 @@
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#removeBytes(org.eclipse.core.resources.IResource, int)
+	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#removeBytes(org.eclipse.core.resources.IResource, int)
 	 */
-	public boolean removeBytes(IResource resource, int depth) throws TeamException {
+	public boolean flushBytes(IResource resource, int depth) throws TeamException {
 		if (getSyncBytesCache().containsKey(resource)) {
 			if (depth != IResource.DEPTH_ZERO) {
 				IResource[] members = members(resource);
 				for (int i = 0; i < members.length; i++) {
 					IResource child = members[i];
-					removeBytes(child, (depth == IResource.DEPTH_INFINITE) ? IResource.DEPTH_INFINITE: IResource.DEPTH_ZERO);
+					flushBytes(child, (depth == IResource.DEPTH_INFINITE) ? IResource.DEPTH_INFINITE: IResource.DEPTH_ZERO);
 				}
 			}
 			getSyncBytesCache().remove(resource);
@@ -115,7 +115,7 @@
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#members(org.eclipse.core.resources.IResource)
+	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#members(org.eclipse.core.resources.IResource)
 	 */
 	public IResource[] members(IResource resource) {
 		List members = (List)membersCache.get(resource);
@@ -126,17 +126,10 @@
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#isVariantKnown(org.eclipse.core.resources.IResource)
+	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#setVariantDoesNotExist(org.eclipse.core.resources.IResource)
 	 */
-	public boolean isVariantKnown(IResource resource) throws TeamException {
-		return internalGetSyncBytes(resource) != null;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree#setVariantDoesNotExist(org.eclipse.core.resources.IResource)
-	 */
-	public boolean setVariantDoesNotExist(IResource resource) throws TeamException {
-		return setBytes(resource, NO_REMOTE);
+	public boolean deleteBytes(IResource resource) throws TeamException {
+		return flushBytes(resource, IResource.DEPTH_ZERO);
 	}
 
 	/**
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 6f496f5..80ee96b 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
@@ -16,9 +16,11 @@
 import org.eclipse.core.runtime.QualifiedName;
 import org.eclipse.team.core.TeamException;
 import org.eclipse.team.core.subscribers.*;
+import org.eclipse.team.core.synchronize.IResourceVariant;
 import org.eclipse.team.core.synchronize.SyncInfo;
-import org.eclipse.team.internal.core.subscribers.caches.SessionResourceVariantTree;
-import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree;
+import org.eclipse.team.internal.ccvs.core.syncinfo.CVSBaseSynchronizationCache;
+import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore;
+import org.eclipse.team.internal.core.subscribers.caches.SessionResourceVariantByteStore;
 
 /**
  * This subscriber is used when comparing the local workspace with its
@@ -30,7 +32,7 @@
 	private static final String UNIQUE_ID_PREFIX = "compare-"; //$NON-NLS-1$
 	
 	private CVSTag tag;
-	private SessionResourceVariantTree remoteSynchronizer;
+	private SessionResourceVariantByteStore remoteSynchronizer;
 	private IResource[] resources;
 	
 	public CVSCompareSubscriber(IResource[] resources, CVSTag tag) {
@@ -41,7 +43,7 @@
 	}
 
 	private void initialize() {
-		remoteSynchronizer = new SessionResourceVariantTree();
+		remoteSynchronizer = new SessionResourceVariantByteStore();
 		CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber().addListener(this);
 	}
 
@@ -73,7 +75,7 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getBaseSynchronizationCache()
 	 */
-	protected ResourceVariantTree getBaseSynchronizationCache() {
+	protected ResourceVariantByteStore getBaseSynchronizationCache() {
 		// No base cache needed since it's a two way compare
 		return null;
 	}
@@ -81,7 +83,7 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getRemoteSynchronizationCache()
 	 */
-	protected ResourceVariantTree getRemoteSynchronizationCache() {
+	protected ResourceVariantByteStore getRemoteSynchronizationCache() {
 		return remoteSynchronizer;
 	}
 	
@@ -182,9 +184,16 @@
 	 * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getSyncInfo(org.eclipse.core.resources.IResource)
 	 */
 	public SyncInfo getSyncInfo(IResource resource) throws TeamException {
+		// TODO: Temporary measure to avoid showing all local as additions before the refresh completes
 		if (remoteSynchronizer.isEmpty()) {
-			return null;
+			// Use the base as the remote so that outgoing changes are included
+			return new CVSSyncInfo(resource, null, getBase(resource), this);
 		}
 		return super.getSyncInfo(resource);
 	}
+
+	private CVSBaseSynchronizationCache baseCache = new CVSBaseSynchronizationCache();
+	private IResourceVariant getBase(IResource resource) throws TeamException {
+		return getRemoteResource(resource, baseCache);
+	}
 }
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 26851a8..500ce8d 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
@@ -23,8 +23,8 @@
 import org.eclipse.team.internal.ccvs.core.syncinfo.CVSSynchronizationCache;
 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.ResourceVariantTree;
-import org.eclipse.team.internal.core.subscribers.caches.PersistantResourceVariantTree;
+import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore;
+import org.eclipse.team.internal.core.subscribers.caches.PersistantResourceVariantByteStore;
 
 /**
  * A CVSMergeSubscriber is responsible for maintaining the remote trees for a merge into
@@ -48,9 +48,9 @@
 	
 	private CVSTag start, end;
 	private List roots;
-	private ResourceVariantTree remoteSynchronizer;
-	private PersistantResourceVariantTree mergedSynchronizer;
-	private ResourceVariantTree baseSynchronizer;
+	private CVSSynchronizationCache remoteSynchronizer;
+	private PersistantResourceVariantByteStore mergedSynchronizer;
+	private CVSSynchronizationCache baseSynchronizer;
 	
 	public CVSMergeSubscriber(IResource[] roots, CVSTag start, CVSTag end) {		
 		this(getUniqueId(), roots, start, end);
@@ -77,7 +77,7 @@
 		String syncKeyPrefix = id.getLocalName();
 		remoteSynchronizer = new CVSSynchronizationCache(new QualifiedName(SYNC_KEY_QUALIFIER, syncKeyPrefix + end.getName()));
 		baseSynchronizer = new CVSSynchronizationCache(new QualifiedName(SYNC_KEY_QUALIFIER, syncKeyPrefix + start.getName()));
-		mergedSynchronizer = new PersistantResourceVariantTree(new QualifiedName(SYNC_KEY_QUALIFIER, syncKeyPrefix + "0merged")); //$NON-NLS-1$
+		mergedSynchronizer = new PersistantResourceVariantByteStore(new QualifiedName(SYNC_KEY_QUALIFIER, syncKeyPrefix + "0merged")); //$NON-NLS-1$
 		
 		ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
 		CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber().addListener(this);
@@ -100,7 +100,7 @@
 	private void internalMerged(IResource resource) throws TeamException {
 		byte[] remoteBytes = remoteSynchronizer.getBytes(resource);
 		if (remoteBytes == null) {
-			mergedSynchronizer.setVariantDoesNotExist(resource);
+			mergedSynchronizer.deleteBytes(resource);
 		} else {
 			mergedSynchronizer.setBytes(resource, remoteBytes);
 		}
@@ -238,14 +238,14 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getBaseSynchronizationCache()
 	 */
-	protected ResourceVariantTree getBaseSynchronizationCache() {
+	protected ResourceVariantByteStore getBaseSynchronizationCache() {
 		return baseSynchronizer;
 	}
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getRemoteSynchronizationCache()
 	 */
-	protected ResourceVariantTree getRemoteSynchronizationCache() {
+	protected ResourceVariantByteStore getRemoteSynchronizationCache() {
 		return remoteSynchronizer;
 	}
 	
@@ -326,6 +326,11 @@
 			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);
 	}
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 2cb785b..4bc1dca 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
@@ -213,14 +213,14 @@
 	/**
 	 * Return the synchronization cache that provides access to the base sychronization bytes.
 	 */
-	protected abstract ResourceVariantTree getBaseSynchronizationCache();
+	protected abstract ResourceVariantByteStore getBaseSynchronizationCache();
 
 	/**
 	 * Return the synchronization cache that provides access to the base sychronization bytes.
 	 */
-	protected abstract ResourceVariantTree getRemoteSynchronizationCache();
+	protected abstract ResourceVariantByteStore getRemoteSynchronizationCache();
 	
-	protected IResourceVariant getRemoteResource(IResource resource, ResourceVariantTree cache) throws TeamException {
+	public IResourceVariant getRemoteResource(IResource resource, ResourceVariantByteStore cache) throws TeamException {
 		byte[] remoteBytes = cache.getBytes(resource);
 		if (remoteBytes == null) {
 			// There is no remote handle for this resource
@@ -260,9 +260,9 @@
 		}
 	}
 	
-	private String getSyncName(ResourceVariantTree cache) {
-		if (cache instanceof PersistantResourceVariantTree) {
-			return ((PersistantResourceVariantTree)cache).getSyncName().toString();
+	private String getSyncName(ResourceVariantByteStore cache) {
+		if (cache instanceof PersistantResourceVariantByteStore) {
+			return ((PersistantResourceVariantByteStore)cache).getSyncName().toString();
 		}
 		return cache.getClass().getName();
 	}
@@ -316,7 +316,7 @@
 		}
 	}
 
-	private IResource[] getMembers(ResourceVariantTree cache, IResource resource) throws TeamException, CoreException {
+	private IResource[] getMembers(ResourceVariantByteStore cache, IResource resource) throws TeamException, CoreException {
 		// Filter and return only phantoms associated with the remote synchronizer.
 		IResource[] members;
 		try {
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 4be128a..3fb66fe 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
@@ -25,8 +25,8 @@
 import org.eclipse.team.internal.ccvs.core.resources.EclipseSynchronizer;
 import org.eclipse.team.internal.ccvs.core.syncinfo.*;
 import org.eclipse.team.internal.ccvs.core.util.ResourceStateChangeListeners;
-import org.eclipse.team.internal.core.subscribers.caches.PersistantResourceVariantTree;
-import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree;
+import org.eclipse.team.internal.core.subscribers.caches.PersistantResourceVariantByteStore;
+import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore;
 import org.eclipse.team.internal.ccvs.core.Policy;
 
 /**
@@ -34,8 +34,8 @@
  */
 public class CVSWorkspaceSubscriber extends CVSSyncTreeSubscriber implements IResourceStateChangeListener {
 	
-	private ResourceVariantTree remoteSynchronizer;
-	private ResourceVariantTree baseSynchronizer;
+	private CVSDescendantSynchronizationCache remoteSynchronizer;
+	private ResourceVariantByteStore baseSynchronizer;
 	
 	// qualified name for remote sync info
 	private static final String REMOTE_RESOURCE_KEY = "remote-resource-key"; //$NON-NLS-1$
@@ -47,7 +47,7 @@
 		baseSynchronizer = new CVSBaseSynchronizationCache();
 		remoteSynchronizer = new CVSDescendantSynchronizationCache(
 				baseSynchronizer, 
-				new PersistantResourceVariantTree(new QualifiedName(SYNC_KEY_QUALIFIER, REMOTE_RESOURCE_KEY)));
+				new PersistantResourceVariantByteStore(new QualifiedName(SYNC_KEY_QUALIFIER, REMOTE_RESOURCE_KEY)));
 		
 		ResourceStateChangeListeners.getListener().addResourceStateChangeListener(this); 
 	}
@@ -96,7 +96,7 @@
 							// managed then this information is stale
 							if (getBaseSynchronizationCache().getBytes(resource) != null) {
 								if (canModifyWorkspace) {
-									remoteSynchronizer.removeBytes(resource, IResource.DEPTH_ZERO);
+									remoteSynchronizer.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)
@@ -107,7 +107,7 @@
 						byte[] localBytes = baseSynchronizer.getBytes(resource);
 						if (localBytes == null || !isLaterRevision(remoteBytes, localBytes)) {
 							if (canModifyWorkspace) {
-								remoteSynchronizer.removeBytes(resource, IResource.DEPTH_ZERO);
+								remoteSynchronizer.flushBytes(resource, IResource.DEPTH_ZERO);
 							} else {
 								// The getRemoteResource method handles the stale sync bytes
 							}
@@ -116,7 +116,7 @@
 				} else if (resource.getType() == IResource.FOLDER) {
 					// If the base has sync info for the folder, purge the remote bytes
 					if (getBaseSynchronizationCache().getBytes(resource) != null && canModifyWorkspace) {
-						remoteSynchronizer.removeBytes(resource, IResource.DEPTH_ZERO);
+						remoteSynchronizer.flushBytes(resource, IResource.DEPTH_ZERO);
 					}
 				}
 			} catch (TeamException e) {
@@ -168,7 +168,7 @@
 	 */
 	public void projectDeconfigured(IProject project) {
 		try {
-			remoteSynchronizer.removeBytes(project, IResource.DEPTH_INFINITE);
+			remoteSynchronizer.flushBytes(project, IResource.DEPTH_INFINITE);
 		} catch (TeamException e) {
 			CVSProviderPlugin.log(e);
 		}
@@ -212,14 +212,14 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getBaseSynchronizationCache()
 	 */
-	protected ResourceVariantTree getBaseSynchronizationCache() {
+	protected ResourceVariantByteStore getBaseSynchronizationCache() {
 		return baseSynchronizer;
 	}
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber#getRemoteSynchronizationCache()
 	 */
-	protected ResourceVariantTree getRemoteSynchronizationCache() {
+	protected ResourceVariantByteStore getRemoteSynchronizationCache() {
 		return remoteSynchronizer;
 	}
 	
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSBaseSynchronizationCache.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSBaseSynchronizationCache.java
index e3059df..b1c6156 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSBaseSynchronizationCache.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSBaseSynchronizationCache.java
@@ -13,11 +13,11 @@
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.team.core.TeamException;
-import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree;
+import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore;
 import org.eclipse.team.internal.ccvs.core.resources.EclipseSynchronizer;
 
 
-public class CVSBaseSynchronizationCache extends ResourceVariantTree {
+public class CVSBaseSynchronizationCache extends ResourceVariantByteStore {
 	public void dispose() {
 		// Do nothing
 	}
@@ -44,13 +44,13 @@
 	public boolean isVariantKnown(IResource resource) throws TeamException {
 		return getBytes(resource) != null;
 	}
-	public boolean removeBytes(IResource resource, int depth) throws TeamException {
+	public boolean flushBytes(IResource resource, int depth) throws TeamException {
 		throw new UnsupportedOperationException();
 	}
 	public boolean setBytes(IResource resource, byte[] bytes) throws TeamException {
 		throw new UnsupportedOperationException();
 	}
-	public boolean setVariantDoesNotExist(IResource resource) throws TeamException {
+	public boolean deleteBytes(IResource resource) throws TeamException {
 		throw new UnsupportedOperationException();
 	}
 	
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantSynchronizationCache.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantSynchronizationCache.java
index a3c4137..7baefb8 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantSynchronizationCache.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantSynchronizationCache.java
@@ -18,9 +18,9 @@
 /**
  * CVS sycnrhonization cache that ignores stale remote bytes
  */
-public class CVSDescendantSynchronizationCache extends DescendantResourceVariantTree {
+public class CVSDescendantSynchronizationCache extends DescendantResourceVariantByteStore {
 
-	public CVSDescendantSynchronizationCache(ResourceVariantTree baseCache, PersistantResourceVariantTree remoteCache) {
+	public CVSDescendantSynchronizationCache(ResourceVariantByteStore baseCache, PersistantResourceVariantByteStore remoteCache) {
 		super(baseCache, remoteCache);
 	}
 
@@ -44,7 +44,7 @@
 		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", ((PersistantResourceVariantTree)getRemoteTree()).getSyncName().toString(), resource.getFullPath().toString()))); //$NON-NLS-1$
+			CVSProviderPlugin.log(new TeamException(Policy.bind("ResourceSynchronizer.missingParentBytesOnSet", ((PersistantResourceVariantByteStore)getRemoteTree()).getSyncName().toString(), resource.getFullPath().toString()))); //$NON-NLS-1$
 		}
 		return changed;
 	}
@@ -59,4 +59,10 @@
 		return (getBytes(resource.getParent()) != null);
 	}
 
+	/* (non-Javadoc)
+	 * @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);
+	}
 }
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSRefreshOperation.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSRefreshOperation.java
index 395166a..829a34d 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSRefreshOperation.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSRefreshOperation.java
@@ -10,10 +10,6 @@
  *******************************************************************************/
 package org.eclipse.team.internal.ccvs.core.syncinfo;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.team.core.TeamException;
@@ -21,19 +17,20 @@
 import org.eclipse.team.internal.ccvs.core.*;
 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
 import org.eclipse.team.internal.ccvs.core.resources.RemoteResource;
+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.ResourceVariantTreeRefresh;
 
 /**
  * CVS Specific refresh operation
  */
-public class CVSRefreshOperation extends ResourceVariantTreeRefresh {
+public class CVSRefreshOperation extends ResourceVariantTree {
 
-	private ResourceVariantTree cache, baseCache;
+	private ResourceVariantByteStore cache, baseCache;
 	private CVSTag tag;
 	private boolean cacheFileContentsHint;
+	private CVSSyncTreeSubscriber subscriber;
 
-	public CVSRefreshOperation(ResourceVariantTree cache, ResourceVariantTree baseCache, CVSTag tag, boolean cacheFileContentsHint) {
+	public CVSRefreshOperation(ResourceVariantByteStore cache, ResourceVariantByteStore baseCache, CVSTag tag, boolean cacheFileContentsHint) {
 		this.tag = tag;
 		this.cache = cache;
 		this.baseCache = cache;
@@ -43,7 +40,7 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.team.core.subscribers.RefreshOperation#getSynchronizationCache()
 	 */
-	protected ResourceVariantTree getResourceVariantTree() {
+	protected ResourceVariantByteStore getByteStore() {
 		return cache;
 	}
 
@@ -75,31 +72,6 @@
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.team.core.subscribers.RefreshOperation#getLocalChildren(org.eclipse.core.resources.IResource)
-	 */
-	protected IResource[] members(IResource local) throws TeamException {
-		IResource[] localChildren = null;			
-		if( local.getType() != IResource.FILE && (local.exists() || local.isPhantom())) {
-			// Include all non-ignored resources including outgoing deletions
-			ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor((IContainer)local);
-			// Look inside existing folders and phantoms that are CVS folders
-			if (local.exists() || cvsFolder.isCVSFolder()) {
-				ICVSResource[] cvsChildren = cvsFolder.members(ICVSFolder.MANAGED_MEMBERS | ICVSFolder.UNMANAGED_MEMBERS);
-				List resourceChildren = new ArrayList();
-				for (int i = 0; i < cvsChildren.length; i++) {
-					ICVSResource cvsResource = cvsChildren[i];
-					resourceChildren.add(cvsResource.getIResource());
-				}
-				localChildren = (IResource[]) resourceChildren.toArray(new IResource[resourceChildren.size()]);
-			}
-		}
-		if (localChildren == null) {
-			localChildren = new IResource[0];
-		}
-		return localChildren;
-	}
-
-	/* (non-Javadoc)
 	 * @see org.eclipse.team.core.subscribers.RefreshOperation#buildRemoteTree(org.eclipse.core.resources.IResource, int, boolean, org.eclipse.core.runtime.IProgressMonitor)
 	 */
 	protected IResourceVariant fetchVariant(IResource resource, int depth, IProgressMonitor monitor) throws TeamException {
@@ -117,4 +89,18 @@
 		return super.collectChanges(local, remote, depth, monitor);
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree#getRoots()
+	 */
+	public IResource[] getRoots() {
+		return subscriber.roots();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree#getResourceVariant(org.eclipse.core.resources.IResource)
+	 */
+	public IResourceVariant getResourceVariant(IResource resource) throws TeamException {
+		return subscriber.getRemoteResource(resource, getByteStore());
+	}
+
 }
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSSynchronizationCache.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSSynchronizationCache.java
index e910a03..32579df 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSSynchronizationCache.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSSynchronizationCache.java
@@ -13,15 +13,15 @@
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.QualifiedName;
 import org.eclipse.team.core.TeamException;
-import org.eclipse.team.internal.core.subscribers.caches.PersistantResourceVariantTree;
+import org.eclipse.team.internal.core.subscribers.caches.PersistantResourceVariantByteStore;
 import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
 import org.eclipse.team.internal.ccvs.core.Policy;
 
 /**
- * Override <code>PersistantResourceVariantTree</code> to log an error
+ * Override <code>PersistantResourceVariantByteStore</code> to log an error
  * if there are no parent bytes for a file.
  */
-public class CVSSynchronizationCache extends PersistantResourceVariantTree {
+public class CVSSynchronizationCache extends PersistantResourceVariantByteStore {
 
 	public CVSSynchronizationCache(QualifiedName name) {
 		super(name);
diff --git a/bundles/org.eclipse.team.ui/.project b/bundles/org.eclipse.team.ui/.project
index 7093fb2..340fab8 100644
--- a/bundles/org.eclipse.team.ui/.project
+++ b/bundles/org.eclipse.team.ui/.project
@@ -12,6 +12,7 @@
 		<project>org.eclipse.team.core</project>
 		<project>org.eclipse.ui</project>
 		<project>org.eclipse.ui.editors</project>
+		<project>org.eclipse.ui.forms</project>
 		<project>org.eclipse.ui.ide</project>
 		<project>org.eclipse.ui.views</project>
 		<project>org.eclipse.ui.workbench.texteditor</project>
diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/subscriber/AllTestsTeamSubscriber.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/subscriber/AllTestsTeamSubscriber.java
index a5905ed..4368eb5 100644
--- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/subscriber/AllTestsTeamSubscriber.java
+++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/subscriber/AllTestsTeamSubscriber.java
@@ -28,10 +28,10 @@
 
 	public static Test suite() {
 		TestSuite suite = new TestSuite();
-	//	suite.addTest(CVSMergeSubscriberTest.suite());
-	//	suite.addTest(CVSWorkspaceSubscriberTest.suite());
+		suite.addTest(CVSMergeSubscriberTest.suite());
+		suite.addTest(CVSWorkspaceSubscriberTest.suite());
 		suite.addTest(CVSCompareSubscriberTest.suite());
-	//	suite.addTest(SyncSetTests.suite());
+		suite.addTest(SyncSetTests.suite());
 		CVSSyncSubscriberTest.setSyncSource(new SynchronizeViewTestAdapter());
 		return new CVSTestSetup(suite);
 	}
diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/SynchronizeViewTestAdapter.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/SynchronizeViewTestAdapter.java
index cb59c58..bcdb064 100644
--- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/SynchronizeViewTestAdapter.java
+++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/SynchronizeViewTestAdapter.java
@@ -43,7 +43,12 @@
 		if (info == null) {
 			info = subscriber.getSyncInfo(resource);
 			if ((info != null && info.getKind() != SyncInfo.IN_SYNC)) {
-				throw new AssertionFailedError();
+				throw new AssertionFailedError(
+						"Sync info for " 
+						+ resource.getFullPath() 
+						+ " was "
+						+ SyncInfo.kindToString(info.getKind())
+						+ " but resource was not collected");
 			}
 		}
 		return info;