Bug 87202 (PatchAttached)[Watch/Edit] automatic 'editors' check doesn't check for updated versions.
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCoreFileModificationValidator.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCoreFileModificationValidator.java
index 082b152..d013860 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCoreFileModificationValidator.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCoreFileModificationValidator.java
@@ -10,12 +10,11 @@
  *******************************************************************************/
 package org.eclipse.team.internal.ccvs.core;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
-import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.*;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.team.core.RepositoryProvider;
 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
@@ -66,18 +65,24 @@
      * @return
      */
     protected IStatus edit(IFile[] readOnlyFiles, Object context) {
-        synchronized(this) {
-	        if (uiValidator == null) {
-	            uiValidator = getPluggedInValidator();
-	        }
-        }
-        if (uiValidator != null) {
-            return uiValidator.validateEdit(readOnlyFiles, context);
+        IFileModificationValidator override = getUIValidator();
+        if (override != null) {
+            return override.validateEdit(readOnlyFiles, context);
         } else {
 	        performEdit(readOnlyFiles);
 	        return Status.OK_STATUS;
         }
     }
+
+    private IFileModificationValidator getUIValidator() {
+        synchronized(this) {
+	        if (uiValidator == null) {
+	            uiValidator = getPluggedInValidator();
+	        }
+        }
+        return uiValidator;
+    }
+    
 	/**
 	 * @see org.eclipse.team.internal.ccvs.core.ICVSFileModificationValidator#validateMoveDelete(org.eclipse.core.resources.IFile[], org.eclipse.core.runtime.IProgressMonitor)
 	 */
@@ -191,4 +196,41 @@
 			return null;
 		}
 	}
+    
+    public ISchedulingRule validateEditRule(CVSResourceRuleFactory factory, IResource[] resources) {
+        IFileModificationValidator override = getUIValidator();
+        if (override instanceof CVSCoreFileModificationValidator) {
+            CVSCoreFileModificationValidator ui = (CVSCoreFileModificationValidator) override;
+            return ui.validateEditRule(factory, resources);
+        }
+        if (resources.length == 0)
+            return null;
+        //optimize rule for single file
+        if (resources.length == 1)
+            return isReadOnly(resources[0]) ? factory.getParent(resources[0]) : null;
+        //need a lock on the parents of all read-only files
+        HashSet rules = new HashSet();
+        for (int i = 0; i < resources.length; i++)
+            if (isReadOnly(resources[i]))
+                rules.add(factory.getParent(resources[i]));
+        return createSchedulingRule(rules);
+    }
+
+    protected ISchedulingRule createSchedulingRule(Set rules) {
+        if (rules.isEmpty())
+            return null;
+        if (rules.size() == 1)
+            return (ISchedulingRule) rules.iterator().next();
+        ISchedulingRule[] ruleArray = (ISchedulingRule[]) rules
+                .toArray(new ISchedulingRule[rules.size()]);
+        return new MultiRule(ruleArray);
+    }
+    
+    protected final boolean isReadOnly(IResource resource) {
+        ResourceAttributes a = resource.getResourceAttributes();
+        if (a != null) {
+            return a.isReadOnly();
+        }
+        return false;
+    }
 }
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSResourceRuleFactory.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSResourceRuleFactory.java
new file mode 100644
index 0000000..d1d31f8
--- /dev/null
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSResourceRuleFactory.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.internal.ccvs.core;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.team.ResourceRuleFactory;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+
+public class CVSResourceRuleFactory extends ResourceRuleFactory {
+    public ISchedulingRule validateEditRule(IResource[] resources) {
+    	return CVSTeamProvider.internalGetFileModificationValidator().validateEditRule(this, resources);
+    }
+    
+    public ISchedulingRule getParent(IResource resource) {
+        return parent(resource);
+    }
+    
+}
\ No newline at end of file
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 d19ec79..7079c53 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
@@ -19,7 +19,6 @@
 import org.eclipse.core.runtime.*;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.ISchedulingRule;
-import org.eclipse.core.runtime.jobs.MultiRule;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.team.core.RepositoryProvider;
 import org.eclipse.team.core.TeamException;
@@ -30,8 +29,6 @@
 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.*;
