*** empty log message ***
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 df51bc1..eb25afb 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
@@ -126,6 +126,7 @@
 	private static final int REPOSITORIES_STATE_FILE_VERSION_2 = -1;
 	private Map repositories = new HashMap();
 	private List repositoryListeners = new ArrayList();
+	private static List decoratorEnablementListeners = new ArrayList();
 	
 	/**
 	 * The identifier for the CVS nature
@@ -450,6 +451,21 @@
 		}
 	}
 	
+	public static void broadcastDecoratorEnablementChanged(final boolean enabled) {
+		for(Iterator it=decoratorEnablementListeners.iterator(); it.hasNext();) {
+			final ICVSDecoratorEnablementListener listener = (ICVSDecoratorEnablementListener)it.next();
+			ISafeRunnable code = new ISafeRunnable() {
+				public void run() throws Exception {
+					listener.decoratorEnablementChanged(enabled);
+				}
+				public void handleException(Throwable e) {
+					// don't log the exception....it is already being logged in Platform#run
+				}
+			};
+			Platform.run(code);
+		}
+	}
+	
 	public static void broadcastModificationStateChanges(final IResource[] resources) {
 		for(Iterator it=listeners.iterator(); it.hasNext();) {
 			final IResourceStateChangeListener listener = (IResourceStateChangeListener)it.next();
@@ -639,6 +655,15 @@
 	}
 	
 	/**
+	 * Register to receive notification of enablement of sync info decoration requirements. This
+	 * can be useful for providing lazy initialization of caches that are only required for decorating
+	 * resource with CVS information.
+	 */
+	public void addDecoratorEnablementListener(ICVSDecoratorEnablementListener listener) {
+		repositoryListeners.add(listener);
+	}
+	
+	/**
 	 * De-register a listener
 	 */
 	public void removeRepositoryListener(ICVSListener listener) {
@@ -646,6 +671,13 @@
 	}
 	
 	/**
+	 * De-register the decorator enablement listener. 
+	 */
+	public void removeDecoratorEnablementListener(ICVSDecoratorEnablementListener listener) {
+		repositoryListeners.remove(listener);
+	}
+	
+	/**
 	 * Create a repository instance from the given properties.
 	 * The supported properties are:
 	 * 
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSDecoratorEnablementListener.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSDecoratorEnablementListener.java
new file mode 100644
index 0000000..563e07f
--- /dev/null
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSDecoratorEnablementListener.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 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 v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ * IBM - Initial implementation
+ ******************************************************************************/
+package org.eclipse.team.internal.ccvs.core;
+
+/**
+ * A decorator enablement listener is notified of changes to the enablement
+ * of CVS state decorators.
+ * <p>
+ * Clients may implement this interface.
+ * </p>
+ * @see CVSProviderPlugin#addDecoratorEnablementListener(ICVSDecoratorEnablementListener)
+ */
+public interface ICVSDecoratorEnablementListener {
+	/**
+	 * Called when CVS decoration is enabled or disabled. Implementers can use the
+	 * decorator enablement change as a chance to create or destroy cached CVS information
+	 * that would help decorate CVS elements. 
+	 * 
+	 * @param enabled a flag indicating the enablement state of the decorators.
+	 */
+	void decoratorEnablementChanged(boolean enabled);
+}
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java
index 374d1ff..c62346d 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java
@@ -508,7 +508,7 @@
 		EclipseSynchronizer.getInstance().markFileAsUpdated(getIFile());
 	}
 	
