diff options
author | cvs2svn | 2002-04-26 18:03:23 +0000 |
---|---|---|
committer | cvs2svn | 2002-04-26 18:03:23 +0000 |
commit | f8c287cd623281fb8fc0bc8f0cc14aa794bc4069 (patch) | |
tree | 0cd8615984ca60bca7dc7cc525ca4f524667652e | |
parent | 9f89115ef9494b68794da0b87c48d3830c174de1 (diff) | |
download | eclipse.platform.team-f8c287cd623281fb8fc0bc8f0cc14aa794bc4069.tar.gz eclipse.platform.team-f8c287cd623281fb8fc0bc8f0cc14aa794bc4069.tar.xz eclipse.platform.team-f8c287cd623281fb8fc0bc8f0cc14aa794bc4069.zip |
This commit was manufactured by cvs2svn to create branch
'compareWithBranch'.
Cherrypick from master 2002-04-26 18:03:22 UTC Michael Valenta <mvalenta> '14704: Unrecognized response from CVS server':
bundles/org.eclipse.team.core/src/org/eclipse/team/core/IProjectSetSerializer.java
bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RemoteCommand.java
bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Version.java
bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSProjectSetSerializer.java
bundles/org.eclipse.team.ui/.classpath
bundles/org.eclipse.team.ui/.project
bundles/org.eclipse.team.ui/icons/basic/clcl16/projectset.gif
bundles/org.eclipse.team.ui/icons/full/clcl16/projectset.gif
bundles/org.eclipse.team.ui/plugin.properties
bundles/org.eclipse.team.ui/plugin.xml
bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ExportProjectSetMainPage.java
bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ImportProjectSetMainPage.java
bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ProjectSetContentHandler.java
bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ProjectSetExportWizard.java
bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ProjectSetImportWizard.java
bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamWizardPage.java
bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties
bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncCompareInput.java
bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncView.java
19 files changed, 2283 insertions, 0 deletions
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/IProjectSetSerializer.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/IProjectSetSerializer.java new file mode 100644 index 000000000..bf1dbf358 --- /dev/null +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/IProjectSetSerializer.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * 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.core; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * IProjectSetSerializer manages the serializing and deserializing + * of references to projects. Given a project, it can produce a + * UTF-8 encoded String which can be stored in a file. + * Given this String, it can create in the workspace an IProject. + */ + +public interface IProjectSetSerializer { + + /** + * For every IProject in providerProjects, return an opaque + * UTF-8 encoded String to act as a reference to that project. + * The format of the String is specific to the provider. + * The format of the String must be such that + * IProjectSetSerializer.addToWorskpace() will be able to + * consume it and recreate a corresponding project. + * @see IProjectSetSerializer.addToWorkspace() + * + * @param providerProjects an array of projects that the serializer should create + * text references for + * @param context a UI context object. This object will either be a + * com.ibm.swt.widgets.Shell or it will be null. + * @param monitor a progress monitor + * @return an array of serialized reference strings uniquely identifying the projects + */ + public String[] asReference(IProject[] providerProjects, Object context, IProgressMonitor monitor) throws TeamException; + + /** + * For every String in referenceStrings, create in the workspace a + * corresponding IProject. Return an Array of the resulting IProjects. + * Result is unspecified in the case where an IProject of that name + * already exists. In the case of failure, a TeamException must be thrown. + * The opaque strings in referenceStrings are guaranteed to have been previously + * produced by IProjectSetSerializer.asReference(). + * @see IProjectSetSerializer.asReference() + * + * @param referenceStrings an array of referene strings uniquely identifying the projects + * @param filename the name of the file that the references were read from. This is included + * in case the provider needs to deduce relative paths + * @param context a UI context object. This object will either be a + * com.ibm.swt.widgets.Shell or it will be null. + * @param monitor a progress monitor + * @return an array of projects that were created + */ + public IProject[] addToWorkspace(String[] referenceStrings, String filename, Object context, IProgressMonitor monitor) throws TeamException; +} diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RemoteCommand.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RemoteCommand.java new file mode 100644 index 000000000..2460bcf4e --- /dev/null +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RemoteCommand.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * 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.core.client; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.internal.ccvs.core.ICVSResource; +import org.eclipse.team.internal.ccvs.core.client.Command.GlobalOption; +import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption; + +/** + * This class acts as a super class for those CVS commands that do not send up the local file structure + */ +public abstract class RemoteCommand extends Command { + + protected ICVSResource[] computeWorkResources(Session session, LocalOption[] localOptions, + String[] arguments) throws CVSException { + return new ICVSResource[0]; + } + + protected void sendLocalResourceState(Session session, GlobalOption[] globalOptions, + LocalOption[] localOptions, ICVSResource[] resources, IProgressMonitor monitor) + throws CVSException { + // do nothing + } + + protected void sendLocalWorkingDirectory(Session session) throws CVSException { + // do nothing + } + +} diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Version.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Version.java new file mode 100644 index 000000000..af1ca8917 --- /dev/null +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Version.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * 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.core.client; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; +import org.eclipse.team.internal.ccvs.core.CVSStatus; +import org.eclipse.team.internal.ccvs.core.ICVSFolder; +import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation; +import org.eclipse.team.internal.ccvs.core.ICVSResource; +import org.eclipse.team.internal.ccvs.core.Policy; +import org.eclipse.team.internal.ccvs.core.client.listeners.ICommandOutputListener; +import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; + +/** + * Here are some of the output formats we know about: + * + * Concurrent Versions System (CVS) 1.11.1p1 (client/server) + * Concurrent Versions System (CVS) NT 1.11.1.1 (Build 27) + * Concurrent Versions System (CVSNT) 1.11.1.3 (Build 57a) (client/server) + */ +public class Version extends RemoteCommand { + + private static final String CVS_NT_PREFIX_1 = "Concurrent Versions System (CVS) NT "; //$NON-NLS-1$ + private static final String CVS_NT_PREFIX_2 = "Concurrent Versions System (CVSNT) "; //$NON-NLS-1$ + private static final String CVS_PREFIX = "Concurrent Versions System (CVS) "; //$NON-NLS-1$ + /** + * @see Request#getRequestId() + */ + protected String getRequestId() { + return "version"; //$NON-NLS-1$ + } + + public IStatus execute(Session session, final ICVSRepositoryLocation location, IProgressMonitor monitor) throws CVSException { + + ICommandOutputListener listener = new ICommandOutputListener() { + public IStatus messageLine(String line, ICVSFolder commandRoot, IProgressMonitor monitor) { + String knownPrefix = null; + boolean isCVSNT = false; + if (line.startsWith(CVS_NT_PREFIX_1)) { + isCVSNT = true; + knownPrefix = CVS_NT_PREFIX_1; + } else if (line.startsWith(CVS_NT_PREFIX_2)) { + isCVSNT = true; + knownPrefix = CVS_NT_PREFIX_2; + } else if (line.startsWith(CVS_PREFIX)) { + knownPrefix = CVS_PREFIX; + } + IStatus status = OK; + if (knownPrefix != null) { + String versionNumber = line.substring(knownPrefix.length(), line.indexOf(' ', knownPrefix.length() + 1)); + if (versionNumber.startsWith("1.10") || versionNumber.equals("1.11") || versionNumber.equals("1.11.1")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + status = new CVSStatus(IStatus.ERROR, CVSStatus.UNSUPPORTED_SERVER_VERSION, Policy.bind("Version.unsupportedVersion", location.getHost(), versionNumber));//$NON-NLS-1$ + } else if (isCVSNT) { + status = new CVSStatus(IStatus.WARNING, CVSStatus.SERVER_IS_CVSNT, Policy.bind("Version.unsupportedCVSNT", location.getHost(), versionNumber));//$NON-NLS-1$ + } + } else { + status = new CVSStatus(IStatus.INFO, CVSStatus.SERVER_IS_UNKNOWN, Policy.bind("Version.unknownVersionFormat", location.getHost(), line));//$NON-NLS-1$ + } + ((CVSRepositoryLocation)location).setServerPlaform(status); + return status; + } + public IStatus errorLine(String line, ICVSFolder commandRoot, IProgressMonitor monitor) { + return new CVSStatus(IStatus.ERROR, CVSStatus.ERROR_LINE, line); + } + }; + + if (session == null) { + return execute(NO_GLOBAL_OPTIONS, NO_LOCAL_OPTIONS, new ICVSResource[] {}, listener, monitor); + } else { + return execute(session, NO_GLOBAL_OPTIONS, NO_LOCAL_OPTIONS, new String[] {}, listener, monitor); + } + } +} diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSProjectSetSerializer.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSProjectSetSerializer.java new file mode 100644 index 000000000..7ae1b7b65 --- /dev/null +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSProjectSetSerializer.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * 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 java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.team.core.IProjectSetSerializer; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.internal.ccvs.core.CVSProvider; +import org.eclipse.team.internal.ccvs.core.CVSTag; +import org.eclipse.team.internal.ccvs.core.CVSTeamProvider; +import org.eclipse.team.internal.ccvs.core.ICVSFolder; +import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation; +import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; +import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; +import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo; + +public class CVSProjectSetSerializer implements IProjectSetSerializer { + + /** + * @see IProjectSetSerializer#asReference(IProject[]) + * + * "1.0,repoLocation,module,projectName[,tag]" + */ + public String[] asReference(IProject[] providerProjects, Object context, IProgressMonitor monitor) throws TeamException { + String[] result = new String[providerProjects.length]; + for (int i = 0; i < providerProjects.length; i++) { + StringBuffer buffer = new StringBuffer(); + buffer.append("1.0,"); //$NON-NLS-1$ + + IProject project = providerProjects[i]; + CVSTeamProvider provider = (CVSTeamProvider)RepositoryProvider.getProvider(project); + CVSWorkspaceRoot root = provider.getCVSWorkspaceRoot(); + CVSRepositoryLocation location = CVSRepositoryLocation.fromString(root.getRemoteLocation().getLocation()); + location.setUserMuteable(true); + String repoLocation = location.getLocation(); + buffer.append(repoLocation); + buffer.append(","); //$NON-NLS-1$ + + ICVSFolder folder = root.getLocalRoot(); + FolderSyncInfo syncInfo = folder.getFolderSyncInfo(); + String module = syncInfo.getRepository(); + buffer.append(module); + buffer.append(","); //$NON-NLS-1$ + + String projectName = folder.getName(); + buffer.append(projectName); + CVSTag tag = syncInfo.getTag(); + if (tag != null) { + if (tag.getType() != CVSTag.DATE) { + buffer.append(","); //$NON-NLS-1$ + String tagName = tag.getName(); + buffer.append(tagName); + } + } + result[i] = buffer.toString(); + } + return result; + } + + /** + * @see IProjectSetSerializer#addToWorkspace(String[]) + */ + public IProject[] addToWorkspace(String[] referenceStrings, String filename, Object context, IProgressMonitor monitor) throws TeamException { + int size = referenceStrings.length; + CVSProvider provider = CVSProvider.getInstance(); + IProject[] projects = new IProject[size]; + try { + ICVSRepositoryLocation[] locations = new ICVSRepositoryLocation[size]; + String[] modules = new String[size]; + CVSTag[] tags = new CVSTag[size]; + + for (int i = 0; i < size; i++) { + StringTokenizer tokenizer = new StringTokenizer(referenceStrings[i], ","); //$NON-NLS-1$ + String version = tokenizer.nextToken(); + if (!version.equals("1.0")) { //$NON-NLS-1$ + // Bail out, this is a newer version + return null; + } + String repo = tokenizer.nextToken(); + locations[i] = CVSRepositoryLocation.fromString(repo); + modules[i] = tokenizer.nextToken(); + String projectName = tokenizer.nextToken(); + projects[i] = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + if (tokenizer.hasMoreTokens()) { + String tagName = tokenizer.nextToken(); + tags[i] = new CVSTag(tagName, CVSTag.BRANCH); + } + } + // Check if any projects will be overwritten, and warn the user. + boolean yesToAll = false; + int action; + int num = size; + for (int i = 0; i < size; i++) { + Shell shell = null; + IProject project = projects[i]; + if (project.exists()) { + if (shell == null) { + if (context instanceof Shell) { + shell = (Shell)context; + } else { + return null; + } + } + action = confirmOverwrite(project, yesToAll, shell); + yesToAll = action == 2; + + // message dialog + switch (action) { + // no + case 1: + // Remove it from the set + locations[i] = null; + num--; + break; + // yes to all + case 2: + // yes + case 0: + break; + // cancel + case 3: + default: + return null; + } + } + } + monitor.beginTask("", 1000 * num); //$NON-NLS-1$ + for (int i = 0; i < size; i++) { + if (locations[i] != null) { + provider.checkout(locations[i], projects[i], modules[i], tags[i], new SubProgressMonitor(monitor, 1000)); + } + } + } finally { + monitor.done(); + } + List result = new ArrayList(); + for (int i = 0; i < projects.length; i++) { + if (projects[i] != null) result.add(projects[i]); + } + return (IProject[])result.toArray(new IProject[result.size()]); + } + private int confirmOverwrite(IProject project, boolean yesToAll, Shell shell) { + if (yesToAll) return 2; + if (!project.exists()) return 0; + final MessageDialog dialog = + new MessageDialog(shell, Policy.bind("CVSProjectSetSerializer.Confirm_Overwrite_Project_8"), null, Policy.bind("CVSProjectSetSerializer.The_project_{0}_already_exists._Do_you_wish_to_overwrite_it__9", project.getName()), MessageDialog.QUESTION, //$NON-NLS-1$ //$NON-NLS-2$ + new String[] { + IDialogConstants.YES_LABEL, + IDialogConstants.NO_LABEL, + IDialogConstants.YES_TO_ALL_LABEL, + IDialogConstants.CANCEL_LABEL}, + 0); + final int[] result = new int[1]; + shell.getDisplay().syncExec(new Runnable() { + public void run() { + result[0] = dialog.open(); + } + }); + return result[0]; + } +} diff --git a/bundles/org.eclipse.team.ui/.classpath b/bundles/org.eclipse.team.ui/.classpath new file mode 100644 index 000000000..b9991d9b2 --- /dev/null +++ b/bundles/org.eclipse.team.ui/.classpath @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="var" path="JRE_LIB" rootpath="JRE_SRCROOT" sourcepath="JRE_SRC"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="/org.eclipse.team.core"/> + <classpathentry kind="src" path="/org.eclipse.core.resources"/> + <classpathentry kind="src" path="/org.eclipse.ui"/> + <classpathentry kind="src" path="/org.eclipse.core.runtime"/> + <classpathentry kind="src" path="/org.eclipse.swt"/> + <classpathentry kind="src" path="/org.eclipse.compare"/> + <classpathentry kind="src" path="/org.apache.xerces"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/bundles/org.eclipse.team.ui/.project b/bundles/org.eclipse.team.ui/.project new file mode 100644 index 000000000..55c7e2e2a --- /dev/null +++ b/bundles/org.eclipse.team.ui/.project @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.team.ui</name> + <comment></comment> + <projects> + <project>org.apache.xerces</project> + <project>org.eclipse.compare</project> + <project>org.eclipse.core.resources</project> + <project>org.eclipse.core.runtime</project> + <project>org.eclipse.swt</project> + <project>org.eclipse.team.core</project> + <project>org.eclipse.ui</project> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + <nature>org.eclipse.team.cvs.core.cvsnature</nature> + </natures> +</projectDescription> diff --git a/bundles/org.eclipse.team.ui/icons/basic/clcl16/projectset.gif b/bundles/org.eclipse.team.ui/icons/basic/clcl16/projectset.gif Binary files differnew file mode 100644 index 000000000..954c7c44a --- /dev/null +++ b/bundles/org.eclipse.team.ui/icons/basic/clcl16/projectset.gif diff --git a/bundles/org.eclipse.team.ui/icons/full/clcl16/projectset.gif b/bundles/org.eclipse.team.ui/icons/full/clcl16/projectset.gif Binary files differnew file mode 100644 index 000000000..9b55c268c --- /dev/null +++ b/bundles/org.eclipse.team.ui/icons/full/clcl16/projectset.gif diff --git a/bundles/org.eclipse.team.ui/plugin.properties b/bundles/org.eclipse.team.ui/plugin.properties new file mode 100644 index 000000000..3849beaba --- /dev/null +++ b/bundles/org.eclipse.team.ui/plugin.properties @@ -0,0 +1,16 @@ +pluginName=Team Support UI + +# This will change shortly to "Text Resources" once a real Team page exists. +TextPreferencePage.name=Team + +IgnorePreferencePage.name=Ignored Resources + +ConfigureProject.label=&Share Project... +ConfigureProject.tooltip=Share the project with others using a version and configuration management provider. + +TeamGroupMenu.label=T&eam + +ProjectSetImportWizard.description=A wizard that imports a team project set +ProjectSetImportWizard.name=Team Project Set +ProjectSetExportWizard.name=Team Project Set +ProjectSetExportWizard.description=A wizard that exports a team project set diff --git a/bundles/org.eclipse.team.ui/plugin.xml b/bundles/org.eclipse.team.ui/plugin.xml new file mode 100644 index 000000000..efc8bfa3d --- /dev/null +++ b/bundles/org.eclipse.team.ui/plugin.xml @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- File written by PDE 1.0 --> +<plugin + id="org.eclipse.team.ui" + name="%pluginName" + version="2.0.0" + provider-name="Object Technology International, Inc." + class="org.eclipse.team.ui.TeamUIPlugin"> +<requires> + <import plugin="org.eclipse.core.resources"/> + <import plugin="org.eclipse.team.core"/> + <import plugin="org.eclipse.ui"/> + <import plugin="org.eclipse.compare"/> + <import plugin="org.apache.xerces"/> +</requires> + +<runtime> + <library name="teamui.jar"> + <export name="*"/> + </library> +</runtime> + +<extension-point id="configurationWizards" name="Configuration Wizards"/> + +<!-- **************** PREFERENCES ******************* --> + <extension + point = "org.eclipse.ui.preferencePages"> + <page id="org.eclipse.team.ui.TextPreferences" + class="org.eclipse.team.internal.ui.TextPreferencePage" + name="%TextPreferencePage.name"> + </page> + <page id="org.eclipse.team.ui.IgnorePreferences" + class="org.eclipse.team.internal.ui.IgnorePreferencePage" + name="%IgnorePreferencePage.name" + category="org.eclipse.team.ui.TextPreferences"> + </page> + </extension> + +<!-- ****************** POPUP ACTIONS *************** --> + +<extension + point="org.eclipse.ui.popupMenus"> + <objectContribution + id="org.eclipse.team.ui.ResourceContributions" + objectClass="org.eclipse.core.resources.IResource" adaptable="true"> + <menu + id="team.main" + path="additions" + label="%TeamGroupMenu.label"> + <separator name="group1"/> + <separator name="group2"/> + <separator name="group3"/> + <separator name="group4"/> + <separator name="group5"/> + <separator name="group6"/> + <separator name="group7"/> + <separator name="group8"/> + <separator name="group9"/> + <separator name="group10"/> + <separator name="projectGroup"/> + </menu> + </objectContribution> + <objectContribution + id="org.eclipse.team.ui.ProjectContributions" + objectClass="org.eclipse.core.resources.IProject" adaptable="true"> + <action + id="org.eclipse.team.ui.ConfigureProject" + label="%ConfigureProject.label" + tooltip="%ConfigureProject.tooltip" + menubarPath="team.main/projectGroup" + enablesFor="1" + class="org.eclipse.team.ui.actions.ConfigureProjectAction"> + </action> + </objectContribution> +</extension> + +<!-- ************** Views ********************** --> +<extension point="org.eclipse.ui.views"> + <category + id="org.eclipse.team.ui" + name="Team"> + </category> + <view + id="org.eclipse.team.ui.sync.SyncView" + icon="icons/full/cview16/synch_synch.gif" + name="Synchronize" + category="org.eclipse.team.ui" + class="org.eclipse.team.ui.sync.SyncView"> + </view> +</extension> + + + +<!-- ****************** Import Wizards ********************* --> + <extension + point="org.eclipse.ui.importWizards"> + <wizard + id="org.eclipse.team.ui.ProjectSetImportWizard" + name="%ProjectSetImportWizard.name" + class="org.eclipse.team.internal.ui.ProjectSetImportWizard" + icon="icons/full/clcl16/projectset.gif"> + <description> + %ProjectSetImportWizard.description + </description> + <selection class="org.eclipse.core.resources.IProject"/> + </wizard> + </extension> + +<!-- ****************** Export Wizards ********************* --> + <extension + point="org.eclipse.ui.exportWizards"> + <wizard + id="org.eclipse.team.ui.ProjectSetExportWizard" + name="%ProjectSetExportWizard.name" + class="org.eclipse.team.internal.ui.ProjectSetExportWizard" + icon="icons/full/clcl16/projectset.gif"> + <description> + %ProjectSetExportWizard.description + </description> + <selection class="org.eclipse.core.resources.IProject"/> + </wizard> + </extension> +</plugin>
\ No newline at end of file diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ExportProjectSetMainPage.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ExportProjectSetMainPage.java new file mode 100644 index 000000000..22efa303c --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ExportProjectSetMainPage.java @@ -0,0 +1,182 @@ +/******************************************************************************* + * 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.ui; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.TableLayout; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.Text; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.ui.model.WorkbenchContentProvider; +import org.eclipse.ui.model.WorkbenchLabelProvider; + +public class ExportProjectSetMainPage extends TeamWizardPage { + Text fileText; + String file = ""; //$NON-NLS-1$ + Button browseButton; + List selectedProjects = new ArrayList(); + + CheckboxTableViewer tableViewer; + Table table; + + class ProjectContentProvider extends WorkbenchContentProvider { + public Object[] getElements(Object element) { + if (element instanceof IProject[]) return (IProject[]) element; + return null; + } + }; + + public ExportProjectSetMainPage(String pageName, String title, ImageDescriptor titleImage) { + super(pageName, title, titleImage); + } + + /* + * @see IDialogPage#createControl(Composite) + */ + public void createControl(Composite parent) { + Composite composite = createComposite(parent, 1); + initializeDialogUnits(composite); + + createLabel(composite, Policy.bind("ExportProjectSetMainPage.Select_the_projects_to_include_in_the_project_set__2")); //$NON-NLS-1$ + + table = new Table(composite, SWT.CHECK); + tableViewer = new CheckboxTableViewer(table); + table.setLayout(new TableLayout()); + table.setLayoutData(new GridData(GridData.FILL_BOTH)); + tableViewer.setContentProvider(new ProjectContentProvider()); + tableViewer.setLabelProvider(new WorkbenchLabelProvider()); + tableViewer.addCheckStateListener(new ICheckStateListener() { + public void checkStateChanged(CheckStateChangedEvent event) { + IProject project = (IProject)event.getElement(); + if (event.getChecked()) { + selectedProjects.add(project); + } else { + selectedProjects.remove(project); + } + } + }); + createLabel(composite, Policy.bind("ExportProjectSetMainPage.Project_Set_File_Name__3")); //$NON-NLS-1$ + + Composite inner = new Composite(composite, SWT.NULL); + inner.setLayoutData(new GridData(GridData.FILL_BOTH)); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + layout.marginHeight = 0; + layout.marginWidth = 0; + inner.setLayout(layout); + + fileText = createTextField(inner); + if (file != null) fileText.setText(file); + fileText.addListener(SWT.Modify, new Listener() { + public void handleEvent(Event event) { + file = fileText.getText(); + updateEnablement(); + } + }); + + browseButton = new Button(inner, SWT.PUSH); + browseButton.setText(Policy.bind("ExportProjectSetMainPage.Browse_4")); //$NON-NLS-1$ + GridData data = new GridData(); + data.horizontalAlignment = GridData.FILL; + data.heightHint = convertVerticalDLUsToPixels(IDialogConstants.BUTTON_HEIGHT); + int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); + data.widthHint = Math.max(widthHint, browseButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x); + browseButton.setLayoutData(data); + browseButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + FileDialog d = new FileDialog(getShell()); + d.setFilterExtensions(new String[] {Policy.bind("ExportProjectSetMainPage.*.psf_2")}); //$NON-NLS-1$ + d.setFilterNames(new String[] {Policy.bind("ExportProjectSetMainPage.Project_Set_Files_3")}); //$NON-NLS-1$ + String f = d.open(); + if (f != null) { + fileText.setText(f); + file = f; + } + } + }); + + initializeProjects(); + setControl(composite); + updateEnablement(); + } + + private void initializeProjects() { + List projectList = new ArrayList(); + IProject[] workspaceProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); + for (int i = 0; i < workspaceProjects.length; i++) { + if (RepositoryProvider.getProvider(workspaceProjects[i]) != null) { + projectList.add(workspaceProjects[i]); + } + } + tableViewer.setInput((IProject[]) projectList.toArray(new IProject[projectList.size()])); + // Check any necessary projects + if (selectedProjects != null) { + tableViewer.setCheckedElements((IProject[])selectedProjects.toArray(new IProject[selectedProjects.size()])); + } + } + private void updateEnablement() { + boolean complete; + + if (file.length() == 0) { + setMessage(null); + complete = false; + } else { + File f = new File(file); + if (f.isDirectory()) { + setMessage(Policy.bind("ExportProjectSetMainPage.You_have_specified_a_folder_5"), ERROR); //$NON-NLS-1$ + complete = false; + } else { + complete = true; + } + } + if (complete) { + setMessage(null); + } + setPageComplete(complete); + } + + public String getFileName() { + return file; + } + public void setFileName(String file) { + if (file != null) { + this.file = file; + } + } + + public IProject[] getSelectedProjects() { + return (IProject[])selectedProjects.toArray(new IProject[selectedProjects.size()]); + } + public void setSelectedProjects(IProject[] selectedProjects) { + this.selectedProjects.addAll(Arrays.asList(selectedProjects)); + } +} diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ImportProjectSetMainPage.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ImportProjectSetMainPage.java new file mode 100644 index 000000000..fbdfaac67 --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ImportProjectSetMainPage.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * 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.ui; + +import java.io.File; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; + +public class ImportProjectSetMainPage extends TeamWizardPage { + Text fileText; + String file = ""; //$NON-NLS-1$ + Button browseButton; + + public ImportProjectSetMainPage(String pageName, String title, ImageDescriptor titleImage) { + super(pageName, title, titleImage); + } + + /* + * @see IDialogPage#createControl(Composite) + */ + public void createControl(Composite parent) { + Composite composite = createComposite(parent, 1); + initializeDialogUnits(composite); + + createLabel(composite, Policy.bind("ImportProjectSetMainPage.Project_Set_File_Name__2")); //$NON-NLS-1$ + + Composite inner = new Composite(composite, SWT.NULL); + inner.setLayoutData(new GridData(GridData.FILL_BOTH)); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + layout.marginHeight = 0; + layout.marginWidth = 0; + inner.setLayout(layout); + + fileText = createTextField(inner); + if (file != null) fileText.setText(file); + fileText.addListener(SWT.Modify, new Listener() { + public void handleEvent(Event event) { + file = fileText.getText(); + updateEnablement(); + } + }); + + browseButton = new Button(inner, SWT.PUSH); + browseButton.setText(Policy.bind("ImportProjectSetMainPage.Browse_3")); //$NON-NLS-1$ + GridData data = new GridData(); + data.horizontalAlignment = GridData.FILL; + data.heightHint = convertVerticalDLUsToPixels(IDialogConstants.BUTTON_HEIGHT); + int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); + data.widthHint = Math.max(widthHint, browseButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x); + browseButton.setLayoutData(data); + browseButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + FileDialog d = new FileDialog(getShell()); + d.setFilterExtensions(new String[] {Policy.bind("ImportProjectSetMainPage.*.psf_1")}); //$NON-NLS-1$ + d.setFilterNames(new String[] {Policy.bind("ImportProjectSetMainPage.Project_Set_Files_2")}); //$NON-NLS-1$ + String f = d.open(); + if (f != null) { + fileText.setText(f); + file = f; + } + } + }); + + setControl(composite); + updateEnablement(); + } + + private void updateEnablement() { + boolean complete; + + if (file.length() == 0) { + setMessage(null); + complete = false; + } else { + // See if the file exists + File f = new File(file); + if (!f.exists()) { + setMessage(Policy.bind("ImportProjectSetMainPage.The_specified_file_does_not_exist_4"), ERROR); //$NON-NLS-1$ + complete = false; + } else if (f.isDirectory()) { + setMessage(Policy.bind("ImportProjectSetMainPage.You_have_specified_a_folder_5"), ERROR); //$NON-NLS-1$ + complete = false; + } else { + complete = true; + } + } + if (complete) { + setMessage(null); + } + setPageComplete(complete); + } + + public String getFileName() { + return file; + } + public void setFileName(String file) { + if (file != null) { + this.file = file; + } + } +}
\ No newline at end of file diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ProjectSetContentHandler.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ProjectSetContentHandler.java new file mode 100644 index 000000000..308680152 --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ProjectSetContentHandler.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * 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.ui; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +public class ProjectSetContentHandler extends DefaultHandler { + boolean inPsf = false; + boolean inProvider = false; + boolean inProject = false; + Map map; + String id; + List references; + boolean isVersionOne = false; + + /** + * @see ContentHandler#startElement(String, String, String, Attributes) + */ + public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { + if (localName.equals("psf")) { //$NON-NLS-1$ + map = new HashMap(); + inPsf = true; + String version = atts.getValue("version"); //$NON-NLS-1$ + isVersionOne = version.equals("1.0"); //$NON-NLS-1$ + return; + } + if (isVersionOne) return; + if (localName.equals("provider")) { //$NON-NLS-1$ + if (!inPsf) throw new SAXException(Policy.bind("ProjectSetContentHandler.Element_provider_must_be_contained_in_element_psf_4")); //$NON-NLS-1$ + inProvider = true; + id = atts.getValue("id"); //$NON-NLS-1$ + references = new ArrayList(); + return; + } + if (localName.equals("project")) { //$NON-NLS-1$ + if (!inProvider) throw new SAXException(Policy.bind("ProjectSetContentHandler.Element_project_must_be_contained_in_element_provider_7")); //$NON-NLS-1$ + inProject = true; + String reference = atts.getValue("reference"); //$NON-NLS-1$ + references.add(reference); + return; + } + } + + /** + * @see ContentHandler#endElement(String, String, String) + */ + public void endElement(String namespaceURI, String localName, String qName) throws SAXException { + if (localName.equals("psf")) { //$NON-NLS-1$ + inPsf = false; + return; + } + if (isVersionOne) return; + if (localName.equals("provider")) { //$NON-NLS-1$ + map.put(id, references); + references = null; + inProvider = false; + return; + } + if (localName.equals("project")) { //$NON-NLS-1$ + inProject = false; + return; + } + } + + public Map getReferences() { + return map; + } + + public boolean isVersionOne() { + return isVersionOne; + } +} diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ProjectSetExportWizard.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ProjectSetExportWizard.java new file mode 100644 index 000000000..2ad409dbb --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ProjectSetExportWizard.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * 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.ui; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.team.core.IProjectSetSerializer; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.Team; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.TeamPlugin; +import org.eclipse.ui.IExportWizard; +import org.eclipse.ui.IWorkbench; + +public class ProjectSetExportWizard extends Wizard implements IExportWizard { + ExportProjectSetMainPage mainPage; + IStructuredSelection selection; + + public ProjectSetExportWizard() { + setNeedsProgressMonitor(true); + setWindowTitle(Policy.bind("ProjectSetExportWizard.Project_Set_1")); //$NON-NLS-1$ + } + + public void addPages() { + mainPage = new ExportProjectSetMainPage("projectSetMainPage", Policy.bind("ProjectSetExportWizard.Export_a_Project_Set_3"), null); //$NON-NLS-1$ //$NON-NLS-2$ + IProject[] projects = (IProject[])selection.toList().toArray(new IProject[0]); + mainPage.setSelectedProjects(projects); + mainPage.setFileName(ProjectSetImportWizard.lastFile); + addPage(mainPage); + } + public boolean performFinish() { + final boolean[] result = new boolean[] {false}; + try { + getContainer().run(false, false, new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException { + + String filename = mainPage.getFileName(); + ProjectSetImportWizard.lastFile = filename; + File file = new File(filename); + File parentFile = file.getParentFile(); + if (!parentFile.exists()) { + boolean r = MessageDialog.openQuestion(getShell(), Policy.bind("ProjectSetExportWizard.Question_4"), Policy.bind("ProjectSetExportWizard.Target_directory_does_not_exist._Would_you_like_to_create_it__5")); //$NON-NLS-1$ //$NON-NLS-2$ + if (!r) { + result[0] = false; + return; + } + r = parentFile.mkdirs(); + if (!r) { + MessageDialog.openError(getShell(), Policy.bind("ProjectSetExportWizard.Export_Problems_6"), Policy.bind("ProjectSetExportWizard.An_error_occurred_creating_the_target_directory_7")); //$NON-NLS-1$ //$NON-NLS-2$ + result[0] = false; + return; + } + } + if (file.exists() && file.isFile()) { + boolean r = MessageDialog.openQuestion(getShell(), Policy.bind("ProjectSetExportWizard.Question_8"), Policy.bind("ProjectSetExportWizard.Target_already_exists._Would_you_like_to_overwrite_it__9")); //$NON-NLS-1$ //$NON-NLS-2$ + if (!r) { + result[0] = false; + return; + } + } + OutputStreamWriter writer = null; + try { + writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); //$NON-NLS-1$ + + writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); //$NON-NLS-1$ + writer.write("<psf version=\"2.0\">\n"); //$NON-NLS-1$ + IProject[] projects = mainPage.getSelectedProjects(); + + // Hash the projects by provider + Map map = new HashMap(); + for (int i = 0; i < projects.length; i++) { + IProject project = projects[i]; + RepositoryProvider provider = RepositoryProvider.getProvider(project); + String id = provider.getID(); + List list = (List)map.get(id); + if (list == null) { + list = new ArrayList(); + map.put(id, list); + } + list.add(project); + } + + // For each provider id, do the writing + Shell shell = getShell(); + Iterator it = map.keySet().iterator(); + monitor.beginTask(null, 1000 * map.keySet().size()); + while (it.hasNext()) { + String id = (String)it.next(); + writer.write("\t<provider id=\""); //$NON-NLS-1$ + writer.write(id); + writer.write("\">\n"); //$NON-NLS-1$ + List list = (List)map.get(id); + IProject[] projectArray = (IProject[])list.toArray(new IProject[list.size()]); + IProjectSetSerializer serializer = Team.getProjectSetSerializer(id); + if (serializer != null) { + String[] references = serializer.asReference(projectArray, shell, new SubProgressMonitor(monitor, 1000)); + for (int i = 0; i < references.length; i++) { + writer.write("\t\t<project reference=\""); //$NON-NLS-1$ + writer.write(references[i]); + writer.write("\"/>\n"); //$NON-NLS-1$ + } + } + writer.write("\t</provider>\n"); //$NON-NLS-1$ + } + writer.write("</psf>\n"); //$NON-NLS-1$ + result[0] = true; + } catch (IOException e) { + throw new InvocationTargetException(e); + } catch (TeamException e) { + throw new InvocationTargetException(e); + } finally { + monitor.done(); + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + throw new InvocationTargetException(e); + } + } + } + } + }); + } catch (InterruptedException e) { + return true; + } catch (InvocationTargetException e) { + Throwable target = e.getTargetException(); + if (target instanceof TeamException) { + ErrorDialog.openError(getShell(), null, null, ((TeamException)target).getStatus()); + return false; + } + if (target instanceof RuntimeException) { + throw (RuntimeException)target; + } + if (target instanceof Error) { + throw (Error)target; + } + } + return result[0]; + } + + public void init(IWorkbench workbench, IStructuredSelection selection) { + this.selection = selection; + } +} diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ProjectSetImportWizard.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ProjectSetImportWizard.java new file mode 100644 index 000000000..e10ca8886 --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ProjectSetImportWizard.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * 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.ui; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.xerces.parsers.SAXParser; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.team.core.IProjectSetSerializer; +import org.eclipse.team.core.Team; +import org.eclipse.team.core.TeamException; +import org.eclipse.ui.IImportWizard; +import org.eclipse.ui.IWorkbench; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class ProjectSetImportWizard extends Wizard implements IImportWizard { + ImportProjectSetMainPage mainPage; + public static String lastFile; + + public ProjectSetImportWizard() { + setNeedsProgressMonitor(true); + setWindowTitle(Policy.bind("ProjectSetImportWizard.Project_Set_1")); //$NON-NLS-1$ + } + + public void addPages() { + mainPage = new ImportProjectSetMainPage("projectSetMainPage", Policy.bind("ProjectSetImportWizard.Import_a_Project_Set_3"), null); //$NON-NLS-1$ //$NON-NLS-2$ + mainPage.setFileName(lastFile); + addPage(mainPage); + } + public boolean performFinish() { + final boolean[] result = new boolean[] {false}; + try { + getContainer().run(false, false, new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException { + InputStreamReader reader = null; + try { + String filename = mainPage.getFileName(); + lastFile = filename; + reader = new InputStreamReader(new FileInputStream(filename), "UTF-8"); //$NON-NLS-1$ + + SAXParser parser = new SAXParser(); + ProjectSetContentHandler handler = new ProjectSetContentHandler(); + parser.setContentHandler(handler); + InputSource source = new InputSource(reader); + parser.parse(source); + + Map map = handler.getReferences(); + if (map.size() == 0 && handler.isVersionOne) { + IProjectSetSerializer serializer = Team.getProjectSetSerializer("versionOneSerializer"); //$NON-NLS-1$ + if (serializer != null) { + serializer.addToWorkspace(new String[0], filename, getShell(), monitor); + } + } else { + Iterator it = map.keySet().iterator(); + while (it.hasNext()) { + String id = (String)it.next(); + List references = (List)map.get(id); + IProjectSetSerializer serializer = Team.getProjectSetSerializer(id); + if (serializer != null) { + serializer.addToWorkspace((String[])references.toArray(new String[references.size()]), filename, getShell(), monitor); + } + } + } + result[0] = true; + } catch (IOException e) { + throw new InvocationTargetException(e); + } catch (SAXException e) { + throw new InvocationTargetException(e); + } catch (TeamException e) { + throw new InvocationTargetException(e); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + throw new InvocationTargetException(e); + } + } + } + } + }); + } catch (InterruptedException e) { + return true; + } catch (InvocationTargetException e) { + Throwable target = e.getTargetException(); + if (target instanceof TeamException) { + ErrorDialog.openError(getShell(), null, null, ((TeamException)target).getStatus()); + return false; + } + if (target instanceof RuntimeException) { + throw (RuntimeException)target; + } + if (target instanceof Error) { + throw (Error)target; + } + } + return result[0]; + } + + public void init(IWorkbench workbench, IStructuredSelection selection) { + } +} diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamWizardPage.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamWizardPage.java new file mode 100644 index 000000000..7eb5198f5 --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamWizardPage.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * 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.ui; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public abstract class TeamWizardPage extends WizardPage { + /** + * CVSWizardPage constructor comment. + * @param pageName the name of the page + */ + public TeamWizardPage(String pageName) { + super(pageName); + } + /** + * CVSWizardPage constructor comment. + * @param pageName the name of the page + * @param title the title of the page + * @param titleImage the image for the page + */ + public TeamWizardPage(String pageName, String title, ImageDescriptor titleImage) { + super(pageName, title, titleImage); + } + /** + * Creates composite control and sets the default layout data. + * + * @param parent the parent of the new composite + * @param numColumns the number of columns for the new composite + * @return the newly-created coposite + */ + protected Composite createComposite(Composite parent, int numColumns) { + Composite composite = new Composite(parent, SWT.NULL); + + // GridLayout + GridLayout layout = new GridLayout(); + layout.numColumns = numColumns; + composite.setLayout(layout); + + // GridData + GridData data = new GridData(); + data.verticalAlignment = GridData.FILL; + data.horizontalAlignment = GridData.FILL; + composite.setLayoutData(data); + return composite; + } + /** + * Utility method that creates a label instance + * and sets the default layout data. + * + * @param parent the parent for the new label + * @param text the text for the new label + * @return the new label + */ + protected Label createLabel(Composite parent, String text) { + return createIndentedLabel(parent, text, 0); + } + /** + * Utility method that creates a label instance indented by the specified + * number of pixels and sets the default layout data. + * + * @param parent the parent for the new label + * @param text the text for the new label + * @param indent the indent in pixels, or 0 for none + * @return the new label + */ + protected Label createIndentedLabel(Composite parent, String text, int indent) { + Label label = new Label(parent, SWT.LEFT); + label.setText(text); + GridData data = new GridData(); + data.horizontalSpan = 1; + data.horizontalAlignment = GridData.FILL; + data.horizontalIndent = indent; + label.setLayoutData(data); + return label; + } + /** + * Create a text field specific for this application + * + * @param parent the parent of the new text field + * @return the new text field + */ + protected Text createTextField(Composite parent) { + Text text = new Text(parent, SWT.SINGLE | SWT.BORDER); + GridData data = new GridData(GridData.FILL_HORIZONTAL); + data.verticalAlignment = GridData.CENTER; + data.grabExcessVerticalSpace = false; + data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; + text.setLayoutData(data); + return text; + } +} diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties new file mode 100644 index 000000000..d83c66af5 --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties @@ -0,0 +1,138 @@ +############################################### +# Message catalog for org.eclipse.team.ui +############################################### + +CatchupReleaseViewer.expand=&Expand All +CatchupReleaseViewer.ignoreWhiteSpace=&Ignore White Space +CatchupReleaseViewer.refreshAction=&Refresh From Repository +CatchupReleaseViewer.showIncomingAction=Show Incoming +CatchupReleaseViewer.showInNavigator=&Show in Navigator +CatchupReleaseViewer.showOnlyConflictsAction=Show Only Conflicts +CatchupReleaseViewer.showOutgoingAction=Show Outgoing + +CheckInAction.checkin=Check In +CheckInAction.checkingIn=Checking In... +CheckOutAction.checkingOut=Checking Out... +CheckOutAction.checkout=Check Out + +ConfigureProjectAction.configureProject=Configure Project +ConfigureProjectWizard.configureProject=Share Project +ConfigureProjectWizard.description=Select the repository plug-in that will be used to share the selected project. +ConfigureProjectWizard.title=Share Project +ConfigureProjectWizardMainPage.selectRepository=Select a repository type: + +ConfigurationWizard.exceptionCreatingWizard=Exception creating wizard. + +DeconfigureProjectAction.deconfigureProject=Deconfigure Project + +DeleteAction.delete=Delete +DeleteAction.deleting=Deleting... +DeleteAction.promptMessage=Are you sure you want to delete the resource(s) from the repository and from the local workspace? +DeleteAction.promptTitle=Confirm Repository Delete + +IgnorePreferencePage.add=&Add... +IgnorePreferencePage.description=You may wish to exclude certain resources from version control.\n\ + Resources whose names match any enabled pattern will not be released.\n\ + The wildcard characters '*' and '?' are permitted.\n\ + These settings will not affect resources already under version control.\n\ + Use this page to specify a list of resource name patterns to ignore. +IgnorePreferencePage.enterPatternLong=Please enter a pattern: +IgnorePreferencePage.enterPatternShort=Enter Ignore Pattern +IgnorePreferencePage.ignorePatterns=&Ignore Patterns: +IgnorePreferencePage.patternExistsLong=The entered pattern already exists. +IgnorePreferencePage.patternExistsShort=Pattern Already Exists +IgnorePreferencePage.remove=&Remove + +MergeResource.commonFile=Common file: {0} +MergeResource.noCommonFile=No common file +MergeResource.noRepositoryFile=No repository file +MergeResource.repositoryFile=Repository file: {0} +MergeResource.workspaceFile=Workspace file: {0} + +nothingToSynchronize=Nothing to Synchronize +simpleInternal=Internal error + +SyncCompareInput.nothingText=Workspace resources are the same as those released in the stream. +SyncCompareInput.refresh=Error During Refresh with Repository +SyncCompareInput.synchronize=Synchronize +SyncCompareInput.taskTitle=Synchronizing with Repository... + +SyncSet.conflicts={0} conflicts, +SyncSet.incomings={0} incoming change(s), +SyncSet.noConflicts=No conflicts, +SyncSet.noIncomings=no incoming changes, +SyncSet.noOutgoings=no outgoing changes. +SyncSet.outgoings={0} outgoing change(s). + +SyncView.freeModeAction=Incoming/Outgoing Mode +SyncView.freeModeTitle=Synchronize - Incoming/Outgoing Mode +SyncView.freeModeToolTip=Incoming/Outgoing Mode +SyncView.incomingModeAction=Incoming Mode +SyncView.incomingModeTitle=Synchronize - Incoming Mode +SyncView.incomingModeToolTip=Incoming Mode +SyncView.outgoingModeAction=Outgoing Mode +SyncView.outgoingModeTitle=Synchronize - Outgoing Mode +SyncView.outgoingModeToolTip=Outgoing Mode +SyncView.same=Workspace resources are the same as those released in the repository. +SyncView.text=Synchronize resources with their team provider to display them here. +SyncView.unableSynchronize=Unable to Synchronize +SyncView.saveTitle=Save Resource +SyncView.saveMessage=Resource has been modified. Save changes? +SyncView.errorSaving=Error while saving modified resources + +TeamAction.internal=Internal error occured. +TeamFile.saveChanges=Unable to save changes to file: {0} + +TextPreferencePage.add=&Add... +TextPreferencePage.binary=Binary +TextPreferencePage.change=&Change +TextPreferencePage.contents=Contents +TextPreferencePage.description=&File extensions with known content: +TextPreferencePage.enterExtensionLong=Please enter a file extension: +TextPreferencePage.enterExtensionShort=Enter File Extension +TextPreferencePage.extension=Extension +TextPreferencePage.extensionExistsLong=The entered extension already exists. +TextPreferencePage.extensionExistsShort=Extension Already Exists +TextPreferencePage.remove=&Remove +TextPreferencePage.text=Text + +UndoCheckOutAction.undoCheckout=Undo Check Out +UndoCheckOutAction.undoing=Undoing Check Out... + +UnManageAction.unmanage=Unmanage +UnManageAction.unmanaging=Unmanaging... + +UpdateAction.title=Get +UpdateAction.updating=Getting... +TextPreferencePage.columnExtension=extension +TextPreferencePage.columnContents=contents + +ExportProjectSetMainPage.Select_the_projects_to_include_in_the_project_set__2=Select the projects to include in the team project set: +ExportProjectSetMainPage.Project_Set_File_Name__3=Team project set file name: +ExportProjectSetMainPage.Browse_4=Browse... +ExportProjectSetMainPage.You_have_specified_a_folder_5=You have specified a folder + +ImportProjectSetMainPage.Project_Set_File_Name__2=Team project set file name: +ImportProjectSetMainPage.Browse_3=Browse... +ImportProjectSetMainPage.The_specified_file_does_not_exist_4=The specified file does not exist +ImportProjectSetMainPage.You_have_specified_a_folder_5=You have specified a folder + +ProjectSetContentHandler.Element_provider_must_be_contained_in_element_psf_4=Element provider must be contained in element psf +ProjectSetContentHandler.Element_project_must_be_contained_in_element_provider_7=Element project must be contained in element provider + +ProjectSetExportWizard.Project_Set_1=Team Project Set +ProjectSetExportWizard.Export_a_Project_Set_3=Export a Team Project Set +ProjectSetExportWizard.Question_4=Question +ProjectSetExportWizard.Target_directory_does_not_exist._Would_you_like_to_create_it__5=Target directory does not exist. Would you like to create it? +ProjectSetExportWizard.Export_Problems_6=Export Problems +ProjectSetExportWizard.An_error_occurred_creating_the_target_directory_7=An error occurred creating the target directory +ProjectSetExportWizard.Question_8=Question +ProjectSetExportWizard.Target_already_exists._Would_you_like_to_overwrite_it__9=Target already exists. Would you like to overwrite it? +ProjectSetImportWizard.Project_Set_1=Team Project Set +ProjectSetImportWizard.Import_a_Project_Set_3=Import a Team Project Set + +ExportProjectSetMainPage.*.psf_2=*.psf +ExportProjectSetMainPage.Project_Set_Files_3=Project Set Files + +ImportProjectSetMainPage.*.psf_1=*.psf +ImportProjectSetMainPage.Project_Set_Files_2=Project Set Files diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncCompareInput.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncCompareInput.java new file mode 100644 index 000000000..f9b606963 --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncCompareInput.java @@ -0,0 +1,422 @@ +package org.eclipse.team.ui.sync; + +/* + * (c) Copyright IBM Corp. 2000, 2002. + * All Rights Reserved. + */ + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.CompareEditorInput; +import org.eclipse.compare.structuremergeviewer.DiffContainer; +import org.eclipse.compare.structuremergeviewer.DiffNode; +import org.eclipse.compare.structuremergeviewer.ICompareInput; +import org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener; +import org.eclipse.compare.structuremergeviewer.IDiffContainer; +import org.eclipse.compare.structuremergeviewer.IDiffElement; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRunnable; +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.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.sync.ILocalSyncElement; +import org.eclipse.team.core.sync.IRemoteSyncElement; +import org.eclipse.team.internal.ui.Policy; +import org.eclipse.team.ui.TeamUIPlugin; +import org.eclipse.ui.IViewSite; + +/** + * <b>Note:</b> This class/interface is part of an interim API that is still under + * development and expected to change significantly before reaching stability. + * It is being made available at this early stage to solicit feedback from pioneering + * adopters on the understanding that any code that uses this API will almost + * certainly be broken (repeatedly) as the API evolves. + * + * Performs a catchup or release operation on an array of resources. + */ +public abstract class SyncCompareInput extends CompareEditorInput { + private IRemoteSyncElement[] trees; + private CatchupReleaseViewer catchupReleaseViewer; + private DiffNode diffRoot; + private Shell shell; + private IViewSite viewSite; + + private ICompareInputChangeListener listener = new ICompareInputChangeListener() { + public void compareInputChanged(ICompareInput source) { + SyncCompareInput.this.compareInputChanged(source); + } + }; + + /** + * Subclasses may override but must call super. + */ + protected void compareInputChanged(ICompareInput source) { + catchupReleaseViewer.update(source, new String[] {CatchupReleaseViewer.PROP_KIND}); + updateStatusLine(); + } + + /** + * Creates a new catchup or release operation. + */ + public SyncCompareInput() { + super(new CompareConfiguration()); + } + + protected abstract IRemoteSyncElement[] createSyncElements(IProgressMonitor monitor) throws TeamException; + + /* + * @see CompareEditorInput#createContents + */ + public Control createContents(Composite parent) { + Control result = super.createContents(parent); + initialSelectionAndExpansionState(); + return result; + } + + /** + * Subclasses must create and return a new CatchupReleaseViewer, and set the viewer + * using setViewer(). + */ + public abstract Viewer createDiffViewer(Composite parent); + + /** + * Returns the root node of the diff tree. + */ + public DiffNode getDiffRoot() { + return diffRoot; + } + + /** + * Returns the first diff element that is still unresolved in the + * subtree rooted at the given root element. + * Returns null if everything is resolved. + */ + private IDiffElement getFirstChange(IDiffElement root) { + if (root instanceof ITeamNode) { + ITeamNode node = (ITeamNode)root; + if (node instanceof TeamFile) { + return node; + } + } + if (root instanceof IDiffContainer) { + IDiffElement[] children = ((IDiffContainer)root).getChildren(); + IDiffElement result = null; + for (int i = 0; i < children.length; i++) { + result = getFirstChange(children[i]); + if (result != null) { + return result; + } + } + } + return null; + } + + protected Shell getShell() { + return shell; + } + + /** + * Returns the name of this operation. + * It is dipslayed in the CompareEditor's title bar. + */ + public String getTitle() { + return Policy.bind("SyncCompareInput.synchronize"); //$NON-NLS-1$ + } + + /** + * Returns the compare viewer; + */ + public CatchupReleaseViewer getViewer() { + return catchupReleaseViewer; + } + + /** + * Returns the view site, or null if this is a merge. + */ + public IViewSite getViewSite() { + return viewSite; + } + + /** + * Returns true if the model has incoming or conflicting changes. + */ + boolean hasIncomingChanges() { + if (diffRoot == null) { + return false; + } + SyncSet set = new SyncSet(new StructuredSelection(diffRoot.getChildren())); + return set.hasIncomingChanges() || set.hasConflicts(); + } + + /** + * Set an appropriate initial selection and expansion state. + */ + private void initialSelectionAndExpansionState() { + // Select the next change + IDiffElement next = getFirstChange(diffRoot); + if (next != null) { + catchupReleaseViewer.setSelection(new StructuredSelection(next), true); + } else { + catchupReleaseViewer.collapseAll(); + catchupReleaseViewer.setSelection(new StructuredSelection()); + } + } + + /** + * Performs a compare on the given selection. + * This method is called before the CompareEditor has been opened. + * If the result of the diff is empty (or an error has occured) + * no CompareEditor is opened but an Alert is shown. + */ + public Object prepareInput(final IProgressMonitor pm) throws InterruptedException, InvocationTargetException { + if (pm.isCanceled()) { + throw new InterruptedException(); + } + + try { + pm.beginTask(Policy.bind("SyncCompareInput.taskTitle"), 100); //$NON-NLS-1$ + + // Estimate 70% of the time is creating the sync elements + this.trees = createSyncElements(Policy.subMonitorFor(pm, 70)); + setMessage(null); + if (trees.length == 0) { + return null; + } + final InterruptedException[] exceptions = new InterruptedException[1]; + + IWorkspaceRunnable runnable = new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + // collect changes and build the diff tree + diffRoot = new DiffNode(0); + try { + doServerDelta(monitor); + } catch (InterruptedException e) { + exceptions[0] = e; + } + } + }; + if (pm.isCanceled()) { + throw new InterruptedException(); + } + // Estimate 30% of the time is doing the server delta + ResourcesPlugin.getWorkspace().run(runnable, Policy.subMonitorFor(pm, 30)); + if (exceptions[0] != null) throw exceptions[0]; + if (pm.isCanceled()) { + throw new InterruptedException(); + } + + if (!diffRoot.hasChildren()) { + diffRoot = null; + } + + updateStatusLine(); + + return diffRoot; + } catch (CoreException e) { + throw new InvocationTargetException(e); + } catch (TeamException e) { + throw new InvocationTargetException(e); + } + } + + void doServerDelta(IProgressMonitor pm) throws InterruptedException { + pm.beginTask(null, trees.length * 1000); + pm.setTaskName(Policy.bind("SyncCompareInput.taskTitle")); //$NON-NLS-1$ + for (int i = 0; i < trees.length; i++) { + IRemoteSyncElement tree = trees[i]; + IProgressMonitor monitor = Policy.subMonitorFor(pm, 1000); + monitor.beginTask(null, 1000); + IDiffElement localRoot = collectResourceChanges(null, tree, monitor); + monitor.done(); + makeParents(localRoot); + } + } + + /* + * This method expects to be past a monitor that has already had it's beginTask invoked + * and has enough ticks to allow 1 unit of work per resource in the tree and an additional + * unit for each folder. + */ + IDiffElement collectResourceChanges(IDiffContainer parent, IRemoteSyncElement tree, IProgressMonitor pm) { + int type = tree.getSyncKind(getSyncGranularity(), Policy.subMonitorFor(pm, 1)); + MergeResource mergeResource = new MergeResource(tree); + + if (tree.isContainer()) { + IDiffContainer element = new ChangedTeamContainer(parent, mergeResource, type); + try { + ILocalSyncElement[] children = tree.members(Policy.subMonitorFor(pm, 1)); + for (int i = 0; i < children.length; i++) { + collectResourceChanges(element, (IRemoteSyncElement)children[i], pm); + } + } catch (TeamException e) { + TeamUIPlugin.log(e.getStatus()); + } + return element; + } else { + TeamFile file = new TeamFile(parent, mergeResource, type, shell); + file.addCompareInputChangeListener(listener); + return file; + } + } + + protected abstract int getSyncGranularity(); + + /** + * Builds a DiffFolder tree under the given root for the given resource. + */ + private DiffContainer buildPath(DiffContainer root, IContainer resource) { + DiffContainer parent = root; + if (resource.getType() == IResource.ROOT) { + return root; + } + if (resource.getType() != IResource.PROJECT) { + parent = buildPath(root, resource.getParent()); + } + + DiffContainer c = (DiffContainer)parent.findChild(resource.getName()); + if (c == null) { + c = new UnchangedTeamContainer(parent, resource); + } + return c; + } + + void makeParents(IDiffElement element) { + IContainer parent = ((ITeamNode)element).getResource().getParent(); + DiffContainer container = buildPath(diffRoot, parent); + container.add(element); + } + + /** + * Performs a refresh, with progress and cancelation. + */ + public void refresh() { + final Object[] input = new Object[1]; + IRunnableWithProgress op = new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + input[0] = prepareInput(monitor); + } + }; + try { + run(op, Policy.bind("SyncCompareInput.refresh")); //$NON-NLS-1$ + } catch (InterruptedException e) { + return; + } + + catchupReleaseViewer.setInput(input[0]); + if (input[0] == null) { + MessageDialog.openInformation(shell, Policy.bind("nothingToSynchronize"), Policy.bind("SyncCompareInput.nothingText")); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + protected void run(IRunnableWithProgress op, String problemMessage) throws InterruptedException { + ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell); + try { + dialog.run(true, true, op); + } catch (InvocationTargetException e) { + Throwable throwable = e.getTargetException(); + IStatus error = null; + if (throwable instanceof CoreException) { + error = ((CoreException)throwable).getStatus(); + } else { + error = new Status(IStatus.ERROR, TeamUIPlugin.ID, 1, Policy.bind("simpleInternal") , throwable); //$NON-NLS-1$ + } + ErrorDialog.openError(shell, problemMessage, error.getMessage(), error); + TeamUIPlugin.log(error); + } + } + + public void setViewSite(IViewSite viewSite) { + this.viewSite = viewSite; + this.shell = viewSite.getShell(); + } + + public void setViewer(CatchupReleaseViewer viewer) { + this.catchupReleaseViewer = viewer; + } + + /** + * Updates the status line. + */ + protected void updateStatusLine() { + if (viewSite != null && !shell.isDisposed()) { + Runnable update = new Runnable() { + public void run() { + if (!shell.isDisposed()) { + IStatusLineManager statusLine = viewSite.getActionBars().getStatusLineManager(); + if (diffRoot == null) { + statusLine.setMessage(null); + statusLine.setErrorMessage(null); + return; + } + SyncSet set = new SyncSet(new StructuredSelection(diffRoot.getChildren())); + if (set.hasConflicts()) { + statusLine.setMessage(null); + statusLine.setErrorMessage(set.getStatusLineMessage()); + } else { + statusLine.setErrorMessage(null); + statusLine.setMessage(set.getStatusLineMessage()); + } + viewSite.getActionBars().updateActionBars(); + } + } + }; + // Post or run the update + if (shell.getDisplay() != Display.getCurrent()) { + shell.getDisplay().asyncExec(update); + } else { + update.run(); + } + } + } + + public boolean saveIfNecessary() { + if (! isSaveNeeded()) return true; + + final boolean[] result = new boolean[] { false }; + getShell().getDisplay().syncExec(new Runnable() { + public void run() { + try { + result[0] = MessageDialog.openQuestion(getShell(), Policy.bind("SyncView.saveTitle"), + Policy.bind("SyncView.saveMessage")); + if (result[0]) { + ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + saveChanges(monitor); + } + }, new NullProgressMonitor()); + } + } catch (CoreException e) { + IStatus status = e.getStatus(); + ErrorDialog.openError(getShell(), status.getMessage(), Policy.bind("SyncView.errorSaving"), status); + result[0] = false; + } + } + }); + return result[0]; + } + + /* + * HACK until Compare fixes dirtyness PR#14378 + */ + public void saveChanges(IProgressMonitor monitor) throws CoreException { + super.saveChanges(monitor); + setDirty(false); + } +} diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncView.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncView.java new file mode 100644 index 000000000..a7fb4ba8c --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/sync/SyncView.java @@ -0,0 +1,392 @@ +package org.eclipse.team.ui.sync; + +/* + * (c) Copyright IBM Corp. 2000, 2002. + * All Rights Reserved. + */ + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.compare.structuremergeviewer.DiffNode; +import org.eclipse.compare.structuremergeviewer.IDiffElement; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.internal.ui.Policy; +import org.eclipse.team.internal.ui.UIConstants; +import org.eclipse.team.ui.TeamUIPlugin; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IPartListener; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.part.ViewPart; + +/** + * <b>Note:</b> This class/interface is part of an interim API that is still under + * development and expected to change significantly before reaching stability. + * It is being made available at this early stage to solicit feedback from pioneering + * adopters on the understanding that any code that uses this API will almost + * certainly be broken (repeatedly) as the API evolves. + * + * This class provides a view for performing synchronizations + * between the local workspace and a repository. + */ +public class SyncView extends ViewPart { + public static final String VIEW_ID = "org.eclipse.team.ui.sync.SyncView"; //$NON-NLS-1$ + private SyncCompareInput input; + private TreeViewer viewer; + private Composite top; + + // The possible sync modes + public static final int SYNC_NONE = 0; + public static final int SYNC_INCOMING = 1; + public static final int SYNC_OUTGOING = 2; + public static final int SYNC_BOTH = 3; + public static final int SYNC_MERGE = 4; + + // Titles cached for efficiency + private final String CATCHUP_TITLE = Policy.bind("SyncView.incomingModeTitle"); //$NON-NLS-1$ + private final String RELEASE_TITLE = Policy.bind("SyncView.outgoingModeTitle"); //$NON-NLS-1$ + private final String FREE_TITLE = Policy.bind("SyncView.freeModeTitle"); //$NON-NLS-1$ + + private int currentSyncMode = SYNC_NONE; + + /** + * Action for toggling the sync mode. + */ + class SyncModeAction extends Action { + // The sync mode that this action enables + private int syncMode; + public SyncModeAction(String title, ImageDescriptor image, int mode) { + super(title, image); + this.syncMode = mode; + } + public void run() { + SyncView.this.setSyncMode(syncMode); + } + } + + private SyncModeAction incomingMode; + private SyncModeAction outgoingMode; + private SyncModeAction freeMode; + + private class PartListener implements IPartListener { + public void partActivated(IWorkbenchPart part) { + } + public void partBroughtToTop(IWorkbenchPart part) { + } + public void partClosed(IWorkbenchPart part) { + } + public void partDeactivated(IWorkbenchPart part) { + if (part == SyncView.this && input != null) { + input.saveIfNecessary(); + } + } + public void partOpened(IWorkbenchPart part) { + } + } + + private IPartListener partListener; + + /** + * Creates a new view. + */ + public SyncView() { + super(); + } + + /* + * @see IWorkbenchPart#createPartControl + */ + public void createPartControl(Composite parent) { + top = new Composite(parent, SWT.NONE); + + //XXX Set the control data to be this part, so the compare + //frames that will eventually live in this widget hierarchy + //have some way to access the action bars for hooking global + //actions. See corresponding XXX comment in CompareEditor#findActionBars + top.setData(this); + + GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + top.setLayout(layout); + top.setLayoutData(new GridData(GridData.FILL_BOTH)); + + showDefaultContents(); + + initializeSyncModes(); + // add part listener + partListener = new PartListener(); + getViewSite().getWorkbenchWindow().getPartService().addPartListener(partListener); + } + + public void dispose() { + // remove part listener + if (partListener != null) { + getViewSite().getWorkbenchWindow().getPartService().removePartListener(partListener); + partListener = null; + } + super.dispose(); + } + + /** + * Makes the sync view visible in the active perspective. If there + * isn't a sync view registered <code>null</code> is returned. + * Otherwise the opened view part is returned. + */ + public static SyncView findInActivePerspective() { + try { + IViewPart part = TeamUIPlugin.getActivePage().findView(VIEW_ID); + if (part == null) { + part = TeamUIPlugin.getActivePage().showView(VIEW_ID); + } + return (SyncView)part; + } catch (PartInitException pe) { + return null; + } + } + + /** + * Sets up the sync modes and the actions for switching between them. + */ + private void initializeSyncModes() { + // Create the actions + incomingMode = new SyncModeAction( + Policy.bind("SyncView.incomingModeAction"), //$NON-NLS-1$ + TeamUIPlugin.getPlugin().getImageDescriptor(UIConstants.IMG_SYNC_MODE_CATCHUP), + SYNC_INCOMING); + incomingMode.setToolTipText(Policy.bind("SyncView.incomingModeToolTip")); //$NON-NLS-1$ + incomingMode.setChecked(false); + + outgoingMode = new SyncModeAction( + Policy.bind("SyncView.outgoingModeAction"), //$NON-NLS-1$ + TeamUIPlugin.getPlugin().getImageDescriptor(UIConstants.IMG_SYNC_MODE_RELEASE), + SYNC_OUTGOING); + outgoingMode.setToolTipText(Policy.bind("SyncView.outgoingModeToolTip")); //$NON-NLS-1$ + outgoingMode.setChecked(false); + + freeMode = new SyncModeAction( + Policy.bind("SyncView.freeModeAction"), //$NON-NLS-1$ + TeamUIPlugin.getPlugin().getImageDescriptor(UIConstants.IMG_SYNC_MODE_FREE), + SYNC_BOTH); + freeMode.setToolTipText(Policy.bind("SyncView.freeModeToolTip")); //$NON-NLS-1$ + freeMode.setChecked(false); + } + + private boolean isEmpty(DiffNode node) { + if (node.getKind() != 0) return false; + IDiffElement[] children = node.getChildren(); + for (int i = 0; i < children.length; i++) { + if (!isEmpty(children[i])) return false; + } + return true; + } + private boolean isEmpty(IDiffElement element) { + if (element.getKind() != 0) return false; + if (element instanceof DiffNode) { + IDiffElement[] children = ((DiffNode)element).getChildren(); + for (int i = 0; i < children.length; i++) { + if (!isEmpty(children[i])) return false; + } + } + return true; + } + + /** + * Runs an operation and handles progress and exceptions. Returns true + * if the operation was successful, and false if there were errors or + * the user canceled. + */ + private boolean run(IRunnableWithProgress op) { + ProgressMonitorDialog dialog = new ProgressMonitorDialog(getSite().getShell()); + try { + dialog.run(true, true, op); + return true; + } catch (InvocationTargetException e) { + Throwable throwable = e.getTargetException(); + IStatus error = null; + if (throwable instanceof TeamException) { + error = ((TeamException)throwable).getStatus(); + } else if (throwable instanceof CoreException) { + error = ((CoreException)throwable).getStatus(); + } else { + error = new Status(IStatus.ERROR, TeamUIPlugin.ID, 1, Policy.bind("simpleInternal"), throwable); //$NON-NLS-1$ + } + ErrorDialog.openError(getSite().getShell(), Policy.bind("SyncView.unableSynchronize"), null, error); //$NON-NLS-1$ + TeamUIPlugin.log(error); + } catch (InterruptedException e) { + } + return false; + } + + /** + * Asks the part to take focus within the workbench. + */ + public void setFocus() { + if (top != null && !top.isDisposed()) { + top.setFocus(); + } + } + + /** + * Activates the given sync mode. + */ + void setSyncMode(int mode) { + // Implement radio button behaviour + switch (mode) { + case SYNC_INCOMING: + incomingMode.setChecked(true); + outgoingMode.setChecked(false); + freeMode.setChecked(false); + setTitle(CATCHUP_TITLE); + break; + case SYNC_OUTGOING: + outgoingMode.setChecked(true); + incomingMode.setChecked(false); + freeMode.setChecked(false); + setTitle(RELEASE_TITLE); + break; + case SYNC_BOTH: + freeMode.setChecked(true); + outgoingMode.setChecked(false); + incomingMode.setChecked(false); + setTitle(FREE_TITLE); + break; + } + // Only update actions if there is valid input + if (input != null && input.getDiffRoot() != null && mode != currentSyncMode) { + currentSyncMode = mode; + input.getViewer().syncModeChanged(mode); + updateActions(); + } + } + + /** + * Shows default contents for the view if there is nothing to synchronize. + */ + private void showDefaultContents() { + Label label = new Label(top, SWT.WRAP); + label.setLayoutData(new GridData(GridData.FILL_BOTH)); + label.setText(Policy.bind("SyncView.text")); //$NON-NLS-1$ + } + + /** + * Shows synchronization information for the given resources in the sync view. + */ + public void showSync(SyncCompareInput input) { + input.setViewSite(getViewSite()); + this.input = input; + currentSyncMode = SYNC_NONE; + + // Remove old viewer + Control[] oldChildren = top.getChildren(); + if (oldChildren != null) { + for (int i = 0; i < oldChildren.length; i++) { + oldChildren[i].dispose(); + } + } + // Remove actions from toolbar + IActionBars bars = getViewSite().getActionBars(); + bars.getToolBarManager().removeAll(); + bars.getToolBarManager().update(false); + bars.getMenuManager().removeAll(); + bars.getMenuManager().update(); + bars.updateActionBars(); + + // Display the default contents while running the diff + showDefaultContents(); + top.layout(); + + // Run the diff and stop if cancel or error occurred. + if (!run(input)) return; + + // Check for problem message + if (input.getMessage() != null) { + MessageDialog.openInformation(getSite().getShell(), Policy.bind("SyncView.unableSynchronize"), input.getMessage()); //$NON-NLS-1$ + return; + } + + // Check for empty comparison + if (isEmpty(input.getDiffRoot())) { + MessageDialog.openInformation(getSite().getShell(), Policy.bind("nothingToSynchronize"), Policy.bind("SyncView.same")); //$NON-NLS-1$ //$NON-NLS-2$ + return; + } + + // Remove the default contents + oldChildren = top.getChildren(); + if (oldChildren != null) { + for (int i = 0; i < oldChildren.length; i++) { + oldChildren[i].dispose(); + } + } + + // Show the result + Control control = input.createContents(top); + control.setLayoutData(new GridData(GridData.FILL_BOTH)); + /*TreeViewer viewer = input.getViewer(); + if (viewer != null) { + Control viewerControl = viewer.getControl(); + if (viewerControl != null && !viewerControl.isDisposed()) { + WorkbenchHelp.setHelp(viewerControl, new ViewContextComputer(this, ITeamHelpContextIds.SYNC_VIEW)); + } + }*/ + + top.layout(); + + // Set the sync mode depending on user preference + // To do: add the user preference later, just say no for now. + // if (TeamUIPlugin.getPlugin().getPreferenceStore().getBoolean(UIConstants.PREF_ALWAYS_IN_CATCHUP_RELEASE)) { + // freeMode.run(); + // } else { + if (input.hasIncomingChanges()) { + incomingMode.run(); + } else { + outgoingMode.run(); + } + // } + // Reveal if fast view + try { + TeamUIPlugin.getActivePage().showView(VIEW_ID); + } catch (PartInitException e) { + TeamUIPlugin.log(e.getStatus()); + } + } + + /** + * Updates the actions for this view's action bar. + */ + private void updateActions() { + IActionBars bars = getViewSite().getActionBars(); + IToolBarManager toolBar = bars.getToolBarManager(); + IMenuManager menu = bars.getMenuManager(); + toolBar.removeAll(); + menu.removeAll(); + + toolBar.add(incomingMode); + toolBar.add(outgoingMode); + toolBar.add(freeMode); + input.getViewer().contributeToActionBars(bars); + + toolBar.update(false); + menu.update(false); + bars.updateActionBars(); + } +}
\ No newline at end of file |