Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 131105 | Differences between
and this patch

Collapse All | Expand All

(-)extensions/org/eclipse/ui/actions/MoveFilesAndFoldersOperation.java (-187 / +216 lines)
Lines 10-15 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.ui.actions;
11
package org.eclipse.ui.actions;
12
12
13
import java.net.URI;
14
13
import org.eclipse.core.resources.IContainer;
15
import org.eclipse.core.resources.IContainer;
14
import org.eclipse.core.resources.IFile;
16
import org.eclipse.core.resources.IFile;
15
import org.eclipse.core.resources.IResource;
17
import org.eclipse.core.resources.IResource;
Lines 19-24 Link Here
19
import org.eclipse.core.runtime.IPath;
21
import org.eclipse.core.runtime.IPath;
20
import org.eclipse.core.runtime.IProgressMonitor;
22
import org.eclipse.core.runtime.IProgressMonitor;
21
import org.eclipse.core.runtime.OperationCanceledException;
23
import org.eclipse.core.runtime.OperationCanceledException;
24
import org.eclipse.core.runtime.Path;
22
import org.eclipse.core.runtime.SubProgressMonitor;
25
import org.eclipse.core.runtime.SubProgressMonitor;
23
import org.eclipse.osgi.util.NLS;
26
import org.eclipse.osgi.util.NLS;
24
import org.eclipse.swt.widgets.Shell;
27
import org.eclipse.swt.widgets.Shell;
Lines 34-226 Link Here
34
 */
37
 */
