Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Michel-Lemieux2003-06-18 13:59:35 -0400
committerJean Michel-Lemieux2003-06-18 13:59:35 -0400
commitb5f215b1c894a255c9fc2270a93d3233c36f174f (patch)
tree92b7fb64b71cf3f6773690fdcb50e4eb1327d17f
parent6dd7a81bc781a287d7ea9e50e57a6755153ff6cb (diff)
downloadeclipse.platform.team-b5f215b1c894a255c9fc2270a93d3233c36f174f.tar.gz
eclipse.platform.team-b5f215b1c894a255c9fc2270a93d3233c36f174f.tar.xz
eclipse.platform.team-b5f215b1c894a255c9fc2270a93d3233c36f174f.zip
allow marking merged resources on update in the merge subscriber
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java136
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSyncInfo.java42
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java6
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/OptimizedRemoteSynchronizer.java6
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/RemoteSynchronizer.java254
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/RemoteTagSynchronizer.java258
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/ResourceSynchronizer.java11
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/MergeUpdateAction.java24
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncResourceSet.java40
9 files changed, 476 insertions, 301 deletions
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java
index c88e11192..f277c539f 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java
@@ -11,17 +11,31 @@
package org.eclipse.team.internal.ccvs.core;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.subscribers.ContentComparisonCriteria;
+import org.eclipse.team.core.subscribers.SyncInfo;
+import org.eclipse.team.core.subscribers.TeamDelta;
import org.eclipse.team.core.subscribers.TeamProvider;
+import org.eclipse.team.core.sync.IRemoteResource;
import org.eclipse.team.internal.ccvs.core.syncinfo.RemoteSynchronizer;
+import org.eclipse.team.internal.ccvs.core.syncinfo.RemoteTagSynchronizer;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSynchronizer;
import org.eclipse.team.internal.core.SaveContext;
@@ -38,16 +52,31 @@ import org.eclipse.team.internal.core.SaveContext;
*
* TODO: Is the merge subscriber interested in workspace sync info changes?
* TODO: Do certain operations (e.g. replace with) invalidate a merge subscriber?
- * TODO: How to ensure that sync info is flushed when projects are deleted?
+ * TODO: How to ensure that sync info is flushed when merge roots are deleted?
*/
-public class CVSMergeSubscriber extends CVSSyncTreeSubscriber {
+public class CVSMergeSubscriber extends CVSSyncTreeSubscriber implements IResourceChangeListener, IResourceStateChangeListener {
public static final String UNIQUE_ID_PREFIX = "merge-";
private CVSTag start, end;
- private IResource[] roots;
- private RemoteSynchronizer remoteSynchronizer;
- private RemoteSynchronizer baseSynchronizer;
+ private List roots;
+ private RemoteTagSynchronizer remoteSynchronizer;
+ private RemoteSynchronizer mergedSynchronizer;
+ private RemoteTagSynchronizer baseSynchronizer;
+
+
+ protected IResource[] refreshRemote(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException {
+ IResource[] remoteChanges = super.refreshRemote(resources, depth, monitor);
+ adjustMergedResources(remoteChanges);
+ return remoteChanges;
+ }
+
+ private void adjustMergedResources(IResource[] remoteChanges) throws CVSException {
+ for (int i = 0; i < remoteChanges.length; i++) {
+ IResource resource = remoteChanges[i];
+ mergedSynchronizer.removeSyncBytes(resource, IResource.DEPTH_ZERO);
+ }
+ }
private static QualifiedName getUniqueId() {
String uniqueId = Long.toString(System.currentTimeMillis());
@@ -62,7 +91,7 @@ public class CVSMergeSubscriber extends CVSSyncTreeSubscriber {
super(id, "CVS Merge: " + start.getName() + " to " + end.getName(), "CVS Merge");
this.start = start;
this.end = end;
- this.roots = roots;
+ this.roots = new ArrayList(Arrays.asList(roots));
initialize();
}
@@ -72,8 +101,9 @@ public class CVSMergeSubscriber extends CVSSyncTreeSubscriber {
private void initialize() {
QualifiedName id = getId();
String syncKeyPrefix = id.getLocalName();
- remoteSynchronizer = new RemoteSynchronizer(syncKeyPrefix + end.getName(), end);
- baseSynchronizer = new RemoteSynchronizer(syncKeyPrefix + start.getName(), start);
+ remoteSynchronizer = new RemoteTagSynchronizer(syncKeyPrefix + end.getName(), end);
+ baseSynchronizer = new RemoteTagSynchronizer(syncKeyPrefix + start.getName(), start);
+ mergedSynchronizer = new RemoteSynchronizer(syncKeyPrefix + "0merged");
try {
setCurrentComparisonCriteria(ContentComparisonCriteria.ID_IGNORE_WS);
@@ -82,14 +112,29 @@ public class CVSMergeSubscriber extends CVSSyncTreeSubscriber {
// always be available.
CVSProviderPlugin.log(e);
}
+
+ ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
}
+ protected SyncInfo getSyncInfo(IResource local, IRemoteResource base, IRemoteResource remote, IProgressMonitor monitor) throws TeamException {
+ return new CVSMergeSyncInfo(local, base, remote, this, monitor);
+ }
+
+ public void merged(IResource[] resources) throws CVSException {
+ for (int i = 0; i < resources.length; i++) {
+ IResource resource = resources[i];
+ mergedSynchronizer.setSyncBytes(resource, remoteSynchronizer.getSyncBytes(resource));
+ }
+ fireTeamResourceChange(TeamDelta.asSyncChangedDeltas(this, resources));
+ }
+
/* (non-Javadoc)
* @see org.eclipse.team.core.sync.TeamSubscriber#cancel()
*/
public void cancel() {
- super.cancel();
- TeamProvider.deregisterSubscriber(this);
+ super.cancel();
+ ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
+ TeamProvider.deregisterSubscriber(this);
remoteSynchronizer.dispose();
baseSynchronizer.dispose();
}
@@ -105,7 +150,7 @@ public class CVSMergeSubscriber extends CVSSyncTreeSubscriber {
* @see org.eclipse.team.core.sync.TeamSubscriber#roots()
*/
public IResource[] roots() throws TeamException {
- return roots;
+ return (IResource[]) roots.toArray(new IResource[roots.size()]);
}
/* (non-Javadoc)
@@ -142,11 +187,13 @@ public class CVSMergeSubscriber extends CVSSyncTreeSubscriber {
state.putInteger("endTagType", end.getType());
// resources roots
- SaveContext[] ctxRoots = new SaveContext[roots.length];
- for (int i = 0; i < roots.length; i++) {
+ SaveContext[] ctxRoots = new SaveContext[roots.size()];
+ int i = 0;
+ for (Iterator it = roots.iterator(); it.hasNext(); i++) {
+ IResource element = (IResource) it.next();
ctxRoots[i] = new SaveContext();
ctxRoots[i].setName("resource");
- ctxRoots[i].putString("fullpath", roots[i].getFullPath().toString());
+ ctxRoots[i].putString("fullpath", element.getFullPath().toString());
}
state.setChildren(ctxRoots);
return state;
@@ -197,4 +244,65 @@ public class CVSMergeSubscriber extends CVSSyncTreeSubscriber {
// you can't release changes to a merge
return false;
}
+
+ /*
+ * What to do when a root resource for this merge changes?
+ * Deleted, Move, Copied
+ * Changed in a CVS way (tag changed, revision changed...)
+ * Contents changed by user
+ * @see IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
+ */
+ public void resourceChanged(IResourceChangeEvent event) {
+ try {
+ IResourceDelta delta = event.getDelta();
+ if(delta != null) {
+ delta.accept(new IResourceDeltaVisitor() {
+ public boolean visit(IResourceDelta delta) throws CoreException {
+ IResource resource = delta.getResource();
+
+ if (resource.getType()==IResource.PROJECT) {
+ IProject project = (IProject)resource;
+ if (!project.isAccessible()) {
+ return false;
+ }
+ if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
+ return false;
+ }
+ if (RepositoryProvider.getProvider(project, CVSProviderPlugin.getTypeId()) == null) {
+ return false;
+ }
+ }
+
+ if (roots.contains(resource)) {
+ if (delta.getKind() == IResourceDelta.REMOVED || delta.getKind() == IResourceDelta.MOVED_TO) {
+ cancel();
+ }
+ // stop visiting children
+ return false;
+ }
+ // keep visiting children
+ return true;
+ }
+ });
+ }
+ } catch (CoreException e) {
+ CVSProviderPlugin.log(e.getStatus());
+ }
+ }
+
+ public void resourceSyncInfoChanged(IResource[] changedResources) {
+ }
+
+ public void resourceModified(IResource[] changedResources) {
+ }
+
+ public void projectConfigured(IProject project) {
+ }
+
+ public void projectDeconfigured(IProject project) {
+ }
+
+ public boolean isMerged(IResource resource) throws CVSException {
+ return mergedSynchronizer.getSyncBytes(resource) != null;
+ }
} \ No newline at end of file
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSyncInfo.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSyncInfo.java
new file mode 100644
index 000000000..1ac9b6780
--- /dev/null
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSyncInfo.java
@@ -0,0 +1,42 @@
+/*
+ * Created on Jun 18, 2003
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+package org.eclipse.team.internal.ccvs.core;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.core.subscribers.TeamSubscriber;
+import org.eclipse.team.core.sync.IRemoteResource;
+
+/**
+ * @author JLemieux
+ *
+ * To change the template for this generated type comment go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+public class CVSMergeSyncInfo extends CVSSyncInfo {
+
+ protected int calculateKind(IProgressMonitor progress) throws TeamException {
+ // Report merged resources as in-sync
+ if (((CVSMergeSubscriber)getSubscriber()).isMerged(getLocal())) {
+ return IN_SYNC;
+ }
+
+ int kind = super.calculateKind(progress);
+
+ // Report outgoing resources as in-sync
+ if((kind & DIRECTION_MASK) == OUTGOING) {
+ return IN_SYNC;
+ }
+
+ return kind;
+ }
+
+ public CVSMergeSyncInfo(IResource local, IRemoteResource base, IRemoteResource remote, TeamSubscriber subscriber, IProgressMonitor monitor) throws TeamException {
+ super(local, base, remote, subscriber, monitor);
+ }
+}
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java
index 8a06bbc1f..a5492a01c 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java
@@ -196,7 +196,7 @@ public abstract class CVSSyncTreeSubscriber extends TeamSubscriber {
* @see org.eclipse.team.core.sync.ISyncTreeSubscriber#refresh(org.eclipse.core.resources.IResource[], int, org.eclipse.core.runtime.IProgressMonitor)
*/
public void refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException {
- IResource[] remoteChanges = getRemoteSynchronizer().refresh(resources, depth, monitor);
+ IResource[] remoteChanges = refreshRemote(resources, depth, monitor);
IResource[] baseChanges = getBaseSynchronizer().refresh(resources, depth, monitor);
Set allChanges = new HashSet();
@@ -206,6 +206,10 @@ public abstract class CVSSyncTreeSubscriber extends TeamSubscriber {
fireTeamResourceChange(TeamDelta.asSyncChangedDeltas(this, changedResources));
}
+ protected IResource[] refreshRemote(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException {
+ return getRemoteSynchronizer().refresh(resources, depth, monitor);
+ }
+
/* (non-Javadoc)
* @see org.eclipse.team.core.sync.ISyncTreeSubscriber#getCurrentComparisonCriteria()
*/
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/OptimizedRemoteSynchronizer.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/OptimizedRemoteSynchronizer.java
index 33833ab95..fa144008c 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/OptimizedRemoteSynchronizer.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/OptimizedRemoteSynchronizer.java
@@ -18,7 +18,7 @@ import org.eclipse.team.internal.ccvs.core.util.Util;
* The optimized remote synchronizer uses the base sync info when the remote
* is unknown
*/
-public class OptimizedRemoteSynchronizer extends RemoteSynchronizer {
+public class OptimizedRemoteSynchronizer extends RemoteTagSynchronizer {
// The local synchronizer is used for cases where the remote is unknown
private BaseSynchronizer baseSynchronizer = new BaseSynchronizer();
@@ -35,8 +35,8 @@ public class OptimizedRemoteSynchronizer extends RemoteSynchronizer {
*/
public byte[] getSyncBytes(IResource resource) throws CVSException {
byte[] bytes = getRemoteBytes(resource);
- if (bytes == null) {
- // The remote was never known so use the base
+ if ((bytes == null) && !hasRemoteBytesFor(resource)) {
+ // The remote was never known so use the base
bytes = baseSynchronizer.getSyncBytes(resource);
}
return bytes;
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/RemoteSynchronizer.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/RemoteSynchronizer.java
index 3ec00d973..ee1ff5a9c 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/RemoteSynchronizer.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/RemoteSynchronizer.java
@@ -10,34 +10,15 @@
*******************************************************************************/
package org.eclipse.team.internal.ccvs.core.syncinfo;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
import java.util.Set;
-import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ISynchronizer;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.sync.IRemoteResource;
import org.eclipse.team.internal.ccvs.core.CVSException;
-import org.eclipse.team.internal.ccvs.core.CVSTag;
-import org.eclipse.team.internal.ccvs.core.ICVSFolder;
-import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource;
-import org.eclipse.team.internal.ccvs.core.ICVSResource;
-import org.eclipse.team.internal.ccvs.core.Policy;
-import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
-import org.eclipse.team.internal.ccvs.core.resources.RemoteResource;
-import org.eclipse.team.internal.ccvs.core.util.Assert;
import org.eclipse.team.internal.ccvs.core.util.Util;
/**
@@ -47,17 +28,12 @@ import org.eclipse.team.internal.ccvs.core.util.Util;
public class RemoteSynchronizer extends ResourceSynchronizer {
public static final String SYNC_KEY_QUALIFIER = "org.eclipse.team.cvs";
+ protected QualifiedName syncName;
+ protected Set changedResources = new HashSet();
- private static final byte[] NO_REMOTE = new byte[0];
-
- private QualifiedName syncName;
- private Set changedResources = new HashSet();
- private CVSTag tag;
-
- public RemoteSynchronizer(String id, CVSTag tag) {
+ public RemoteSynchronizer(String id) {
syncName = new QualifiedName(SYNC_KEY_QUALIFIER, id);
getSynchronizer().add(syncName);
- this.tag = tag;
}
/**
@@ -66,18 +42,15 @@ public class RemoteSynchronizer extends ResourceSynchronizer {
public void dispose() {
getSynchronizer().remove(getSyncName());
}
-
- private ISynchronizer getSynchronizer() {
+
+ protected ISynchronizer getSynchronizer() {
return ResourcesPlugin.getWorkspace().getSynchronizer();
}
-
- private QualifiedName getSyncName() {
+
+ protected QualifiedName getSyncName() {
return syncName;
}
-
- /*
- * Get the sync bytes for the remote resource
- */
+
public byte[] getSyncBytes(IResource resource) throws CVSException {
try {
return getSynchronizer().getSyncInfo(getSyncName(), resource);
@@ -85,7 +58,7 @@ public class RemoteSynchronizer extends ResourceSynchronizer {
throw CVSException.wrapException(e);
}
}
-
+
public void setSyncBytes(IResource resource, byte[] bytes) throws CVSException {
byte[] oldBytes = getSyncBytes(resource);
if (oldBytes != null && Util.equals(oldBytes, bytes)) return;
@@ -96,7 +69,7 @@ public class RemoteSynchronizer extends ResourceSynchronizer {
}
changedResources.add(resource);
}
-
+
public void removeSyncBytes(IResource resource, int depth) throws CVSException {
if (resource.exists() || resource.isPhantom()) {
try {
@@ -108,209 +81,4 @@ public class RemoteSynchronizer extends ResourceSynchronizer {
}
}
- /**
- * @param resource
- */
- public void collectChanges(IResource local, ICVSRemoteResource remote, int depth, IProgressMonitor monitor) throws TeamException {
- byte[] remoteBytes;
- if (remote != null) {
- remoteBytes = ((RemoteResource)remote).getSyncBytes();
- } else {
- remoteBytes = NO_REMOTE;
- }
- setSyncBytes(local, remoteBytes);
- if (depth == IResource.DEPTH_ZERO) return;
- Map children = mergedMembers(local, remote, monitor);
- for (Iterator it = children.keySet().iterator(); it.hasNext();) {
- IResource localChild = (IResource) it.next();
- ICVSRemoteResource remoteChild = (ICVSRemoteResource)children.get(localChild);
- collectChanges(localChild, remoteChild,
- depth == IResource.DEPTH_INFINITE ? IResource.DEPTH_INFINITE : IResource.DEPTH_ZERO,
- monitor);
- }
- }
-
- protected Map mergedMembers(IResource local, IRemoteResource remote, IProgressMonitor progress) throws TeamException {
-
- // {IResource -> IRemoteResource}
- Map mergedResources = new HashMap();
-
- IRemoteResource[] remoteChildren = getRemoteChildren(remote, progress);
-
- IResource[] localChildren = getLocalChildren(local);
-
- if (remoteChildren.length > 0 || localChildren.length > 0) {
- List syncChildren = new ArrayList(10);
- Set allSet = new HashSet(20);
- Map localSet = null;
- Map remoteSet = null;
-
- if (localChildren.length > 0) {
- localSet = new HashMap(10);
- for (int i = 0; i < localChildren.length; i++) {
- IResource localChild = localChildren[i];
- String name = localChild.getName();
- localSet.put(name, localChild);
- allSet.add(name);
- }
- }
-
- if (remoteChildren.length > 0) {
- remoteSet = new HashMap(10);
- for (int i = 0; i < remoteChildren.length; i++) {
- IRemoteResource remoteChild = remoteChildren[i];
- String name = remoteChild.getName();
- remoteSet.put(name, remoteChild);
- allSet.add(name);
- }
- }
-
- Iterator e = allSet.iterator();
- while (e.hasNext()) {
- String keyChildName = (String) e.next();
-
- if (progress != null) {
- if (progress.isCanceled()) {
- throw new OperationCanceledException();
- }
- // XXX show some progress?
- }
-
- IResource localChild =
- localSet != null ? (IResource) localSet.get(keyChildName) : null;
-
- IRemoteResource remoteChild =
- remoteSet != null ? (IRemoteResource) remoteSet.get(keyChildName) : null;
-
- if (localChild == null) {
- // there has to be a remote resource available if we got this far
- Assert.isTrue(remoteChild != null);
- boolean isContainer = remoteChild.isContainer();
- localChild = getResourceChild(local /* parent */, keyChildName, isContainer);
- }
- mergedResources.put(localChild, remoteChild);
- }
- }
- return mergedResources;
- }
-
- private IRemoteResource[] getRemoteChildren(IRemoteResource remote, IProgressMonitor progress) throws TeamException {
- return remote != null ? remote.members(progress) : new IRemoteResource[0];
- }
-
- private IResource[] getLocalChildren(IResource local) throws TeamException {
- IResource[] localChildren;
- if( local.getType() != IResource.FILE && local.exists() ) {
- // TODO: This should be a list of all non-ignored resources including outgoing deletions
- ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor((IContainer)local);
- ICVSResource[] cvsChildren = cvsFolder.members(ICVSFolder.MANAGED_MEMBERS | ICVSFolder.UNMANAGED_MEMBERS);
- List resourceChildren = new ArrayList();
- for (int i = 0; i < cvsChildren.length; i++) {
- ICVSResource cvsResource = cvsChildren[i];
- resourceChildren.add(cvsResource.getIResource());
- }
- localChildren = (IResource[]) resourceChildren.toArray(new IResource[resourceChildren.size()]);
- } else {
- localChildren = new IResource[0];
- }
- return localChildren;
- }
-
- /*
- * Returns a handle to a non-existing resource.
- */
- private IResource getResourceChild(IResource parent, String childName, boolean isContainer) {
- if (parent.getType() == IResource.FILE) {
- return null;
- }
- if (isContainer) {
- return ((IContainer) parent).getFolder(new Path(childName));
- } else {
- return ((IContainer) parent).getFile(new Path(childName));
- }
- }
-
- /**
- *
- * @param resource
- * @return
- * @throws TeamException
- */
- public IRemoteResource getRemoteResource(IResource resource) throws TeamException {
- byte[] remoteBytes = getSyncBytes(resource);
- if (remoteBytes == null || remoteDoesNotExist(remoteBytes)) {
- // The remote is known to not exist or there is no base
- return null;
- } else {
- return super.getRemoteResource(resource);
- }
- }
-
- /*
- * Return true if the given bytes indocate that the remote does not exist.
- * The provided byte array must not be null;
- */
- private boolean remoteDoesNotExist(byte[] remoteBytes) {
- Assert.isNotNull(remoteBytes);
- return Util.equals(remoteBytes, NO_REMOTE);
- }
-
- /**
- * @return
- */
- public IResource[] getChangedResources() {
- return (IResource[]) changedResources.toArray(new IResource[changedResources.size()]);
- }
-
- public void resetChanges() {
- changedResources.clear();
- }
-
- /**
- * Refreshes the contents of the remote synchronizer and returns the list
- * of resources whose remote sync state changed.
- *
- * @param resources
- * @param depth
- * @param monitor
- * @return
- * @throws TeamException
- */
- public IResource[] refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException {
- int work = 100 * resources.length;
- monitor.beginTask(null, work);
- resetChanges();
- try {
- for (int i = 0; i < resources.length; i++) {
- IResource resource = resources[i];
-
- // build the remote tree only if an initial tree hasn't been provided
- ICVSRemoteResource tree = buildRemoteTree(resource, depth, Policy.subMonitorFor(monitor, 70));
-
- // update the known remote handles
- IProgressMonitor sub = Policy.infiniteSubMonitorFor(monitor, 30);
- try {
- sub.beginTask(null, 512);
- removeSyncBytes(resource, IResource.DEPTH_INFINITE);
- collectChanges(resource, tree, depth, sub);
- } finally {
- sub.done();
- }
- }
- } finally {
- monitor.done();
- }
- IResource[] changes = getChangedResources();
- resetChanges();
- return changes;
- }
-
- /**
- * Build a remote tree for the given parameters.
- */
- protected ICVSRemoteResource buildRemoteTree(IResource resource, int depth, IProgressMonitor monitor) throws TeamException {
- // TODO: we are currently ignoring the depth parameter because the build remote tree is
- // by default deep!
- return CVSWorkspaceRoot.getRemoteTree(resource, tag, monitor);
- }
-}
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/RemoteTagSynchronizer.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/RemoteTagSynchronizer.java
new file mode 100644
index 000000000..7c977ee26
--- /dev/null
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/RemoteTagSynchronizer.java
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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 v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.team.internal.ccvs.core.syncinfo;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.core.sync.IRemoteResource;
+import org.eclipse.team.internal.ccvs.core.CVSException;
+import org.eclipse.team.internal.ccvs.core.CVSTag;
+import org.eclipse.team.internal.ccvs.core.ICVSFolder;
+import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource;
+import org.eclipse.team.internal.ccvs.core.ICVSResource;
+import org.eclipse.team.internal.ccvs.core.Policy;
+import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
+import org.eclipse.team.internal.ccvs.core.resources.RemoteResource;
+import org.eclipse.team.internal.ccvs.core.util.Assert;
+import org.eclipse.team.internal.ccvs.core.util.Util;
+
+/**
+ * This RemoteSynchronizr uses a CVS Tag to fetch the remote tree
+ */
+public class RemoteTagSynchronizer extends RemoteSynchronizer {
+
+ private static final byte[] NO_REMOTE = new byte[0];
+ private CVSTag tag;
+
+ public RemoteTagSynchronizer(String id, CVSTag tag) {
+ super(id);
+ this.tag = tag;
+ }
+
+ public void collectChanges(IResource local, ICVSRemoteResource remote, int depth, IProgressMonitor monitor) throws TeamException {
+ byte[] remoteBytes;
+ if (remote != null) {
+ remoteBytes = ((RemoteResource)remote).getSyncBytes();
+ } else {
+ remoteBytes = NO_REMOTE;
+ }
+ setSyncBytes(local, remoteBytes);
+ if (depth == IResource.DEPTH_ZERO) return;
+ Map children = mergedMembers(local, remote, monitor);
+ for (Iterator it = children.keySet().iterator(); it.hasNext();) {
+ IResource localChild = (IResource) it.next();
+ ICVSRemoteResource remoteChild = (ICVSRemoteResource)children.get(localChild);
+ collectChanges(localChild, remoteChild,
+ depth == IResource.DEPTH_INFINITE ? IResource.DEPTH_INFINITE : IResource.DEPTH_ZERO,
+ monitor);
+ }
+ }
+
+ protected Map mergedMembers(IResource local, IRemoteResource remote, IProgressMonitor progress) throws TeamException {
+
+ // {IResource -> IRemoteResource}
+ Map mergedResources = new HashMap();
+
+ IRemoteResource[] remoteChildren = getRemoteChildren(remote, progress);
+
+ IResource[] localChildren = getLocalChildren(local);
+
+ if (remoteChildren.length > 0 || localChildren.length > 0) {
+ List syncChildren = new ArrayList(10);
+ Set allSet = new HashSet(20);
+ Map localSet = null;
+ Map remoteSet = null;
+
+ if (localChildren.length > 0) {
+ localSet = new HashMap(10);
+ for (int i = 0; i < localChildren.length; i++) {
+ IResource localChild = localChildren[i];
+ String name = localChild.getName();
+ localSet.put(name, localChild);
+ allSet.add(name);
+ }
+ }
+
+ if (remoteChildren.length > 0) {
+ remoteSet = new HashMap(10);
+ for (int i = 0; i < remoteChildren.length; i++) {
+ IRemoteResource remoteChild = remoteChildren[i];
+ String name = remoteChild.getName();
+ remoteSet.put(name, remoteChild);
+ allSet.add(name);
+ }
+ }
+
+ Iterator e = allSet.iterator();
+ while (e.hasNext()) {
+ String keyChildName = (String) e.next();
+
+ if (progress != null) {
+ if (progress.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ // XXX show some progress?
+ }
+
+ IResource localChild =
+ localSet != null ? (IResource) localSet.get(keyChildName) : null;
+
+ IRemoteResource remoteChild =
+ remoteSet != null ? (IRemoteResource) remoteSet.get(keyChildName) : null;
+
+ if (localChild == null) {
+ // there has to be a remote resource available if we got this far
+ Assert.isTrue(remoteChild != null);
+ boolean isContainer = remoteChild.isContainer();
+ localChild = getResourceChild(local /* parent */, keyChildName, isContainer);
+ }
+ mergedResources.put(localChild, remoteChild);
+ }
+ }
+ return mergedResources;
+ }
+
+ private IRemoteResource[] getRemoteChildren(IRemoteResource remote, IProgressMonitor progress) throws TeamException {
+ return remote != null ? remote.members(progress) : new IRemoteResource[0];
+ }
+
+ private IResource[] getLocalChildren(IResource local) throws TeamException {
+ IResource[] localChildren;
+ if( local.getType() != IResource.FILE && local.exists() ) {
+ // TODO: This should be a list of all non-ignored resources including outgoing deletions
+ ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor((IContainer)local);
+ ICVSResource[] cvsChildren = cvsFolder.members(ICVSFolder.MANAGED_MEMBERS | ICVSFolder.UNMANAGED_MEMBERS);
+ List resourceChildren = new ArrayList();
+ for (int i = 0; i < cvsChildren.length; i++) {
+ ICVSResource cvsResource = cvsChildren[i];
+ resourceChildren.add(cvsResource.getIResource());
+ }
+ localChildren = (IResource[]) resourceChildren.toArray(new IResource[resourceChildren.size()]);
+ } else {
+ localChildren = new IResource[0];
+ }
+ return localChildren;
+ }
+
+ /*
+ * Returns a handle to a non-existing resource.
+ */
+ private IResource getResourceChild(IResource parent, String childName, boolean isContainer) {
+ if (parent.getType() == IResource.FILE) {
+ return null;
+ }
+ if (isContainer) {
+ return ((IContainer) parent).getFolder(new Path(childName));
+ } else {
+ return ((IContainer) parent).getFile(new Path(childName));
+ }
+ }
+
+ /**
+ * Return true if remote bytes for the resource have been fetched during
+ * a refresh. This will also return true for remote resources that do not exist
+ * (i.e. they have no sync bytes but did not exist remotely at the time of the
+ * last refresh.
+ *
+ * @param resource
+ * @return
+ */
+ public boolean hasRemoteBytesFor(IResource resource) throws CVSException {
+ return super.getSyncBytes(resource) != null;
+ }
+
+ /**
+ * This method will return null in both cases when the remote has never been fetched
+ * or when the remote does not exist. Use <code>hasRemoteBytesFor</code> to
+ * differentiate these cases.
+ */
+ public byte[] getSyncBytes(IResource resource) throws CVSException {
+ byte[] syncBytes = super.getSyncBytes(resource);
+ if (syncBytes != null && Util.equals(syncBytes, NO_REMOTE)) {
+ // If it is known that there is no remote, return null
+ return null;
+ }
+ return syncBytes;
+ }
+
+ /**
+ * @return
+ */
+ public IResource[] getChangedResources() {
+ return (IResource[]) changedResources.toArray(new IResource[changedResources.size()]);
+ }
+
+ public void resetChanges() {
+ changedResources.clear();
+ }
+
+ /**
+ * Refreshes the contents of the remote synchronizer and returns the list
+ * of resources whose remote sync state changed.
+ *
+ * @param resources
+ * @param depth
+ * @param monitor
+ * @return
+ * @throws TeamException
+ */
+ public IResource[] refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException {
+ int work = 100 * resources.length;
+ monitor.beginTask(null, work);
+ resetChanges();
+ try {
+ for (int i = 0; i < resources.length; i++) {
+ IResource resource = resources[i];
+
+ // build the remote tree only if an initial tree hasn't been provided
+ ICVSRemoteResource tree = buildRemoteTree(resource, depth, Policy.subMonitorFor(monitor, 70));
+
+ // update the known remote handles
+ IProgressMonitor sub = Policy.infiniteSubMonitorFor(monitor, 30);
+ try {
+ sub.beginTask(null, 512);
+ removeSyncBytes(resource, IResource.DEPTH_INFINITE);
+ collectChanges(resource, tree, depth, sub);
+ } finally {
+ sub.done();
+ }
+ }
+ } finally {
+ monitor.done();
+ }
+ IResource[] changes = getChangedResources();
+ resetChanges();
+ return changes;
+ }
+
+ /**
+ * Build a remote tree for the given parameters.
+ */
+ protected ICVSRemoteResource buildRemoteTree(IResource resource, int depth, IProgressMonitor monitor) throws TeamException {
+ // TODO: we are currently ignoring the depth parameter because the build remote tree is
+ // by default deep!
+ return CVSWorkspaceRoot.getRemoteTree(resource, tag, monitor);
+ }
+
+}
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/ResourceSynchronizer.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/ResourceSynchronizer.java
index e7d4f4ff4..0c19297c8 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/ResourceSynchronizer.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/ResourceSynchronizer.java
@@ -25,14 +25,6 @@ import org.eclipse.team.internal.ccvs.core.resources.RemoteFolder;
*/
public abstract class ResourceSynchronizer {
- public abstract byte[] getSyncBytes(IResource resource) throws CVSException;
-
- /**
- *
- * @param resource
- * @return
- * @throws TeamException
- */
public IRemoteResource getRemoteResource(IResource resource) throws TeamException {
byte[] remoteBytes = getSyncBytes(resource);
if (remoteBytes == null) {
@@ -50,6 +42,8 @@ public abstract class ResourceSynchronizer {
}
}
+ public abstract byte[] getSyncBytes(IResource resource) throws CVSException;
+
/**
* Refreshes the contents of the resource synchronizer and returns the list
* of resources whose remote sync state changed.
@@ -61,4 +55,5 @@ public abstract class ResourceSynchronizer {
public IResource[] refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException {
return new IResource[0];
}
+
}
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/MergeUpdateAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/MergeUpdateAction.java
index b9b172d4b..c81cd58a4 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/MergeUpdateAction.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/MergeUpdateAction.java
@@ -71,11 +71,25 @@ public class MergeUpdateAction extends SubscriberUpdateAction {
// The update will fail for conflicts that turn out to be non-automergable
super.run(syncSet, Policy.subMonitorFor(monitor, syncSet.size() * 100));
- // It is possible that some of the conflicting changes were not auto-mergable
- SyncResourceSet failedSet = createFailedSet(syncSet, willFail, (IFile[]) skippedFiles.toArray(new IFile[skippedFiles.size()]));
- if (failedSet.isEmpty()) return;
- if (!promptForOverwrite(failedSet)) return;
- runOverwrite(failedSet.getSyncResources(), Policy.subMonitorFor(monitor, willFail.length * 100));
+ // It is possible that some of the conflicting changes were not auto-mergable.
+ // Accumulate all resources that have not been updated so far
+ final SyncResourceSet failedSet = createFailedSet(syncSet, willFail, (IFile[]) skippedFiles.toArray(new IFile[skippedFiles.size()]));
+
+ // Remove all these from the original sync set
+ syncSet.rejectNodes(new SyncInfoFilter() {
+ public boolean select(SyncInfo info) {
+ return failedSet.getNodeFor(info.getLocal()) != null;
+ }
+ });
+
+ // Ask the user if a replace should be performed on the remaining nodes
+ if (!failedSet.isEmpty() && promptForOverwrite(failedSet)) {
+ runOverwrite(failedSet.getSyncResources(), Policy.subMonitorFor(monitor, willFail.length * 100));
+ syncSet.addAll(failedSet);
+ }
+
+ // Mark all succesfully updated resources as merged
+ ((CVSMergeSubscriber)getSubscriber()).merged(syncSet.getResources());
} finally {
monitor.done();
}
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncResourceSet.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncResourceSet.java
index 92be4eb16..abb41ffde 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncResourceSet.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncResourceSet.java
@@ -21,12 +21,6 @@ import org.eclipse.core.resources.IResource;
import org.eclipse.team.core.subscribers.SyncInfo;
import org.eclipse.team.internal.ui.sync.views.SyncResource;
-/**
- * @author Administrator
- *
- * To change the template for this generated type comment go to
- * Window>Preferences>Java>Code Generation>Code and Comments
- */
public class SyncResourceSet {
Set set = new HashSet();
@@ -159,9 +153,6 @@ public class SyncResourceSet {
return (SyncResource[]) result.toArray(new SyncResource[result.size()]);
}
- /**
- *
- */
public SyncResource[] getSyncResources() {
return (SyncResource[]) set.toArray(new SyncResource[set.size()]);
}
@@ -178,26 +169,17 @@ public class SyncResourceSet {
return resources;
}
- /**
- * @return
- */
public boolean isEmpty() {
return set.isEmpty();
}
- /**
- * @param resources
- */
public void removeResources(IResource[] resources) {
for (int i = 0; i < resources.length; i++) {
IResource resource = resources[i];
removeResource(resource);
}
- }
-
- /**
- * @param resource
- */
+ }
+
private void removeResource(IResource resource) {
for (Iterator it = set.iterator(); it.hasNext();) {
SyncResource node = (SyncResource)it.next();
@@ -208,16 +190,11 @@ public class SyncResourceSet {
}
}
}
- /**
- * @return
- */
+
public int size() {
return set.size();
}
- /**
- * @param file
- * @return
- */
+
public SyncResource getNodeFor(IResource resource) {
for (Iterator it = set.iterator(); it.hasNext();) {
SyncResource node = (SyncResource)it.next();
@@ -228,4 +205,13 @@ public class SyncResourceSet {
return null;
}
+ public void addAll(SyncResourceSet set) {
+ SyncResource[] resources = set.getSyncResources();
+ for (int i = 0; i < resources.length; i++) {
+ SyncResource resource = resources[i];
+ this.set.add(resource);
+ }
+
+ }
+
}

Back to the top