Eclipse refactoring...
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java
index 799fe56..1db4af6 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java
@@ -22,6 +22,7 @@
 import org.eclipse.team.internal.ccvs.core.CVSProvider;
 import org.eclipse.team.internal.ccvs.core.Policy;
 import org.eclipse.team.internal.ccvs.core.client.Command.QuietOption;
+import org.eclipse.team.internal.ccvs.core.resources.EclipseSynchronizer;
 import org.eclipse.team.internal.ccvs.core.util.OrphanedFolderListener;
 import org.eclipse.team.internal.ccvs.core.util.ProjectDescriptionManager;
 import org.eclipse.team.internal.ccvs.core.util.Util;
@@ -152,6 +153,7 @@
 		Policy.localize("org.eclipse.team.internal.ccvs.core.messages"); //$NON-NLS-1$
 
 		CVSProvider.startup();
+		EclipseSynchronizer.startup();
 		ProjectDescriptionManager.initializeChangeListener();
 		new OrphanedFolderListener().register();
 	}
@@ -162,7 +164,9 @@
 	public void shutdown() throws CoreException {
 		super.shutdown();
 		CVSProvider.shutdown();
+		EclipseSynchronizer.shutdown();
 	}
+	
 		
 	/*
 	 * Add a resource change listener to the workspace in order to respond to 
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSTeamProvider.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSTeamProvider.java
index 95ac8a2..615cff9 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSTeamProvider.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSTeamProvider.java
@@ -190,9 +190,9 @@
 			try {		
 				// Auto-add parents if they are not already managed
 				IContainer parent = resources[i].getParent();
-				// XXX Need to consider workspace root
 				ICVSFolder cvsParent = CVSWorkspaceRoot.getCVSFolderFor(parent);
-				while (parent.getType()!=IResource.PROJECT && !cvsParent.isManaged()) {
+				while (parent.getType()!=IResource.PROJECT && 
+						parent.getType()!=IResource.ROOT && !cvsParent.isManaged()) {
 					folders.add(parent.getProjectRelativePath().toString());
 					parent = parent.getParent();
 				}
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseResource.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseResource.java
index e752f4e..47118d6 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseResource.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseResource.java
@@ -236,6 +236,8 @@
 	 * @see ICVSResource#unmanage()
 	 */
 	public void unmanage() throws CVSException {
-		EclipseSynchronizer.getInstance().deleteResourceSync(resource, new NullProgressMonitor());
+		if(isManaged()) {
+			EclipseSynchronizer.getInstance().deleteResourceSync(resource, new NullProgressMonitor());
+		}
 	}
 }
\ No newline at end of file
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseSynchronizer.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseSynchronizer.java
index 409debc..b91b8dc 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseSynchronizer.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseSynchronizer.java
@@ -75,23 +75,10 @@
 	
 	private static final boolean DEBUG = false;
 	
