| /******************************************************************************* |
| * Copyright (c) 2000, 2016 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.releng.tools; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.MultiStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.SubMonitor; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.dialogs.ErrorDialog; |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.jface.wizard.IWizardPage; |
| import org.eclipse.jface.wizard.Wizard; |
| import org.eclipse.jface.wizard.WizardDialog; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.releng.tools.preferences.MapProjectPreferencePage; |
| import org.eclipse.swt.events.ControlEvent; |
| import org.eclipse.swt.events.ControlListener; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.team.core.TeamException; |
| import org.eclipse.team.internal.ccvs.core.CVSTag; |
| import org.eclipse.team.internal.ccvs.core.client.Command; |
| import org.eclipse.team.internal.ccvs.ui.CVSLightweightDecorator; |
| import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin; |
| import org.eclipse.team.internal.ccvs.ui.operations.CommitOperation; |
| import org.eclipse.team.internal.ccvs.ui.operations.RepositoryProviderOperation; |
| import org.eclipse.team.internal.ui.ITeamUIImages; |
| import org.eclipse.team.internal.ui.TeamUIPlugin; |
| import org.eclipse.team.internal.ui.dialogs.IPromptCondition; |
| import org.eclipse.team.internal.ui.dialogs.PromptingDialog; |
| |
| |
| public class ReleaseWizard extends Wizard { |
| |
| // Dialog store constants |
| private static final String BOUNDS_HEIGHT= "bounds.height"; //$NON-NLS-1$ |
| private static final String BOUNDS_WIDTH= "bounds.width"; //$NON-NLS-1$ |
| private static final String BOUNDS_Y= "bounds.y"; //$NON-NLS-1$ |
| private static final String BOUNDS_X= "bounds.x"; //$NON-NLS-1$ |
| |
| private MapProjectSelectionPage mapSelectionPage; |
| private ProjectSelectionPage projectSelectionPage; |
| private TagPage tagPage; |
| private ProjectComparePage projectComparePage; |
| private MapFileComparePage mapComparePage; |
| private CommitCommentPage commentPage; |
| private BuildNotesPage buildNotesPage; |
| private ValidatePage validatePage; |
| |
| private Dialog parentDialog; |
| private IDialogSettings section; |
| |
| private MapProject mapProject; |
| private IProject[] preSelectedProjects; |
| private IProject[] selectedProjects; |
| private IPreferenceStore preferenceStore; |
| private boolean defaultBeingUsed; |
| |
| |
| public ReleaseWizard() { |
| setWindowTitle("Release"); //$NON-NLS-1$ |
| IDialogSettings settings = RelEngPlugin.getDefault().getDialogSettings(); |
| section = settings.getSection("ReleaseWizard");//$NON-NLS-1$ |
| if (section == null) { |
| section = settings.addNewSection("ReleaseWizard");//$NON-NLS-1$ |
| } |
| setDialogSettings(section); |
| preferenceStore = RelEngPlugin.getDefault().getPreferenceStore(); |
| } |
| |
| /* |
| * @see org.eclipse.jface.wizard.Wizard#createPageControls(org.eclipse.swt.widgets.Composite) |
| * @since 3.1 |
| */ |
| @Override |
| public void createPageControls(Composite pageContainer) { |
| super.createPageControls(pageContainer); |
| |
| if (getDialogSettings().get(BOUNDS_X) != null) { |
| int x= getDialogSettings().getInt(BOUNDS_X); |
| int y= getDialogSettings().getInt(BOUNDS_Y); |
| int width= getDialogSettings().getInt(BOUNDS_WIDTH); |
| int height= getDialogSettings().getInt(BOUNDS_HEIGHT); |
| getShell().setBounds(x, y, width, height); |
| } |
| |
| getShell().addControlListener(new ControlListener() { |
| |
| @Override |
| public void controlMoved(ControlEvent e) { |
| storeBounds(e); |
| } |
| |
| @Override |
| public void controlResized(ControlEvent e) { |
| storeBounds(e); |
| } |
| |
| private void storeBounds(ControlEvent e) { |
| Rectangle bounds= getShell().getBounds(); |
| getDialogSettings().put(BOUNDS_X, bounds.x); |
| getDialogSettings().put(BOUNDS_Y, bounds.y); |
| getDialogSettings().put(BOUNDS_WIDTH, bounds.width); |
| getDialogSettings().put(BOUNDS_HEIGHT, bounds.height); |
| } |
| }); |
| } |
| |
| public boolean execute(Shell shell) { |
| setNeedsProgressMonitor(true); |
| WizardDialog dialog = new WizardDialog(shell, this); |
| setParentDialog(dialog); |
| return (dialog.open() == Window.OK); |
| } |
| |
| /** |
| * @see org.eclipse.jface.wizard.IWizard#addPages() |
| */ |
| @Override |
| public void addPages() { |
| defaultBeingUsed = false; |
| if (preferenceStore.getBoolean(MapProjectPreferencePage.USE_DEFAULT_MAP_PROJECT) && |
| (preferenceStore.getString(MapProjectPreferencePage.SELECTED_MAP_PROJECT_PATH).length() > 1)) { |
| String path = preferenceStore.getString(MapProjectPreferencePage.SELECTED_MAP_PROJECT_PATH); |
| |
| try { |
| mapProject = new MapProject(ResourcesPlugin.getWorkspace().getRoot().getProject(path)); |
| defaultBeingUsed = true; |
| } |
| catch (CoreException e) { |
| //this is ok, we will use the mapSelectionPage instead |
| } |
| } |
| |
| ImageDescriptor wizardPageImageDescriptor = TeamUIPlugin |
| .getImageDescriptor(ITeamUIImages.IMG_WIZBAN_SHARE); |
| |
| if (!defaultBeingUsed) |
| addMapSelectionPage(wizardPageImageDescriptor); |
| |
| projectSelectionPage = new ProjectSelectionPage("ProjectSelectionPage", //$NON-NLS-1$ |
| Messages.getString("ReleaseWizard.6"), //$NON-NLS-1$ |
| section, wizardPageImageDescriptor); |
| projectSelectionPage.setDescription(Messages |
| .getString("ReleaseWizard.7")); //$NON-NLS-1$ |
| addPage(projectSelectionPage); |
| |
| tagPage = new TagPage("TagPage", //$NON-NLS-1$ |
| Messages.getString("ReleaseWizard.9"), //$NON-NLS-1$ |
| section, |
| wizardPageImageDescriptor); |
| tagPage.setDescription(Messages.getString("ReleaseWizard.10")); //$NON-NLS-1$ |
| addPage(tagPage); |
| |
| projectComparePage = new ProjectComparePage("ProjectComparePage", //$NON-NLS-1$ |
| Messages.getString("ReleaseWizard.12"), //$NON-NLS-1$ |
| section, |
| wizardPageImageDescriptor); |
| projectComparePage.setDescription(Messages.getString("ReleaseWizard.13")); //$NON-NLS-1$ |
| addPage(projectComparePage); |
| |
| buildNotesPage = new BuildNotesPage("Build Notes Page", //$NON-NLS-1$ |
| Messages.getString("ReleaseWizard.1"), //$NON-NLS-1$ |
| section, |
| wizardPageImageDescriptor); |
| buildNotesPage.setDescription(Messages.getString("ReleaseWizard.0")); //$NON-NLS-1$ |
| addPage(buildNotesPage); |
| |
| mapComparePage = new MapFileComparePage("MapComparePage", //$NON-NLS-1$ |
| Messages.getString("ReleaseWizard.15"), //$NON-NLS-1$ |
| wizardPageImageDescriptor); |
| mapComparePage.setDescription(Messages.getString("ReleaseWizard.16")); //$NON-NLS-1$ |
| addPage(mapComparePage); |
| |
| commentPage = new CommitCommentPage(parentDialog, "Commit", //$NON-NLS-1$ |
| Messages.getString("ReleaseWizard.18"), //$NON-NLS-1$ |
| wizardPageImageDescriptor, |
| Messages.getString("ReleaseWizard.19")); //$NON-NLS-1$ |
| addPage(commentPage); |
| |
| validatePage = new ValidatePage(parentDialog, "ValidatePage", //$NON-NLS-1$ |
| Messages.getString("ReleaseWizard.validatePageTitle"), //$NON-NLS-1$ |
| wizardPageImageDescriptor); |
| addPage(validatePage); |
| |
| if (defaultBeingUsed) broadcastMapProjectChange(mapProject); |
| } |
| |
| /* |
| * @see org.eclipse.jface.wizard.Wizard#dispose() |
| * @since 3.7 |
| */ |
| @Override |
| public void dispose() { |
| if (mapProject != null) { |
| mapProject.dispose(); |
| mapProject= null; |
| } |
| super.dispose(); |
| } |
| |
| private void addMapSelectionPage(ImageDescriptor wizardPageImageDescriptor) { |
| mapSelectionPage = new MapProjectSelectionPage( |
| "MapProjectSelectionPage", //$NON-NLS-1$ |
| Messages.getString("ReleaseWizard.4"), //$NON-NLS-1$ |
| section, wizardPageImageDescriptor); |
| mapSelectionPage.setDescription(Messages.getString("ReleaseWizard.3")); //$NON-NLS-1$ |
| addPage(mapSelectionPage); |
| } |
| |
| /* |
| * commit buildnotes file if update option selected |
| */ |
| public boolean buildNotesOperation() { |
| if (buildNotesPage.isUpdateNotesButtonChecked() && projectComparePage.isBuildNotesButtonChecked()) { |
| buildNotesPage.updateNotesFile(); |
| try { |
| getContainer().run(true, true, monitor -> { |
| IFile iFile = buildNotesPage.getIFile(); |
| IProject iProject = iFile.getProject(); |
| monitor.beginTask(Messages.getString("ReleaseWizard.20"), 100); //$NON-NLS-1$ |
| new CommitOperation(null, |
| RepositoryProviderOperation.asResourceMappers(new IResource[] { iProject }), |
| new Command.LocalOption[0], commentPage.getComment()).run(monitor); |
| monitor.done(); |
| }); |
| } catch (InterruptedException e) { |
| // Cancelled. |
| return false; |
| } catch (InvocationTargetException e) { |
| CVSUIPlugin.openError(getShell(), null, null, e); |
| } |
| checkProjects(); |
| } |
| return true; |
| } |
| |
| /* |
| * add project of build notes file if not already in selected projects |
| */ |
| public void checkProjects() { |
| IProject[] temp = new IProject[selectedProjects.length + 1]; |
| for (int i = 0; i < selectedProjects.length; i++) { |
| if (selectedProjects[i] == buildNotesPage.getIFile().getProject()) { |
| return; |
| } |
| } |
| System.arraycopy(selectedProjects, 0, temp, 0, selectedProjects.length); |
| temp[temp.length - 1] = buildNotesPage.getIFile().getProject(); |
| selectedProjects = temp; |
| } |
| |
| /** |
| * @see org.eclipse.jface.wizard.Wizard#performFinish() |
| */ |
| @Override |
| public boolean performFinish() { |
| if(!isProjectSelected())return false; |
| |
| if (projectSelectionPage.isCompareButtonChecked() && !buildNotesOperation()) { |
| return true; // Build notes file update cancelled. Close dialog. |
| } |
| |
| try { |
| getContainer().run(true, true, monitor -> { |
| CVSTag tag = new CVSTag(tagPage.getTagString(), CVSTag.VERSION); |
| TagAndReleaseOperation operation = new TagAndReleaseOperation(null, mapProject, selectedProjects, tag, |
| commentPage.getComment()); |
| if (tagPage.isMoveButtonSelected()) { |
| operation.moveTag(); |
| } |
| monitor.beginTask(Messages.getString("ReleaseWizard.21"), 100); //$NON-NLS-1$ |
| operation.run(SubMonitor.convert(monitor, 90)); |
| if (operation.isMapFileUpdated()) { |
| try { |
| if (tagPage.isValidateButtonSelected()) { |
| try { |
| getShell().getDisplay().asyncExec(() -> { |
| if (parentDialog instanceof WizardDialog) |
| ((WizardDialog) parentDialog).showPage(validatePage); |
| }); |
| validateRelease(SubMonitor.convert(monitor, 10)); |
| } catch (TeamException e) { |
| throw new InvocationTargetException(e); |
| } |
| } |
| } finally { |
| monitor.done(); |
| } |
| } else { |
| // The map file update didn't occur and no exception was |
| // thrown. |
| // Let the user know of the failure |
| IStatus[] errors = operation.getErrors(); |
| IStatus status; |
| if (errors.length == 0) { |
| status = new Status(IStatus.ERROR, RelEngPlugin.ID, 0, Messages.getString("ReleaseWizard.22"), //$NON-NLS-1$ |
| null); |
| } else if (errors.length == 1) { |
| status = errors[0]; |
| } else { |
| status = new MultiStatus(RelEngPlugin.ID, 0, errors, Messages.getString("ReleaseWizard.23"), //$NON-NLS-1$ |
| null); |
| } |
| ErrorDialog.openError(getShell(), Messages.getString("ReleaseWizard.24"), //$NON-NLS-1$ |
| Messages.getString("ReleaseWizard.25"), //$NON-NLS-1$ |
| status, IStatus.ERROR | IStatus.WARNING); |
| } |
| }); |
| if (!defaultBeingUsed) { |
| mapSelectionPage.saveSettings(); |
| updatePreferenceStore(); |
| } |
| projectSelectionPage.saveSettings(); |
| projectComparePage.saveSettings(); |
| buildNotesPage.saveSettings(); |
| tagPage.saveSettings(); |
| return true; |
| } catch (InterruptedException e) { |
| // Cancelled. Ignore and close dialog |
| return true; |
| } catch (InvocationTargetException e) { |
| CVSUIPlugin.openError(getShell(), null, null, e); |
| } |
| return false; |
| } |
| |
| private void updatePreferenceStore() { |
| preferenceStore.setValue(MapProjectPreferencePage.USE_DEFAULT_MAP_PROJECT, mapSelectionPage.useDefaultMapProject()); |
| String fullPath = mapSelectionPage.getSelectedMapProject().getProject().getFullPath().toString(); |
| preferenceStore.setValue(MapProjectPreferencePage.SELECTED_MAP_PROJECT_PATH, fullPath); |
| } |
| |
| public void setParentDialog(Dialog p) { |
| this.parentDialog = p; |
| } |
| |
| @Override |
| public IWizardPage getNextPage(IWizardPage page) { |
| if (page == mapSelectionPage) { |
| if (selectedProjects == null && preSelectedProjects != null) { |
| projectSelectionPage.setSelection(preSelectedProjects); |
| selectedProjects= preSelectedProjects; |
| } |
| return projectSelectionPage; |
| } |
| if (page == projectSelectionPage) { |
| IProject[] projects = projectSelectionPage.getCheckedProjects(); |
| if (projects != null && projects.length > 0){ |
| selectedProjects = projects; |
| } |
| |
| if (projectSelectionPage.isCompareButtonChecked()){ |
| return projectComparePage; |
| } |
| else |
| return tagPage; |
| } |
| if (page == tagPage) { |
| if (tagPage.compareButtonSelected()){ |
| mapComparePage.setTag(tagPage.getTagString()); |
| return mapComparePage; |
| } |
| if (tagPage.commitButtonSelected()) |
| return commentPage; |
| } |
| if (page == mapComparePage) |
| return commentPage; |
| if (page == projectComparePage) { |
| if (projectComparePage.isBuildNotesButtonChecked()) { |
| buildNotesPage.setSyncInfoSet(projectComparePage |
| .getSyncInfoSet()); |
| return buildNotesPage; |
| } |
| return tagPage; |
| } |
| if (page == buildNotesPage) { |
| return tagPage; |
| } |
| return null; |
| } |
| |
| public void setPreSelectedProjects(IResource[] resources) { |
| if (resources.length < 1) { |
| preSelectedProjects = null; |
| } else { |
| Set<IProject> list = new HashSet<>(); |
| for (int i = 0; i < resources.length; i++) { |
| list.add(resources[i].getProject()); |
| } |
| preSelectedProjects = list.toArray(new IProject[list.size()]); |
| } |
| } |
| |
| // Prompt for any uncommitted changes |
| protected IProject[] performPrompting(IProject[] projects) { |
| IResource[] resources; |
| PromptingDialog prompt = new PromptingDialog(getShell(), projects, |
| getPromptCondition(projects), Messages.getString("TagAction_uncommittedChangesTitle")); //$NON-NLS-1$ |
| try { |
| resources = prompt.promptForMultiple(); |
| } catch(InterruptedException e) { |
| return null; |
| } |
| if(resources.length == 0) { |
| return null; |
| } |
| projects = new IProject[resources.length ]; |
| for(int i = 0; i < resources.length; i++){ |
| if(resources[i] instanceof IProject) |
| projects[i] = (IProject)resources[i]; |
| } |
| return projects; |
| } |
| |
| |
| protected IPromptCondition getPromptCondition(IResource[] resources) { |
| return new IPromptCondition() { |
| @Override |
| public boolean needsPrompt(IResource resource) { |
| return CVSLightweightDecorator.isDirty(resource); |
| } |
| @Override |
| public String promptMessage(IResource resource) { |
| return NLS.bind(Messages.getString("TagAction_uncommittedChanges"), new String[] { resource.getName() }); //$NON-NLS-1$ |
| } |
| }; |
| } |
| |
| public IProject[] getSelectedProjects(){ |
| return selectedProjects; |
| } |
| |
| //the update will happen when (1)from project selection page to compare project page or (2)from |
| //project selection page to Enter Tag page. It calls shouldRemove() to determine the projects to keep |
| public void updateSelectedProject(){ |
| selectedProjects = projectSelectionPage.getCheckedProjects(); |
| selectedProjects = performPrompting(selectedProjects); |
| projectSelectionPage.setSelection(selectedProjects); |
| } |
| |
| public void setSelectedProjects(IResource[] projects){ |
| if(projects == null) selectedProjects = null; |
| else { |
| selectedProjects = new IProject[projects.length]; |
| for(int i = 0; i < projects.length; i++){ |
| selectedProjects[i] = (IProject)projects[i]; |
| } |
| } |
| } |
| protected ProjectSelectionPage getProjectSelectionPage(){ |
| return projectSelectionPage; |
| } |
| |
| //This method is called if validate button in TagPage is checked |
| private void validateRelease(IProgressMonitor monitor) throws TeamException{ |
| ProjectValidationDialog.validateRelease(getShell(), selectedProjects, mapProject.getTagsFor(selectedProjects), monitor); |
| } |
| |
| |
| private boolean isProjectSelected(){ |
| if (selectedProjects == null || selectedProjects.length == 0){ |
| return false; |
| } |
| return true; |
| } |
| |
| public IProject[] getPreSelectedProjects(){ |
| return preSelectedProjects; |
| } |
| |
| @Override |
| public boolean canFinish() { |
| // There must be projects selected |
| if (!isProjectSelected()) { |
| return false; |
| } |
| // There must be a tag |
| if (!tagPage.isPageComplete()) { |
| return false; |
| } |
| IWizardPage currentPage = getContainer().getCurrentPage(); |
| if (currentPage == validatePage) |
| return false; |
| |
| // Force map comparison if option set by user |
| if(currentPage == tagPage){ |
| if(tagPage.compareButtonSelected()){ |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| public MapProject getMapProject(){ |
| return mapProject; |
| } |
| public void broadcastMapProjectChange(MapProject m){ |
| mapProject = m; |
| projectSelectionPage.updateMapProject(m); |
| projectComparePage.updateMapProject(m); |
| mapComparePage.updateMapProject(m); |
| } |
| } |