-import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
-import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
 import org.eclipse.team.internal.ccvs.core.util.*;
 import org.eclipse.team.internal.core.streams.CRLFtoLFInputStream;
 import org.eclipse.team.internal.core.streams.LFtoCRLFInputStream;
@@ -67,27 +64,7 @@
  */
 public class CVSTeamProvider extends RepositoryProvider {
 
-	private static final ResourceRuleFactory RESOURCE_RULE_FACTORY = new ResourceRuleFactory() {
-		public ISchedulingRule validateEditRule(IResource[] resources) {
-			if (resources.length == 0)
-				return null;
-			//optimize rule for single file
-			if (resources.length == 1)
-				return resources[0].isReadOnly() ? parent(resources[0]) : null;
-			//need a lock on the parents of all read-only files
-			HashSet rules = new HashSet();
-			for (int i = 0; i < resources.length; i++)
-				if (resources[i].isReadOnly())
-					rules.add(parent(resources[i]));
-			if (rules.isEmpty())
-				return null;
-			if (rules.size() == 1)
-				return (ISchedulingRule) rules.iterator().next();
-			ISchedulingRule[] ruleArray = (ISchedulingRule[]) rules
-					.toArray(new ISchedulingRule[rules.size()]);
-			return new MultiRule(ruleArray);
-		}
-	};
+	private static final ResourceRuleFactory RESOURCE_RULE_FACTORY = new CVSResourceRuleFactory();
 	
 	private static final boolean IS_CRLF_PLATFORM = Arrays.equals(
 		System.getProperty("line.separator").getBytes(), new byte[] { '\r', '\n' }); //$NON-NLS-1$
@@ -102,7 +79,7 @@
 	private IProject project;
 	
 	private static MoveDeleteHook moveDeleteHook= new MoveDeleteHook();
-	private static IFileModificationValidator fileModificationValidator;
+	private static CVSCoreFileModificationValidator fileModificationValidator;
 	
 	// property used to indicate whether new directories should be discovered for the project
 	private final static QualifiedName FETCH_ABSENT_DIRECTORIES_PROP_KEY = 
@@ -110,7 +87,18 @@
 	// property used to indicate whether the project is configured to use Watch/edit
 	private final static QualifiedName WATCH_EDIT_PROP_KEY = 
 		new QualifiedName("org.eclipse.team.cvs.core", "watch_edit");  //$NON-NLS-1$  //$NON-NLS-2$
-				
+			
+    /**
+     * Return the file modification validator used for all CVS repository providers.
+     * @return the file modification validator used for all CVS repository providers
+     */
+    protected static CVSCoreFileModificationValidator internalGetFileModificationValidator() {
+        if (CVSTeamProvider.fileModificationValidator == null) {
+            CVSTeamProvider.fileModificationValidator = new CVSCoreFileModificationValidator();
+        }
+        return CVSTeamProvider.fileModificationValidator;
+    }
+    
 	/**
 	 * No-arg Constructor for IProjectNature conformance
 	 */
@@ -649,10 +637,7 @@
 	 * @see org.eclipse.team.core.RepositoryProvider#getFileModificationValidator()
 	 */
 	public IFileModificationValidator getFileModificationValidator() {
-		if (CVSTeamProvider.fileModificationValidator == null) {
-			CVSTeamProvider.fileModificationValidator = new CVSCoreFileModificationValidator();
-		}
-		return CVSTeamProvider.fileModificationValidator;
+		return internalGetFileModificationValidator();
 	}
 	
 	/**
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIMessages.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIMessages.java
index 4abc91e..f6cd198 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIMessages.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIMessages.java
@@ -701,6 +701,10 @@
 	public static String WatchEditPreferencePage_neverPrompt;
 	public static String WatchEditPreferencePage_alwaysPrompt;
 	public static String WatchEditPreferencePage_onlyPrompt;
+	public static String WatchEditPreferencePage_updatePrompt;
+	public static String WatchEditPreferencePage_autoUpdate;
+	public static String WatchEditPreferencePage_promptUpdate;
+	public static String WatchEditPreferencePage_neverUpdate;
 
 	public static String Uneditaction_confirmMessage;
 	public static String Uneditaction_confirmTitle;
@@ -872,6 +876,8 @@
 
 	public static String FileModificationValidator_3;
 	public static String FileModificationValidator_4;
+    public static String FileModificationValidator_5;
+    public static String FileModificationValidator_6;
 	public static String CVSSynchronizeWizard_0;
 	public static String Participant_comparing;
 	public static String Participant_merging;
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 b01ad6e..ba4876a 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
@@ -563,6 +563,7 @@
 		store.setDefault(ICVSUIConstants.PREF_CHECKOUT_READ_ONLY, corePrefs.getDefaultBoolean(CVSProviderPlugin.READ_ONLY));
 		store.setDefault(ICVSUIConstants.PREF_EDIT_ACTION, ICVSUIConstants.PREF_EDIT_IN_BACKGROUND);
 		store.setDefault(ICVSUIConstants.PREF_EDIT_PROMPT, ICVSUIConstants.PREF_EDIT_PROMPT_IF_EDITORS);
+        store.setDefault(ICVSUIConstants.PREF_UPDATE_PROMPT, ICVSUIConstants.PREF_UPDATE_PROMPT_NEVER);
 		// Ensure that the preference values in UI match Core
 		store.setValue(ICVSUIConstants.PREF_CHECKOUT_READ_ONLY, corePrefs.getBoolean(CVSProviderPlugin.READ_ONLY));
 		
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
index 49b0380..482f1d8 100644
--- 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
@@ -12,18 +12,24 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.net.URL;
+import java.util.HashSet;
+import java.util.Set;
 
 import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.operation.IRunnableWithProgress;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.team.core.TeamException;
-import org.eclipse.team.internal.ccvs.core.CVSCoreFileModificationValidator;
-import org.eclipse.team.internal.ccvs.core.CVSException;
+import org.eclipse.team.core.synchronize.SyncInfo;
+import org.eclipse.team.internal.ccvs.core.*;
+import org.eclipse.team.internal.ccvs.core.client.Command;
 import org.eclipse.team.internal.ccvs.ui.actions.EditorsAction;
+import org.eclipse.team.internal.ccvs.ui.operations.UpdateOperation;
 import org.eclipse.ui.progress.IProgressConstants;
 
 /**
@@ -66,6 +72,28 @@
 					throw new InterruptedException();
 				}
 				
+                // see if the file is up to date
+                if (shell != null && promptToUpdateFiles(files, shell)) {
+                    // The user wants to update the file
+                    // Run the update in a runnable in order to get a busy cursor.
+                    // This runnable is syncExeced in order to get a busy cursor
+                    IRunnableWithProgress updateRunnable = new IRunnableWithProgress() {
+                        public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+                            performUpdate(files, monitor);
+                        }
+                    };
+                    if (isRunningInUIThread()) {
+                        // Only show a busy cursor if validate edit is blocking the UI
+                        CVSUIPlugin.runWithProgress(shell, false, updateRunnable);
+                    } else {
+                        // We can't show a busy cursor (i.e., run in the UI thread)
+                        // since this thread may hold locks and
+                        // running an edit in the UI thread could try to obtain the
+                        // same locks, resulting in a deadlock.
+                        updateRunnable.run(new NullProgressMonitor());
+                    }
+                }
+                
 				// Run the edit in a runnable in order to get a busy cursor.
 				// This runnable is syncExeced in order to get a busy cursor
 				IRunnableWithProgress editRunnable = new IRunnableWithProgress() {
@@ -139,6 +167,23 @@
 		}
 	}
 	
+    private boolean promptToUpdateFiles(IFile[] files, Shell shell) throws InvocationTargetException, InterruptedException {
+        if (files.length == 0)
+            return false;
+        
+        if (isNeverUpdate())
+            return false;
+        
+        // Contact the server to see if the files are up-to-date
+        if (needsUpdate(files, new NullProgressMonitor())) {
+            if (isPromptUpdate())
+                return (promptUpdate(shell));
+            return true; // auto update
+        }
+        
+        return false;
+    }
+
 	private boolean promptEdit(Shell shell) {
 		// Open the dialog using a sync exec (there are no guarentees that we
 		// were called from the UI thread
@@ -152,6 +197,19 @@
 		return result[0];
 	}
 
+    private boolean promptUpdate(Shell shell) {
+        // Open the dialog using a sync exec (there are no guarentees that we
+        // were called from the UI thread
+        final boolean[] result = new boolean[] { false };
+        int flags = isRunningInUIThread() ? 0 : CVSUIPlugin.PERFORM_SYNC_EXEC;
+        CVSUIPlugin.openDialog(shell, new CVSUIPlugin.IOpenableInShell() {
+            public void open(Shell shell) {
+                result[0] = MessageDialog.openQuestion(shell,CVSUIMessages.FileModificationValidator_5,CVSUIMessages.FileModificationValidator_6);
+            }
+        }, flags);
+        return result[0];
+    }
+
 	private boolean isPerformEdit() {
 		return ICVSUIConstants.PREF_EDIT_PROMPT_EDIT.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_EDIT_ACTION));
 	}
@@ -187,4 +245,50 @@
 	private boolean isAlwaysPrompt() {
 		return ICVSUIConstants.PREF_EDIT_PROMPT_ALWAYS.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_EDIT_PROMPT));
 	}
+    
+    private boolean needsUpdate(IFile[] files, IProgressMonitor monitor) {
+        try {
+            CVSWorkspaceSubscriber subscriber = CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber();
+            subscriber.refresh(files, IResource.DEPTH_ZERO, monitor);
+            for (int i = 0; i < files.length; i++) {
+                IFile file = files[i];
+                SyncInfo info = subscriber.getSyncInfo(file);
+                int direction = info.getKind() & SyncInfo.DIRECTION_MASK;
+                if (direction == SyncInfo.CONFLICTING || direction == SyncInfo.INCOMING) {
+                    return true;
+                }
+            }
+        } catch (TeamException e) {
+            // Log the exception and assume we don't need to update it
+            CVSProviderPlugin.log(e);
+        }
+        return false;
+    }
+    
+    private void performUpdate(IFile[] files, IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+        // TODO: This obtains the project rule which can cause a rule violation
+        new UpdateOperation(null /* no target part */, files, Command.NO_LOCAL_OPTIONS, null /* no tag */).run(monitor);
+    }
+    
+    private boolean isPromptUpdate() {
+        return ICVSUIConstants.PREF_UPDATE_PROMPT_IF_OUTDATED.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_UPDATE_PROMPT));
+    }
+    
+    private boolean isNeverUpdate() {
+        return ICVSUIConstants.PREF_UPDATE_PROMPT_NEVER.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_UPDATE_PROMPT));
+    }
+    
+    public ISchedulingRule validateEditRule(CVSResourceRuleFactory factory, IResource[] resources) {
+        if (!isNeverUpdate()) {
+            // We may need to perform an update so we need to obtain the lock on each project
+            Set projects = new HashSet();
+            for (int i = 0; i < resources.length; i++) {
+                IResource resource = resources[i];
+                if (isReadOnly(resource))
+                    projects.add(resource.getProject());
+            }
+            return createSchedulingRule(projects);
+        }
+        return super.validateEditRule(factory, resources);
+    }
 }
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/ICVSUIConstants.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/ICVSUIConstants.java
index 8d467ef..0da5f93 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/ICVSUIConstants.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/ICVSUIConstants.java
@@ -132,6 +132,12 @@
 	public final String PREF_EDIT_PROMPT_NEVER = "never"; //$NON-NLS-1$
 	public final String PREF_EDIT_PROMPT_ALWAYS = "always";	 //$NON-NLS-1$
 	public final String PREF_EDIT_PROMPT_IF_EDITORS = "only";	 //$NON-NLS-1$
