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; }