blob: a1f5a423170f09adb03791d0e6cbd7c8b92ef693 [file] [log] [blame]
/*******************************************************************************
* 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 API and implementation
******************************************************************************/
package org.eclipse.team.internal.ccvs.ui;
import org.eclipse.core.resources.IFile;
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.team.IMoveDeleteHook;
import org.eclipse.core.resources.team.IResourceTree;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.internal.ccvs.core.CVSException;
import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.internal.ccvs.core.ICVSFile;
import org.eclipse.team.internal.ccvs.core.ICVSFolder;
import org.eclipse.team.internal.ccvs.core.ICVSResource;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
import org.eclipse.ui.IWorkbenchWindow;
public class CVSMoveDeleteHook implements IMoveDeleteHook {
public interface IRunnableWithShell {
public void run(Shell shell);
}
private void showDialog(final IRunnableWithShell runnable) {
Display.getDefault().syncExec(new Runnable() {
public void run() {
IWorkbenchWindow window = CVSUIPlugin.getPlugin().getWorkbench().getActiveWorkbenchWindow();
if (window != null) {
runnable.run(window.getShell());
} else {
Display display = Display.getCurrent();
Shell shell = new Shell(display);
runnable.run(shell);
}
}
});
}
/*
* Delete the file and return true if an outgoing deletion will result
* and the parent folder needs to remain
*/
private boolean makeFileOutgoingDeletion(IResourceTree tree, IFile source, IFile destination, int updateFlags, IProgressMonitor monitor) throws CoreException {
// Delete or move the file
if (destination == null) {
tree.standardDeleteFile(source, updateFlags, monitor);
} else {
tree.standardMoveFile(source, destination, updateFlags, monitor);
}
// Indicate whether the parent folder must remain for outgoing deletions
ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(source);
boolean mustRemain;
try {
mustRemain = (cvsFile.isManaged() && ! cvsFile.getSyncInfo().isAdded());
} catch (CVSException e) {
tree.failed(e.getStatus());
mustRemain = true;
}
return mustRemain;
}
/*
* Delete the files contained in the folder structure rooted at source.
* Return true if at least one file has been marked as an outgoing deletion and the parent folder must remain
*/
private boolean makeFolderOutgoingDeletion(IResourceTree tree, IFolder source, IFolder destination, int updateFlags, IProgressMonitor monitor) throws CoreException {
boolean fileFound = false;
// Create the destination for a move
if (destination != null && ! destination.exists()) {
destination.create(false, true, monitor);
}
// Move or delete the children
IResource[] members = source.members();
for (int i = 0; i < members.length; i++) {
IResource child = members[i];
if (child.getType() == IResource.FOLDER) {
// Determine the corresponding destination folder
IFolder destFolder = null;
if (destination != null) {
destFolder = destination.getFolder(child.getFullPath().removeFirstSegments(source.getFullPath().segmentCount()));
}
// Try to delete/move the child
if (makeFolderOutgoingDeletion(tree, (IFolder)child, destFolder, updateFlags, monitor)) {
fileFound = true;
// XXX Below line commented out for now
// tree.failed(new CVSStatus(IStatus.WARNING, CVSStatus.FOLDER_NEEDED_FOR_FILE_DELETIONS, Policy.bind("CVSMoveDeleteHook.folderDeletionFailure", resource.getFullPath().toString()))); //$NON-NLS-1$
}
} else if (child.getType() == IResource.FILE) {
IFile destFile = null;
if (destination != null) {
destFile = destination.getFile(child.getFullPath().removeFirstSegments(source.getFullPath().segmentCount()));
}
fileFound = makeFileOutgoingDeletion(tree, (IFile)child, destFile, updateFlags, monitor);
}
}
// If there were no files, delete the folder
if ( ! fileFound) {
try {
ICVSFolder folder = CVSWorkspaceRoot.getCVSFolderFor(source);
// We we need to check if the folder already has outgoing deletions
ICVSResource[] files = folder.members(ICVSFolder.FILE_MEMBERS);
for (int i = 0; i < files.length; i++) {
ICVSFile cvsFile = (ICVSFile)files[i];
if (cvsFile.isManaged() && ! cvsFile.getSyncInfo().isAdded()) {
fileFound = true;
break;
}
}
// If there is still no file, we can delete the folder
if ( ! fileFound) {
tree.standardDeleteFolder(source, updateFlags, monitor);
folder.unmanage(null);
}
} catch (CVSException e) {
tree.failed(e.getStatus());
}
}
return fileFound;
}
private boolean checkForTeamPrivate(final IResource resource) {
if (resource.isTeamPrivateMember()) {
showDialog(new IRunnableWithShell() {
public void run(Shell shell) {
ErrorDialog.openError(shell, Policy.bind("CVSMoveDeleteHook.Team_Private_Resource_1"), Policy.bind("CVSMoveDeleteHook.Deletion_of_team_private_resources_is_not_permitted_2", resource.getFullPath().toString()), null); //$NON-NLS-1$ //$NON-NLS-2$
}
});
return true;
}
return false;
}
private boolean deleteFile(
final IResourceTree tree,
final IFile source,
final IFile destination,
final int updateFlags,
final String title,
final String message,
final IProgressMonitor monitor) {
if (checkForTeamPrivate(source)) {
return true;
}
final ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(source);
ResourceSyncInfo info = null;
try {
info = cvsFile.getSyncInfo();
} catch (CVSException e) {
}
if (info != null && ! info.isAdded()) {
// prompt the user for choices: Mark as outgoing deletion or cancel
final boolean[] performDelete = new boolean[] { ! CVSProviderPlugin.getPlugin().getPromptOnFileDelete()};
if ( ! performDelete[0]){
showDialog(new IRunnableWithShell() {
public void run(Shell shell) {
AvoidableMessageDialog dialog = new AvoidableMessageDialog(
shell,
title,
null, // accept the default window icon
message,
MessageDialog.QUESTION,
new String[] {IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL},
0); // yes is the default
performDelete[0] = dialog.open() == 0;
if (performDelete[0]) {
// The CVS core delta listener will mark the file as an outgoing deletion
// so we just need to say that we didn't handle it. Core will delete the
// file and the delta listener will do it's thing.
CVSProviderPlugin.getPlugin().setPromptOnFileDelete( ! dialog.isDontShowAgain());
CVSUIPlugin.getPlugin().getPreferenceStore().setValue(ICVSUIConstants.PREF_PROMPT_ON_FILE_DELETE, CVSProviderPlugin.getPlugin().getPromptOnFileDelete());
}
}
});
}
if (performDelete[0]) {
// Issue a delete for all child files
// The CVS core delta listener will mark each file as an outgoing deletion
// so we just need to delete each file and let the delta listener do its thing
try {
makeFileOutgoingDeletion(tree, source, destination, updateFlags, monitor);
} catch (final CoreException e) {
showDialog(new IRunnableWithShell() {
public void run(Shell shell) {
ErrorDialog.openError(shell, null, null, e.getStatus());
}
});
}
}
return true;
}
return false;
}
private boolean deleteFolder(
final IResourceTree tree,
final IFolder source,
final IFolder destination,
final int updateFlags,
final String title,
final String message,
final IProgressMonitor monitor) {
if (checkForTeamPrivate(source)) {
return true;
}
final ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor(source);
if (cvsFolder.isManaged()) {
// prompt the user for choices: Mark as outgoing deletion or cancel
final boolean[] performDelete = new boolean[] { ! CVSProviderPlugin.getPlugin().getPromptOnFolderDelete()};
boolean dialogShown = false;
if ( ! performDelete[0]) {
dialogShown = true;
showDialog(new IRunnableWithShell() {
public void run(Shell shell) {
AvoidableMessageDialog dialog = new AvoidableMessageDialog(
shell,
title,
null, // accept the default window icon
message,
MessageDialog.QUESTION,
new String[] {IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL},
0); // yes is the default
performDelete[0] = dialog.open() == 0;
if (performDelete[0]) {
CVSProviderPlugin.getPlugin().setPromptOnFolderDelete( ! dialog.isDontShowAgain());
CVSUIPlugin.getPlugin().getPreferenceStore().setValue(ICVSUIConstants.PREF_PROMPT_ON_FOLDER_DELETE, CVSProviderPlugin.getPlugin().getPromptOnFolderDelete());
}
}
});
}
if (performDelete[0]) {
// Issue a delete for all child files
// The CVS core delta listener will mark each file as an outgoing deletion
// so we just need to delete each file and let the delta listener do its thing
try {
makeFolderOutgoingDeletion(tree, source, destination, updateFlags, monitor);
} catch (final CoreException e) {
showDialog(new IRunnableWithShell() {
public void run(Shell shell) {
ErrorDialog.openError(shell, null, null, e.getStatus());
}
});
}
}
return true;
}
return false;
}
/**
* @see IMoveDeleteHook#deleteFile(IResourceTree, IFile, int, IProgressMonitor)
*/
public boolean deleteFile(
final IResourceTree tree,
final IFile file,
int updateFlags,
final IProgressMonitor monitor) {
return deleteFile(tree, file, null, updateFlags,
Policy.bind("CVSMoveDeleteHook.deleteFileTitle"), //$NON-NLS-1$
Policy.bind("CVSMoveDeleteHook.deleteFileMessage", file.getFullPath().toString()), //$NON-NLS-1$
monitor);
}
/**
* @see IMoveDeleteHook#deleteFolder(IResourceTree, IFolder, int, IProgressMonitor)
*/
public boolean deleteFolder(
final IResourceTree tree,
final IFolder folder,
final int updateFlags,
final IProgressMonitor monitor) {
return deleteFolder(tree, folder, null, updateFlags,
Policy.bind("CVSMoveDeleteHook.deleteFolderTitle"), //$NON-NLS-1$
Policy.bind("CVSMoveDeleteHook.deleteFolderMessage", folder.getFullPath().toString()), //$NON-NLS-1$
monitor);
}
/**
* @see IMoveDeleteHook#deleteProject(IResourceTree, IProject, int, IProgressMonitor)
*/
public boolean deleteProject(
IResourceTree tree,
IProject project,
int updateFlags,
IProgressMonitor monitor) {
// No special action needed
return false;
}
/**
* @see IMoveDeleteHook#moveFile(IResourceTree, IFile, IFile, int, IProgressMonitor)
*/
public boolean moveFile(
IResourceTree tree,
IFile source,
IFile destination,
int updateFlags,
IProgressMonitor monitor) {
return deleteFile(tree, source, destination, updateFlags,
Policy.bind("CVSMoveDeleteHook.moveFileTitle"), //$NON-NLS-1$
Policy.bind("CVSMoveDeleteHook.moveFileMessage", source.getFullPath().toString()), //$NON-NLS-1$
monitor);
}
/**
* @see IMoveDeleteHook#moveFolder(IResourceTree, IFolder, IFolder, int, IProgressMonitor)
*/
public boolean moveFolder(
IResourceTree tree,
IFolder source,
IFolder destination,
int updateFlags,
IProgressMonitor monitor) {
return deleteFolder(tree, source, destination, updateFlags,
Policy.bind("CVSMoveDeleteHook.moveFolderTitle"), //$NON-NLS-1$
Policy.bind("CVSMoveDeleteHook.moveFolderMessage", source.getFullPath().toString()), //$NON-NLS-1$
monitor);
}
/**
* @see IMoveDeleteHook#moveProject(IResourceTree, IProject, IProjectDescription, int, IProgressMonitor)
*/
public boolean moveProject(
IResourceTree tree,
IProject source,
IProjectDescription description,
int updateFlags,
IProgressMonitor monitor) {
// No special action
return false;
}
}