+    
+    // update preferences
+    public final String PREF_UPDATE_PROMPT = "pref_upate_prompt";
+    public final String PREF_UPDATE_PROMPT_NEVER = "never";    //$NON-NLS-1$
+    public final String PREF_UPDATE_PROMPT_AUTO = "auto"; //$NON-NLS-1$
+    public final String PREF_UPDATE_PROMPT_IF_OUTDATED = "only";  //$NON-NLS-1$
 	
 	// Repositories view preferences
 	public final String PREF_GROUP_VERSIONS_BY_PROJECT = "pref_group_versions_by_project"; //$NON-NLS-1$
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 78ceba2..89ff200 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
@@ -21,6 +21,7 @@
 public class WatchEditPreferencePage extends CVSFieldEditorPreferencePage {
 	
 	private RadioGroupFieldEditor promptEditor;
+    private RadioGroupFieldEditor updateEditor;
 	private RadioGroupFieldEditor actionEditor;
 	private IPreferenceStore store;
 
@@ -58,7 +59,6 @@
 							}, 	//$NON-NLS-1$ //$NON-NLS-2$
 			getFieldEditorParent(), true);
 		addField(actionEditor);
-
 		
 		promptEditor = new RadioGroupFieldEditor(
 			ICVSUIConstants.PREF_EDIT_PROMPT,
@@ -69,8 +69,20 @@
 							{CVSUIMessages.WatchEditPreferencePage_neverPrompt, ICVSUIConstants.PREF_EDIT_PROMPT_NEVER}, //$NON-NLS-1$
 							},	//$NON-NLS-1$ //$NON-NLS-2$
 			getFieldEditorParent(), true);
