diff options
Diffstat (limited to 'bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/ResourceDeltaSyncHandler.java')
-rw-r--r-- | bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/ResourceDeltaSyncHandler.java | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/ResourceDeltaSyncHandler.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/ResourceDeltaSyncHandler.java new file mode 100644 index 000000000..3dfe66858 --- /dev/null +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/ResourceDeltaSyncHandler.java @@ -0,0 +1,223 @@ +package org.eclipse.team.internal.ccvs.core.util; + +/* + * (c) Copyright IBM Corp. 2000, 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +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.team.ccvs.core.CVSProviderPlugin; +import org.eclipse.team.ccvs.core.CVSTeamProvider; +import org.eclipse.team.ccvs.core.ICVSFile; +import org.eclipse.team.ccvs.core.ICVSFolder; +import org.eclipse.team.core.ITeamProvider; +import org.eclipse.team.core.TeamPlugin; +import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.internal.ccvs.core.Policy; +import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; +import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; + +/** + * Listen for the addition of orphaned subtrees as a result of a copy or move. + * + * Listen in IResourceChangeEvent.PRE_AUTO_BUILD so that other interested parties + * (most notably, the file synchronizer) will receive up to date notifications + */ +public class ResourceDeltaSyncHandler implements IResourceDeltaVisitor { + + private static IResourceChangeListener listener; + private static ResourceDeltaSyncHandler visitor; + + public static IResource getResourceFor(IProject container, IResource destination, IPath originating) { + switch(destination.getType()) { + case IResource.FILE : return container.getFile(originating); + case IResource.FOLDER: return container.getFolder(originating); + case IResource.PROJECT: return ResourcesPlugin.getWorkspace().getRoot().getProject(originating.toString()); + } + return destination; + } + + /** + * @see IResourceDeltaVisitor#visit(IResourceDelta) + */ + public boolean visit(IResourceDelta delta) throws CoreException { + IResource resource = delta.getResource(); + IProject project = resource.getProject(); + boolean movedTo = (delta.getFlags() & IResourceDelta.MOVED_TO) > 0; + boolean movedFrom = (delta.getFlags() & IResourceDelta.MOVED_FROM) > 0; + switch (delta.getKind()) { + case IResourceDelta.ADDED : + if (resource.getType() == IResource.FOLDER) { + return ! handleOrphanedSubtree((IContainer)resource); + } else if (resource.getType() == IResource.FILE) { + handleReplacedDeletion((IFile)resource); + } + break; + case IResourceDelta.REMOVED : + if (resource.getType() == IResource.FOLDER) { + // Only record files as there's nothing we can do about folders + } else if (resource.getType() == IResource.FILE) { + if (movedTo) { + IPath target = delta.getMovedToPath(); + if (target.segment(0).equals(project.getName())) { + handleMovedFile(project, (IFile)resource, project.getFile(target.removeFirstSegments(1))); + } else { + handleDeletedFile((IFile)resource); + } + } else { + handleDeletedFile((IFile)resource); + } + } + break; + case IResourceDelta.CHANGED : + // This state means there is a resource before and after but changes were made by deleting and moving. + // For files, we shouldn'd do anything. + // For folders, we should purge the CVS info + if (resource.getType() == IResource.FOLDER) { + // When folders are moved, purge the CVS folders + if (movedFrom) + return ! handleOrphanedSubtree((IContainer)resource); + } + break; + } + return true; + } + + /* + * Determine if the container is an orphaned subtree. + * If it is, handle it and return true. + * Otherwise, return false + */ + private boolean handleOrphanedSubtree(IContainer resource) { + try { + ICVSFolder mFolder = CVSWorkspaceRoot.getCVSFolderFor((IContainer)resource); + if (mFolder.isCVSFolder() && ! mFolder.isManaged() && mFolder.getParent().isCVSFolder()) { + mFolder.unmanage(); + return true; + } + } catch (CVSException e) { + CVSProviderPlugin.log(e); + } + return false; + } + + + /* + * Mark deleted managed files as outgoing deletions + */ + private void handleDeletedFile(IFile resource) { + try { + ICVSFile mFile = CVSWorkspaceRoot.getCVSFileFor((IFile)resource); + if (mFile.isManaged()) { + ResourceSyncInfo info = mFile.getSyncInfo(); + if (info.isAdded()) { + mFile.unmanage(); + } else { + mFile.setSyncInfo(new ResourceSyncInfo(info.getName(), info.DELETED_PREFIX + info.getRevision(), info.getTimeStamp(), info.getKeywordMode(), info.getTag(), info.getPermissions())); + } + } + } catch (CVSException e) { + CVSProviderPlugin.log(e); + } + } + + /* + * Handle the case where an added file has the same name as a "cvs removed" file + * by restoring the sync info to what it was before the delete + */ + private void handleReplacedDeletion(IFile resource) { + try { + ICVSFile mFile = CVSWorkspaceRoot.getCVSFileFor((IFile)resource); + if (mFile.isManaged()) { + ResourceSyncInfo info = mFile.getSyncInfo(); + if (info.isDeleted()) { + mFile.setSyncInfo(new ResourceSyncInfo(info.getName(), info.getRevision(), info.getTimeStamp(), info.getKeywordMode(), info.getTag(), info.getPermissions())); + } + } + } catch (CVSException e) { + CVSProviderPlugin.log(e); + } + } + + /* + * Managed new location if old location was managed. + * Also ensure that replaced deletions are handled. + */ + private void handleMovedFile(IProject project, IFile fromResource, IFile toResource) { + try { + + ResourceSyncInfo fromInfo = null; + ICVSFile fromFile = CVSWorkspaceRoot.getCVSFileFor(fromResource); + // If the from file was managed mark it as an outgoing deletion + if (fromFile.isManaged()) { + fromInfo = fromFile.getSyncInfo(); + if (fromInfo.isAdded()) { + fromFile.unmanage(); + } else { + fromFile.setSyncInfo(new ResourceSyncInfo(fromInfo.getName(), fromInfo.DELETED_PREFIX + fromInfo.getRevision(), fromInfo.getTimeStamp(), fromInfo.getKeywordMode(), fromInfo.getTag(), fromInfo.getPermissions())); + } + } + + ICVSFile toFile = CVSWorkspaceRoot.getCVSFileFor(toResource); + // If the to file is not managed, mark it as an outgoing addition + if (toFile.isManaged()) { + ResourceSyncInfo info = toFile.getSyncInfo(); + if (info.isDeleted()) { + toFile.setSyncInfo(new ResourceSyncInfo(info.getName(), info.getRevision(), info.getTimeStamp(), info.getKeywordMode(), info.getTag(), info.getPermissions())); + } + } else if (fromInfo != null) { + toFile.setSyncInfo(new ResourceSyncInfo(toFile.getName(), ResourceSyncInfo.ADDED_REVISION, ResourceSyncInfo.DUMMY_TIMESTAMP, fromInfo.getKeywordMode(), fromInfo.getTag(), fromInfo.getPermissions())); + } + + } catch (CVSException e) { + CVSProviderPlugin.log(e); + } + } + + public static void startup() { + if (visitor == null) + visitor = new ResourceDeltaSyncHandler(); + if (listener == null) + listener = new IResourceChangeListener() { + public void resourceChanged(IResourceChangeEvent event) { + try { + IResourceDelta root = event.getDelta(); + IResourceDelta[] projectDeltas = root.getAffectedChildren(); + for (int i = 0; i < projectDeltas.length; i++) { + IResourceDelta delta = projectDeltas[i]; + IResource resource = delta.getResource(); + ITeamProvider provider = TeamPlugin.getManager().getProvider(resource); + + // if a project is moved the originating project will not be associated with the CVS provider + // however listeners will probably still be interested in the move delta. + if ((delta.getFlags() & IResourceDelta.MOVED_TO) > 0) { + IResource destination = getResourceFor(resource.getProject(), resource, delta.getMovedToPath()); + provider = TeamPlugin.getManager().getProvider(destination); + } + + if (provider instanceof CVSTeamProvider) { + delta.accept(visitor); + } + } + } catch (CoreException e) { + Util.logError(Policy.bind("ResourceDeltaVisitor.visitError"), e);//$NON-NLS-1$ + } + } + }; + ResourcesPlugin.getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.PRE_AUTO_BUILD); + } + + public static void shutdown() { + ResourcesPlugin.getWorkspace().removeResourceChangeListener(listener); + } +}
\ No newline at end of file |