-	private EclipseSynchronizer() {
-		getSynchronizer().add(RESOURCE_SYNC_KEY);
-		getSynchronizer().add(RESOURCE_SYNC_LOADED_KEY);
-		getSynchronizer().add(FOLDER_SYNC_KEY);
-		getSynchronizer().add(IGNORE_SYNC_KEY);
-		try {
-			flushAll(ResourcesPlugin.getWorkspace().getRoot(), false /*don't purge from disk*/);
-		} catch(CVSException e) {
-			// severe problem, it would mean that we are working with stale sync info
-			CVSProviderPlugin.log(e.getStatus());
-		}
+	private EclipseSynchronizer() {		
 	}
 	
-	public static EclipseSynchronizer getInstance() {
-		if (instance == null) {
-			instance = new EclipseSynchronizer();						
-		}
+	public static EclipseSynchronizer getInstance() {		
 		return instance;
 	}
 
@@ -179,6 +166,7 @@
 	
 	public void setIgnored(IResource resource, String pattern) throws CVSException {
 		SyncFileWriter.addCvsIgnoreEntry(CVSWorkspaceRoot.getCVSResourceFor(resource), pattern);
+		TeamPlugin.getManager().broadcastResourceStateChanges(new IResource[] {resource});
 	}
 		
 	public IResource[] members(IContainer folder) throws CVSException {
@@ -199,6 +187,29 @@
 		}
 	}
 	
+	static public void startup() {
+		Assert.isTrue(instance==null);
+		instance = new EclipseSynchronizer();	
+		getSynchronizer().add(RESOURCE_SYNC_KEY);
+		getSynchronizer().add(RESOURCE_SYNC_LOADED_KEY);
+		getSynchronizer().add(FOLDER_SYNC_KEY);
+		getSynchronizer().add(IGNORE_SYNC_KEY);
+		try {
+			flushAll(ResourcesPlugin.getWorkspace().getRoot(), false /*don't purge from disk*/);
+		} catch(CVSException e) {
+			//	// severe problem, it would mean that we are working with stale sync info
+			CVSProviderPlugin.log(e.getStatus());
+		}					
+	}
+	
+	static public void shutdown() {
+		// so that the workspace won't persist cached sync info
+		getSynchronizer().remove(RESOURCE_SYNC_KEY);
+		getSynchronizer().remove(RESOURCE_SYNC_LOADED_KEY);
+		getSynchronizer().remove(FOLDER_SYNC_KEY);
+		getSynchronizer().remove(IGNORE_SYNC_KEY);
+	}
+	
 	public void beginOperation(IProgressMonitor monitor) throws CVSException {
 		if (nestingCount++ == 0) {
 			// any work here?
@@ -467,7 +478,7 @@
 		}
 	}
 	
-	private void flushAll(final IContainer root, final boolean purgeFromDisk) throws CVSException {
+	static private void flushAll(final IContainer root, final boolean purgeFromDisk) throws CVSException {
 		if (! (root.exists() || root.isPhantom())) return;
 		try {
 			// purge sync information from children
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSDecorator.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSDecorator.java
index 0e672e9..63a3b87 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSDecorator.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSDecorator.java
@@ -6,6 +6,7 @@
  */
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -16,6 +17,7 @@
 import java.util.Set;
 
 import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
 import org.eclipse.core.resources.IResourceVisitor;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
@@ -33,6 +35,7 @@
 import org.eclipse.team.core.TeamPlugin;
 import org.eclipse.team.internal.ccvs.core.CVSProvider;
 import org.eclipse.team.internal.ccvs.core.util.Assert;
+import org.eclipse.team.internal.ccvs.core.util.ResourceDeltaVisitor;
 
 /**
  * Classes registered with the workbench decoration extension point. The <code>CVSDecorationRunnable</code> class
@@ -66,6 +69,25 @@
 	
 	private Hashtable imageCache = new Hashtable();
 	
+	private ChangeListener changeListener;
+	
+	private class ChangeListener extends ResourceDeltaVisitor {
+		List changedResources = new ArrayList();
+		protected void handleAdded(IResource[] resources) {
+		}
+		protected void handleRemoved(IResource[] resources) {
+		}
+		protected void handleChanged(IResource[] resources) {
+			changedResources.addAll(Arrays.asList(resources));
+		}
+		protected void finished() {
+			resourceStateChanged((IResource[])changedResources.toArray(new IResource[changedResources.size()]));
+		}
+		protected int getEventMask() {
+			return IResourceChangeEvent.PRE_AUTO_BUILD;
+		}
+	}
+	
 	public CVSDecorator() {
 		// The decorator is a singleton, there should never be more than one instance.
 		// temporary until the UI component properly calls dispose when the workbench shutsdown
@@ -76,6 +98,8 @@
 		decoratorUpdateThread = new Thread(new CVSDecorationRunnable(this), "CVS"); //$NON-NLS-1$
 		decoratorUpdateThread.start();
 		TeamPlugin.getManager().addResourceStateChangeListener(this);
+		changeListener = new ChangeListener();
+		changeListener.register();
 	}
 
 	public String decorateText(String text, Object o) {
@@ -348,10 +372,15 @@
 	 */
 	public void dispose() {
 		super.dispose();
+		
+		// terminate decoration thread
 		shutdown();
 		
+		// unregister change listeners
+		changeListener.register();
 		TeamPlugin.getManager().removeResourceStateChangeListener(this);
 		
+		// dispose of images created as overlays
 		decoratorNeedsUpdating.clear();
 		cache.clear();
 		Iterator it = imageCache.values().iterator();
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/AddAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/AddAction.java
index c00ca4a..c604079 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/AddAction.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/AddAction.java
@@ -16,6 +16,7 @@
 import org.eclipse.core.runtime.SubProgressMonitor;
 import org.eclipse.jface.action.IAction;
 import org.eclipse.team.ccvs.core.CVSTeamProvider;
+import org.eclipse.team.ccvs.core.ICVSFolder;
 import org.eclipse.team.ccvs.core.ICVSResource;
 import org.eclipse.team.core.ITeamManager;
 import org.eclipse.team.core.ITeamProvider;
@@ -70,7 +71,11 @@
 			ITeamProvider provider = manager.getProvider(resources[i].getProject());
 			if(provider == null) return false;
 			ICVSResource cvsResource = CVSWorkspaceRoot.getCVSResourceFor(resources[i]);
-			if (cvsResource.isManaged()) return false;
+			if(cvsResource.isFolder()) {
+				if(((ICVSFolder)cvsResource).isCVSFolder()) return false;
+			} else {
+				if (cvsResource.isManaged()) return false;
+			}
 		}
 		return true;
 	}
diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/CVSProviderTest.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/CVSProviderTest.java
index f554913..b09367e 100644
--- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/CVSProviderTest.java
+++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/CVSProviderTest.java
@@ -11,6 +11,7 @@
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.team.ccvs.core.CVSProviderPlugin;
 import org.eclipse.team.ccvs.core.CVSTag;
 import org.eclipse.team.core.TeamException;
@@ -165,6 +166,17 @@
 		getProvider(copy).get(new IResource[] {copy}, IResource.DEPTH_INFINITE, DEFAULT_MONITOR);
 		assertEquals(project, copy);
 	}
+	
+	public void testAdd() throws TeamException, CoreException, IOException {		
+		// Create a project
+		IProject project = createProject("testAdd", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt" });
+		addResources(project, new String[] { "added.txt", "folder2/", "folder2/added.txt" }, false);
+
+		// get the remote conetns
+		getProvider(project).add(new IResource[] {project}, IResource.DEPTH_INFINITE, DEFAULT_MONITOR);
+		getProvider(project).checkin(new IResource[] {project}, IResource.DEPTH_INFINITE, DEFAULT_MONITOR);
+		assertLocalStateEqualsRemote(project);
+	}
 
 }