+        
+        updateEditor = new RadioGroupFieldEditor(
+                ICVSUIConstants.PREF_UPDATE_PROMPT,
+                CVSUIMessages.WatchEditPreferencePage_updatePrompt, //$NON-NLS-1$
+                1,
+                new String[][] {{CVSUIMessages.WatchEditPreferencePage_autoUpdate, ICVSUIConstants.PREF_UPDATE_PROMPT_AUTO}, //$NON-NLS-1$
+                                {CVSUIMessages.WatchEditPreferencePage_promptUpdate, ICVSUIConstants.PREF_UPDATE_PROMPT_IF_OUTDATED}, //$NON-NLS-1$
+                                {CVSUIMessages.WatchEditPreferencePage_neverUpdate, ICVSUIConstants.PREF_UPDATE_PROMPT_NEVER}, //$NON-NLS-1$
+                                },  //$NON-NLS-1$ //$NON-NLS-2$
+                getFieldEditorParent(), true);
+        
 		store = getCVSPreferenceStore();
 		addField(promptEditor);
+        addField(updateEditor);
 	}
 
 	private boolean isEditEnabled() {
@@ -93,10 +105,10 @@
 	 */
 	public void propertyChange(PropertyChangeEvent event) {
 		if (event.getSource() == actionEditor) {
-			promptEditor.setEnabled(
-				event.getNewValue().equals(ICVSUIConstants.PREF_EDIT_PROMPT_EDIT), 
-				getFieldEditorParent());
-		}
+            boolean enabled = event.getNewValue().equals(ICVSUIConstants.PREF_EDIT_PROMPT_EDIT);
+			promptEditor.setEnabled(enabled, getFieldEditorParent());
+            updateEditor.setEnabled(enabled, getFieldEditorParent());
+        }
 		super.propertyChange(event);
 	}
 
