Fixing the update behavior in the merge editor. In progress.
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/merge/UpdateMergeAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/merge/UpdateMergeAction.java
index 5f918f5..5c894e1 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/merge/UpdateMergeAction.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/merge/UpdateMergeAction.java
@@ -9,31 +9,118 @@
 import java.util.Arrays;
 import java.util.List;
 
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.jface.viewers.ISelectionProvider;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.team.ccvs.core.CVSTag;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.core.sync.IRemoteResource;
+import org.eclipse.team.core.sync.RemoteSyncElement;
+import org.eclipse.team.internal.ccvs.core.CVSException;
 import org.eclipse.team.internal.ccvs.core.client.Command;
 import org.eclipse.team.internal.ccvs.core.client.Update;
+import org.eclipse.team.internal.ccvs.core.resources.CVSRemoteSyncElement;
+import org.eclipse.team.internal.ccvs.ui.RepositoryManager;
 import org.eclipse.team.internal.ccvs.ui.sync.CVSSyncCompareInput;
 import org.eclipse.team.internal.ccvs.ui.sync.UpdateSyncAction;
+import org.eclipse.team.ui.sync.ITeamNode;
 
+/*
+ * To be done:
+ * 1. add another action that allows a force merge merging since we can't tell the manual vs automatic conflicts when building the sync tree.
+ * 2. fix progress monitoring
+ */
 public class UpdateMergeAction extends UpdateSyncAction {
 	public UpdateMergeAction(CVSSyncCompareInput model, ISelectionProvider sp, String label, Shell shell) {
 		super(model, sp, label, shell);
 	}
-	protected Command.LocalOption[] getLocalOptions(Command.LocalOption[] baseOptions) {
-		List list = new ArrayList();
-		list.addAll(Arrays.asList(baseOptions));
+		
+	/*
+	 * @see UpdateSyncAction#runUpdateDeep(IProgressMonitor, List, RepositoryManager)
+ 	 * incoming-change
+ 	 * incoming-deletion
+	 */
+	protected void runUpdateDeep(ITeamNode[] nodes, RepositoryManager manager, IProgressMonitor monitor) throws TeamException {		
+		ITeamNode[] incoming = removeOutgoing(nodes);
+		for (int i = 0; i < incoming.length; i++) {
+			CVSRemoteSyncElement element = getSyncElementFrom(incoming[i]);
+			if(element!=null) {
+				makeRemoteLocal(element);
+			}
+		}
+	}
+		
+	/*
+	 * @see UpdateSyncAction#runUpdateIgnoreLocalShallow(IProgressMonitor, List, RepositoryManager)
+	 * incoming-addition
+	 * incoming-conflict (no-merge)
+	 */
+	protected void runUpdateIgnoreLocalShallow(ITeamNode[] nodes, RepositoryManager manager, IProgressMonitor monitor)	throws TeamException {
+		runUpdateDeep(nodes, manager, monitor);
+	}
+
+	/*
+	 * @see UpdateSyncAction#runUpdateShallow(ITeamNode[], RepositoryManager, IProgressMonitor)
+	 */
+	protected void runUpdateShallow(ITeamNode[] nodes, RepositoryManager manager, IProgressMonitor monitor) throws TeamException {	
 		CVSTag startTag = ((MergeEditorInput)getDiffModel()).getStartTag();
 		CVSTag endTag = ((MergeEditorInput)getDiffModel()).getEndTag();
+	
+		Command.LocalOption[] options = new Command.LocalOption[] {
+			Command.DO_NOT_RECURSE,
+			Update.makeArgumentOption(Update.JOIN, startTag.getName()),
+			Update.makeArgumentOption(Update.JOIN, endTag.getName()) };
 
-		if(!Update.IGNORE_LOCAL_CHANGES.isElementOf(baseOptions)) {
-			list.add(Update.makeArgumentOption(Update.JOIN, startTag.getName()));
-			list.add(Update.makeArgumentOption(Update.JOIN, endTag.getName()));
-		} else {
-			//list.add(Update.makeTagOption(endTag));
-			list.add(Update.makeArgumentOption(Update.JOIN, endTag.getName()));
-		}
-		return (Command.LocalOption[]) list.toArray(new Command.LocalOption[list.size()]);
+		// run a join update using the start and end tags and the join points
+		manager.update(getIResourcesFrom(nodes), options, false, monitor);
 	}
-}
+
+	private ITeamNode[] removeOutgoing(ITeamNode[] nodes) {
+		List incomingNodes = new ArrayList();
+		for (int i = 0; i < nodes.length; i++) {
+			// filter out pseudo conflicts
+			if((nodes[i].getKind() & RemoteSyncElement.PSEUDO_CONFLICT) == 0) {
+				switch((nodes[i].getKind() & RemoteSyncElement.DIRECTION_MASK)) {
+					case RemoteSyncElement.OUTGOING: break; // ignore
+					case RemoteSyncElement.INCOMING:
+					case RemoteSyncElement.CONFLICTING:
+						incomingNodes.add(nodes[i]);
+				}
+			}
+		}
+		return (ITeamNode[])incomingNodes.toArray(new ITeamNode[incomingNodes.size()]);
+	}
+	
+	private void makeRemoteLocal(CVSRemoteSyncElement element) throws CVSException {
+		IRemoteResource remote = element.getRemote();
+		IResource local = element.getLocal();
+		try {
+			if(remote==null) {
+				local.delete(false, null);
+			} else {
+				if(remote.isContainer()) {
+					if(!local.exists()) {
+						((IFolder)local).create(false /*don't force*/, true /*local*/, null);
+					}
+				} else {
+					IFile localFile = (IFile)local;
+					if(local.exists()) {
+						localFile.setContents(remote.getContents(new NullProgressMonitor()), false /*don't force*/, true /*keep history*/, null);
+					} else {
+						localFile.create(remote.getContents(new NullProgressMonitor()), false /*don't force*/, null);
+					}
+				}
+			}
+		} catch(CoreException e) {
+			throw new CVSException("Problems merging remote resources into workspace", e);
+		} catch(TeamException e) {
+			throw new CVSException("Problems merging remote resources into workspace", e);
+		}
+	}	
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/sync/UpdateSyncAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/sync/UpdateSyncAction.java
index bcf7c93..9a08d35 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/sync/UpdateSyncAction.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/sync/UpdateSyncAction.java
@@ -156,17 +156,18 @@
 					parentConflictElements.add(parent);
 				}
 			}