35
public class MoveFilesAndFoldersOperation extends CopyFilesAndFoldersOperation {
38
public class MoveFilesAndFoldersOperation extends CopyFilesAndFoldersOperation {
36
39
37
    /** 
40
	/**
38
     * Creates a new operation initialized with a shell.
41
	 * Creates a new operation initialized with a shell.
39
     * 
42
	 * 
40
     * @param shell parent shell for error dialogs
43
	 * @param shell
41
     */
44
	 *            parent shell for error dialogs
42
    public MoveFilesAndFoldersOperation(Shell shell) {
45
	 */
43
        super(shell);
46
	public MoveFilesAndFoldersOperation(Shell shell) {
44
    }
47
		super(shell);
45
48
	}
46
    /**
49
47
     * Returns whether this operation is able to perform on-the-fly 
50
	/**
48
     * auto-renaming of resources with name collisions.
51
	 * Returns whether this operation is able to perform on-the-fly
49
     *
52
	 * auto-renaming of resources with name collisions.
50
     * @return <code>true</code> if auto-rename is supported, 
53
	 * 
51
     * 	and <code>false</code> otherwise
54
	 * @return <code>true</code> if auto-rename is supported, and
52
     */
55
	 *         <code>false</code> otherwise
53
    protected boolean canPerformAutoRename() {
56
	 */
54
        return false;
57
	protected boolean canPerformAutoRename() {
55
    }
58
		return false;
56
59
	}
57
    /**
60
58
     * Moves the resources to the given destination.  This method is 
61
	/**
59
     * called recursively to merge folders during folder move.
62
	 * Moves the resources to the given destination. This method is called
60
     * 
63
	 * recursively to merge folders during folder move.
61
     * @param resources the resources to move
64
	 * 
62
     * @param destination destination to which resources will be moved
65
	 * @param resources
63
     * @param subMonitor a progress monitor for showing progress and for cancelation
66
	 *            the resources to move
64
     */
67
	 * @param destination
65
    protected void copy(IResource[] resources, IPath destination,
68
	 *            destination to which resources will be moved
66
            IProgressMonitor subMonitor) throws CoreException {
69
	 * @param subMonitor
67
        for (int i = 0; i < resources.length; i++) {
70
	 *            a progress monitor for showing progress and for cancelation
68
            IResource source = resources[i];
71
	 */
69
            IPath destinationPath = destination.append(source.getName());
72
	protected void copy(IResource[] resources, IPath destination,
70
            IWorkspace workspace = source.getWorkspace();
73
			IProgressMonitor subMonitor) throws CoreException {
71
            IWorkspaceRoot workspaceRoot = workspace.getRoot();
74
		for (int i = 0; i < resources.length; i++) {
72
            IResource existing = workspaceRoot.findMember(destinationPath);
75
			IResource source = resources[i];
73
            if (source.getType() == IResource.FOLDER && existing != null) {
76
			IPath destinationPath = destination.append(source.getName());
74
                // the resource is a folder and it exists in the destination, move the
77
			IWorkspace workspace = source.getWorkspace();
75
                // children of the folder.
78
			IWorkspaceRoot workspaceRoot = workspace.getRoot();
76
                if (homogenousResources(source, existing)) {
79
			IResource existing = workspaceRoot.findMember(destinationPath);
77
                    IResource[] children = ((IContainer) source).members();
80
			if (source.getType() == IResource.FOLDER && existing != null) {
78
                    copy(children, destinationPath, subMonitor);
81
				// the resource is a folder and it exists in the destination,
79
                    delete(source, subMonitor);
82
				// move the
80
                } else {
83
				// children of the folder.
81
                    // delete the destination folder, moving a linked folder
84
				if (homogenousResources(source, existing)) {
82
                    // over an unlinked one or vice versa. Fixes bug 28772. 
85
					IResource[] children = ((IContainer) source).members();
83
                    delete(existing, new SubProgressMonitor(subMonitor, 0));
86
					copy(children, destinationPath, subMonitor);
84
                    source.move(destinationPath, IResource.SHALLOW
87
					delete(source, subMonitor);
85
                            | IResource.KEEP_HISTORY, new SubProgressMonitor(
88
				} else {
86
                            subMonitor, 0));
89
					// delete the destination folder, moving a linked folder
87
                }
90
					// over an unlinked one or vice versa. Fixes bug 28772.
88
            } else {
91
					delete(existing, new SubProgressMonitor(subMonitor, 0));
89
                // if we're merging folders, we could be overwriting an existing file				
92
					source.move(destinationPath, IResource.SHALLOW
90
                if (existing != null) {
93
							| IResource.KEEP_HISTORY, new SubProgressMonitor(
91
                    if (homogenousResources(source, existing)) {
94
							subMonitor, 0));
95
				}
96
			} else {
97
				// if we're merging folders, we could be overwriting an existing
98
				// file
99
				if (existing != null) {
100
					if (homogenousResources(source, existing)) {
92
						moveExisting(source, existing, subMonitor);
101
						moveExisting(source, existing, subMonitor);
93
					} else {
102
					} else {
94
                        // Moving a linked resource over unlinked or vice versa.
103
						// Moving a linked resource over unlinked or vice versa.
95
                        // Can't use setContents here. Fixes bug 28772.
104
						// Can't use setContents here. Fixes bug 28772.
96
                        delete(existing, new SubProgressMonitor(subMonitor, 0));
105
						delete(existing, new SubProgressMonitor(subMonitor, 0));
97
                        source.move(destinationPath, IResource.SHALLOW
106
						source.move(destinationPath, IResource.SHALLOW
98
                                | IResource.KEEP_HISTORY,
107
								| IResource.KEEP_HISTORY,
99
                                new SubProgressMonitor(subMonitor, 0));
108
								new SubProgressMonitor(subMonitor, 0));
100
                    }
109
					}
101
                } else {
110
				} else {
102
                    source.move(destinationPath, IResource.SHALLOW
111
					source.move(destinationPath, IResource.SHALLOW
103
                            | IResource.KEEP_HISTORY, new SubProgressMonitor(
112
							| IResource.KEEP_HISTORY, new SubProgressMonitor(
104
                            subMonitor, 0));
113
							subMonitor, 0));
105
                }
114
				}
106
                subMonitor.worked(1);
115
				subMonitor.worked(1);
107
                if (subMonitor.isCanceled()) {
116
				if (subMonitor.isCanceled()) {
108
                    throw new OperationCanceledException();
117
					throw new OperationCanceledException();
109
                }
118
				}
110
            }
119
			}
111
        }
120
		}
112
    }
121
	}
113
122
114
    /**
123
	/**
115
     * Returns the message for querying deep copy/move of a linked 
124
	 * Returns the message for querying deep copy/move of a linked resource.
116
     * resource.
125
	 * 
117
     *
126
	 * @param source
118
     * @param source resource the query is made for
127
	 *            resource the query is made for
119
     * @return the deep query message
128
	 * @return the deep query message
120
     */
129
	 */
121
    protected String getDeepCheckQuestion(IResource source) {
130
	protected String getDeepCheckQuestion(IResource source) {
122
        return NLS.bind(IDEWorkbenchMessages.CopyFilesAndFoldersOperation_deepMoveQuestion, source.getFullPath().makeRelative());
131
		return NLS
123
    }
132
				.bind(
124
133
						IDEWorkbenchMessages.CopyFilesAndFoldersOperation_deepMoveQuestion,
125
    /**
134
						source.getFullPath().makeRelative());
126
     * Returns the task title for this operation's progress dialog.
135
	}
127
     *
136
128
     * @return the task title
137
	/**
129
     */
138
	 * Returns the task title for this operation's progress dialog.
130
    protected String getOperationTitle() {
139
	 * 
131
        return IDEWorkbenchMessages.MoveFilesAndFoldersOperation_operationTitle;
140
	 * @return the task title
132
    }
141
	 */
133
142
	protected String getOperationTitle() {
134
    /**
143
		return IDEWorkbenchMessages.MoveFilesAndFoldersOperation_operationTitle;
135
     * Returns the message for this operation's problems dialog.
144
	}
136
     *
145
137
     * @return the problems message
146
	/**
138
     */
147
	 * Returns the message for this operation's problems dialog.
139
    protected String getProblemsMessage() {
148
	 * 
140
        return IDEWorkbenchMessages.MoveFilesAndFoldersOperation_problemMessage;
149
	 * @return the problems message
141
    }
150
	 */
142
151
	protected String getProblemsMessage() {
143
    /**
152
		return IDEWorkbenchMessages.MoveFilesAndFoldersOperation_problemMessage;
144
     * Returns the title for this operation's problems dialog.
153
	}
145
     *
154
146
     * @return the problems dialog title
155
	/**
147
     */
156
	 * Returns the title for this operation's problems dialog.
148
    protected String getProblemsTitle() {
157
	 * 
149
        return IDEWorkbenchMessages.MoveFilesAndFoldersOperation_moveFailedTitle;
158
	 * @return the problems dialog title
150
    }
159
	 */
151
160
	protected String getProblemsTitle() {
152
    /**
161
		return IDEWorkbenchMessages.MoveFilesAndFoldersOperation_moveFailedTitle;
153
     * Returns whether the source file in a destination collision
162
	}
154
     * will be validateEdited together with the collision itself.
163
155
     * Returns true.
164
	/**
156
     * 
165
	 * Returns whether the source file in a destination collision will be
157
     * @return boolean <code>true</code>, the source file in a  
166
	 * validateEdited together with the collision itself. Returns true.
158
     * 	destination collision should be validateEdited.  
167
	 * 
159
     */
168
	 * @return boolean <code>true</code>, the source file in a destination
160
    protected boolean getValidateConflictSource() {
169
	 *         collision should be validateEdited.
161
        return true;
170
	 */
162
    }
171
	protected boolean getValidateConflictSource() {
163
172
		return true;
164
    /**
173
	}
165
     * Sets the content of the existing file to the source file content.
174
166
     * Deletes the source file.
175
	/**
167
     * 
176
	 * Sets the content of the existing file to the source file content. Deletes
168
     * @param source source file to move
177
	 * the source file.
169
     * @param existing existing file to set the source content in
178
	 * 
170
     * @param subMonitor a progress monitor for showing progress and for cancelation
179
	 * @param source
171
     * @throws CoreException setContents failed
180
	 *            source file to move
172
     */
181
	 * @param existing
173
    private void moveExisting(IResource source, IResource existing,
182
	 *            existing file to set the source content in
174
            IProgressMonitor subMonitor) throws CoreException {
183
	 * @param subMonitor
175
        IFile existingFile = getFile(existing);
184
	 *            a progress monitor for showing progress and for cancelation
176
185
	 * @throws CoreException
177
        if (existingFile != null) {
186
	 *             setContents failed
178
            IFile sourceFile = getFile(source);
187
	 */
179
188
	private void moveExisting(IResource source, IResource existing,
180
            if (sourceFile != null) {
189
			IProgressMonitor subMonitor) throws CoreException {
181
                existingFile.setContents(sourceFile.getContents(),
190
		IFile existingFile = getFile(existing);
182
                        IResource.KEEP_HISTORY, new SubProgressMonitor(
191
183
                                subMonitor, 0));
192
		if (existingFile != null) {
184
                delete(sourceFile, subMonitor);
193
			IFile sourceFile = getFile(source);
185
            }
194
186
        }
195
			if (sourceFile != null) {
187
    }
196
				existingFile.setContents(sourceFile.getContents(),
188
197
						IResource.KEEP_HISTORY, new SubProgressMonitor(
189
    /* (non-Javadoc)
198
								subMonitor, 0));
190
     * Overrides method in CopyFilesAndFoldersOperation
199
				delete(sourceFile, subMonitor);
191
     *
200
			}
192
     * Note this method is for internal use only. It is not API.
201
		}
193
     *
202
	}
194
     */
203
195
    public String validateDestination(IContainer destination,
204
196
            IResource[] sourceResources) {
205
	/* (non-Javadoc)
197
        IPath destinationLocation = destination.getLocation();
206
	 * @see org.eclipse.ui.actions.CopyFilesAndFoldersOperation#validateDestination(org.eclipse.core.resources.IContainer, org.eclipse.core.resources.IResource[])
198
207
	 * Note this method is for internal use only. It is not API.
199
        for (int i = 0; i < sourceResources.length; i++) {
208
	 */
200
            IResource sourceResource = sourceResources[i];
209
	public String validateDestination(IContainer destination,
201
210
			IResource[] sourceResources) {
202
            // is the source being copied onto itself?
211
		URI destinationLocation = destination.getLocationURI();
203
            if (sourceResource.getParent().equals(destination)) {
212
		IPath destinationPath = null;
204
                return NLS.bind(IDEWorkbenchMessages.MoveFilesAndFoldersOperation_sameSourceAndDest, sourceResource.getName());
213
205
            }
214
		if (destinationLocation != null)
206
            // test if linked source is copied onto itself. Fixes bug 29913.
215
			destinationPath = new Path(destinationLocation.toString());
207
            if (destinationLocation != null) {
216
208
                IPath sourceLocation = sourceResource.getLocation();
217
		for (int i = 0; i < sourceResources.length; i++) {
209
                IPath destinationResource = destinationLocation
218
			IResource sourceResource = sourceResources[i];
210
                        .append(sourceResource.getName());
219
211
                if (sourceLocation != null
220
			// is the source being copied onto itself?
212
                        && sourceLocation.isPrefixOf(destinationResource)) {
221
			if (sourceResource.getParent().equals(destination)) {
213
                    return NLS.bind(IDEWorkbenchMessages.MoveFilesAndFoldersOperation_sameSourceAndDest, sourceResource.getName());
222
				return NLS
214
                }
223
						.bind(
215
            }
224
								IDEWorkbenchMessages.MoveFilesAndFoldersOperation_sameSourceAndDest,
216
        }
225
								sourceResource.getName());
217
        return super.validateDestination(destination, sourceResources);
226
			}
218
    }
227
			// test if linked source is copied onto itself. Fixes bug 29913.
219
    
228
			if (destinationPath != null) {
220
    /* (non-Javadoc)
229
				URI sourceLocation = sourceResource.getLocationURI();
221
     * @see org.eclipse.ui.actions.CopyFilesAndFoldersOperation#isMove()
230
				if (sourceLocation != null) {
222
     */
231
					IPath sourcePath = new Path(sourceLocation.toString());
223
    protected boolean isMove() {
232
224
    	return true;
233
					IPath destinationResource = destinationPath
225
    }
234
							.append(sourceResource.getName());
235
236
					if (sourcePath.isPrefixOf(destinationResource))
237
						return NLS
238
								.bind(
239
										IDEWorkbenchMessages.MoveFilesAndFoldersOperation_sameSourceAndDest,
240
										sourceResource.getName());
241
				}
242
			}
243
		}
244
		return super.validateDestination(destination, sourceResources);
245
	}
246
247
	/*
248
	 * (non-Javadoc)
249
	 * 
250
	 * @see org.eclipse.ui.actions.CopyFilesAndFoldersOperation#isMove()
251
	 */
252
	protected boolean isMove() {
253
		return true;
254
	}
226
}
255
}

Return to bug 131105