@@ -107,5 +119,6 @@
 	protected void initialize() {
 		super.initialize();
 		promptEditor.setEnabled(isEditEnabled(), getFieldEditorParent());
+        updateEditor.setEnabled(isEditEnabled(), getFieldEditorParent());
 	}
 }
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/messages.properties b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/messages.properties
index 742c9c3..af224d8 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/messages.properties
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/messages.properties
@@ -731,6 +731,10 @@
 WatchEditPreferencePage_neverPrompt=&Never prompt
 WatchEditPreferencePage_alwaysPrompt=Always &prompt
 WatchEditPreferencePage_onlyPrompt=&Only prompt if there are other editors
+WatchEditPreferencePage_updatePrompt=Update edited files
+WatchEditPreferencePage_autoUpdate=Always &update before editing
+WatchEditPreferencePage_promptUpdate=Prompt to update if out of &date
+WatchEditPreferencePage_neverUpdate=Ne&ver update
 
 Uneditaction_confirmMessage=Overwrite local changes to edited files?
 Uneditaction_confirmTitle=Confirm Unedit
@@ -931,6 +935,8 @@
 
 FileModificationValidator_3=Perform Edit?
 FileModificationValidator_4=A CVS edit notification is required to be sent to the server in order to allow editing of one or more selected files. Continue?
+FileModificationValidator_5=Perform Update?
+FileModificationValidator_6=Some of the files being edited have been modified on the server. Would you like to update before continuing?
 CVSSynchronizeWizard_0=Unknown
 Participant_comparing=Comparing
 Participant_merging=Merging