-			int kind = changed[i].getKind();
-			IResource resource = changed[i].getResource();
+			ITeamNode changedNode = changed[i];
+			int kind = changedNode.getKind();
+			IResource resource = changedNode.getResource();
 			switch (kind & Differencer.DIRECTION_MASK) {
 				case ITeamNode.INCOMING:
 					switch (kind & Differencer.CHANGE_TYPE_MASK) {
 						case Differencer.ADDITION:
-							updateIgnoreLocalShallow.add(resource);
+							updateIgnoreLocalShallow.add(changedNode);
 							break;
 						case Differencer.DELETION:
 						case Differencer.CHANGE:
-							updateDeep.add(resource);
+							updateDeep.add(changedNode);
 							break;
 					}
 					break;
@@ -174,14 +175,14 @@
 					switch (kind & Differencer.CHANGE_TYPE_MASK) {
 						case Differencer.ADDITION:
 							// Unmanage the file if necessary and delete it.
-							deletions.add(changed[i]);
+							deletions.add(changedNode);
 							break;
 						case Differencer.DELETION:
-							makeIncoming.add(changed[i]);
-							updateDeep.add(resource);
+							makeIncoming.add(changedNode);
+							updateDeep.add(changedNode);
 							break;
 						case Differencer.CHANGE:
-							updateIgnoreLocalShallow.add(resource);
+							updateIgnoreLocalShallow.add(changedNode);
 							break;
 					}
 					break;
@@ -189,18 +190,18 @@
 					switch (kind & Differencer.CHANGE_TYPE_MASK) {
 						case Differencer.ADDITION:
 							// To do: conflicting addition: must make incoming first
-							makeIncoming.add(changed[i]);
-							updateIgnoreLocalShallow.add(resource);
+							makeIncoming.add(changedNode);
+							updateIgnoreLocalShallow.add(changedNode);
 							break;
 						case Differencer.DELETION:
 							// Doesn't happen, these nodes don't appear in the tree.
 							break;
 						case Differencer.CHANGE:
 							// Depends on the flag.
-							if (onlyUpdateAutomergeable && (changed[i].getKind() & IRemoteSyncElement.AUTOMERGE_CONFLICT) != 0) {
-								updateShallow.add(resource);
+							if (onlyUpdateAutomergeable && (changedNode.getKind() & IRemoteSyncElement.AUTOMERGE_CONFLICT) != 0) {
+								updateShallow.add(changedNode);
 							} else {
-								updateIgnoreLocalShallow.add(resource);
+								updateIgnoreLocalShallow.add(changedNode);
 							}
 							break;
 					}
@@ -233,37 +234,25 @@
 			Iterator it = makeIncoming.iterator();
 			while (it.hasNext()) {
 				ITeamNode node = (ITeamNode)it.next();
-				if (node instanceof TeamFile) {
-					CVSRemoteSyncElement element = (CVSRemoteSyncElement)((TeamFile)node).getMergeResource().getSyncElement();
-					element.makeIncoming(monitor);
-				} else if (node instanceof ChangedTeamContainer) {
-					CVSRemoteSyncElement element = (CVSRemoteSyncElement)((ChangedTeamContainer)node).getMergeResource().getSyncElement();
-					element.makeIncoming(monitor);
-				}
+				CVSRemoteSyncElement element = getSyncElementFrom(node);
 			}
 			// Outgoing additions must be unmanaged (if necessary) and locally deleted.
 			it = deletions.iterator();
 			while (it.hasNext()) {
 				ITeamNode node = (ITeamNode)it.next();
-				if (node instanceof TeamFile) {
-					CVSRemoteSyncElement element = (CVSRemoteSyncElement)((TeamFile)node).getMergeResource().getSyncElement();
-					element.makeIncoming(monitor);
-					element.getLocal().delete(true, monitor);
-				} else if (node instanceof ChangedTeamContainer) {
-					CVSRemoteSyncElement element = (CVSRemoteSyncElement)((ChangedTeamContainer)node).getMergeResource().getSyncElement();
-					element.makeIncoming(monitor);
-					element.getLocal().delete(true, monitor);
-				}
+				CVSRemoteSyncElement element = getSyncElementFrom(node);
+				element.makeIncoming(monitor);
+				element.getLocal().delete(true, monitor);
 			}
 			
 			if (updateShallow.size() > 0) {
-				manager.update((IResource[])updateShallow.toArray(new IResource[0]), getLocalOptions(new Command.LocalOption[] { Command.DO_NOT_RECURSE }), false, monitor);
+				runUpdateShallow((ITeamNode[])updateShallow.toArray(new ITeamNode[updateShallow.size()]), manager, monitor);
 			}
 			if (updateIgnoreLocalShallow.size() > 0) {
-				manager.update((IResource[])updateIgnoreLocalShallow.toArray(new IResource[0]), getLocalOptions(new Command.LocalOption[] { Update.IGNORE_LOCAL_CHANGES, Command.DO_NOT_RECURSE }), false, monitor);
+				runUpdateIgnoreLocalShallow((ITeamNode[])updateIgnoreLocalShallow.toArray(new ITeamNode[updateIgnoreLocalShallow.size()]), manager, monitor);
 			}
 			if (updateDeep.size() > 0) {
-				manager.update((IResource[])updateDeep.toArray(new IResource[0]), getLocalOptions(Command.NO_LOCAL_OPTIONS), false, monitor);
+				runUpdateDeep((ITeamNode[])updateDeep.toArray(new ITeamNode[updateDeep.size()]), manager, monitor);
 			}
 		} catch (final TeamException e) {
 			getShell().getDisplay().syncExec(new Runnable() {
@@ -283,8 +272,17 @@
 		}
 		return syncSet;
 	}
-	protected Command.LocalOption[] getLocalOptions(Command.LocalOption[] baseOptions) {
-		return baseOptions;
+	
+	protected void runUpdateDeep(ITeamNode[] nodes, RepositoryManager manager, IProgressMonitor monitor) throws TeamException {
+		manager.update(getIResourcesFrom(nodes), Command.NO_LOCAL_OPTIONS, false, monitor);
+	}
+	
+	protected void runUpdateIgnoreLocalShallow(ITeamNode[] nodes, RepositoryManager manager, IProgressMonitor monitor) throws TeamException {
+		manager.update(getIResourcesFrom(nodes), new Command.LocalOption[] { Update.IGNORE_LOCAL_CHANGES, Command.DO_NOT_RECURSE }, false, monitor);
+	}
+	
+	protected void runUpdateShallow(ITeamNode[] nodes, RepositoryManager manager, IProgressMonitor monitor) throws TeamException {
+		manager.update(getIResourcesFrom(nodes), new Command.LocalOption[] { Command.DO_NOT_RECURSE }, false, monitor);
 	}
 	
 	protected void makeInSync(IDiffElement parentElement) throws TeamException {
@@ -309,6 +307,25 @@
 			}
 		}
 	}
+	
+	protected CVSRemoteSyncElement getSyncElementFrom(ITeamNode node) {
+		CVSRemoteSyncElement element = null;
+		if (node instanceof TeamFile) {
+			element = (CVSRemoteSyncElement)((TeamFile)node).getMergeResource().getSyncElement();
+		} else if (node instanceof ChangedTeamContainer) {
+			element = (CVSRemoteSyncElement)((ChangedTeamContainer)node).getMergeResource().getSyncElement();
+		}
+		return element;
+	}
+	
+	protected IResource[] getIResourcesFrom(ITeamNode[] nodes) {
+		List resources = new ArrayList(nodes.length);
+		for (int i = 0; i < nodes.length; i++) {
+			resources.add(nodes[i].getResource());
+		}
+		return (IResource[]) resources.toArray(new IResource[resources.size()]);
+	}
+	
 	protected boolean isEnabled(ITeamNode node) {
 		return true;
 	}