aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Webster2010-10-26 15:08:53 (EDT)
committerChris Aniszczyk2011-03-02 11:31:05 (EST)
commite9f88374f691bc60c4a5573391aa3f43b4ef3c04 (patch)
tree964889cd490a66dbe7fe8d1bfa7b1c3afa9f5de7
parent49a5e613ea229f8f6d1314122fa42811145cc8a1 (diff)
downloadegit-pde-e9f88374f691bc60c4a5573391aa3f43b4ef3c04.zip
egit-pde-e9f88374f691bc60c4a5573391aa3f43b4ef3c04.tar.gz
egit-pde-e9f88374f691bc60c4a5573391aa3f43b4ef3c04.tar.bz2
Add a releng tool for gitrefs/changes/26/1826/3
It supports picking a map project, selecting map file entries to update and replacing lines in the mapfile with the new tag entry. Bug: 328745 Change-Id: Ib1529eace4ba2c571358d1212e2c40cf00fee274 Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
-rw-r--r--org.eclipse.egit.relengtools/META-INF/MANIFEST.MF5
-rw-r--r--org.eclipse.egit.relengtools/OSGI-INF/l10n/bundle.properties21
-rw-r--r--org.eclipse.egit.relengtools/plugin.xml38
-rwxr-xr-xorg.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/BuildNotesPage.java481
-rwxr-xr-xorg.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/GetBugsOperation.java224
-rw-r--r--org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/GitCopyrightAdapter.java (renamed from org.eclipse.egit.relengtools/src/org/eclipse/egit/relengtools/internal/GitCopyrightAdapter.java)2
-rw-r--r--org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/GitCopyrightAdapterFactory.java (renamed from org.eclipse.egit.relengtools/src/org/eclipse/egit/relengtools/internal/GitCopyrightAdapterFactory.java)2
-rwxr-xr-xorg.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapContentDocument.java163
-rwxr-xr-xorg.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapEntry.java362
-rwxr-xr-xorg.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapFile.java183
-rwxr-xr-xorg.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapProject.java270
-rwxr-xr-xorg.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapProjectSelectionPage.java243
-rwxr-xr-xorg.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/Messages.java34
-rwxr-xr-xorg.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/OrderedMap.java183
-rwxr-xr-xorg.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/ProjectSelectionPage.java350
-rw-r--r--org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/ReleaseWizard.java219
-rw-r--r--org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/RepoCheck.java56
-rw-r--r--org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/ShowInfoHandler.java303
-rw-r--r--org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/TagAndReleaseHandler.java50
-rwxr-xr-xorg.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/TagPage.java398
-rwxr-xr-xorg.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/messages.properties100
21 files changed, 3663 insertions, 24 deletions
diff --git a/org.eclipse.egit.relengtools/META-INF/MANIFEST.MF b/org.eclipse.egit.relengtools/META-INF/MANIFEST.MF
index cb6abed..b0b4c2c 100644
--- a/org.eclipse.egit.relengtools/META-INF/MANIFEST.MF
+++ b/org.eclipse.egit.relengtools/META-INF/MANIFEST.MF
@@ -11,7 +11,8 @@ Require-Bundle: org.eclipse.releng.tools;bundle-version="[3.3.0,4.0.0)",
org.eclipse.team.ui;bundle-version="[3.5.100,4.0.0)",
org.eclipse.core.resources;bundle-version="3.6.0",
org.eclipse.egit.core;bundle-version="0.10.0",
- org.eclipse.jgit;bundle-version="0.10.0"
+ org.eclipse.jgit;bundle-version="0.10.0",
+ org.eclipse.compare;bundle-version="3.5.100"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-Vendor: %Bundle-Vendor
-Export-Package: org.eclipse.egit.relengtools.internal;x-internal:=true
+Export-Package: org.eclipse.egit.internal.relengtools;x-internal:=true
diff --git a/org.eclipse.egit.relengtools/OSGI-INF/l10n/bundle.properties b/org.eclipse.egit.relengtools/OSGI-INF/l10n/bundle.properties
index 251836e..e087e19 100644
--- a/org.eclipse.egit.relengtools/OSGI-INF/l10n/bundle.properties
+++ b/org.eclipse.egit.relengtools/OSGI-INF/l10n/bundle.properties
@@ -3,12 +3,15 @@
# 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:
-# Gunnar Wagenknecht - initial API and implementation
-###############################################################################
-#Properties file for org.eclipse.egit.relengtools
-Bundle-Vendor = Eclipse EGit
-Bundle-Name = EGit Releng Tools Integration (Incubation)
+# 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:
+# Gunnar Wagenknecht - initial API and implementation
+###############################################################################
+#Properties file for org.eclipse.egit.relengtools
+Bundle-Vendor = Eclipse EGit
+Bundle-Name = EGit Releng Tools Integration (Incubation)
+
+command.tagAndRelease = Release...
+command.showInfo = Show Info
diff --git a/org.eclipse.egit.relengtools/plugin.xml b/org.eclipse.egit.relengtools/plugin.xml
index 0b176c2..3bd3349 100644
--- a/org.eclipse.egit.relengtools/plugin.xml
+++ b/org.eclipse.egit.relengtools/plugin.xml
@@ -13,14 +13,30 @@
<plugin>
<extension
- point="org.eclipse.core.runtime.adapters">
- <factory
- adaptableType="org.eclipse.team.core.RepositoryProviderType"
- class="org.eclipse.egit.relengtools.internal.GitCopyrightAdapterFactory">
- <adapter
- type="org.eclipse.releng.tools.IRepositoryProviderCopyrightAdapterFactory">
- </adapter>
- </factory>
- </extension>
-
-</plugin>
+ point="org.eclipse.core.runtime.adapters">
+ <factory
+ adaptableType="org.eclipse.team.core.RepositoryProviderType"
+ class="org.eclipse.egit.internal.relengtools.GitCopyrightAdapterFactory">
+ <adapter
+ type="org.eclipse.releng.tools.IRepositoryProviderCopyrightAdapterFactory">
+ </adapter>
+ </factory>
+ </extension>
+ <extension
+ point="org.eclipse.ui.commands">
+ <command
+ categoryId="org.eclipse.ui.category.project"
+ defaultHandler="org.eclipse.egit.internal.relengtools.TagAndReleaseHandler"
+ id="z.ex.git.releng.tagAndRelease"
+ name="%command.tagAndRelease">
+ </command>
+ <command
+ categoryId="org.eclipse.ui.category.project"
+ defaultHandler="org.eclipse.egit.internal.relengtools.ShowInfoHandler:test"
+ id="org.eclipse.egit.relengtools.showInfo"
+ name="%command.showInfo">
+ </command>
+ </extension>
+
+
+</plugin>
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/BuildNotesPage.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/BuildNotesPage.java
new file mode 100755
index 0000000..77102c1
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/BuildNotesPage.java
@@ -0,0 +1,481 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.egit.internal.relengtools;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+public class BuildNotesPage extends WizardPage {
+
+ private static final String FOLDER_BIN = "bin"; //$NON-NLS-1$
+
+ private static final String EXT_HTML = "html"; //$NON-NLS-1$
+
+ private static final String BUILD_NOTES_HTML = "/build_notes.html"; //$NON-NLS-1$
+
+ private final String FILE_PATH_KEY = "BuildNotesPage.filePath"; //$NON-NLS-1$
+
+ private final String UPDATE_FILE_KEY = "BuildNotesPage.updateNotesButton"; //$NON-NLS-1$
+
+ private Button updateNotesButton;
+
+ private boolean updateNotesButtonChecked;
+
+ private final IDialogSettings settings;
+
+ private Text reportText;
+
+ private Map bugSummaryMap;
+
+ private boolean validPath;
+
+ private Text filePath;
+
+ private Button browse;
+
+ private IFile iFile;
+
+ protected BuildNotesPage(String pageName, String title,
+ IDialogSettings settings, ImageDescriptor image) {
+ super(pageName, title, image);
+ this.settings = settings;
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ GridData data = new GridData(GridData.FILL_BOTH);
+ final Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout(3, false));
+ composite.setLayoutData(data);
+
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ data.horizontalSpan = 3;
+ updateNotesButton = new Button(composite, SWT.CHECK);
+ updateNotesButton.setText(Messages.getString("BuildNotesPage.2")); //$NON-NLS-1$
+ updateNotesButton.setLayoutData(data);
+ updateNotesButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateNotesButtonChecked = updateNotesButton.getSelection();
+ if (updateNotesButtonChecked) {
+ filePath.setEnabled(true);
+ filePath.setText(filePath.getText());
+ browse.setEnabled(true);
+ } else {
+ filePath.setEnabled(false);
+ setErrorMessage(null);
+ browse.setEnabled(false);
+ }
+ updateButtons();
+ }
+ });
+
+ final Label label = new Label(composite, SWT.LEFT);
+ label.setText(Messages.getString("BuildNotesPage.3")); //$NON-NLS-1$
+
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ filePath = new Text(composite, SWT.BORDER);
+ filePath.setLayoutData(data);
+ filePath.addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ final Path path = new Path(filePath.getText());
+ validPath = false;
+ if (!path.isEmpty()) {
+ final IFile file = ResourcesPlugin.getWorkspace().getRoot()
+ .getFile(path);
+ if (path.isValidPath(filePath.getText())
+ && file.getParent().exists()) {
+ if (path.getFileExtension().equals(EXT_HTML)) {
+ setErrorMessage(null);
+ validPath = true;
+ iFile = file;
+ } else {
+ setErrorMessage(Messages
+ .getString("BuildNotesPage.5")); //$NON-NLS-1$
+ }
+ } else {
+ setErrorMessage(Messages.getString("BuildNotesPage.6")); //$NON-NLS-1$
+ }
+ } else {
+ // path is empty
+ setErrorMessage(Messages.getString("BuildNotesPage.7")); //$NON-NLS-1$
+ }
+ updateButtons();
+ }
+ });
+
+ browse = new Button(composite, SWT.PUSH);
+ browse.setText(Messages.getString("BuildNotesPage.8")); //$NON-NLS-1$
+ browse.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ final IResource iResource = buildNotesFileDialog();
+ if (iResource instanceof IFile) {
+ final IFile iFile = (IFile) iResource;
+ filePath.setText(iFile.getFullPath().toString());
+ } else if (iResource instanceof IFolder) {
+ final IFolder iFolder = (IFolder) iResource;
+ filePath.setText(iFolder.getFullPath().toString()
+ + BUILD_NOTES_HTML);
+ } else if (iResource instanceof IProject) {
+ final IProject iProject = (IProject) iResource;
+ filePath.setText(iProject.getFullPath().toString()
+ + BUILD_NOTES_HTML);
+ }
+ }
+ });
+ // SWTUtil.setButtonDimensionHint(browse);
+
+ data = new GridData(GridData.FILL_BOTH);
+ data.horizontalSpan = 3;
+ reportText = new Text(composite, SWT.READ_ONLY | SWT.MULTI | SWT.BORDER
+ | SWT.WRAP | SWT.V_SCROLL);
+ reportText.setLayoutData(data);
+
+ initialize();
+ setControl(composite);
+ }
+
+ private void initialize() {
+ initSelections();
+ }
+
+ /*
+ * initialize the controls on the page
+ */
+ private void initSelections() {
+ if (settings == null || settings.get(UPDATE_FILE_KEY) == null
+ || settings.get(FILE_PATH_KEY) == null) {
+ updateNotesButton.setSelection(false);
+ updateNotesButtonChecked = false;
+ browse.setEnabled(false);
+ filePath.setEnabled(false);
+ return;
+ } else {
+ final boolean b = settings.getBoolean(UPDATE_FILE_KEY);
+ updateNotesButton.setSelection(b);
+ updateNotesButtonChecked = b;
+ filePath.setText(settings.get(FILE_PATH_KEY));
+ browse.setEnabled(true);
+ filePath.setEnabled(true);
+ }
+ }
+
+ /*
+ * enable or disable wizard buttons
+ */
+ public void updateButtons() {
+ if (isUpdateNotesButtonChecked() && !getValidPath()) {
+ setPageComplete(false);
+ } else {
+ setPageComplete(true);
+ }
+ }
+
+ /*
+ * if file doesn't already exist, prepare new one otherwise call method to
+ * write to existing file
+ */
+ public void updateNotesFile() {
+ if (bugSummaryMap != null && !filePath.isDisposed()) {
+ final Path path = new Path(filePath.getText());
+ final IWorkspaceRoot root = ResourcesPlugin.getWorkspace()
+ .getRoot();
+ final IFile file = root.getFile(path);
+ if (file.exists()) {
+ writeUpdate(file);
+ } else {
+ if (file.getParent().exists()) {
+ try {
+ getContainer().run(true, true,
+ new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor)
+ throws InvocationTargetException,
+ InterruptedException {
+ monitor.beginTask(
+ Messages.getString("BuildNotesPage.11"), //$NON-NLS-1$
+ 100);
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append("<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">\n");
+ buffer.append("<html>\n\n");
+ buffer.append("<head>\n");
+ buffer.append(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n");
+ buffer.append(" <meta name=\"Build\" content=\"Build\">\n");
+ buffer.append(" <title>Eclipse Platform Release Notes (3.3) - JFace and Workbench</title>\n");
+ buffer.append("</head>\n\n");
+ buffer.append("<body>\n\n");
+ buffer.append("<h1>Eclipse Platform Build Notes (3.3)<br>\n");
+ buffer.append("JFace and Workbench</h1>");
+
+ final ByteArrayInputStream c = new ByteArrayInputStream(
+ buffer.toString().getBytes());
+ try {
+ file.create(c, true, monitor);
+ } catch (final CoreException e) {
+ e.printStackTrace();
+ }
+
+ try {
+ c.close();
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ monitor.done();
+ }
+ });
+ } catch (final InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ writeUpdate(file);
+ }
+ }
+ }
+ }
+
+ /*
+ * write update to build notes file
+ */
+ public void writeUpdate(final IFile file) {
+ BufferedInputStream originalContents = null;
+ try {
+ originalContents = new BufferedInputStream(file.getContents());
+ final StringBuffer buffer = new StringBuffer();
+
+ int character;
+ while ((character = originalContents.read()) != -1) {
+ buffer.append((char) character);
+ }
+
+ final String marker = "</h1>";
+ final SimpleDateFormat formatter = new SimpleDateFormat(
+ "MMMM dd, yyyy, h:mm a");
+ final Date currentTime = new Date();
+ String dateString = formatter.format(currentTime);
+ dateString = dateString.replaceAll("AM", "a.m.");
+ dateString = dateString.replaceAll("PM", "p.m.");
+
+ final int index = buffer.indexOf(marker) + marker.length();
+ if (index != -1) {
+ final StringBuffer insertBuffer = new StringBuffer();
+ insertBuffer.append("\n<p>Integration Build (" + dateString
+ + ")</p>\n");
+ insertBuffer.append(" <p>Problem reports updated</p>\n");
+ insertBuffer.append(" <p>\n");
+
+ final Iterator i = bugSummaryMap.entrySet().iterator();
+ while (i.hasNext()) {
+ final Map.Entry entry = (Map.Entry) i.next();
+ final Integer bug = (Integer) entry.getKey();
+ final String summary = (String) entry.getValue();
+ insertBuffer
+ .append("<a href=\"https://bugs.eclipse.org/bugs/show_bug.cgi?id=");
+ insertBuffer.append(bug);
+ insertBuffer.append("\">Bug ");
+ insertBuffer.append(bug);
+ insertBuffer.append("</a>. ");
+ insertBuffer.append(summary + "<br>\n");
+ }
+ insertBuffer.append(" </p>");
+ buffer.insert(index, "\n" + insertBuffer.toString());
+
+ try {
+ getContainer().run(true, true, new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor)
+ throws InvocationTargetException,
+ InterruptedException {
+ monitor.beginTask(
+ Messages.getString("BuildNotesPage.38"), 100); //$NON-NLS-1$
+ final ByteArrayInputStream c = new ByteArrayInputStream(
+ buffer.toString().getBytes());
+ try {
+ file.setContents(c, true, true, monitor);
+ c.close();
+ } catch (final CoreException e) {
+ e.printStackTrace();
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ monitor.done();
+ }
+ });
+ } catch (final InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ } catch (final IOException e) {
+ e.printStackTrace();
+ } catch (final CoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if (visible) {
+ reportText.setText("");
+ // TODO this is where we need to scan the logs and get the bugs.
+ final GetBugsOperation getBugsOperation = new GetBugsOperation(
+ (ReleaseWizard) getWizard(), null);
+ getBugsOperation.run(this);
+ if (bugSummaryMap != null) {
+ final String tempText = outputReport();
+ if (tempText != null) {
+ reportText.setText(tempText);
+ }
+ }
+ }
+ }
+
+ public IResource buildNotesFileDialog() {
+ final ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(
+ getShell(), new WorkbenchLabelProvider(),
+ new WorkbenchContentProvider());
+
+ // filter for .html files only and exclude bin folders
+ dialog.addFilter(new ViewerFilter() {
+ @Override
+ public boolean select(Viewer viewer, Object parentElement,
+ Object element) {
+ if (element instanceof IFile) {
+ final IFile file = (IFile) element;
+ final IPath path = file.getFullPath();
+ if (path.getFileExtension().equals(EXT_HTML)) {
+ return true;
+ }
+ } else if (element instanceof IFolder) {
+ final IFolder folder = (IFolder) element;
+ if (folder.getName().equals(FOLDER_BIN)) {
+ return false;
+ }
+ return true;
+ } else if (element instanceof IProject) {
+ return true;
+ }
+ return false;
+ }
+ });
+
+ dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());
+ dialog.setAllowMultiple(false);
+ dialog.setTitle(Messages.getString("BuildNotesPage.42")); //$NON-NLS-1$
+ dialog.setMessage(Messages.getString("BuildNotesPage.43")); //$NON-NLS-1$
+ if (dialog.open() == Window.OK) {
+ final Object[] elements = dialog.getResult();
+ if (elements != null && elements.length > 0) {
+ if (elements[0] instanceof IFile) {
+ final IFile iFile = (IFile) elements[0];
+ return iFile;
+ } else if (elements[0] instanceof IFolder) {
+ final IFolder iFolder = (IFolder) elements[0];
+ return iFolder;
+ } else if (elements[0] instanceof IProject) {
+ final IProject iProject = (IProject) elements[0];
+ return iProject;
+ }
+ }
+ }
+ return null;
+ }
+
+ public boolean isUpdateNotesButtonChecked() {
+ return updateNotesButtonChecked;
+ }
+
+ /**
+ * return string of report
+ */
+ public String outputReport() {
+ final StringBuffer buffer = new StringBuffer();
+ if (bugSummaryMap.size() < 1) {
+ buffer.append("The map file has been updated.\n");
+ } else {
+ buffer.append("The map file has been updated for the following Bug changes:\n");
+ final Iterator i = bugSummaryMap.entrySet().iterator();
+
+ while (i.hasNext()) {
+ final Map.Entry entry = (Map.Entry) i.next();
+ final Integer bug = (Integer) entry.getKey();
+ final String summary = (String) entry.getValue();
+ buffer.append("+ Bug " + bug + ". " + summary + "\n");
+ }
+ }
+ buffer.append("\nThe following projects have changed:\n");
+ final IProject[] iProjects = ((ReleaseWizard) getWizard())
+ .getSelectedProjects();
+ for (int j = 0; j < iProjects.length; j++) {
+ buffer.append(iProjects[j].getName() + "\n");
+ }
+ return buffer.toString();
+ }
+
+ public void setMap(Map map) {
+ this.bugSummaryMap = map;
+ }
+
+ public boolean getValidPath() {
+ return validPath;
+ }
+
+ public IFile getIFile() {
+ return iFile;
+ }
+
+ public void saveSettings() {
+ settings.put(UPDATE_FILE_KEY, updateNotesButtonChecked);
+ settings.put(FILE_PATH_KEY, filePath.getText());
+ }
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/GetBugsOperation.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/GetBugsOperation.java
new file mode 100755
index 0000000..1b41e9b
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/GetBugsOperation.java
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 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.egit.internal.relengtools;
+
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.egit.core.GitTag;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.ui.statushandlers.StatusManager;
+
+public class GetBugsOperation {
+ private static final String BUG_DATABASE_PREFIX = "https://bugs.eclipse.org/bugs/show_bug.cgi?id=";
+
+ private static final String BUG_DATABASE_POSTFIX = "&ctype=xml";
+
+ private static final String SUM_OPEN_TAG = "<short_desc>";
+
+ private static final String SUM_CLOSE_TAG = "</short_desc>";
+
+ private static final String STATUS_OPEN_TAG = "<bug_status>";
+
+ private static final String STATUS_CLOSE_TAG = "</bug_status";
+
+ private static final String RES_OPEN_TAG = "<resolution>";
+
+ private static final String RES_CLOSE_TAG = "</resolution>";
+
+ private static final String RESOLVED = "RESOLVED";
+
+ private static final String VERIFIED = "VERIFIED";
+
+ private final ReleaseWizard wizard;
+
+ private final Pattern bugPattern;
+
+ protected GetBugsOperation(ReleaseWizard wizard, Object syncInfoSet) {
+ this.wizard = wizard;
+ bugPattern = Pattern.compile("bug (\\d+)", Pattern.CASE_INSENSITIVE
+ | Pattern.UNICODE_CASE);
+ }
+
+ protected void run(final BuildNotesPage page) {
+ try {
+ wizard.getContainer().run(true, true, new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor) {
+ final int totalWork = 101;
+ monitor.beginTask(
+ Messages.getString("GetBugsOperation.0"), totalWork); //$NON-NLS-1$
+
+ // task 1 -- get bug number from comments
+ final Set bugTree = new HashSet();
+
+ // task 2 -- create map of bugs and summaries
+ final Integer[] bugs = (Integer[]) bugTree
+ .toArray(new Integer[0]);
+ final TreeMap map = (TreeMap) getBugzillaSummaries(bugs,
+ new SubProgressMonitor(monitor, 15,
+ SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));
+ page.getShell().getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ page.setMap(map);
+ }
+ });
+ monitor.done();
+ }
+ });
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ } catch (final InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected Set getBugNumbersFromComments(Object[] syncInfos,
+ IProgressMonitor monitor) {
+ monitor.beginTask("Scanning comments for bug numbers", syncInfos.length);
+ final TreeSet set = new TreeSet();
+ for (int i = 0; i < syncInfos.length; i++) {
+ final Object info = syncInfos[i];
+ getBugNumbersForSyncInfo(info, monitor, set);
+ monitor.worked(1);
+ }
+ monitor.done();
+ return set;
+ }
+
+ private void getBugNumbersForSyncInfo(Object info,
+ IProgressMonitor monitor, Set set) {
+
+ }
+
+ private GitTag getProjectTag(IProject project) {
+ return MapEntry.DEFAULT;
+ }
+
+ protected void findBugNumber(String comment, Set set) {
+ if (comment == null) {
+ return;
+ }
+ final Matcher matcher = bugPattern.matcher(comment);
+ while (matcher.find()) {
+ final Integer bugNumber = new Integer(matcher.group(1));
+ set.add(bugNumber);
+ }
+ }
+
+ /*
+ * Method uses set of bug numbers to query bugzilla and get summary of each
+ * bug
+ */
+ protected Map getBugzillaSummaries(Integer[] bugs, IProgressMonitor monitor) {
+ monitor.beginTask(
+ Messages.getString("GetBugsOperation.1"), bugs.length + 1); //$NON-NLS-1$
+ HttpURLConnection hURL;
+ DataInputStream in;
+ URLConnection url;
+ StringBuffer buffer;
+ final TreeMap map = new TreeMap();
+ for (int i = 0; i < bugs.length; i++) {
+ try {
+ url = (new URL(BUG_DATABASE_PREFIX + bugs[i]
+ + BUG_DATABASE_POSTFIX).openConnection());
+ if (url instanceof HttpURLConnection) {
+ hURL = (HttpURLConnection) url;
+ hURL.setAllowUserInteraction(true);
+ hURL.connect();
+ in = new DataInputStream(hURL.getInputStream());
+ buffer = new StringBuffer();
+ try {
+ if (hURL.getResponseCode() != HttpURLConnection.HTTP_OK) {
+ throw new IOException("Bad response code");
+ }
+ while (true) {
+ buffer.append((char) in.readUnsignedByte());
+ }
+ } catch (final EOFException e) {
+ hURL.disconnect();
+ }
+ final String webPage = buffer.toString();
+ final int summaryStartIndex = webPage.indexOf(SUM_OPEN_TAG);
+ final int summaryEndIndex = webPage.indexOf(SUM_CLOSE_TAG,
+ summaryStartIndex);
+ if (summaryStartIndex != -1 & summaryEndIndex != -1) {
+ String summary = webPage.substring(summaryStartIndex
+ + SUM_OPEN_TAG.length(), summaryEndIndex);
+ summary = summary.replaceAll("&quot;", "\"");
+ summary = summary.replaceAll("&lt;", "<");
+ summary = summary.replaceAll("&gt;", ">");
+ summary = summary.replaceAll("&amp;", "&");
+ summary = summary.replaceAll("&apos;", "'");
+ final int statusStartIndex = webPage
+ .indexOf(STATUS_OPEN_TAG);
+ final int statusEndIndex = webPage
+ .indexOf(STATUS_CLOSE_TAG);
+ if (statusStartIndex != -1 && statusEndIndex != -1) {
+ final String bugStatus = webPage
+ .substring(statusStartIndex
+ + STATUS_OPEN_TAG.length(),
+ statusEndIndex);
+ if (bugStatus.equalsIgnoreCase(RESOLVED)
+ || bugStatus.equalsIgnoreCase(VERIFIED)) {
+ final int resStartIndex = webPage
+ .indexOf(RES_OPEN_TAG);
+ final int resEndIndex = webPage
+ .indexOf(RES_CLOSE_TAG);
+ if (resStartIndex != -1 && resEndIndex != -1) {
+ final String resolution = webPage
+ .substring(resStartIndex
+ + RES_OPEN_TAG.length(),
+ resEndIndex);
+ if (resolution != null
+ && !resolution.equals("")) {
+ summary = summary + " (" + resolution
+ + ")";
+ }
+ }
+ } else {
+ summary = summary + " (" + bugStatus + ")";
+ }
+ }
+ map.put(bugs[i], summary);
+ }
+ }
+ } catch (final IOException e) {
+ StatusManager
+ .getManager()
+ .handle(new Status(IStatus.ERROR, "id", Messages
+ .getString("GetBugsOperation.Error"), e),
+ StatusManager.SHOW | StatusManager.LOG);
+ }
+ monitor.worked(1);
+ }
+ monitor.done();
+ return map;
+ }
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/relengtools/internal/GitCopyrightAdapter.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/GitCopyrightAdapter.java
index 48806d4..dfce499 100644
--- a/org.eclipse.egit.relengtools/src/org/eclipse/egit/relengtools/internal/GitCopyrightAdapter.java
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/GitCopyrightAdapter.java
@@ -10,7 +10,7 @@
* IBM Corporation - initial API and implementation of CVS adapter
* Gunnar Wagenknecht - initial API and implementation
*******************************************************************************/
-package org.eclipse.egit.relengtools.internal;
+package org.eclipse.egit.internal.relengtools;
import java.io.IOException;
import java.util.Calendar;
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/relengtools/internal/GitCopyrightAdapterFactory.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/GitCopyrightAdapterFactory.java
index d10ed37..cbab564 100644
--- a/org.eclipse.egit.relengtools/src/org/eclipse/egit/relengtools/internal/GitCopyrightAdapterFactory.java
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/GitCopyrightAdapterFactory.java
@@ -9,7 +9,7 @@
* Contributors:
* Gunnar Wagenknecht - initial API and implementation
*******************************************************************************/
-package org.eclipse.egit.relengtools.internal;
+package org.eclipse.egit.internal.relengtools;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdapterFactory;
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapContentDocument.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapContentDocument.java
new file mode 100755
index 0000000..bbc85eb
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapContentDocument.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 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.egit.internal.relengtools;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.eclipse.compare.IStreamContentAccessor;
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.swt.graphics.Image;
+
+public class MapContentDocument implements ITypedElement,
+ IStreamContentAccessor {
+ private MapFile mapFile;
+
+ private String oldContents = ""; //$NON-NLS-1$
+
+ private String newContents = ""; //$NON-NLS-1$
+
+ public MapContentDocument(MapFile aMapFile) {
+ mapFile = aMapFile;
+ initialize();
+ }
+
+ /**
+ * Update the tag associated with the given project in the new contents.
+ */
+ public void updateTag(IProject project, String tag) throws CoreException {
+ InputStream inputStream = new BufferedInputStream(
+ new ByteArrayInputStream(newContents.getBytes()));
+ boolean match = false;
+ StringBuffer buffer = new StringBuffer();
+ try {
+ BufferedReader aReader = new BufferedReader(new InputStreamReader(
+ inputStream));
+ String aLine = aReader.readLine();
+ while (aLine != null) {
+ if (aLine.trim().length() != 0 && !aLine.startsWith("!")
+ && !aLine.startsWith("#")) {
+ // Found a possible match
+ MapEntry entry = new MapEntry(aLine);
+ if (!entry.isValid()) {
+ throw new CoreException(new Status(IStatus.ERROR, "",
+ "Malformed map file line: " + aLine));
+ }
+ if (entry.isMappedTo(project)) {
+ // Now for sure we have a match. Replace the line.
+ entry.setTagName(tag);
+ aLine = entry.getMapString();
+ match = true;
+ }
+ }
+ buffer.append(aLine);
+ aLine = aReader.readLine();
+ if (aLine != null) {
+ buffer.append(System.getProperty("line.separator")); //$NON-NLS-1$
+ }
+ }
+ } catch (IOException e) {
+ throw new CoreException(new Status(IStatus.ERROR, "",
+ e.getMessage(), e));
+ } finally {
+ if (inputStream != null) {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ if (match) {
+ newContents = buffer.toString();
+ }
+ }
+
+ public boolean isChanged() {
+ return !(oldContents.equals(newContents));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.compare.ITypedElement#getName()
+ */
+ public String getName() {
+ return mapFile.getFile().getName();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.compare.ITypedElement#getImage()
+ */
+ public Image getImage() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.compare.ITypedElement#getType()
+ */
+ public String getType() {
+ return mapFile.getFile().getFileExtension();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.compare.IStreamContentAccessor#getContents()
+ */
+ public InputStream getContents() throws CoreException {
+ return new ByteArrayInputStream(getNewContent().getBytes());
+ }
+
+ public MapFile getMapFile() {
+ return mapFile;
+ }
+
+ private String getNewContent() {
+ return newContents;
+ }
+
+ private void initialize() {
+ InputStream inputStream;
+ StringBuffer buffer = new StringBuffer();
+ try {
+ inputStream = mapFile.getFile().getContents();
+ BufferedReader aReader = new BufferedReader(new InputStreamReader(
+ inputStream));
+ String aLine = aReader.readLine();
+ while (aLine != null) {
+ buffer.append(aLine);
+ aLine = aReader.readLine();
+ if (aLine != null) {
+ buffer.append(System.getProperty("line.separator")); //$NON-NLS-1$
+ }
+ }
+ oldContents = buffer.toString();
+ newContents = new String(oldContents);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapEntry.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapEntry.java
new file mode 100755
index 0000000..6b3a590
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapEntry.java
@@ -0,0 +1,362 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 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.egit.internal.relengtools;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.egit.core.GitTag;
+
+/**
+ * This class provides access to information stored in RelEng map files
+ */
+public class MapEntry {
+ public static final GitTag DEFAULT = new GitTag("master");
+
+ private static final String HEAD = "HEAD";
+
+ private static final String KEY_TAG = "tag"; //$NON-NLS-1$
+
+ private static final String KEY_PATH = "path"; //$NON-NLS-1$
+
+ private static final String REPO = "repo";
+
+ private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+
+ private boolean valid = false;
+
+ private String type = EMPTY_STRING;
+
+ private String id = EMPTY_STRING;
+
+ private OrderedMap arguments = new OrderedMap();
+
+ private boolean legacy = false;
+
+ private String version;
+
+ public static void main(String[] args) {
+ // For testing only
+
+ final String[] strings = {
+ "",
+ " ",
+ "type",
+ "type@",
+ "type@id",
+ "type@id=",
+ "type@id=tag,",
+ "type@id=tag, connectString",
+ "type@id=tag, connectString,",
+ "type@id=tag, connectString,password",
+ "type@id=tag, connectString,password,",
+ "type@id=tag, connectString,password,moduleName",
+ "type@id=tag, connectString,,moduleName",
+ "!*************** FEATURE CONTRIBUTION ******************************************************",
+ "@",
+ "=",
+ ",,,",
+ "@=,,,,",
+ "type@id,version=CVS,tag=myTag,cvsRoot=myCvsRoot,password=password,path=myPath", };
+
+ for (int i = 0; i < strings.length; i++) {
+ final String string = strings[i];
+ final MapEntry anEntry = new MapEntry(string);
+
+ System.out
+ .println("-----------------------------------------------");
+ System.out.println("input: " + string);
+ System.out.println("map string: " + anEntry.getMapString());
+ // System.out.println(anEntry.getReferenceString());
+ anEntry.display();
+ }
+
+ }
+
+ private void display() {
+ // For testing only
+ System.out.println("Is Valid: " + isValid());
+ System.out.println("Type: " + getType());
+ System.out.println("Project Name: " + getId());
+ System.out.println("Tag: " + getTagName());
+ if (version != null)
+ System.out.println("Version: " + version);
+ System.out.println("Connect: " + getRepo());
+ System.out.println("Path: " + getPath());
+ }
+
+ public MapEntry(String entryLine) {
+ init(entryLine);
+ }
+
+ /**
+ * Parse a map file entry line
+ *
+ * @param entryLine
+ */
+ private void init(String entryLine) {
+ valid = false;
+
+ // check for commented out entry
+ if (entryLine.startsWith("#") || entryLine.startsWith("!"))
+ return;
+
+ // Type
+ int start = 0;
+ int end = entryLine.indexOf('@');
+ if (end == -1)
+ return;
+ type = entryLine.substring(start, end).trim();
+
+ // Project Name
+ start = end + 1;
+ end = entryLine.indexOf('=', start);
+ if (end == -1)
+ return;
+ id = entryLine.substring(start, end).trim();
+ // we have a version that we have to strip off
+ final int comma = id.indexOf(',');
+ if (comma != -1) {
+ version = id.substring(comma + 1);
+ id = id.substring(0, comma);
+ }
+
+ final String[] args = getArrayFromStringWithBlank(
+ entryLine.substring(end + 1), ",");
+ this.arguments = populate(args);
+ final String tag = (String) arguments.get(KEY_TAG);
+ final String repo = (String) arguments.get(REPO);
+ if (tag == null || tag.length() == 0 || repo == null
+ || repo.length() == 0)
+ return;
+ valid = true;
+ }
+
+ /*
+ * Build a table from the given array. In the new format,the array contains
+ * key=value elements. Otherwise we fill in the key based on the old format.
+ */
+ private OrderedMap populate(String[] entries) {
+ final OrderedMap result = new OrderedMap();
+ for (int i = 0; i < entries.length; i++) {
+ final String entry = entries[i];
+ final int index = entry.indexOf('=');
+ if (index == -1) {
+ // we only handle CVS entries
+ if (i == 0 && "GIT".equalsIgnoreCase(entry))
+ continue;
+ // legacy story...
+ return legacyPopulate(entries);
+ }
+ final String key = entry.substring(0, index);
+ final String value = entry.substring(index + 1);
+ result.put(key, value);
+ }
+ result.toString();
+ return result;
+ }
+
+ private OrderedMap legacyPopulate(String[] entries) {
+ legacy = true;
+ final OrderedMap result = new OrderedMap();
+ // must have at least tag and connect string
+ if (entries.length >= 2) {
+ // Version
+ result.put(KEY_TAG, entries[0]);
+ // Repo Connect String
+ result.put(REPO, entries[1]);
+
+ // Optional CVS Module Name
+ if (entries.length >= 3)
+ result.put(KEY_PATH, entries[3]);
+ }
+ return result;
+ }
+
+ /**
+ * Convert a list of tokens into an array. The list separator has to be
+ * specified. The specificity of this method is that it returns an empty
+ * element when to same separators are following each others. For example
+ * the string a,,b returns the following array [a, ,b]
+ *
+ */
+ public static String[] getArrayFromStringWithBlank(String list,
+ String separator) {
+ if (list == null || list.trim().length() == 0)
+ return new String[0];
+ final List result = new ArrayList();
+ boolean previousWasSeparator = true;
+ for (final StringTokenizer tokens = new StringTokenizer(list,
+ separator, true); tokens.hasMoreTokens();) {
+ final String token = tokens.nextToken().trim();
+ if (token.equals(separator)) {
+ if (previousWasSeparator)
+ result.add(""); //$NON-NLS-1$
+ previousWasSeparator = true;
+ } else {
+ result.add(token);
+ previousWasSeparator = false;
+ }
+ }
+ return (String[]) result.toArray(new String[result.size()]);
+ }
+
+ public String getTagName() {
+ final String value = (String) arguments.get(KEY_TAG);
+ return value == null || HEAD.equals(value) ? EMPTY_STRING : value;
+ }
+
+ public GitTag getTag() {
+ if (getTagName().equals(HEAD) || getTagName().equals(""))
+ return DEFAULT;
+ return new GitTag(getTagName());
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ private String internalGetCVSModule() {
+ final String module = (String) arguments.get(KEY_PATH);
+ return module == null ? id : module;
+ }
+
+ public String getPath() {
+ final String value = (String) arguments.get(KEY_PATH);
+ return value == null ? EMPTY_STRING : value;
+ }
+
+ public String getRepo() {
+ final String value = (String) arguments.get(REPO);
+ return value == null ? EMPTY_STRING : value;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public boolean isValid() {
+ return valid;
+ }
+
+ public String getReferenceString() {
+ if (!isValid())
+ return null;
+ // This is the format used by the CVS IProjectSerializer
+ final String projectName = new Path(internalGetCVSModule())
+ .lastSegment();
+ return "1.0," + getRepo() + "," + internalGetCVSModule() + ","
+ + projectName + "," + getTagName();
+ }
+
+ public String getMapString() {
+ final StringBuffer result = new StringBuffer();
+ if (legacy) {
+ result.append(getType());
+ result.append('@');
+ result.append(getId());
+ if (version != null) {
+ result.append(',');
+ result.append(version);
+ }
+ result.append('=');
+ result.append(getTagName());
+ result.append(',');
+ result.append(getRepo());
+ result.append(',');
+ result.append(getPath());
+ return result.toString();
+ }
+ result.append(getType());
+ result.append('@');
+ result.append(getId());
+ if (version != null) {
+ result.append(',');
+ result.append(version);
+ }
+ result.append('=');
+ result.append("GIT");
+ for (final Iterator iter = arguments.keys().iterator(); iter.hasNext();) {
+ final String key = (String) iter.next();
+ final String value = (String) arguments.get(key);
+ if (value != null && value.length() > 0)
+ result.append(',' + key + '=' + value);
+ }
+ return result.toString();
+ }
+
+ /*
+ * Return the version specified for this entry. Can be null.
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ public void setId(String projectID) {
+ this.id = projectID;
+ }
+
+ public void setCVSModule(String path) {
+ arguments.put(KEY_PATH, path);
+ }
+
+ public void setRepo(String repo) {
+ arguments.put(REPO, repo);
+ }
+
+ public void setTagName(String tagName) {
+ arguments.put(KEY_TAG, tagName);
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public void setValid(boolean valid) {
+ this.valid = valid;
+ }
+
+ @Override
+ public String toString() {
+ return "Entry: " + getMapString();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof MapEntry) {
+ return ((MapEntry) obj).getMapString().equals(getMapString());
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * Return <code>true</code> if the entry is mapped to the given project and
+ * <code>false</code> otherwise.
+ */
+ public boolean isMappedTo(IProject project) {
+ // RepositoryProvider provider =
+ // RepositoryProvider.getProvider(project);
+ if (id.equals(project.getName())) {
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapFile.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapFile.java
new file mode 100755
index 0000000..045f716
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapFile.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 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.egit.internal.relengtools;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.ResourcesPlugin;
+
+public class MapFile {
+
+ /**
+ * @deprecated As of 3.7, replaced by {@link #isMapFile(IFile)}
+ */
+ public static final String MAP_FILE_EXTENSION = "map"; //$NON-NLS-1$
+
+ private static final String MAP_FILE_NAME_ENDING = '.' + MAP_FILE_EXTENSION;
+
+ protected IFile file;
+
+ protected MapEntry[] entries;
+
+ public MapFile(IFile aFile) throws CoreException {
+ file = aFile;
+ loadEntries();
+ }
+
+ public IFile getFile() {
+ return file;
+ }
+
+ protected void loadEntries() throws CoreException {
+ InputStream inputStream = null;
+ List list = new ArrayList();
+
+ try {
+ inputStream = file.getContents();
+ BufferedReader aReader = new BufferedReader(new InputStreamReader(
+ inputStream));
+ String aLine = aReader.readLine();
+ while (aLine != null) {
+ if (isMapLine(aLine)) {
+ list.add(new MapEntry(aLine));
+ }
+ aLine = aReader.readLine();
+ }
+ } catch (IOException e) {
+ throw new CoreException(new Status(IStatus.ERROR, "what", 0,
+ "An I/O Error occurred process map file "
+ + file.getFullPath().toString(), e));
+ } finally {
+ if (inputStream != null) {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ // Ignore close exceptions so we don't mask another
+ // exception
+ }
+ }
+ }
+
+ this.entries = (MapEntry[]) list.toArray(new MapEntry[list.size()]);
+ }
+
+ private boolean isMapLine(String line) {
+ if (line.trim().length() == 0)
+ return false;
+ if (line.startsWith("!"))
+ return false;
+ return true;
+ }
+
+ public boolean contains(IProject project) {
+ for (int j = 0; j < entries.length; j++) {
+ if (entries[j].isMappedTo(project)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public MapEntry getMapEntry(IProject project) {
+ for (int j = 0; j < entries.length; j++) {
+ if (entries[j].isMappedTo(project)) {
+ return entries[j];
+ }
+ }
+ return null;
+ }
+
+ public IProject[] getAccessibleProjects() {
+ Set list = new HashSet();
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
+ .getProjects();
+ if (entries == null || entries.length == 0)
+ return null;
+ for (int i = 0; i < projects.length; i++) {
+ IProject project = projects[i];
+ if (project.isAccessible()) {
+ for (int j = 0; j < entries.length; j++) {
+ if (entries[j].isMappedTo(project)) {
+ list.add(project);
+ }
+ }
+ }
+ }
+ return (IProject[]) list.toArray(new IProject[list.size()]);
+ }
+
+ public String getName() {
+ return file.getName();
+ }
+
+ /**
+ * Finds all map files in the workspace.
+ *
+ * @param resource
+ * the resource for which to find the map files
+ * @return an array of all map file for the given resource
+ * @throws CoreException
+ * if something goes wrong
+ * @since 3.7
+ */
+ public static MapFile[] findAllMapFiles(IResource resource)
+ throws CoreException {
+ final ArrayList mapFiles = new ArrayList();
+ IResourceProxyVisitor visitor = new IResourceProxyVisitor() {
+ public boolean visit(IResourceProxy resourceProxy)
+ throws CoreException {
+ if (!resourceProxy.isAccessible())
+ return false;
+
+ int type = resourceProxy.getType();
+ if (type == IResource.PROJECT) {
+ // TODO: we need to care that this is shared or not
+ // return
+ // RelEngPlugin.isShared((IProject)resourceProxy.requestResource());
+ return true;
+ }
+
+ if (type == IResource.FILE
+ && resourceProxy.getName().endsWith(
+ MAP_FILE_NAME_ENDING))
+ mapFiles.add(new MapFile((IFile) resourceProxy
+ .requestResource()));
+
+ return true;
+ }
+ };
+
+ resource.accept(visitor, IResource.NONE);
+
+ return (MapFile[]) mapFiles.toArray(new MapFile[mapFiles.size()]);
+ }
+
+ public static boolean isMapFile(IFile aFile) {
+ return MapFile.MAP_FILE_EXTENSION.equals(aFile.getFileExtension());
+ }
+
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapProject.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapProject.java
new file mode 100755
index 0000000..1e30291
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapProject.java
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 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.egit.internal.relengtools;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.GitTag;
+
+public class MapProject implements IResourceChangeListener {
+
+ public static final String MAP_PROJECT_NAME = Messages
+ .getString("RelEngPlugin.1"); //$NON-NLS-1$
+
+ public static final String MAP_FOLDER = Messages
+ .getString("RelEngPlugin.2"); //$NON-NLS-1$
+
+ private static MapProject mapProject = null;
+
+ private IProject project;
+
+ private MapFile[] mapFiles;
+
+ /**
+ * Return the default map project (org.eclipse.releng) or <code>null</code>
+ * if the project does not exist or there is an error processing it. If
+ * there is an error, it will be logged.
+ *
+ * @return the default map project
+ */
+ public static MapProject getDefaultMapProject() {
+ if (mapProject == null) {
+ IProject project = getProjectFromWorkspace();
+ try {
+ mapProject = new MapProject(project);
+ } catch (CoreException e) {
+ // RelEngPlugin.log(e);
+ }
+ }
+ return mapProject;
+ }
+
+ private static IProject getProjectFromWorkspace() {
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IWorkspaceRoot root = workspace.getRoot();
+ IProject project = root.getProject(MAP_PROJECT_NAME);
+ return project;
+ }
+
+ public MapProject(IProject p) throws CoreException {
+ this.project = p;
+ loadMapFiles();
+ ResourcesPlugin.getWorkspace().addResourceChangeListener(this,
+ IResourceChangeEvent.POST_CHANGE);
+ }
+
+ public IProject getProject() {
+ return project;
+ }
+
+ public void setProject(IProject p) {
+ this.project = p;
+ }
+
+ private MapFile getMapFile(IProject p) {
+ for (int i = 0; i < mapFiles.length; i++) {
+ if (mapFiles[i].contains(p)) {
+ return mapFiles[i];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return the MapEntry for the given project
+ *
+ * @param string
+ * @param string1
+ */
+ public MapEntry getMapEntry(IProject p) {
+ MapFile file = getMapFile(p);
+ if (file != null) {
+ return file.getMapEntry(p);
+ }
+ return null;
+ }
+
+ public boolean mapsAreLoaded() {
+ return project.exists();
+ }
+
+ public MapFile[] getValidMapFiles() {
+ List list = new ArrayList();
+ for (int i = 0; i < mapFiles.length; i++) {
+ IProject[] projects = mapFiles[i].getAccessibleProjects();
+ if (projects != null && projects.length > 0) {
+ list.add(mapFiles[i]);
+ }
+ }
+ return (MapFile[]) list.toArray(new MapFile[list.size()]);
+ }
+
+ /**
+ * @param aProject
+ * The map entry of the specified project will be changed to the
+ * specified tag
+ * @param tag
+ * The specified tag
+ * @return returns if no map file having such a map entry is found
+ */
+ public void updateFile(IProject aProject, String tag) throws CoreException {
+ MapFile aFile = getMapFile(aProject);
+ if (aFile == null)
+ return;
+ MapContentDocument changed = new MapContentDocument(aFile);
+ changed.updateTag(aProject, tag);
+ if (changed.isChanged()) {
+ aFile.getFile().setContents(changed.getContents(),
+ IFile.KEEP_HISTORY, null);
+ }
+ }
+
+ public void commitMapProject(String comment, IProgressMonitor monitor)
+ throws CoreException {
+ // try {
+ // new CommitOperation(null,
+ // RepositoryProviderOperation.asResourceMappers(new IResource[] {
+ // project }), new Command.LocalOption[0], comment).run(monitor);
+ // } catch (InvocationTargetException e) {
+ // throw TeamException.asTeamException(e);
+ // } catch (InterruptedException e) {
+ // // Ignore;
+ // e.printStackTrace();
+ // }
+ }
+
+ public MapFile[] getMapFilesFor(IProject[] projects) {
+ Set alist = new HashSet();
+ for (int i = 0; i < projects.length; i++) {
+ MapFile aMapFile = getMapFile(projects[i]);
+ alist.add(aMapFile);
+ }
+ return (MapFile[]) alist.toArray(new MapFile[alist.size()]);
+ }
+
+ /**
+ * Get the tags for the given projects. If no tag is found for whatever
+ * reason, HEAD is used.
+ *
+ * @param projects
+ * @return
+ */
+ public GitTag[] getTagsFor(IProject[] projects) {
+ if (projects == null || projects.length == 0)
+ return null;
+ GitTag[] tags = new GitTag[projects.length];
+ for (int i = 0; i < tags.length; i++) {
+ MapEntry entry = getMapEntry(projects[i]);
+ if (entry == null)
+ tags[i] = MapEntry.DEFAULT;
+ else
+ tags[i] = entry.getTag();
+ }
+ return tags;
+ }
+
+ /**
+ * Deregister the IResourceChangeListner. It is reserved for use in the
+ * future. It is never called for now
+ */
+ public void dispose() {
+ ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
+ mapFiles = null;
+ }
+
+ /**
+ * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent)
+ */
+ public void resourceChanged(IResourceChangeEvent event) {
+ IResourceDelta root = event.getDelta();
+
+ // TODO: Need to add code to handle map project deletion, addition and
+ // rename
+ IResourceDelta folderDelta = root.findMember(getMapFolder()
+ .getFullPath());
+ if (folderDelta == null)
+ return;
+
+ // Handle map files deletion, addition and rename
+ IResourceDelta[] deltas = folderDelta.getAffectedChildren();
+ if (deltas == null || deltas.length == 0)
+ return;
+ for (int i = 0; i < deltas.length; i++) {
+ IResourceDelta delta = deltas[i];
+ if (delta.getResource().getType() == IResource.FILE) {
+ try {
+ IFile aFile = (IFile) (delta.getResource());
+ MapFile mFile = null;
+ if (MapFile.isMapFile(aFile)) {
+ // Handle content change
+ if (delta.getKind() == IResourceDelta.CHANGED) {
+ mFile = getMapFileFor(aFile);
+ mFile.loadEntries();
+ }
+ // Handle deletion. We cannot simply remove the map file
+ // directly bacause we have to call
+ // getMapFileFor(IFile) in order to do so. But the IFile
+ // is already deleted. So we have to
+ // reconstuct the map files.
+ if (delta.getKind() == IResourceDelta.REMOVED) {
+ loadMapFiles();
+ }
+ // Handle addition
+ if (delta.getKind() == IResourceDelta.ADDED) {
+ mFile = getMapFileFor(aFile);
+ addMapFile(mFile);
+ }
+ }
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private IFolder getMapFolder() {
+ return getProject().getFolder(MAP_FOLDER);
+ }
+
+ private void loadMapFiles() throws CoreException {
+ mapFiles = MapFile.findAllMapFiles(project);
+ }
+
+ private MapFile getMapFileFor(IFile file) throws CoreException {
+ for (int i = 0; i < mapFiles.length; i++) {
+ if (mapFiles[i].getFile().equals(file))
+ return mapFiles[i];
+ }
+ return new MapFile(file);
+ }
+
+ private void addMapFile(MapFile aFile) {
+ Set set = new HashSet(Arrays.asList(mapFiles));
+ set.add(aFile);
+ mapFiles = (MapFile[]) set.toArray(new MapFile[set.size()]);
+ }
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapProjectSelectionPage.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapProjectSelectionPage.java
new file mode 100755
index 0000000..8f556c3
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/MapProjectSelectionPage.java
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2010 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.egit.internal.relengtools;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ListViewer;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.List;
+import org.eclipse.team.core.RepositoryProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+public class MapProjectSelectionPage extends WizardPage {
+
+ private MapProject selectedMapProject;
+
+ private IDialogSettings settings;
+
+ private ListViewer mapProjectListViewer;
+
+ protected Button useDefaultProjectButton;
+
+ protected boolean useDefaultMapProject;
+
+ private final String SELECTED_PROJECT_KEY = "Selected Project"; //$NON-NLS-1$
+
+ public MapProjectSelectionPage(String pageName, String title,
+ IDialogSettings settings, ImageDescriptor image) {
+ super(pageName, title, image);
+ this.settings = settings;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets
+ * .Composite)
+ */
+ public void createControl(Composite parent) {
+ Composite topContainer = new Composite(parent, SWT.NONE);
+ topContainer.setLayout(new GridLayout());
+ topContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ mapProjectListViewer = createListViewer(topContainer);
+ mapProjectListViewer.setInput(getMapFileProjects());
+ useDefaultProjectButton = new Button(topContainer, SWT.CHECK);
+ useDefaultProjectButton.setText(Messages
+ .getString("MapProjectSelectionPage.0")); //$NON-NLS-1$
+ useDefaultProjectButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ useDefaultMapProject = (useDefaultProjectButton.getSelection());
+ updateOthers();
+ }
+ });
+
+ Dialog.applyDialogFont(parent);
+ initializedViewer();
+ setControl(topContainer);
+ }
+
+ protected ListViewer createListViewer(Composite parent) {
+ List tree = new List(parent, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.heightHint = tree.getItemHeight() * 15;
+ tree.setLayoutData(gd);
+ ListViewer result = new ListViewer(tree);
+ result.setContentProvider(new IStructuredContentProvider() {
+ public Object[] getElements(Object inputElement) {
+ Set projects = (Set) inputElement;
+ return ((IProject[]) projects.toArray(new IProject[projects
+ .size()]));
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput,
+ Object newInput) {
+ }
+ });
+ result.setLabelProvider(new WorkbenchLabelProvider());
+ result.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ updateOthers();
+ }
+ });
+ // result.setComparator((new
+ // ResourceComparator(ResourceComparator.NAME)));
+ return result;
+ }
+
+ private static Set getMapFileProjects() {
+ Set projects = new HashSet();
+ MapFile[] mapFiles;
+ try {
+ mapFiles = MapFile.findAllMapFiles(ResourcesPlugin.getWorkspace()
+ .getRoot());
+ } catch (CoreException ex) {
+ return Collections.EMPTY_SET;
+ }
+ for (int i = 0; i < mapFiles.length; i++)
+ projects.add(mapFiles[i].getFile().getProject());
+ for (Iterator iterator = projects.iterator(); iterator.hasNext();) {
+ MapProject mapProject = null;
+ try {
+ mapProject = new MapProject((IProject) iterator.next());
+ if (mapProject.getValidMapFiles().length == 0)
+ iterator.remove();
+ } catch (CoreException e) {
+ iterator.remove();
+ } finally {
+ if (mapProject != null)
+ mapProject.dispose();
+ }
+
+ }
+ return projects;
+ }
+
+ private void updateMapProject() {
+ if (selectedMapProject != null) {
+ selectedMapProject.dispose();
+ selectedMapProject = null;
+ }
+
+ IStructuredSelection selection = (IStructuredSelection) mapProjectListViewer
+ .getSelection();
+ if (!selection.isEmpty()) {
+ Object obj = selection.getFirstElement();
+ if (obj instanceof IProject) {
+ try {
+ selectedMapProject = new MapProject((IProject) obj);
+ } catch (CoreException e) {
+ selectedMapProject = null;
+ }
+ }
+ }
+ setPageComplete(isValid(selectedMapProject));
+ }
+
+ /*
+ * @see org.eclipse.jface.dialogs.DialogPage#dispose()
+ *
+ * @since 3.7
+ */
+ public void dispose() {
+ if (selectedMapProject != null) {
+ selectedMapProject.dispose();
+ selectedMapProject = null;
+ }
+ super.dispose();
+ }
+
+ private void initializedViewer() {
+ readSettings();
+ updateOthers();
+ }
+
+ protected void updateOthers() {
+ updateMapProject();
+ }
+
+ private void readSettings() {
+ String name = settings.get(SELECTED_PROJECT_KEY);
+ if (name != null) {
+ ISelection selection = new StructuredSelection(ResourcesPlugin
+ .getWorkspace().getRoot().getProject(name));
+ mapProjectListViewer.setSelection(selection);
+ }
+ mapProjectListViewer.getList().setFocus();
+ }
+
+ public void saveSettings() {
+ IStructuredSelection selection = (IStructuredSelection) mapProjectListViewer
+ .getSelection();
+ if (!selection.isEmpty()) {
+ Object obj = selection.getFirstElement();
+ if (obj instanceof IProject) {
+ settings.put(SELECTED_PROJECT_KEY, ((IProject) obj).getName());
+ }
+ }
+ }
+
+ private boolean isValid(final MapProject mapProject) {
+ // Check if map project is accessible
+ if (mapProject == null || (!mapProject.getProject().isAccessible())) {
+ setErrorMessage(Messages.getString("MapProjectSelectionPage.1")); //$NON-NLS-1$
+ return false;
+ }
+
+ // Check if the map project is shared
+ if (RepositoryProvider.getProvider(mapProject.getProject()) == null) {
+ setErrorMessage(Messages.getString("MapProjectSelectionPage.2") + mapProject.getProject().getName() + Messages.getString("MapProjectSelectionPage.3")); //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ }
+ setErrorMessage(null);
+ if (getWizard() instanceof ReleaseWizard)
+ ((ReleaseWizard) getWizard()).broadcastMapProjectChange(mapProject);
+ return true;
+ }
+
+ // Used by MapProjectSelectionWizard for storing preferences
+ protected MapProject getSelectedMapProject() {
+ return selectedMapProject;
+ }
+
+ // Used by MapProjectSelectionWizard for storing preferences
+ protected boolean useDefaultMapProject() {
+ return useDefaultMapProject;
+ }
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/Messages.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/Messages.java
new file mode 100755
index 0000000..34a2eb8
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/Messages.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 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.egit.internal.relengtools;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+ private static final String BUNDLE_NAME = "org.eclipse.releng.tools.messages";//$NON-NLS-1$
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+ .getBundle(BUNDLE_NAME);
+
+ private Messages() {
+ // TODO Auto-generated constructor stub
+ }
+
+ public static String getString(String key) {
+ // TODO Auto-generated method stub
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/OrderedMap.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/OrderedMap.java
new file mode 100755
index 0000000..27e677b
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/OrderedMap.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 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.egit.internal.relengtools;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Don't implement the Map interface because we don't want people calling
+ * #entrySet because order is important.
+ */
+public class OrderedMap {
+
+ private List keys = new ArrayList();
+
+ private List values = new ArrayList();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#clear()
+ */
+ public void clear() {
+ keys = new ArrayList();
+ values = new ArrayList();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#containsKey(java.lang.Object)
+ */
+ public boolean containsKey(Object key) {
+ for (Iterator iter = keys.iterator(); iter.hasNext();) {
+ if (key.equals(iter.next()))
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#containsValue(java.lang.Object)
+ */
+ public boolean containsValue(Object value) {
+ for (Iterator iter = values.iterator(); iter.hasNext();) {
+ if (value.equals(iter.next()))
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#get(java.lang.Object)
+ */
+ public Object get(Object key) {
+ int index = indexOf(key);
+ return index == -1 ? null : values.get(index);
+ }
+
+ private int indexOf(Object key) {
+ int length = keys.size();
+ for (int i = 0; i < length; i++) {
+ Object tempKey = keys.get(i);
+ if (key.equals(tempKey))
+ return i;
+ }
+ return -1;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#isEmpty()
+ */
+ public boolean isEmpty() {
+ return keys.size() == 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#put(java.lang.Object, java.lang.Object)
+ */
+ public Object put(Object key, Object value) {
+ int index = indexOf(key);
+ if (index == -1) {
+ keys.add(key);
+ values.add(value);
+ return null;
+ }
+ Object oldValue = values.get(index);
+ values.set(index, value);
+ return oldValue;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#putAll(java.util.Map)
+ */
+ public void putAll(Map other) {
+ for (Iterator iter = other.entrySet().iterator(); iter.hasNext();) {
+ Object key = iter.next();
+ put(key, other.get(key));
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#remove(java.lang.Object)
+ */
+ public Object remove(Object key) {
+ int index = indexOf(key);
+ if (index == -1)
+ return null;
+ keys.remove(index);
+ return values.remove(index);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#size()
+ */
+ public int size() {
+ return keys.size();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#values()
+ */
+ public Collection values() {
+ return values;
+ }
+
+ public Collection keys() {
+ return keys;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer result = new StringBuffer();
+ result.append("{"); //$NON-NLS-1$
+ for (Iterator iter = keys().iterator(); iter.hasNext();) {
+ Object key = iter.next();
+ Object value = get(key);
+ result.append(key);
+ result.append('=');
+ result.append(value);
+ result.append(",\n"); //$NON-NLS-1$
+ }
+ // delete last 2 chars... comma and new-line
+ if (result.length() > 2) {
+ result = result.deleteCharAt(result.length() - 1);
+ result = result.deleteCharAt(result.length() - 1);
+ }
+ result.append("}"); //$NON-NLS-1$
+ return result.toString();
+ }
+
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/ProjectSelectionPage.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/ProjectSelectionPage.java
new file mode 100755
index 0000000..6761ffb
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/ProjectSelectionPage.java
@@ -0,0 +1,350 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 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.egit.internal.relengtools;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+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.Label;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.jface.wizard.WizardPage;
+
+import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.views.navigator.ResourceComparator;
+
+/**
+ * This class extends
+ * <code>WizardPage<code> class and use a <code>CheckboxTreeViewer<code> to
+ * display selectable items.
+ */
+public class ProjectSelectionPage extends WizardPage {
+ private CheckboxTreeViewer viewer;
+
+ private IDialogSettings settings;
+
+ private Button compareButton;
+
+ private boolean compareButtonChecked;
+
+ private String SELECTED_ITEMS_KEY = Messages
+ .getString("ProjectSelectionPage.0"); //$NON-NLS-1$
+
+ private String COMPARE_BUTTON_KEY = Messages
+ .getString("ProjectSelectionPage.1"); //$NON-NLS-1$
+
+ private MapProject mapProject;
+
+ private class MapFileLabelProvider extends LabelProvider {
+ WorkbenchLabelProvider provider = new WorkbenchLabelProvider();
+
+ public String getText(Object element) {
+ if (element instanceof MapFile) {
+ return ((MapFile) element).getName();
+ }
+ return provider.getText(element);
+ }
+
+ public Image getImage(Object element) {
+ if (element instanceof MapFile) {
+ return provider.getImage(((MapFile) element).getFile());
+ }
+ return provider.getImage(element);
+ }
+
+ public void dispose() {
+ provider.dispose();
+ super.dispose();
+ }
+ }
+
+ public ProjectSelectionPage(String pageName, String title,
+ IDialogSettings settings, ImageDescriptor image) {
+ super(pageName, title, image);
+ this.settings = settings;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets
+ * .Composite)
+ */
+ public void createControl(Composite parent) {
+ Font font = parent.getFont();
+
+ Composite topContainer = new Composite(parent, SWT.NONE);
+ topContainer.setLayout(new GridLayout());
+ topContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Label label = new Label(topContainer, SWT.HORIZONTAL);
+ label.setFont(font);
+ label.setText(Messages.getString("ProjectSelectionPage.2")); //$NON-NLS-1$
+
+ viewer = new ContainerCheckedTreeViewer(topContainer, SWT.SINGLE
+ | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.heightHint = viewer.getTree().getItemHeight() * 15;
+ viewer.getTree().setLayoutData(gd);
+ viewer.getTree().setFont(font);
+ viewer.setLabelProvider(new MapFileLabelProvider());
+ viewer.setContentProvider(getContentProvider());
+ viewer.setComparator(new ResourceComparator(ResourceComparator.NAME) {
+ public int compare(Viewer viewer, Object o1, Object o2) {
+ if (o1 instanceof MapFile && o2 instanceof MapFile) {
+ return super.compare(viewer, ((MapFile) o1).getFile(),
+ ((MapFile) o2).getFile());
+ }
+ return super.compare(viewer, o1, o2);
+ }
+ });
+ viewer.setInput(mapProject);
+ viewer.expandAll();
+ viewer.addCheckStateListener(new ICheckStateListener() {
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ updatePageComplete();
+ }
+ });
+
+ compareButton = new Button(topContainer, SWT.CHECK);
+ compareButton.setText(Messages.getString("ProjectSelectionPage.3")); //$NON-NLS-1$
+ compareButton.setFont(font);
+ compareButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ compareButtonChecked = compareButton.getSelection();
+ }
+ });
+
+ initialize();
+ setControl(topContainer);
+ }
+
+ /**
+ * Returns the content provider for the viewer
+ */
+ private IContentProvider getContentProvider() {
+ return new WorkbenchContentProvider() {
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof MapProject) {
+ return mapProject.getValidMapFiles();
+ }
+ if (parentElement instanceof MapFile) {
+ return ((MapFile) parentElement).getAccessibleProjects();
+ }
+ return null;
+ }
+
+ /*
+ * @see
+ * org.eclipse.ui.model.BaseWorkbenchContentProvider#getParent(java
+ * .lang.Object)
+ *
+ * @since 3.7
+ */
+ public Object getParent(Object element) {
+ if (mapProject == null)
+ return null;
+
+ if (element instanceof MapFile) {
+ return mapProject;
+ }
+ if (element instanceof IProject) {
+ MapFile[] mapFiles = mapProject.getValidMapFiles();
+ for (int i = 0; i < mapFiles.length; i++) {
+ if (mapFiles[i].contains((IProject) element))
+ return mapFiles[i];
+ }
+ }
+ return super.getParent(element);
+ }
+
+ public boolean hasChildren(Object element) {
+ if (element instanceof MapFile) {
+ return ((MapFile) element).getAccessibleProjects().length > 0;
+ }
+ return false;
+ }
+ };
+ }
+
+ /**
+ * Returns all the checked items if they are IProject
+ */
+ public IProject[] getCheckedProjects() {
+ ArrayList projectsToRelease = new ArrayList();
+ Object[] obj = viewer.getCheckedElements();
+ if (obj == null)
+ return null;
+ for (int i = 0; i < obj.length; i++) {
+ if (obj[i] instanceof IProject)
+ projectsToRelease.add(obj[i]);
+ }
+ return (IProject[]) projectsToRelease
+ .toArray(new IProject[projectsToRelease.size()]);
+ }
+
+ private void readProjectSettings() {
+ if (settings == null)
+ return;
+ if (settings.getArray(SELECTED_ITEMS_KEY) != null) {
+ ArrayList nameList = new ArrayList(Arrays.asList(settings
+ .getArray(SELECTED_ITEMS_KEY)));
+ if (nameList != null) {
+ Iterator iter = nameList.iterator();
+ while (iter.hasNext()) {
+ String name = (String) iter.next();
+ IProject project = getProjectWithName(name);
+ if (project != null) {
+ viewer.setChecked(project, true);
+ }
+ }
+ }
+ }
+ }
+
+ private void initCompareEnablement() {
+ if (settings == null || settings.get(COMPARE_BUTTON_KEY) == null) {
+ compareButton.setSelection(true);
+ compareButtonChecked = true;
+ return;
+ } else {
+ boolean b = settings.getBoolean(COMPARE_BUTTON_KEY);
+ compareButton.setSelection(b);
+ compareButtonChecked = b;
+ }
+ }
+
+ /**
+ * Save the checked items and the checkbox options to dialog settings
+ */
+ public void saveSettings() {
+ Object[] obj = viewer.getCheckedElements();
+ ArrayList names = new ArrayList();
+ for (int i = 0; i < obj.length; i++) {
+ if (obj[i] instanceof IProject) {
+ names.add(((IProject) obj[i]).getName());
+ }
+ }
+ settings.put(SELECTED_ITEMS_KEY,
+ (String[]) names.toArray(new String[names.size()]));
+ settings.put(COMPARE_BUTTON_KEY, compareButtonChecked);
+ }
+
+ /*
+ * @see
+ * org.eclipse.jface.wizard.WizardPage#setPreviousPage(org.eclipse.jface
+ * .wizard.IWizardPage)
+ *
+ * @since 3.7
+ */
+ public void setPreviousPage(IWizardPage page) {
+ super.setPreviousPage(page);
+ updatePageComplete();
+ }
+
+ private void initialize() {
+ initCheckedProjects();
+ initCompareEnablement();
+ updatePageComplete();
+ }
+
+ private void initCheckedProjects() {
+ IProject[] p = ((ReleaseWizard) getWizard()).getPreSelectedProjects();
+ if (p != null) {
+ viewer.setCheckedElements(p);
+ } else {
+ readProjectSettings();
+ }
+ }
+
+ /**
+ * Called by
+ * <code>readSettings()<code> to return the project associated with the given name
+ */
+ private IProject getProjectWithName(String name) {
+ IProject project = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject(name);
+ if (project.exists() && project.isAccessible())
+ return project;
+ return null;
+ }
+
+ public boolean isCompareButtonChecked() {
+ return compareButtonChecked;
+ }
+
+ /**
+ * This page will not complete until at least one project is checked
+ */
+ private void updatePageComplete() {
+ Object[] obj = viewer.getCheckedElements();
+ if (obj.length > 0) {
+ for (int i = 0; i < obj.length; i++) {
+ // Exclude the situation that an empty shown map file is
+ // selected
+ if (obj[i] instanceof IProject) {
+ setPageComplete(true);
+ break;
+ }
+ }
+ } else {
+ setPageComplete(false);
+ }
+ }
+
+ private CheckboxTreeViewer getViewer() {
+ return viewer;
+ }
+
+ public void setSelection(IProject[] projects) {
+ if (projects != null && projects.length > 0) {
+ getViewer().setCheckedElements(projects);
+ }
+ }
+
+ public void updateMapProject(MapProject m) {
+ mapProject = m;
+ if (viewer != null) {
+ Object[] checkedElements = null;
+ if (m != null && mapProject != null
+ && m.getProject().equals(mapProject.getProject()))
+ checkedElements = viewer.getCheckedElements();
+ viewer.setInput(mapProject);
+ viewer.expandAll();
+ if (checkedElements != null)
+ viewer.setCheckedElements(checkedElements);
+ }
+ }
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/ReleaseWizard.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/ReleaseWizard.java
new file mode 100644
index 0000000..e624f3d
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/ReleaseWizard.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.egit.internal.relengtools;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.DialogSettings;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+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.swt.widgets.Shell;
+
+public class ReleaseWizard extends Wizard {
+
+ private Dialog parentDialog;
+
+ private ArrayList<IProject> preSelectedProjects;
+
+ private final IDialogSettings section = new DialogSettings("Section");
+
+ private MapProject mapProject;
+
+ private MapProjectSelectionPage mapSelectionPage;
+
+ private ProjectSelectionPage projectSelectionPage;
+
+ private IProject[] selectedProjects;
+
+ private TagPage tagPage;
+
+ private BuildNotesPage buildNotesPage;
+
+ @Override
+ public boolean performFinish() {
+ if (!isProjectSelected())
+ return false;
+ try {
+ getContainer().run(true, true, new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor)
+ throws InvocationTargetException, InterruptedException {
+ monitor.beginTask("Processing", 1 + selectedProjects.length);
+ monitor.worked(1);
+ final String tag = tagPage.getTagString();
+ System.out.println("Processing tag: " + tag);
+ for (final IProject proj : selectedProjects) {
+ monitor.worked(1);
+ System.out.println("processing: " + proj);
+ try {
+ mapProject.updateFile(proj, tag);
+ } catch (final CoreException e) {
+ e.printStackTrace();
+ }
+ }
+ monitor.done();
+ }
+ });
+ return true;
+ } catch (final InvocationTargetException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (final InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ private boolean isProjectSelected() {
+ if (selectedProjects == null || selectedProjects.length == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ public void setPreSelection(ArrayList<IProject> selection) {
+ preSelectedProjects = selection;
+ }
+
+ public boolean execute(Shell shell) {
+ setNeedsProgressMonitor(true);
+ final WizardDialog dialog = new WizardDialog(shell, this);
+ setParentDialog(dialog);
+ return (dialog.open() == Window.OK);
+ }
+
+ public void setParentDialog(Dialog p) {
+ this.parentDialog = p;
+ }
+
+ @Override
+ public void addPages() {
+ addMapSelectionPage();
+ }
+
+ private void addMapSelectionPage() {
+ mapSelectionPage = new MapProjectSelectionPage(
+ "MapProjectSelectionPage", "Map Project Selection", section,
+ null);
+ mapSelectionPage.setDescription("Map Project Selection"); //$NON-NLS-1$
+ addPage(mapSelectionPage);
+
+ projectSelectionPage = new ProjectSelectionPage("ProjectSelectionPage", //$NON-NLS-1$
+ Messages.getString("ReleaseWizard.6"), //$NON-NLS-1$
+ section, null);
+ 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, null);
+ tagPage.setDescription(Messages.getString("ReleaseWizard.10")); //$NON-NLS-1$
+ addPage(tagPage);
+
+ buildNotesPage = new BuildNotesPage("Build Notes Page", //$NON-NLS-1$
+ Messages.getString("ReleaseWizard.1"), //$NON-NLS-1$
+ section, null);
+ buildNotesPage.setDescription(Messages.getString("ReleaseWizard.0")); //$NON-NLS-1$
+ addPage(buildNotesPage);
+ }
+
+ @Override
+ public IWizardPage getNextPage(IWizardPage page) {
+ if (page == mapSelectionPage) {
+ // if (selectedProjects == null && preSelectedProjectsArr != null) {
+ // projectSelectionPage.setSelection(preSelectedProjectsARrr);
+ // selectedProjects= preSelectedProjects;
+ // }
+ return projectSelectionPage;
+ }
+ if (page == projectSelectionPage) {
+ final IProject[] projects = projectSelectionPage
+ .getCheckedProjects();
+ if (projects != null && projects.length > 0) {
+ selectedProjects = projects;
+ }
+
+ if (projectSelectionPage.isCompareButtonChecked()) {
+ return buildNotesPage;
+ } else
+ return tagPage;
+ }
+ if (page == buildNotesPage) {
+ return tagPage;
+ }
+ // if (page == tagPage) {
+ // if (tagPage.compareButtonSelected()){
+ // mapComparePage.setTag(tagPage.getTagString());
+ // return mapComparePage;
+ // }
+ // if (tagPage.commitButtonSelected())
+ // return commentPage;
+ // }
+ return null;
+ }
+
+ public MapProject getMapProject() {
+ return mapProject;
+ }
+
+ public void broadcastMapProjectChange(MapProject m) {
+ mapProject = m;
+ projectSelectionPage.updateMapProject(m);
+ // projectComparePage.updateMapProject(m);
+ // mapComparePage.updateMapProject(m);
+ }
+
+ public IProject[] getPreSelectedProjects() {
+ return preSelectedProjects.toArray(new IProject[preSelectedProjects
+ .size()]);
+ }
+
+ // 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;
+ }
+
+ public IProject[] getSelectedProjects() {
+ return selectedProjects;
+ }
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/RepoCheck.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/RepoCheck.java
new file mode 100644
index 0000000..f53b2b5
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/RepoCheck.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.egit.internal.relengtools;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.jgit.storage.file.FileRepository;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+
+public class RepoCheck {
+
+ private File repoDir;
+
+ private FileRepository repo;
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ if (args.length == 0) {
+ System.err.println("USAGE: " + RepoCheck.class.getName()
+ + " /path/to/repo");
+ return;
+ }
+ try {
+ RepoCheck check = new RepoCheck(args[0]);
+ check.build();
+ check.displayInfo();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void displayInfo() throws IOException {
+ System.out.println("current branch: " + repo.getBranch());
+ }
+
+ public RepoCheck(String repoDirectory) {
+ repoDir = new File(repoDirectory);
+ }
+
+ public void build() throws IOException {
+ FileRepositoryBuilder builder = new FileRepositoryBuilder();
+ builder.setWorkTree(repoDir);
+ repo = builder.readEnvironment().findGitDir(repoDir).build();
+ }
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/ShowInfoHandler.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/ShowInfoHandler.java
new file mode 100644
index 0000000..f6f0e16
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/ShowInfoHandler.java
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Copyright (C) 2011, Chris Aniszczyk <caniszczyk@gmail.com>
+ *
+ * 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:
+ * Chris Aniszczyk - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.egit.internal.relengtools;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.LogCommand;
+import org.eclipse.jgit.api.errors.NoHeadException;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevSort;
+import org.eclipse.jgit.revwalk.RevTag;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilter;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.internal.util.Util;
+
+public class ShowInfoHandler extends AbstractHandler implements
+ IExecutableExtension {
+ static final String OLD_TAG = "v20100723-1115";
+
+ static final String NEW_TAG = "v20101018-1500";
+
+ private boolean runTest = false;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.
+ * ExecutionEvent)
+ */
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ if (runTest) {
+ try {
+ runTest();
+ } catch (final Exception e) {
+ throw new ExecutionException(e.getMessage(), e);
+ }
+ return null;
+ }
+ // show info on an existing project
+ final ISelection s = HandlerUtil.getCurrentSelection(event);
+ if (s instanceof IStructuredSelection) {
+ final Object obj = ((IStructuredSelection) s).getFirstElement();
+ final IProject proj = (IProject) Util.getAdapter(obj,
+ IProject.class);
+ if (proj != null) {
+ try {
+ showInfo(proj);
+ } catch (final Exception e) {
+ throw new ExecutionException(e.getMessage(), e);
+ }
+ }
+ }
+ return null;
+ }
+
+ private void runTest() throws Exception {
+ // first test project
+ deeplinkTest();
+
+ // second test project
+ handlerTest();
+ }
+
+ private void deeplinkTest() throws Exception {
+ final IProject deeplink = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject("org.eclipse.e4.core.deeplink");
+ System.out.println("\nTest for project: " + deeplink);
+ final RepositoryMapping rm = RepositoryMapping.getMapping(deeplink);
+ final Repository repo = rm.getRepository();
+ final RevCommit expectedLastCommit = getCommit(repo,
+ "d660f0a07c8ff16c9b46b3d69bc1c271b2cf4aba");
+ final RevCommit latestCommit = getLatestCommitFor(rm, repo, deeplink);
+ System.out.println(expectedLastCommit.equals(latestCommit)
+ + " Latest commit: expected: " + expectedLastCommit
+ + "\n\tgot: " + latestCommit);
+
+ final Map<String, Ref> tags = repo.getTags();
+ final Set<Ref> expectedTags = new HashSet<Ref>(Arrays.asList(tags
+ .get(NEW_TAG)));
+ final Set<Ref> twoTags = getTagsForCommit(repo, expectedLastCommit);
+ System.out.println(expectedTags.equals(twoTags)
+ + " Found tags: expected: " + expectedTags + "\n\tgot: "
+ + twoTags);
+
+ final Set<Ref> tagsContainingCommit = getTagsContainingCommit(repo,
+ expectedLastCommit);
+ System.out.println(expectedTags.equals(tagsContainingCommit)
+ + " Found tags containing commit " + expectedLastCommit
+ + ":\n\texpected: " + expectedTags + "\n\tgot: "
+ + tagsContainingCommit);
+ }
+
+ private void handlerTest() throws Exception {
+ final IProject handler = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject("org.eclipse.e4.core.deeplink.handler");
+ System.out.println("\nTest for project: " + handler);
+ final RepositoryMapping rm = RepositoryMapping.getMapping(handler);
+ final Repository repo = rm.getRepository();
+ final RevCommit expectedLastCommit = getCommit(repo,
+ "b42ad39c90fc57b679154ca33dfb306004dc08a3");
+ final RevCommit latestCommit = getLatestCommitFor(rm, repo, handler);
+ System.out.println(expectedLastCommit.equals(latestCommit)
+ + " Latest commit: expected: " + expectedLastCommit
+ + "\n\tgot: " + latestCommit);
+
+ final Set<Ref> expectedTags = Collections.EMPTY_SET;
+ final Set<Ref> noTags = getTagsForCommit(repo, expectedLastCommit);
+ System.out.println(expectedTags.equals(noTags)
+ + " Found tags: expected: " + expectedTags + "\n\tgot: "
+ + noTags);
+
+ final Map<String, Ref> tags = repo.getTags();
+ final Set<Ref> expectedContainingTags = new HashSet<Ref>(Arrays.asList(
+ tags.get("R0_10"), tags.get("v20100722-1700"),
+ tags.get("v20100723-1115"), tags.get("v20101018-1500")));
+ final Set<Ref> tagsContainingCommit = getTagsContainingCommit(repo,
+ expectedLastCommit);
+ System.out.println(expectedContainingTags.equals(tagsContainingCommit)
+ + " Found tags containing commit " + expectedLastCommit
+ + ":\n\texpected: " + expectedContainingTags + "\n\tgot: "
+ + tagsContainingCommit);
+ }
+
+ /**
+ * @param proj
+ * @throws Exception
+ */
+ private void showInfo(IProject proj) throws Exception {
+ final RepositoryMapping rm = RepositoryMapping.getMapping(proj);
+ final Repository repo = rm.getRepository();
+
+ // final RevCommit latestCommit = getLatestCommitFor(rm, repo, proj);
+ final RevCommit latestCommit = getLatestCommitFor(rm, repo, proj);
+ System.out
+ .println(latestCommit + ": " + latestCommit.getShortMessage());
+
+ final RevCommit oldCommit = getCommitForTag(repo, OLD_TAG);
+
+ final RevCommit newCommit = getCommitForTag(repo, NEW_TAG);
+
+ System.out.println(getTagsForCommit(repo, newCommit));
+ System.out.println(getTagsForCommit(repo, newCommit));
+ System.out.println(getTagsForCommit(repo,
+ getCommit(repo, "b42ad39c90fc57b679154ca33dfb306004dc08a3")));
+
+ showLogBetween(repo, oldCommit, newCommit);
+ }
+
+ public static void showLogBetween(final Repository repo,
+ final RevCommit oldCommit, final RevCommit newCommit)
+ throws MissingObjectException, IncorrectObjectTypeException,
+ NoHeadException, Exception {
+ final Git git = new Git(repo);
+ final LogCommand command = git.log();
+ command.addRange(oldCommit, newCommit);
+ System.out.println("\nCommits:");
+ for (final RevCommit rc : command.call()) {
+ System.out.println(rc);
+ System.out.print("Tags: ");
+ System.out.println(getTagsForCommit(repo, rc));
+ System.out.println(rc.getShortMessage());
+ }
+ }
+
+ public static RevCommit getLatestCommitFor(RepositoryMapping mapping,
+ Repository repo, IProject project) throws Exception {
+ final RevWalk walk = new RevWalk(repo);
+ walk.reset();
+ walk.sort(RevSort.TOPO, true);
+ walk.sort(RevSort.COMMIT_TIME_DESC, true);
+ walk.setTreeFilter(AndTreeFilter.create(TreeFilter.ANY_DIFF,
+ PathFilter.create(mapping.getRepoRelativePath(project))));
+ final ObjectId start = repo.resolve(Constants.HEAD);
+ walk.markStart(walk.parseCommit(start));
+
+ // I should only be able to see commits that contain files
+ // where project is a path prefix
+ final RevCommit commit = walk.next();
+ return commit;
+ }
+
+ public static RevCommit getCommitForTag(Repository repo, String name)
+ throws Exception {
+ final Ref ref = repo.getTags().get(name);
+ final RevWalk walk = new RevWalk(repo);
+ final RevObject obj = walk.parseAny(ref.getObjectId());
+ final RevCommit tagCommit;
+ if (obj instanceof RevCommit) {
+ tagCommit = (RevCommit) obj;
+ } else {
+ tagCommit = walk.parseCommit(((RevTag) obj).getObject());
+ }
+ return tagCommit;
+ }
+
+ public static Set<Ref> getTagsForCommit(Repository repo, RevCommit c)
+ throws Exception {
+ initializeTagMap(repo);
+ Set<Ref> s = commitToTagRef.get(c);
+ if (s == null) {
+ s = Collections.EMPTY_SET;
+ }
+ return s;
+ }
+
+ private static HashMap<RevCommit, Set<Ref>> commitToTagRef = null;
+
+ private static void initializeTagMap(Repository repo) throws Exception {
+ if (commitToTagRef == null) {
+ final RevWalk walk = new RevWalk(repo);
+ commitToTagRef = new HashMap<RevCommit, Set<Ref>>();
+ for (final Ref ref : repo.getTags().values()) {
+ final RevObject obj = walk.parseAny(ref.getObjectId());
+ RevCommit commit = null;
+ if (obj instanceof RevCommit) {
+ commit = (RevCommit) obj;
+ } else if (obj instanceof RevTag) {
+ commit = walk.parseCommit(((RevTag) obj).getObject());
+ }
+
+ Set<Ref> tags = commitToTagRef.get(commit);
+ if (tags == null) {
+ tags = new HashSet<Ref>();
+ commitToTagRef.put(commit, tags);
+ }
+ tags.add(ref);
+ }
+ }
+ }
+
+ // mimic git tag --contains <commit>
+ private static Set<Ref> getTagsContainingCommit(Repository repo,
+ RevCommit commit) throws Exception {
+ final Set<Ref> tags = new HashSet<Ref>();
+ final RevWalk walk = new RevWalk(repo);
+ commit = walk.parseCommit(commit);
+ for (final Ref ref : repo.getTags().values()) {
+ final RevCommit tagCommit;
+ try {
+ tagCommit = walk.parseCommit(ref.getObjectId());
+ } catch (final IncorrectObjectTypeException notCommit) {
+ continue;
+ }
+ if (walk.isMergedInto(commit, tagCommit)) {
+ tags.add(ref);
+ }
+ }
+ return tags;
+ }
+
+ public static RevCommit getCommit(Repository repo, String name)
+ throws Exception {
+ final RevWalk walk = new RevWalk(repo);
+ final ObjectId id = repo.resolve(name);
+ return walk.parseCommit(id);
+ }
+
+ @Override
+ public void setInitializationData(IConfigurationElement config,
+ String propertyName, Object data) throws CoreException {
+ if ("test".equals(data)) {
+ runTest = true;
+ }
+ }
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/TagAndReleaseHandler.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/TagAndReleaseHandler.java
new file mode 100644
index 0000000..c352954
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/TagAndReleaseHandler.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.egit.internal.relengtools;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.internal.util.Util;
+
+public class TagAndReleaseHandler extends AbstractHandler {
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ Shell shell = HandlerUtil.getActiveShellChecked(event);
+ ReleaseWizard wizard = new ReleaseWizard();
+ ArrayList<IProject> selection = new ArrayList<IProject>();
+ ISelection s = HandlerUtil.getCurrentSelection(event);
+ if (s instanceof IStructuredSelection) {
+ Iterator i = ((IStructuredSelection) s).iterator();
+ while (i.hasNext()) {
+ Object obj = i.next();
+ IProject proj = (IProject) Util.getAdapter(obj, IProject.class);
+ if (proj != null) {
+ selection.add(proj);
+ }
+ }
+ }
+ if (!s.isEmpty()) {
+ wizard.setPreSelection(selection);
+ }
+ wizard.execute(shell);
+ return null;
+ }
+
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/TagPage.java b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/TagPage.java
new file mode 100755
index 0000000..581fcf8
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/TagPage.java
@@ -0,0 +1,398 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 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.egit.internal.relengtools;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * This class extends
+ * <code>WizardPage<code>. It allows user to enter a tag name and make some additional
+ * options.
+ */
+public class TagPage extends WizardPage {
+
+ private String tagString;
+
+ private Combo tagCombo;
+
+ private static final int COMBO_HISTORY_LENGTH = 5;
+
+ private final String DEFAULT_TAG_PREFIX = "v";
+
+ private Button moveButton;
+
+ private Button validateButton;
+
+ private Button compareButton;
+
+ private Button commitButton;
+
+ private boolean moveButtonSelected;
+
+ private boolean compareButtonSelected;
+
+ private boolean commitButtonSelected;
+
+ private boolean validateButtonSelected;
+
+ private boolean hasError;// for tag validation
+
+ private final IDialogSettings settings;
+
+ private final String TAG_KEY = Messages.getString("TagPage.1"); //$NON-NLS-1$
+
+ private final String COMPARE_BUTTON_KEY = Messages.getString("TagPage.2"); //$NON-NLS-1$
+
+ private final String COMMIT_BUTTON_KEY = Messages.getString("TagPage.3"); //$NON-NLS-1$
+
+ private final String MOVE_BUTTON_KEY = Messages.getString("TagPage.4"); //$NON-NLS-1$
+
+ private final String VALIDATE_BUTTON_KEY = Messages.getString("TagPage.5"); //$NON-NLS-1$
+
+ /**
+ * @param pageName
+ * @param title
+ * @param titleImage
+ */
+ public TagPage(String pageName, String title, IDialogSettings settings,
+ ImageDescriptor image) {
+ super(pageName, title, image);
+ this.settings = settings;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets
+ * .Composite)
+ */
+ @Override
+ public void createControl(Composite parent) {
+ final Font font = parent.getFont();
+ final Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout());
+ final GridData data = new GridData(GridData.FILL_BOTH);
+ composite.setLayoutData(data);
+ composite.setFont(font);
+
+ final Label label = new Label(composite, SWT.HORIZONTAL);
+ label.setText(Messages.getString("TagPage.6")); //$NON-NLS-1$
+ label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ label.setFont(font);
+
+ final Listener listener = new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ tagString = null;
+ modifyTag();
+ }
+ };
+
+ tagCombo = new Combo(composite, SWT.NONE);
+ tagCombo.addListener(SWT.Selection, listener);
+ tagCombo.addListener(SWT.Modify, listener);
+ tagCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ tagCombo.setFont(font);
+
+ moveButton = new Button(composite, SWT.CHECK);
+ moveButton.setVisible(true);
+ moveButton.setText(Messages.getString("TagPage.7")); //$NON-NLS-1$
+ moveButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ moveButtonSelected = moveButton.getSelection();
+ }
+ });
+ moveButton.setFont(font);
+
+ validateButton = new Button(composite, SWT.CHECK);
+ validateButton.setText(Messages.getString("TagPage.8")); //$NON-NLS-1$
+ validateButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ validateButtonSelected = validateButton.getSelection();
+ }
+ });
+ validateButton.setFont(font);
+
+ final Group group = new Group(composite, SWT.LEFT);
+ group.setLayout(new GridLayout());
+ final GridData layoutData = new GridData(GridData.FILL,
+ GridData.CENTER, true, false);
+ group.setLayoutData(layoutData);
+ group.setFont(font);
+ group.setText(Messages.getString("TagPage.9")); //$NON-NLS-1$
+
+ compareButton = new Button(group, SWT.RADIO);
+ compareButton.setText(Messages.getString("TagPage.10")); //$NON-NLS-1$
+ compareButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ compareButtonSelected = compareButton.getSelection();
+ updateFinishStatus();
+ }
+ });
+ compareButton.setFont(font);
+
+ commitButton = new Button(group, SWT.RADIO);
+ commitButton.setText(Messages.getString("TagPage.11")); //$NON-NLS-1$
+ commitButton.setSelection(true);
+ commitButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ commitButtonSelected = commitButton.getSelection();
+ }
+ });
+ commitButton.setFont(font);
+
+ initializePage();
+ setControl(composite);
+
+ }
+
+ public String getTagString() {
+ return tagString;
+ }
+
+ /**
+ * Validates tag name
+ */
+ private void validateTag(String tag) {
+ String message = null;
+ hasError = false;
+ if (tag.length() == 0) {
+ hasError = true;
+ } else {
+ final IStatus status = Status.OK_STATUS;
+ if (!status.isOK()) {
+ message = status.getMessage();
+ hasError = true;
+ }
+ }
+ setErrorMessage(message);
+ }
+
+ public boolean isMoveButtonSelected() {
+ return moveButtonSelected;
+ }
+
+ public boolean compareButtonSelected() {
+ return compareButtonSelected;
+ }
+
+ public boolean commitButtonSelected() {
+ return commitButtonSelected;
+ }
+
+ private boolean isPageCompleted() {
+ return (!hasError);
+ }
+
+ public void saveSettings() {
+ String[] tags = settings.getArray(TAG_KEY);
+ if (tags == null)
+ tags = new String[0];
+ tags = addToTagList(tags, tagCombo.getText());
+ settings.put(TAG_KEY, tags);
+ settings.put(COMPARE_BUTTON_KEY, compareButtonSelected);
+ settings.put(COMMIT_BUTTON_KEY, commitButtonSelected);
+ settings.put(MOVE_BUTTON_KEY, moveButtonSelected);
+ settings.put(VALIDATE_BUTTON_KEY, validateButtonSelected);
+ }
+
+ private void readSettings() {
+ if (settings.get(COMPARE_BUTTON_KEY) != null) {
+ compareButton.setSelection(settings.getBoolean(COMPARE_BUTTON_KEY));
+ compareButtonSelected = settings.getBoolean(COMPARE_BUTTON_KEY);
+ } else {
+ compareButton.setSelection(true);
+ compareButtonSelected = true;
+ }
+ if (settings.get(COMMIT_BUTTON_KEY) != null) {
+ commitButton.setSelection(settings.getBoolean(COMMIT_BUTTON_KEY));
+ commitButtonSelected = settings.getBoolean(COMMIT_BUTTON_KEY);
+ } else {
+ commitButton.setSelection(false);
+ commitButtonSelected = false;
+ }
+ if (settings.get(MOVE_BUTTON_KEY) != null) {
+ moveButton.setSelection(settings.getBoolean(MOVE_BUTTON_KEY));
+ moveButtonSelected = settings.getBoolean(MOVE_BUTTON_KEY);
+ } else {
+ moveButton.setSelection(false);
+ moveButtonSelected = false;
+ }
+ if (settings.get(VALIDATE_BUTTON_KEY) != null) {
+ validateButton.setSelection(settings
+ .getBoolean(VALIDATE_BUTTON_KEY));
+ validateButtonSelected = settings.getBoolean(VALIDATE_BUTTON_KEY);
+ } else {
+ validateButton.setSelection(true);
+ validateButtonSelected = true;
+ }
+ // insert the tag template to the head of the list and avoid duplicated
+ // items.
+ if (settings.getArray(TAG_KEY) == null) {
+ tagCombo.add(getTagTemplate());
+ } else {
+ final String[] savedTags = settings.getArray(TAG_KEY);
+ if (savedTags != null && savedTags.length > 0) {
+ final String[] newTags = addToTagList(savedTags,
+ getTagTemplate());
+ for (int i = 0; i < newTags.length; i++) {
+ tagCombo.add(newTags[i]);
+ }
+ } else {
+ tagCombo.add(getTagTemplate());
+ }
+ }
+ }
+
+ private void initializePage() {
+ if (settings != null) {
+ readSettings();
+ } else {
+ commitButton.setSelection(false);
+ compareButton.setSelection(true);
+ validateButton.setSelection(true);
+ moveButton.setSelection(false);
+ commitButtonSelected = false;
+ compareButtonSelected = true;
+ moveButtonSelected = false;
+ validateButtonSelected = true;
+ tagCombo.add(getTagTemplate());
+ }
+ hasError = false;
+ setPageComplete(false);
+ }
+
+ private void modifyTag() {
+ tagString = tagCombo.getText();
+ validateTag(tagString);
+ setPageComplete(isPageCompleted());
+ }
+
+ // The default tag format is "vYYYYMMDD"
+ private String getTagTemplate() {
+ String tag = getTagPrefix();
+ final Calendar today = Calendar.getInstance();
+ tag += today.get(Calendar.YEAR);
+ final int month = today.get(Calendar.MONTH) + 1;
+ if (month < 10) {
+ tag += "0" + month; //$NON-NLS-1$
+ } else {
+ tag += month;
+ }
+ final int day = today.get(Calendar.DAY_OF_MONTH);
+ if (day < 10) {
+ tag += "0" + day;
+ } else {
+ tag += day;
+ }
+ return tag;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
+ */
+ @Override
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ final ReleaseWizard wizard = (ReleaseWizard) getWizard();
+ final boolean b = wizard.getProjectSelectionPage()
+ .isCompareButtonChecked();
+ if (visible && !b) {
+ // In case the wizard switches to this page from Project Selection
+ // Page and there are some projects have outgoing changes
+ wizard.updateSelectedProject();
+ }
+ tagCombo.setFocus();
+ }
+
+ public boolean isValidateButtonSelected() {
+ return validateButtonSelected;
+ }
+
+ private String[] addToTagList(String[] history, String newEntry) {
+ final ArrayList l = new ArrayList(Arrays.asList(history));
+ addToTagList(l, newEntry);
+ final String[] r = new String[l.size()];
+ l.toArray(r);
+ return r;
+ }
+
+ private void addToTagList(List history, String newEntry) {
+ history.remove(newEntry);
+ history.add(0, newEntry);
+ // since only one new item was added, we can be over the limit
+ // by at most one item
+ if (history.size() > COMBO_HISTORY_LENGTH)
+ history.remove(COMBO_HISTORY_LENGTH);
+ }
+
+ private String getTagPrefix() {
+ if (settings != null) {
+ if (settings.getArray(TAG_KEY) != null) {
+ final String[] tags = settings.getArray(TAG_KEY);
+ if (tags != null && tags.length > 0) {
+ final String s = parseFirstTag(tags[0]);
+ if (s != null)
+ return s;
+ }
+ }
+ }
+ return DEFAULT_TAG_PREFIX;
+ }
+
+ private String parseFirstTag(String s) {
+ if (s == null)
+ return null;
+ final int length = s.length();
+ if (length == 0 || !Character.isLetter(s.charAt(0)))
+ return null;
+ int i = 0;
+ for (i = 0; i < length; i++) {
+ if (Character.isDigit(s.charAt(i))) {
+ break;
+ }
+ }
+ return s.substring(0, i);
+ }
+
+ private void updateFinishStatus() {
+ ((ReleaseWizard) getWizard()).getContainer().updateButtons();
+ }
+}
diff --git a/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/messages.properties b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/messages.properties
new file mode 100755
index 0000000..6f4a040
--- /dev/null
+++ b/org.eclipse.egit.relengtools/src/org/eclipse/egit/internal/relengtools/messages.properties
@@ -0,0 +1,100 @@
+###############################################################################
+# Copyright (c) 2003, 2010 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
+###############################################################################
+ReleaseWizard.6=Project Selection
+ReleaseWizard.7=Select the projects to be considered for release.
+ReleaseWizard.9=Release Tag
+ReleaseWizard.4=Map Project Selection
+ReleaseWizard.3=Specify a map project to release projects
+ReleaseWizard.0=List of changes for this build.
+ReleaseWizard.10=Enter the tag to be used for this release.
+ReleaseWizard.12=Changed Projects
+ReleaseWizard.13=Review the changes that will be released.
+ReleaseWizard.15=Map File Changes
+ReleaseWizard.16=Review changes applied to map files.
+ReleaseWizard.18=Commit Comment
+ReleaseWizard.19=Enter the commit comment for changed map files.
+ReleaseWizard.1=Notes for Build Changes
+ReleaseWizard.20=Releasing build notes file...
+ReleaseWizard.21=Releasing
+ReleaseWizard.22=Map file was not committed
+ReleaseWizard.23=Errors occurred during release
+ReleaseWizard.24=Release Failed
+ReleaseWizard.25=There were errors reported during the release. The map files have not been updated
+ReleaseWizard.26=Releng Release
+ReleaseWizard.validatePageTitle=Release Validation
+MapProjectSelectionWizard.1=Map Project Selection
+MapProjectSelectionWizard.2=Specify a map project to perform action with local file
+MapProjectSelectionPage.0=&Always use this map project
+MapProjectSelectionPage.1=Invalid map project selected
+MapProjectSelectionPage.2=Project
+MapProjectSelectionPage.3=\ is not shared
+ProjectSelectionPage.0=ProjectSelectionPage.selected
+ProjectSelectionPage.1=ProjectSelectionPage.compareButton
+ProjectSelectionPage.2=&Select the projects to be released:
+ProjectSelectionPage.3=&Release only projects that have changed since the last release
+TagPage.1=TagPage.Tag
+TagPage.2=TagPage.Compare
+TagPage.3=TagPage.Commmit
+TagPage.4=TagPage.move
+TagPage.5=TagePage.validate
+TagPage.6=&Tag name:
+TagPage.7=&Move tag if it already exists
+TagPage.8=&Validate the release once completed
+TagPage.9=Action for changed map files
+TagPage.10=&Show the file change before committing
+TagPage.11=&Commit the files without showing changes
+RepositorySelectionDialog.0=Select Repository Location
+RepositorySelectionDialog.1=Select the repository location to be used for tagging
+ProjectComparePage.1=There were no changes in the selected projects.
+ProjectComparePage.2=&Generate Build Notes
+ProjectComparePage.3=RelEng Release
+RelEngPlugin.1=org.eclipse.releng
+RelEngPlugin.2=maps
+RelEngPlugin.3=RelEngPluginResources
+ProjectValidationDialog.2=Project Validation
+RelEngPreferenceInitializer.0=Copyright (c) ${date} IBM Corporation and others.\nAll rights reserved. This program and the accompanying materials\nare made available under the terms of the Eclipse Public License v1.0\nwhich accompanies this distribution, and is available at\nhttp://www.eclipse.org/legal/epl-v10.html\n\nContributors:\n IBM Corporation - initial API and implementation
+CopyrightPreferencePage.0=Use "${date}" to substitute in "creation_year, revision_year"
+CopyrightPreferencePage.1=Default creation year:
+CopyrightPreferencePage.2=Replace all existing copyright comments with this copyright template
+CopyrightPreferencePage.4=Skip over properties files
+CopyrightPreferencePage.5=Copyright template
+CopyrightPreferencePage.6=Default year must be a positive number
+CopyrightPreferencePage.7=Default revision year:
+CopyrightPreferencePage.8=Always use default revision year instead of repository lookup
+CopyrightPreferencePage.9=Skip over XML files
+BuildNotesPage.2=&Update Build Notes file
+BuildNotesPage.3=Build Notes &file:
+BuildNotesPage.5=Invalid file extension.
+BuildNotesPage.6=Invalid path.
+BuildNotesPage.7=Input a file path.
+BuildNotesPage.8=&Browse...
+BuildNotesPage.11=Creating file...
+BuildNotesPage.38=Updating File...
+BuildNotesPage.42=Select Build Notes File
+BuildNotesPage.43=&Select the file to update with the new build notes:
+GetBugsOperation.0=Beginning Bug Operation
+GetBugsOperation.1=Fetching Bugzilla Summaries.
+GetBugsOperation.Error=Problem while fetching Bugzilla summaries
+CopyrightDialog.1=Fix Copyrights
+CopyrightDialog.2=&Enter a search string:
+CopyrightDialog.3=Any file whose last CVS commit comment contained the above as a substring will be excluded from this copyright update.\nThis is to prevent these files from being updated multiple times if the copyright update needs to be run again in the near future.\nLeave the field empty to include all files in this update.
+MapProjectPreferencePage.1=Choose the name of the project which contains your map files.
+MapProjectPreferencePage.2=&Select one of the following to be used as your default map project:
+MapProjectPreferencePage.0=&Always prompt
+MapProjectPreferencePage.3=No project from the selected map file in the workspace.
+CompareLocalToMap.1=Map file entry was not found for the following project(s), comparison will be done from HEAD
+CompareLocalToMap.0=Compare With
+CVSTagHelper.1=Would you like to continue anyways?
+CVSTagHelper.2=Map file entry not found
+ReplaceLocalFromMap.1=Map file entry was not found for the following project(s), replacement will be done from HEAD
+ReplaceLocalFromMap.0=Replace With
+SourceFile.0=The file buffer could not be acquired for: {0}
+ValidatePage.description=Projects tagged and map files released. Validating the release...