diff options
author | Michael Valenta | 2002-11-19 21:55:31 +0000 |
---|---|---|
committer | Michael Valenta | 2002-11-19 21:55:31 +0000 |
commit | 4652f36bfd9333df028190408aaaf1d7766dba3a (patch) | |
tree | addb2df7d16607d4f5a757b4813fb32c0a537e18 | |
parent | 523ada77134b2a1a874ce0b36a7f5e3cdaa34269 (diff) | |
download | eclipse.platform.team-4652f36bfd9333df028190408aaaf1d7766dba3a.tar.gz eclipse.platform.team-4652f36bfd9333df028190408aaaf1d7766dba3a.tar.xz eclipse.platform.team-4652f36bfd9333df028190408aaaf1d7766dba3a.zip |
21577: [CVS Watch/Edit] Readonly/Edit/Unedit Support
22 files changed, 882 insertions, 202 deletions
diff --git a/bundles/org.eclipse.team.cvs.core/plugin.xml b/bundles/org.eclipse.team.cvs.core/plugin.xml index 829d78d59..3024a3ca2 100644 --- a/bundles/org.eclipse.team.cvs.core/plugin.xml +++ b/bundles/org.eclipse.team.cvs.core/plugin.xml @@ -21,6 +21,7 @@ <!-- *************** Extension Points **************** --> <extension-point name="Authenticator" id="authenticator"/> <extension-point name="ConnectionMethods" id="connectionmethods"/> + <extension-point name="FileModificationValidator" id="filemodificationvalidator"/> <!-- *************** Connection Methods **************** --> <extension id="pserver" point="org.eclipse.team.cvs.core.connectionmethods"> diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java index eaf84431f..e94d678b4 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java @@ -29,7 +29,6 @@ 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.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; @@ -39,6 +38,7 @@ import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Plugin; +import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.Status; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.core.Team; @@ -56,6 +56,9 @@ import org.eclipse.team.internal.ccvs.core.util.SyncFileChangeListener; import org.eclipse.team.internal.ccvs.core.util.Util; public class CVSProviderPlugin extends Plugin { + + // preference names + public static final String READ_ONLY = "cvs.read.only"; //$NON-NLS-1$ // external command to run for ext connection method public static final String DEFAULT_CVS_RSH = "ssh"; //$NON-NLS-1$ @@ -78,6 +81,7 @@ public class CVSProviderPlugin extends Plugin { public static final String ID = "org.eclipse.team.cvs.core"; //$NON-NLS-1$ public static final String PT_AUTHENTICATOR = "authenticator"; //$NON-NLS-1$ public static final String PT_CONNECTIONMETHODS = "connectionmethods"; //$NON-NLS-1$ + public static final String PT_FILE_MODIFICATION_VALIDATOR = "filemodificationvalidator"; //$NON-NLS-1$ // Directory to cache file contents private static final String CACHE_DIRECTORY = ".cache"; //$NON-NLS-1$ @@ -97,7 +101,6 @@ public class CVSProviderPlugin extends Plugin { private String cvsRshParameters = DEFAULT_CVS_RSH_PARAMETERS; private String cvsServer = DEFAULT_CVS_SERVER; private IConsoleListener consoleListener; - private boolean watchEditEnabled = true; private boolean determineVersionEnabled = true; private static CVSProviderPlugin instance; @@ -281,6 +284,7 @@ public class CVSProviderPlugin extends Plugin { // save the state which includes the known repositories saveState(); + savePluginPreferences(); // remove listeners IWorkspace workspace = ResourcesPlugin.getWorkspace(); @@ -291,49 +295,12 @@ public class CVSProviderPlugin extends Plugin { deleteCacheDirectory(); } - /* - * Add a resource change listener to the workspace in order to respond to - * resource deletions and moves and to ensure or project desription file is up to date. + /** + * @see org.eclipse.core.runtime.Plugin#initializeDefaultPluginPreferences() */ - private void initializeChangeListener() { - - // Build a change listener for changes to thr project meta-information - IResourceChangeListener projectChangeListener = new IResourceChangeListener() { - public void resourceChanged(IResourceChangeEvent event) { - try { - IResourceDelta root = event.getDelta(); - IResourceDelta[] projectDeltas = root.getAffectedChildren(IResourceDelta.CHANGED); - for (int i = 0; i < projectDeltas.length; i++) { - IResourceDelta delta = projectDeltas[i]; - IResource resource = delta.getResource(); - if (resource.getType() == IResource.PROJECT) { - IProject project = (IProject)resource; - // Get the team provider for the project and - RepositoryProvider provider = RepositoryProvider.getProvider(project, getTypeId()); - if(provider==null) continue; - /* Check if the project description changed. */ - if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) { - /* The project description changed. Write the file. */ - ProjectDescriptionManager.writeProjectDescriptionIfNecessary((CVSTeamProvider)provider, project, Policy.monitorFor(null)); - } - - /* Check if the .vcm_meta file for the project is in the delta. */ - IResourceDelta[] children = delta.getAffectedChildren(IResourceDelta.REMOVED); - for (int j = 0; j < children.length; j++) { - IResourceDelta childDelta = children[j]; - IResource childResource = childDelta.getResource(); - if (ProjectDescriptionManager.isProjectDescription(childResource)) { - ProjectDescriptionManager.writeProjectDescriptionIfNecessary((CVSTeamProvider)provider, project, Policy.monitorFor(null)); - } - } - } - } - } catch (CVSException ex) { - Util.logError(Policy.bind("CVSProviderPlugin.cannotUpdateDescription"), ex); //$NON-NLS-1$ - } - } - }; - ResourcesPlugin.getWorkspace().addResourceChangeListener(projectChangeListener, IResourceChangeEvent.POST_AUTO_BUILD); + protected void initializeDefaultPluginPreferences(){ + Preferences store = getPluginPreferences(); + store.setDefault(READ_ONLY, false); } /** @@ -424,14 +391,6 @@ public class CVSProviderPlugin extends Plugin { promptOnFolderDelete = prompt; } - public boolean isWatchEditEnabled() { - return watchEditEnabled; - } - - public void setWatchEditEnabled(boolean enabled) { - watchEditEnabled = enabled; - } - private static List listeners = new ArrayList(); /* diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSTeamProvider.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSTeamProvider.java index 25fb7764d..e4d59de2e 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSTeamProvider.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSTeamProvider.java @@ -36,10 +36,13 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.team.IMoveDeleteHook; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.Status; import org.eclipse.team.core.RepositoryProvider; @@ -100,6 +103,7 @@ import org.eclipse.team.internal.core.streams.LFtoCRLFInputStream; * have them appear in Eclipse. This may be changed in the future. */ public class CVSTeamProvider extends RepositoryProvider { + private static final boolean IS_CRLF_PLATFORM = Arrays.equals( System.getProperty("line.separator").getBytes(), new byte[] { '\r', '\n' }); //$NON-NLS-1$ @@ -110,11 +114,31 @@ public class CVSTeamProvider extends RepositoryProvider { private String comment = ""; //$NON-NLS-1$ private static MoveDeleteHook moveDeleteHook= new MoveDeleteHook(); + private static IFileModificationValidator fileModificationValidator; // property used to indicate whether new directories should be discovered for the project private final static QualifiedName FETCH_ABSENT_DIRECTORIES_PROP_KEY = new QualifiedName("org.eclipse.team.cvs.core", "fetch_absent_directories"); //$NON-NLS-1$ //$NON-NLS-2$ - + + private static IFileModificationValidator getPluggedInValidator() { + IExtension[] extensions = Platform.getPluginRegistry().getExtensionPoint(CVSProviderPlugin.ID, CVSProviderPlugin.PT_FILE_MODIFICATION_VALIDATOR).getExtensions(); + if (extensions.length == 0) + return null; + IExtension extension = extensions[0]; + IConfigurationElement[] configs = extension.getConfigurationElements(); + if (configs.length == 0) { + CVSProviderPlugin.log(new Status(IStatus.ERROR, CVSProviderPlugin.ID, 0, Policy.bind("CVSAdapter.noConfigurationElement", new Object[] {extension.getUniqueIdentifier()}), null));//$NON-NLS-1$ + return null; + } + try { + IConfigurationElement config = configs[0]; + return (IFileModificationValidator) config.createExecutableExtension("run");//$NON-NLS-1$ + } catch (CoreException ex) { + CVSProviderPlugin.log(new Status(IStatus.ERROR, CVSProviderPlugin.ID, 0, Policy.bind("CVSAdapter.unableToInstantiate", new Object[] {extension.getUniqueIdentifier()}), ex));//$NON-NLS-1$ + return null; + } + } + /** * No-arg Constructor for IProjectNature conformance */ @@ -1098,54 +1122,15 @@ public class CVSTeamProvider extends RepositoryProvider { * @see org.eclipse.team.core.RepositoryProvider#getFileModificationValidator() */ public IFileModificationValidator getFileModificationValidator() { - if (isWatchEditEnabled()) { - return new IFileModificationValidator() { - public IStatus validateEdit(IFile[] files, Object context) { - try { - // only do this for files that are read-only - List readOnlys = new ArrayList(); - for (int i = 0; i < files.length; i++) { - IFile iFile = files[i]; - if (iFile.isReadOnly()) - readOnlys.add(iFile); - } - if (readOnlys.isEmpty()) return OK; - - // XXX We should try to create a PM using the provided context - edit((IFile[]) readOnlys.toArray(new IFile[readOnlys.size()]), - false /* recurse */, true /* notify server */, - ICVSFile.NO_NOTIFICATION, null); - } catch (TeamException e) { - return e.getStatus(); - } - return OK; - } - public IStatus validateSave(IFile file) { - // Ignore files that are not read-only - if (!file.isReadOnly()) return OK; - try { - edit(new IResource[] {file}, - false /* recurse */, true /* notify server */, - ICVSFile.NO_NOTIFICATION, null); - } catch (TeamException e) { - return e.getStatus(); - } - return OK; - } - }; - } else { - return super.getFileModificationValidator(); + if (CVSTeamProvider.fileModificationValidator == null) { + CVSTeamProvider.fileModificationValidator = CVSTeamProvider.getPluggedInValidator(); + if (CVSTeamProvider.fileModificationValidator == null) { + CVSTeamProvider.fileModificationValidator =super.getFileModificationValidator(); + } } + return CVSTeamProvider.fileModificationValidator; } - - /** - * Answer true if watch/edit support is enabled for this provider. - * @return boolean - */ - public boolean isWatchEditEnabled() { - return CVSProviderPlugin.getPlugin().isWatchEditEnabled(); - } - + /** * Checkout (cvs edit) the provided resources so they can be modified locally and committed. * This will make any read-only resources in the list writable and will notify the server @@ -1176,7 +1161,7 @@ public class CVSTeamProvider extends RepositoryProvider { notifyEditUnedit(resources, recurse, notifyServer, new ICVSResourceVisitor() { public void visitFile(ICVSFile file) throws CVSException { if (file.isReadOnly()) - file.edit(notification); + file.edit(notification, Policy.monitorFor(null)); } public void visitFolder(ICVSFolder folder) throws CVSException { // nothing needs to be done here as the recurse will handle the traversal @@ -1210,7 +1195,7 @@ public class CVSTeamProvider extends RepositoryProvider { notifyEditUnedit(resources, recurse, notifyServer, new ICVSResourceVisitor() { public void visitFile(ICVSFile file) throws CVSException { if (!file.isReadOnly()) - file.unedit(); + file.unedit(Policy.monitorFor(null)); } public void visitFolder(ICVSFolder folder) throws CVSException { // nothing needs to be done here as the recurse will handle the traversal @@ -1276,4 +1261,5 @@ public class CVSTeamProvider extends RepositoryProvider { throw new CVSException(new CVSStatus(IStatus.ERROR, Policy.bind("CVSTeamProvider.errorSettingFetchProperty", project.getName()), e)); //$NON-NLS-1$ } } + }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSFile.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSFile.java index 6d9800ddb..0348c5c4a 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSFile.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSFile.java @@ -16,6 +16,7 @@ import java.util.Date; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.core.TeamException; import org.eclipse.team.internal.ccvs.core.syncinfo.NotifyInfo; +import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; /** * The CVS analog of a file. CVS files have access to synchronization information @@ -124,7 +125,7 @@ public interface ICVSFile extends ICVSResource { * @param notifications the set of operations for which the local user would like notification * while the local file is being edited. */ - public void edit(int notifications) throws CVSException; + public void edit(int notifications, IProgressMonitor monitor) throws CVSException; /** * Undo a checkout of the file (analogous to "cvs unedit"). @@ -132,8 +133,15 @@ public interface ICVSFile extends ICVSResource { * a notification message that will be sent to the server on the next connection * If <code>isCheckedOut()</code> returns <code>false</code> then nothing is done. */ - public void unedit() throws CVSException; - + public void unedit(IProgressMonitor monitor) throws CVSException; + + /** + * Update the file's sync info to the given value and reset the read-only + * status of the file if a previous revision of the file was stored in the + * CVS/BASE directory. + */ + public void committed(ResourceSyncInfo info) throws CVSException; + /** * Answer any pending notification information associated with the receiver. * diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSFileModificationValidator.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSFileModificationValidator.java new file mode 100644 index 000000000..59fb2be25 --- /dev/null +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSFileModificationValidator.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2002 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM - Initial implementation + ******************************************************************************/ +package org.eclipse.team.internal.ccvs.core; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFileModificationValidator; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; + +/** + * @author Administrator + * + * To change this generated comment edit the template variable "typecomment": + * Window>Preferences>Java>Templates. + * To enable and disable the creation of type comments go to + * Window>Preferences>Java>Code Generation. + */ +public interface ICVSFileModificationValidator extends IFileModificationValidator { + + public IStatus validateMoveDelete(IFile[] files, IProgressMonitor monitor); + +} diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/CheckedInHandler.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/CheckedInHandler.java index 8217bf20a..1b7845b20 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/CheckedInHandler.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/CheckedInHandler.java @@ -57,7 +57,7 @@ class CheckedInHandler extends ResponseHandler { newInfo = new ResourceSyncInfo(entryLine, fileInfo.getPermissions(), mFile.getTimeStamp()); } - mFile.setSyncInfo(newInfo); + mFile.committed(newInfo); } } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Command.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Command.java index 02256bc1c..1eddf23b0 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Command.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Command.java @@ -509,6 +509,19 @@ public abstract class Command extends Request { public void send(Session session) throws CVSException { session.sendGlobalOption(option); } + /** + * Add the given global option to the end of the provided list + * + * @param newOption + * @param options + * @return GlobalOption[] + */ + protected GlobalOption[] addToEnd(GlobalOption[] options) { + GlobalOption[] globalOptions = new GlobalOption[options.length + 1]; + System.arraycopy(options, 0, globalOptions, 0, options.length); + globalOptions[globalOptions.length - 1] = this; + return globalOptions; + } } /** * Option subtype for global quietness options. @@ -665,6 +678,8 @@ public abstract class Command extends Request { /** * Allows commands to filter the set of global options to be sent. + * This method invokes the method of the same name on the session + * itself in order to get any session wide or globally set options. * Subclasses that override this method should call the superclass. * * @param session the session @@ -672,16 +687,7 @@ public abstract class Command extends Request { * @return the filtered global options */ protected GlobalOption[] filterGlobalOptions(Session session, GlobalOption[] globalOptions) { - if (! DO_NOT_CHANGE.isElementOf(globalOptions)) { - QuietOption quietOption = CVSProviderPlugin.getPlugin().getQuietness(); - if (quietOption != null) { - GlobalOption[] oldOptions = globalOptions; - globalOptions = new GlobalOption[oldOptions.length + 1]; - System.arraycopy(oldOptions, 0, globalOptions, 1, oldOptions.length); - globalOptions[0] = quietOption; - } - } - return globalOptions; + return session.filterGlobalOptions(globalOptions); } /** diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java index 605ce45a3..a22d00bd7 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java @@ -48,6 +48,8 @@ import org.eclipse.team.internal.ccvs.core.ICVSResource; import org.eclipse.team.internal.ccvs.core.ICVSResourceVisitor; import org.eclipse.team.internal.ccvs.core.ICVSRunnable; import org.eclipse.team.internal.ccvs.core.Policy; +import org.eclipse.team.internal.ccvs.core.client.Command.GlobalOption; +import org.eclipse.team.internal.ccvs.core.client.Command.QuietOption; import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; import org.eclipse.team.internal.ccvs.core.connection.Connection; import org.eclipse.team.internal.ccvs.core.syncinfo.NotifyInfo; @@ -1094,4 +1096,30 @@ public class Session { public void setTextTransferOverride(Collection textTransferOverrideSet) { this.textTransferOverrideSet = textTransferOverrideSet; } + + /** + * Filter the provided global options using parameters set on this session + * or globally. The session may add global options that correspond to user + * preferences or remove those that contradict requirements for this + * particular session. + * + * @param globalOptions the global options, read-only + * @return the filtered global options + */ + protected GlobalOption[] filterGlobalOptions(GlobalOption[] globalOptions) { + if (! Command.DO_NOT_CHANGE.isElementOf(globalOptions)) { + // Get the user preference for verbosity + QuietOption quietOption = CVSProviderPlugin.getPlugin().getQuietness(); + if (quietOption != null) { + globalOptions = quietOption.addToEnd(globalOptions); + } + // Get the user preference for read-only + if (CVSProviderPlugin.getPlugin().getPluginPreferences().getBoolean(CVSProviderPlugin.READ_ONLY)) { + if (!Command.MAKE_READ_ONLY.isElementOf(globalOptions)) { + globalOptions = Command.MAKE_READ_ONLY.addToEnd(globalOptions); + } + } + } + return globalOptions; + } } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/LogListener.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/LogListener.java index 06556b9e6..7cb07e209 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/LogListener.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/LogListener.java @@ -36,7 +36,7 @@ public class LogListener implements ICommandOutputListener { private String fileState; // private StringBuffer comment; // comment - private static final String NOTHING_KNOWN_ABOUT = "nothing known about "; + private static final String NOTHING_KNOWN_ABOUT = "nothing known about "; //$NON-NLS-1$ public LogListener(RemoteFile file, List entries) { this.file = file; diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties index 8e99de7ee..0309da753 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties @@ -231,6 +231,8 @@ SyncFileUtil_Error_reloading_sync_information_58=Error reloading sync informatio SyncFileUtil_Error_writing_to_.cvsignore_61=Error writing to .cvsignore SyncFileUtil_Cannot_close_.cvsignore_62=Cannot close .cvsignore SyncFileWriter.cvsFolderNotHidden=Folder ''{0}'' was not previously hidden but has now been marked as hidden. If it still appears in a view, close that view and reopen it. +SyncFileWriter.baseNotAvailable=Could not restore the base contents of ''{0}'' from the local cache. +BaseRevInfo.malformedEntryLine=Malformed entry line ''{0}'' for base revision information file. FileModificationValidator.isReadOnly=File is Read Only. diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java index 56685c03b..c3a15d487 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java @@ -31,6 +31,7 @@ import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource; import org.eclipse.team.internal.ccvs.core.ICVSResourceVisitor; import org.eclipse.team.internal.ccvs.core.ILogEntry; import org.eclipse.team.internal.ccvs.core.Policy; +import org.eclipse.team.internal.ccvs.core.syncinfo.BaserevInfo; import org.eclipse.team.internal.ccvs.core.syncinfo.NotifyInfo; import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; @@ -260,10 +261,34 @@ public class EclipseFile extends EclipseResource implements ICVSFile { } /** + * @see org.eclipse.team.internal.ccvs.core.ICVSFile#setNotifyInfo(NotifyInfo) + */ + public void setBaserevInfo(BaserevInfo info) throws CVSException { + if (isManaged()) { + if (info == null) { + EclipseSynchronizer.getInstance().deleteBaserevInfo(resource); + EclipseSynchronizer.getInstance().deleteFileFromBaseDirectory(getIFile(), null); + } else + EclipseSynchronizer.getInstance().setBaserevInfo(resource, info); + } + } + /** + * @see org.eclipse.team.internal.ccvs.core.ICVSFile#getNotifyInfo() + */ + public BaserevInfo getBaserevInfo() throws CVSException { + if (isManaged()) { + return EclipseSynchronizer.getInstance().getBaserevInfo(resource); + } + return null; + } + + /** * @see org.eclipse.team.internal.ccvs.core.ICVSFile#checkout(int) */ - public void edit(int notifications) throws CVSException { + public void edit(int notifications, IProgressMonitor monitor) throws CVSException { if (!isReadOnly()) return; + ResourceSyncInfo info = getSyncInfo(); + if (info == null || info.isAdded()) return; // convert the notifications to internal form char[] internalFormat; @@ -286,10 +311,11 @@ public class EclipseFile extends EclipseResource implements ICVSFile { } // record the notification - NotifyInfo info = new NotifyInfo(getName(), NotifyInfo.EDIT, new Date(), internalFormat); - setNotifyInfo(info); + NotifyInfo notifyInfo = new NotifyInfo(getName(), NotifyInfo.EDIT, new Date(), internalFormat); + setNotifyInfo(notifyInfo); - // XXX Copy original file to CVS/Base directory abd update CVS/Baserev file + EclipseSynchronizer.getInstance().copyFileToBaseDirectory(getIFile(), monitor); + setBaserevInfo(new BaserevInfo(getName(), info.getRevision())); // allow editing setReadOnly(false); @@ -298,7 +324,7 @@ public class EclipseFile extends EclipseResource implements ICVSFile { /** * @see org.eclipse.team.internal.ccvs.core.ICVSFile#uncheckout() */ - public void unedit() throws CVSException { + public void unedit(IProgressMonitor monitor) throws CVSException { if (isReadOnly()) return; // record the notification @@ -310,7 +336,8 @@ public class EclipseFile extends EclipseResource implements ICVSFile { } setNotifyInfo(info); - // XXX Copy original file back from CVS/Base directory + EclipseSynchronizer.getInstance().restoreFileFromBaseDirectory(getIFile(), monitor); + setBaserevInfo(null); // prevent editing setReadOnly(true); @@ -329,5 +356,29 @@ public class EclipseFile extends EclipseResource implements ICVSFile { public NotifyInfo getPendingNotification() throws CVSException { return getNotifyInfo(); } + + /** + * @see org.eclipse.team.internal.ccvs.core.ICVSFile#committed(org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo) + */ + public void committed(ResourceSyncInfo info) throws CVSException { + setSyncInfo(info); + clearCachedBase(); + } + + private void clearCachedBase() throws CVSException { + BaserevInfo base = getBaserevInfo(); + if (base != null) { + setBaserevInfo(null); + setReadOnly(true); + } + } + + /** + * @see org.eclipse.team.internal.ccvs.core.ICVSResource#unmanage(org.eclipse.core.runtime.IProgressMonitor) + */ + public void unmanage(IProgressMonitor monitor) throws CVSException { + super.unmanage(monitor); + clearCachedBase(); + } }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFolder.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFolder.java index bf38c18fc..8843a53be 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFolder.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFolder.java @@ -285,13 +285,13 @@ class EclipseFolder extends EclipseResource implements ICVSFolder { final CVSException[] error = new CVSException[1]; // Remove the registered Move/Delete hook, assuming that the cvs runnable will keep sync info up-to-date final MoveDeleteHook hook = CVSTeamProvider.getRegisteredMoveDeleteHook(); - boolean oldSetting = hook.isRecordOutgoingDeletions(); + boolean oldSetting = hook.isWithinCVSOperation(); try { ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { try { - hook.setRecordOutgoingDeletions(false); - internalRun(job, monitor); + hook.setWithinCVSOperation(true); + EclipseSynchronizer.getInstance().run(job, monitor); } catch(CVSException e) { error[0] = e; } @@ -300,7 +300,7 @@ class EclipseFolder extends EclipseResource implements ICVSFolder { } catch(CoreException e) { throw CVSException.wrapException(e); } finally { - hook.setRecordOutgoingDeletions(oldSetting); + hook.setWithinCVSOperation(oldSetting); } if(error[0]!=null) { throw error[0]; @@ -316,22 +316,10 @@ class EclipseFolder extends EclipseResource implements ICVSFolder { */ public void run(final ICVSRunnable job, int flags, IProgressMonitor monitor) throws CVSException { if (flags == READ_ONLY) - internalRun(job, monitor); + EclipseSynchronizer.getInstance().run(job, monitor); else run(job, monitor); } - - private void internalRun(ICVSRunnable job, IProgressMonitor monitor) throws CVSException { - monitor = Policy.monitorFor(monitor); - monitor.beginTask(null, 100); - try { - EclipseSynchronizer.getInstance().beginOperation(Policy.subMonitorFor(monitor, 5)); - job.run(Policy.subMonitorFor(monitor, 60)); - } finally { - EclipseSynchronizer.getInstance().endOperation(Policy.subMonitorFor(monitor, 35)); - monitor.done(); - } - } /** * @see ICVSFolder#fetchChildren(IProgressMonitor) diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseSynchronizer.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseSynchronizer.java index ef515a265..6485c9133 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseSynchronizer.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseSynchronizer.java @@ -31,7 +31,9 @@ import org.eclipse.core.runtime.Status; import org.eclipse.team.internal.ccvs.core.CVSException; import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; import org.eclipse.team.internal.ccvs.core.CVSStatus; +import org.eclipse.team.internal.ccvs.core.ICVSRunnable; import org.eclipse.team.internal.ccvs.core.Policy; +import org.eclipse.team.internal.ccvs.core.syncinfo.BaserevInfo; import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo; import org.eclipse.team.internal.ccvs.core.syncinfo.NotifyInfo; import org.eclipse.team.internal.ccvs.core.syncinfo.ReentrantLock; @@ -883,7 +885,7 @@ public class EclipseSynchronizer { } return null; } - + /** * Method deleteNotifyInfo. * @param resource @@ -904,13 +906,107 @@ public class EclipseSynchronizer { } SyncFileWriter.writeAllNotifyInfo(resource.getParent(), newInfos); } + + /** + * Add the entry to the CVS/Baserev file. We are not initially concerned + * with efficiency since edit/unedit are typically issued on a small set of + * files. + * + * XXX If there was a previous notify entry for the resource, it is replaced. This is + * probably not the proper behavior (see EclipseFile). + * + * @param resource + * @param info + */ + public void setBaserevInfo(IResource resource, BaserevInfo info) throws CVSException { + BaserevInfo[] infos = SyncFileWriter.readAllBaserevInfo(resource.getParent()); + if (infos == null) { + infos = new BaserevInfo[] { info }; + } else { + Map infoMap = new HashMap(); + for (int i = 0; i < infos.length; i++) { + infoMap.put(infos[i].getName(), infos[i]); + } + infoMap.put(info.getName(), info); + BaserevInfo[] newInfos = new BaserevInfo[infoMap.size()]; + int i = 0; + for (Iterator iter = infoMap.values().iterator(); iter.hasNext();) { + newInfos[i++] = (BaserevInfo) iter.next(); + } + infos = newInfos; + } + SyncFileWriter.writeAllBaserevInfo(resource.getParent(), infos); + } + + /** + * Method getBaserevInfo. + * @param resource + * @return BaserevInfo + */ + public BaserevInfo getBaserevInfo(IResource resource) throws CVSException { + BaserevInfo[] infos = SyncFileWriter.readAllBaserevInfo(resource.getParent()); + if (infos == null) return null; + for (int i = 0; i < infos.length; i++) { + BaserevInfo info = infos[i]; + if (info.getName().equals(resource.getName())) { + return info; + } + } + return null; + } + + /** + * Method deleteNotifyInfo. + * @param resource + */ + public void deleteBaserevInfo(IResource resource) throws CVSException { + BaserevInfo[] infos = SyncFileWriter.readAllBaserevInfo(resource.getParent()); + if (infos == null) return; + Map infoMap = new HashMap(); + for (int i = 0; i < infos.length; i++) { + infoMap.put(infos[i].getName(), infos[i]); + } + infoMap.remove(resource.getName()); + BaserevInfo[] newInfos = new BaserevInfo[infoMap.size()]; + int i = 0; + for (Iterator iter = infoMap.values().iterator(); iter.hasNext();) { + newInfos[i++] = (BaserevInfo) iter.next(); + } + SyncFileWriter.writeAllBaserevInfo(resource.getParent(), newInfos); + } - public void copyFileToBaseDirectory(IFile file) throws CVSException { + public void copyFileToBaseDirectory(final IFile file, IProgressMonitor monitor) throws CVSException { + run(new ICVSRunnable() { + public void run(IProgressMonitor monitor) throws CVSException { + ResourceSyncInfo info = getResourceSync(file); + // The file must exist remotely and locally + if (info == null || info.isAdded() || info.isDeleted()) + return; + SyncFileWriter.writeFileToBaseDirectory(file, monitor); + changedResources.add(file); + } + }, monitor); + } + + public void restoreFileFromBaseDirectory(final IFile file, IProgressMonitor monitor) throws CVSException { + run(new ICVSRunnable() { + public void run(IProgressMonitor monitor) throws CVSException { + ResourceSyncInfo info = getResourceSync(file); + // The file must exist remotely + if (info == null || info.isAdded()) + return; + SyncFileWriter.restoreFileFromBaseDirectory(file, monitor); + changedResources.add(file); + } + }, monitor); + } + + public void deleteFileFromBaseDirectory(final IFile file, IProgressMonitor monitor) throws CVSException { ResourceSyncInfo info = getResourceSync(file); - // The file must exist remotely and must exist - if (info == null || info.isAdded() || info.isDeleted()) + // The file must exist remotely + if (info == null || info.isAdded()) return; - SyncFileWriter.writeFileToBaseDirectory(file, info); + SyncFileWriter.deleteFileFromBaseDirectory(file, monitor); } /** @@ -997,4 +1093,16 @@ public class EclipseSynchronizer { } return (IContainer[]) folders.toArray(new IContainer[folders.size()]); } + + public void run(ICVSRunnable job, IProgressMonitor monitor) throws CVSException { + monitor = Policy.monitorFor(monitor); + monitor.beginTask(null, 100); + try { + beginOperation(Policy.subMonitorFor(monitor, 5)); + job.run(Policy.subMonitorFor(monitor, 60)); + } finally { + endOperation(Policy.subMonitorFor(monitor, 35)); + monitor.done(); + } + } }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java index a664fd138..922fbe480 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java @@ -552,14 +552,14 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { /** * @see org.eclipse.team.internal.ccvs.core.ICVSFile#checkout(int) */ - public void edit(int notifications) throws CVSException { + public void edit(int notifications, IProgressMonitor monitor) throws CVSException { // do nothing } /** * @see org.eclipse.team.internal.ccvs.core.ICVSFile#uncheckout() */ - public void unedit() throws CVSException { + public void unedit(IProgressMonitor monitor) throws CVSException { // do nothing } @@ -595,5 +595,11 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { remoteFolder.setChildren(new ICVSRemoteResource[] { remoteFile }); return remoteFile; } + /** + * @see org.eclipse.team.internal.ccvs.core.ICVSFile#committed(org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo) + */ + public void committed(ResourceSyncInfo info) throws CVSException { + // do nothing + } }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/BaserevInfo.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/BaserevInfo.java new file mode 100644 index 000000000..e9422ff9d --- /dev/null +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/BaserevInfo.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2002 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM - Initial implementation + ******************************************************************************/ +package org.eclipse.team.internal.ccvs.core.syncinfo; + +import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.internal.ccvs.core.Policy; +import org.eclipse.team.internal.ccvs.core.util.EmptyTokenizer; + +/** + * This class represents the information in the CVS/Baserev file + */ +public class BaserevInfo { + private static final String BASEREV_PREFIX = "B"; //$NON-NLS-1$ + + private String name; + private String revision; + + public BaserevInfo(String entryLine) throws CVSException { + setEntryLine(entryLine); + } + + public BaserevInfo(String name, String revision) { + this.name = name; + this.revision = revision; + } + /** + * Return the entry line as it appears in the CVS/Baserev file + * @return String + */ + public String getEntryLine() { + StringBuffer result = new StringBuffer(); + result.append(BASEREV_PREFIX); + result.append(name); + result.append(ResourceSyncInfo.SEPARATOR); + result.append(revision); + return result.toString(); + } + private void setEntryLine(String entryLine) throws CVSException { + if(entryLine.startsWith(BASEREV_PREFIX)) { + entryLine = entryLine.substring(1); + } + EmptyTokenizer tokenizer = new EmptyTokenizer(entryLine, ResourceSyncInfo.SEPARATOR); + if(tokenizer.countTokens() != 2) { + throw new CVSException(Policy.bind("BaseRevInfo.malformedEntryLine", entryLine)); //$NON-NLS-1$ + } + + name = tokenizer.nextToken(); + + if(name.length()==0) { + throw new CVSException(Policy.bind("BaseRevInfo.malformedEntryLine", entryLine)); //$NON-NLS-1$ + } + + revision = tokenizer.nextToken(); + + if(revision.length()==0) { + throw new CVSException(Policy.bind("BaseRevInfo.malformedEntryLine", entryLine)); //$NON-NLS-1$ + } + } + /** + * Returns the name. + * @return String + */ + public String getName() { + return name; + } + + /** + * Returns the revision. + * @return String + */ + public String getRevision() { + return revision; + } + +} diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/MoveDeleteHook.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/MoveDeleteHook.java index 7a76a31ad..0000158ad 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/MoveDeleteHook.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/MoveDeleteHook.java @@ -10,20 +10,30 @@ ******************************************************************************/ package org.eclipse.team.internal.ccvs.core.util; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFileModificationValidator; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.team.IMoveDeleteHook; import org.eclipse.core.resources.team.IResourceTree; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.internal.ccvs.core.CVSException; import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; +import org.eclipse.team.internal.ccvs.core.CVSTeamProvider; import org.eclipse.team.internal.ccvs.core.ICVSFile; +import org.eclipse.team.internal.ccvs.core.ICVSFileModificationValidator; import org.eclipse.team.internal.ccvs.core.ICVSFolder; import org.eclipse.team.internal.ccvs.core.ICVSRunnable; +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.EclipseSynchronizer; import org.eclipse.team.internal.ccvs.core.syncinfo.MutableResourceSyncInfo; @@ -35,7 +45,7 @@ import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; */ public class MoveDeleteHook implements IMoveDeleteHook { - private boolean recordOutgoingDeletions = true; + private boolean withinCVSOperation = false; /* * Delete the file and return true if an outgoing deletion will result @@ -53,7 +63,7 @@ public class MoveDeleteHook implements IMoveDeleteHook { ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(source); try { ResourceSyncInfo info = cvsFile.getSyncInfo(); - if (recordOutgoingDeletions && info != null && ! info.isAdded()) { + if (!withinCVSOperation && info != null && ! info.isAdded()) { MutableResourceSyncInfo newInfo = info.cloneMutable(); newInfo.setDeleted(true); cvsFile.setSyncInfo(newInfo); @@ -125,12 +135,12 @@ public class MoveDeleteHook implements IMoveDeleteHook { IFile file, int updateFlags, IProgressMonitor monitor) { - - // No special action is required here. - // The AddDeleteMoveListener will update the sync info of the file - return false; + + // Return the opposite of the checkout request. + // If the file is deleted, the AddDeleteMoveListener will update the sync info of the file + return !checkOutFiles(tree, new IFile[] {file}, monitor); } - + /** * @see IMoveDeleteHook#deleteFolder(IResourceTree, IFolder, int, IProgressMonitor) */ @@ -140,10 +150,12 @@ public class MoveDeleteHook implements IMoveDeleteHook { final int updateFlags, IProgressMonitor monitor) { - final ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor(folder); + monitor.beginTask(null, 100); try { + if (!ensureCheckedOut(folder, tree, Policy.subMonitorFor(monitor, 30))) return true; + final ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor(folder); if (cvsFolder.isManaged()) { - cvsFolder.run(new ICVSRunnable() { + EclipseSynchronizer.getInstance().run(new ICVSRunnable() { public void run(IProgressMonitor monitor) throws CVSException { try { makeFolderOutgoingDeletion(tree, folder, null, updateFlags, monitor); @@ -151,11 +163,13 @@ public class MoveDeleteHook implements IMoveDeleteHook { tree.failed(e.getStatus()); } } - }, monitor); + }, Policy.subMonitorFor(monitor, 70)); return true; } } catch (CVSException e) { tree.failed(e.getStatus()); + } finally { + monitor.done(); } return false; } @@ -175,6 +189,7 @@ public class MoveDeleteHook implements IMoveDeleteHook { } catch (CVSException e) { CVSProviderPlugin.log(e.getStatus()); } + // todo: Perform a "cvs release" if there are any edits on the project return false; } @@ -182,15 +197,18 @@ public class MoveDeleteHook implements IMoveDeleteHook { * @see IMoveDeleteHook#moveFile(IResourceTree, IFile, IFile, int, IProgressMonitor) */ public boolean moveFile( - IResourceTree tree, - IFile source, - IFile destination, - int updateFlags, - IProgressMonitor monitor) { - - // No special action is required here. - // The AddDeleteMoveListener will update the sync info of the source - return false; + IResourceTree tree, + IFile source, + IFile destination, + int updateFlags, + IProgressMonitor monitor) { + + // See comment in deleteFile + if (destination.exists()) + // Ensure that we can write to the destination + return !checkOutFiles(tree, new IFile[] {source, destination}, monitor); + else + return !checkOutFiles(tree, new IFile[] {source}, monitor); } /** @@ -203,10 +221,13 @@ public class MoveDeleteHook implements IMoveDeleteHook { final int updateFlags, IProgressMonitor monitor) { - final ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor(source); + monitor.beginTask(null, 100); try { + if (!ensureCheckedOut(source, tree, Policy.subMonitorFor(monitor, 30))) return true; + if (!ensureCheckedOut(destination, tree, Policy.subMonitorFor(monitor, 10))) return true; + final ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor(source); if (cvsFolder.isManaged()) { - cvsFolder.run(new ICVSRunnable() { + EclipseSynchronizer.getInstance().run(new ICVSRunnable() { public void run(IProgressMonitor monitor) throws CVSException { try { makeFolderOutgoingDeletion(tree, source, destination, updateFlags, monitor); @@ -214,11 +235,13 @@ public class MoveDeleteHook implements IMoveDeleteHook { tree.failed(e.getStatus()); } } - }, monitor); + }, Policy.subMonitorFor(monitor, 60)); return true; } } catch (CVSException e) { tree.failed(e.getStatus()); + } finally { + monitor.done(); } return false; @@ -236,7 +259,8 @@ public class MoveDeleteHook implements IMoveDeleteHook { // We need to move (or flush) any remembered folder deletions for the deleted project // XXX We flush for now. This means that deleting a managed folder and then moving the - // project will mean that the file deletions will be lost. + // project will mean that the file deletions will be lost. It also means that phantom + // folders are lost. try { EclipseSynchronizer.getInstance().prepareForDeletion(source); } catch (CVSException e) { @@ -249,16 +273,72 @@ public class MoveDeleteHook implements IMoveDeleteHook { * Returns the recordOutgoingDeletions. * @return boolean */ - public boolean isRecordOutgoingDeletions() { - return recordOutgoingDeletions; + public boolean isWithinCVSOperation() { + return withinCVSOperation; } /** * Sets the recordOutgoingDeletions. * @param recordOutgoingDeletions The recordOutgoingDeletions to set */ - public void setRecordOutgoingDeletions(boolean recordOutgoingDeletions) { - this.recordOutgoingDeletions = recordOutgoingDeletions; + public void setWithinCVSOperation(boolean withinCVSOperation) { + this.withinCVSOperation = withinCVSOperation; + } + + /** + * Ensure that the given file is checked out (i.e. not read only). Return + * true if it is OK to procede and false otherwise. + * + * @param tree + * @param file + * @return boolean + */ + private boolean checkOutFiles(IResourceTree tree, IFile[] files, IProgressMonitor monitor) { + // Ensure that the file is "checked out" (i.e. not read-only + IFileModificationValidator validator = getFileModificationValidator(files); + if (validator instanceof ICVSFileModificationValidator) { + IStatus status = ((ICVSFileModificationValidator)validator).validateMoveDelete(files, monitor); + if (status.isOK()) { + return true; + } else { + tree.failed(status); + return false; + } + } + return true; } + private boolean ensureCheckedOut(IFolder folder, IResourceTree tree, IProgressMonitor monitor) { + if (!folder.exists()) return true; + try { + final List readOnlyFiles = new ArrayList(); + // First, find any read-only files + folder.accept(new IResourceVisitor() { + public boolean visit(IResource resource) throws CoreException { + if (resource.getType() == IResource.FILE) { + IFile file = (IFile) resource; + if (file.isReadOnly()) { + readOnlyFiles.add(file); + } + } + return true; + } + }); + if (readOnlyFiles.isEmpty()) return true; + // Next, ensure they are checked out + return checkOutFiles(tree, (IFile[]) readOnlyFiles.toArray(new IFile[readOnlyFiles.size()]), monitor); + } catch (CoreException e) { + tree.failed(e.getStatus()); + return false; + } + } + + private IFileModificationValidator getFileModificationValidator(IFile[] files) { + return getProvider(files).getFileModificationValidator(); + } + + private CVSTeamProvider getProvider(IFile[] files) { + CVSTeamProvider provider = (CVSTeamProvider)RepositoryProvider.getProvider(files[0].getProject(), CVSProviderPlugin.getTypeId()); + return provider; + } } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/SyncFileWriter.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/SyncFileWriter.java index 658345fad..af0bbf738 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/SyncFileWriter.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/SyncFileWriter.java @@ -34,6 +34,7 @@ import org.eclipse.team.internal.ccvs.core.CVSStatus; import org.eclipse.team.internal.ccvs.core.CVSTag; import org.eclipse.team.internal.ccvs.core.Policy; import org.eclipse.team.internal.ccvs.core.resources.CVSEntryLineTag; +import org.eclipse.team.internal.ccvs.core.syncinfo.BaserevInfo; import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo; import org.eclipse.team.internal.ccvs.core.syncinfo.NotifyInfo; import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; @@ -315,7 +316,64 @@ public class SyncFileWriter { writeLines(cvsSubDir.getFile(NOTIFY), entries); } } - + + /** + * Reads the CVS/Baserev file from the specified folder and returns + * BaserevInfo instances for the data stored therein. If the folder does not + * have a CVS subdirectory then <code>null</code> is returned. + */ + public static BaserevInfo[] readAllBaserevInfo(IContainer parent) throws CVSException { + IFolder cvsSubDir = getCVSSubdirectory(parent); + if (! cvsSubDir.exists()) return null; + + // process Notify file contents + String[] entries = readLines(cvsSubDir.getFile(BASEREV)); + if (entries == null) return null; + Map infos = new TreeMap(); + for (int i = 0; i < entries.length; i++) { + String line = entries[i]; + if(!"".equals(line)) { //$NON-NLS-1$ + BaserevInfo info = new BaserevInfo(line); + infos.put(info.getName(), info); + } + } + + return (BaserevInfo[])infos.values().toArray(new BaserevInfo[infos.size()]); + } + + /** + * Writes the CVS/Baserev file to the specified folder using the data + * contained in the specified BaserevInfo instances. A CVS subdirectory must + * already exist (an exception is thrown if it doesn't). + */ + public static void writeAllBaserevInfo(IContainer parent, BaserevInfo[] infos) throws CVSException { + // get the CVS directory + IFolder cvsSubDir = getCVSSubdirectory(parent); + // write lines will throw an exception if the CVS directory does not exist + + if (infos.length == 0) { + // if there are no notify entries, delete the notify file + try { + IFile file = cvsSubDir.getFile(BASEREV); + if(file.exists()) { + file.delete(IResource.NONE, null); + } + } catch (CoreException e) { + throw CVSException.wrapException(e); + } + } else { + // format file contents + String[] entries = new String[infos.length]; + for (int i = 0; i < infos.length; i++) { + BaserevInfo info = infos[i]; + entries[i] = info.getEntryLine(); + } + + // write Notify entries + writeLines(cvsSubDir.getFile(BASEREV), entries); + } + } + /** * Returns the CVS subdirectory for this folder. */ @@ -445,24 +503,73 @@ public class SyncFileWriter { * @param file * @param info */ - public static void writeFileToBaseDirectory(IFile file, ResourceSyncInfo info) throws CVSException { + public static void writeFileToBaseDirectory(IFile file, IProgressMonitor monitor) throws CVSException { + monitor = Policy.monitorFor(monitor); + monitor.beginTask(null, 100); try { IContainer cvsFolder = getCVSSubdirectory(file.getParent()); IFolder baseFolder = cvsFolder.getFolder(new Path(BASE_DIRNAME)); if (!baseFolder.exists()) { - baseFolder.create(false /* force */, true /* local */, null); + baseFolder.create(false /* force */, true /* local */, Policy.subMonitorFor(monitor, 10)); } IFile target = baseFolder.getFile(new Path(file.getName())); if (target.exists()) { // XXX Should ensure that we haven't already copied it // XXX write the revision to the CVS/Baserev file - target.setContents(file.getContents(), false /* force */, false /* history */, null); - } else { - // should use copy to ensure timestamp is the same - target.create(file.getContents(), false /* force */, null); + target.delete(true, Policy.subMonitorFor(monitor, 10)); + } + // Copy the file so the timestamp is maintained + file.copy(target.getFullPath(), true /* force */, Policy.subMonitorFor(monitor, 80)); + } catch (CoreException e) { + throw CVSException.wrapException(e); + } finally { + monitor.done(); + } + } + /** + * Method restoreFileFromBaseDirectory. + * @param file + * @param info + * @param monitor + */ + public static void restoreFileFromBaseDirectory(IFile file, IProgressMonitor monitor) throws CVSException { + monitor = Policy.monitorFor(monitor); + monitor.beginTask(null, 100); + try { + IContainer cvsFolder = getCVSSubdirectory(file.getParent()); + IFolder baseFolder = cvsFolder.getFolder(new Path(BASE_DIRNAME)); + IFile source = baseFolder.getFile(new Path(file.getName())); + if (!source.exists()) { + throw new CVSException(Policy.bind("SyncFileWriter.baseNotAvailable", file.getFullPath().toString())); //$NON-NLS-1$ + } + // Copy the file so the timestamp is maintained + source.move(file.getFullPath(), false /* force */, Policy.subMonitorFor(monitor, 100)); + } catch (CoreException e) { + throw CVSException.wrapException(e); + } finally { + monitor.done(); + } + } + + /** + * Method deleteFileFromBaseDirectory. + * @param file + * @param monitor + */ + public static void deleteFileFromBaseDirectory(IFile file, IProgressMonitor monitor) throws CVSException { + monitor = Policy.monitorFor(monitor); + monitor.beginTask(null, 100); + try { + IContainer cvsFolder = getCVSSubdirectory(file.getParent()); + IFolder baseFolder = cvsFolder.getFolder(new Path(BASE_DIRNAME)); + IFile source = baseFolder.getFile(new Path(file.getName())); + if (source.exists()) { + source.delete(false, false, Policy.subMonitorFor(monitor, 100)); } } catch (CoreException e) { throw CVSException.wrapException(e); + } finally { + monitor.done(); } } diff --git a/bundles/org.eclipse.team.cvs.ui/plugin.xml b/bundles/org.eclipse.team.cvs.ui/plugin.xml index f3acdd757..efe4a5c3c 100644 --- a/bundles/org.eclipse.team.cvs.ui/plugin.xml +++ b/bundles/org.eclipse.team.cvs.ui/plugin.xml @@ -31,6 +31,15 @@ </run> </authenticator> </extension> +<!-- *************** CVS File Modification Validator **************** --> + <extension + point="org.eclipse.team.cvs.core.filemodificationvalidator"> + <validator> + <run + class="org.eclipse.team.internal.ccvs.ui.FileModificationValidator"> + </run> + </validator> + </extension> <!-- ******************* Wizards ****************** --> <extension point="org.eclipse.team.ui.configurationWizards"> @@ -572,7 +581,6 @@ id="org.eclipse.team.cvs.ui.ExtMethodPreferencePage"> </page> </extension> - <!-- <extension point="org.eclipse.ui.preferencePages"> <page @@ -582,7 +590,7 @@ id="org.eclipse.team.cvs.ui.WatchEditPreferencePage"> </page> </extension> - --> + <!-- **************** Decorator ******************* --> <extension point="org.eclipse.ui.decorators"> diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIPlugin.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIPlugin.java index a68fc0e89..4e6415949 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIPlugin.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIPlugin.java @@ -369,6 +369,43 @@ public class CVSUIPlugin extends AbstractUIPlugin implements IPropertyChangeList // Log if the user requested it if (log) CVSUIPlugin.log(status); + // Create a runnable that will display the error status + final String displayTitle = title; + final String displayMessage = message; + final IStatus displayStatus = status; + final IOpenableInShell openable = new IOpenableInShell() { + public void open(Shell shell) { + if (displayStatus.getSeverity() == IStatus.INFO && !displayStatus.isMultiStatus()) { + MessageDialog.openInformation(shell, Policy.bind("information"), displayStatus.getMessage()); //$NON-NLS-1$ + } else { + ErrorDialog.openError(shell, displayTitle, displayMessage, displayStatus); + } + } + }; + openDialog(providedShell, openable, flags); + + // return the status we display + return status; + } + + /** + * Interface that allows a shell to be passed to an open method. The + * provided shell can be used without sync-execing, etc. + */ + public interface IOpenableInShell { + public void open(Shell shell); + } + + /** + * Open the dialog code provided in the IOpenableInShell, ensuring that + * the provided whll is valid. This method will provide a shell to the + * IOpenableInShell if one is not provided to the method. + * + * @param providedShell + * @param openable + * @param flags + */ + public static void openDialog(Shell providedShell, final IOpenableInShell openable, int flags) { // If no shell was provided, try to get one from the active window if (providedShell == null) { IWorkbenchWindow window = CVSUIPlugin.getPlugin().getWorkbench().getActiveWorkbenchWindow(); @@ -378,13 +415,10 @@ public class CVSUIPlugin extends AbstractUIPlugin implements IPropertyChangeList flags = flags | PERFORM_SYNC_EXEC; } } - + // Create a runnable that will display the error status final Shell shell = providedShell; - final String displayTitle = title; - final String displayMessage = message; - final IStatus displayStatus = status; - Runnable runnable = new Runnable() { + Runnable outerRunnable = new Runnable() { public void run() { Shell displayShell; if (shell == null) { @@ -393,17 +427,13 @@ public class CVSUIPlugin extends AbstractUIPlugin implements IPropertyChangeList } else { displayShell = shell; } - if (displayStatus.getSeverity() == IStatus.INFO && !displayStatus.isMultiStatus()) { - MessageDialog.openInformation(displayShell, Policy.bind("information"), displayStatus.getMessage()); //$NON-NLS-1$ - } else { - ErrorDialog.openError(displayShell, displayTitle, displayMessage, displayStatus); - } + openable.open(displayShell); if (shell == null) { displayShell.dispose(); } } }; - + // Execute the above runnable as determined by the parameters if (shell == null || (flags & PERFORM_SYNC_EXEC) > 0) { Display display; @@ -415,13 +445,10 @@ public class CVSUIPlugin extends AbstractUIPlugin implements IPropertyChangeList } else { display = shell.getDisplay(); } - display.syncExec(runnable); + display.syncExec(outerRunnable); } else { - runnable.run(); + outerRunnable.run(); } - - // return the status we display - return status; } /** diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/FileModificationValidator.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/FileModificationValidator.java new file mode 100644 index 000000000..c0547370f --- /dev/null +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/FileModificationValidator.java @@ -0,0 +1,185 @@ +/******************************************************************************* + * Copyright (c) 2002 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM - Initial implementation + ******************************************************************************/ +package org.eclipse.team.internal.ccvs.ui; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; +import org.eclipse.team.internal.ccvs.core.CVSTeamProvider; +import org.eclipse.team.internal.ccvs.core.ICVSFile; +import org.eclipse.team.internal.ccvs.core.ICVSFileModificationValidator; +import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; + +/** + * IFileModificationValidator that is pluged into the CVS Repository Provider + */ +public class FileModificationValidator implements ICVSFileModificationValidator { + + public static final IStatus OK = new Status(IStatus.OK, CVSUIPlugin.ID, 0, Policy.bind("ok"), null); //$NON-NLS-1$ + private static final int HIGHJACK = 1; + + public FileModificationValidator() { + } + + /** + * @see org.eclipse.core.resources.IFileModificationValidator#validateEdit(org.eclipse.core.resources.IFile, java.lang.Object) + */ + public IStatus validateEdit(IFile[] files, Object context) { + IFile[] readOnlyFiles = getManagedReadOnlyFiles(files); + if (readOnlyFiles.length == 0) return OK; + return edit(readOnlyFiles, getShell(context)); + } + + /** + * @see org.eclipse.core.resources.IFileModificationValidator#validateSave(org.eclipse.core.resources.IFile) + */ + public IStatus validateSave(IFile file) { + if (!needsCheckout(file)) return OK; + return edit(new IFile[] {file}, (Shell)null); + } + + /** + * @see org.eclipse.team.internal.ccvs.core.ICVSFileModificationValidator#validateMoveDelete(org.eclipse.core.resources.IFile[], org.eclipse.core.runtime.IProgressMonitor) + */ + public IStatus validateMoveDelete(IFile[] files, IProgressMonitor monitor) { + IFile[] readOnlyFiles = getManagedReadOnlyFiles(files); + if (readOnlyFiles.length == 0) return OK; + if (isPrompt()) { + IStatus status = promptToEditFiles(files, null); + if (!status.isOK() || status.getCode() == HIGHJACK) return status; + } + try { + edit(readOnlyFiles, monitor); + return OK; + } catch (CVSException e) { + return e.getStatus(); + } + } + + private IFile[] getManagedReadOnlyFiles(IFile[] files) { + List readOnlys = new ArrayList(); + for (int i = 0; i < files.length; i++) { + IFile iFile = files[i]; + if (needsCheckout(iFile)) { + readOnlys.add(iFile); + } + } + return (IFile[]) readOnlys.toArray(new IFile[readOnlys.size()]); + } + + private boolean needsCheckout(IFile file) { + try { + if (file.isReadOnly()) { + ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(file); + return cvsFile.isManaged(); + } + } catch (CVSException e) { + // Log the exception and assume we don't need a checkout + CVSUIPlugin.log(e); + } + return false; + } + + private CVSTeamProvider getProvider(IFile[] files) { + CVSTeamProvider provider = (CVSTeamProvider)RepositoryProvider.getProvider(files[0].getProject(), CVSProviderPlugin.getTypeId()); + return provider; + } + + private Shell getShell(Object context) { + if (context instanceof Shell) + return (Shell)context; + return null; + } + + private IStatus getStatus(InvocationTargetException e) { + Throwable target = e.getTargetException(); + if (target instanceof TeamException) { + return ((TeamException) target).getStatus(); + } else if (target instanceof CoreException) { + return ((CoreException) target).getStatus(); + } + return new Status(IStatus.ERROR, CVSUIPlugin.ID, 0, Policy.bind("internal"), target); + } + + private IStatus edit(final IFile[] files, Shell shell) { + if (isPrompt()) { + IStatus status = promptToEditFiles(files, shell); + if (!status.isOK() || status.getCode() == HIGHJACK) return status; + } + // Create a runnable to edit the file + try { + run(shell, new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + try { + edit(files, monitor); + } catch (CVSException e) { + new InvocationTargetException(e); + } + } + }); + return OK; + } catch (InvocationTargetException e) { + return getStatus(e); + } + } + + private boolean isPrompt() { + return WatchEditPreferencePage.PROMPT.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_PROMPT_ON_EDIT)); + } + + private IStatus promptToEditFiles(IFile[] files, Shell shell) { + final IStatus[] result = new IStatus[] { OK }; + CVSUIPlugin.openDialog(shell, new CVSUIPlugin.IOpenableInShell() { + public void open(Shell shell) { + if (!MessageDialog.openQuestion(shell, "CVS Edit Files?", "There are read-only files being modified. Should a 'cvs edit' be performed?")) { + result[0] = new Status(IStatus.ERROR, CVSUIPlugin.ID, 0, "User vetoed file modfication", null); + } + //todo: need a custom DetailsDialog + } + }, 0); + return result[0]; + } + + private void run(Shell shell, final IRunnableWithProgress runnable) throws InvocationTargetException { + final InvocationTargetException[] exception = new InvocationTargetException[] { null }; + CVSUIPlugin.openDialog(shell, new CVSUIPlugin.IOpenableInShell() { + public void open(Shell shell) { + try { + new ProgressMonitorDialog(shell).run(true /* fork */, true /* cancellable */, runnable); + } catch (InvocationTargetException e) { + exception[0] = e; + } catch (InterruptedException e) { + // do nothing + } + } + }, 0); + if (exception[0] != null) + throw exception[0]; + } + + private void edit(IFile[] files, IProgressMonitor monitor) throws CVSException { + getProvider(files).edit(files, false /* recurse */, true /* notify server */, ICVSFile.NO_NOTIFICATION, monitor); + } +} diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/WatchEditPreferencePage.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/WatchEditPreferencePage.java index edd6be436..fc7af7fdf 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/WatchEditPreferencePage.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/WatchEditPreferencePage.java @@ -10,9 +10,11 @@ ******************************************************************************/ package org.eclipse.team.internal.ccvs.ui; +import org.eclipse.core.runtime.Preferences; import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.RadioGroupFieldEditor; +import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; /** * This page contains preferences related to the cvs watch/edit commands @@ -23,9 +25,16 @@ public class WatchEditPreferencePage extends CVSFieldEditorPreferencePage { public static final String PROMPT = "prompt"; //$NON-NLS-1$ public static void setDefaults() { + // Get the preference store from CVS core + Preferences corePrefs = CVSProviderPlugin.getPlugin().getPluginPreferences(); + // Set the UI defaults IPreferenceStore store = getCVSPreferenceStore(); - store.setDefault(ICVSUIConstants.PREF_CHECKOUT_READ_ONLY, false); + store.setDefault(ICVSUIConstants.PREF_CHECKOUT_READ_ONLY, + corePrefs.getDefaultBoolean(CVSProviderPlugin.READ_ONLY)); store.setDefault(ICVSUIConstants.PREF_PROMPT_ON_EDIT, PROMPT); + // Ensure that the preference values in UI match Core + store.setValue(ICVSUIConstants.PREF_CHECKOUT_READ_ONLY, + corePrefs.getBoolean(CVSProviderPlugin.READ_ONLY)); } /** @@ -63,8 +72,16 @@ public class WatchEditPreferencePage extends CVSFieldEditorPreferencePage { */ public boolean performOk() { if (!super.performOk()) return false; - // todo: push settings into core + pushPreferences(); return true; } + private void pushPreferences() { + IPreferenceStore source = getCVSPreferenceStore(); + Preferences target = CVSProviderPlugin.getPlugin().getPluginPreferences(); + target.setValue( + CVSProviderPlugin.READ_ONLY, + source.getBoolean(ICVSUIConstants.PREF_CHECKOUT_READ_ONLY)); + } + } diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/ResourceDeltaTest.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/ResourceDeltaTest.java index cbf6ac7e1..380ce598b 100644 --- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/ResourceDeltaTest.java +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/ResourceDeltaTest.java @@ -121,7 +121,8 @@ public class ResourceDeltaTest extends EclipseTest { folder = project.getFolder(new Path("sub/moved")); ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor(folder); assertNotManaged(cvsFolder); - assertAdditionMarkerFor(folder, true); + assertAdditionMarkerFor(target, true); + assertAdditionMarkerFor(folder, false); } public void testDeletionHandling() throws TeamException, CoreException { @@ -150,7 +151,6 @@ public class ResourceDeltaTest extends EclipseTest { assertTrue("File " + file.getName() + " should not be marked as deleted", ! info.isDeleted()); assertTrue("File " + file.getName() + " should not be marked as addition", ! info.isAdded()); assertDeletionMarkerFor(project.getFile("deleted.txt"), false); - assertAdditionMarkerFor(project.getFile("added.txt"), false); } public void testFolderAdditionHandling() throws TeamException, CoreException { |