-	public void handleModification(boolean forAddition) throws CVSException {
+	public boolean handleModification(boolean forAddition) throws CVSException {
 		if (isIgnored()) {			
 			// Special case handling for when a resource passes from the un-managed state
 			// to the ignored state (e.g. ignoring the ignore file). Parent dirty state must be
@@ -519,13 +519,14 @@
 			if(! resource.isDerived()) {
 				setModified(false);
 			}
-			return;
+			return true;
 		} 
-		if (EclipseSynchronizer.getInstance().contentsChangedByUpdate(getIFile()))
-			return;
-			
-		// set the modification state to what it really is and return true if the modification state changed
-		setModified(computeModified(getSyncInfo()));
+		if(!EclipseSynchronizer.getInstance().contentsChangedByUpdate(getIFile(), true /* clear update state */)) {
+			// set the modification state to what it really is and return true if the modification state changed
+			setModified(computeModified(getSyncInfo()));
+			return true;
+		}
+		return false;
 	}
 	
 	/**
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFolder.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFolder.java
index 5beb59f..c03109c 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFolder.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFolder.java
@@ -358,9 +358,9 @@
 		return indicator == EclipseSynchronizer.IS_DIRTY_INDICATOR;
 	}
 	
-	public void handleModification(boolean forAddition) throws CVSException {
+	public boolean handleModification(boolean forAddition) throws CVSException {
 		// For non-additions, we are only interested in sync info changes
-		if (isIgnored() || !forAddition) return;
+		if (isIgnored() || !forAddition) return false;
 
 		// the folder is an addition.
 		FolderSyncInfo info = getFolderSyncInfo();
@@ -368,7 +368,9 @@
 		// otherwise, flush the ancestors to recalculate
 		if (info == null) {
 			setModified((IContainer)getIResource(), EclipseSynchronizer.IS_DIRTY_INDICATOR);
+			return true;
 		}
+		return false;
 	}
 	
 	/**
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 7aa031c..de6092a 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
@@ -292,7 +292,7 @@
 		return resource;
 	}
 
-	public abstract void handleModification(boolean forAddition) throws CVSException;
+	public abstract boolean handleModification(boolean forAddition) throws CVSException;
 	
 	/**
 	 * Method created is invoked after a resource is created
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 a98fa2c..ac5ab32 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
@@ -827,7 +827,8 @@
 			}
 			
 			/*** broadcast events ***/
-			changedResources.addAll(changedFolders);				
+			changedResources.addAll(changedFolders);
+			changedResources.addAll(dirtyParents);	
 			IResource[] resources = (IResource[]) changedResources.toArray(
 				new IResource[changedResources.size()]);
 			broadcastResourceStateChanges(resources);
@@ -859,7 +860,10 @@
 			for (int i = 0; i < resources.length; i++) {
 				IResource resource = resources[i];
 				try {
-					internalSetDirtyIndicator(resource, RECOMPUTE_INDICATOR);
+					if((resource.getType() == IResource.FILE && !contentsChangedByUpdate((IFile)resource, false /* don't clear */)) ||
+					    resource.getType() != IResource.FILE) {
+						adjustDirtyStateRecursively(resource, RECOMPUTE_INDICATOR);
+					}
 				} catch (CVSException e) {
 					CVSProviderPlugin.log(e);
 				}
@@ -1230,35 +1234,36 @@
 		return SyncFileWriter.isEdited(resource);
 	}
 	
-	private void internalSetDirtyIndicator(IResource resource, String indicator) throws CVSException {		
-		adjustDirtyStateRecursively(resource, indicator);
-	}
-	
-	public void adjustDirtyStateRecursively(IResource resource, String indicator) throws CVSException {
+	private void adjustDirtyStateRecursively(IResource resource, String indicator) throws CVSException {
 		if (resource.getType() == IResource.ROOT) return;
-			try {
-				beginOperation(null);
-				try {
-					if (Policy.DEBUG_DIRTY_CACHING) {
-						debug(resource, indicator, "adjusting dirty state");
-					}
-					getSyncInfoCacheFor(resource).setDirtyIndicator(resource, indicator);
-				} finally {
-					IContainer parent = resource.getParent();
-					String parentIndicator = getDirtyIndicator(parent);
-					if(indicator == RECOMPUTE_INDICATOR) {
-						adjustDirtyStateRecursively(parent, RECOMPUTE_INDICATOR);
-					} else if(indicator == IS_DIRTY_INDICATOR && parentIndicator == NOT_DIRTY_INDICATOR) {
-						adjustDirtyStateRecursively(parent, indicator);
-					} else if(indicator == NOT_DIRTY_INDICATOR && parentIndicator == IS_DIRTY_INDICATOR) {
-						adjustDirtyStateRecursively(parent, RECOMPUTE_INDICATOR);
-					} else {
-						// parents are already in the good state
-					}
-				}
-			} finally {
-				endOperation(null);
+		try {
+			beginOperation(null);
+			
+			if (indicator == getDirtyIndicator(resource)) {
+				return;
+			} 					
+			
+			if (Policy.DEBUG_DIRTY_CACHING) {
+				debug(resource, indicator, "adjusting dirty state");
 			}
+
+			getSyncInfoCacheFor(resource).setDirtyIndicator(resource, indicator);										
+
+			IContainer parent = resource.getParent();
+			if(indicator == NOT_DIRTY_INDICATOR) {
+				adjustDirtyStateRecursively(parent, RECOMPUTE_INDICATOR);
+			}
+			
+			if(indicator == RECOMPUTE_INDICATOR) {
+				adjustDirtyStateRecursively(parent, RECOMPUTE_INDICATOR);
+			} 
+			
+			if(indicator == IS_DIRTY_INDICATOR) {
+				adjustDirtyStateRecursively(parent, indicator);
+			} 
+		} finally {
+			endOperation(null);
+		}
 	}
 
 	protected String getDirtyIndicator(IResource resource) throws CVSException {
@@ -1279,11 +1284,6 @@
 		try {
 			beginOperation(null);
 			String indicator = modified ? IS_DIRTY_INDICATOR : NOT_DIRTY_INDICATOR;
-		
-			if (indicator == getDirtyIndicator(resource)) {
-				return;
-			} 
-			
 			// set the dirty indicator and adjust the parent accordingly			
 			adjustDirtyStateRecursively(resource, indicator);
 		} finally {
@@ -1302,8 +1302,12 @@
 		sessionPropertyCache.markFileAsUpdated(file);
 	}
 	
-	protected boolean contentsChangedByUpdate(IFile file) throws CVSException {
-		return sessionPropertyCache.contentsChangedByUpdate(file);
+	protected boolean contentsChangedByUpdate(IFile file, boolean clear) throws CVSException {
+		if(file.exists()) {
+			return sessionPropertyCache.contentsChangedByUpdate(file, clear);
+		} else {
+			return false;
+		}
 	}
 
 	/**
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/FileModificationManager.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/FileModificationManager.java
index e3ee649..13eb413 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/FileModificationManager.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/FileModificationManager.java
@@ -43,6 +43,14 @@
 		
 	private Set modifiedResources = new HashSet();
 
+	// consider the following changes types and ignore the others (e.g. marker and description changes are ignored)
+	protected int INTERESTING_CHANGES = 	IResourceDelta.CONTENT | 
+																	IResourceDelta.MOVED_FROM | 
+																	IResourceDelta.MOVED_TO |
+																	IResourceDelta.OPEN | 
+																	IResourceDelta.REPLACED |
+																	IResourceDelta.TYPE;
+
 	/**
 	 * Listen for file modifications and fire modification state changes
 	 * 
@@ -68,7 +76,10 @@
 					}
 					
 					if (resource.getType()==IResource.FILE && delta.getKind() == IResourceDelta.CHANGED && resource.exists()) {
-						contentsChanged((IFile)resource);
+						int flags = delta.getFlags();
+						if((flags & INTERESTING_CHANGES) != 0) {
+							contentsChanged((IFile)resource);
+						}
 					} else if (delta.getKind() == IResourceDelta.ADDED) {
 						resourceAdded(resource);
 					} else if (delta.getKind() == IResourceDelta.REMOVED) {
@@ -143,7 +154,6 @@
 		try {
 			EclipseFile cvsFile = (EclipseFile)CVSWorkspaceRoot.getCVSFileFor(file);
 			cvsFile.handleModification(false /* addition */);
-			// add all files to the modified list
 			modifiedResources.add(file);
 		} catch (CVSException e) {
 			throw e.toCoreException();
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/SessionPropertySyncInfoCache.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/SessionPropertySyncInfoCache.java
index 71e1614..80eeb1f 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/SessionPropertySyncInfoCache.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/SessionPropertySyncInfoCache.java
@@ -14,17 +14,20 @@
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceStatus;
 import org.eclipse.core.resources.IResourceVisitor;
 import org.eclipse.core.resources.ISaveContext;
 import org.eclipse.core.resources.ISaveParticipant;
 import org.eclipse.core.resources.ISynchronizer;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.QualifiedName;
 import org.eclipse.team.core.RepositoryProvider;
 import org.eclipse.team.internal.ccvs.core.CVSException;
 import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
+import org.eclipse.team.internal.ccvs.core.ICVSDecoratorEnablementListener;
 import org.eclipse.team.internal.ccvs.core.Policy;
 import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
 import org.eclipse.team.internal.ccvs.core.util.SyncFileWriter;
@@ -35,7 +38,8 @@
  * state for all cvs managed folders are persisted using the resource's plugin
  * synchronizer.
  */
-/*package*/ class SessionPropertySyncInfoCache extends SyncInfoCache implements ISaveParticipant {
+/*package*/ class SessionPropertySyncInfoCache extends SyncInfoCache 
+																		  implements ISaveParticipant, ICVSDecoratorEnablementListener {
 	
 	// key used on a folder to indicate that the resource sync has been cahced for it's children
 	private static final QualifiedName RESOURCE_SYNC_CACHED_KEY = new QualifiedName(CVSProviderPlugin.ID, "resource-sync-cached"); //$NON-NLS-1$
@@ -44,10 +48,17 @@
 	/*package*/ static final String[] NULL_IGNORES = new String[0];
 	private static final FolderSyncInfo NULL_FOLDER_SYNC_INFO = new FolderSyncInfo("", "", null, false); //$NON-NLS-1$ //$NON-NLS-2$
 	
+	private QualifiedName FOLDER_DIRTY_STATE_KEY = new QualifiedName(CVSProviderPlugin.ID, "folder-dirty-state-cached"); //$NON-NLS-1$
+	private boolean isDecoratorEnabled = true;
+	
 	/*package*/ SessionPropertySyncInfoCache() {
 		try {
 			// this save participant is removed when the plugin is shutdown.			
 			ResourcesPlugin.getWorkspace().addSaveParticipant(CVSProviderPlugin.getPlugin(), this);
+			CVSProviderPlugin.getPlugin().addDecoratorEnablementListener(this);
+
+			final ISynchronizer synchronizer = ResourcesPlugin.getWorkspace().getSynchronizer();
+			synchronizer.add(FOLDER_DIRTY_STATE_KEY);
 		} catch (CoreException e) {
 			CVSProviderPlugin.log(e.getStatus());
 		}
@@ -61,43 +72,27 @@
 	 * @return the folder ignore patterns, or an empty array if none
 	 */
 	/*package*/ String[] cacheFolderIgnores(IContainer container) throws CVSException {
-		try {
-			// don't try to load if the information is already cached
-			String[] ignores = (String[])container.getSessionProperty(IGNORE_SYNC_KEY);
-			if (ignores == null) {
-				// read folder ignores and remember it
-				ignores = SyncFileWriter.readCVSIgnoreEntries(container);
-				if (ignores == null) ignores = NULL_IGNORES;
-				container.setSessionProperty(IGNORE_SYNC_KEY, ignores);
-			}
-			return ignores;
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
+		// don't try to load if the information is already cached
+		String[] ignores = (String[])safeGetSessionProperty(container, IGNORE_SYNC_KEY);
+		if (ignores == null) {
+			// read folder ignores and remember it
+			ignores = SyncFileWriter.readCVSIgnoreEntries(container);
+			if (ignores == null) ignores = NULL_IGNORES;
+			safeSetSessionProperty(container, IGNORE_SYNC_KEY, ignores);
 		}
+		return ignores;
 	}
 
 	/*package*/ boolean isFolderSyncInfoCached(IContainer container) throws CVSException {
-		try {
-			return container.getSessionProperty(FOLDER_SYNC_KEY) != null;
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
-		}
+		return safeGetSessionProperty(container, FOLDER_SYNC_KEY) != null;
 	}
 
 	/*package*/ boolean isResourceSyncInfoCached(IContainer container) throws CVSException {
-		try {
-			return container.getSessionProperty(RESOURCE_SYNC_CACHED_KEY) != null;
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
-		}
+		return safeGetSessionProperty(container, RESOURCE_SYNC_CACHED_KEY) != null;
 	}
 	
 	/*package*/ void setResourceSyncInfoCached(IContainer container) throws CVSException {
-		try {
-			container.setSessionProperty(RESOURCE_SYNC_CACHED_KEY, RESOURCE_SYNC_CACHED);
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
-		}
+		safeSetSessionProperty(container, RESOURCE_SYNC_CACHED_KEY, RESOURCE_SYNC_CACHED);
 	}
 
 	/**
@@ -110,18 +105,13 @@
 	 * @see #cacheFolderSync
 	 */
 	/*package*/ FolderSyncInfo getCachedFolderSync(IContainer container) throws CVSException {
-		if (!container.exists()) return null;
-		try {
-			FolderSyncInfo info = (FolderSyncInfo)container.getSessionProperty(FOLDER_SYNC_KEY);
-			if (info == null) {
-				// There should be sync info but it was missing. Report the error
-				throw new CVSException(Policy.bind("EclipseSynchronizer.folderSyncInfoMissing", container.getFullPath().toString())); //$NON-NLS-1$
-			}
-			if (info == NULL_FOLDER_SYNC_INFO) return null;
-			return info;
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
+		FolderSyncInfo info = (FolderSyncInfo)safeGetSessionProperty(container, FOLDER_SYNC_KEY);
+		if (info == null) {
+			// There should be sync info but it was missing. Report the error
+			throw new CVSException(Policy.bind("EclipseSynchronizer.folderSyncInfoMissing", container.getFullPath().toString())); //$NON-NLS-1$
 		}
+		if (info == NULL_FOLDER_SYNC_INFO) return null;
+		return info;
 	}
 
 	/**
@@ -132,9 +122,9 @@
 		if (! container.exists()) return;
 		try {
 			if (container.getType() != IResource.ROOT) {
-				container.setSessionProperty(IGNORE_SYNC_KEY, null);
-				container.setSessionProperty(FOLDER_SYNC_KEY, null);
-				container.setSessionProperty(RESOURCE_SYNC_CACHED_KEY, null);
+				safeSetSessionProperty(container, IGNORE_SYNC_KEY, null);
+				safeSetSessionProperty(container, FOLDER_SYNC_KEY, null);
+				safeSetSessionProperty(container, RESOURCE_SYNC_CACHED_KEY, null);
 			}
 			IResource[] members = container.members();
 			for (int i = 0; i < members.length; i++) {
@@ -150,11 +140,7 @@
 	}
 	
 	/* package*/ void purgeResourceSyncCache(IResource resource) throws CVSException {
-		try {
-			resource.setSessionProperty(RESOURCE_SYNC_KEY, null);
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
-		}
+		safeSetSessionProperty(resource, RESOURCE_SYNC_KEY, null);
 	}
 	
 	/**
@@ -165,11 +151,7 @@
 	 * @param ignores the array of ignore patterns
 	 */
 	/*package*/ void setCachedFolderIgnores(IContainer container, String[] ignores) throws CVSException {
-		try {
-			container.setSessionProperty(IGNORE_SYNC_KEY, ignores);
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
-		}
+		safeSetSessionProperty(container, IGNORE_SYNC_KEY, ignores);
 	}
 
 
@@ -183,12 +165,10 @@
 	 */
 	/*package*/ void setCachedFolderSync(IContainer container, FolderSyncInfo info) throws CVSException {
 		if (!container.exists()) return;
-		try {
-			if (info == null) info = NULL_FOLDER_SYNC_INFO;
-			container.setSessionProperty(FOLDER_SYNC_KEY, info);
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
-		}
+		if (info == null) {
+			info = NULL_FOLDER_SYNC_INFO;
+		} 
+		safeSetSessionProperty(container, FOLDER_SYNC_KEY, info);
 	}
 
 	/*package*/ void setDirtyIndicator(IResource resource, String indicator) throws CVSException {
@@ -205,40 +185,32 @@
 			return internalGetDirtyIndicator((IContainer)resource);
 		}
 	}
+	
 	private void internalSetDirtyIndicator(IFile file, String indicator) throws CVSException {
-		try {
-			file.setSessionProperty(IS_DIRTY, indicator);
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
-		}
+		safeSetSessionProperty(file, IS_DIRTY, indicator);
 	}
+	
 	private String internalGetDirtyIndicator(IFile file) throws CVSException {
-		try {
-			String di = (String)file.getSessionProperty(IS_DIRTY);
-			if(di == null) {
-				di = RECOMPUTE_INDICATOR;
-			}
-			return di;
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
+		String di = (String)safeGetSessionProperty(file, IS_DIRTY);
+		if(di == null) {
+			di = RECOMPUTE_INDICATOR;
 		}
+		return di;
 	}
+
 	private void internalSetDirtyIndicator(IContainer container, String indicator) throws CVSException {
-		try {
-			container.setSessionProperty(IS_DIRTY, indicator);
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
-		}
+		safeSetSessionProperty(container, IS_DIRTY, indicator);
 	}
+	
 	private String internalGetDirtyIndicator(IContainer container) throws CVSException {
 		try {
-			String di = (String)container.getSessionProperty(IS_DIRTY);
+			String di = (String)safeGetSessionProperty(container, IS_DIRTY);
 			
 			// if the session property is not available then restore from persisted sync info. At this
 			// time the sync info is not flushed because we don't want the workspace to generate
 			// a delta.			
 			if(di == null) {
-				byte [] diBytes = ResourcesPlugin.getWorkspace().getSynchronizer().getSyncInfo(RESOURCE_SYNC_KEY, container);
+				byte [] diBytes = ResourcesPlugin.getWorkspace().getSynchronizer().getSyncInfo(FOLDER_DIRTY_STATE_KEY, container);
 				if(diBytes != null) {
 					di = new String(diBytes);
 					if(di.equals(NOT_DIRTY_INDICATOR)) {
@@ -264,15 +236,11 @@
 	 */
 	/*package*/ void flushDirtyCache(IResource resource) throws CVSException {
 		if (resource.exists()) {
-			try {
-				if (resource.getType() == IResource.FILE) {
-					resource.setSessionProperty(IS_DIRTY, RECOMPUTE_INDICATOR);
-					resource.setSessionProperty(CLEAN_UPDATE, null);
-				} else {
-					resource.setSessionProperty(IS_DIRTY, RECOMPUTE_INDICATOR);
-				}
-			} catch (CoreException e) {
-				throw CVSException.wrapException(e);
+			if (resource.getType() == IResource.FILE) {
+				safeSetSessionProperty(resource, IS_DIRTY, RECOMPUTE_INDICATOR);
+				safeSetSessionProperty(resource, CLEAN_UPDATE, null);
+			} else {
+				safeSetSessionProperty(resource, IS_DIRTY, RECOMPUTE_INDICATOR);
 			}
 		}
 	}
@@ -285,31 +253,21 @@
 	 * @param mFile
 	 */
 	/*package*/ void markFileAsUpdated(IFile file) throws CVSException {
-		try {
-			file.setSessionProperty(CLEAN_UPDATE, UPDATED_INDICATOR);
-			
-			// update dirty state so that decorators don't have to recompute after
-			// an update is completed.
-			contentsChangedByUpdate(file);
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
-		}
+		safeSetSessionProperty(file, CLEAN_UPDATE, UPDATED_INDICATOR);
 	}
 
-	/*package*/ boolean contentsChangedByUpdate(IFile file) throws CVSException {
-		try {
-			Object indicator = file.getSessionProperty(CLEAN_UPDATE);
-			boolean updated = false;
-			if (indicator == UPDATED_INDICATOR) {
-				// the file was changed due to a clean update (i.e. no local mods) so skip it
-				file.setSessionProperty(CLEAN_UPDATE, null);
-				file.setSessionProperty(IS_DIRTY, NOT_DIRTY_INDICATOR);
-				updated = true;
+	/*package*/ boolean contentsChangedByUpdate(IFile file, boolean clear) throws CVSException {
+		Object indicator = safeGetSessionProperty(file, CLEAN_UPDATE);
+		boolean updated = false;
+		if (indicator == UPDATED_INDICATOR) {
+			// the file was changed due to a clean update (i.e. no local mods) so skip it
+			if(clear) {
+				safeSetSessionProperty(file, CLEAN_UPDATE, null);
+				safeSetSessionProperty(file, IS_DIRTY, NOT_DIRTY_INDICATOR);
 			}
-			return updated;
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
+			updated = true;
 		}
+		return updated;
 	}
 	
 	/**
@@ -321,18 +279,13 @@
 	 * @return boolean
 	 */
 	/*package*/ boolean isSyncInfoLoaded(IContainer parent) throws CVSException {
-		try {
-			if (parent.getFolder(new Path(SyncFileWriter.CVS_DIRNAME)).exists()) {
-				if (parent.getSessionProperty(RESOURCE_SYNC_CACHED_KEY) == null)
-					return false;
-				if (parent.getSessionProperty(FOLDER_SYNC_KEY) == null)
-					return false;
+		if (parent.getFolder(new Path(SyncFileWriter.CVS_DIRNAME)).exists()) {
+			if (safeGetSessionProperty(parent, RESOURCE_SYNC_CACHED_KEY) == null)
+				return false;
+			if (safeGetSessionProperty(parent, FOLDER_SYNC_KEY) == null)
+				return false;
 //				if (parent.getSessionProperty(IGNORE_SYNC_KEY) == null)
 //					return false;
-			}
-		} catch (CoreException e) {
-			// let future operations surface the error
-			return false;
 		}
 		return true;
 	}
@@ -341,21 +294,51 @@
 	 * @see org.eclipse.team.internal.ccvs.core.resources.SyncInfoCache#getCachedSyncBytes(org.eclipse.core.resources.IResource)
 	 */
 	/*package*/ byte[] getCachedSyncBytes(IResource resource) throws CVSException {
+		return (byte[])safeGetSessionProperty(resource, RESOURCE_SYNC_KEY);
+	}
+
+	Object safeGetSessionProperty(IResource resource, QualifiedName key) throws CVSException {
 		try {
-			return (byte[])resource.getSessionProperty(RESOURCE_SYNC_KEY);
+			return resource.getSessionProperty(key);
 		} catch (CoreException e) {
+			IStatus status = e.getStatus();
+			if(status != null) {
+				int code = e.getStatus().getCode();
+				if(code != IResourceStatus.RESOURCE_NOT_LOCAL ||
+					code != IResourceStatus.RESOURCE_NOT_FOUND) {
+						// ignore error since a phantom would of been created
+						// and we can safely ignore these cases
+						return null;
+				}
+			}
+			// some other error we did not expect
 			throw CVSException.wrapException(e);
 		}
 	}
+	
+	void safeSetSessionProperty(IResource resource, QualifiedName key, Object value) throws CVSException {
+			try {
+				resource.setSessionProperty(key, value);
+			} catch (CoreException e) {
+				IStatus status = e.getStatus();
+				if(status != null) {
+					int code = e.getStatus().getCode();
+					if(code == IResourceStatus.RESOURCE_NOT_LOCAL ||
+					    code == IResourceStatus.RESOURCE_NOT_FOUND) {
+					    	// ignore error since a phantom would of been created
+					    	// and we can safely ignore these cases
+					}
+					// some other error we did not expect
+					throw CVSException.wrapException(e);
+				}
+			}
+		}
+	
 	/**
 	 * @see org.eclipse.team.internal.ccvs.core.resources.SyncInfoCache#setCachedSyncBytes(org.eclipse.core.resources.IResource, byte[])
 	 */
 	/*package*/ void setCachedSyncBytes(IResource resource, byte[] syncBytes) throws CVSException {
-		try {
-			resource.setSessionProperty(RESOURCE_SYNC_KEY, syncBytes);
-		} catch (CoreException e) {
-			throw CVSException.wrapException(e);
-		}
+		safeSetSessionProperty(resource, RESOURCE_SYNC_KEY, syncBytes);
 	}
 
 	/* (non-Javadoc)
@@ -396,10 +379,9 @@
 		boolean fullSave = (context.getKind() == ISaveContext.FULL_SAVE);
 		boolean projectSave = (context.getKind() == ISaveContext.PROJECT_SAVE);
 		
-		if(projectSave || fullSave) {
+		if(isDecoratorEnabled && (projectSave || fullSave)) {
 			// persist all session properties for folders into sync info.
 			final ISynchronizer synchronizer = ResourcesPlugin.getWorkspace().getSynchronizer();
-			synchronizer.add(RESOURCE_SYNC_KEY);
 		
 			// traverse the workspace looking for CVS managed projects or just the 
 			// specific projects being closed
@@ -430,7 +412,7 @@
 									CVSProviderPlugin.log(e);
 								}
 								if(di != null) {
-									synchronizer.setSyncInfo(RESOURCE_SYNC_KEY, resource, di.getBytes());
+									synchronizer.setSyncInfo(FOLDER_DIRTY_STATE_KEY, resource, di.getBytes());
 								}								
 							}
 							return true;
@@ -440,4 +422,41 @@
 			}
 		}
 	}
+
+	/* (non-Javadoc)
+	 * @see ICVSDecoratorEnablementListener#decoratorEnablementChanged(boolean)
+	 */
+	public void decoratorEnablementChanged(boolean enabled) {
+		// DECORATOR enable this code once PR 32354 is fixed.
+		// In addition, try and remove any code paths that are not required if the decorators
+		// are turned off.
+//		isDecoratorEnabled = enabled;
+//		if(!enabled) {
+//			flushDirtyStateFromDisk();		
+//		}
+	}
+	
+	/* 
+	 * Called to clear the folder dirty state from the resource sync tree and stop persisting
+	 * these values to disk.
+	 */
+	private void flushDirtyStateFromDisk() {
+		final ISynchronizer synchronizer = ResourcesPlugin.getWorkspace().getSynchronizer();
+	
+		IProject[] projects;
+		projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+
+		for (int i = 0; i < projects.length; i++) {
+			IProject project = projects[i];
+			RepositoryProvider provider = RepositoryProvider.getProvider(
+													project,
+													CVSProviderPlugin.getTypeId());
+													
+			try {
+				synchronizer.flushSyncInfo(FOLDER_DIRTY_STATE_KEY, project, IResource.DEPTH_INFINITE);
+			} catch (CoreException e) {
+				CVSProviderPlugin.log(e.getStatus());
+			}
+		}
+	}
 }
\ No newline at end of file
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/SyncFileChangeListener.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/SyncFileChangeListener.java
index 1eda04c..5d707e8 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/SyncFileChangeListener.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/SyncFileChangeListener.java
@@ -50,6 +50,15 @@
  * See: http://dev.eclipse.org/bugs/show_bug.cgi?id=12386
  */
 public class SyncFileChangeListener implements IResourceChangeListener {
+	
+	// consider the following changes types and ignore the others (e.g. marker and description changes are ignored)
+	protected int INTERESTING_CHANGES = 	IResourceDelta.CONTENT | 
+																	IResourceDelta.MOVED_FROM | 
+																	IResourceDelta.MOVED_TO |
+																	IResourceDelta.OPEN | 
+																	IResourceDelta.REPLACED |
+																	IResourceDelta.TYPE;
+	
 	/*
 	 * When a resource changes this method will detect if the changed resources is a meta file that has changed 
 	 * by a 3rd party. For example, if the command line tool was run and then the user refreshed from local. To
@@ -75,9 +84,17 @@
 						if (!resource.isAccessible()) return false;
 						if ((delta.getFlags() & IResourceDelta.OPEN) != 0) return false;
 					}
-					
+															
 					String name = resource.getName();
 					int kind = delta.getKind();
+					
+					// if the file has changed but not in a way that we care
+					// then ignore the change (e.g. marker changes to files).
+					if(kind == IResourceDelta.CHANGED && 
+						(delta.getFlags() & INTERESTING_CHANGES) == 0) {
+							return true;
+					}
+					
 					IResource[] toBeNotified = new IResource[0];
 					
 					if(name.equals(SyncFileWriter.CVS_DIRNAME)) {
@@ -92,7 +109,7 @@
 							}
 						}
 					}
-					
+										
 					if(isMetaFile(resource)) {
 						toBeNotified = handleChangedMetaFile(resource, kind);
 					} else if(name.equals(SyncFileWriter.IGNORE_FILE)) {