Bug 148990 [Subscriber] Failure to update files that are removed from server using rm
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/UpdateContentCachingService.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/UpdateContentCachingService.java
index c62d28e..aedc283 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/UpdateContentCachingService.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/UpdateContentCachingService.java
@@ -10,8 +10,7 @@
  *******************************************************************************/
 package org.eclipse.team.internal.ccvs.core.resources;
 
-import java.util.ArrayList;
-import java.util.Date;
+import java.util.*;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
@@ -23,7 +22,7 @@
 import org.eclipse.team.internal.ccvs.core.*;
 import org.eclipse.team.internal.ccvs.core.client.*;
 import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
-import org.eclipse.team.internal.ccvs.core.client.listeners.ICommandOutputListener;
+import org.eclipse.team.internal.ccvs.core.client.listeners.*;
 import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation;
 import org.eclipse.team.internal.ccvs.core.connection.CVSServerException;
 import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
@@ -32,13 +31,14 @@
 /**
  * This class can be used to fetch and cache file contents for remote files.
  */
-public class UpdateContentCachingService {
+public class UpdateContentCachingService implements IUpdateMessageListener {
 
 	private CVSRepositoryLocation repository;
 	private ICVSFolder remoteRoot;
 	private final CVSTag tag;
 	private final int depth;
 	private boolean fetchAbsentDirectories = true;
+	private ArrayList removed = new ArrayList();
 
 	public class SandboxUpdate extends Update {
 		
@@ -228,7 +228,7 @@
 				Command.NO_GLOBAL_OPTIONS,
 				getLocalOptions(),
 				new String[] { Session.CURRENT_LOCAL_FOLDER },
-				null,
+				new UpdateListener(this),
 				Policy.subMonitorFor(monitor, 90));
 			if (!status.isOK()) {
 				if (status.getCode() == CVSStatus.SERVER_ERROR) {
@@ -240,6 +240,11 @@
 					throw new CVSException(status);
 				}
 			}
+			for (Iterator iterator = removed.iterator(); iterator.hasNext();) {
+				ICVSResource resource = (ICVSResource) iterator.next();
+				if (resource.exists())
+					resource.delete();
+			}
 		} finally {
 			session.close();
 			monitor.done();
@@ -270,4 +275,29 @@
 		
 		return Command.NO_LOCAL_OPTIONS;
 	}
+
+	public void directoryDoesNotExist(ICVSFolder commandRoot, String path) {
+		try {
+			removed.add(commandRoot.getChild(path));
+		} catch (CVSException e) {
+			CVSProviderPlugin.log(e);
+		}
+	}
+
+	public void directoryInformation(ICVSFolder commandRoot, String path,
+			boolean newDirectory) {
+		// Nothing to do
+	}
+
+	public void fileDoesNotExist(ICVSFolder parent, String filename) {
+		try {
+			removed.add(parent.getChild(filename));
+		} catch (CVSException e) {
+			CVSProviderPlugin.log(e);
+		}
+	}
+
+	public void fileInformation(int type, ICVSFolder parent, String filename) {
+		// Nothing to do
+	}
 }
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/CacheTreeContentsOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/CacheTreeContentsOperation.java
index 3a845e0..876f12d 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/CacheTreeContentsOperation.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/CacheTreeContentsOperation.java
@@ -27,6 +27,8 @@
 import org.eclipse.team.internal.ccvs.core.*;
 import org.eclipse.team.internal.ccvs.core.client.*;
 import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
+import org.eclipse.team.internal.ccvs.core.client.listeners.IUpdateMessageListener;
+import org.eclipse.team.internal.ccvs.core.client.listeners.UpdateListener;
 import org.eclipse.team.internal.ccvs.core.resources.RemoteFile;
 import org.eclipse.team.internal.ccvs.ui.CVSUIMessages;
 import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
@@ -151,7 +153,21 @@
                 Command.NO_GLOBAL_OPTIONS,
                 getLocalOptions(true),
                 resources,
-                null,
+                new UpdateListener(new IUpdateMessageListener() {
+					public void fileInformation(int type, ICVSFolder parent, String filename) {
+						// Do nothing
+					}
+					public void fileDoesNotExist(ICVSFolder parent, String filename) {
+						// Do nothing
+					}
+					public void directoryInformation(ICVSFolder commandRoot, String path,
+							boolean newDirectory) {
+						// Do nothing
+					}
+					public void directoryDoesNotExist(ICVSFolder commandRoot, String path) {
+						// Do nothing
+					}
+				}),
                 monitor);
 	}
 
@@ -190,5 +206,12 @@
 	public boolean consultModelsForMappings() {
 		return false;
 	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.team.internal.ccvs.ui.operations.CVSOperation#isReportableError(org.eclipse.core.runtime.IStatus)
+	 */
+	protected boolean isReportableError(IStatus status) {
+		return super.isReportableError(status) && status.getSeverity() == IStatus.ERROR;
+	}
 
 }
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 2028413..88e1d16 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
@@ -612,6 +612,23 @@
     	updateResources(project, new String[] { "a.txt"}, false);
     }
     
+    public void testUpdateOfRemotelyRemovedFile() throws CoreException, IOException {
+    	IProject project = createProject(new String[] { "a.txt"});
+    	IProject copy = checkoutCopy(project, "-copy");
+    	//Create a file and add it to version control (but don't commit)
+    	addResources(copy, new String[] { "b.txt"}, false);
+    	// Change the revision of the file so it appears to exist remotely
+    	ICVSFile file = CVSWorkspaceRoot.getCVSFileFor(copy.getFile("b.txt"));
+    	byte[] syncBytes = file.getSyncBytes();
+    	syncBytes = ResourceSyncInfo.setRevision(syncBytes, "1.1");
+    	file.setSyncBytes(syncBytes, ICVSFile.UNKNOWN);
+    	file.checkedIn(null, true);
+    	// Update the project and verify that the file gets removed
+    	updateProject(copy, null, false);
+    	assertEquals(project, copy);
+    	
+    }
+    
     public void testMergeWithTrailingLineFeeds() throws CoreException, IOException {
 		IProject project = createProject("testFileConflict", new String[] { "file1.txt"});
 		// Set the contents of file1.txt to ensure proper merging