blob: 91ea803a66d8e62f9d30e01ca71a893f6123f54b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2009 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.team.internal.ccvs.ui.wizards;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.*;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
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.*;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
import org.eclipse.team.internal.ccvs.core.util.KnownRepositories;
import org.eclipse.team.internal.ccvs.ui.*;
import org.eclipse.team.internal.ccvs.ui.Policy;
import org.eclipse.team.internal.ccvs.ui.operations.*;
import org.eclipse.team.internal.ccvs.ui.tags.*;
import org.eclipse.team.internal.ui.Utils;
import org.eclipse.team.ui.IConfigurationWizard;
import org.eclipse.team.ui.synchronize.ModelSynchronizeParticipant;
import org.eclipse.ui.IWorkbench;
/**
* This wizard helps the user to import a new project in their workspace
* into a CVS repository for the first time.
*/
public class SharingWizard extends Wizard implements IConfigurationWizard, ICVSWizard {
// The project to configure
private IProject project;
// The autoconnect page is used if CVS/ directories already exist.
private ConfigurationWizardAutoconnectPage autoconnectPage;
// The import page is used if CVS/ directories do not exist.
private RepositorySelectionPage locationPage;
// The page that prompts the user for connection information.
private ConfigurationWizardMainPage createLocationPage;
// The page that prompts the user for module name.
private ModuleSelectionPage modulePage;
// The page that lets the user pick a branch to share against
private TagSelectionWizardPage tagPage;
// The page that allows the user to commit or update resources
private SharingWizardSyncPage syncPage;
// Keep track of location state so we know what to do at the end
private ICVSRepositoryLocation location;
private boolean isNewLocation;
// Keep track of the folder that existed the last time we checked
private ICVSRemoteFolder existingRemote;
private ICVSRemoteFolder remoteFolder;
public SharingWizard() {
IDialogSettings cvsSettings = CVSUIPlugin.getPlugin().getDialogSettings();
IDialogSettings section = cvsSettings.getSection("SharingWizard");//$NON-NLS-1$
if (section == null) {
section = cvsSettings.addNewSection("SharingWizard");//$NON-NLS-1$
}
setDialogSettings(section);
setNeedsProgressMonitor(true);
setWindowTitle(CVSUIMessages.SharingWizard_title);
}
@Override
public void addPages() {
ImageDescriptor sharingImage = CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_WIZBAN_SHARE);
boolean autoconnect = false;
if (doesCVSDirectoryExist()) {
autoconnectPage = new ConfigurationWizardAutoconnectPage("autoconnectPage", CVSUIMessages.SharingWizard_autoConnectTitle, sharingImage); //$NON-NLS-1$
if (autoconnectPage.setProject(project)) {
autoconnectPage.setDescription(CVSUIMessages.SharingWizard_autoConnectTitleDescription);
addPage(autoconnectPage);
autoconnect = true;
}
}
if (!autoconnect) {
ICVSRepositoryLocation[] locations = CVSUIPlugin.getPlugin().getRepositoryManager().getKnownRepositoryLocations();
if (locations.length > 0) {
locationPage = new RepositorySelectionPage("importPage", CVSUIMessages.SharingWizard_importTitle, sharingImage); //$NON-NLS-1$
locationPage.setDescription(CVSUIMessages.SharingWizard_importTitleDescription);
addPage(locationPage);
}
createLocationPage = new ConfigurationWizardMainPage("createLocationPage", CVSUIMessages.SharingWizard_enterInformation, sharingImage); //$NON-NLS-1$
createLocationPage.setDescription(CVSUIMessages.SharingWizard_enterInformationDescription);
createLocationPage.setCVSWizard(this);
createLocationPage.setDialogSettings(NewLocationWizard.getLocationDialogSettings());
addPage(createLocationPage);
modulePage = new ModuleSelectionPage("modulePage", CVSUIMessages.SharingWizard_enterModuleName, sharingImage); //$NON-NLS-1$
modulePage.setDescription(CVSUIMessages.SharingWizard_enterModuleNameDescription);
modulePage.setCVSWizard(this);
modulePage.setProject(project);
modulePage.setHelpContxtId(IHelpContextIds.SHARING_MODULE_PAGE);
addPage(modulePage);
addTagPage(sharingImage);
addSyncPage(sharingImage);
}
}
private void addTagPage(ImageDescriptor sharingImage) {
tagPage = new TagSelectionWizardPage("tagPage", //$NON-NLS-1$
CVSUIMessages.SharingWizard_selectTagTitle,
sharingImage,
CVSUIMessages.SharingWizard_selectTag,
TagSource.EMPTY, // start with an empty tag source
TagSourceWorkbenchAdapter.INCLUDE_HEAD_TAG | TagSourceWorkbenchAdapter.INCLUDE_BRANCHES);
tagPage.setCVSWizard(this);
tagPage.setHelpContxtId(IHelpContextIds.SHARING_TAG_SELETION_PAGE);
addPage(tagPage);
}
private void addSyncPage(ImageDescriptor sharingImage) {
syncPage = new SharingWizardSyncPage("syncPagePage", //$NON-NLS-1$
CVSUIMessages.SharingWizard_23,
sharingImage,
CVSUIMessages.SharingWizard_24);
syncPage.setProject(project);
syncPage.setCVSWizard(this);
addPage(syncPage);
}
@Override
public boolean canFinish() {
IWizardPage page = getContainer().getCurrentPage();
return (page == autoconnectPage || page == syncPage);
}
@Override
public IWizardPage getNextPage(IWizardPage page) {
// Assume the page is about to be shown when this method is
// invoked
return getNextPage(page, true /* about to show*/);
}
@Override
public IWizardPage getNextPage(IWizardPage page, boolean aboutToShow) {
if (page == autoconnectPage) return null;
if (page == locationPage) {
if (locationPage.getLocation() == null) {
return createLocationPage;
} else {
if (aboutToShow) {
try {
modulePage.setLocation(getLocation());
} catch (TeamException e1) {
CVSUIPlugin.log(e1);
}
}
return modulePage;
}
}
if (page == createLocationPage) {
if (aboutToShow) {
try {
modulePage.setLocation(getLocation());
} catch (TeamException e1) {
CVSUIPlugin.log(e1);
}
}
return modulePage;
}
try {
if (page == modulePage) {
if (aboutToShow) {
remoteFolder = null; // reset
getRemoteFolder(); // initialize remoteFolder
if (exists(remoteFolder)) {
prepareTagPage(remoteFolder);
return tagPage;
} else {
try {
populateSyncPage(false /* remote doesn't exist */);
} catch (InvocationTargetException e) {
CVSUIPlugin.openError(getShell(), null, null, e);
if (!RepositoryProvider.isShared(project)) {
// Only stay on the current page if the sharing was a total failure
return null;
}
}
return syncPage;
}
} else {
return syncPage;
}
}
if (page == tagPage) {
if (aboutToShow) {
remoteFolder = null; // reset
getRemoteFolder(); // initialize remoteFolder
populateSyncPage(true /* remote exists */);
}
return syncPage;
}
} catch (InvocationTargetException e) {
// Show the error and fall through to return null as the next page
CVSUIPlugin.openError(getShell(), null, null, e);
} catch (InterruptedException e) {
// The user cancelled. Fall through and return null as the next page.
}
return null;
}
/*
* @see IWizard#performFinish
*/
@Override
public boolean performFinish() {
final boolean[] result = new boolean[] { true };
if (isAutoconnect()) {
try {
getContainer().run(true /* fork */, true /* cancel */, monitor -> {
try {
result[0] = autoconnectCVSProject(monitor);
} catch (TeamException e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
});
} catch (InterruptedException e) {
return true;
} catch (InvocationTargetException e) {
CVSUIPlugin.openError(getContainer().getShell(), null, null, e);
result[0] = false;
}
}
// Add the location to the provider if it is new
if (result[0] && isNewLocation) {
KnownRepositories.getInstance().addRepository(location, true /* broadcast */);
}
final Shell parentShell= getShell().getParent().getShell();
if (getContainer().getCurrentPage() == syncPage) {
syncPage.saveSettings();
if (syncPage.commitChanges()) {
Display.getCurrent().asyncExec(() -> {
try {
CommitWizard.run(null, parentShell, new IResource[] { syncPage.getProject() });
} catch (CVSException e) {
// TODO:handle
CVSUIPlugin.log(e);
}
});
}
}
return result[0];
}
@Override
public boolean performCancel() {
boolean disposeLocation = isNewLocation;
ICVSRepositoryLocation location;
try {
location = getLocation();
} catch (TeamException e) {
CVSUIPlugin.log(e);
return true;
}
if (location == null) return true;
// If on the last page, offer to disconnect
if (getContainer().getCurrentPage() == syncPage
&& RepositoryProvider.getProvider(project) != null) {
// Prompt to see if we should undo out work
if (promptToKeepMapping()) {
// If we didn't disconnect, don't dispose the repo
disposeLocation = false;
// Add the location to the provider if it is new
if (isNewLocation) {
KnownRepositories.getInstance().addRepository(location, true /* broadcast */);
}
} else {
try {
getContainer().run(true, true,
monitor -> new DisconnectOperation(null, new IProject[] { project }, true).run(monitor));
} catch (InvocationTargetException e) {
CVSUIPlugin.log(IStatus.ERROR, e.getMessage(), e.getTargetException());
} catch (InterruptedException e) {
// Ignore
}
}
}
// Dispose of the location if appropriate
if (disposeLocation) {
KnownRepositories.getInstance().disposeRepository(location);
}
return super.performCancel();
}
private boolean promptToKeepMapping() {
return (MessageDialog.openQuestion(getShell(), CVSUIMessages.SharingWizard_26, NLS.bind(CVSUIMessages.SharingWizard_27, new String[] { project.getName() }))); //
}
private void reconcileProject(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
new ReconcileProjectOperation(getShell(), project, getRemoteFolder()).run(monitor);
}
/**
* Return an ICVSRepositoryLocation
*/
private ICVSRepositoryLocation getLocation() throws TeamException {
// If there is an autoconnect page then it has the location
if (autoconnectPage != null) {
return recordLocation(autoconnectPage.getLocation());
}
// If the location page has a location, use it.
if (locationPage != null) {
ICVSRepositoryLocation newLocation = locationPage.getLocation();
if (newLocation != null) {
return recordLocation(newLocation);
}
}
// Otherwise, get the location from the create location page
final ICVSRepositoryLocation[] locations = new ICVSRepositoryLocation[] { null };
final CVSException[] exception = new CVSException[] { null };
getShell().getDisplay().syncExec(() -> {
try {
locations[0] = createLocationPage.getLocation();
} catch (CVSException e) {
exception[0] = e;
}
});
if (exception[0] != null) {
throw exception[0];
}
return recordLocation(locations[0]);
}
private ICVSRepositoryLocation recordLocation(ICVSRepositoryLocation newLocation) {
if (newLocation == null) return location;
if (location == null || !newLocation.equals(location)) {
if (location != null && isNewLocation) {
// Dispose of the previous location
KnownRepositories.getInstance().disposeRepository(location);
}
location = newLocation;
isNewLocation = !KnownRepositories.getInstance().isKnownRepository(newLocation.getLocation(false));
if (isNewLocation) {
// Add the location silently so we can work with it
location = KnownRepositories.getInstance().addRepository(location, false /* silently */);
}
}
return location;
}
/*
* @see IConfigurationWizard#init(IWorkbench, IProject)
*/
@Override
public void init(IWorkbench workbench, IProject project) {
this.project = project;
}
private boolean doesCVSDirectoryExist() {
// Determine if there is an existing CVS/ directory from which configuration
// information can be retrieved.
Shell shell = null;
if (getContainer() != null) {
shell = getContainer().getShell();
}
final boolean[] isCVSFolder = new boolean[] { false };
try {
CVSUIPlugin.runWithRefresh(shell, new IResource[] { project }, monitor -> {
try {
ICVSFolder folder = (ICVSFolder) CVSWorkspaceRoot.getCVSResourceFor(project);
FolderSyncInfo info = folder.getFolderSyncInfo();
isCVSFolder[0] = info != null;
} catch (final TeamException e) {
throw new InvocationTargetException(e);
}
}, null);
} catch (InvocationTargetException e) {
CVSUIPlugin.openError(shell, null, null, e);
} catch (InterruptedException e) {
// Cancelled. Just fall through
}
return isCVSFolder[0];
}
/*
* Should the project be auto-connected
*/
/* private*/ boolean isAutoconnect() {
return autoconnectPage != null && doesCVSDirectoryExist();
}
/*
* Auto-connect to the repository using CVS/ directories
*/
/*private */ boolean autoconnectCVSProject(IProgressMonitor monitor) throws TeamException {
try {
monitor.beginTask(null, 100);
FolderSyncInfo info = autoconnectPage.getFolderSyncInfo();
if (info == null) {
// Error!
return false;
}
// Get the repository location (the get will add the location to the provider)
ICVSRepositoryLocation location = getLocation();
// Validate the connection if the user wants to
boolean validate = autoconnectPage.getValidate();
if (validate) {
// Do the validation
try {
location.validateConnection(Policy.subMonitorFor(monitor, 50));
} catch (final TeamException e) {
// Exception validating. We can continue if the user wishes.
final boolean[] keep = new boolean[] { false };
getShell().getDisplay()
.syncExec(() -> keep[0] = MessageDialog.openQuestion(getContainer().getShell(),
CVSUIMessages.SharingWizard_validationFailedTitle,
NLS.bind(CVSUIMessages.SharingWizard_validationFailedText,
(new Object[] { e.getStatus().getMessage() }))));
if (!keep[0]) {
return false;
}
// They want to keep the connection anyway. Fall through.
}
}
// Set the sharing
CVSWorkspaceRoot.setSharing(project, info, Policy.subMonitorFor(monitor, 50));
return true;
} finally {
monitor.done();
}
}
private boolean shareProject(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
monitor.beginTask(null, 100);
ICVSRepositoryLocation location = null;
try {
location = getLocation();
location.validateConnection(Policy.subMonitorFor(monitor, 50));
} catch (TeamException e) {
CVSUIPlugin.openError(getShell(), null, null, e, CVSUIPlugin.PERFORM_SYNC_EXEC);
if (isNewLocation && location != null) location.flushUserInfo();
return false;
}
// Create the remote module for the project
ShareProjectOperation op = new ShareProjectOperation(null, location, project, getRemoteFolder().getRepositoryRelativePath());
op.setShell(getShell());
op.run(Policy.subMonitorFor(monitor, 50));
return true;
}
private CVSTag getTag() {
if (tagPage == null || tagPage.getSelectedTag() == null) {
return CVSTag.DEFAULT;
}
return tagPage.getSelectedTag();
}
private ICVSRemoteFolder getRemoteFolder() {
if (remoteFolder == null) {
ICVSRemoteFolder folder = modulePage.getSelectedModule();
remoteFolder = (ICVSRemoteFolder)folder.forTag(getTag());
}
return remoteFolder;
}
private boolean exists(ICVSRemoteFolder folder, IProgressMonitor monitor) throws TeamException {
if (existingRemote != null && existingRemote.equals(folder)) return true;
if (folder.exists(monitor)) {
existingRemote = folder;
return true;
} else {
existingRemote = null;
return false;
}
}
private boolean exists(final ICVSRemoteFolder folder) throws InvocationTargetException, InterruptedException {
final boolean[] result = new boolean[] { false };
getContainer().run(true, true, monitor -> {
try {
result[0] = exists(folder, monitor);
} catch (TeamException e) {
throw new InvocationTargetException(e);
}
});
return result[0];
}
private void populateSyncPage(final boolean exists) throws InvocationTargetException, InterruptedException {
getContainer().run(true, true, monitor -> {
monitor.beginTask(null, IProgressMonitor.UNKNOWN);
if (exists) {
reconcileProject(Policy.subMonitorFor(monitor, 50));
} else {
shareProject(Policy.subMonitorFor(monitor, 50));
}
try {
getParticipant().getContext().refresh(Utils.getResourceMappings(new IProject[] { project }),
Policy.subMonitorFor(monitor, 50));
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
if (monitor.isCanceled()) {
throw new InterruptedException();
}
monitor.done();
});
}
@Override
public IWizardPage getPreviousPage(IWizardPage page) {
if (page == syncPage) {
// There's no going back from the sync page
return null;
}
return super.getPreviousPage(page);
}
private void prepareTagPage(ICVSRemoteFolder remote) {
tagPage.setTagSource(TagSource.create(remote));
tagPage.setDescription(NLS.bind(CVSUIMessages.SharingWizard_25, new String[] { remote.getRepositoryRelativePath() }));
}
private ModelSynchronizeParticipant getParticipant() {
return syncPage.getParticipant();
}
}