From b2d6176ab678441fcc129445dab739bf7f441979 Mon Sep 17 00:00:00 2001
From: Andre Weinand
Date: Tue, 12 Feb 2002 15:52:48 +0000
Subject: NLS work, patch: #6346
---
.../compare/internal/CompareMessages.properties | 3 +
.../compare/internal/ComparePreferencePage.java | 12 +-
.../eclipse/compare/internal/CompareUIPlugin.java | 77 +-
.../eclipse/compare/internal/ExceptionHandler.java | 127 +++
.../compare/internal/ListContentProvider.java | 41 +
.../org/eclipse/compare/internal/ListDialog.java | 83 ++
.../org/eclipse/compare/internal/Utilities.java | 2 +-
.../internal/patch/CompareWithPatchAction.java | 166 ++++
.../org/eclipse/compare/internal/patch/Diff.java | 87 ++
.../org/eclipse/compare/internal/patch/Hunk.java | 120 +++
.../compare/internal/patch/InputPatchPage.java | 609 +++++++++++++
.../eclipse/compare/internal/patch/LineReader.java | 115 +++
.../compare/internal/patch/PatchCompareInput.java | 180 ++++
.../compare/internal/patch/PatchErrorDialog.java | 17 +
.../compare/internal/patch/PatchMessages.java | 26 +
.../internal/patch/PatchMessages.properties | 73 ++
.../compare/internal/patch/PatchWizard.java | 148 ++++
.../compare/internal/patch/PatchedResource.java | 69 ++
.../eclipse/compare/internal/patch/Patcher.java | 948 +++++++++++++++++++++
.../compare/internal/patch/PreviewPatchPage.java | 497 +++++++++++
.../compare/patch/CompareWithPatchAction.java | 44 -
.../compare/org/eclipse/compare/patch/Diff.java | 87 --
.../compare/org/eclipse/compare/patch/Hunk.java | 106 ---
.../org/eclipse/compare/patch/InputPatchPage.java | 604 -------------
.../org/eclipse/compare/patch/LineReader.java | 115 ---
.../eclipse/compare/patch/PatchCompareInput.java | 179 ----
.../org/eclipse/compare/patch/PatchWizard.java | 131 ---
.../org/eclipse/compare/patch/PatchedResource.java | 69 --
.../compare/org/eclipse/compare/patch/Patcher.java | 906 --------------------
.../eclipse/compare/patch/PreviewPatchPage.java | 510 -----------
bundles/org.eclipse.compare/plugin.xml | 2 +-
.../compare/internal/CompareMessages.properties | 3 +
.../compare/internal/ComparePreferencePage.java | 12 +-
.../eclipse/compare/internal/CompareUIPlugin.java | 77 +-
.../eclipse/compare/internal/ExceptionHandler.java | 127 +++
.../compare/internal/ListContentProvider.java | 41 +
.../org/eclipse/compare/internal/ListDialog.java | 83 ++
.../org/eclipse/compare/internal/Utilities.java | 2 +-
.../compare/internal/patch/Attic/LineReader.java | 115 +++
.../internal/patch/CompareWithPatchAction.java | 166 ++++
.../org/eclipse/compare/internal/patch/Diff.java | 87 ++
.../org/eclipse/compare/internal/patch/Hunk.java | 120 +++
.../compare/internal/patch/InputPatchPage.java | 609 +++++++++++++
.../eclipse/compare/internal/patch/LineReader.java | 115 +++
.../compare/internal/patch/PatchCompareInput.java | 180 ++++
.../compare/internal/patch/PatchErrorDialog.java | 17 +
.../compare/internal/patch/PatchMessages.java | 26 +
.../internal/patch/PatchMessages.properties | 73 ++
.../compare/internal/patch/PatchWizard.java | 148 ++++
.../compare/internal/patch/PatchedResource.java | 69 ++
.../eclipse/compare/internal/patch/Patcher.java | 948 +++++++++++++++++++++
.../compare/internal/patch/PreviewPatchPage.java | 497 +++++++++++
.../compare/patch/CompareWithPatchAction.java | 44 -
.../compare/org/eclipse/compare/patch/Diff.java | 87 --
.../compare/org/eclipse/compare/patch/Hunk.java | 106 ---
.../org/eclipse/compare/patch/InputPatchPage.java | 604 -------------
.../org/eclipse/compare/patch/LineReader.java | 115 ---
.../eclipse/compare/patch/PatchCompareInput.java | 179 ----
.../org/eclipse/compare/patch/PatchWizard.java | 131 ---
.../org/eclipse/compare/patch/PatchedResource.java | 69 --
.../compare/org/eclipse/compare/patch/Patcher.java | 906 --------------------
.../eclipse/compare/patch/PreviewPatchPage.java | 510 -----------
.../plugins/org.eclipse.compare/plugin.xml | 2 +-
63 files changed, 6881 insertions(+), 5540 deletions(-)
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ExceptionHandler.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ListContentProvider.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ListDialog.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CompareWithPatchAction.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Diff.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Hunk.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/InputPatchPage.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/LineReader.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchCompareInput.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchErrorDialog.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchedResource.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Patcher.java
create mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage.java
delete mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/CompareWithPatchAction.java
delete mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/Diff.java
delete mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/Hunk.java
delete mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/InputPatchPage.java
delete mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/LineReader.java
delete mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchCompareInput.java
delete mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchWizard.java
delete mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchedResource.java
delete mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/Patcher.java
delete mode 100644 bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PreviewPatchPage.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ExceptionHandler.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ListContentProvider.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ListDialog.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Attic/LineReader.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CompareWithPatchAction.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Diff.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Hunk.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/InputPatchPage.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/LineReader.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchCompareInput.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchErrorDialog.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchedResource.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Patcher.java
create mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage.java
delete mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/CompareWithPatchAction.java
delete mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/Diff.java
delete mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/Hunk.java
delete mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/InputPatchPage.java
delete mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/LineReader.java
delete mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchCompareInput.java
delete mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchWizard.java
delete mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchedResource.java
delete mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/Patcher.java
delete mode 100644 bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PreviewPatchPage.java
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareMessages.properties b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareMessages.properties
index cf31617aa..44538cec9 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareMessages.properties
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareMessages.properties
@@ -3,6 +3,9 @@
# All Rights Reserved.
# =====================================
+ComparePlugin.internal_error= Internal Error
+ExceptionDialog.seeErrorLogMessage= See error log for more details.
+
#
# Title format for CompareViewerSwitchingPane
#
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePreferencePage.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePreferencePage.java
index c9ac102fd..f8a64840f 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePreferencePage.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePreferencePage.java
@@ -19,9 +19,9 @@ public class ComparePreferencePage extends FieldEditorPreferencePage implements
public static final String SYNCHRONIZE_SCROLLING= PREFIX + "SynchronizeScrolling"; //$NON-NLS-1$
public static final String SHOW_PSEUDO_CONFLICTS= PREFIX + "ShowPseudoConflicts"; //$NON-NLS-1$
public static final String INITIALLY_SHOW_ANCESTOR_PANE= PREFIX + "InitiallyShowAncestorPane"; //$NON-NLS-1$
+ public static final String PREF_SAVE_ALL_EDITORS= PREFIX + "SaveAllEditors"; //$NON-NLS-1$
public static final String TEXT_FONT= PREFIX + "TextFont"; //$NON-NLS-1$
-
public ComparePreferencePage() {
super(GRID);
}
@@ -34,6 +34,16 @@ public class ComparePreferencePage extends FieldEditorPreferencePage implements
WorkbenchChainedTextFontFieldEditor.startPropagate(store, TEXT_FONT);
}
+ static public boolean getSaveAllEditors() {
+ IPreferenceStore store= CompareUIPlugin.getDefault().getPreferenceStore();
+ return store.getBoolean(PREF_SAVE_ALL_EDITORS);
+ }
+
+ static public void setSaveAllEditors(boolean value) {
+ IPreferenceStore store= CompareUIPlugin.getDefault().getPreferenceStore();
+ store.setValue(PREF_SAVE_ALL_EDITORS, value);
+ }
+
public void init(IWorkbench workbench) {
}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
index 4c56ee5e5..1ed9d6397 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
@@ -57,6 +57,9 @@ public final class CompareUIPlugin extends AbstractUIPlugin {
public static final String CTOOL_PREV= "clcl16/prev_nav.gif"; //$NON-NLS-1$
public static final String ETOOL_PREV= "elcl16/prev_nav.gif"; //$NON-NLS-1$
+ /** Status code describing an internal error */
+ public static final int INTERNAL_ERROR= 1;
+
private static boolean NORMALIZE_CASE= true;
private final static String CLASS_ATTRIBUTE= "class"; //$NON-NLS-1$
@@ -195,6 +198,20 @@ public final class CompareUIPlugin extends AbstractUIPlugin {
return fgResourceBundle;
}
+ public static IWorkbench getActiveWorkbench() {
+ CompareUIPlugin plugin= getDefault();
+ if (plugin == null)
+ return null;
+ return plugin.getWorkbench();
+ }
+
+ public static IWorkbenchWindow getActiveWorkbenchWindow() {
+ IWorkbench workbench= getActiveWorkbench();
+ if (workbench == null)
+ return null;
+ return workbench.getActiveWorkbenchWindow();
+ }
+
/**
* Returns the active workkbench page or null
if
* no active workkbench page can be determined.
@@ -203,13 +220,7 @@ public final class CompareUIPlugin extends AbstractUIPlugin {
* no active workkbench page can be determined
*/
private static IWorkbenchPage getActivePage() {
- CompareUIPlugin plugin= getDefault();
- if (plugin == null)
- return null;
- IWorkbench workbench= plugin.getWorkbench();
- if (workbench == null)
- return null;
- IWorkbenchWindow window= workbench.getActiveWorkbenchWindow();
+ IWorkbenchWindow window= getActiveWorkbenchWindow();
if (window == null)
return null;
return window.getActivePage();
@@ -223,16 +234,10 @@ public final class CompareUIPlugin extends AbstractUIPlugin {
* no workbench window is active
*/
public static Shell getShell() {
- CompareUIPlugin p= getDefault();
- if (p == null)
- return null;
- IWorkbench wb= p.getWorkbench();
- if (wb == null)
- return null;
- IWorkbenchWindow ww= wb.getActiveWorkbenchWindow();
- if (ww == null)
+ IWorkbenchWindow window= getActiveWorkbenchWindow();
+ if (window == null)
return null;
- return ww.getShell();
+ return window.getShell();
}
/**
@@ -810,4 +815,44 @@ public final class CompareUIPlugin extends AbstractUIPlugin {
iter.remove();
}
}
+
+ /**
+ * Returns an array of all editors that have an unsaved content. If the identical content is
+ * presented in more than one editor, only one of those editor parts is part of the result.
+ *
+ * @return an array of all dirty editor parts.
+ */
+ public static IEditorPart[] getDirtyEditors() {
+ Set inputs= new HashSet(7);
+ ArrayList result= new ArrayList(0);
+ IWorkbench workbench= CompareUIPlugin.getDefault().getWorkbench();
+ IWorkbenchWindow[] windows= workbench.getWorkbenchWindows();
+ for (int i= 0; i < windows.length; i++) {
+ IWorkbenchPage[] pages= windows[i].getPages();
+ for (int x= 0; x < pages.length; x++) {
+ IEditorPart[] editors= pages[x].getEditors();
+ for (int z= 0; z < editors.length; z++) {
+ IEditorPart editor= editors[z];
+ IEditorInput input= editor.getEditorInput();
+ if (editor.isDirty() && !inputs.contains(input)) {
+ inputs.add(input);
+ result.add(editor);
+ }
+ }
+ }
+ }
+ return (IEditorPart[])result.toArray(new IEditorPart[result.size()]);
+ }
+
+ public static void log(Throwable e) {
+ log(new Status(IStatus.ERROR, getPluginId(), INTERNAL_ERROR, CompareMessages.getString("JavaPlugin.internal_error"), e)); //$NON-NLS-1$
+ }
+
+ public static void log(IStatus status) {
+ getDefault().getLog().log(status);
+ }
+
+ public static String getPluginId() {
+ return getDefault().getDescriptor().getUniqueIdentifier();
+ }
}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ExceptionHandler.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ExceptionHandler.java
new file mode 100644
index 000000000..773b0499c
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ExceptionHandler.java
@@ -0,0 +1,127 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal;
+
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+
+/**
+ * The default exception handler shows an error dialog when one of its handle methods
+ * is called. If the passed exception is a CoreException
an error dialog
+ * pops up showing the exception's status information. For a InvocationTargetException
+ * a normal message dialog pops up showing the exception's message. Additionally the exception
+ * is written to the platform log.
+ */
+public class ExceptionHandler {
+
+ private static ExceptionHandler fgInstance= new ExceptionHandler();
+
+ /**
+ * Logs the given exception using the platform's logging mechanism. The exception is
+ * logged as an error with the error code JavaStatusConstants.INTERNAL_ERROR
.
+ */
+ public static void log(Throwable t, String message) {
+ CompareUIPlugin.log(new Status(IStatus.ERROR, CompareUIPlugin.getPluginId(),
+ CompareUIPlugin.INTERNAL_ERROR, message, t));
+ }
+
+ /**
+ * Handles the given CoreException
. The workbench shell is used as a parent
+ * for the dialog window.
+ *
+ * @param e the CoreException
to be handled
+ * @param title the dialog window's window title
+ * @param message message to be displayed by the dialog window
+ */
+ public static void handle(CoreException e, String title, String message) {
+ handle(e, CompareUIPlugin.getShell(), title, message);
+ }
+
+ /**
+ * Handles the given CoreException
.
+ *
+ * @param e the CoreException
to be handled
+ * @param parent the dialog window's parent shell
+ * @param title the dialog window's window title
+ * @param message message to be displayed by the dialog window
+ */
+ public static void handle(CoreException e, Shell parent, String title, String message) {
+ fgInstance.perform(e, parent, title, message);
+ }
+
+ /**
+ * Handles the given InvocationTargetException
. The workbench shell is used
+ * as a parent for the dialog window.
+ *
+ * @param e the InvocationTargetException
to be handled
+ * @param title the dialog window's window title
+ * @param message message to be displayed by the dialog window
+ */
+ public static void handle(InvocationTargetException e, String title, String message) {
+ handle(e, CompareUIPlugin.getShell(), title, message);
+ }
+
+ /**
+ * Handles the given InvocationTargetException
.
+ *
+ * @param e the InvocationTargetException
to be handled
+ * @param parent the dialog window's parent shell
+ * @param title the dialog window's window title
+ * @param message message to be displayed by the dialog window
+ */
+ public static void handle(InvocationTargetException e, Shell parent, String title, String message) {
+ fgInstance.perform(e, parent, title, message);
+ }
+
+ //---- Hooks for subclasses to control exception handling ------------------------------------
+
+ protected void perform(CoreException e, Shell shell, String title, String message) {
+ CompareUIPlugin.log(e);
+ IStatus status= e.getStatus();
+ if (status != null) {
+ ErrorDialog.openError(shell, title, message, status);
+ } else {
+ displayMessageDialog(e, e.getMessage(), shell, title, message);
+ }
+ }
+
+ protected void perform(InvocationTargetException e, Shell shell, String title, String message) {
+ Throwable target= e.getTargetException();
+ if (target instanceof CoreException) {
+ perform((CoreException)target, shell, title, message);
+ } else {
+ CompareUIPlugin.log(e);
+ if (e.getMessage() != null && e.getMessage().length() > 0) {
+ displayMessageDialog(e, e.getMessage(), shell, title, message);
+ } else {
+ displayMessageDialog(e, target.getMessage(), shell, title, message);
+ }
+ }
+ }
+
+ //---- Helper methods -----------------------------------------------------------------------
+
+ private void displayMessageDialog(Throwable t, String exceptionMessage, Shell shell, String title, String message) {
+ StringWriter msg= new StringWriter();
+ if (message != null) {
+ msg.write(message);
+ msg.write("\n\n"); //$NON-NLS-1$
+ }
+ if (exceptionMessage == null || exceptionMessage.length() == 0)
+ msg.write(CompareMessages.getString("ExceptionDialog.seeErrorLogMessage")); //$NON-NLS-1$
+ else
+ msg.write(exceptionMessage);
+ MessageDialog.openError(shell, title, msg.toString());
+ }
+}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ListContentProvider.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ListContentProvider.java
new file mode 100644
index 000000000..9170edeca
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ListContentProvider.java
@@ -0,0 +1,41 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal;
+
+import java.util.List;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * A specialized content provider to show a list of editor parts.
+ */
+public class ListContentProvider implements IStructuredContentProvider {
+ List fContents;
+
+ public ListContentProvider() {
+ }
+
+ public Object[] getElements(Object input) {
+ if (fContents != null && fContents == input)
+ return fContents.toArray();
+ return new Object[0];
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ if (newInput instanceof List)
+ fContents= (List)newInput;
+ else
+ fContents= null;
+ // we use a fixed set.
+ }
+
+ public void dispose() {
+ }
+
+ public boolean isDeleted(Object o) {
+ return fContents != null && !fContents.contains(o);
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ListDialog.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ListDialog.java
new file mode 100644
index 000000000..7cd262479
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ListDialog.java
@@ -0,0 +1,83 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.*;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.*;
+
+import org.eclipse.ui.dialogs.SelectionDialog;
+
+public class ListDialog extends SelectionDialog {
+
+ private IStructuredContentProvider fContentProvider;
+ private ILabelProvider fLabelProvider;
+ private Object fInput;
+ private TableViewer fTableViewer;
+ private boolean fAddCancelButton;
+
+ public ListDialog(Shell parent) {
+ super(parent);
+ fAddCancelButton= false;
+ }
+
+ public void setInput(Object input) {
+ fInput= input;
+ }
+
+ public void setContentProvider(IStructuredContentProvider sp){
+ fContentProvider= sp;
+ }
+
+ public void setLabelProvider(ILabelProvider lp){
+ fLabelProvider= lp;
+ }
+
+ public void setAddCancelButton(boolean addCancelButton) {
+ fAddCancelButton= addCancelButton;
+ }
+
+ public TableViewer getTableViewer(){
+ return fTableViewer;
+ }
+
+ public boolean hasFilters(){
+ return fTableViewer.getFilters() != null && fTableViewer.getFilters().length != 0;
+ }
+
+ public void create() {
+ setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE);
+ super.create();
+ }
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ if (! fAddCancelButton)
+ createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ else
+ super.createButtonsForButtonBar(parent);
+ }
+
+ protected Control createDialogArea(Composite container) {
+ Composite parent= (Composite) super.createDialogArea(container);
+ createMessageArea(parent);
+ fTableViewer= new TableViewer(parent, getTableStyle());
+ fTableViewer.setContentProvider(fContentProvider);
+ Table table= fTableViewer.getTable();
+ fTableViewer.setLabelProvider(fLabelProvider);
+ fTableViewer.setInput(fInput);
+ GridData gd= new GridData(GridData.FILL_BOTH);
+ gd.heightHint= convertHeightInCharsToPixels(15);
+ gd.widthHint= convertWidthInCharsToPixels(55);
+ table.setLayoutData(gd);
+ return parent;
+ }
+
+ protected int getTableStyle() {
+ return SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER;
+ }
+}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/Utilities.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/Utilities.java
index 01f63aab0..0a81cc115 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/Utilities.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/Utilities.java
@@ -204,7 +204,7 @@ public class Utilities {
}
public static String getIconPath(Display display) {
- return "icons/full/";
+ return "icons/full/"; //$NON-NLS-1$
}
/**
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CompareWithPatchAction.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CompareWithPatchAction.java
new file mode 100644
index 000000000..28dff2473
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CompareWithPatchAction.java
@@ -0,0 +1,166 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.lang.reflect.InvocationTargetException;
+import java.text.MessageFormat;
+import java.util.Arrays;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Button;
+
+import org.eclipse.jface.dialogs.*;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.*;
+import org.eclipse.jface.action.IAction;
+
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.internal.*;
+import org.eclipse.ui.IActionDelegate;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+
+import org.eclipse.compare.internal.*;
+
+public class CompareWithPatchAction implements IActionDelegate {
+
+ static class PatchWizardDialog extends WizardDialog {
+
+ PatchWizardDialog(Shell parent, IWizard wizard) {
+ super(parent, wizard);
+
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ setMinimumPageSize(700, 500);
+ }
+ }
+
+ private ISelection fSelection;
+ private boolean fSavedFiles;
+ private boolean fAutobuildState;
+
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ fSelection= selection;
+ action.setEnabled(fSelection != null && !fSelection.isEmpty());
+ }
+
+ public void run(IAction action) {
+ PatchWizard wizard= new PatchWizard(fSelection);
+
+ if (areAllEditorsSaved()) {
+ //RefactoringStatus activationStatus= refactoring.checkActivation(new NullProgressMonitor());
+ //if (! activationStatus.hasFatalError()){
+ // wizard.setActivationStatus(activationStatus);
+ PatchWizardDialog dialog= new PatchWizardDialog(CompareUIPlugin.getShell(), wizard);
+ if (dialog.open() == Dialog.CANCEL)
+ triggerBuild();
+
+ //} else{
+ //RefactoringErrorDialog.open(dialogTitle, activationStatus);
+ //}
+ }
+ }
+
+ private boolean areAllEditorsSaved(){
+ if (CompareUIPlugin.getDirtyEditors().length == 0)
+ return true;
+ if (! saveAllDirtyEditors())
+ return false;
+ Shell shell= CompareUIPlugin.getShell();
+ try {
+ // Save isn't cancelable.
+ IWorkspace workspace= ResourcesPlugin.getWorkspace();
+ IWorkspaceDescription description= workspace.getDescription();
+ boolean autoBuild= description.isAutoBuilding();
+ description.setAutoBuilding(false);
+ workspace.setDescription(description);
+ try {
+ new ProgressMonitorDialog(shell).run(false, false, createRunnable());
+ fSavedFiles= true;
+ } finally {
+ description.setAutoBuilding(autoBuild);
+ workspace.setDescription(description);
+ }
+ return true;
+ } catch (InvocationTargetException e) {
+ ExceptionHandler.handle(e, shell, PatchMessages.getString("PatchAction.ExceptionTitle"), PatchMessages.getString("Exception")); //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ } catch (CoreException e) {
+ ExceptionHandler.handle(e, shell, PatchMessages.getString("PatchAction.ExceptionTitle"), PatchMessages.getString("Exception")); //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ } catch (InterruptedException e) {
+ Assert.isTrue(false); // Can't happen. Operation isn't cancelable.
+ return false;
+ }
+ }
+
+ private IRunnableWithProgress createRunnable() {
+ return new IRunnableWithProgress() {
+ public void run(IProgressMonitor pm) {
+ IEditorPart[] editorsToSave= CompareUIPlugin.getDirtyEditors();
+ pm.beginTask(PatchMessages.getString("PatchAction.SavingDirtyEditorsTask"), editorsToSave.length); //$NON-NLS-1$
+ for (int i= 0; i < editorsToSave.length; i++) {
+ editorsToSave[i].doSave(new SubProgressMonitor(pm, 1));
+ pm.worked(1);
+ }
+ pm.done();
+ }
+ };
+ }
+
+ private boolean saveAllDirtyEditors() {
+ if (ComparePreferencePage.getSaveAllEditors()) //must save everything
+ return true;
+ ListDialog dialog= new ListDialog(CompareUIPlugin.getShell()) {
+ protected Control createDialogArea(Composite parent) {
+ Composite result= (Composite) super.createDialogArea(parent);
+ final Button check= new Button(result, SWT.CHECK);
+ check.setText(PatchMessages.getString("PatchAction.AlwaysSaveQuestion")); //$NON-NLS-1$
+ check.setSelection(ComparePreferencePage.getSaveAllEditors());
+ check.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ ComparePreferencePage.setSaveAllEditors(check.getSelection());
+ }
+ }
+ );
+ return result;
+ }
+ };
+ dialog.setTitle(PatchMessages.getString("PatchAction.SaveAllQuestion")); //$NON-NLS-1$
+ dialog.setAddCancelButton(true);
+ dialog.setLabelProvider(createDialogLabelProvider());
+ dialog.setMessage(PatchMessages.getString("PatchAction.SaveAllDescription")); //$NON-NLS-1$
+ dialog.setContentProvider(new ListContentProvider());
+ dialog.setInput(Arrays.asList(CompareUIPlugin.getDirtyEditors()));
+ return dialog.open() == Dialog.OK;
+ }
+
+ private ILabelProvider createDialogLabelProvider() {
+ return new LabelProvider() {
+ public Image getImage(Object element) {
+ return ((IEditorPart) element).getTitleImage();
+ }
+ public String getText(Object element) {
+ return ((IEditorPart) element).getTitle();
+ }
+ };
+ }
+
+ private void triggerBuild() {
+ if (fSavedFiles && ResourcesPlugin.getWorkspace().getDescription().isAutoBuilding()) {
+ new GlobalBuildAction(CompareUIPlugin.getActiveWorkbench(), IncrementalProjectBuilder.INCREMENTAL_BUILD).run();
+ }
+ }
+}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Diff.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Diff.java
new file mode 100644
index 000000000..9682d5cfe
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Diff.java
@@ -0,0 +1,87 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.util.*;
+
+import org.eclipse.core.runtime.IPath;
+
+import org.eclipse.compare.structuremergeviewer.Differencer;
+
+
+/* package */ class Diff {
+
+ IPath fOldPath, fNewPath;
+ long fOldDate, fNewDate; // if 0: no file
+ List fHunks= new ArrayList();
+ boolean fIsEnabled= true;
+ String fRejected;
+
+
+ /* package */ Diff(IPath oldPath, long oldDate, IPath newPath, long newDate) {
+ fOldPath= oldPath;
+ fOldDate= oldPath == null ? 0 : oldDate;
+ fNewPath= newPath;
+ fNewDate= newPath == null ? 0 : newDate;
+ }
+
+ void reverse() {
+ IPath tp= fOldPath;
+ fOldPath= fNewPath;
+ fNewPath= tp;
+
+ long t= fOldDate;
+ fOldDate= fNewDate;
+ fNewDate= t;
+
+ Iterator iter= fHunks.iterator();
+ while (iter.hasNext()) {
+ Hunk hunk= (Hunk) iter.next();
+ hunk.reverse();
+ }
+ }
+
+ Hunk[] getHunks() {
+ return (Hunk[]) fHunks.toArray((Hunk[]) new Hunk[fHunks.size()]);
+ }
+
+ IPath getPath() {
+ if (fOldPath != null)
+ return fOldPath;
+ return fNewPath;
+ }
+
+ void finish() {
+ if (fHunks.size() == 1) {
+ Hunk h= (Hunk) fHunks.get(0);
+ if (h.fNewLength == 0) {
+ fNewDate= 0;
+ fNewPath= fOldPath;
+ }
+ }
+ }
+
+ /* package */ void add(Hunk hunk) {
+ fHunks.add(hunk);
+ }
+
+ /* package */ int getType() {
+ if (fOldDate == 0)
+ return Differencer.ADDITION;
+ if (fNewDate == 0)
+ return Differencer.DELETION;
+ return Differencer.CHANGE;
+ }
+
+ /* package */ String getDescription(int strip) {
+ IPath path= fOldPath;
+ if (fOldDate == 0)
+ path= fNewPath;
+ if (strip > 0 && strip < path.segmentCount())
+ path= path.removeFirstSegments(strip);
+ return path.toOSString();
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Hunk.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Hunk.java
new file mode 100644
index 000000000..28dc90b55
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Hunk.java
@@ -0,0 +1,120 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.util.List;
+
+import org.eclipse.jface.util.Assert;
+
+
+/**
+ * A Hunk describes a range of changed lines and some context lines.
+ */
+/* package */ class Hunk {
+
+ Diff fParent;
+ int fOldStart, fOldLength;
+ int fNewStart, fNewLength;
+ String[] fLines;
+ boolean fIsEnabled= true;
+
+
+ /* package */ Hunk(Diff parent, int[] oldRange, int[] newRange, List lines) {
+
+ fParent= parent;
+ if (fParent != null)
+ fParent.add(this);
+
+ if (oldRange[0] > 0)
+ fOldStart= oldRange[0]-1; // line number start at 0!
+ else
+ fOldStart= 0;
+ fOldLength= oldRange[1];
+ if (newRange[0] > 0)
+ fNewStart= newRange[0]-1; // line number start at 0!
+ else
+ fNewStart= 0;
+ fNewLength= newRange[1];
+
+ fLines= (String[]) lines.toArray(new String[lines.size()]);
+ }
+
+ void reverse() {
+ int t= fOldStart;
+ fOldStart= fNewStart;
+ fNewStart= t;
+
+ t= fOldLength;
+ fOldLength= fNewLength;
+ fNewLength= t;
+
+ for (int i= 0; i < fLines.length; i++) {
+ String line= fLines[i];
+ char c= line.charAt(0);
+ switch (c) {
+ case '+':
+ fLines[i]= '-' + line.substring(1);
+ break;
+ case '-':
+ fLines[i]= '+' + line.substring(1);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ /**
+ * Returns the contents of this hunk.
+ * Each line starts with a control character. Their meaning is as follows:
+ *
IResource
s that returns
+ * only children of the given resource type.
+ */
+ private ITreeContentProvider getResourceProvider(final int resourceType) {
+ return new WorkbenchContentProvider() {
+ public Object[] getChildren(Object o) {
+ if (o instanceof IContainer) {
+ try {
+ ArrayList results= new ArrayList();
+ IResource[] members= ((IContainer)o).members();
+ for (int i= 0; i < members.length; i++)
+ // filter out the desired resource types
+ if ((members[i].getType() & resourceType) != 0)
+ results.add(members[i]);
+ return results.toArray();
+ } catch (CoreException e) {
+ }
+ }
+ // just return an empty set of children
+ return new Object[0];
+ }
+ };
+ }
+
+ /**
+ * Updates the enable state of this page's controls.
+ */
+ private void updateWidgetEnablements() {
+
+ String error= null;
+
+ ISelection selection= fPatchTargets.getSelection();
+ boolean anySelected= selection != null && !selection.isEmpty();
+ if (!anySelected)
+ error= PatchMessages.getString("InputPatchPage.NothingSelected.message"); //$NON-NLS-1$
+
+ boolean gotPatch= false;
+ if (getUseClipboard()) {
+ Control c= getControl();
+ if (c != null) {
+ Clipboard clipboard= new Clipboard(c.getDisplay());
+ Object o= clipboard.getContents(TextTransfer.getInstance());
+ if (o instanceof String) {
+ String s= ((String) o).trim();
+ if (s.length() > 0)
+ gotPatch= true;
+ else
+ error= PatchMessages.getString("InputPatchPage.ClipboardIsEmpty.message"); //$NON-NLS-1$
+ } else
+ error= PatchMessages.getString("InputPatchPage.NoTextInClipboard.message"); //$NON-NLS-1$
+ } else
+ error= PatchMessages.getString("InputPatchPage.CouldNotReadClipboard.message"); //$NON-NLS-1$
+ } else {
+ String path= fPatchFileNameField.getText();
+ if (path != null && path.length() > 0) {
+ File file= new File(path);
+ gotPatch= file.exists() && file.isFile() && file.length() > 0;
+ if (!gotPatch)
+ error= PatchMessages.getString("InputPatchPage.CannotLocatePatch.message") + path; //$NON-NLS-1$
+ } else {
+ error= PatchMessages.getString("InputPatchPage.NoFileName.message"); //$NON-NLS-1$
+ }
+ }
+
+ setPageComplete(anySelected && gotPatch);
+ setErrorMessage(error);
+ }
+
+ protected void handlePatchFileBrowseButtonPressed() {
+ FileDialog dialog= new FileDialog(getShell(), SWT.NONE);
+ dialog.setText(PatchMessages.getString("InputPatchPage.SelectPatchFileDialog.title")); //$NON-NLS-1$
+ dialog.setFilterPath(getPatchFilePath());
+ String res= dialog.open();
+ if (res == null)
+ return;
+
+ String patchFilePath= dialog.getFileName();
+ IPath filterPath= new Path(dialog.getFilterPath());
+ IPath path= filterPath.append(patchFilePath).makeAbsolute();
+ patchFilePath= path.toOSString();
+ //fDialogSettings.put(IUIConstants.DIALOGSTORE_LASTEXTJAR, filterPath.toOSString());
+
+ fPatchFileNameField.setText(patchFilePath);
+ //setSourceName(patchFilePath);
+ }
+
+ /**
+ * Sets the source name of the import to be the supplied path.
+ * Adds the name of the path to the list of items in the
+ * source combo and selects it.
+ *
+ * @param path the path to be added
+ */
+ protected void setSourceName(String path) {
+
+ if (path.length() > 0) {
+
+ String[] currentItems= fPatchFileNameField.getItems();
+ int selectionIndex= -1;
+ for (int i= 0; i < currentItems.length; i++)
+ if (currentItems[i].equals(path))
+ selectionIndex= i;
+
+ if (selectionIndex < 0) { // not found in history
+ int oldLength= currentItems.length;
+ String[] newItems= new String[oldLength + 1];
+ System.arraycopy(currentItems, 0, newItems, 0, oldLength);
+ newItems[oldLength]= path;
+ fPatchFileNameField.setItems(newItems);
+ selectionIndex= oldLength;
+ }
+ fPatchFileNameField.select(selectionIndex);
+
+ //resetSelection();
+ }
+ }
+
+ /**
+ * The Finish button was pressed. Try to do the required work now and answer
+ * a boolean indicating success. If false is returned then the wizard will
+ * not close.
+ *
+ * @return boolean
+ */
+ public boolean finish() {
+// if (!ensureSourceIsValid())
+// return false;
+
+ saveWidgetValues();
+
+// Iterator resourcesEnum = getSelectedResources().iterator();
+// List fileSystemObjects = new ArrayList();
+// while (resourcesEnum.hasNext()) {
+// fileSystemObjects.add(
+// ((FileSystemElement) resourcesEnum.next()).getFileSystemObject());
+// }
+//
+// if (fileSystemObjects.size() > 0)
+// return importResources(fileSystemObjects);
+//
+// MessageDialog
+// .openInformation(
+// getContainer().getShell(),
+// DataTransferMessages.getString("DataTransfer.information"), //$NON-NLS-1$
+// DataTransferMessages.getString("FileImport.noneSelected")); //$NON-NLS-1$
+//
+// return false;
+
+ return true;
+ }
+
+ /**
+ * Use the dialog store to restore widget values to the values that they held
+ * last time this wizard was used to completion
+ */
+ private void restoreWidgetValues() {
+ IDialogSettings settings= getDialogSettings();
+ if (settings != null) {
+
+ // set 'Use Clipboard' radio button
+ setUseClipboard(settings.getBoolean(STORE_USE_CLIPBOARD_ID));
+
+ // set filenames history
+ String[] sourceNames= settings.getArray(STORE_PATCH_FILES_ID);
+ if (sourceNames != null)
+ for (int i= 0; i < sourceNames.length; i++)
+ if (sourceNames[i] != null && sourceNames[i].length() > 0)
+ fPatchFileNameField.add(sourceNames[i]);
+
+ // set patch file path
+ String patchFilePath= settings.get(STORE_PATCH_FILES_ID);
+ if (patchFilePath != null)
+ setSourceName(patchFilePath);
+ }
+ }
+
+ /**
+ * Since Finish was pressed, write widget values to the dialog store so that they
+ * will persist into the next invocation of this wizard page
+ */
+ void saveWidgetValues() {
+ IDialogSettings settings= getDialogSettings();
+ if (settings != null) {
+
+ settings.put(STORE_USE_CLIPBOARD_ID, getUseClipboard());
+ settings.put(STORE_PATCH_FILES_ID, getPatchFilePath());
+
+ // update source names history
+ String[] sourceNames= settings.getArray(STORE_PATCH_FILES_ID);
+ if (sourceNames == null)
+ sourceNames= new String[0];
+
+ sourceNames= addToHistory(sourceNames, getPatchFilePath());
+ settings.put(STORE_PATCH_FILES_ID, sourceNames);
+ }
+ }
+
+ // static helpers
+
+ private void setUseClipboard(boolean useClipboard) {
+ if (useClipboard)
+ fUseClipboardButton.setSelection(true);
+ else
+ fUsePatchFileButton.setSelection(true);
+ setEnablePatchFile(!useClipboard);
+ }
+
+ private boolean getUseClipboard() {
+ if (fUseClipboardButton != null)
+ return fUseClipboardButton.getSelection();
+ return false;
+ }
+
+ private String getPatchFilePath() {
+ if (fPatchFileNameField != null)
+ return fPatchFileNameField.getText();
+ return ""; //$NON-NLS-1$
+ }
+
+ /**
+ * Creates a new label with a bold font.
+ *
+ * @param parent the parent control
+ * @param text the label text
+ * @return the new label control
+ */
+ private static Label buildPlainLabel(Composite parent, String text) {
+ Label label= new Label(parent, SWT.NONE);
+ label.setText(text);
+ GridData data= new GridData();
+ data.verticalAlignment= GridData.FILL;
+ data.horizontalAlignment= GridData.FILL;
+ label.setLayoutData(data);
+ return label;
+ }
+
+ /**
+ * Adds an entry to a history, while taking care of duplicate history items
+ * and excessively long histories. The assumption is made that all histories
+ * should be of length COMBO_HISTORY_LENGTH
.
+ *
+ * @param history the current history
+ * @param newEntry the entry to add to the history
+ */
+ protected static String[] addToHistory(String[] history, String newEntry) {
+ java.util.ArrayList l= new java.util.ArrayList(java.util.Arrays.asList(history));
+
+ l.remove(newEntry);
+ l.add(0,newEntry);
+
+ // since only one new item was added, we can be over the limit
+ // by at most one item
+ if (l.size() > COMBO_HISTORY_LENGTH)
+ l.remove(COMBO_HISTORY_LENGTH);
+
+ return (String[]) l.toArray(new String[l.size()]);
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/LineReader.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/LineReader.java
new file mode 100644
index 000000000..98026451e
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/LineReader.java
@@ -0,0 +1,115 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.io.*;
+import java.util.*;
+
+import org.eclipse.jface.util.Assert;
+
+/* package */ class LineReader {
+
+ private boolean fHaveChar= false;
+ private int fLastChar;
+ private boolean fSawEOF= false;
+ private BufferedReader fReader;
+
+ /* package */ LineReader(BufferedReader reader) {
+ fReader= reader;
+ Assert.isNotNull(reader);
+ }
+
+ /**
+ * Reads a line of text. A line is considered to be terminated by any one
+ * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
+ * followed immediately by a linefeed.
+ * @return A string containing the contents of the line including
+ * the line-termination characters, or null
if the end of the
+ * stream has been reached
+ * @exception IOException If an I/O error occurs
+ */
+ /* package */ String readLine() throws IOException {
+ StringBuffer sb= null;
+
+ while (!fSawEOF) {
+ int c= readChar();
+ if (c == -1) {
+ fSawEOF= true;
+ break;
+ }
+ if (sb == null)
+ sb= new StringBuffer();
+ sb.append((char)c);
+ if (c == '\n')
+ break;
+ if (c == '\r') {
+ c= readChar();
+ if (c == -1) {
+ fSawEOF= true;
+ break; // EOF
+ }
+ if (c != '\n') {
+ fHaveChar= true;
+ fLastChar= c;
+ } else
+ sb.append((char)c);
+ break;
+ }
+ }
+
+ if (sb != null)
+ return sb.toString();
+ return null;
+ }
+
+ /* package */ void close() {
+ try {
+ fReader.close();
+ } catch (IOException ex) {
+ }
+ }
+
+ /* package */ List readLines() {
+ try {
+ List lines= new ArrayList();
+ String line;
+ while ((line= readLine()) != null)
+ lines.add(line);
+ return lines;
+ } catch (IOException ex) {
+ //System.out.println("error while reading file: " + fileName + "(" + ex + ")");
+ } finally {
+ close();
+ }
+ return null;
+ }
+ /**
+ * Returns the number of characters in the given string without
+ * counting a trailing line separator.
+ */
+ /* package */ int lineContentLength(String line) {
+ if (line == null)
+ return 0;
+ int length= line.length();
+ for (int i= length-1; i >= 0; i--) {
+ char c= line.charAt(i);
+ if (c =='\n' || c == '\r')
+ length--;
+ else
+ break;
+ }
+ return length;
+ }
+
+ //---- private
+
+ private int readChar() throws IOException {
+ if (fHaveChar) {
+ fHaveChar= false;
+ return fLastChar;
+ }
+ return fReader.read();
+ }
+}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchCompareInput.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchCompareInput.java
new file mode 100644
index 000000000..1f26392b3
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchCompareInput.java
@@ -0,0 +1,180 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.io.*;
+import java.io.ByteArrayInputStream;
+import java.text.MessageFormat;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.*;
+
+import org.eclipse.jface.viewers.*;
+
+import org.eclipse.compare.*;
+import org.eclipse.compare.structuremergeviewer.*;
+import org.eclipse.compare.internal.*;
+
+
+/**
+ * A PatchCompareInput uses a Patcher to
+ * patch selected workspace resources.
+ */
+/* package */ class PatchCompareInput extends CompareEditorInput {
+
+ static class Rejected extends DiffNode implements IStreamContentAccessor {
+ Diff fDiff;
+ String fName;
+ Rejected(IDiffContainer parent, String name, Diff diff) {
+ super(parent, Differencer.NO_CHANGE);
+ fName= name;
+ fDiff= diff;
+ }
+ public String getName() {
+ return fName + " *"; //$NON-NLS-1$
+ }
+ public String getType() {
+ return "txt"; //$NON-NLS-1$
+ }
+ public Image getImage() {
+ return CompareUI.getImage("file"); //$NON-NLS-1$
+ }
+ public InputStream getContents() {
+ return new ByteArrayInputStream(fDiff.fRejected.getBytes());
+ }
+ }
+
+ private DiffNode fRoot;
+ private IResource fTarget;
+ private Patcher fPatcher;
+
+ /**
+ * Creates an compare editor input for the given selection.
+ */
+ /* package */ PatchCompareInput(CompareConfiguration config, Patcher patcher, ISelection selection) {
+ super(config);
+ fPatcher= patcher;
+ IResource[] s= Utilities.getResources(selection);
+ if (s.length == 1)
+ fTarget= s[0];
+ }
+
+ /**
+ * Performs a two-way or three-way diff on the current selection.
+ */
+ public Object prepareInput(IProgressMonitor pm) throws InvocationTargetException {
+
+ CompareConfiguration cc= (CompareConfiguration) getCompareConfiguration();
+
+ try {
+ Diff[] diffs= fPatcher.getDiffs();
+
+ pm.beginTask(Utilities.getString("ResourceCompare.taskName"), diffs.length); //$NON-NLS-1$
+
+ fRoot= new DiffNode(0);
+ IContainer rootFolder= null;
+ if (fTarget instanceof IContainer)
+ rootFolder= (IContainer) fTarget;
+
+ for (int i= 0; i < diffs.length; i++) {
+ Diff diff= diffs[i];
+ if (diff.fIsEnabled) {
+ IPath path= fPatcher.getPath(diff);
+ createPath(fRoot, rootFolder, path, diff, false);
+
+ String rej= diff.fRejected;
+ if (rej != null) {
+ IPath pp= path.removeLastSegments(1);
+ pp= pp.append(path.lastSegment() + ".rej"); //$NON-NLS-1$
+ createPath(fRoot, rootFolder, pp, diff, true);
+ }
+ }
+ pm.worked(1);
+ }
+
+ fTarget.refreshLocal(IResource.DEPTH_INFINITE, pm);
+
+ String leftLabel= fTarget.getName();
+ cc.setLeftLabel(leftLabel);
+ cc.setLeftImage(CompareUIPlugin.getImage(fTarget));
+
+ String rformat= PatchMessages.getString("PatchCompareInput.RightTitle.format"); //$NON-NLS-1$
+ String rightLabel= MessageFormat.format(rformat, new String[] { fPatcher.getName() } );
+ cc.setRightLabel(rightLabel);
+ //cc.setRightImage(CompareUIPlugin.getImage(fRightResource));
+
+ String format= Utilities.getString("ResourceCompare.twoWay.title"); //$NON-NLS-1$
+ String title= MessageFormat.format(format, new String[] {leftLabel, rightLabel} );
+ setTitle(title);
+
+ return fRoot;
+
+ } catch (CoreException ex) {
+ throw new InvocationTargetException(ex);
+ } finally {
+ pm.done();
+ }
+ }
+
+ public void saveChanges(IProgressMonitor pm) throws CoreException {
+ if (fRoot instanceof DiffNode) {
+ try {
+ commit(pm, (DiffNode) fRoot);
+ } finally {
+ setDirty(false);
+ }
+ }
+ }
+
+ /*
+ * Recursively walks the diff tree and commits all changes.
+ */
+ private static void commit(IProgressMonitor pm, DiffNode node) throws CoreException {
+
+ ITypedElement left= node.getLeft();
+ if (left instanceof BufferedResourceNode)
+ ((BufferedResourceNode) left).commit(pm);
+
+ ITypedElement right= node.getRight();
+ if (right instanceof BufferedResourceNode)
+ ((BufferedResourceNode) right).commit(pm);
+
+ IDiffElement[] children= node.getChildren();
+ if (children != null) {
+ for (int i= 0; i < children.length; i++) {
+ IDiffElement element= children[i];
+ if (element instanceof DiffNode)
+ commit(pm, (DiffNode) element);
+ }
+ }
+ }
+
+ private void createPath(DiffContainer root, IContainer folder, IPath path, Diff diff, boolean reject) {
+ if (path.segmentCount() > 1) {
+ IFolder f= folder.getFolder(path.uptoSegment(1));
+ IDiffElement child= root.findChild(path.segment(0));
+ if (child == null) {
+ ResourceNode rn= new ResourceNode(f);
+ child= new DiffNode(root, Differencer.CHANGE, null, rn, rn);
+ }
+ if (child instanceof DiffContainer)
+ createPath((DiffContainer)child, f, path.removeFirstSegments(1), diff, reject);
+ } else {
+ // a leaf
+ BufferedResourceNode rn= new BufferedResourceNode(folder.getFile(path));
+ if (reject) {
+ new Rejected(root, path.segment(0), diff);
+ } else {
+ new DiffNode(root, diff.getType(), null, rn, new PatchedResource(rn, diff, path, fPatcher));
+ }
+ }
+ }
+}
+
+
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchErrorDialog.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchErrorDialog.java
new file mode 100644
index 000000000..cd4cb28a6
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchErrorDialog.java
@@ -0,0 +1,17 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+
+import org.eclipse.compare.internal.ListDialog;
+
+public class PatchErrorDialog {
+
+ private PatchErrorDialog() {
+ // no instance.
+ }
+
+}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java
new file mode 100644
index 000000000..8dce380cc
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java
@@ -0,0 +1,26 @@
+/*
+ * (c) Copyright IBM Corp. 2002.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class PatchMessages {
+
+ private static final String RESOURCE_BUNDLE= "org.eclipse.compare.internal.patch.PatchMessages";//$NON-NLS-1$
+
+ private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE);
+
+ private PatchMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ }
+}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties
new file mode 100644
index 000000000..e9aed4f47
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties
@@ -0,0 +1,73 @@
+# =====================================
+# (c) Copyright IBM Corp. 2002.
+# All Rights Reserved.
+# =====================================
+
+#
+# 'Compare with Patch' Action
+#
+PatchAction.ExceptionTitle=Saving Resources
+PatchAction.Exception=Unexpected exception. See log for details
+PatchAction.SavingDirtyEditorsTask=Saving dirty editors
+PatchAction.AlwaysSaveQuestion=&Always save all modified resources automatically prior to patching
+PatchAction.SaveAllQuestion=Save all modified resources
+PatchAction.SaveAllDescription=All modified resources must be saved before this operation.\nPress OK to confirm or Cancel otherwise
+
+#
+# PatchWizard
+#
+PatchWizard.title=Resource Patcher
+
+#
+# InputPatchPage
+#
+InputPatchPage.title= Patch Input Specification
+InputPatchPage.message= Define what resource to patch with which patch
+InputPatchPage.Clipboard=Clipboard
+InputPatchPage.SelectInput=Select a single file or folder to patch:
+InputPatchPage.PatchErrorDialog=Patch Error
+InputPatchPage.SelectPatch.title=Select Patch
+InputPatchPage.FileButton.text=File
+InputPatchPage.ChooseFileButton.text=Choose
+InputPatchPage.UseClipboardButton.text=Clipboard
+InputPatchPage.NothingSelected.message=Nothing selected to apply patch to
+InputPatchPage.ClipboardIsEmpty.message=Clipboard is empty
+InputPatchPage.NoTextInClipboard.message=Clipboard does not contain text
+InputPatchPage.CouldNotReadClipboard.message=Couldn\'t retrieve clipboard contents
+InputPatchPage.CannotLocatePatch.message=Can\'t locate patch file:
+InputPatchPage.NoFileName.message=No file name
+InputPatchPage.SelectPatchFileDialog.title=Select Patch File
+InputPatchPage.PatchFileNotFound.message=Patch file not found.
+InputPatchPage.ParseError.message=Error while parsing patch
+InputPatchPage.NoDiffsFound.message=No diffs found in
+
+#
+# PreviewPatchPage
+#
+PreviewPatchPage.title= Verify Patch
+PreviewPatchPage.message= The tree shows the contents of the patch.\nA checked item indicates that a patch could be applied succesfully. Uncheck an item if you want to exclude it.
+PreviewPatchPage.Left.title= Original
+PreviewPatchPage.Right.title= Result
+PreviewPatchPage.PatchOptions.title=Patch Options
+PreviewPatchPage.IgnoreSegments.text=Ignore leading path name segments:
+PreviewPatchPage.ReversePatch.text=Reverse Patch
+PreviewPatchPage.FuzzFactor.text=Maximum fuzz factor:
+PreviewPatchPage.FuzzFactor.tooltip=Allow context to shift this number of lines from the original place
+PreviewPatchPage.IgnoreWhitespace.text=Ignore Whitespace
+PreviewPatchPage.NoName.text=no name
+PreviewPatchPage.FileExists.error=(file already exists)
+PreviewPatchPage.FileDoesNotExist.error=(file doesn\'t exist)
+PreviewPatchPage.NoMatch.error=(no match)
+
+#
+# Patcher
+#
+Patcher.ErrorDialog.title=title
+Patcher.DeleteError.message=Error while deleting resource
+Patcher.UpdateError.message=Error while updating resource
+Patcher.RefreshError.message=Error while refreshing from local
+
+#
+# PatchCompareInput
+#
+PatchCompareInput.RightTitle.format= Patch: {0}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java
new file mode 100644
index 000000000..466b59a42
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java
@@ -0,0 +1,148 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.compare.*;
+import org.eclipse.compare.internal.*;
+import org.eclipse.compare.structuremergeviewer.Differencer;
+
+
+/* package */ class PatchWizard extends Wizard {
+
+ // dialog store id constants
+ private final static String DIALOG_SETTINGS_KEY= "PatchWizard"; //$NON-NLS-1$
+
+ private boolean fHasNewDialogSettings;
+
+ private InputPatchPage fPatchWizardPage;
+ private PreviewPatchPage fPreviewPatchPage;
+
+ private Patcher fPatcher;
+ private IResource fTarget;
+
+
+ /**
+ * Creates a wizard for applying a patch file to the workspace.
+ */
+ /* package */ PatchWizard(ISelection selection) {
+
+ fTarget= getResource(selection);
+
+ fPatcher= new Patcher();
+
+ setWindowTitle(PatchMessages.getString("PatchWizard.title")); //$NON-NLS-1$
+
+ IDialogSettings workbenchSettings= CompareUIPlugin.getDefault().getDialogSettings();
+ IDialogSettings section= workbenchSettings.getSection(DIALOG_SETTINGS_KEY); //$NON-NLS-1$
+ if (section == null)
+ fHasNewDialogSettings= true;
+ else {
+ fHasNewDialogSettings= false;
+ setDialogSettings(section);
+ }
+ }
+
+ static IResource getResource(ISelection selection) {
+ IResource[] rs= Utilities.getResources(selection);
+ if (rs != null && rs.length > 0)
+ return rs[0];
+ return null;
+ }
+
+ Patcher getPatcher() {
+ return fPatcher;
+ }
+
+ IResource getTarget() {
+ return fTarget;
+ }
+
+ void setTarget(IResource target) {
+ fTarget= target;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on IWizard.
+ */
+ public void addPages() {
+ super.addPages();
+
+ addPage(fPatchWizardPage= new InputPatchPage(this));
+ addPage(fPreviewPatchPage= new PreviewPatchPage(this));
+ }
+
+ /* (non-Javadoc)
+ * Method declared on IWizard.
+ */
+ public boolean performFinish() {
+
+ if (false) {
+ CompareConfiguration cc= new CompareConfiguration() {
+ public Image getImage(int kind) {
+ if (kind == Differencer.ADDITION)
+ kind= Differencer.DELETION;
+ else if (kind == Differencer.DELETION)
+ kind= Differencer.ADDITION;
+ return super.getImage(kind);
+ }
+ public Image getImage(Image base, int kind) {
+ if (kind == Differencer.ADDITION)
+ kind= Differencer.DELETION;
+ else if (kind == Differencer.DELETION)
+ kind= Differencer.ADDITION;
+ return super.getImage(base, kind);
+ }
+ };
+ cc.setProperty(CompareEditor.CONFIRM_SAVE_PROPERTY, new Boolean(false));
+
+ fPatcher.setName(fPatchWizardPage.getPatchName());
+
+ CompareUI.openCompareEditor(new PatchCompareInput(cc, fPatcher, new StructuredSelection(fTarget)));
+ } else {
+ fPatcher.setName(fPatchWizardPage.getPatchName());
+
+ try {
+ IRunnableWithProgress op= new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ fPatcher.applyAll(getTarget(), monitor);
+ }
+ };
+ new ProgressMonitorDialog(CompareUIPlugin.getShell()).run(true, true, op);
+ } catch (InvocationTargetException e) {
+ // handle exception
+ } catch (InterruptedException e) {
+ // handle cancelation
+ }
+ }
+
+ // Save the dialog settings
+ if (fHasNewDialogSettings) {
+ IDialogSettings workbenchSettings= CompareUIPlugin.getDefault().getDialogSettings();
+ IDialogSettings section= workbenchSettings.getSection(DIALOG_SETTINGS_KEY);
+ section= workbenchSettings.addNewSection(DIALOG_SETTINGS_KEY);
+ setDialogSettings(section);
+ }
+
+ fPatchWizardPage.saveWidgetValues();
+ //fPreviewPatchPage.saveWidgetValues();
+
+ return true;
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchedResource.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchedResource.java
new file mode 100644
index 000000000..5236f80e0
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchedResource.java
@@ -0,0 +1,69 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.io.*;
+
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.core.runtime.*;
+
+import org.eclipse.compare.*;
+
+
+/* package */ class PatchedResource implements ITypedElement, IStreamContentAccessor {
+
+ private Diff fDiff;
+ private IStreamContentAccessor fCurrent;
+ private IPath fPath;
+ private byte[] fContent;
+ private Patcher fPatcher;
+
+ /* package */ PatchedResource(IStreamContentAccessor current, Diff diff, IPath path, Patcher patcher) {
+ fDiff= diff;
+ fCurrent= current;
+ fPath= path;
+ fPatcher= patcher;
+ }
+
+ public InputStream getContents() throws CoreException {
+ if (fContent == null) {
+ InputStream is= null;
+
+ try {
+ is= fCurrent.getContents();
+ } catch (CoreException ex) {
+ is= new ByteArrayInputStream(new byte[0]);
+ }
+ if (is != null) {
+ BufferedReader br= new BufferedReader(new InputStreamReader(is));
+ String s= fPatcher.patch(fDiff,br, null);
+ if (s != null)
+ fContent= s.getBytes();
+ try {
+ is.close();
+ } catch (IOException ex) {
+ }
+ }
+ }
+ return new ByteArrayInputStream(fContent);
+ }
+
+ public Image getImage() {
+ return CompareUI.getImage(getType());
+ }
+
+ public String getName() {
+ return fPath.toOSString();
+ }
+
+ public String getType() {
+ String type= fPath.getFileExtension();
+ if (type != null)
+ return type;
+ return ITypedElement.UNKNOWN_TYPE;
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Patcher.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Patcher.java
new file mode 100644
index 000000000..c2d5264b3
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Patcher.java
@@ -0,0 +1,948 @@
+package org.eclipse.compare.internal.patch;
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+import org.eclipse.jface.util.Assert;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.*;
+
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.compare.internal.ExceptionHandler;
+
+
+/**
+ * A Patcher
+ * - knows how to parse various patch file formats into some in-memory structure,
+ * - holds onto the parsed data and the options to use when applying the patches,
+ * - knows how to apply the patches to files and folders.
+ */
+public class Patcher {
+
+ private static final boolean DEBUG= false;
+
+ private static final String DEV_NULL= "/dev/null"; //$NON-NLS-1$
+
+ // diff formats
+ private static final int CONTEXT= 0;
+ private static final int ED= 1;
+ private static final int NORMAL= 2;
+ private static final int UNIFIED= 3;
+
+ // we recognize the following date/time formats
+ private static DateFormat[] DATE_FORMATS= new DateFormat[] {
+ new SimpleDateFormat("EEE MMM dd kk:mm:ss yyyy"), //$NON-NLS-1$
+ new SimpleDateFormat("yyyy/MM/dd kk:mm:ss"), //$NON-NLS-1$
+ new SimpleDateFormat("EEE MMM dd kk:mm:ss yyyy", Locale.US) //$NON-NLS-1$
+ };
+
+ private String fName;
+ private Diff[] fDiffs;
+ // patch options
+ private int fStripPrefixSegments;
+ private int fFuzz;
+ private boolean fIgnoreWhitespace;
+ private boolean fReverse= false;
+
+
+ Patcher() {
+ }
+
+ //---- options
+
+ void setName(String name) {
+ fName= name;
+ }
+
+ String getName() {
+ return fName;
+ }
+
+ /**
+ * Returns an array of Diffs after a sucessfull call to parse
.
+ * If parse
hasn't been called returns null
.
+ */
+ Diff[] getDiffs() {
+ return fDiffs;
+ }
+
+ IPath getPath(Diff diff) {
+ IPath path= diff.getPath();
+ if (fStripPrefixSegments > 0 && fStripPrefixSegments < path.segmentCount())
+ path= path.removeFirstSegments(fStripPrefixSegments);
+ return path;
+ }
+
+ /**
+ * Returns true
if new value differs from old.
+ */
+ boolean setStripPrefixSegments(int strip) {
+ if (strip != fStripPrefixSegments) {
+ fStripPrefixSegments= strip;
+ return true;
+ }
+ return false;
+ }
+
+ int getStripPrefixSegments() {
+ return fStripPrefixSegments;
+ }
+
+ /**
+ * Returns true
if new value differs from old.
+ */
+ boolean setFuzz(int fuzz) {
+ if (fuzz != fFuzz) {
+ fFuzz= fuzz;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true
if new value differs from old.
+ */
+ boolean setReversed(boolean reverse) {
+ if (fReverse != reverse) {
+ fReverse= reverse;
+
+ for (int i= 0; i < fDiffs.length; i++)
+ fDiffs[i].reverse();
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true
if new value differs from old.
+ */
+ boolean setIgnoreWhitespace(boolean ignoreWhitespace) {
+ if (ignoreWhitespace != fIgnoreWhitespace) {
+ fIgnoreWhitespace= ignoreWhitespace;
+ return true;
+ }
+ return false;
+ }
+
+ //---- parsing patch files
+
+ /* package */ void parse(BufferedReader reader) throws IOException {
+ List diffs= new ArrayList();
+ String line= null;
+ boolean reread= false;
+ String diffArgs= null;
+ String fileName= null;
+
+ LineReader lr= new LineReader(reader);
+
+ // read leading garbage
+ while (true) {
+ if (!reread)
+ line= lr.readLine();
+ reread= false;
+ if (line == null)
+ break;
+ if (line.length() < 4)
+ continue; // too short
+
+ // remember some infos
+ if (line.startsWith("Index: ")) { //$NON-NLS-1$
+ fileName= line.substring(7).trim();
+ continue;
+ }
+ if (line.startsWith("diff")) { //$NON-NLS-1$
+ diffArgs= line.substring(4).trim();
+ continue;
+ }
+
+ if (line.startsWith("--- ")) { //$NON-NLS-1$
+ line= readUnifiedDiff(diffs, lr, line, diffArgs, fileName);
+ diffArgs= fileName= null;
+ reread= true;
+ } else if (line.startsWith("*** ")) { //$NON-NLS-1$
+ line= readContextDiff(diffs, lr, line, diffArgs, fileName);
+ diffArgs= fileName= null;
+ reread= true;
+ }
+ }
+
+ lr.close();
+
+ fDiffs= (Diff[]) diffs.toArray((Diff[]) new Diff[diffs.size()]);
+ }
+
+ /**
+ * Returns the next line that does not belong to this diff
+ */
+ private String readUnifiedDiff(List diffs, LineReader reader, String line, String args, String fileName) throws IOException {
+
+ String[] oldArgs= split(line.substring(4));
+
+ // read info about new file
+ line= reader.readLine();
+ if (line == null || !line.startsWith("+++ ")) //$NON-NLS-1$
+ return line;
+
+ String[] newArgs= split(line.substring(4));
+
+ Diff diff= new Diff(extractPath(oldArgs, 0, fileName), extractDate(oldArgs, 1),
+ extractPath(newArgs, 0, fileName), extractDate(newArgs, 1));
+ diffs.add(diff);
+
+ int[] oldRange= new int[2];
+ int[] newRange= new int[2];
+ List lines= new ArrayList();
+
+ try {
+ // read lines of hunk
+ while (true) {
+
+ line= reader.readLine();
+ if (line == null)
+ return null;
+
+ if (reader.lineContentLength(line) == 0) {
+ lines.add(' ' + line);
+ continue;
+ }
+
+ char c= line.charAt(0);
+ switch (c) {
+ case '@':
+ if (line.startsWith("@@ ")) { //$NON-NLS-1$
+ // flush old hunk
+ if (lines.size() > 0) {
+ new Hunk(diff, oldRange, newRange, lines);
+ lines.clear();
+ }
+
+ // format: @@ -oldStart,oldLength +newStart,newLength @@
+ extractPair(line, '-', oldRange);
+ extractPair(line, '+', newRange);
+ continue;
+ }
+ break;
+ case ' ':
+ case '+':
+ case '-':
+ lines.add(line);
+ continue;
+ case '\\':
+ if (line.startsWith("No newline at end of file", 2)) { //$NON-NLS-1$
+ int lastIndex= lines.size();
+ if (lastIndex > 0) {
+ line= (String) lines.get(lastIndex-1);
+ int end= line.length()-1;
+ char lc= line.charAt(end);
+ if (lc == '\n') {
+ end--;
+ if (end > 0 && line.charAt(end-1) == '\r')
+ end--;
+ } else if (lc == '\r') {
+ end--;
+ }
+ line= line.substring(0, end);
+ lines.set(lastIndex-1, line);
+ }
+ continue;
+ }
+ break;
+ default:
+ if (DEBUG) {
+ int a1= c, a2= 0;
+ if (line.length() > 1)
+ a2= line.charAt(1);
+ System.out.println("char: " + a1 + " " + a2); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ break;
+ }
+ return line;
+ }
+ } finally {
+ if (lines.size() > 0)
+ new Hunk(diff, oldRange, newRange, lines);
+ diff.finish();
+ }
+ }
+
+ /**
+ * Returns the next line that does not belong to this diff
+ */
+ private String readContextDiff(List diffs, LineReader reader, String line, String args, String fileName) throws IOException {
+
+ String[] oldArgs= split(line.substring(4));
+
+ // read info about new file
+ line= reader.readLine();
+ if (line == null || !line.startsWith("--- ")) //$NON-NLS-1$
+ return line;
+
+ String[] newArgs= split(line.substring(4));
+
+ Diff diff= new Diff(extractPath(oldArgs, 0, fileName), extractDate(oldArgs, 1),
+ extractPath(newArgs, 0, fileName), extractDate(newArgs, 1));
+ diffs.add(diff);
+
+ int[] oldRange= new int[2];
+ int[] newRange= new int[2];
+ List oldLines= new ArrayList();
+ List newLines= new ArrayList();
+ List lines= oldLines;
+
+ try {
+ // read lines of hunk
+ while (true) {
+
+ line= reader.readLine();
+ if (line == null)
+ return line;
+
+ int l= line.length();
+ if (l == 0)
+ continue;
+ if (l > 1) {
+ switch (line.charAt(0)) {
+ case '*':
+ if (line.startsWith("***************")) { // new hunk //$NON-NLS-1$
+ // flush old hunk
+ if (oldLines.size() > 0 || newLines.size() > 0) {
+ new Hunk(diff, oldRange, newRange, unifyLines(oldLines, newLines));
+ oldLines.clear();
+ newLines.clear();
+ }
+ continue;
+ }
+ if (line.startsWith("*** ")) { // old range //$NON-NLS-1$
+ // format: *** oldStart,oldEnd ***
+ extractPair(line, ' ', oldRange);
+ oldRange[1]= oldRange[1]-oldRange[0]+1;
+ lines= oldLines;
+ continue;
+ }
+ break;
+ case ' ': // context line
+ case '+': // addition
+ case '!': // change
+ if (line.charAt(1) == ' ') {
+ lines.add(line);
+ continue;
+ }
+ break;
+ case '-':
+ if (line.charAt(1) == ' ') { // deletion
+ lines.add(line);
+ continue;
+ }
+ if (line.startsWith("--- ")) { // new range //$NON-NLS-1$
+ // format: *** newStart,newEnd ***
+ extractPair(line, ' ', newRange);
+ newRange[1]= newRange[1]-newRange[0]+1;
+ lines= newLines;
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return line;
+ }
+ } finally {
+ // flush last hunk
+ if (oldLines.size() > 0 || newLines.size() > 0)
+ new Hunk(diff, oldRange, newRange, unifyLines(oldLines, newLines));
+ diff.finish();
+ }
+ }
+
+ /**
+ * Creates a List of lines in the unified format from
+ * two Lists of lines in the 'classic' format.
+ */
+ private List unifyLines(List oldLines, List newLines) {
+ List result= new ArrayList();
+
+ String[] ol= (String[]) oldLines.toArray(new String[oldLines.size()]);
+ String[] nl= (String[]) newLines.toArray(new String[newLines.size()]);
+
+ int oi= 0, ni= 0;
+
+ while (true) {
+
+ char oc= 0;
+ String o= null;
+ if (oi < ol.length) {
+ o= ol[oi];
+ oc= o.charAt(0);
+ }
+
+ char nc= 0;
+ String n= null;
+ if (ni < nl.length) {
+ n= nl[ni];
+ nc= n.charAt(0);
+ }
+
+ // EOF
+ if (oc == 0 && nc == 0)
+ break;
+
+ // deletion in old
+ if (oc == '-') {
+ do {
+ result.add('-' + o.substring(2));
+ oi++;
+ if (oi >= ol.length)
+ break;
+ o= ol[oi];
+ } while (o.charAt(0) == '-');
+ continue;
+ }
+
+ // addition in new
+ if (nc == '+') {
+ do {
+ result.add('+' + n.substring(2));
+ ni++;
+ if (ni >= nl.length)
+ break;
+ n= nl[ni];
+ } while (n.charAt(0) == '+');
+ continue;
+ }
+
+ // differing lines on both sides
+ if (oc == '!' && nc == '!') {
+ // remove old
+ do {
+ result.add('-' + o.substring(2));
+ oi++;
+ if (oi >= ol.length)
+ break;
+ o= ol[oi];
+ } while (o.charAt(0) == '!');
+
+ // add new
+ do {
+ result.add('+' + n.substring(2));
+ ni++;
+ if (ni >= nl.length)
+ break;
+ n= nl[ni];
+ } while (n.charAt(0) == '!');
+
+ continue;
+ }
+
+ // context lines
+ if (oc == ' ' && nc == ' ') {
+ do {
+ Assert.isTrue(o.equals(n), "non matching context lines"); //$NON-NLS-1$
+ result.add(' ' + o.substring(2));
+ oi++;
+ ni++;
+ if (oi >= ol.length || ni >= nl.length)
+ break;
+ o= ol[oi];
+ n= nl[ni];
+ } while (o.charAt(0) == ' ' && n.charAt(0) == ' ');
+ continue;
+ }
+
+ if (oc == ' ') {
+ do {
+ result.add(' ' + o.substring(2));
+ oi++;
+ if (oi >= ol.length)
+ break;
+ o= ol[oi];
+ } while (o.charAt(0) == ' ');
+ continue;
+ }
+
+ if (nc == ' ') {
+ do {
+ result.add(' ' + n.substring(2));
+ ni++;
+ if (ni >= nl.length)
+ break;
+ n= nl[ni];
+ } while (n.charAt(0) == ' ');
+ continue;
+ }
+
+ Assert.isTrue(false, "unexpected char <" + oc + "> <" + nc + ">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ return result;
+ }
+
+ /**
+ * Breaks the given string into tab separated substrings.
+ * Leading and trailing whitespace is removed from each token.
+ */
+ private String[] split(String line) {
+ List l= new ArrayList();
+ StringTokenizer st= new StringTokenizer(line, "\t"); //$NON-NLS-1$
+ while (st.hasMoreElements()) {
+ String token= st.nextToken().trim();
+ if (token.length() > 0)
+ l.add(token);
+ }
+ return (String[]) l.toArray(new String[l.size()]);
+ }
+
+ /**
+ * @return the parsed time/date in milliseconds or -1 on error
+ */
+ private long extractDate(String[] args, int n) {
+ if (n < args.length) {
+ String line= args[n];
+ for (int i= 0; i < DATE_FORMATS.length; i++) {
+ DATE_FORMATS[i].setLenient(true);
+ try {
+ Date date= DATE_FORMATS[i].parse(line);
+ return date.getTime();
+ } catch (ParseException ex) {
+ }
+ }
+ // System.err.println("can't parse date: <" + line + ">");
+ }
+ return -1;
+ }
+
+ /**
+ * Returns null if file name is "/dev/null".
+ */
+ private IPath extractPath(String[] args, int n, String path2) {
+ if (n < args.length) {
+ String path= args[n];
+ if (DEV_NULL.equals(path))
+ return null;
+ int pos= path.lastIndexOf(':');
+ if (pos >= 0)
+ path= path.substring(0, pos);
+ if (path2 != null && !path2.equals(path)) {
+ if (DEBUG) System.out.println("path mismatch: " + path2); //$NON-NLS-1$
+ path= path2;
+ }
+ return new Path(path);
+ }
+ return null;
+ }
+
+ /**
+ * Tries to extract two integers separated by a comma.
+ * The parsing of the line starts at the position after
+ * the first occurrence of the given character start an ends
+ * at the first blank (or the end of the line).
+ * If only a single number is found this is assumed to be the length of the range.
+ * In this case the start of the range is set to 1.
+ * If an error occurs the range -1,-1 is returned.
+ */
+ private void extractPair(String line, char start, int[] pair) {
+ pair[0]= pair[1]= -1;
+ int startPos= line.indexOf(start);
+ if (startPos < 0) {
+ if (DEBUG) System.out.println("parsing error in extractPair: couldn't find \'" + start + "\'"); //$NON-NLS-1$ //$NON-NLS-2$
+ return;
+ }
+ line= line.substring(startPos+1);
+ int endPos= line.indexOf(' ');
+ if (endPos < 0) {
+ if (DEBUG) System.out.println("parsing error in extractPair: couldn't find end blank"); //$NON-NLS-1$
+ return;
+ }
+ line= line.substring(0, endPos);
+ int comma= line.indexOf(',');
+ if (comma >= 0) {
+ pair[0]= Integer.parseInt(line.substring(0, comma));
+ pair[1]= Integer.parseInt(line.substring(comma+1));
+ } else {
+ pair[0]= 1;
+ pair[1]= Integer.parseInt(line.substring(comma+1));
+ }
+ }
+
+ //---- applying a patch file
+
+ /**
+ * Tries to patch the given lines with the specified Diff.
+ * Any hunk that couldn't be applied is returned in the list failedHunks.
+ */
+ /* package */ void patch(Diff diff, List lines, List failedHunks) {
+
+ int shift= 0;
+ Iterator iter= diff.fHunks.iterator();
+ while (iter.hasNext()) {
+ Hunk hunk= (Hunk) iter.next();
+ shift= patch(hunk, lines, shift, failedHunks);
+ }
+ }
+
+ /**
+ * Tries to patch the contents of the given reader with the specified Diff.
+ * Any hunk that couldn't be applied is returned in the list failedHunks.
+ */
+ /* package */ String patch(Diff diff, BufferedReader reader, List failedHunks) {
+
+ List lines= new LineReader(reader).readLines();
+ if (lines == null)
+ lines= new ArrayList();
+
+ patch(diff, lines, failedHunks);
+
+ return createString(lines);
+ }
+
+ /**
+ * Tries to apply the specified hunk to the given lines.
+ * If the hunk cannot be applied at the original position
+ * the methods tries Fuzz lines before and after.
+ * If this fails the Hunk is added to the given list of failed hunks.
+ */
+ private int patch(Hunk hunk, List lines, int shift, List failedHunks) {
+ if (tryPatch(hunk, lines, shift)) {
+ shift+= doPatch(hunk, lines, shift);
+ } else {
+ boolean found= false;
+ int oldShift= shift;
+
+ for (int i= shift-1; i > shift-fFuzz; i--) {
+ if (tryPatch(hunk, lines, i)) {
+ shift= i;
+ found= true;
+ break;
+ }
+ }
+
+ if (! found) {
+ for (int i= shift+1; i < shift+fFuzz; i++) {
+ if (tryPatch(hunk, lines, i)) {
+ shift= i;
+ found= true;
+ break;
+ }
+ }
+ }
+
+ if (found) {
+ if (DEBUG) System.out.println("patched hunk at offset: " + (shift-oldShift)); //$NON-NLS-1$
+ shift+= doPatch(hunk, lines, shift);
+ } else {
+ if (failedHunks != null) {
+ if (DEBUG) System.out.println("failed hunk"); //$NON-NLS-1$
+ failedHunks.add(hunk);
+ }
+ }
+ oldShift= oldShift; // prevent compiler warning about unused local variable
+ }
+ return shift;
+ }
+
+ private boolean tryPatch(Hunk hunk, List lines, int shift) {
+ int pos= hunk.fOldStart + shift;
+ int contextMatches= 0;
+ int deleteMatches= 0;
+ for (int i= 0; i < hunk.fLines.length; i++) {
+ String s= hunk.fLines[i];
+ Assert.isTrue(s.length() > 0);
+ String line= s.substring(1);
+ char controlChar= s.charAt(0);
+ if (controlChar == ' ') { // context lines
+ while (true) {
+ if (pos < 0 || pos >= lines.size())
+ return false;
+ if (linesMatch(line, (String) lines.get(pos))) {
+ contextMatches++;
+ pos++;
+ break;
+ }
+ if (contextMatches <= 0)
+ return false;
+ pos++;
+ }
+ } else if (controlChar == '-') {
+ // deleted lines
+ while (true) {
+ if (pos < 0 || pos >= lines.size())
+ return false;
+ if (linesMatch(line, (String) lines.get(pos))) {
+ deleteMatches++;
+ pos++;
+ break;
+ }
+ if (deleteMatches <= 0)
+ return false;
+ pos++;
+ }
+ } else if (controlChar == '+') {
+ // added lines
+ // we don't have to do anything for a 'try'
+ } else
+ Assert.isTrue(false, "tryPatch: unknown control charcter: " + controlChar); //$NON-NLS-1$
+ }
+ return true;
+ }
+
+ private int doPatch(Hunk hunk, List lines, int shift) {
+ int pos= hunk.fOldStart + shift;
+ for (int i= 0; i < hunk.fLines.length; i++) {
+ String s= hunk.fLines[i];
+ Assert.isTrue(s.length() > 0);
+ String line= s.substring(1);
+ char controlChar= s.charAt(0);
+ if (controlChar == ' ') { // context lines
+ while (true) {
+ Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in context"); //$NON-NLS-1$
+ if (linesMatch(line, (String) lines.get(pos))) {
+ pos++;
+ break;
+ }
+ pos++;
+ }
+ } else if (controlChar == '-') {
+ // deleted lines
+ while (true) {
+ Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in deleted lines"); //$NON-NLS-1$
+ if (linesMatch(line, (String) lines.get(pos))) {
+ break;
+ }
+ pos++;
+ }
+ lines.remove(pos);
+ } else if (controlChar == '+') {
+ // added lines
+ lines.add(pos, line);
+ pos++;
+ } else
+ Assert.isTrue(false, "doPatch: unknown control charcter: " + controlChar); //$NON-NLS-1$
+ }
+ return hunk.fNewLength - hunk.fOldLength;
+ }
+
+ public void applyAll(IResource target, IProgressMonitor pm) {
+
+ final int WORK_UNIT= 10;
+
+ if (DEBUG) System.out.println("applyAll: start"); //$NON-NLS-1$
+
+ IFile file= null; // file to be patched
+ IContainer container= null;
+ if (target instanceof IContainer)
+ container= (IContainer) target;
+ else if (target instanceof IFile) {
+ file= (IFile) target;
+ container= file.getParent();
+ } else {
+ System.out.println("applyAll: not yet implemented"); //$NON-NLS-1$
+ return;
+ }
+
+ if (pm != null)
+ pm.beginTask("Patching", fDiffs.length*WORK_UNIT);
+
+ for (int i= 0; i < fDiffs.length; i++) {
+
+ int workTicks= WORK_UNIT;
+
+ Diff diff= fDiffs[i];
+ if (diff.fIsEnabled) {
+
+ IPath path= getPath(diff);
+ if (pm != null)
+ pm.subTask(path.toString());
+
+ if (container != null)
+ file= createPath(container, path);
+ List failed= new ArrayList();
+ List result= null;
+
+ int type= diff.getType();
+ switch (type) {
+ case Differencer.ADDITION:
+ // patch it and collect rejected hunks
+ result= apply(diff, file, true, failed);
+ updateFile(createString(result), file, new SubProgressMonitor(pm, workTicks));
+ workTicks-= WORK_UNIT;
+ break;
+ case Differencer.DELETION:
+ deleteFile(file, new SubProgressMonitor(pm, workTicks));
+ workTicks-= WORK_UNIT;
+ break;
+ case Differencer.CHANGE:
+ // patch it and collect rejected hunks
+ result= apply(diff, file, false, failed);
+ updateFile(createString(result), file, new SubProgressMonitor(pm, workTicks));
+ workTicks-= WORK_UNIT;
+ break;
+ }
+
+ if (failed.size() > 0) {
+ IPath pp= null;
+ if (path.segmentCount() > 1) {
+ pp= path.removeLastSegments(1);
+ pp= pp.append(path.lastSegment() + ".rej"); //$NON-NLS-1$
+ } else
+ pp= new Path(path.lastSegment() + ".rej"); //$NON-NLS-1$
+ file= createPath(container, pp);
+ updateFile(getRejected(failed), file, pm);
+ }
+ }
+
+ if (pm != null) {
+ if (pm.isCanceled())
+ break;
+ if (workTicks > 0)
+ pm.worked(workTicks);
+ }
+ }
+
+ /*
+ if (pm != null)
+ pm.subTask("Refreshing");
+ try {
+ target.refreshLocal(IResource.DEPTH_INFINITE, pm);
+ } catch (CoreException ex) {
+ ExceptionHandler.handle(ex,
+ PatchMessages.getString("Patcher.ErrorDialog.title"), //$NON-NLS-1$
+ PatchMessages.getString("Patcher.RefreshError.message")); //$NON-NLS-1$
+ }
+ */
+
+ // IWorkspace.validateEdit(IFile[], Object context);
+ }
+
+ List apply(Diff diff, IFile file, boolean create, List failedHunks) {
+
+ List lines= null;
+ if (!create && file != null) {
+ // read current contents
+ InputStream is= null;
+ try {
+ is= file.getContents();
+ BufferedReader reader= new BufferedReader(new InputStreamReader(is));
+ lines= new LineReader(reader).readLines();
+ if (DEBUG) System.out.println(" creating reader successful"); //$NON-NLS-1$
+ } catch(CoreException ex) {
+ if (DEBUG) System.out.println(" reading contents: " + ex); //$NON-NLS-1$
+ } finally {
+ if (is != null)
+ try {
+ is.close();
+ } catch(IOException ex) {
+ }
+ }
+ }
+
+ if (lines == null)
+ lines= new ArrayList();
+
+ patch(diff, lines, failedHunks);
+
+ return lines;
+ }
+
+ String getRejected(List failedHunks) {
+ if (failedHunks.size() <= 0)
+ return null;
+
+ StringBuffer sb= new StringBuffer();
+ Iterator iter= failedHunks.iterator();
+ while (iter.hasNext()) {
+ Hunk hunk= (Hunk) iter.next();
+ sb.append(hunk.getRejectedDescription());
+ sb.append('\n');
+ sb.append(hunk.getContent());
+ }
+ return sb.toString();
+ }
+
+ private void deleteFile(IFile file, IProgressMonitor pm) {
+ try {
+ file.delete(true, true, pm);
+ } catch (CoreException ex) {
+ ExceptionHandler.handle(ex,
+ PatchMessages.getString("Patcher.ErrorDialog.title"), //$NON-NLS-1$
+ PatchMessages.getString("Patcher.DeleteError.message")); //$NON-NLS-1$
+ }
+ }
+
+ private String createString(List lines) {
+ // convert the result into a String
+ StringBuffer sb= new StringBuffer();
+ Iterator iter= lines.iterator();
+ while (iter.hasNext())
+ sb.append((String)iter.next());
+ return sb.toString();
+ }
+
+ private void updateFile(String contents, IFile file, IProgressMonitor pm) {
+
+ // and save it
+ InputStream is= new ByteArrayInputStream(contents.getBytes());
+ try {
+ if (file.exists()) {
+ file.setContents(is, false, true, pm);
+ } else {
+ file.create(is, false, pm);
+ }
+ } catch (CoreException ex) {
+ ExceptionHandler.handle(ex,
+ PatchMessages.getString("Patcher.ErrorDialog.title"), //$NON-NLS-1$
+ PatchMessages.getString("Patcher.UpdateError.message")); //$NON-NLS-1$
+ } finally {
+ if (is != null)
+ try {
+ is.close();
+ } catch(IOException ex) {
+ }
+ }
+ }
+
+ private IFile createPath(IContainer folder, IPath path) {
+ if (path.segmentCount() > 1) {
+ IFolder f= folder.getFolder(path.uptoSegment(1));
+ //System.out.println("createPath: " + f + " " + f.exists());
+ return createPath(f, path.removeFirstSegments(1));
+ }
+ // a leaf
+ return folder.getFile(path);
+ }
+
+ private static String stripWhiteSpace(String s) {
+ StringBuffer sb= new StringBuffer();
+ int l= s.length();
+ for (int i= 0; i < l; i++) {
+ char c= s.charAt(i);
+ if (!Character.isWhitespace(c))
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Compares two strings.
+ * If fIgnoreWhitespace is true whitespace and line endings are ignored.
+ */
+ private boolean linesMatch(String line1, String line2) {
+ if (fIgnoreWhitespace)
+ return stripWhiteSpace(line1).equals(stripWhiteSpace(line2));
+ return line1.equals(line2);
+ }
+
+ /**
+ * Returns the length (exluding end-of-line characters) of the given string.
+ */
+ /* package */ static int length(String s) {
+ int l= s.length();
+ if (l > 0 && s.charAt(l-1) == '\n')
+ l--;
+ if (l > 1 && s.charAt(l-2) == '\r')
+ l--;
+ return l;
+ }
+}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage.java
new file mode 100644
index 000000000..99e82b5f6
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage.java
@@ -0,0 +1,497 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.io.*;
+import java.util.*;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.wizard.WizardPage;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+
+import org.eclipse.compare.*;
+import org.eclipse.compare.internal.*;
+import org.eclipse.compare.structuremergeviewer.*;
+
+
+/**
+ * Shows the parsed patch file and any mismatches
+ * between files, hunks and the currently selected
+ * resources.
+ */
+/* package */ class PreviewPatchPage extends WizardPage {
+
+ /**
+ * Used with CompareInput
+ */
+ static class HunkInput implements ITypedElement, IStreamContentAccessor {
+ String fContent;
+ String fType;
+
+ HunkInput(String type, String s) {
+ fType= type;
+ fContent= s;
+ }
+ public Image getImage() {
+ return null;
+ }
+ public String getName() {
+ return PatchMessages.getString("PreviewPatchPage.NoName.text"); //$NON-NLS-1$
+ }
+ public String getType() {
+ return fType;
+ }
+ public InputStream getContents() {
+ return new ByteArrayInputStream(fContent.getBytes());
+ }
+ };
+
+ private PatchWizard fPatchWizard;
+
+ private Tree fTree;
+ private Combo fStripPrefixSegments;
+ private CompareViewerSwitchingPane fHunkViewer;
+ private Button fIgnoreWhitespaceButton;
+ private Button fReversePatchButton;
+ private Text fFuzzField;
+
+ private Image fNullImage;
+ private Image fAddImage;
+ private Image fDelImage;
+
+ private CompareConfiguration fCompareConfiguration;
+
+
+ /* package */ PreviewPatchPage(PatchWizard pw) {
+ super("PreviewPatchPage", PatchMessages.getString("PreviewPatchPage.title"), null); //$NON-NLS-1$ //$NON-NLS-2$
+
+ setMessage(PatchMessages.getString("PreviewPatchPage.message")); //$NON-NLS-1$
+
+ fPatchWizard= pw;
+ //setPageComplete(false);
+
+ int w= 16;
+ fNullImage= new DiffImage(null, null, w).createImage();
+ fAddImage= new DiffImage(null, CompareUIPlugin.getImageDescriptor("ovr16/add_ov.gif"), w).createImage(); //$NON-NLS-1$
+ fDelImage= new DiffImage(null, CompareUIPlugin.getImageDescriptor("ovr16/del_ov.gif"), w).createImage(); //$NON-NLS-1$
+
+ fCompareConfiguration= new CompareConfiguration();
+
+ fCompareConfiguration.setLeftEditable(false);
+ fCompareConfiguration.setLeftLabel(PatchMessages.getString("PreviewPatchPage.Left.title")); //$NON-NLS-1$
+
+ fCompareConfiguration.setRightEditable(false);
+ fCompareConfiguration.setRightLabel(PatchMessages.getString("PreviewPatchPage.Right.title")); //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * Method declared in WizardPage
+ */
+ public void setVisible(boolean visible) {
+ if (visible)
+ buildTree();
+ super.setVisible(visible);
+ }
+
+ Image getImage(Diff diff) {
+ switch (diff.getType()) {
+ case Differencer.ADDITION:
+ return fAddImage;
+ case Differencer.DELETION:
+ return fDelImage;
+ }
+ return fNullImage;
+ }
+
+ public void createControl(Composite parent) {
+
+ Composite composite= new Composite(parent, SWT.NULL);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));
+ setControl(composite);
+
+ buildPatchOptionsGroup(composite);
+
+ // top pane showing diffs and hunks in a check box tree
+ fTree= new Tree(composite, SWT.CHECK | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
+ GridData gd= new GridData();
+ gd.verticalAlignment= GridData.FILL;
+ gd.horizontalAlignment= GridData.FILL;
+ gd.grabExcessHorizontalSpace= true;
+ gd.grabExcessVerticalSpace= true;
+ fTree.setLayoutData(gd);
+
+ // bottom pane showing hunks in compare viewer
+ fHunkViewer= new CompareViewerSwitchingPane(composite, SWT.BORDER) {
+ protected Viewer getViewer(Viewer oldViewer, Object input) {
+ return CompareUI.findContentViewer(oldViewer, (ICompareInput)input, this, fCompareConfiguration);
+ }
+ };
+ gd= new GridData();
+ gd.verticalAlignment= GridData.FILL;
+ gd.horizontalAlignment= GridData.FILL;
+ gd.grabExcessHorizontalSpace= true;
+ gd.grabExcessVerticalSpace= true;
+ fHunkViewer.setLayoutData(gd);
+
+ // register listeners
+
+ fTree.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ TreeItem ti= (TreeItem) e.item;
+ Object data= e.item.getData();
+ if (e.detail == SWT.CHECK) {
+ boolean enabled= ti.getChecked();
+ if (data instanceof Hunk) {
+ ((Hunk)data).fIsEnabled= enabled;
+ updateGrayedState(ti);
+ } else if (data instanceof Diff) {
+ ((Diff)data).fIsEnabled= enabled;
+ updateCheckedState(ti);
+ }
+ } else {
+ if (data instanceof Hunk)
+ PreviewPatchPage.this.fHunkViewer.setInput(createInput((Hunk)data));
+ else
+ PreviewPatchPage.this.fHunkViewer.setInput(null);
+ }
+ }
+ }
+ );
+
+ // creating tree's content
+ buildTree();
+
+ // WorkbenchHelp.setHelp(composite, new DialogPageContextComputer(this, PATCH_HELP_CONTEXT_ID));
+ }
+
+ /**
+ * Create the group for setting various patch options
+ */
+ private void buildPatchOptionsGroup(Composite parent) {
+
+ final Patcher patcher= fPatchWizard.getPatcher();
+
+ Group group= new Group(parent, SWT.NONE);
+ group.setText(PatchMessages.getString("PreviewPatchPage.PatchOptions.title")); //$NON-NLS-1$
+ GridLayout layout= new GridLayout();
+ layout.numColumns= 5;
+ group.setLayout(layout);
+ group.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
+ //fPatchFileGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // 1st row
+ new Label(group, SWT.NONE).setText(PatchMessages.getString("PreviewPatchPage.IgnoreSegments.text")); //$NON-NLS-1$
+
+ fStripPrefixSegments= new Combo(group, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.SIMPLE);
+ int prefixCnt= patcher.getStripPrefixSegments();
+ String prefix= Integer.toString(prefixCnt);
+ fStripPrefixSegments.add(prefix);
+ fStripPrefixSegments.setText(prefix);
+
+ addSpacer(group);
+
+ fReversePatchButton= new Button(group, SWT.CHECK);
+ fReversePatchButton.setText(PatchMessages.getString("PreviewPatchPage.ReversePatch.text")); //$NON-NLS-1$
+
+ addSpacer(group);
+
+ // 2nd row
+ Label l= new Label(group, SWT.NONE);
+ l.setText(PatchMessages.getString("PreviewPatchPage.FuzzFactor.text")); //$NON-NLS-1$
+ l.setToolTipText(PatchMessages.getString("PreviewPatchPage.FuzzFactor.tooltip")); //$NON-NLS-1$
+ fFuzzField= new Text(group, SWT.BORDER);
+ fFuzzField.setText("2"); //$NON-NLS-1$
+ GridData gd2= new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
+ gd2.widthHint= 30;
+ fFuzzField.setLayoutData(gd2);
+
+ addSpacer(group);
+
+ fIgnoreWhitespaceButton= new Button(group, SWT.CHECK);
+ fIgnoreWhitespaceButton.setText(PatchMessages.getString("PreviewPatchPage.IgnoreWhitespace.text")); //$NON-NLS-1$
+
+ addSpacer(group);
+
+ // register listeners
+
+ if (fStripPrefixSegments != null)
+ fStripPrefixSegments.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (patcher.setStripPrefixSegments(getStripPrefixSegments()))
+ updateTree();
+ }
+ }
+ );
+ fReversePatchButton.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (patcher.setReversed(fReversePatchButton.getSelection()))
+ updateTree();
+ }
+ }
+ );
+ fIgnoreWhitespaceButton.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (patcher.setIgnoreWhitespace(fIgnoreWhitespaceButton.getSelection()))
+ updateTree();
+ }
+ }
+ );
+
+ fFuzzField.addModifyListener(
+ new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ if (patcher.setFuzz(getFuzzFactor()))
+ updateTree();
+ }
+ }
+ );
+ }
+
+ ICompareInput createInput(Hunk hunk) {
+
+ String[] lines= hunk.fLines;
+ StringBuffer left= new StringBuffer();
+ StringBuffer right= new StringBuffer();
+
+ for (int i= 0; i < lines.length; i++) {
+ String line= lines[i];
+ String rest= line.substring(1);
+ switch (line.charAt(0)) {
+ case ' ':
+ left.append(rest);
+ right.append(rest);
+ break;
+ case '-':
+ left.append(rest);
+ break;
+ case '+':
+ right.append(rest);
+ break;
+ }
+ }
+
+ Diff diff= hunk.fParent;
+ IPath path= diff.getPath();
+ String type= path.getFileExtension();
+
+ return new DiffNode(new HunkInput(type, left.toString()), new HunkInput(type, right.toString()));
+ }
+
+ /**
+ * Builds a tree from list of Diffs.
+ * As a side effect it calculates the maximum number of segments
+ * in all paths.
+ */
+ private void buildTree() {
+ setPageComplete(true);
+ if (fTree != null && !fTree.isDisposed()) {
+ fTree.removeAll();
+ fHunkViewer.setInput(null);
+
+ int length= 99;
+
+ Diff[] diffs= fPatchWizard.getPatcher().getDiffs();
+ if (diffs != null) {
+ for (int i= 0; i < diffs.length; i++) {
+ Diff diff= diffs[i];
+ TreeItem d= new TreeItem(fTree, SWT.NULL);
+ d.setData(diff);
+ d.setImage(getImage(diff));
+
+ if (diff.fOldPath != null)
+ length= Math.min(length, diff.fOldPath.segmentCount());
+ if (diff.fNewPath != null)
+ length= Math.min(length, diff.fNewPath.segmentCount());
+
+ java.util.List hunks= diff.fHunks;
+ java.util.Iterator iter= hunks.iterator();
+ while (iter.hasNext()) {
+ Hunk hunk= (Hunk) iter.next();
+ TreeItem h= new TreeItem(d, SWT.NULL);
+ h.setData(hunk);
+ h.setText(hunk.getDescription());
+ }
+ }
+ }
+ if (fStripPrefixSegments != null && length != 99)
+ for (int i= 1; i < length; i++)
+ fStripPrefixSegments.add(Integer.toString(i));
+ }
+
+ updateTree();
+ }
+
+ private IFile existsInSelection(IPath path) {
+ IResource target= fPatchWizard.getTarget();
+ if (target instanceof IFile) {
+ IFile file= (IFile) target;
+ IPath path2= file.getFullPath().removeFirstSegments(1);
+ //System.out.println("target: " + path2.toOSString());
+ //System.out.println(" path: " + path.toOSString());
+ if (path.equals(path2))
+ return file;
+// String name= file.getName();
+// if (path.lastSegment().equals(name))
+// return file;
+ } else if (target instanceof IContainer) {
+ IContainer c= (IContainer) target;
+ if (c.exists(path))
+ return c.getFile(path);
+ }
+ return null;
+ }
+
+ /**
+ * Updates label and checked state of tree items.
+ */
+ private void updateTree() {
+ if (fTree == null || fTree.isDisposed())
+ return;
+ int strip= getStripPrefixSegments();
+ TreeItem[] children= fTree.getItems();
+ for (int i= 0; i < children.length; i++) {
+ TreeItem item= children[i];
+ Diff diff= (Diff) item.getData();
+ String error= null;
+
+ boolean create= false;
+ IFile file= null;
+ if (diff.getType() == Differencer.ADDITION) {
+ IPath p= diff.fNewPath;
+ if (strip > 0 && strip < p.segmentCount())
+ p= p.removeFirstSegments(strip);
+ file= existsInSelection(p);
+ if (file == null) {
+ diff.fIsEnabled= true;
+ } else {
+ // file already exists
+ diff.fIsEnabled= false;
+ error= PatchMessages.getString("PreviewPatchPage.FileExists.error"); //$NON-NLS-1$
+ }
+ create= true;
+ } else {
+ IPath p= diff.fOldPath;
+ if (strip > 0 && strip < p.segmentCount())
+ p= p.removeFirstSegments(strip);
+ file= existsInSelection(p);
+ diff.fIsEnabled= file != null;
+ if (file != null) {
+ diff.fIsEnabled= true;
+ } else {
+ // file doesn't exist
+ diff.fIsEnabled= false;
+ error= PatchMessages.getString("PreviewPatchPage.FileDoesNotExist.error"); //$NON-NLS-1$
+ }
+ }
+
+ boolean checked= false;
+
+ ArrayList failedHunks= new ArrayList();
+ fPatchWizard.getPatcher().apply(diff, file, create, failedHunks);
+
+ if (failedHunks.size() > 0)
+ diff.fRejected= fPatchWizard.getPatcher().getRejected(failedHunks);
+
+ int checkedSubs= 0; // counts checked hunk items
+ TreeItem[] hunkItems= item.getItems();
+ for (int h= 0; h < hunkItems.length; h++) {
+ Hunk hunk= (Hunk) hunkItems[h].getData();
+ boolean failed= failedHunks.contains(hunk);
+ String hunkError= null;
+ if (failed)
+ hunkError= PatchMessages.getString("PreviewPatchPage.NoMatch.error"); //$NON-NLS-1$
+ hunk.fIsEnabled= diff.fIsEnabled && !failed;
+ hunkItems[h].setChecked(hunk.fIsEnabled);
+ if (hunk.fIsEnabled) {
+ checkedSubs++;
+ checked= true;
+ }
+ String hunkLabel= hunk.getDescription();
+ if (hunkError != null)
+ hunkLabel+= " " + hunkError; //$NON-NLS-1$
+ hunkItems[h].setText(hunkLabel);
+ }
+
+ String label= diff.getDescription(strip);
+ if (error != null)
+ label+= " " + error; //$NON-NLS-1$
+ item.setText(label);
+ item.setImage(getImage(diff));
+ item.setChecked(checked);
+ boolean gray= (checkedSubs > 0 && checkedSubs < hunkItems.length);
+ item.setGrayed(gray);
+ item.setExpanded(gray);
+ }
+ }
+
+ /**
+ * Updates the gray state of the given diff and the checked state of its children.
+ */
+ private void updateCheckedState(TreeItem diff) {
+ boolean checked= diff.getChecked();
+ diff.setGrayed(false);
+ TreeItem[] hunks= diff.getItems();
+ for (int i= 0; i < hunks.length; i++)
+ hunks[i].setChecked(checked);
+ }
+
+ /**
+ * Updates the gray state of the given items parent.
+ */
+ private void updateGrayedState(TreeItem hunk) {
+ TreeItem diff= hunk.getParentItem();
+ TreeItem[] hunks= diff.getItems();
+ int checked= 0;
+ for (int i= 0; i < hunks.length; i++)
+ if (hunks[i].getChecked())
+ checked++;
+ diff.setChecked(checked > 0);
+ diff.setGrayed(checked > 0 && checked < hunks.length);
+ }
+
+ private void addSpacer(Composite parent) {
+ Label label= new Label(parent, SWT.NONE);
+ GridData gd= new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint= 20;
+ label.setLayoutData(gd);
+ }
+
+ private int getStripPrefixSegments() {
+ int stripPrefixSegments= 0;
+ if (fStripPrefixSegments != null) {
+ String s= fStripPrefixSegments.getText();
+ try {
+ stripPrefixSegments= Integer.parseInt(s);
+ } catch(NumberFormatException ex) {
+ }
+ }
+ return stripPrefixSegments;
+ }
+
+ private int getFuzzFactor() {
+ int fuzzFactor= 0;
+ if (fFuzzField != null) {
+ String s= fFuzzField.getText();
+ try {
+ fuzzFactor= Integer.parseInt(s);
+ } catch(NumberFormatException ex) {
+ }
+ }
+ return fuzzFactor;
+ }
+}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/CompareWithPatchAction.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/CompareWithPatchAction.java
deleted file mode 100644
index 73c2021c1..000000000
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/CompareWithPatchAction.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Shell;
-
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.wizard.*;
-
-import org.eclipse.ui.IActionDelegate;
-
-import org.eclipse.compare.internal.CompareUIPlugin;
-
-
-public class CompareWithPatchAction implements IActionDelegate {
-
- static class PatchWizardDialog extends WizardDialog {
-
- PatchWizardDialog(Shell parent, IWizard wizard) {
- super(parent, wizard);
-
- setShellStyle(getShellStyle() | SWT.RESIZE);
- setMinimumPageSize(700, 500);
- }
- }
-
- private ISelection fSelection;
-
- public void run(IAction action) {
-
- PatchWizard wizard= new PatchWizard(fSelection);
- PatchWizardDialog wd= new PatchWizardDialog(CompareUIPlugin.getShell(), wizard);
- wd.open();
- }
-
- public void selectionChanged(IAction action, ISelection selection) {
- fSelection= selection;
- action.setEnabled(fSelection != null && !fSelection.isEmpty());
- }
-}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/Diff.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/Diff.java
deleted file mode 100644
index 77dc42e28..000000000
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/Diff.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import java.util.*;
-
-import org.eclipse.core.runtime.IPath;
-
-import org.eclipse.compare.structuremergeviewer.Differencer;
-
-
-/* package */ class Diff {
-
- IPath fOldPath, fNewPath;
- long fOldDate, fNewDate; // if 0: no file
- List fHunks= new ArrayList();
- boolean fIsEnabled= true;
- String fRejected;
-
-
- /* package */ Diff(IPath oldPath, long oldDate, IPath newPath, long newDate) {
- fOldPath= oldPath;
- fOldDate= oldPath == null ? 0 : oldDate;
- fNewPath= newPath;
- fNewDate= newPath == null ? 0 : newDate;
- }
-
- void reverse() {
- IPath tp= fOldPath;
- fOldPath= fNewPath;
- fNewPath= tp;
-
- long t= fOldDate;
- fOldDate= fNewDate;
- fNewDate= t;
-
- Iterator iter= fHunks.iterator();
- while (iter.hasNext()) {
- Hunk hunk= (Hunk) iter.next();
- hunk.reverse();
- }
- }
-
- Hunk[] getHunks() {
- return (Hunk[]) fHunks.toArray((Hunk[]) new Hunk[fHunks.size()]);
- }
-
- IPath getPath() {
- if (fOldPath != null)
- return fOldPath;
- return fNewPath;
- }
-
- void finish() {
- if (fHunks.size() == 1) {
- Hunk h= (Hunk) fHunks.get(0);
- if (h.fNewLength == 0) {
- fNewDate= 0;
- fNewPath= fOldPath;
- }
- }
- }
-
- /* package */ void add(Hunk hunk) {
- fHunks.add(hunk);
- }
-
- /* package */ int getType() {
- if (fOldDate == 0)
- return Differencer.ADDITION;
- if (fNewDate == 0)
- return Differencer.DELETION;
- return Differencer.CHANGE;
- }
-
- /* package */ String getDescription(int strip) {
- IPath path= fOldPath;
- if (fOldDate == 0)
- path= fNewPath;
- if (strip > 0 && strip < path.segmentCount())
- path= path.removeFirstSegments(strip);
- return path.toOSString();
- }
-}
-
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/Hunk.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/Hunk.java
deleted file mode 100644
index 6620af3a5..000000000
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/Hunk.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import java.util.List;
-
-import org.eclipse.jface.util.Assert;
-
-
-/**
- * A Hunk describes a range of changed lines and some context lines.
- */
-/* package */ class Hunk {
-
- Diff fParent;
- int fOldStart, fOldLength;
- int fNewStart, fNewLength;
- String[] fLines;
- boolean fIsEnabled= true;
-
-
- /* package */ Hunk(Diff parent, int[] oldRange, int[] newRange, List lines) {
-
- fParent= parent;
- if (fParent != null)
- fParent.add(this);
-
- if (oldRange[0] > 0)
- fOldStart= oldRange[0]-1; // line number start at 0!
- else
- fOldStart= 0;
- fOldLength= oldRange[1];
- if (newRange[0] > 0)
- fNewStart= newRange[0]-1; // line number start at 0!
- else
- fNewStart= 0;
- fNewLength= newRange[1];
-
- fLines= (String[]) lines.toArray(new String[lines.size()]);
- }
-
- void reverse() {
- int t= fOldStart;
- fOldStart= fNewStart;
- fNewStart= t;
-
- t= fOldLength;
- fOldLength= fNewLength;
- fNewLength= t;
-
- for (int i= 0; i < fLines.length; i++) {
- String line= fLines[i];
- char c= line.charAt(0);
- switch (c) {
- case '+':
- fLines[i]= '-' + line.substring(1);
- break;
- case '-':
- fLines[i]= '+' + line.substring(1);
- break;
- default:
- break;
- }
- }
- }
-
- /**
- * Returns the contents of this hunk.
- * Each line starts with a control character. Their meaning is as follows:
- * IResource
s that returns
- * only children of the given resource type.
- */
- private ITreeContentProvider getResourceProvider(final int resourceType) {
- return new WorkbenchContentProvider() {
- public Object[] getChildren(Object o) {
- if (o instanceof IContainer) {
- try {
- ArrayList results= new ArrayList();
- IResource[] members= ((IContainer)o).members();
- for (int i= 0; i < members.length; i++)
- // filter out the desired resource types
- if ((members[i].getType() & resourceType) != 0)
- results.add(members[i]);
- return results.toArray();
- } catch (CoreException e) {
- }
- }
- // just return an empty set of children
- return new Object[0];
- }
- };
- }
-
- /**
- * Updates the enable state of this page's controls.
- */
- private void updateWidgetEnablements() {
-
- String error= null;
-
- ISelection selection= fPatchTargets.getSelection();
- boolean anySelected= selection != null && !selection.isEmpty();
- if (!anySelected)
- error= "Nothing selected to apply patch to.";
-
- boolean gotPatch= false;
- if (getUseClipboard()) {
- Control c= getControl();
- if (c != null) {
- Clipboard clipboard= new Clipboard(c.getDisplay());
- Object o= clipboard.getContents(TextTransfer.getInstance());
- if (o instanceof String) {
- String s= ((String) o).trim();
- if (s.length() > 0)
- gotPatch= true;
- else
- error= "Clipboard is empty.";
- } else
- error= "Clipboard does not contain text.";
- } else
- error= "Couldn't retrieve clipboard contents.";
- } else {
- String path= fPatchFileNameField.getText();
- if (path != null && path.length() > 0) {
- File file= new File(path);
- gotPatch= file.exists() && file.isFile() && file.length() > 0;
- if (!gotPatch)
- error= "Can't locate patch file: " + path;
- } else {
- error= "No file name.";
- }
- }
-
- setPageComplete(anySelected && gotPatch);
- setErrorMessage(error);
- }
-
- protected void handlePatchFileBrowseButtonPressed() {
- FileDialog dialog= new FileDialog(getShell(), SWT.NONE);
- dialog.setText("Select Patch File");
- dialog.setFilterPath(getPatchFilePath());
- String res= dialog.open();
- if (res == null)
- return;
-
- String patchFilePath= dialog.getFileName();
- IPath filterPath= new Path(dialog.getFilterPath());
- IPath path= filterPath.append(patchFilePath).makeAbsolute();
- patchFilePath= path.toOSString();
- //fDialogSettings.put(IUIConstants.DIALOGSTORE_LASTEXTJAR, filterPath.toOSString());
-
- fPatchFileNameField.setText(patchFilePath);
- //setSourceName(patchFilePath);
- }
-
- /**
- * Sets the source name of the import to be the supplied path.
- * Adds the name of the path to the list of items in the
- * source combo and selects it.
- *
- * @param path the path to be added
- */
- protected void setSourceName(String path) {
-
- if (path.length() > 0) {
-
- String[] currentItems= fPatchFileNameField.getItems();
- int selectionIndex= -1;
- for (int i= 0; i < currentItems.length; i++)
- if (currentItems[i].equals(path))
- selectionIndex= i;
-
- if (selectionIndex < 0) { // not found in history
- int oldLength= currentItems.length;
- String[] newItems= new String[oldLength + 1];
- System.arraycopy(currentItems, 0, newItems, 0, oldLength);
- newItems[oldLength]= path;
- fPatchFileNameField.setItems(newItems);
- selectionIndex= oldLength;
- }
- fPatchFileNameField.select(selectionIndex);
-
- //resetSelection();
- }
- }
-
- /**
- * The Finish button was pressed. Try to do the required work now and answer
- * a boolean indicating success. If false is returned then the wizard will
- * not close.
- *
- * @return boolean
- */
- public boolean finish() {
-// if (!ensureSourceIsValid())
-// return false;
-
- saveWidgetValues();
-
-// Iterator resourcesEnum = getSelectedResources().iterator();
-// List fileSystemObjects = new ArrayList();
-// while (resourcesEnum.hasNext()) {
-// fileSystemObjects.add(
-// ((FileSystemElement) resourcesEnum.next()).getFileSystemObject());
-// }
-//
-// if (fileSystemObjects.size() > 0)
-// return importResources(fileSystemObjects);
-//
-// MessageDialog
-// .openInformation(
-// getContainer().getShell(),
-// DataTransferMessages.getString("DataTransfer.information"), //$NON-NLS-1$
-// DataTransferMessages.getString("FileImport.noneSelected")); //$NON-NLS-1$
-//
-// return false;
-
- return true;
- }
-
- /**
- * Use the dialog store to restore widget values to the values that they held
- * last time this wizard was used to completion
- */
- private void restoreWidgetValues() {
- IDialogSettings settings= getDialogSettings();
- if (settings != null) {
-
- // set 'Use Clipboard' radio button
- setUseClipboard(settings.getBoolean(STORE_USE_CLIPBOARD_ID));
-
- // set filenames history
- String[] sourceNames= settings.getArray(STORE_PATCH_FILES_ID);
- if (sourceNames != null)
- for (int i= 0; i < sourceNames.length; i++)
- if (sourceNames[i] != null && sourceNames[i].length() > 0)
- fPatchFileNameField.add(sourceNames[i]);
-
- // set patch file path
- String patchFilePath= settings.get(STORE_PATCH_FILES_ID);
- if (patchFilePath != null)
- setSourceName(patchFilePath);
- } else
- System.out.println("restoreWidgetValues: no dialog settings");
- }
-
- /**
- * Since Finish was pressed, write widget values to the dialog store so that they
- * will persist into the next invocation of this wizard page
- */
- void saveWidgetValues() {
- IDialogSettings settings= getDialogSettings();
- if (settings != null) {
-
- settings.put(STORE_USE_CLIPBOARD_ID, getUseClipboard());
- settings.put(STORE_PATCH_FILES_ID, getPatchFilePath());
-
- // update source names history
- String[] sourceNames= settings.getArray(STORE_PATCH_FILES_ID);
- if (sourceNames == null)
- sourceNames= new String[0];
-
- sourceNames= addToHistory(sourceNames, getPatchFilePath());
- settings.put(STORE_PATCH_FILES_ID, sourceNames);
- }
- }
-
- // static helpers
-
- private void setUseClipboard(boolean useClipboard) {
- if (useClipboard)
- fUseClipboardButton.setSelection(true);
- else
- fUsePatchFileButton.setSelection(true);
- setEnablePatchFile(!useClipboard);
- }
-
- private boolean getUseClipboard() {
- if (fUseClipboardButton != null)
- return fUseClipboardButton.getSelection();
- return false;
- }
-
- private String getPatchFilePath() {
- if (fPatchFileNameField != null)
- return fPatchFileNameField.getText();
- return "";
- }
-
- /**
- * Creates a new label with a bold font.
- *
- * @param parent the parent control
- * @param text the label text
- * @return the new label control
- */
- private static Label buildPlainLabel(Composite parent, String text) {
- Label label= new Label(parent, SWT.NONE);
- label.setText(text);
- GridData data= new GridData();
- data.verticalAlignment= GridData.FILL;
- data.horizontalAlignment= GridData.FILL;
- label.setLayoutData(data);
- return label;
- }
-
- /**
- * Adds an entry to a history, while taking care of duplicate history items
- * and excessively long histories. The assumption is made that all histories
- * should be of length COMBO_HISTORY_LENGTH
.
- *
- * @param history the current history
- * @param newEntry the entry to add to the history
- */
- protected static String[] addToHistory(String[] history, String newEntry) {
- java.util.ArrayList l= new java.util.ArrayList(java.util.Arrays.asList(history));
-
- l.remove(newEntry);
- l.add(0,newEntry);
-
- // since only one new item was added, we can be over the limit
- // by at most one item
- if (l.size() > COMBO_HISTORY_LENGTH)
- l.remove(COMBO_HISTORY_LENGTH);
-
- return (String[]) l.toArray(new String[l.size()]);
- }
-}
-
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/LineReader.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/LineReader.java
deleted file mode 100644
index 4306e63ea..000000000
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/LineReader.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import java.io.*;
-import java.util.*;
-
-import org.eclipse.jface.util.Assert;
-
-/* package */ class LineReader {
-
- private boolean fHaveChar= false;
- private int fLastChar;
- private boolean fSawEOF= false;
- private BufferedReader fReader;
-
- /* package */ LineReader(BufferedReader reader) {
- fReader= reader;
- Assert.isNotNull(reader);
- }
-
- /**
- * Reads a line of text. A line is considered to be terminated by any one
- * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
- * followed immediately by a linefeed.
- * @return A string containing the contents of the line including
- * the line-termination characters, or null
if the end of the
- * stream has been reached
- * @exception IOException If an I/O error occurs
- */
- /* package */ String readLine() throws IOException {
- StringBuffer sb= null;
-
- while (!fSawEOF) {
- int c= readChar();
- if (c == -1) {
- fSawEOF= true;
- break;
- }
- if (sb == null)
- sb= new StringBuffer();
- sb.append((char)c);
- if (c == '\n')
- break;
- if (c == '\r') {
- c= readChar();
- if (c == -1) {
- fSawEOF= true;
- break; // EOF
- }
- if (c != '\n') {
- fHaveChar= true;
- fLastChar= c;
- } else
- sb.append((char)c);
- break;
- }
- }
-
- if (sb != null)
- return sb.toString();
- return null;
- }
-
- /* package */ void close() {
- try {
- fReader.close();
- } catch (IOException ex) {
- }
- }
-
- /* package */ List readLines() {
- try {
- List lines= new ArrayList();
- String line;
- while ((line= readLine()) != null)
- lines.add(line);
- return lines;
- } catch (IOException ex) {
- //System.out.println("error while reading file: " + fileName + "(" + ex + ")");
- } finally {
- close();
- }
- return null;
- }
- /**
- * Returns the number of characters in the given string without
- * counting a trailing line separator.
- */
- /* package */ int lineContentLength(String line) {
- if (line == null)
- return 0;
- int length= line.length();
- for (int i= length-1; i >= 0; i--) {
- char c= line.charAt(i);
- if (c =='\n' || c == '\r')
- length--;
- else
- break;
- }
- return length;
- }
-
- //---- private
-
- private int readChar() throws IOException {
- if (fHaveChar) {
- fHaveChar= false;
- return fLastChar;
- }
- return fReader.read();
- }
-}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchCompareInput.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchCompareInput.java
deleted file mode 100644
index 47f73dc24..000000000
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchCompareInput.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import java.io.*;
-import java.io.ByteArrayInputStream;
-import java.text.MessageFormat;
-import java.lang.reflect.InvocationTargetException;
-
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Composite;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.core.resources.*;
-
-import org.eclipse.jface.viewers.*;
-
-import org.eclipse.compare.*;
-import org.eclipse.compare.structuremergeviewer.*;
-import org.eclipse.compare.internal.*;
-
-
-/**
- * A PatchCompareInput uses a Patcher to
- * patch selected workspace resources.
- */
-/* package */ class PatchCompareInput extends CompareEditorInput {
-
- static class Rejected extends DiffNode implements IStreamContentAccessor {
- Diff fDiff;
- String fName;
- Rejected(IDiffContainer parent, String name, Diff diff) {
- super(parent, Differencer.NO_CHANGE);
- fName= name;
- fDiff= diff;
- }
- public String getName() {
- return fName + " *";
- }
- public String getType() {
- return "txt";
- }
- public Image getImage() {
- return CompareUI.getImage("file");
- }
- public InputStream getContents() {
- return new ByteArrayInputStream(fDiff.fRejected.getBytes());
- }
- }
-
- private DiffNode fRoot;
- private IResource fTarget;
- private Patcher fPatcher;
-
- /**
- * Creates an compare editor input for the given selection.
- */
- /* package */ PatchCompareInput(CompareConfiguration config, Patcher patcher, ISelection selection) {
- super(config);
- fPatcher= patcher;
- IResource[] s= Utilities.getResources(selection);
- if (s.length == 1)
- fTarget= s[0];
- }
-
- /**
- * Performs a two-way or three-way diff on the current selection.
- */
- public Object prepareInput(IProgressMonitor pm) throws InvocationTargetException {
-
- CompareConfiguration cc= (CompareConfiguration) getCompareConfiguration();
-
- try {
- Diff[] diffs= fPatcher.getDiffs();
-
- pm.beginTask(Utilities.getString("ResourceCompare.taskName"), diffs.length); //$NON-NLS-1$
-
- fRoot= new DiffNode(0);
- IContainer rootFolder= null;
- if (fTarget instanceof IContainer)
- rootFolder= (IContainer) fTarget;
-
- for (int i= 0; i < diffs.length; i++) {
- Diff diff= diffs[i];
- if (diff.fIsEnabled) {
- IPath path= fPatcher.getPath(diff);
- createPath(fRoot, rootFolder, path, diff, false);
-
- String rej= diff.fRejected;
- if (rej != null) {
- IPath pp= path.removeLastSegments(1);
- pp= pp.append(path.lastSegment() + ".rej");
- createPath(fRoot, rootFolder, pp, diff, true);
- }
- }
- pm.worked(1);
- }
-
- fTarget.refreshLocal(IResource.DEPTH_INFINITE, pm);
-
- String leftLabel= fTarget.getName();
- cc.setLeftLabel(leftLabel);
- cc.setLeftImage(CompareUIPlugin.getImage(fTarget));
-
- String rightLabel= "Patch: " + fPatcher.getName();
- cc.setRightLabel(rightLabel);
- //cc.setRightImage(CompareUIPlugin.getImage(fRightResource));
-
- String format= Utilities.getString("ResourceCompare.twoWay.title"); //$NON-NLS-1$
- String title= MessageFormat.format(format, new String[] {leftLabel, rightLabel} );
- setTitle(title);
-
- return fRoot;
-
- } catch (CoreException ex) {
- throw new InvocationTargetException(ex);
- } finally {
- pm.done();
- }
- }
-
- public void saveChanges(IProgressMonitor pm) throws CoreException {
- if (fRoot instanceof DiffNode) {
- try {
- commit(pm, (DiffNode) fRoot);
- } finally {
- setDirty(false);
- }
- }
- }
-
- /*
- * Recursively walks the diff tree and commits all changes.
- */
- private static void commit(IProgressMonitor pm, DiffNode node) throws CoreException {
-
- ITypedElement left= node.getLeft();
- if (left instanceof BufferedResourceNode)
- ((BufferedResourceNode) left).commit(pm);
-
- ITypedElement right= node.getRight();
- if (right instanceof BufferedResourceNode)
- ((BufferedResourceNode) right).commit(pm);
-
- IDiffElement[] children= node.getChildren();
- if (children != null) {
- for (int i= 0; i < children.length; i++) {
- IDiffElement element= children[i];
- if (element instanceof DiffNode)
- commit(pm, (DiffNode) element);
- }
- }
- }
-
- private void createPath(DiffContainer root, IContainer folder, IPath path, Diff diff, boolean reject) {
- if (path.segmentCount() > 1) {
- IFolder f= folder.getFolder(path.uptoSegment(1));
- IDiffElement child= root.findChild(path.segment(0));
- if (child == null) {
- ResourceNode rn= new ResourceNode(f);
- child= new DiffNode(root, Differencer.CHANGE, null, rn, rn);
- }
- if (child instanceof DiffContainer)
- createPath((DiffContainer)child, f, path.removeFirstSegments(1), diff, reject);
- } else {
- // a leaf
- BufferedResourceNode rn= new BufferedResourceNode(folder.getFile(path));
- if (reject) {
- new Rejected(root, path.segment(0), diff);
- } else {
- new DiffNode(root, diff.getType(), null, rn, new PatchedResource(rn, diff, path, fPatcher));
- }
- }
- }
-}
-
-
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchWizard.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchWizard.java
deleted file mode 100644
index 8fc93f312..000000000
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchWizard.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import org.eclipse.swt.graphics.Image;
-
-import org.eclipse.jface.dialogs.IDialogSettings;
-import org.eclipse.jface.viewers.*;
-import org.eclipse.jface.wizard.Wizard;
-
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.NullProgressMonitor;
-
-import org.eclipse.compare.*;
-import org.eclipse.compare.internal.*;
-import org.eclipse.compare.structuremergeviewer.Differencer;
-
-
-/* package */ class PatchWizard extends Wizard {
-
- // dialog store id constants
- private final static String DIALOG_SETTINGS_KEY= "PatchWizard"; //$NON-NLS-1$
-
- private boolean fHasNewDialogSettings;
-
- private InputPatchPage fPatchWizardPage;
- private PreviewPatchPage fPreviewPatchPage;
-
- private Patcher fPatcher;
- private IResource fTarget;
-
-
- /**
- * Creates a wizard for applying a patch file to the workspace.
- */
- /* package */ PatchWizard(ISelection selection) {
-
- fTarget= getResource(selection);
-
- fPatcher= new Patcher();
-
- setWindowTitle("Resource Patcher");
-
- IDialogSettings workbenchSettings= CompareUIPlugin.getDefault().getDialogSettings();
- IDialogSettings section= workbenchSettings.getSection(DIALOG_SETTINGS_KEY); //$NON-NLS-1$
- if (section == null)
- fHasNewDialogSettings= true;
- else {
- fHasNewDialogSettings= false;
- setDialogSettings(section);
- }
- }
-
- static IResource getResource(ISelection selection) {
- IResource[] rs= Utilities.getResources(selection);
- if (rs != null && rs.length > 0)
- return rs[0];
- return null;
- }
-
- Patcher getPatcher() {
- return fPatcher;
- }
-
- IResource getTarget() {
- return fTarget;
- }
-
- void setTarget(IResource target) {
- fTarget= target;
- }
-
- /* (non-Javadoc)
- * Method declared on IWizard.
- */
- public void addPages() {
- super.addPages();
-
- addPage(fPatchWizardPage= new InputPatchPage(this));
- addPage(fPreviewPatchPage= new PreviewPatchPage(this));
- }
-
- /* (non-Javadoc)
- * Method declared on IWizard.
- */
- public boolean performFinish() {
-
- if (false) {
- CompareConfiguration cc= new CompareConfiguration() {
- public Image getImage(int kind) {
- if (kind == Differencer.ADDITION)
- kind= Differencer.DELETION;
- else if (kind == Differencer.DELETION)
- kind= Differencer.ADDITION;
- return super.getImage(kind);
- }
- public Image getImage(Image base, int kind) {
- if (kind == Differencer.ADDITION)
- kind= Differencer.DELETION;
- else if (kind == Differencer.DELETION)
- kind= Differencer.ADDITION;
- return super.getImage(base, kind);
- }
- };
- cc.setProperty(CompareEditor.CONFIRM_SAVE_PROPERTY, new Boolean(false));
-
- fPatcher.setName(fPatchWizardPage.getPatchName());
-
- CompareUI.openCompareEditor(new PatchCompareInput(cc, fPatcher, new StructuredSelection(fTarget)));
- } else {
- fPatcher.setName(fPatchWizardPage.getPatchName());
- fPatcher.applyAll(getTarget(), new NullProgressMonitor());
- }
-
- // Save the dialog settings
- if (fHasNewDialogSettings) {
- IDialogSettings workbenchSettings= CompareUIPlugin.getDefault().getDialogSettings();
- IDialogSettings section= workbenchSettings.getSection(DIALOG_SETTINGS_KEY);
- section= workbenchSettings.addNewSection(DIALOG_SETTINGS_KEY);
- setDialogSettings(section);
- }
-
- fPatchWizardPage.saveWidgetValues();
- //fPreviewPatchPage.saveWidgetValues();
-
- return true;
- }
-}
-
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchedResource.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchedResource.java
deleted file mode 100644
index 9e8a36156..000000000
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchedResource.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import java.io.*;
-
-import org.eclipse.swt.graphics.Image;
-
-import org.eclipse.core.runtime.*;
-
-import org.eclipse.compare.*;
-
-
-/* package */ class PatchedResource implements ITypedElement, IStreamContentAccessor {
-
- private Diff fDiff;
- private IStreamContentAccessor fCurrent;
- private IPath fPath;
- private byte[] fContent;
- private Patcher fPatcher;
-
- /* package */ PatchedResource(IStreamContentAccessor current, Diff diff, IPath path, Patcher patcher) {
- fDiff= diff;
- fCurrent= current;
- fPath= path;
- fPatcher= patcher;
- }
-
- public InputStream getContents() throws CoreException {
- if (fContent == null) {
- InputStream is= null;
-
- try {
- is= fCurrent.getContents();
- } catch (CoreException ex) {
- is= new ByteArrayInputStream(new byte[0]);
- }
- if (is != null) {
- BufferedReader br= new BufferedReader(new InputStreamReader(is));
- String s= fPatcher.patch(fDiff,br, null);
- if (s != null)
- fContent= s.getBytes();
- try {
- is.close();
- } catch (IOException ex) {
- }
- }
- }
- return new ByteArrayInputStream(fContent);
- }
-
- public Image getImage() {
- return CompareUI.getImage(getType());
- }
-
- public String getName() {
- return fPath.toOSString();
- }
-
- public String getType() {
- String type= fPath.getFileExtension();
- if (type != null)
- return type;
- return ITypedElement.UNKNOWN_TYPE;
- }
-}
-
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/Patcher.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/Patcher.java
deleted file mode 100644
index 36f8ac677..000000000
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/Patcher.java
+++ /dev/null
@@ -1,906 +0,0 @@
-package org.eclipse.compare.patch;
-
-import java.io.*;
-import java.text.*;
-import java.util.*;
-
-import org.eclipse.jface.util.Assert;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.core.resources.*;
-
-import org.eclipse.compare.structuremergeviewer.Differencer;
-
-
-/**
- * A Patcher
- * - knows how to parse various patch file formats into some in-memory structure,
- * - holds onto the parsed data and the options to use when applying the patches,
- * - knows how to apply the patches to files and folders.
- */
-public class Patcher {
-
- private static final boolean DEBUG= false;
-
- private static final String DEV_NULL= "/dev/null"; //$NON-NLS-1$
-
- // diff formats
- private static final int CONTEXT= 0;
- private static final int ED= 1;
- private static final int NORMAL= 2;
- private static final int UNIFIED= 3;
-
- // we recognize the following date/time formats
- private static DateFormat[] DATE_FORMATS= new DateFormat[] {
- new SimpleDateFormat("EEE MMM dd kk:mm:ss yyyy"), //$NON-NLS-1$
- new SimpleDateFormat("yyyy/MM/dd kk:mm:ss"), //$NON-NLS-1$
- new SimpleDateFormat("EEE MMM dd kk:mm:ss yyyy", Locale.US) //$NON-NLS-1$
- };
-
- private String fName;
- private Diff[] fDiffs;
- // patch options
- private int fStripPrefixSegments;
- private int fFuzz;
- private boolean fIgnoreWhitespace;
- private boolean fReverse= false;
-
-
- Patcher() {
- }
-
- //---- options
-
- void setName(String name) {
- fName= name;
- }
-
- String getName() {
- return fName;
- }
-
- /**
- * Returns an array of Diffs after a sucessfull call to parse
.
- * If parse
hasn't been called returns null
.
- */
- Diff[] getDiffs() {
- return fDiffs;
- }
-
- IPath getPath(Diff diff) {
- IPath path= diff.getPath();
- if (fStripPrefixSegments > 0 && fStripPrefixSegments < path.segmentCount())
- path= path.removeFirstSegments(fStripPrefixSegments);
- return path;
- }
-
- /**
- * Returns true
if new value differs from old.
- */
- boolean setStripPrefixSegments(int strip) {
- if (strip != fStripPrefixSegments) {
- fStripPrefixSegments= strip;
- return true;
- }
- return false;
- }
-
- int getStripPrefixSegments() {
- return fStripPrefixSegments;
- }
-
- /**
- * Returns true
if new value differs from old.
- */
- boolean setFuzz(int fuzz) {
- if (fuzz != fFuzz) {
- fFuzz= fuzz;
- return true;
- }
- return false;
- }
-
- /**
- * Returns true
if new value differs from old.
- */
- boolean setReversed(boolean reverse) {
- if (fReverse != reverse) {
- fReverse= reverse;
-
- for (int i= 0; i < fDiffs.length; i++)
- fDiffs[i].reverse();
-
- return true;
- }
- return false;
- }
-
- /**
- * Returns true
if new value differs from old.
- */
- boolean setIgnoreWhitespace(boolean ignoreWhitespace) {
- if (ignoreWhitespace != fIgnoreWhitespace) {
- fIgnoreWhitespace= ignoreWhitespace;
- return true;
- }
- return false;
- }
-
- //---- parsing patch files
-
- /* package */ void parse(BufferedReader reader) throws IOException {
- List diffs= new ArrayList();
- String line= null;
- boolean reread= false;
- String diffArgs= null;
- String fileName= null;
-
- LineReader lr= new LineReader(reader);
-
- // read leading garbage
- while (true) {
- if (!reread)
- line= lr.readLine();
- reread= false;
- if (line == null)
- break;
- if (line.length() < 4)
- continue; // too short
-
- // remember some infos
- if (line.startsWith("Index: ")) { //$NON-NLS-1$
- fileName= line.substring(7).trim();
- continue;
- }
- if (line.startsWith("diff")) { //$NON-NLS-1$
- diffArgs= line.substring(4).trim();
- continue;
- }
-
- if (line.startsWith("--- ")) { //$NON-NLS-1$
- line= readUnifiedDiff(diffs, lr, line, diffArgs, fileName);
- diffArgs= fileName= null;
- reread= true;
- } else if (line.startsWith("*** ")) { //$NON-NLS-1$
- line= readContextDiff(diffs, lr, line, diffArgs, fileName);
- diffArgs= fileName= null;
- reread= true;
- }
- }
-
- lr.close();
-
- fDiffs= (Diff[]) diffs.toArray((Diff[]) new Diff[diffs.size()]);
- }
-
- /**
- * Returns the next line that does not belong to this diff
- */
- private String readUnifiedDiff(List diffs, LineReader reader, String line, String args, String fileName) throws IOException {
-
- String[] oldArgs= split(line.substring(4));
-
- // read info about new file
- line= reader.readLine();
- if (line == null || !line.startsWith("+++ ")) //$NON-NLS-1$
- return line;
-
- String[] newArgs= split(line.substring(4));
-
- Diff diff= new Diff(extractPath(oldArgs, 0, fileName), extractDate(oldArgs, 1),
- extractPath(newArgs, 0, fileName), extractDate(newArgs, 1));
- diffs.add(diff);
-
- int[] oldRange= new int[2];
- int[] newRange= new int[2];
- List lines= new ArrayList();
-
- try {
- // read lines of hunk
- while (true) {
-
- line= reader.readLine();
- if (line == null)
- return null;
-
- if (reader.lineContentLength(line) == 0) {
- lines.add(' ' + line);
- continue;
- }
-
- char c= line.charAt(0);
- switch (c) {
- case '@':
- if (line.startsWith("@@ ")) { //$NON-NLS-1$
- // flush old hunk
- if (lines.size() > 0) {
- new Hunk(diff, oldRange, newRange, lines);
- lines.clear();
- }
-
- // format: @@ -oldStart,oldLength +newStart,newLength @@
- extractPair(line, '-', oldRange);
- extractPair(line, '+', newRange);
- continue;
- }
- break;
- case ' ':
- case '+':
- case '-':
- lines.add(line);
- continue;
- case '\\':
- if (line.startsWith("No newline at end of file", 2)) { //$NON-NLS-1$
- int lastIndex= lines.size();
- if (lastIndex > 0) {
- line= (String) lines.get(lastIndex-1);
- int end= line.length()-1;
- char lc= line.charAt(end);
- if (lc == '\n') {
- end--;
- if (end > 0 && line.charAt(end-1) == '\r')
- end--;
- } else if (lc == '\r') {
- end--;
- }
- line= line.substring(0, end);
- lines.set(lastIndex-1, line);
- }
- continue;
- }
- break;
- default:
- int a1= c, a2= 0;
- if (line.length() > 1)
- a2= line.charAt(1);
- if (DEBUG) System.out.println("char: " + a1 + " " + a2);
- break;
- }
- return line;
- }
- } finally {
- if (lines.size() > 0)
- new Hunk(diff, oldRange, newRange, lines);
- diff.finish();
- }
- }
-
- /**
- * Returns the next line that does not belong to this diff
- */
- private String readContextDiff(List diffs, LineReader reader, String line, String args, String fileName) throws IOException {
-
- String[] oldArgs= split(line.substring(4));
-
- // read info about new file
- line= reader.readLine();
- if (line == null || !line.startsWith("--- ")) //$NON-NLS-1$
- return line;
-
- String[] newArgs= split(line.substring(4));
-
- Diff diff= new Diff(extractPath(oldArgs, 0, fileName), extractDate(oldArgs, 1),
- extractPath(newArgs, 0, fileName), extractDate(newArgs, 1));
- diffs.add(diff);
-
- int[] oldRange= new int[2];
- int[] newRange= new int[2];
- List oldLines= new ArrayList();
- List newLines= new ArrayList();
- List lines= oldLines;
-
- try {
- // read lines of hunk
- while (true) {
-
- line= reader.readLine();
- if (line == null)
- return line;
-
- int l= line.length();
- if (l == 0)
- continue;
- if (l > 1) {
- switch (line.charAt(0)) {
- case '*':
- if (line.startsWith("***************")) { // new hunk //$NON-NLS-1$
- // flush old hunk
- if (oldLines.size() > 0 || newLines.size() > 0) {
- new Hunk(diff, oldRange, newRange, unifyLines(oldLines, newLines));
- oldLines.clear();
- newLines.clear();
- }
- continue;
- }
- if (line.startsWith("*** ")) { // old range //$NON-NLS-1$
- // format: *** oldStart,oldEnd ***
- extractPair(line, ' ', oldRange);
- oldRange[1]= oldRange[1]-oldRange[0]+1;
- lines= oldLines;
- continue;
- }
- break;
- case ' ': // context line
- case '+': // addition
- case '!': // change
- if (line.charAt(1) == ' ') {
- lines.add(line);
- continue;
- }
- break;
- case '-':
- if (line.charAt(1) == ' ') { // deletion
- lines.add(line);
- continue;
- }
- if (line.startsWith("--- ")) { // new range //$NON-NLS-1$
- // format: *** newStart,newEnd ***
- extractPair(line, ' ', newRange);
- newRange[1]= newRange[1]-newRange[0]+1;
- lines= newLines;
- continue;
- }
- break;
- default:
- break;
- }
- }
- return line;
- }
- } finally {
- // flush last hunk
- if (oldLines.size() > 0 || newLines.size() > 0)
- new Hunk(diff, oldRange, newRange, unifyLines(oldLines, newLines));
- diff.finish();
- }
- }
-
- /**
- * Creates a List of lines in the unified format from
- * two Lists of lines in the 'classic' format.
- */
- private List unifyLines(List oldLines, List newLines) {
- List result= new ArrayList();
-
- String[] ol= (String[]) oldLines.toArray(new String[oldLines.size()]);
- String[] nl= (String[]) newLines.toArray(new String[newLines.size()]);
-
- int oi= 0, ni= 0;
-
- while (true) {
-
- char oc= 0;
- String o= null;
- if (oi < ol.length) {
- o= ol[oi];
- oc= o.charAt(0);
- }
-
- char nc= 0;
- String n= null;
- if (ni < nl.length) {
- n= nl[ni];
- nc= n.charAt(0);
- }
-
- // EOF
- if (oc == 0 && nc == 0)
- break;
-
- // deletion in old
- if (oc == '-') {
- do {
- result.add('-' + o.substring(2));
- oi++;
- if (oi >= ol.length)
- break;
- o= ol[oi];
- } while (o.charAt(0) == '-');
- continue;
- }
-
- // addition in new
- if (nc == '+') {
- do {
- result.add('+' + n.substring(2));
- ni++;
- if (ni >= nl.length)
- break;
- n= nl[ni];
- } while (n.charAt(0) == '+');
- continue;
- }
-
- // differing lines on both sides
- if (oc == '!' && nc == '!') {
- // remove old
- do {
- result.add('-' + o.substring(2));
- oi++;
- if (oi >= ol.length)
- break;
- o= ol[oi];
- } while (o.charAt(0) == '!');
-
- // add new
- do {
- result.add('+' + n.substring(2));
- ni++;
- if (ni >= nl.length)
- break;
- n= nl[ni];
- } while (n.charAt(0) == '!');
-
- continue;
- }
-
- // context lines
- if (oc == ' ' && nc == ' ') {
- do {
- Assert.isTrue(o.equals(n), "non matching context lines"); //$NON-NLS-1$
- result.add(' ' + o.substring(2));
- oi++;
- ni++;
- if (oi >= ol.length || ni >= nl.length)
- break;
- o= ol[oi];
- n= nl[ni];
- } while (o.charAt(0) == ' ' && n.charAt(0) == ' ');
- continue;
- }
-
- if (oc == ' ') {
- do {
- result.add(' ' + o.substring(2));
- oi++;
- if (oi >= ol.length)
- break;
- o= ol[oi];
- } while (o.charAt(0) == ' ');
- continue;
- }
-
- if (nc == ' ') {
- do {
- result.add(' ' + n.substring(2));
- ni++;
- if (ni >= nl.length)
- break;
- n= nl[ni];
- } while (n.charAt(0) == ' ');
- continue;
- }
-
- Assert.isTrue(false, "unexpected char <" + oc + "> <" + nc + ">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- return result;
- }
-
- /**
- * Breaks the given string into tab separated substrings.
- * Leading and trailing whitespace is removed from each token.
- */
- private String[] split(String line) {
- List l= new ArrayList();
- StringTokenizer st= new StringTokenizer(line, "\t"); //$NON-NLS-1$
- while (st.hasMoreElements()) {
- String token= st.nextToken().trim();
- if (token.length() > 0)
- l.add(token);
- }
- return (String[]) l.toArray(new String[l.size()]);
- }
-
- /**
- * @return the parsed time/date in milliseconds or -1 on error
- */
- private long extractDate(String[] args, int n) {
- if (n < args.length) {
- String line= args[n];
- for (int i= 0; i < DATE_FORMATS.length; i++) {
- DATE_FORMATS[i].setLenient(true);
- try {
- Date date= DATE_FORMATS[i].parse(line);
- return date.getTime();
- } catch (ParseException ex) {
- }
- }
- // System.err.println("can't parse date: <" + line + ">");
- }
- return -1;
- }
-
- /**
- * Returns null if file name is "/dev/null".
- */
- private IPath extractPath(String[] args, int n, String path2) {
- if (n < args.length) {
- String path= args[n];
- if (DEV_NULL.equals(path))
- return null;
- int pos= path.lastIndexOf(':');
- if (pos >= 0)
- path= path.substring(0, pos);
- if (path2 != null && !path2.equals(path)) {
- if (DEBUG) System.out.println("path mismatch: " + path2);
- path= path2;
- }
- return new Path(path);
- }
- return null;
- }
-
- /**
- * Tries to extract two integers separated by a comma.
- * The parsing of the line starts at the position after
- * the first occurrence of the given character start an ends
- * at the first blank (or the end of the line).
- * If only a single number is found this is assumed to be the length of the range.
- * In this case the start of the range is set to 1.
- * If an error occurs the range -1,-1 is returned.
- */
- private void extractPair(String line, char start, int[] pair) {
- pair[0]= pair[1]= -1;
- int startPos= line.indexOf(start);
- if (startPos < 0) {
- if (DEBUG) System.out.println("parsing error in extractPair: couldn't find \'" + start + "\'");
- return;
- }
- line= line.substring(startPos+1);
- int endPos= line.indexOf(' ');
- if (endPos < 0) {
- if (DEBUG) System.out.println("parsing error in extractPair: couldn't find end blank");
- return;
- }
- line= line.substring(0, endPos);
- int comma= line.indexOf(',');
- if (comma >= 0) {
- pair[0]= Integer.parseInt(line.substring(0, comma));
- pair[1]= Integer.parseInt(line.substring(comma+1));
- } else {
- pair[0]= 1;
- pair[1]= Integer.parseInt(line.substring(comma+1));
- }
- }
-
- //---- applying a patch file
-
- /**
- * Tries to patch the given lines with the specified Diff.
- * Any hunk that couldn't be applied is returned in the list failedHunks.
- */
- /* package */ void patch(Diff diff, List lines, List failedHunks) {
-
- int shift= 0;
- Iterator iter= diff.fHunks.iterator();
- while (iter.hasNext()) {
- Hunk hunk= (Hunk) iter.next();
- shift= patch(hunk, lines, shift, failedHunks);
- }
- }
-
- /**
- * Tries to patch the contents of the given reader with the specified Diff.
- * Any hunk that couldn't be applied is returned in the list failedHunks.
- */
- /* package */ String patch(Diff diff, BufferedReader reader, List failedHunks) {
-
- List lines= new LineReader(reader).readLines();
- if (lines == null)
- lines= new ArrayList();
-
- patch(diff, lines, failedHunks);
-
- StringBuffer sb= new StringBuffer();
- Iterator iter= lines.iterator();
- while (iter.hasNext())
- sb.append((String)iter.next());
- return sb.toString();
- }
-
- /**
- * Tries to apply the specified hunk to the given lines.
- * If the hunk cannot be applied at the original position
- * the methods tries Fuzz lines before and after.
- * If this fails the Hunk is added to the given list of failed hunks.
- */
- private int patch(Hunk hunk, List lines, int shift, List failedHunks) {
- if (tryPatch(hunk, lines, shift)) {
- shift+= doPatch(hunk, lines, shift);
- } else {
- boolean found= false;
- int oldShift= shift;
-
- for (int i= shift-1; i > shift-fFuzz; i--) {
- if (tryPatch(hunk, lines, i)) {
- shift= i;
- found= true;
- break;
- }
- }
-
- if (! found) {
- for (int i= shift+1; i < shift+fFuzz; i++) {
- if (tryPatch(hunk, lines, i)) {
- shift= i;
- found= true;
- break;
- }
- }
- }
-
- if (found) {
- if (DEBUG) System.out.println("patched hunk at offset: " + (shift-oldShift));
- shift+= doPatch(hunk, lines, shift);
- } else {
- if (failedHunks != null) {
- if (DEBUG) System.out.println("failed hunk");
- failedHunks.add(hunk);
- }
- }
- }
- return shift;
- }
-
- private boolean tryPatch(Hunk hunk, List lines, int shift) {
- int pos= hunk.fOldStart + shift;
- int contextMatches= 0;
- int deleteMatches= 0;
- for (int i= 0; i < hunk.fLines.length; i++) {
- String s= hunk.fLines[i];
- Assert.isTrue(s.length() > 0);
- String line= s.substring(1);
- char controlChar= s.charAt(0);
- if (controlChar == ' ') { // context lines
- while (true) {
- if (pos < 0 || pos >= lines.size())
- return false;
- if (linesMatch(line, (String) lines.get(pos))) {
- contextMatches++;
- pos++;
- break;
- }
- if (contextMatches <= 0)
- return false;
- pos++;
- }
- } else if (controlChar == '-') {
- // deleted lines
- while (true) {
- if (pos < 0 || pos >= lines.size())
- return false;
- if (linesMatch(line, (String) lines.get(pos))) {
- deleteMatches++;
- pos++;
- break;
- }
- if (deleteMatches <= 0)
- return false;
- pos++;
- }
- } else if (controlChar == '+') {
- // added lines
- // we don't have to do anything for a 'try'
- } else
- Assert.isTrue(false, "tryPatch: unknown control charcter: " + controlChar); //$NON-NLS-1$
- }
- return true;
- }
-
- private int doPatch(Hunk hunk, List lines, int shift) {
- int pos= hunk.fOldStart + shift;
- for (int i= 0; i < hunk.fLines.length; i++) {
- String s= hunk.fLines[i];
- Assert.isTrue(s.length() > 0);
- String line= s.substring(1);
- char controlChar= s.charAt(0);
- if (controlChar == ' ') { // context lines
- while (true) {
- Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in context"); //$NON-NLS-1$
- if (linesMatch(line, (String) lines.get(pos))) {
- pos++;
- break;
- }
- pos++;
- }
- } else if (controlChar == '-') {
- // deleted lines
- while (true) {
- Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in deleted lines"); //$NON-NLS-1$
- if (linesMatch(line, (String) lines.get(pos))) {
- break;
- }
- pos++;
- }
- lines.remove(pos);
- } else if (controlChar == '+') {
- // added lines
- lines.add(pos, line);
- pos++;
- } else
- Assert.isTrue(false, "doPatch: unknown control charcter: " + controlChar); //$NON-NLS-1$
- }
- return hunk.fNewLength - hunk.fOldLength;
- }
-
- public void applyAll(IResource target, IProgressMonitor pm) {
-
- if (DEBUG) System.out.println("applyAll: start");
-
- IContainer container= null;
- if (target instanceof IContainer)
- container= (IContainer) target;
- else {
- if (DEBUG) System.out.println("applyAll: not yet implemented");
- return;
- }
-
- for (int i= 0; i < fDiffs.length; i++) {
- Diff diff= fDiffs[i];
- if (diff.fIsEnabled) {
-
- IPath path= getPath(diff);
- IFile file= createPath(container, path);
-
- int type= diff.getType();
- switch (type) {
- case Differencer.ADDITION:
- if (DEBUG) System.out.println(" add: " + path);
- updateFile(diff, file, true, pm);
- break;
- case Differencer.DELETION:
- if (DEBUG) System.out.println(" del: " + path);
- deleteFile(file, pm);
- break;
- case Differencer.CHANGE:
- if (DEBUG) System.out.println(" chg: " + path);
- updateFile(diff, file, false, pm);
- break;
- }
-
- /*
- String rej= diff.fRejected;
- if (rej != null) {
- IPath pp= path.removeLastSegments(1);
- pp= pp.append(path.lastSegment() + ".rej");
- createPath(fRoot, rootFolder, pp, diff, true);
- }
- */
- }
- if (pm != null)
- pm.worked(1);
- }
-
- try {
- target.refreshLocal(IResource.DEPTH_INFINITE, pm);
- } catch (CoreException ex) {
- if (DEBUG) System.out.println("refreshLocal: exception " + ex);
- }
- if (DEBUG) System.out.println("applyAll: end");
- }
-
- List apply(Diff diff, IFile file, boolean create, List failedHunks) {
-
- if (file == null)
- if (DEBUG) System.out.println(" file == null");
-
- List lines= null;
- if (!create) {
- // read current contents
- InputStream is= null;
- try {
- is= file.getContents();
- BufferedReader reader= new BufferedReader(new InputStreamReader(is));
- lines= new LineReader(reader).readLines();
- if (DEBUG) System.out.println(" creating reader successful");
- } catch(CoreException ex) {
- if (DEBUG) System.out.println(" reading contents: " + ex);
- } finally {
- if (is != null)
- try {
- is.close();
- } catch(IOException ex) {
- }
- }
- }
-
- if (lines == null)
- lines= new ArrayList();
-
- patch(diff, lines, failedHunks);
-
- return lines;
- }
-
- private void deleteFile(IFile file, IProgressMonitor pm) {
- try {
- file.delete(true, true, pm);
- } catch (CoreException ex) {
- System.out.println("deleteFile: exception: " + ex);
- }
- }
-
- private void updateFile(Diff diff, IFile file, boolean create, IProgressMonitor pm) {
-
- if (DEBUG) System.out.println(" updateFile: start");
-
- // patch it and collect rejected hunks
- List failed= new ArrayList();
-
- if (DEBUG) System.out.println(" patching: start");
- List lines= apply(diff, file, create, failed);
- if (DEBUG) System.out.println(" patching: end");
-
- // convert the result into a String
- StringBuffer sb= new StringBuffer();
- Iterator iter= lines.iterator();
- while (iter.hasNext())
- sb.append((String)iter.next());
- String contents= sb.toString();
-
- // and save it
- InputStream is= new ByteArrayInputStream(contents.getBytes());
- try {
- if (file.exists()) {
- file.setContents(is, false, true, pm);
- if (DEBUG) System.out.println(" setContents: successfull");
- } else {
- file.create(is, false, pm);
- if (DEBUG) System.out.println(" create: successfull");
- }
- } catch (CoreException ex) {
- if (DEBUG) System.out.println(" exception: " + ex);
- } finally {
- if (is != null)
- try {
- is.close();
- } catch(IOException ex) {
- }
- }
- if (DEBUG) System.out.println(" updateFile: end");
- }
-
- private IFile createPath(IContainer folder, IPath path) {
- if (path.segmentCount() > 1) {
- IFolder f= folder.getFolder(path.uptoSegment(1));
- //System.out.println("createPath: " + f + " " + f.exists());
- return createPath(f, path.removeFirstSegments(1));
- }
- // a leaf
- return folder.getFile(path);
- }
-
- private static String stripWhiteSpace(String s) {
- StringBuffer sb= new StringBuffer();
- int l= s.length();
- for (int i= 0; i < l; i++) {
- char c= s.charAt(i);
- if (!Character.isWhitespace(c))
- sb.append(c);
- }
- return sb.toString();
- }
-
- /**
- * Compares two strings.
- * If fIgnoreWhitespace is true whitespace and line endings are ignored.
- */
- private boolean linesMatch(String line1, String line2) {
- if (fIgnoreWhitespace)
- return stripWhiteSpace(line1).equals(stripWhiteSpace(line2));
- return line1.equals(line2);
- }
-
- /**
- * Returns the length (exluding end-of-line characters) of the given string.
- */
- /* package */ static int length(String s) {
- int l= s.length();
- if (l > 0 && s.charAt(l-1) == '\n')
- l--;
- if (l > 1 && s.charAt(l-2) == '\r')
- l--;
- return l;
- }
-}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PreviewPatchPage.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PreviewPatchPage.java
deleted file mode 100644
index 952c5615f..000000000
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/PreviewPatchPage.java
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import java.io.*;
-import java.util.*;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.*;
-import org.eclipse.swt.widgets.*;
-
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.wizard.WizardPage;
-
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
-
-import org.eclipse.compare.*;
-import org.eclipse.compare.internal.*;
-import org.eclipse.compare.structuremergeviewer.*;
-
-
-/**
- * Shows the parsed patch file and any mismatches
- * between files, hunks and the currently selected
- * resources.
- */
-/* package */ class PreviewPatchPage extends WizardPage {
-
- /**
- * Used with CompareInput
- */
- static class HunkInput implements ITypedElement, IStreamContentAccessor {
- String fContent;
- String fType;
-
- HunkInput(String type, String s) {
- fType= type;
- fContent= s;
- }
- public Image getImage() {
- return null;
- }
- public String getName() {
- return "no name";
- }
- public String getType() {
- return fType;
- }
- public InputStream getContents() {
- return new ByteArrayInputStream(fContent.getBytes());
- }
- };
-
- private PatchWizard fPatchWizard;
-
- private Tree fTree;
- private Combo fStripPrefixSegments;
- private CompareViewerSwitchingPane fHunkViewer;
- private Button fIgnoreWhitespaceButton;
- private Button fReversePatchButton;
- private Text fFuzzField;
-
- private Image fNullImage;
- private Image fAddImage;
- private Image fDelImage;
-
- private CompareConfiguration fCompareConfiguration;
-
-
- /* package */ PreviewPatchPage(PatchWizard pw) {
- super("PreviewPatchPage", "Verify Patch", null);
-
- setMessage(
- "The tree shows the contents of the patch. " +
- "A checked item indicates that a patch could be applied succesfully.\n" +
- "Uncheck an item if you want to exclude it.");
-
- fPatchWizard= pw;
- //setPageComplete(false);
-
- int w= 16;
- fNullImage= new DiffImage(null, null, w).createImage();
- fAddImage= new DiffImage(null, CompareUIPlugin.getImageDescriptor("ovr16/add_ov.gif"), w).createImage();
- fDelImage= new DiffImage(null, CompareUIPlugin.getImageDescriptor("ovr16/del_ov.gif"), w).createImage();
-
- fCompareConfiguration= new CompareConfiguration();
-
- fCompareConfiguration.setLeftEditable(false);
- fCompareConfiguration.setLeftLabel("Original");
-
- fCompareConfiguration.setRightEditable(false);
- fCompareConfiguration.setRightLabel("Result");
- }
-
- /* (non-Javadoc)
- * Method declared in WizardPage
- */
- public void setVisible(boolean visible) {
- if (visible)
- buildTree();
- super.setVisible(visible);
- }
-
- Image getImage(Diff diff) {
- switch (diff.getType()) {
- case Differencer.ADDITION:
- return fAddImage;
- case Differencer.DELETION:
- return fDelImage;
- }
- return fNullImage;
- }
-
- public void createControl(Composite parent) {
-
- Composite composite= new Composite(parent, SWT.NULL);
- composite.setLayout(new GridLayout());
- composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));
- setControl(composite);
-
- buildPatchOptionsGroup(composite);
-
- // top pane showing diffs and hunks in a check box tree
- fTree= new Tree(composite, SWT.CHECK | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
- GridData gd= new GridData();
- gd.verticalAlignment= GridData.FILL;
- gd.horizontalAlignment= GridData.FILL;
- gd.grabExcessHorizontalSpace= true;
- gd.grabExcessVerticalSpace= true;
- fTree.setLayoutData(gd);
-
- // bottom pane showing hunks in compare viewer
- fHunkViewer= new CompareViewerSwitchingPane(composite, SWT.BORDER) {
- protected Viewer getViewer(Viewer oldViewer, Object input) {
- return CompareUI.findContentViewer(oldViewer, (ICompareInput)input, this, fCompareConfiguration);
- }
- };
- gd= new GridData();
- gd.verticalAlignment= GridData.FILL;
- gd.horizontalAlignment= GridData.FILL;
- gd.grabExcessHorizontalSpace= true;
- gd.grabExcessVerticalSpace= true;
- fHunkViewer.setLayoutData(gd);
-
- // register listeners
-
- fTree.addSelectionListener(
- new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- TreeItem ti= (TreeItem) e.item;
- Object data= e.item.getData();
- if (e.detail == SWT.CHECK) {
- boolean enabled= ti.getChecked();
- if (data instanceof Hunk) {
- ((Hunk)data).fIsEnabled= enabled;
- updateGrayedState(ti);
- } else if (data instanceof Diff) {
- ((Diff)data).fIsEnabled= enabled;
- updateCheckedState(ti);
- }
- } else {
- if (data instanceof Hunk)
- PreviewPatchPage.this.fHunkViewer.setInput(createInput((Hunk)data));
- else
- PreviewPatchPage.this.fHunkViewer.setInput(null);
- }
- }
- }
- );
-
- // creating tree's content
- buildTree();
-
- // WorkbenchHelp.setHelp(composite, new DialogPageContextComputer(this, PATCH_HELP_CONTEXT_ID));
- }
-
- /**
- * Create the group for setting various patch options
- */
- private void buildPatchOptionsGroup(Composite parent) {
-
- final Patcher patcher= fPatchWizard.getPatcher();
-
- Group group= new Group(parent, SWT.NONE);
- group.setText("Patch Options");
- GridLayout layout= new GridLayout();
- layout.numColumns= 5;
- group.setLayout(layout);
- group.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
- //fPatchFileGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-
- // 1st row
- new Label(group, SWT.NONE).setText("Ignore leading path name segments:");
-
- fStripPrefixSegments= new Combo(group, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.SIMPLE);
- int prefixCnt= patcher.getStripPrefixSegments();
- String prefix= Integer.toString(prefixCnt);
- fStripPrefixSegments.add(prefix);
- fStripPrefixSegments.setText(prefix);
-
- addSpacer(group);
-
- fReversePatchButton= new Button(group, SWT.CHECK);
- fReversePatchButton.setText("Reverse Patch");
-
- addSpacer(group);
-
- // 2nd row
- Label l= new Label(group, SWT.NONE);
- l.setText("Maximum fuzz factor:");
- l.setToolTipText("Allow context to shift this number of lines from the original place");
- fFuzzField= new Text(group, SWT.BORDER);
- fFuzzField.setText("2");
- GridData gd2= new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
- gd2.widthHint= 30;
- fFuzzField.setLayoutData(gd2);
-
- addSpacer(group);
-
- fIgnoreWhitespaceButton= new Button(group, SWT.CHECK);
- fIgnoreWhitespaceButton.setText("Ignore Whitespace");
-
- addSpacer(group);
-
- // register listeners
-
- if (fStripPrefixSegments != null)
- fStripPrefixSegments.addSelectionListener(
- new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- if (patcher.setStripPrefixSegments(getStripPrefixSegments()))
- updateTree();
- }
- }
- );
- fReversePatchButton.addSelectionListener(
- new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- if (patcher.setReversed(fReversePatchButton.getSelection()))
- updateTree();
- }
- }
- );
- fIgnoreWhitespaceButton.addSelectionListener(
- new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- if (patcher.setIgnoreWhitespace(fIgnoreWhitespaceButton.getSelection()))
- updateTree();
- }
- }
- );
-
- fFuzzField.addModifyListener(
- new ModifyListener() {
- public void modifyText(ModifyEvent e) {
- if (patcher.setFuzz(getFuzzFactor()))
- updateTree();
- }
- }
- );
- }
-
- ICompareInput createInput(Hunk hunk) {
-
- String[] lines= hunk.fLines;
- StringBuffer left= new StringBuffer();
- StringBuffer right= new StringBuffer();
-
- for (int i= 0; i < lines.length; i++) {
- String line= lines[i];
- String rest= line.substring(1);
- switch (line.charAt(0)) {
- case ' ':
- left.append(rest);
- right.append(rest);
- break;
- case '-':
- left.append(rest);
- break;
- case '+':
- right.append(rest);
- break;
- }
- }
-
- Diff diff= hunk.fParent;
- IPath path= diff.getPath();
- String type= path.getFileExtension();
-
- return new DiffNode(new HunkInput(type, left.toString()), new HunkInput(type, right.toString()));
- }
-
- /**
- * Builds a tree from list of Diffs.
- * As a side effect it calculates the maximum number of segments
- * in all paths.
- */
- private void buildTree() {
- setPageComplete(true);
- if (fTree != null && !fTree.isDisposed()) {
- fTree.removeAll();
- fHunkViewer.setInput(null);
-
- int length= 99;
-
- Diff[] diffs= fPatchWizard.getPatcher().getDiffs();
- if (diffs != null) {
- for (int i= 0; i < diffs.length; i++) {
- Diff diff= diffs[i];
- TreeItem d= new TreeItem(fTree, SWT.NULL);
- d.setData(diff);
- d.setImage(getImage(diff));
-
- if (diff.fOldPath != null)
- length= Math.min(length, diff.fOldPath.segmentCount());
- if (diff.fNewPath != null)
- length= Math.min(length, diff.fNewPath.segmentCount());
-
- java.util.List hunks= diff.fHunks;
- java.util.Iterator iter= hunks.iterator();
- while (iter.hasNext()) {
- Hunk hunk= (Hunk) iter.next();
- TreeItem h= new TreeItem(d, SWT.NULL);
- h.setData(hunk);
- h.setText(hunk.getDescription());
- }
- }
- }
- if (fStripPrefixSegments != null && length != 99)
- for (int i= 1; i < length; i++)
- fStripPrefixSegments.add(Integer.toString(i));
- }
-
- updateTree();
- }
-
- private IFile existsInSelection(IPath path) {
- IResource target= fPatchWizard.getTarget();
- if (target instanceof IFile) {
- IFile file= (IFile) target;
- IPath path2= file.getFullPath().removeFirstSegments(1);
- //System.out.println("target: " + path2.toOSString());
- //System.out.println(" path: " + path.toOSString());
- if (path.equals(path2))
- return file;
-// String name= file.getName();
-// if (path.lastSegment().equals(name))
-// return file;
- } else if (target instanceof IContainer) {
- IContainer c= (IContainer) target;
- if (c.exists(path))
- return c.getFile(path);
- }
- return null;
- }
-
- /**
- * Updates label and checked state of tree items.
- */
- private void updateTree() {
- if (fTree == null || fTree.isDisposed())
- return;
- int strip= getStripPrefixSegments();
- TreeItem[] children= fTree.getItems();
- for (int i= 0; i < children.length; i++) {
- TreeItem item= children[i];
- Diff diff= (Diff) item.getData();
- String error= null;
-
- boolean create= false;
- IFile file= null;
- if (diff.getType() == Differencer.ADDITION) {
- IPath p= diff.fNewPath;
- if (strip > 0 && strip < p.segmentCount())
- p= p.removeFirstSegments(strip);
- file= existsInSelection(p);
- if (file == null) {
- diff.fIsEnabled= true;
- } else {
- // file already exists
- diff.fIsEnabled= false;
- error= "(file already exists)";
- }
- create= true;
- } else {
- IPath p= diff.fOldPath;
- if (strip > 0 && strip < p.segmentCount())
- p= p.removeFirstSegments(strip);
- file= existsInSelection(p);
- diff.fIsEnabled= file != null;
- if (file != null) {
- diff.fIsEnabled= true;
- } else {
- // file doesn't exist
- diff.fIsEnabled= false;
- error= "(file doesn't exist)";
- }
- }
-
- boolean checked= false;
-
- ArrayList failedHunks= new ArrayList(); // collect rejected hunks here
-
- fPatchWizard.getPatcher().apply(diff, file, create, failedHunks);
-
- if (! failedHunks.isEmpty()) {
- StringBuffer sb= new StringBuffer();
- Iterator iter= failedHunks.iterator();
- while (iter.hasNext()) {
- Hunk hunk= (Hunk) iter.next();
- sb.append(hunk.getDescription());
- sb.append('\n');
- sb.append(hunk.getContent());
- }
- diff.fRejected= sb.toString();
- }
-
- int checkedSubs= 0; // counts checked hunk items
- TreeItem[] hunkItems= item.getItems();
- for (int h= 0; h < hunkItems.length; h++) {
- Hunk hunk= (Hunk) hunkItems[h].getData();
- boolean failed= failedHunks.contains(hunk);
- String hunkError= null;
- if (failed)
- hunkError= "(no match)";
- hunk.fIsEnabled= diff.fIsEnabled && !failed;
- hunkItems[h].setChecked(hunk.fIsEnabled);
- if (hunk.fIsEnabled) {
- checkedSubs++;
- checked= true;
- }
- String hunkLabel= hunk.getDescription();
- if (hunkError != null)
- hunkLabel+= " " + hunkError;
- hunkItems[h].setText(hunkLabel);
- }
-
- String label= diff.getDescription(strip);
- if (error != null)
- label+= " " + error;
- item.setText(label);
- item.setImage(getImage(diff));
- item.setChecked(checked);
- boolean gray= (checkedSubs > 0 && checkedSubs < hunkItems.length);
- item.setGrayed(gray);
- item.setExpanded(gray);
- }
- }
-
- /**
- * Updates the gray state of the given diff and the checked state of its children.
- */
- private void updateCheckedState(TreeItem diff) {
- boolean checked= diff.getChecked();
- diff.setGrayed(false);
- TreeItem[] hunks= diff.getItems();
- for (int i= 0; i < hunks.length; i++)
- hunks[i].setChecked(checked);
- }
-
- /**
- * Updates the gray state of the given items parent.
- */
- private void updateGrayedState(TreeItem hunk) {
- TreeItem diff= hunk.getParentItem();
- TreeItem[] hunks= diff.getItems();
- int checked= 0;
- for (int i= 0; i < hunks.length; i++)
- if (hunks[i].getChecked())
- checked++;
- diff.setChecked(checked > 0);
- diff.setGrayed(checked > 0 && checked < hunks.length);
- }
-
- private void addSpacer(Composite parent) {
- Label label= new Label(parent, SWT.NONE);
- GridData gd= new GridData(GridData.FILL_HORIZONTAL);
- gd.widthHint= 20;
- label.setLayoutData(gd);
- }
-
- private int getStripPrefixSegments() {
- int stripPrefixSegments= 0;
- if (fStripPrefixSegments != null) {
- String s= fStripPrefixSegments.getText();
- try {
- stripPrefixSegments= Integer.parseInt(s);
- } catch(NumberFormatException ex) {
- }
- }
- return stripPrefixSegments;
- }
-
- private int getFuzzFactor() {
- int fuzzFactor= 0;
- if (fFuzzField != null) {
- String s= fFuzzField.getText();
- try {
- fuzzFactor= Integer.parseInt(s);
- } catch(NumberFormatException ex) {
- }
- }
- return fuzzFactor;
- }
-}
diff --git a/bundles/org.eclipse.compare/plugin.xml b/bundles/org.eclipse.compare/plugin.xml
index 5eb8c2d4c..23fd860fc 100644
--- a/bundles/org.eclipse.compare/plugin.xml
+++ b/bundles/org.eclipse.compare/plugin.xml
@@ -91,7 +91,7 @@
tooltip="%CompareWithPatchAction.tooltip"
menubarPath="compareWithMenu/compareWithGroup"
enablesFor="1"
- class="org.eclipse.compare.patch.CompareWithPatchAction">
+ class="org.eclipse.compare.internal.patch.CompareWithPatchAction">
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareMessages.properties b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareMessages.properties
index cf31617aa..44538cec9 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareMessages.properties
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareMessages.properties
@@ -3,6 +3,9 @@
# All Rights Reserved.
# =====================================
+ComparePlugin.internal_error= Internal Error
+ExceptionDialog.seeErrorLogMessage= See error log for more details.
+
#
# Title format for CompareViewerSwitchingPane
#
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePreferencePage.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePreferencePage.java
index c9ac102fd..f8a64840f 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePreferencePage.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePreferencePage.java
@@ -19,9 +19,9 @@ public class ComparePreferencePage extends FieldEditorPreferencePage implements
public static final String SYNCHRONIZE_SCROLLING= PREFIX + "SynchronizeScrolling"; //$NON-NLS-1$
public static final String SHOW_PSEUDO_CONFLICTS= PREFIX + "ShowPseudoConflicts"; //$NON-NLS-1$
public static final String INITIALLY_SHOW_ANCESTOR_PANE= PREFIX + "InitiallyShowAncestorPane"; //$NON-NLS-1$
+ public static final String PREF_SAVE_ALL_EDITORS= PREFIX + "SaveAllEditors"; //$NON-NLS-1$
public static final String TEXT_FONT= PREFIX + "TextFont"; //$NON-NLS-1$
-
public ComparePreferencePage() {
super(GRID);
}
@@ -34,6 +34,16 @@ public class ComparePreferencePage extends FieldEditorPreferencePage implements
WorkbenchChainedTextFontFieldEditor.startPropagate(store, TEXT_FONT);
}
+ static public boolean getSaveAllEditors() {
+ IPreferenceStore store= CompareUIPlugin.getDefault().getPreferenceStore();
+ return store.getBoolean(PREF_SAVE_ALL_EDITORS);
+ }
+
+ static public void setSaveAllEditors(boolean value) {
+ IPreferenceStore store= CompareUIPlugin.getDefault().getPreferenceStore();
+ store.setValue(PREF_SAVE_ALL_EDITORS, value);
+ }
+
public void init(IWorkbench workbench) {
}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
index 4c56ee5e5..1ed9d6397 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
@@ -57,6 +57,9 @@ public final class CompareUIPlugin extends AbstractUIPlugin {
public static final String CTOOL_PREV= "clcl16/prev_nav.gif"; //$NON-NLS-1$
public static final String ETOOL_PREV= "elcl16/prev_nav.gif"; //$NON-NLS-1$
+ /** Status code describing an internal error */
+ public static final int INTERNAL_ERROR= 1;
+
private static boolean NORMALIZE_CASE= true;
private final static String CLASS_ATTRIBUTE= "class"; //$NON-NLS-1$
@@ -195,6 +198,20 @@ public final class CompareUIPlugin extends AbstractUIPlugin {
return fgResourceBundle;
}
+ public static IWorkbench getActiveWorkbench() {
+ CompareUIPlugin plugin= getDefault();
+ if (plugin == null)
+ return null;
+ return plugin.getWorkbench();
+ }
+
+ public static IWorkbenchWindow getActiveWorkbenchWindow() {
+ IWorkbench workbench= getActiveWorkbench();
+ if (workbench == null)
+ return null;
+ return workbench.getActiveWorkbenchWindow();
+ }
+
/**
* Returns the active workkbench page or null
if
* no active workkbench page can be determined.
@@ -203,13 +220,7 @@ public final class CompareUIPlugin extends AbstractUIPlugin {
* no active workkbench page can be determined
*/
private static IWorkbenchPage getActivePage() {
- CompareUIPlugin plugin= getDefault();
- if (plugin == null)
- return null;
- IWorkbench workbench= plugin.getWorkbench();
- if (workbench == null)
- return null;
- IWorkbenchWindow window= workbench.getActiveWorkbenchWindow();
+ IWorkbenchWindow window= getActiveWorkbenchWindow();
if (window == null)
return null;
return window.getActivePage();
@@ -223,16 +234,10 @@ public final class CompareUIPlugin extends AbstractUIPlugin {
* no workbench window is active
*/
public static Shell getShell() {
- CompareUIPlugin p= getDefault();
- if (p == null)
- return null;
- IWorkbench wb= p.getWorkbench();
- if (wb == null)
- return null;
- IWorkbenchWindow ww= wb.getActiveWorkbenchWindow();
- if (ww == null)
+ IWorkbenchWindow window= getActiveWorkbenchWindow();
+ if (window == null)
return null;
- return ww.getShell();
+ return window.getShell();
}
/**
@@ -810,4 +815,44 @@ public final class CompareUIPlugin extends AbstractUIPlugin {
iter.remove();
}
}
+
+ /**
+ * Returns an array of all editors that have an unsaved content. If the identical content is
+ * presented in more than one editor, only one of those editor parts is part of the result.
+ *
+ * @return an array of all dirty editor parts.
+ */
+ public static IEditorPart[] getDirtyEditors() {
+ Set inputs= new HashSet(7);
+ ArrayList result= new ArrayList(0);
+ IWorkbench workbench= CompareUIPlugin.getDefault().getWorkbench();
+ IWorkbenchWindow[] windows= workbench.getWorkbenchWindows();
+ for (int i= 0; i < windows.length; i++) {
+ IWorkbenchPage[] pages= windows[i].getPages();
+ for (int x= 0; x < pages.length; x++) {
+ IEditorPart[] editors= pages[x].getEditors();
+ for (int z= 0; z < editors.length; z++) {
+ IEditorPart editor= editors[z];
+ IEditorInput input= editor.getEditorInput();
+ if (editor.isDirty() && !inputs.contains(input)) {
+ inputs.add(input);
+ result.add(editor);
+ }
+ }
+ }
+ }
+ return (IEditorPart[])result.toArray(new IEditorPart[result.size()]);
+ }
+
+ public static void log(Throwable e) {
+ log(new Status(IStatus.ERROR, getPluginId(), INTERNAL_ERROR, CompareMessages.getString("JavaPlugin.internal_error"), e)); //$NON-NLS-1$
+ }
+
+ public static void log(IStatus status) {
+ getDefault().getLog().log(status);
+ }
+
+ public static String getPluginId() {
+ return getDefault().getDescriptor().getUniqueIdentifier();
+ }
}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ExceptionHandler.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ExceptionHandler.java
new file mode 100644
index 000000000..773b0499c
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ExceptionHandler.java
@@ -0,0 +1,127 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal;
+
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+
+/**
+ * The default exception handler shows an error dialog when one of its handle methods
+ * is called. If the passed exception is a CoreException
an error dialog
+ * pops up showing the exception's status information. For a InvocationTargetException
+ * a normal message dialog pops up showing the exception's message. Additionally the exception
+ * is written to the platform log.
+ */
+public class ExceptionHandler {
+
+ private static ExceptionHandler fgInstance= new ExceptionHandler();
+
+ /**
+ * Logs the given exception using the platform's logging mechanism. The exception is
+ * logged as an error with the error code JavaStatusConstants.INTERNAL_ERROR
.
+ */
+ public static void log(Throwable t, String message) {
+ CompareUIPlugin.log(new Status(IStatus.ERROR, CompareUIPlugin.getPluginId(),
+ CompareUIPlugin.INTERNAL_ERROR, message, t));
+ }
+
+ /**
+ * Handles the given CoreException
. The workbench shell is used as a parent
+ * for the dialog window.
+ *
+ * @param e the CoreException
to be handled
+ * @param title the dialog window's window title
+ * @param message message to be displayed by the dialog window
+ */
+ public static void handle(CoreException e, String title, String message) {
+ handle(e, CompareUIPlugin.getShell(), title, message);
+ }
+
+ /**
+ * Handles the given CoreException
.
+ *
+ * @param e the CoreException
to be handled
+ * @param parent the dialog window's parent shell
+ * @param title the dialog window's window title
+ * @param message message to be displayed by the dialog window
+ */
+ public static void handle(CoreException e, Shell parent, String title, String message) {
+ fgInstance.perform(e, parent, title, message);
+ }
+
+ /**
+ * Handles the given InvocationTargetException
. The workbench shell is used
+ * as a parent for the dialog window.
+ *
+ * @param e the InvocationTargetException
to be handled
+ * @param title the dialog window's window title
+ * @param message message to be displayed by the dialog window
+ */
+ public static void handle(InvocationTargetException e, String title, String message) {
+ handle(e, CompareUIPlugin.getShell(), title, message);
+ }
+
+ /**
+ * Handles the given InvocationTargetException
.
+ *
+ * @param e the InvocationTargetException
to be handled
+ * @param parent the dialog window's parent shell
+ * @param title the dialog window's window title
+ * @param message message to be displayed by the dialog window
+ */
+ public static void handle(InvocationTargetException e, Shell parent, String title, String message) {
+ fgInstance.perform(e, parent, title, message);
+ }
+
+ //---- Hooks for subclasses to control exception handling ------------------------------------
+
+ protected void perform(CoreException e, Shell shell, String title, String message) {
+ CompareUIPlugin.log(e);
+ IStatus status= e.getStatus();
+ if (status != null) {
+ ErrorDialog.openError(shell, title, message, status);
+ } else {
+ displayMessageDialog(e, e.getMessage(), shell, title, message);
+ }
+ }
+
+ protected void perform(InvocationTargetException e, Shell shell, String title, String message) {
+ Throwable target= e.getTargetException();
+ if (target instanceof CoreException) {
+ perform((CoreException)target, shell, title, message);
+ } else {
+ CompareUIPlugin.log(e);
+ if (e.getMessage() != null && e.getMessage().length() > 0) {
+ displayMessageDialog(e, e.getMessage(), shell, title, message);
+ } else {
+ displayMessageDialog(e, target.getMessage(), shell, title, message);
+ }
+ }
+ }
+
+ //---- Helper methods -----------------------------------------------------------------------
+
+ private void displayMessageDialog(Throwable t, String exceptionMessage, Shell shell, String title, String message) {
+ StringWriter msg= new StringWriter();
+ if (message != null) {
+ msg.write(message);
+ msg.write("\n\n"); //$NON-NLS-1$
+ }
+ if (exceptionMessage == null || exceptionMessage.length() == 0)
+ msg.write(CompareMessages.getString("ExceptionDialog.seeErrorLogMessage")); //$NON-NLS-1$
+ else
+ msg.write(exceptionMessage);
+ MessageDialog.openError(shell, title, msg.toString());
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ListContentProvider.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ListContentProvider.java
new file mode 100644
index 000000000..9170edeca
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ListContentProvider.java
@@ -0,0 +1,41 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal;
+
+import java.util.List;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * A specialized content provider to show a list of editor parts.
+ */
+public class ListContentProvider implements IStructuredContentProvider {
+ List fContents;
+
+ public ListContentProvider() {
+ }
+
+ public Object[] getElements(Object input) {
+ if (fContents != null && fContents == input)
+ return fContents.toArray();
+ return new Object[0];
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ if (newInput instanceof List)
+ fContents= (List)newInput;
+ else
+ fContents= null;
+ // we use a fixed set.
+ }
+
+ public void dispose() {
+ }
+
+ public boolean isDeleted(Object o) {
+ return fContents != null && !fContents.contains(o);
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ListDialog.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ListDialog.java
new file mode 100644
index 000000000..7cd262479
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ListDialog.java
@@ -0,0 +1,83 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.*;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.*;
+
+import org.eclipse.ui.dialogs.SelectionDialog;
+
+public class ListDialog extends SelectionDialog {
+
+ private IStructuredContentProvider fContentProvider;
+ private ILabelProvider fLabelProvider;
+ private Object fInput;
+ private TableViewer fTableViewer;
+ private boolean fAddCancelButton;
+
+ public ListDialog(Shell parent) {
+ super(parent);
+ fAddCancelButton= false;
+ }
+
+ public void setInput(Object input) {
+ fInput= input;
+ }
+
+ public void setContentProvider(IStructuredContentProvider sp){
+ fContentProvider= sp;
+ }
+
+ public void setLabelProvider(ILabelProvider lp){
+ fLabelProvider= lp;
+ }
+
+ public void setAddCancelButton(boolean addCancelButton) {
+ fAddCancelButton= addCancelButton;
+ }
+
+ public TableViewer getTableViewer(){
+ return fTableViewer;
+ }
+
+ public boolean hasFilters(){
+ return fTableViewer.getFilters() != null && fTableViewer.getFilters().length != 0;
+ }
+
+ public void create() {
+ setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE);
+ super.create();
+ }
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ if (! fAddCancelButton)
+ createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ else
+ super.createButtonsForButtonBar(parent);
+ }
+
+ protected Control createDialogArea(Composite container) {
+ Composite parent= (Composite) super.createDialogArea(container);
+ createMessageArea(parent);
+ fTableViewer= new TableViewer(parent, getTableStyle());
+ fTableViewer.setContentProvider(fContentProvider);
+ Table table= fTableViewer.getTable();
+ fTableViewer.setLabelProvider(fLabelProvider);
+ fTableViewer.setInput(fInput);
+ GridData gd= new GridData(GridData.FILL_BOTH);
+ gd.heightHint= convertHeightInCharsToPixels(15);
+ gd.widthHint= convertWidthInCharsToPixels(55);
+ table.setLayoutData(gd);
+ return parent;
+ }
+
+ protected int getTableStyle() {
+ return SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER;
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Utilities.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Utilities.java
index 01f63aab0..0a81cc115 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Utilities.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Utilities.java
@@ -204,7 +204,7 @@ public class Utilities {
}
public static String getIconPath(Display display) {
- return "icons/full/";
+ return "icons/full/"; //$NON-NLS-1$
}
/**
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Attic/LineReader.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Attic/LineReader.java
new file mode 100644
index 000000000..98026451e
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Attic/LineReader.java
@@ -0,0 +1,115 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.io.*;
+import java.util.*;
+
+import org.eclipse.jface.util.Assert;
+
+/* package */ class LineReader {
+
+ private boolean fHaveChar= false;
+ private int fLastChar;
+ private boolean fSawEOF= false;
+ private BufferedReader fReader;
+
+ /* package */ LineReader(BufferedReader reader) {
+ fReader= reader;
+ Assert.isNotNull(reader);
+ }
+
+ /**
+ * Reads a line of text. A line is considered to be terminated by any one
+ * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
+ * followed immediately by a linefeed.
+ * @return A string containing the contents of the line including
+ * the line-termination characters, or null
if the end of the
+ * stream has been reached
+ * @exception IOException If an I/O error occurs
+ */
+ /* package */ String readLine() throws IOException {
+ StringBuffer sb= null;
+
+ while (!fSawEOF) {
+ int c= readChar();
+ if (c == -1) {
+ fSawEOF= true;
+ break;
+ }
+ if (sb == null)
+ sb= new StringBuffer();
+ sb.append((char)c);
+ if (c == '\n')
+ break;
+ if (c == '\r') {
+ c= readChar();
+ if (c == -1) {
+ fSawEOF= true;
+ break; // EOF
+ }
+ if (c != '\n') {
+ fHaveChar= true;
+ fLastChar= c;
+ } else
+ sb.append((char)c);
+ break;
+ }
+ }
+
+ if (sb != null)
+ return sb.toString();
+ return null;
+ }
+
+ /* package */ void close() {
+ try {
+ fReader.close();
+ } catch (IOException ex) {
+ }
+ }
+
+ /* package */ List readLines() {
+ try {
+ List lines= new ArrayList();
+ String line;
+ while ((line= readLine()) != null)
+ lines.add(line);
+ return lines;
+ } catch (IOException ex) {
+ //System.out.println("error while reading file: " + fileName + "(" + ex + ")");
+ } finally {
+ close();
+ }
+ return null;
+ }
+ /**
+ * Returns the number of characters in the given string without
+ * counting a trailing line separator.
+ */
+ /* package */ int lineContentLength(String line) {
+ if (line == null)
+ return 0;
+ int length= line.length();
+ for (int i= length-1; i >= 0; i--) {
+ char c= line.charAt(i);
+ if (c =='\n' || c == '\r')
+ length--;
+ else
+ break;
+ }
+ return length;
+ }
+
+ //---- private
+
+ private int readChar() throws IOException {
+ if (fHaveChar) {
+ fHaveChar= false;
+ return fLastChar;
+ }
+ return fReader.read();
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CompareWithPatchAction.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CompareWithPatchAction.java
new file mode 100644
index 000000000..28dff2473
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CompareWithPatchAction.java
@@ -0,0 +1,166 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.lang.reflect.InvocationTargetException;
+import java.text.MessageFormat;
+import java.util.Arrays;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Button;
+
+import org.eclipse.jface.dialogs.*;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.*;
+import org.eclipse.jface.action.IAction;
+
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.internal.*;
+import org.eclipse.ui.IActionDelegate;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+
+import org.eclipse.compare.internal.*;
+
+public class CompareWithPatchAction implements IActionDelegate {
+
+ static class PatchWizardDialog extends WizardDialog {
+
+ PatchWizardDialog(Shell parent, IWizard wizard) {
+ super(parent, wizard);
+
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ setMinimumPageSize(700, 500);
+ }
+ }
+
+ private ISelection fSelection;
+ private boolean fSavedFiles;
+ private boolean fAutobuildState;
+
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ fSelection= selection;
+ action.setEnabled(fSelection != null && !fSelection.isEmpty());
+ }
+
+ public void run(IAction action) {
+ PatchWizard wizard= new PatchWizard(fSelection);
+
+ if (areAllEditorsSaved()) {
+ //RefactoringStatus activationStatus= refactoring.checkActivation(new NullProgressMonitor());
+ //if (! activationStatus.hasFatalError()){
+ // wizard.setActivationStatus(activationStatus);
+ PatchWizardDialog dialog= new PatchWizardDialog(CompareUIPlugin.getShell(), wizard);
+ if (dialog.open() == Dialog.CANCEL)
+ triggerBuild();
+
+ //} else{
+ //RefactoringErrorDialog.open(dialogTitle, activationStatus);
+ //}
+ }
+ }
+
+ private boolean areAllEditorsSaved(){
+ if (CompareUIPlugin.getDirtyEditors().length == 0)
+ return true;
+ if (! saveAllDirtyEditors())
+ return false;
+ Shell shell= CompareUIPlugin.getShell();
+ try {
+ // Save isn't cancelable.
+ IWorkspace workspace= ResourcesPlugin.getWorkspace();
+ IWorkspaceDescription description= workspace.getDescription();
+ boolean autoBuild= description.isAutoBuilding();
+ description.setAutoBuilding(false);
+ workspace.setDescription(description);
+ try {
+ new ProgressMonitorDialog(shell).run(false, false, createRunnable());
+ fSavedFiles= true;
+ } finally {
+ description.setAutoBuilding(autoBuild);
+ workspace.setDescription(description);
+ }
+ return true;
+ } catch (InvocationTargetException e) {
+ ExceptionHandler.handle(e, shell, PatchMessages.getString("PatchAction.ExceptionTitle"), PatchMessages.getString("Exception")); //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ } catch (CoreException e) {
+ ExceptionHandler.handle(e, shell, PatchMessages.getString("PatchAction.ExceptionTitle"), PatchMessages.getString("Exception")); //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ } catch (InterruptedException e) {
+ Assert.isTrue(false); // Can't happen. Operation isn't cancelable.
+ return false;
+ }
+ }
+
+ private IRunnableWithProgress createRunnable() {
+ return new IRunnableWithProgress() {
+ public void run(IProgressMonitor pm) {
+ IEditorPart[] editorsToSave= CompareUIPlugin.getDirtyEditors();
+ pm.beginTask(PatchMessages.getString("PatchAction.SavingDirtyEditorsTask"), editorsToSave.length); //$NON-NLS-1$
+ for (int i= 0; i < editorsToSave.length; i++) {
+ editorsToSave[i].doSave(new SubProgressMonitor(pm, 1));
+ pm.worked(1);
+ }
+ pm.done();
+ }
+ };
+ }
+
+ private boolean saveAllDirtyEditors() {
+ if (ComparePreferencePage.getSaveAllEditors()) //must save everything
+ return true;
+ ListDialog dialog= new ListDialog(CompareUIPlugin.getShell()) {
+ protected Control createDialogArea(Composite parent) {
+ Composite result= (Composite) super.createDialogArea(parent);
+ final Button check= new Button(result, SWT.CHECK);
+ check.setText(PatchMessages.getString("PatchAction.AlwaysSaveQuestion")); //$NON-NLS-1$
+ check.setSelection(ComparePreferencePage.getSaveAllEditors());
+ check.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ ComparePreferencePage.setSaveAllEditors(check.getSelection());
+ }
+ }
+ );
+ return result;
+ }
+ };
+ dialog.setTitle(PatchMessages.getString("PatchAction.SaveAllQuestion")); //$NON-NLS-1$
+ dialog.setAddCancelButton(true);
+ dialog.setLabelProvider(createDialogLabelProvider());
+ dialog.setMessage(PatchMessages.getString("PatchAction.SaveAllDescription")); //$NON-NLS-1$
+ dialog.setContentProvider(new ListContentProvider());
+ dialog.setInput(Arrays.asList(CompareUIPlugin.getDirtyEditors()));
+ return dialog.open() == Dialog.OK;
+ }
+
+ private ILabelProvider createDialogLabelProvider() {
+ return new LabelProvider() {
+ public Image getImage(Object element) {
+ return ((IEditorPart) element).getTitleImage();
+ }
+ public String getText(Object element) {
+ return ((IEditorPart) element).getTitle();
+ }
+ };
+ }
+
+ private void triggerBuild() {
+ if (fSavedFiles && ResourcesPlugin.getWorkspace().getDescription().isAutoBuilding()) {
+ new GlobalBuildAction(CompareUIPlugin.getActiveWorkbench(), IncrementalProjectBuilder.INCREMENTAL_BUILD).run();
+ }
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Diff.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Diff.java
new file mode 100644
index 000000000..9682d5cfe
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Diff.java
@@ -0,0 +1,87 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.util.*;
+
+import org.eclipse.core.runtime.IPath;
+
+import org.eclipse.compare.structuremergeviewer.Differencer;
+
+
+/* package */ class Diff {
+
+ IPath fOldPath, fNewPath;
+ long fOldDate, fNewDate; // if 0: no file
+ List fHunks= new ArrayList();
+ boolean fIsEnabled= true;
+ String fRejected;
+
+
+ /* package */ Diff(IPath oldPath, long oldDate, IPath newPath, long newDate) {
+ fOldPath= oldPath;
+ fOldDate= oldPath == null ? 0 : oldDate;
+ fNewPath= newPath;
+ fNewDate= newPath == null ? 0 : newDate;
+ }
+
+ void reverse() {
+ IPath tp= fOldPath;
+ fOldPath= fNewPath;
+ fNewPath= tp;
+
+ long t= fOldDate;
+ fOldDate= fNewDate;
+ fNewDate= t;
+
+ Iterator iter= fHunks.iterator();
+ while (iter.hasNext()) {
+ Hunk hunk= (Hunk) iter.next();
+ hunk.reverse();
+ }
+ }
+
+ Hunk[] getHunks() {
+ return (Hunk[]) fHunks.toArray((Hunk[]) new Hunk[fHunks.size()]);
+ }
+
+ IPath getPath() {
+ if (fOldPath != null)
+ return fOldPath;
+ return fNewPath;
+ }
+
+ void finish() {
+ if (fHunks.size() == 1) {
+ Hunk h= (Hunk) fHunks.get(0);
+ if (h.fNewLength == 0) {
+ fNewDate= 0;
+ fNewPath= fOldPath;
+ }
+ }
+ }
+
+ /* package */ void add(Hunk hunk) {
+ fHunks.add(hunk);
+ }
+
+ /* package */ int getType() {
+ if (fOldDate == 0)
+ return Differencer.ADDITION;
+ if (fNewDate == 0)
+ return Differencer.DELETION;
+ return Differencer.CHANGE;
+ }
+
+ /* package */ String getDescription(int strip) {
+ IPath path= fOldPath;
+ if (fOldDate == 0)
+ path= fNewPath;
+ if (strip > 0 && strip < path.segmentCount())
+ path= path.removeFirstSegments(strip);
+ return path.toOSString();
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Hunk.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Hunk.java
new file mode 100644
index 000000000..28dc90b55
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Hunk.java
@@ -0,0 +1,120 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.util.List;
+
+import org.eclipse.jface.util.Assert;
+
+
+/**
+ * A Hunk describes a range of changed lines and some context lines.
+ */
+/* package */ class Hunk {
+
+ Diff fParent;
+ int fOldStart, fOldLength;
+ int fNewStart, fNewLength;
+ String[] fLines;
+ boolean fIsEnabled= true;
+
+
+ /* package */ Hunk(Diff parent, int[] oldRange, int[] newRange, List lines) {
+
+ fParent= parent;
+ if (fParent != null)
+ fParent.add(this);
+
+ if (oldRange[0] > 0)
+ fOldStart= oldRange[0]-1; // line number start at 0!
+ else
+ fOldStart= 0;
+ fOldLength= oldRange[1];
+ if (newRange[0] > 0)
+ fNewStart= newRange[0]-1; // line number start at 0!
+ else
+ fNewStart= 0;
+ fNewLength= newRange[1];
+
+ fLines= (String[]) lines.toArray(new String[lines.size()]);
+ }
+
+ void reverse() {
+ int t= fOldStart;
+ fOldStart= fNewStart;
+ fNewStart= t;
+
+ t= fOldLength;
+ fOldLength= fNewLength;
+ fNewLength= t;
+
+ for (int i= 0; i < fLines.length; i++) {
+ String line= fLines[i];
+ char c= line.charAt(0);
+ switch (c) {
+ case '+':
+ fLines[i]= '-' + line.substring(1);
+ break;
+ case '-':
+ fLines[i]= '+' + line.substring(1);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ /**
+ * Returns the contents of this hunk.
+ * Each line starts with a control character. Their meaning is as follows:
+ * IResource
s that returns
+ * only children of the given resource type.
+ */
+ private ITreeContentProvider getResourceProvider(final int resourceType) {
+ return new WorkbenchContentProvider() {
+ public Object[] getChildren(Object o) {
+ if (o instanceof IContainer) {
+ try {
+ ArrayList results= new ArrayList();
+ IResource[] members= ((IContainer)o).members();
+ for (int i= 0; i < members.length; i++)
+ // filter out the desired resource types
+ if ((members[i].getType() & resourceType) != 0)
+ results.add(members[i]);
+ return results.toArray();
+ } catch (CoreException e) {
+ }
+ }
+ // just return an empty set of children
+ return new Object[0];
+ }
+ };
+ }
+
+ /**
+ * Updates the enable state of this page's controls.
+ */
+ private void updateWidgetEnablements() {
+
+ String error= null;
+
+ ISelection selection= fPatchTargets.getSelection();
+ boolean anySelected= selection != null && !selection.isEmpty();
+ if (!anySelected)
+ error= PatchMessages.getString("InputPatchPage.NothingSelected.message"); //$NON-NLS-1$
+
+ boolean gotPatch= false;
+ if (getUseClipboard()) {
+ Control c= getControl();
+ if (c != null) {
+ Clipboard clipboard= new Clipboard(c.getDisplay());
+ Object o= clipboard.getContents(TextTransfer.getInstance());
+ if (o instanceof String) {
+ String s= ((String) o).trim();
+ if (s.length() > 0)
+ gotPatch= true;
+ else
+ error= PatchMessages.getString("InputPatchPage.ClipboardIsEmpty.message"); //$NON-NLS-1$
+ } else
+ error= PatchMessages.getString("InputPatchPage.NoTextInClipboard.message"); //$NON-NLS-1$
+ } else
+ error= PatchMessages.getString("InputPatchPage.CouldNotReadClipboard.message"); //$NON-NLS-1$
+ } else {
+ String path= fPatchFileNameField.getText();
+ if (path != null && path.length() > 0) {
+ File file= new File(path);
+ gotPatch= file.exists() && file.isFile() && file.length() > 0;
+ if (!gotPatch)
+ error= PatchMessages.getString("InputPatchPage.CannotLocatePatch.message") + path; //$NON-NLS-1$
+ } else {
+ error= PatchMessages.getString("InputPatchPage.NoFileName.message"); //$NON-NLS-1$
+ }
+ }
+
+ setPageComplete(anySelected && gotPatch);
+ setErrorMessage(error);
+ }
+
+ protected void handlePatchFileBrowseButtonPressed() {
+ FileDialog dialog= new FileDialog(getShell(), SWT.NONE);
+ dialog.setText(PatchMessages.getString("InputPatchPage.SelectPatchFileDialog.title")); //$NON-NLS-1$
+ dialog.setFilterPath(getPatchFilePath());
+ String res= dialog.open();
+ if (res == null)
+ return;
+
+ String patchFilePath= dialog.getFileName();
+ IPath filterPath= new Path(dialog.getFilterPath());
+ IPath path= filterPath.append(patchFilePath).makeAbsolute();
+ patchFilePath= path.toOSString();
+ //fDialogSettings.put(IUIConstants.DIALOGSTORE_LASTEXTJAR, filterPath.toOSString());
+
+ fPatchFileNameField.setText(patchFilePath);
+ //setSourceName(patchFilePath);
+ }
+
+ /**
+ * Sets the source name of the import to be the supplied path.
+ * Adds the name of the path to the list of items in the
+ * source combo and selects it.
+ *
+ * @param path the path to be added
+ */
+ protected void setSourceName(String path) {
+
+ if (path.length() > 0) {
+
+ String[] currentItems= fPatchFileNameField.getItems();
+ int selectionIndex= -1;
+ for (int i= 0; i < currentItems.length; i++)
+ if (currentItems[i].equals(path))
+ selectionIndex= i;
+
+ if (selectionIndex < 0) { // not found in history
+ int oldLength= currentItems.length;
+ String[] newItems= new String[oldLength + 1];
+ System.arraycopy(currentItems, 0, newItems, 0, oldLength);
+ newItems[oldLength]= path;
+ fPatchFileNameField.setItems(newItems);
+ selectionIndex= oldLength;
+ }
+ fPatchFileNameField.select(selectionIndex);
+
+ //resetSelection();
+ }
+ }
+
+ /**
+ * The Finish button was pressed. Try to do the required work now and answer
+ * a boolean indicating success. If false is returned then the wizard will
+ * not close.
+ *
+ * @return boolean
+ */
+ public boolean finish() {
+// if (!ensureSourceIsValid())
+// return false;
+
+ saveWidgetValues();
+
+// Iterator resourcesEnum = getSelectedResources().iterator();
+// List fileSystemObjects = new ArrayList();
+// while (resourcesEnum.hasNext()) {
+// fileSystemObjects.add(
+// ((FileSystemElement) resourcesEnum.next()).getFileSystemObject());
+// }
+//
+// if (fileSystemObjects.size() > 0)
+// return importResources(fileSystemObjects);
+//
+// MessageDialog
+// .openInformation(
+// getContainer().getShell(),
+// DataTransferMessages.getString("DataTransfer.information"), //$NON-NLS-1$
+// DataTransferMessages.getString("FileImport.noneSelected")); //$NON-NLS-1$
+//
+// return false;
+
+ return true;
+ }
+
+ /**
+ * Use the dialog store to restore widget values to the values that they held
+ * last time this wizard was used to completion
+ */
+ private void restoreWidgetValues() {
+ IDialogSettings settings= getDialogSettings();
+ if (settings != null) {
+
+ // set 'Use Clipboard' radio button
+ setUseClipboard(settings.getBoolean(STORE_USE_CLIPBOARD_ID));
+
+ // set filenames history
+ String[] sourceNames= settings.getArray(STORE_PATCH_FILES_ID);
+ if (sourceNames != null)
+ for (int i= 0; i < sourceNames.length; i++)
+ if (sourceNames[i] != null && sourceNames[i].length() > 0)
+ fPatchFileNameField.add(sourceNames[i]);
+
+ // set patch file path
+ String patchFilePath= settings.get(STORE_PATCH_FILES_ID);
+ if (patchFilePath != null)
+ setSourceName(patchFilePath);
+ }
+ }
+
+ /**
+ * Since Finish was pressed, write widget values to the dialog store so that they
+ * will persist into the next invocation of this wizard page
+ */
+ void saveWidgetValues() {
+ IDialogSettings settings= getDialogSettings();
+ if (settings != null) {
+
+ settings.put(STORE_USE_CLIPBOARD_ID, getUseClipboard());
+ settings.put(STORE_PATCH_FILES_ID, getPatchFilePath());
+
+ // update source names history
+ String[] sourceNames= settings.getArray(STORE_PATCH_FILES_ID);
+ if (sourceNames == null)
+ sourceNames= new String[0];
+
+ sourceNames= addToHistory(sourceNames, getPatchFilePath());
+ settings.put(STORE_PATCH_FILES_ID, sourceNames);
+ }
+ }
+
+ // static helpers
+
+ private void setUseClipboard(boolean useClipboard) {
+ if (useClipboard)
+ fUseClipboardButton.setSelection(true);
+ else
+ fUsePatchFileButton.setSelection(true);
+ setEnablePatchFile(!useClipboard);
+ }
+
+ private boolean getUseClipboard() {
+ if (fUseClipboardButton != null)
+ return fUseClipboardButton.getSelection();
+ return false;
+ }
+
+ private String getPatchFilePath() {
+ if (fPatchFileNameField != null)
+ return fPatchFileNameField.getText();
+ return ""; //$NON-NLS-1$
+ }
+
+ /**
+ * Creates a new label with a bold font.
+ *
+ * @param parent the parent control
+ * @param text the label text
+ * @return the new label control
+ */
+ private static Label buildPlainLabel(Composite parent, String text) {
+ Label label= new Label(parent, SWT.NONE);
+ label.setText(text);
+ GridData data= new GridData();
+ data.verticalAlignment= GridData.FILL;
+ data.horizontalAlignment= GridData.FILL;
+ label.setLayoutData(data);
+ return label;
+ }
+
+ /**
+ * Adds an entry to a history, while taking care of duplicate history items
+ * and excessively long histories. The assumption is made that all histories
+ * should be of length COMBO_HISTORY_LENGTH
.
+ *
+ * @param history the current history
+ * @param newEntry the entry to add to the history
+ */
+ protected static String[] addToHistory(String[] history, String newEntry) {
+ java.util.ArrayList l= new java.util.ArrayList(java.util.Arrays.asList(history));
+
+ l.remove(newEntry);
+ l.add(0,newEntry);
+
+ // since only one new item was added, we can be over the limit
+ // by at most one item
+ if (l.size() > COMBO_HISTORY_LENGTH)
+ l.remove(COMBO_HISTORY_LENGTH);
+
+ return (String[]) l.toArray(new String[l.size()]);
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/LineReader.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/LineReader.java
new file mode 100644
index 000000000..98026451e
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/LineReader.java
@@ -0,0 +1,115 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.io.*;
+import java.util.*;
+
+import org.eclipse.jface.util.Assert;
+
+/* package */ class LineReader {
+
+ private boolean fHaveChar= false;
+ private int fLastChar;
+ private boolean fSawEOF= false;
+ private BufferedReader fReader;
+
+ /* package */ LineReader(BufferedReader reader) {
+ fReader= reader;
+ Assert.isNotNull(reader);
+ }
+
+ /**
+ * Reads a line of text. A line is considered to be terminated by any one
+ * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
+ * followed immediately by a linefeed.
+ * @return A string containing the contents of the line including
+ * the line-termination characters, or null
if the end of the
+ * stream has been reached
+ * @exception IOException If an I/O error occurs
+ */
+ /* package */ String readLine() throws IOException {
+ StringBuffer sb= null;
+
+ while (!fSawEOF) {
+ int c= readChar();
+ if (c == -1) {
+ fSawEOF= true;
+ break;
+ }
+ if (sb == null)
+ sb= new StringBuffer();
+ sb.append((char)c);
+ if (c == '\n')
+ break;
+ if (c == '\r') {
+ c= readChar();
+ if (c == -1) {
+ fSawEOF= true;
+ break; // EOF
+ }
+ if (c != '\n') {
+ fHaveChar= true;
+ fLastChar= c;
+ } else
+ sb.append((char)c);
+ break;
+ }
+ }
+
+ if (sb != null)
+ return sb.toString();
+ return null;
+ }
+
+ /* package */ void close() {
+ try {
+ fReader.close();
+ } catch (IOException ex) {
+ }
+ }
+
+ /* package */ List readLines() {
+ try {
+ List lines= new ArrayList();
+ String line;
+ while ((line= readLine()) != null)
+ lines.add(line);
+ return lines;
+ } catch (IOException ex) {
+ //System.out.println("error while reading file: " + fileName + "(" + ex + ")");
+ } finally {
+ close();
+ }
+ return null;
+ }
+ /**
+ * Returns the number of characters in the given string without
+ * counting a trailing line separator.
+ */
+ /* package */ int lineContentLength(String line) {
+ if (line == null)
+ return 0;
+ int length= line.length();
+ for (int i= length-1; i >= 0; i--) {
+ char c= line.charAt(i);
+ if (c =='\n' || c == '\r')
+ length--;
+ else
+ break;
+ }
+ return length;
+ }
+
+ //---- private
+
+ private int readChar() throws IOException {
+ if (fHaveChar) {
+ fHaveChar= false;
+ return fLastChar;
+ }
+ return fReader.read();
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchCompareInput.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchCompareInput.java
new file mode 100644
index 000000000..1f26392b3
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchCompareInput.java
@@ -0,0 +1,180 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.io.*;
+import java.io.ByteArrayInputStream;
+import java.text.MessageFormat;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.*;
+
+import org.eclipse.jface.viewers.*;
+
+import org.eclipse.compare.*;
+import org.eclipse.compare.structuremergeviewer.*;
+import org.eclipse.compare.internal.*;
+
+
+/**
+ * A PatchCompareInput uses a Patcher to
+ * patch selected workspace resources.
+ */
+/* package */ class PatchCompareInput extends CompareEditorInput {
+
+ static class Rejected extends DiffNode implements IStreamContentAccessor {
+ Diff fDiff;
+ String fName;
+ Rejected(IDiffContainer parent, String name, Diff diff) {
+ super(parent, Differencer.NO_CHANGE);
+ fName= name;
+ fDiff= diff;
+ }
+ public String getName() {
+ return fName + " *"; //$NON-NLS-1$
+ }
+ public String getType() {
+ return "txt"; //$NON-NLS-1$
+ }
+ public Image getImage() {
+ return CompareUI.getImage("file"); //$NON-NLS-1$
+ }
+ public InputStream getContents() {
+ return new ByteArrayInputStream(fDiff.fRejected.getBytes());
+ }
+ }
+
+ private DiffNode fRoot;
+ private IResource fTarget;
+ private Patcher fPatcher;
+
+ /**
+ * Creates an compare editor input for the given selection.
+ */
+ /* package */ PatchCompareInput(CompareConfiguration config, Patcher patcher, ISelection selection) {
+ super(config);
+ fPatcher= patcher;
+ IResource[] s= Utilities.getResources(selection);
+ if (s.length == 1)
+ fTarget= s[0];
+ }
+
+ /**
+ * Performs a two-way or three-way diff on the current selection.
+ */
+ public Object prepareInput(IProgressMonitor pm) throws InvocationTargetException {
+
+ CompareConfiguration cc= (CompareConfiguration) getCompareConfiguration();
+
+ try {
+ Diff[] diffs= fPatcher.getDiffs();
+
+ pm.beginTask(Utilities.getString("ResourceCompare.taskName"), diffs.length); //$NON-NLS-1$
+
+ fRoot= new DiffNode(0);
+ IContainer rootFolder= null;
+ if (fTarget instanceof IContainer)
+ rootFolder= (IContainer) fTarget;
+
+ for (int i= 0; i < diffs.length; i++) {
+ Diff diff= diffs[i];
+ if (diff.fIsEnabled) {
+ IPath path= fPatcher.getPath(diff);
+ createPath(fRoot, rootFolder, path, diff, false);
+
+ String rej= diff.fRejected;
+ if (rej != null) {
+ IPath pp= path.removeLastSegments(1);
+ pp= pp.append(path.lastSegment() + ".rej"); //$NON-NLS-1$
+ createPath(fRoot, rootFolder, pp, diff, true);
+ }
+ }
+ pm.worked(1);
+ }
+
+ fTarget.refreshLocal(IResource.DEPTH_INFINITE, pm);
+
+ String leftLabel= fTarget.getName();
+ cc.setLeftLabel(leftLabel);
+ cc.setLeftImage(CompareUIPlugin.getImage(fTarget));
+
+ String rformat= PatchMessages.getString("PatchCompareInput.RightTitle.format"); //$NON-NLS-1$
+ String rightLabel= MessageFormat.format(rformat, new String[] { fPatcher.getName() } );
+ cc.setRightLabel(rightLabel);
+ //cc.setRightImage(CompareUIPlugin.getImage(fRightResource));
+
+ String format= Utilities.getString("ResourceCompare.twoWay.title"); //$NON-NLS-1$
+ String title= MessageFormat.format(format, new String[] {leftLabel, rightLabel} );
+ setTitle(title);
+
+ return fRoot;
+
+ } catch (CoreException ex) {
+ throw new InvocationTargetException(ex);
+ } finally {
+ pm.done();
+ }
+ }
+
+ public void saveChanges(IProgressMonitor pm) throws CoreException {
+ if (fRoot instanceof DiffNode) {
+ try {
+ commit(pm, (DiffNode) fRoot);
+ } finally {
+ setDirty(false);
+ }
+ }
+ }
+
+ /*
+ * Recursively walks the diff tree and commits all changes.
+ */
+ private static void commit(IProgressMonitor pm, DiffNode node) throws CoreException {
+
+ ITypedElement left= node.getLeft();
+ if (left instanceof BufferedResourceNode)
+ ((BufferedResourceNode) left).commit(pm);
+
+ ITypedElement right= node.getRight();
+ if (right instanceof BufferedResourceNode)
+ ((BufferedResourceNode) right).commit(pm);
+
+ IDiffElement[] children= node.getChildren();
+ if (children != null) {
+ for (int i= 0; i < children.length; i++) {
+ IDiffElement element= children[i];
+ if (element instanceof DiffNode)
+ commit(pm, (DiffNode) element);
+ }
+ }
+ }
+
+ private void createPath(DiffContainer root, IContainer folder, IPath path, Diff diff, boolean reject) {
+ if (path.segmentCount() > 1) {
+ IFolder f= folder.getFolder(path.uptoSegment(1));
+ IDiffElement child= root.findChild(path.segment(0));
+ if (child == null) {
+ ResourceNode rn= new ResourceNode(f);
+ child= new DiffNode(root, Differencer.CHANGE, null, rn, rn);
+ }
+ if (child instanceof DiffContainer)
+ createPath((DiffContainer)child, f, path.removeFirstSegments(1), diff, reject);
+ } else {
+ // a leaf
+ BufferedResourceNode rn= new BufferedResourceNode(folder.getFile(path));
+ if (reject) {
+ new Rejected(root, path.segment(0), diff);
+ } else {
+ new DiffNode(root, diff.getType(), null, rn, new PatchedResource(rn, diff, path, fPatcher));
+ }
+ }
+ }
+}
+
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchErrorDialog.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchErrorDialog.java
new file mode 100644
index 000000000..cd4cb28a6
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchErrorDialog.java
@@ -0,0 +1,17 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+
+import org.eclipse.compare.internal.ListDialog;
+
+public class PatchErrorDialog {
+
+ private PatchErrorDialog() {
+ // no instance.
+ }
+
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java
new file mode 100644
index 000000000..8dce380cc
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java
@@ -0,0 +1,26 @@
+/*
+ * (c) Copyright IBM Corp. 2002.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class PatchMessages {
+
+ private static final String RESOURCE_BUNDLE= "org.eclipse.compare.internal.patch.PatchMessages";//$NON-NLS-1$
+
+ private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE);
+
+ private PatchMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties
new file mode 100644
index 000000000..e9aed4f47
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties
@@ -0,0 +1,73 @@
+# =====================================
+# (c) Copyright IBM Corp. 2002.
+# All Rights Reserved.
+# =====================================
+
+#
+# 'Compare with Patch' Action
+#
+PatchAction.ExceptionTitle=Saving Resources
+PatchAction.Exception=Unexpected exception. See log for details
+PatchAction.SavingDirtyEditorsTask=Saving dirty editors
+PatchAction.AlwaysSaveQuestion=&Always save all modified resources automatically prior to patching
+PatchAction.SaveAllQuestion=Save all modified resources
+PatchAction.SaveAllDescription=All modified resources must be saved before this operation.\nPress OK to confirm or Cancel otherwise
+
+#
+# PatchWizard
+#
+PatchWizard.title=Resource Patcher
+
+#
+# InputPatchPage
+#
+InputPatchPage.title= Patch Input Specification
+InputPatchPage.message= Define what resource to patch with which patch
+InputPatchPage.Clipboard=Clipboard
+InputPatchPage.SelectInput=Select a single file or folder to patch:
+InputPatchPage.PatchErrorDialog=Patch Error
+InputPatchPage.SelectPatch.title=Select Patch
+InputPatchPage.FileButton.text=File
+InputPatchPage.ChooseFileButton.text=Choose
+InputPatchPage.UseClipboardButton.text=Clipboard
+InputPatchPage.NothingSelected.message=Nothing selected to apply patch to
+InputPatchPage.ClipboardIsEmpty.message=Clipboard is empty
+InputPatchPage.NoTextInClipboard.message=Clipboard does not contain text
+InputPatchPage.CouldNotReadClipboard.message=Couldn\'t retrieve clipboard contents
+InputPatchPage.CannotLocatePatch.message=Can\'t locate patch file:
+InputPatchPage.NoFileName.message=No file name
+InputPatchPage.SelectPatchFileDialog.title=Select Patch File
+InputPatchPage.PatchFileNotFound.message=Patch file not found.
+InputPatchPage.ParseError.message=Error while parsing patch
+InputPatchPage.NoDiffsFound.message=No diffs found in
+
+#
+# PreviewPatchPage
+#
+PreviewPatchPage.title= Verify Patch
+PreviewPatchPage.message= The tree shows the contents of the patch.\nA checked item indicates that a patch could be applied succesfully. Uncheck an item if you want to exclude it.
+PreviewPatchPage.Left.title= Original
+PreviewPatchPage.Right.title= Result
+PreviewPatchPage.PatchOptions.title=Patch Options
+PreviewPatchPage.IgnoreSegments.text=Ignore leading path name segments:
+PreviewPatchPage.ReversePatch.text=Reverse Patch
+PreviewPatchPage.FuzzFactor.text=Maximum fuzz factor:
+PreviewPatchPage.FuzzFactor.tooltip=Allow context to shift this number of lines from the original place
+PreviewPatchPage.IgnoreWhitespace.text=Ignore Whitespace
+PreviewPatchPage.NoName.text=no name
+PreviewPatchPage.FileExists.error=(file already exists)
+PreviewPatchPage.FileDoesNotExist.error=(file doesn\'t exist)
+PreviewPatchPage.NoMatch.error=(no match)
+
+#
+# Patcher
+#
+Patcher.ErrorDialog.title=title
+Patcher.DeleteError.message=Error while deleting resource
+Patcher.UpdateError.message=Error while updating resource
+Patcher.RefreshError.message=Error while refreshing from local
+
+#
+# PatchCompareInput
+#
+PatchCompareInput.RightTitle.format= Patch: {0}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java
new file mode 100644
index 000000000..466b59a42
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java
@@ -0,0 +1,148 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.compare.*;
+import org.eclipse.compare.internal.*;
+import org.eclipse.compare.structuremergeviewer.Differencer;
+
+
+/* package */ class PatchWizard extends Wizard {
+
+ // dialog store id constants
+ private final static String DIALOG_SETTINGS_KEY= "PatchWizard"; //$NON-NLS-1$
+
+ private boolean fHasNewDialogSettings;
+
+ private InputPatchPage fPatchWizardPage;
+ private PreviewPatchPage fPreviewPatchPage;
+
+ private Patcher fPatcher;
+ private IResource fTarget;
+
+
+ /**
+ * Creates a wizard for applying a patch file to the workspace.
+ */
+ /* package */ PatchWizard(ISelection selection) {
+
+ fTarget= getResource(selection);
+
+ fPatcher= new Patcher();
+
+ setWindowTitle(PatchMessages.getString("PatchWizard.title")); //$NON-NLS-1$
+
+ IDialogSettings workbenchSettings= CompareUIPlugin.getDefault().getDialogSettings();
+ IDialogSettings section= workbenchSettings.getSection(DIALOG_SETTINGS_KEY); //$NON-NLS-1$
+ if (section == null)
+ fHasNewDialogSettings= true;
+ else {
+ fHasNewDialogSettings= false;
+ setDialogSettings(section);
+ }
+ }
+
+ static IResource getResource(ISelection selection) {
+ IResource[] rs= Utilities.getResources(selection);
+ if (rs != null && rs.length > 0)
+ return rs[0];
+ return null;
+ }
+
+ Patcher getPatcher() {
+ return fPatcher;
+ }
+
+ IResource getTarget() {
+ return fTarget;
+ }
+
+ void setTarget(IResource target) {
+ fTarget= target;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on IWizard.
+ */
+ public void addPages() {
+ super.addPages();
+
+ addPage(fPatchWizardPage= new InputPatchPage(this));
+ addPage(fPreviewPatchPage= new PreviewPatchPage(this));
+ }
+
+ /* (non-Javadoc)
+ * Method declared on IWizard.
+ */
+ public boolean performFinish() {
+
+ if (false) {
+ CompareConfiguration cc= new CompareConfiguration() {
+ public Image getImage(int kind) {
+ if (kind == Differencer.ADDITION)
+ kind= Differencer.DELETION;
+ else if (kind == Differencer.DELETION)
+ kind= Differencer.ADDITION;
+ return super.getImage(kind);
+ }
+ public Image getImage(Image base, int kind) {
+ if (kind == Differencer.ADDITION)
+ kind= Differencer.DELETION;
+ else if (kind == Differencer.DELETION)
+ kind= Differencer.ADDITION;
+ return super.getImage(base, kind);
+ }
+ };
+ cc.setProperty(CompareEditor.CONFIRM_SAVE_PROPERTY, new Boolean(false));
+
+ fPatcher.setName(fPatchWizardPage.getPatchName());
+
+ CompareUI.openCompareEditor(new PatchCompareInput(cc, fPatcher, new StructuredSelection(fTarget)));
+ } else {
+ fPatcher.setName(fPatchWizardPage.getPatchName());
+
+ try {
+ IRunnableWithProgress op= new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ fPatcher.applyAll(getTarget(), monitor);
+ }
+ };
+ new ProgressMonitorDialog(CompareUIPlugin.getShell()).run(true, true, op);
+ } catch (InvocationTargetException e) {
+ // handle exception
+ } catch (InterruptedException e) {
+ // handle cancelation
+ }
+ }
+
+ // Save the dialog settings
+ if (fHasNewDialogSettings) {
+ IDialogSettings workbenchSettings= CompareUIPlugin.getDefault().getDialogSettings();
+ IDialogSettings section= workbenchSettings.getSection(DIALOG_SETTINGS_KEY);
+ section= workbenchSettings.addNewSection(DIALOG_SETTINGS_KEY);
+ setDialogSettings(section);
+ }
+
+ fPatchWizardPage.saveWidgetValues();
+ //fPreviewPatchPage.saveWidgetValues();
+
+ return true;
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchedResource.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchedResource.java
new file mode 100644
index 000000000..5236f80e0
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchedResource.java
@@ -0,0 +1,69 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.io.*;
+
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.core.runtime.*;
+
+import org.eclipse.compare.*;
+
+
+/* package */ class PatchedResource implements ITypedElement, IStreamContentAccessor {
+
+ private Diff fDiff;
+ private IStreamContentAccessor fCurrent;
+ private IPath fPath;
+ private byte[] fContent;
+ private Patcher fPatcher;
+
+ /* package */ PatchedResource(IStreamContentAccessor current, Diff diff, IPath path, Patcher patcher) {
+ fDiff= diff;
+ fCurrent= current;
+ fPath= path;
+ fPatcher= patcher;
+ }
+
+ public InputStream getContents() throws CoreException {
+ if (fContent == null) {
+ InputStream is= null;
+
+ try {
+ is= fCurrent.getContents();
+ } catch (CoreException ex) {
+ is= new ByteArrayInputStream(new byte[0]);
+ }
+ if (is != null) {
+ BufferedReader br= new BufferedReader(new InputStreamReader(is));
+ String s= fPatcher.patch(fDiff,br, null);
+ if (s != null)
+ fContent= s.getBytes();
+ try {
+ is.close();
+ } catch (IOException ex) {
+ }
+ }
+ }
+ return new ByteArrayInputStream(fContent);
+ }
+
+ public Image getImage() {
+ return CompareUI.getImage(getType());
+ }
+
+ public String getName() {
+ return fPath.toOSString();
+ }
+
+ public String getType() {
+ String type= fPath.getFileExtension();
+ if (type != null)
+ return type;
+ return ITypedElement.UNKNOWN_TYPE;
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Patcher.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Patcher.java
new file mode 100644
index 000000000..c2d5264b3
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/Patcher.java
@@ -0,0 +1,948 @@
+package org.eclipse.compare.internal.patch;
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+import org.eclipse.jface.util.Assert;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.*;
+
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.compare.internal.ExceptionHandler;
+
+
+/**
+ * A Patcher
+ * - knows how to parse various patch file formats into some in-memory structure,
+ * - holds onto the parsed data and the options to use when applying the patches,
+ * - knows how to apply the patches to files and folders.
+ */
+public class Patcher {
+
+ private static final boolean DEBUG= false;
+
+ private static final String DEV_NULL= "/dev/null"; //$NON-NLS-1$
+
+ // diff formats
+ private static final int CONTEXT= 0;
+ private static final int ED= 1;
+ private static final int NORMAL= 2;
+ private static final int UNIFIED= 3;
+
+ // we recognize the following date/time formats
+ private static DateFormat[] DATE_FORMATS= new DateFormat[] {
+ new SimpleDateFormat("EEE MMM dd kk:mm:ss yyyy"), //$NON-NLS-1$
+ new SimpleDateFormat("yyyy/MM/dd kk:mm:ss"), //$NON-NLS-1$
+ new SimpleDateFormat("EEE MMM dd kk:mm:ss yyyy", Locale.US) //$NON-NLS-1$
+ };
+
+ private String fName;
+ private Diff[] fDiffs;
+ // patch options
+ private int fStripPrefixSegments;
+ private int fFuzz;
+ private boolean fIgnoreWhitespace;
+ private boolean fReverse= false;
+
+
+ Patcher() {
+ }
+
+ //---- options
+
+ void setName(String name) {
+ fName= name;
+ }
+
+ String getName() {
+ return fName;
+ }
+
+ /**
+ * Returns an array of Diffs after a sucessfull call to parse
.
+ * If parse
hasn't been called returns null
.
+ */
+ Diff[] getDiffs() {
+ return fDiffs;
+ }
+
+ IPath getPath(Diff diff) {
+ IPath path= diff.getPath();
+ if (fStripPrefixSegments > 0 && fStripPrefixSegments < path.segmentCount())
+ path= path.removeFirstSegments(fStripPrefixSegments);
+ return path;
+ }
+
+ /**
+ * Returns true
if new value differs from old.
+ */
+ boolean setStripPrefixSegments(int strip) {
+ if (strip != fStripPrefixSegments) {
+ fStripPrefixSegments= strip;
+ return true;
+ }
+ return false;
+ }
+
+ int getStripPrefixSegments() {
+ return fStripPrefixSegments;
+ }
+
+ /**
+ * Returns true
if new value differs from old.
+ */
+ boolean setFuzz(int fuzz) {
+ if (fuzz != fFuzz) {
+ fFuzz= fuzz;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true
if new value differs from old.
+ */
+ boolean setReversed(boolean reverse) {
+ if (fReverse != reverse) {
+ fReverse= reverse;
+
+ for (int i= 0; i < fDiffs.length; i++)
+ fDiffs[i].reverse();
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true
if new value differs from old.
+ */
+ boolean setIgnoreWhitespace(boolean ignoreWhitespace) {
+ if (ignoreWhitespace != fIgnoreWhitespace) {
+ fIgnoreWhitespace= ignoreWhitespace;
+ return true;
+ }
+ return false;
+ }
+
+ //---- parsing patch files
+
+ /* package */ void parse(BufferedReader reader) throws IOException {
+ List diffs= new ArrayList();
+ String line= null;
+ boolean reread= false;
+ String diffArgs= null;
+ String fileName= null;
+
+ LineReader lr= new LineReader(reader);
+
+ // read leading garbage
+ while (true) {
+ if (!reread)
+ line= lr.readLine();
+ reread= false;
+ if (line == null)
+ break;
+ if (line.length() < 4)
+ continue; // too short
+
+ // remember some infos
+ if (line.startsWith("Index: ")) { //$NON-NLS-1$
+ fileName= line.substring(7).trim();
+ continue;
+ }
+ if (line.startsWith("diff")) { //$NON-NLS-1$
+ diffArgs= line.substring(4).trim();
+ continue;
+ }
+
+ if (line.startsWith("--- ")) { //$NON-NLS-1$
+ line= readUnifiedDiff(diffs, lr, line, diffArgs, fileName);
+ diffArgs= fileName= null;
+ reread= true;
+ } else if (line.startsWith("*** ")) { //$NON-NLS-1$
+ line= readContextDiff(diffs, lr, line, diffArgs, fileName);
+ diffArgs= fileName= null;
+ reread= true;
+ }
+ }
+
+ lr.close();
+
+ fDiffs= (Diff[]) diffs.toArray((Diff[]) new Diff[diffs.size()]);
+ }
+
+ /**
+ * Returns the next line that does not belong to this diff
+ */
+ private String readUnifiedDiff(List diffs, LineReader reader, String line, String args, String fileName) throws IOException {
+
+ String[] oldArgs= split(line.substring(4));
+
+ // read info about new file
+ line= reader.readLine();
+ if (line == null || !line.startsWith("+++ ")) //$NON-NLS-1$
+ return line;
+
+ String[] newArgs= split(line.substring(4));
+
+ Diff diff= new Diff(extractPath(oldArgs, 0, fileName), extractDate(oldArgs, 1),
+ extractPath(newArgs, 0, fileName), extractDate(newArgs, 1));
+ diffs.add(diff);
+
+ int[] oldRange= new int[2];
+ int[] newRange= new int[2];
+ List lines= new ArrayList();
+
+ try {
+ // read lines of hunk
+ while (true) {
+
+ line= reader.readLine();
+ if (line == null)
+ return null;
+
+ if (reader.lineContentLength(line) == 0) {
+ lines.add(' ' + line);
+ continue;
+ }
+
+ char c= line.charAt(0);
+ switch (c) {
+ case '@':
+ if (line.startsWith("@@ ")) { //$NON-NLS-1$
+ // flush old hunk
+ if (lines.size() > 0) {
+ new Hunk(diff, oldRange, newRange, lines);
+ lines.clear();
+ }
+
+ // format: @@ -oldStart,oldLength +newStart,newLength @@
+ extractPair(line, '-', oldRange);
+ extractPair(line, '+', newRange);
+ continue;
+ }
+ break;
+ case ' ':
+ case '+':
+ case '-':
+ lines.add(line);
+ continue;
+ case '\\':
+ if (line.startsWith("No newline at end of file", 2)) { //$NON-NLS-1$
+ int lastIndex= lines.size();
+ if (lastIndex > 0) {
+ line= (String) lines.get(lastIndex-1);
+ int end= line.length()-1;
+ char lc= line.charAt(end);
+ if (lc == '\n') {
+ end--;
+ if (end > 0 && line.charAt(end-1) == '\r')
+ end--;
+ } else if (lc == '\r') {
+ end--;
+ }
+ line= line.substring(0, end);
+ lines.set(lastIndex-1, line);
+ }
+ continue;
+ }
+ break;
+ default:
+ if (DEBUG) {
+ int a1= c, a2= 0;
+ if (line.length() > 1)
+ a2= line.charAt(1);
+ System.out.println("char: " + a1 + " " + a2); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ break;
+ }
+ return line;
+ }
+ } finally {
+ if (lines.size() > 0)
+ new Hunk(diff, oldRange, newRange, lines);
+ diff.finish();
+ }
+ }
+
+ /**
+ * Returns the next line that does not belong to this diff
+ */
+ private String readContextDiff(List diffs, LineReader reader, String line, String args, String fileName) throws IOException {
+
+ String[] oldArgs= split(line.substring(4));
+
+ // read info about new file
+ line= reader.readLine();
+ if (line == null || !line.startsWith("--- ")) //$NON-NLS-1$
+ return line;
+
+ String[] newArgs= split(line.substring(4));
+
+ Diff diff= new Diff(extractPath(oldArgs, 0, fileName), extractDate(oldArgs, 1),
+ extractPath(newArgs, 0, fileName), extractDate(newArgs, 1));
+ diffs.add(diff);
+
+ int[] oldRange= new int[2];
+ int[] newRange= new int[2];
+ List oldLines= new ArrayList();
+ List newLines= new ArrayList();
+ List lines= oldLines;
+
+ try {
+ // read lines of hunk
+ while (true) {
+
+ line= reader.readLine();
+ if (line == null)
+ return line;
+
+ int l= line.length();
+ if (l == 0)
+ continue;
+ if (l > 1) {
+ switch (line.charAt(0)) {
+ case '*':
+ if (line.startsWith("***************")) { // new hunk //$NON-NLS-1$
+ // flush old hunk
+ if (oldLines.size() > 0 || newLines.size() > 0) {
+ new Hunk(diff, oldRange, newRange, unifyLines(oldLines, newLines));
+ oldLines.clear();
+ newLines.clear();
+ }
+ continue;
+ }
+ if (line.startsWith("*** ")) { // old range //$NON-NLS-1$
+ // format: *** oldStart,oldEnd ***
+ extractPair(line, ' ', oldRange);
+ oldRange[1]= oldRange[1]-oldRange[0]+1;
+ lines= oldLines;
+ continue;
+ }
+ break;
+ case ' ': // context line
+ case '+': // addition
+ case '!': // change
+ if (line.charAt(1) == ' ') {
+ lines.add(line);
+ continue;
+ }
+ break;
+ case '-':
+ if (line.charAt(1) == ' ') { // deletion
+ lines.add(line);
+ continue;
+ }
+ if (line.startsWith("--- ")) { // new range //$NON-NLS-1$
+ // format: *** newStart,newEnd ***
+ extractPair(line, ' ', newRange);
+ newRange[1]= newRange[1]-newRange[0]+1;
+ lines= newLines;
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return line;
+ }
+ } finally {
+ // flush last hunk
+ if (oldLines.size() > 0 || newLines.size() > 0)
+ new Hunk(diff, oldRange, newRange, unifyLines(oldLines, newLines));
+ diff.finish();
+ }
+ }
+
+ /**
+ * Creates a List of lines in the unified format from
+ * two Lists of lines in the 'classic' format.
+ */
+ private List unifyLines(List oldLines, List newLines) {
+ List result= new ArrayList();
+
+ String[] ol= (String[]) oldLines.toArray(new String[oldLines.size()]);
+ String[] nl= (String[]) newLines.toArray(new String[newLines.size()]);
+
+ int oi= 0, ni= 0;
+
+ while (true) {
+
+ char oc= 0;
+ String o= null;
+ if (oi < ol.length) {
+ o= ol[oi];
+ oc= o.charAt(0);
+ }
+
+ char nc= 0;
+ String n= null;
+ if (ni < nl.length) {
+ n= nl[ni];
+ nc= n.charAt(0);
+ }
+
+ // EOF
+ if (oc == 0 && nc == 0)
+ break;
+
+ // deletion in old
+ if (oc == '-') {
+ do {
+ result.add('-' + o.substring(2));
+ oi++;
+ if (oi >= ol.length)
+ break;
+ o= ol[oi];
+ } while (o.charAt(0) == '-');
+ continue;
+ }
+
+ // addition in new
+ if (nc == '+') {
+ do {
+ result.add('+' + n.substring(2));
+ ni++;
+ if (ni >= nl.length)
+ break;
+ n= nl[ni];
+ } while (n.charAt(0) == '+');
+ continue;
+ }
+
+ // differing lines on both sides
+ if (oc == '!' && nc == '!') {
+ // remove old
+ do {
+ result.add('-' + o.substring(2));
+ oi++;
+ if (oi >= ol.length)
+ break;
+ o= ol[oi];
+ } while (o.charAt(0) == '!');
+
+ // add new
+ do {
+ result.add('+' + n.substring(2));
+ ni++;
+ if (ni >= nl.length)
+ break;
+ n= nl[ni];
+ } while (n.charAt(0) == '!');
+
+ continue;
+ }
+
+ // context lines
+ if (oc == ' ' && nc == ' ') {
+ do {
+ Assert.isTrue(o.equals(n), "non matching context lines"); //$NON-NLS-1$
+ result.add(' ' + o.substring(2));
+ oi++;
+ ni++;
+ if (oi >= ol.length || ni >= nl.length)
+ break;
+ o= ol[oi];
+ n= nl[ni];
+ } while (o.charAt(0) == ' ' && n.charAt(0) == ' ');
+ continue;
+ }
+
+ if (oc == ' ') {
+ do {
+ result.add(' ' + o.substring(2));
+ oi++;
+ if (oi >= ol.length)
+ break;
+ o= ol[oi];
+ } while (o.charAt(0) == ' ');
+ continue;
+ }
+
+ if (nc == ' ') {
+ do {
+ result.add(' ' + n.substring(2));
+ ni++;
+ if (ni >= nl.length)
+ break;
+ n= nl[ni];
+ } while (n.charAt(0) == ' ');
+ continue;
+ }
+
+ Assert.isTrue(false, "unexpected char <" + oc + "> <" + nc + ">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ return result;
+ }
+
+ /**
+ * Breaks the given string into tab separated substrings.
+ * Leading and trailing whitespace is removed from each token.
+ */
+ private String[] split(String line) {
+ List l= new ArrayList();
+ StringTokenizer st= new StringTokenizer(line, "\t"); //$NON-NLS-1$
+ while (st.hasMoreElements()) {
+ String token= st.nextToken().trim();
+ if (token.length() > 0)
+ l.add(token);
+ }
+ return (String[]) l.toArray(new String[l.size()]);
+ }
+
+ /**
+ * @return the parsed time/date in milliseconds or -1 on error
+ */
+ private long extractDate(String[] args, int n) {
+ if (n < args.length) {
+ String line= args[n];
+ for (int i= 0; i < DATE_FORMATS.length; i++) {
+ DATE_FORMATS[i].setLenient(true);
+ try {
+ Date date= DATE_FORMATS[i].parse(line);
+ return date.getTime();
+ } catch (ParseException ex) {
+ }
+ }
+ // System.err.println("can't parse date: <" + line + ">");
+ }
+ return -1;
+ }
+
+ /**
+ * Returns null if file name is "/dev/null".
+ */
+ private IPath extractPath(String[] args, int n, String path2) {
+ if (n < args.length) {
+ String path= args[n];
+ if (DEV_NULL.equals(path))
+ return null;
+ int pos= path.lastIndexOf(':');
+ if (pos >= 0)
+ path= path.substring(0, pos);
+ if (path2 != null && !path2.equals(path)) {
+ if (DEBUG) System.out.println("path mismatch: " + path2); //$NON-NLS-1$
+ path= path2;
+ }
+ return new Path(path);
+ }
+ return null;
+ }
+
+ /**
+ * Tries to extract two integers separated by a comma.
+ * The parsing of the line starts at the position after
+ * the first occurrence of the given character start an ends
+ * at the first blank (or the end of the line).
+ * If only a single number is found this is assumed to be the length of the range.
+ * In this case the start of the range is set to 1.
+ * If an error occurs the range -1,-1 is returned.
+ */
+ private void extractPair(String line, char start, int[] pair) {
+ pair[0]= pair[1]= -1;
+ int startPos= line.indexOf(start);
+ if (startPos < 0) {
+ if (DEBUG) System.out.println("parsing error in extractPair: couldn't find \'" + start + "\'"); //$NON-NLS-1$ //$NON-NLS-2$
+ return;
+ }
+ line= line.substring(startPos+1);
+ int endPos= line.indexOf(' ');
+ if (endPos < 0) {
+ if (DEBUG) System.out.println("parsing error in extractPair: couldn't find end blank"); //$NON-NLS-1$
+ return;
+ }
+ line= line.substring(0, endPos);
+ int comma= line.indexOf(',');
+ if (comma >= 0) {
+ pair[0]= Integer.parseInt(line.substring(0, comma));
+ pair[1]= Integer.parseInt(line.substring(comma+1));
+ } else {
+ pair[0]= 1;
+ pair[1]= Integer.parseInt(line.substring(comma+1));
+ }
+ }
+
+ //---- applying a patch file
+
+ /**
+ * Tries to patch the given lines with the specified Diff.
+ * Any hunk that couldn't be applied is returned in the list failedHunks.
+ */
+ /* package */ void patch(Diff diff, List lines, List failedHunks) {
+
+ int shift= 0;
+ Iterator iter= diff.fHunks.iterator();
+ while (iter.hasNext()) {
+ Hunk hunk= (Hunk) iter.next();
+ shift= patch(hunk, lines, shift, failedHunks);
+ }
+ }
+
+ /**
+ * Tries to patch the contents of the given reader with the specified Diff.
+ * Any hunk that couldn't be applied is returned in the list failedHunks.
+ */
+ /* package */ String patch(Diff diff, BufferedReader reader, List failedHunks) {
+
+ List lines= new LineReader(reader).readLines();
+ if (lines == null)
+ lines= new ArrayList();
+
+ patch(diff, lines, failedHunks);
+
+ return createString(lines);
+ }
+
+ /**
+ * Tries to apply the specified hunk to the given lines.
+ * If the hunk cannot be applied at the original position
+ * the methods tries Fuzz lines before and after.
+ * If this fails the Hunk is added to the given list of failed hunks.
+ */
+ private int patch(Hunk hunk, List lines, int shift, List failedHunks) {
+ if (tryPatch(hunk, lines, shift)) {
+ shift+= doPatch(hunk, lines, shift);
+ } else {
+ boolean found= false;
+ int oldShift= shift;
+
+ for (int i= shift-1; i > shift-fFuzz; i--) {
+ if (tryPatch(hunk, lines, i)) {
+ shift= i;
+ found= true;
+ break;
+ }
+ }
+
+ if (! found) {
+ for (int i= shift+1; i < shift+fFuzz; i++) {
+ if (tryPatch(hunk, lines, i)) {
+ shift= i;
+ found= true;
+ break;
+ }
+ }
+ }
+
+ if (found) {
+ if (DEBUG) System.out.println("patched hunk at offset: " + (shift-oldShift)); //$NON-NLS-1$
+ shift+= doPatch(hunk, lines, shift);
+ } else {
+ if (failedHunks != null) {
+ if (DEBUG) System.out.println("failed hunk"); //$NON-NLS-1$
+ failedHunks.add(hunk);
+ }
+ }
+ oldShift= oldShift; // prevent compiler warning about unused local variable
+ }
+ return shift;
+ }
+
+ private boolean tryPatch(Hunk hunk, List lines, int shift) {
+ int pos= hunk.fOldStart + shift;
+ int contextMatches= 0;
+ int deleteMatches= 0;
+ for (int i= 0; i < hunk.fLines.length; i++) {
+ String s= hunk.fLines[i];
+ Assert.isTrue(s.length() > 0);
+ String line= s.substring(1);
+ char controlChar= s.charAt(0);
+ if (controlChar == ' ') { // context lines
+ while (true) {
+ if (pos < 0 || pos >= lines.size())
+ return false;
+ if (linesMatch(line, (String) lines.get(pos))) {
+ contextMatches++;
+ pos++;
+ break;
+ }
+ if (contextMatches <= 0)
+ return false;
+ pos++;
+ }
+ } else if (controlChar == '-') {
+ // deleted lines
+ while (true) {
+ if (pos < 0 || pos >= lines.size())
+ return false;
+ if (linesMatch(line, (String) lines.get(pos))) {
+ deleteMatches++;
+ pos++;
+ break;
+ }
+ if (deleteMatches <= 0)
+ return false;
+ pos++;
+ }
+ } else if (controlChar == '+') {
+ // added lines
+ // we don't have to do anything for a 'try'
+ } else
+ Assert.isTrue(false, "tryPatch: unknown control charcter: " + controlChar); //$NON-NLS-1$
+ }
+ return true;
+ }
+
+ private int doPatch(Hunk hunk, List lines, int shift) {
+ int pos= hunk.fOldStart + shift;
+ for (int i= 0; i < hunk.fLines.length; i++) {
+ String s= hunk.fLines[i];
+ Assert.isTrue(s.length() > 0);
+ String line= s.substring(1);
+ char controlChar= s.charAt(0);
+ if (controlChar == ' ') { // context lines
+ while (true) {
+ Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in context"); //$NON-NLS-1$
+ if (linesMatch(line, (String) lines.get(pos))) {
+ pos++;
+ break;
+ }
+ pos++;
+ }
+ } else if (controlChar == '-') {
+ // deleted lines
+ while (true) {
+ Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in deleted lines"); //$NON-NLS-1$
+ if (linesMatch(line, (String) lines.get(pos))) {
+ break;
+ }
+ pos++;
+ }
+ lines.remove(pos);
+ } else if (controlChar == '+') {
+ // added lines
+ lines.add(pos, line);
+ pos++;
+ } else
+ Assert.isTrue(false, "doPatch: unknown control charcter: " + controlChar); //$NON-NLS-1$
+ }
+ return hunk.fNewLength - hunk.fOldLength;
+ }
+
+ public void applyAll(IResource target, IProgressMonitor pm) {
+
+ final int WORK_UNIT= 10;
+
+ if (DEBUG) System.out.println("applyAll: start"); //$NON-NLS-1$
+
+ IFile file= null; // file to be patched
+ IContainer container= null;
+ if (target instanceof IContainer)
+ container= (IContainer) target;
+ else if (target instanceof IFile) {
+ file= (IFile) target;
+ container= file.getParent();
+ } else {
+ System.out.println("applyAll: not yet implemented"); //$NON-NLS-1$
+ return;
+ }
+
+ if (pm != null)
+ pm.beginTask("Patching", fDiffs.length*WORK_UNIT);
+
+ for (int i= 0; i < fDiffs.length; i++) {
+
+ int workTicks= WORK_UNIT;
+
+ Diff diff= fDiffs[i];
+ if (diff.fIsEnabled) {
+
+ IPath path= getPath(diff);
+ if (pm != null)
+ pm.subTask(path.toString());
+
+ if (container != null)
+ file= createPath(container, path);
+ List failed= new ArrayList();
+ List result= null;
+
+ int type= diff.getType();
+ switch (type) {
+ case Differencer.ADDITION:
+ // patch it and collect rejected hunks
+ result= apply(diff, file, true, failed);
+ updateFile(createString(result), file, new SubProgressMonitor(pm, workTicks));
+ workTicks-= WORK_UNIT;
+ break;
+ case Differencer.DELETION:
+ deleteFile(file, new SubProgressMonitor(pm, workTicks));
+ workTicks-= WORK_UNIT;
+ break;
+ case Differencer.CHANGE:
+ // patch it and collect rejected hunks
+ result= apply(diff, file, false, failed);
+ updateFile(createString(result), file, new SubProgressMonitor(pm, workTicks));
+ workTicks-= WORK_UNIT;
+ break;
+ }
+
+ if (failed.size() > 0) {
+ IPath pp= null;
+ if (path.segmentCount() > 1) {
+ pp= path.removeLastSegments(1);
+ pp= pp.append(path.lastSegment() + ".rej"); //$NON-NLS-1$
+ } else
+ pp= new Path(path.lastSegment() + ".rej"); //$NON-NLS-1$
+ file= createPath(container, pp);
+ updateFile(getRejected(failed), file, pm);
+ }
+ }
+
+ if (pm != null) {
+ if (pm.isCanceled())
+ break;
+ if (workTicks > 0)
+ pm.worked(workTicks);
+ }
+ }
+
+ /*
+ if (pm != null)
+ pm.subTask("Refreshing");
+ try {
+ target.refreshLocal(IResource.DEPTH_INFINITE, pm);
+ } catch (CoreException ex) {
+ ExceptionHandler.handle(ex,
+ PatchMessages.getString("Patcher.ErrorDialog.title"), //$NON-NLS-1$
+ PatchMessages.getString("Patcher.RefreshError.message")); //$NON-NLS-1$
+ }
+ */
+
+ // IWorkspace.validateEdit(IFile[], Object context);
+ }
+
+ List apply(Diff diff, IFile file, boolean create, List failedHunks) {
+
+ List lines= null;
+ if (!create && file != null) {
+ // read current contents
+ InputStream is= null;
+ try {
+ is= file.getContents();
+ BufferedReader reader= new BufferedReader(new InputStreamReader(is));
+ lines= new LineReader(reader).readLines();
+ if (DEBUG) System.out.println(" creating reader successful"); //$NON-NLS-1$
+ } catch(CoreException ex) {
+ if (DEBUG) System.out.println(" reading contents: " + ex); //$NON-NLS-1$
+ } finally {
+ if (is != null)
+ try {
+ is.close();
+ } catch(IOException ex) {
+ }
+ }
+ }
+
+ if (lines == null)
+ lines= new ArrayList();
+
+ patch(diff, lines, failedHunks);
+
+ return lines;
+ }
+
+ String getRejected(List failedHunks) {
+ if (failedHunks.size() <= 0)
+ return null;
+
+ StringBuffer sb= new StringBuffer();
+ Iterator iter= failedHunks.iterator();
+ while (iter.hasNext()) {
+ Hunk hunk= (Hunk) iter.next();
+ sb.append(hunk.getRejectedDescription());
+ sb.append('\n');
+ sb.append(hunk.getContent());
+ }
+ return sb.toString();
+ }
+
+ private void deleteFile(IFile file, IProgressMonitor pm) {
+ try {
+ file.delete(true, true, pm);
+ } catch (CoreException ex) {
+ ExceptionHandler.handle(ex,
+ PatchMessages.getString("Patcher.ErrorDialog.title"), //$NON-NLS-1$
+ PatchMessages.getString("Patcher.DeleteError.message")); //$NON-NLS-1$
+ }
+ }
+
+ private String createString(List lines) {
+ // convert the result into a String
+ StringBuffer sb= new StringBuffer();
+ Iterator iter= lines.iterator();
+ while (iter.hasNext())
+ sb.append((String)iter.next());
+ return sb.toString();
+ }
+
+ private void updateFile(String contents, IFile file, IProgressMonitor pm) {
+
+ // and save it
+ InputStream is= new ByteArrayInputStream(contents.getBytes());
+ try {
+ if (file.exists()) {
+ file.setContents(is, false, true, pm);
+ } else {
+ file.create(is, false, pm);
+ }
+ } catch (CoreException ex) {
+ ExceptionHandler.handle(ex,
+ PatchMessages.getString("Patcher.ErrorDialog.title"), //$NON-NLS-1$
+ PatchMessages.getString("Patcher.UpdateError.message")); //$NON-NLS-1$
+ } finally {
+ if (is != null)
+ try {
+ is.close();
+ } catch(IOException ex) {
+ }
+ }
+ }
+
+ private IFile createPath(IContainer folder, IPath path) {
+ if (path.segmentCount() > 1) {
+ IFolder f= folder.getFolder(path.uptoSegment(1));
+ //System.out.println("createPath: " + f + " " + f.exists());
+ return createPath(f, path.removeFirstSegments(1));
+ }
+ // a leaf
+ return folder.getFile(path);
+ }
+
+ private static String stripWhiteSpace(String s) {
+ StringBuffer sb= new StringBuffer();
+ int l= s.length();
+ for (int i= 0; i < l; i++) {
+ char c= s.charAt(i);
+ if (!Character.isWhitespace(c))
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Compares two strings.
+ * If fIgnoreWhitespace is true whitespace and line endings are ignored.
+ */
+ private boolean linesMatch(String line1, String line2) {
+ if (fIgnoreWhitespace)
+ return stripWhiteSpace(line1).equals(stripWhiteSpace(line2));
+ return line1.equals(line2);
+ }
+
+ /**
+ * Returns the length (exluding end-of-line characters) of the given string.
+ */
+ /* package */ static int length(String s) {
+ int l= s.length();
+ if (l > 0 && s.charAt(l-1) == '\n')
+ l--;
+ if (l > 1 && s.charAt(l-2) == '\r')
+ l--;
+ return l;
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage.java
new file mode 100644
index 000000000..99e82b5f6
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage.java
@@ -0,0 +1,497 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package org.eclipse.compare.internal.patch;
+
+import java.io.*;
+import java.util.*;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.wizard.WizardPage;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+
+import org.eclipse.compare.*;
+import org.eclipse.compare.internal.*;
+import org.eclipse.compare.structuremergeviewer.*;
+
+
+/**
+ * Shows the parsed patch file and any mismatches
+ * between files, hunks and the currently selected
+ * resources.
+ */
+/* package */ class PreviewPatchPage extends WizardPage {
+
+ /**
+ * Used with CompareInput
+ */
+ static class HunkInput implements ITypedElement, IStreamContentAccessor {
+ String fContent;
+ String fType;
+
+ HunkInput(String type, String s) {
+ fType= type;
+ fContent= s;
+ }
+ public Image getImage() {
+ return null;
+ }
+ public String getName() {
+ return PatchMessages.getString("PreviewPatchPage.NoName.text"); //$NON-NLS-1$
+ }
+ public String getType() {
+ return fType;
+ }
+ public InputStream getContents() {
+ return new ByteArrayInputStream(fContent.getBytes());
+ }
+ };
+
+ private PatchWizard fPatchWizard;
+
+ private Tree fTree;
+ private Combo fStripPrefixSegments;
+ private CompareViewerSwitchingPane fHunkViewer;
+ private Button fIgnoreWhitespaceButton;
+ private Button fReversePatchButton;
+ private Text fFuzzField;
+
+ private Image fNullImage;
+ private Image fAddImage;
+ private Image fDelImage;
+
+ private CompareConfiguration fCompareConfiguration;
+
+
+ /* package */ PreviewPatchPage(PatchWizard pw) {
+ super("PreviewPatchPage", PatchMessages.getString("PreviewPatchPage.title"), null); //$NON-NLS-1$ //$NON-NLS-2$
+
+ setMessage(PatchMessages.getString("PreviewPatchPage.message")); //$NON-NLS-1$
+
+ fPatchWizard= pw;
+ //setPageComplete(false);
+
+ int w= 16;
+ fNullImage= new DiffImage(null, null, w).createImage();
+ fAddImage= new DiffImage(null, CompareUIPlugin.getImageDescriptor("ovr16/add_ov.gif"), w).createImage(); //$NON-NLS-1$
+ fDelImage= new DiffImage(null, CompareUIPlugin.getImageDescriptor("ovr16/del_ov.gif"), w).createImage(); //$NON-NLS-1$
+
+ fCompareConfiguration= new CompareConfiguration();
+
+ fCompareConfiguration.setLeftEditable(false);
+ fCompareConfiguration.setLeftLabel(PatchMessages.getString("PreviewPatchPage.Left.title")); //$NON-NLS-1$
+
+ fCompareConfiguration.setRightEditable(false);
+ fCompareConfiguration.setRightLabel(PatchMessages.getString("PreviewPatchPage.Right.title")); //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * Method declared in WizardPage
+ */
+ public void setVisible(boolean visible) {
+ if (visible)
+ buildTree();
+ super.setVisible(visible);
+ }
+
+ Image getImage(Diff diff) {
+ switch (diff.getType()) {
+ case Differencer.ADDITION:
+ return fAddImage;
+ case Differencer.DELETION:
+ return fDelImage;
+ }
+ return fNullImage;
+ }
+
+ public void createControl(Composite parent) {
+
+ Composite composite= new Composite(parent, SWT.NULL);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));
+ setControl(composite);
+
+ buildPatchOptionsGroup(composite);
+
+ // top pane showing diffs and hunks in a check box tree
+ fTree= new Tree(composite, SWT.CHECK | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
+ GridData gd= new GridData();
+ gd.verticalAlignment= GridData.FILL;
+ gd.horizontalAlignment= GridData.FILL;
+ gd.grabExcessHorizontalSpace= true;
+ gd.grabExcessVerticalSpace= true;
+ fTree.setLayoutData(gd);
+
+ // bottom pane showing hunks in compare viewer
+ fHunkViewer= new CompareViewerSwitchingPane(composite, SWT.BORDER) {
+ protected Viewer getViewer(Viewer oldViewer, Object input) {
+ return CompareUI.findContentViewer(oldViewer, (ICompareInput)input, this, fCompareConfiguration);
+ }
+ };
+ gd= new GridData();
+ gd.verticalAlignment= GridData.FILL;
+ gd.horizontalAlignment= GridData.FILL;
+ gd.grabExcessHorizontalSpace= true;
+ gd.grabExcessVerticalSpace= true;
+ fHunkViewer.setLayoutData(gd);
+
+ // register listeners
+
+ fTree.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ TreeItem ti= (TreeItem) e.item;
+ Object data= e.item.getData();
+ if (e.detail == SWT.CHECK) {
+ boolean enabled= ti.getChecked();
+ if (data instanceof Hunk) {
+ ((Hunk)data).fIsEnabled= enabled;
+ updateGrayedState(ti);
+ } else if (data instanceof Diff) {
+ ((Diff)data).fIsEnabled= enabled;
+ updateCheckedState(ti);
+ }
+ } else {
+ if (data instanceof Hunk)
+ PreviewPatchPage.this.fHunkViewer.setInput(createInput((Hunk)data));
+ else
+ PreviewPatchPage.this.fHunkViewer.setInput(null);
+ }
+ }
+ }
+ );
+
+ // creating tree's content
+ buildTree();
+
+ // WorkbenchHelp.setHelp(composite, new DialogPageContextComputer(this, PATCH_HELP_CONTEXT_ID));
+ }
+
+ /**
+ * Create the group for setting various patch options
+ */
+ private void buildPatchOptionsGroup(Composite parent) {
+
+ final Patcher patcher= fPatchWizard.getPatcher();
+
+ Group group= new Group(parent, SWT.NONE);
+ group.setText(PatchMessages.getString("PreviewPatchPage.PatchOptions.title")); //$NON-NLS-1$
+ GridLayout layout= new GridLayout();
+ layout.numColumns= 5;
+ group.setLayout(layout);
+ group.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
+ //fPatchFileGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // 1st row
+ new Label(group, SWT.NONE).setText(PatchMessages.getString("PreviewPatchPage.IgnoreSegments.text")); //$NON-NLS-1$
+
+ fStripPrefixSegments= new Combo(group, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.SIMPLE);
+ int prefixCnt= patcher.getStripPrefixSegments();
+ String prefix= Integer.toString(prefixCnt);
+ fStripPrefixSegments.add(prefix);
+ fStripPrefixSegments.setText(prefix);
+
+ addSpacer(group);
+
+ fReversePatchButton= new Button(group, SWT.CHECK);
+ fReversePatchButton.setText(PatchMessages.getString("PreviewPatchPage.ReversePatch.text")); //$NON-NLS-1$
+
+ addSpacer(group);
+
+ // 2nd row
+ Label l= new Label(group, SWT.NONE);
+ l.setText(PatchMessages.getString("PreviewPatchPage.FuzzFactor.text")); //$NON-NLS-1$
+ l.setToolTipText(PatchMessages.getString("PreviewPatchPage.FuzzFactor.tooltip")); //$NON-NLS-1$
+ fFuzzField= new Text(group, SWT.BORDER);
+ fFuzzField.setText("2"); //$NON-NLS-1$
+ GridData gd2= new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
+ gd2.widthHint= 30;
+ fFuzzField.setLayoutData(gd2);
+
+ addSpacer(group);
+
+ fIgnoreWhitespaceButton= new Button(group, SWT.CHECK);
+ fIgnoreWhitespaceButton.setText(PatchMessages.getString("PreviewPatchPage.IgnoreWhitespace.text")); //$NON-NLS-1$
+
+ addSpacer(group);
+
+ // register listeners
+
+ if (fStripPrefixSegments != null)
+ fStripPrefixSegments.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (patcher.setStripPrefixSegments(getStripPrefixSegments()))
+ updateTree();
+ }
+ }
+ );
+ fReversePatchButton.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (patcher.setReversed(fReversePatchButton.getSelection()))
+ updateTree();
+ }
+ }
+ );
+ fIgnoreWhitespaceButton.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (patcher.setIgnoreWhitespace(fIgnoreWhitespaceButton.getSelection()))
+ updateTree();
+ }
+ }
+ );
+
+ fFuzzField.addModifyListener(
+ new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ if (patcher.setFuzz(getFuzzFactor()))
+ updateTree();
+ }
+ }
+ );
+ }
+
+ ICompareInput createInput(Hunk hunk) {
+
+ String[] lines= hunk.fLines;
+ StringBuffer left= new StringBuffer();
+ StringBuffer right= new StringBuffer();
+
+ for (int i= 0; i < lines.length; i++) {
+ String line= lines[i];
+ String rest= line.substring(1);
+ switch (line.charAt(0)) {
+ case ' ':
+ left.append(rest);
+ right.append(rest);
+ break;
+ case '-':
+ left.append(rest);
+ break;
+ case '+':
+ right.append(rest);
+ break;
+ }
+ }
+
+ Diff diff= hunk.fParent;
+ IPath path= diff.getPath();
+ String type= path.getFileExtension();
+
+ return new DiffNode(new HunkInput(type, left.toString()), new HunkInput(type, right.toString()));
+ }
+
+ /**
+ * Builds a tree from list of Diffs.
+ * As a side effect it calculates the maximum number of segments
+ * in all paths.
+ */
+ private void buildTree() {
+ setPageComplete(true);
+ if (fTree != null && !fTree.isDisposed()) {
+ fTree.removeAll();
+ fHunkViewer.setInput(null);
+
+ int length= 99;
+
+ Diff[] diffs= fPatchWizard.getPatcher().getDiffs();
+ if (diffs != null) {
+ for (int i= 0; i < diffs.length; i++) {
+ Diff diff= diffs[i];
+ TreeItem d= new TreeItem(fTree, SWT.NULL);
+ d.setData(diff);
+ d.setImage(getImage(diff));
+
+ if (diff.fOldPath != null)
+ length= Math.min(length, diff.fOldPath.segmentCount());
+ if (diff.fNewPath != null)
+ length= Math.min(length, diff.fNewPath.segmentCount());
+
+ java.util.List hunks= diff.fHunks;
+ java.util.Iterator iter= hunks.iterator();
+ while (iter.hasNext()) {
+ Hunk hunk= (Hunk) iter.next();
+ TreeItem h= new TreeItem(d, SWT.NULL);
+ h.setData(hunk);
+ h.setText(hunk.getDescription());
+ }
+ }
+ }
+ if (fStripPrefixSegments != null && length != 99)
+ for (int i= 1; i < length; i++)
+ fStripPrefixSegments.add(Integer.toString(i));
+ }
+
+ updateTree();
+ }
+
+ private IFile existsInSelection(IPath path) {
+ IResource target= fPatchWizard.getTarget();
+ if (target instanceof IFile) {
+ IFile file= (IFile) target;
+ IPath path2= file.getFullPath().removeFirstSegments(1);
+ //System.out.println("target: " + path2.toOSString());
+ //System.out.println(" path: " + path.toOSString());
+ if (path.equals(path2))
+ return file;
+// String name= file.getName();
+// if (path.lastSegment().equals(name))
+// return file;
+ } else if (target instanceof IContainer) {
+ IContainer c= (IContainer) target;
+ if (c.exists(path))
+ return c.getFile(path);
+ }
+ return null;
+ }
+
+ /**
+ * Updates label and checked state of tree items.
+ */
+ private void updateTree() {
+ if (fTree == null || fTree.isDisposed())
+ return;
+ int strip= getStripPrefixSegments();
+ TreeItem[] children= fTree.getItems();
+ for (int i= 0; i < children.length; i++) {
+ TreeItem item= children[i];
+ Diff diff= (Diff) item.getData();
+ String error= null;
+
+ boolean create= false;
+ IFile file= null;
+ if (diff.getType() == Differencer.ADDITION) {
+ IPath p= diff.fNewPath;
+ if (strip > 0 && strip < p.segmentCount())
+ p= p.removeFirstSegments(strip);
+ file= existsInSelection(p);
+ if (file == null) {
+ diff.fIsEnabled= true;
+ } else {
+ // file already exists
+ diff.fIsEnabled= false;
+ error= PatchMessages.getString("PreviewPatchPage.FileExists.error"); //$NON-NLS-1$
+ }
+ create= true;
+ } else {
+ IPath p= diff.fOldPath;
+ if (strip > 0 && strip < p.segmentCount())
+ p= p.removeFirstSegments(strip);
+ file= existsInSelection(p);
+ diff.fIsEnabled= file != null;
+ if (file != null) {
+ diff.fIsEnabled= true;
+ } else {
+ // file doesn't exist
+ diff.fIsEnabled= false;
+ error= PatchMessages.getString("PreviewPatchPage.FileDoesNotExist.error"); //$NON-NLS-1$
+ }
+ }
+
+ boolean checked= false;
+
+ ArrayList failedHunks= new ArrayList();
+ fPatchWizard.getPatcher().apply(diff, file, create, failedHunks);
+
+ if (failedHunks.size() > 0)
+ diff.fRejected= fPatchWizard.getPatcher().getRejected(failedHunks);
+
+ int checkedSubs= 0; // counts checked hunk items
+ TreeItem[] hunkItems= item.getItems();
+ for (int h= 0; h < hunkItems.length; h++) {
+ Hunk hunk= (Hunk) hunkItems[h].getData();
+ boolean failed= failedHunks.contains(hunk);
+ String hunkError= null;
+ if (failed)
+ hunkError= PatchMessages.getString("PreviewPatchPage.NoMatch.error"); //$NON-NLS-1$
+ hunk.fIsEnabled= diff.fIsEnabled && !failed;
+ hunkItems[h].setChecked(hunk.fIsEnabled);
+ if (hunk.fIsEnabled) {
+ checkedSubs++;
+ checked= true;
+ }
+ String hunkLabel= hunk.getDescription();
+ if (hunkError != null)
+ hunkLabel+= " " + hunkError; //$NON-NLS-1$
+ hunkItems[h].setText(hunkLabel);
+ }
+
+ String label= diff.getDescription(strip);
+ if (error != null)
+ label+= " " + error; //$NON-NLS-1$
+ item.setText(label);
+ item.setImage(getImage(diff));
+ item.setChecked(checked);
+ boolean gray= (checkedSubs > 0 && checkedSubs < hunkItems.length);
+ item.setGrayed(gray);
+ item.setExpanded(gray);
+ }
+ }
+
+ /**
+ * Updates the gray state of the given diff and the checked state of its children.
+ */
+ private void updateCheckedState(TreeItem diff) {
+ boolean checked= diff.getChecked();
+ diff.setGrayed(false);
+ TreeItem[] hunks= diff.getItems();
+ for (int i= 0; i < hunks.length; i++)
+ hunks[i].setChecked(checked);
+ }
+
+ /**
+ * Updates the gray state of the given items parent.
+ */
+ private void updateGrayedState(TreeItem hunk) {
+ TreeItem diff= hunk.getParentItem();
+ TreeItem[] hunks= diff.getItems();
+ int checked= 0;
+ for (int i= 0; i < hunks.length; i++)
+ if (hunks[i].getChecked())
+ checked++;
+ diff.setChecked(checked > 0);
+ diff.setGrayed(checked > 0 && checked < hunks.length);
+ }
+
+ private void addSpacer(Composite parent) {
+ Label label= new Label(parent, SWT.NONE);
+ GridData gd= new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint= 20;
+ label.setLayoutData(gd);
+ }
+
+ private int getStripPrefixSegments() {
+ int stripPrefixSegments= 0;
+ if (fStripPrefixSegments != null) {
+ String s= fStripPrefixSegments.getText();
+ try {
+ stripPrefixSegments= Integer.parseInt(s);
+ } catch(NumberFormatException ex) {
+ }
+ }
+ return stripPrefixSegments;
+ }
+
+ private int getFuzzFactor() {
+ int fuzzFactor= 0;
+ if (fFuzzField != null) {
+ String s= fFuzzField.getText();
+ try {
+ fuzzFactor= Integer.parseInt(s);
+ } catch(NumberFormatException ex) {
+ }
+ }
+ return fuzzFactor;
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/CompareWithPatchAction.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/CompareWithPatchAction.java
deleted file mode 100644
index 73c2021c1..000000000
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/CompareWithPatchAction.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Shell;
-
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.wizard.*;
-
-import org.eclipse.ui.IActionDelegate;
-
-import org.eclipse.compare.internal.CompareUIPlugin;
-
-
-public class CompareWithPatchAction implements IActionDelegate {
-
- static class PatchWizardDialog extends WizardDialog {
-
- PatchWizardDialog(Shell parent, IWizard wizard) {
- super(parent, wizard);
-
- setShellStyle(getShellStyle() | SWT.RESIZE);
- setMinimumPageSize(700, 500);
- }
- }
-
- private ISelection fSelection;
-
- public void run(IAction action) {
-
- PatchWizard wizard= new PatchWizard(fSelection);
- PatchWizardDialog wd= new PatchWizardDialog(CompareUIPlugin.getShell(), wizard);
- wd.open();
- }
-
- public void selectionChanged(IAction action, ISelection selection) {
- fSelection= selection;
- action.setEnabled(fSelection != null && !fSelection.isEmpty());
- }
-}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/Diff.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/Diff.java
deleted file mode 100644
index 77dc42e28..000000000
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/Diff.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import java.util.*;
-
-import org.eclipse.core.runtime.IPath;
-
-import org.eclipse.compare.structuremergeviewer.Differencer;
-
-
-/* package */ class Diff {
-
- IPath fOldPath, fNewPath;
- long fOldDate, fNewDate; // if 0: no file
- List fHunks= new ArrayList();
- boolean fIsEnabled= true;
- String fRejected;
-
-
- /* package */ Diff(IPath oldPath, long oldDate, IPath newPath, long newDate) {
- fOldPath= oldPath;
- fOldDate= oldPath == null ? 0 : oldDate;
- fNewPath= newPath;
- fNewDate= newPath == null ? 0 : newDate;
- }
-
- void reverse() {
- IPath tp= fOldPath;
- fOldPath= fNewPath;
- fNewPath= tp;
-
- long t= fOldDate;
- fOldDate= fNewDate;
- fNewDate= t;
-
- Iterator iter= fHunks.iterator();
- while (iter.hasNext()) {
- Hunk hunk= (Hunk) iter.next();
- hunk.reverse();
- }
- }
-
- Hunk[] getHunks() {
- return (Hunk[]) fHunks.toArray((Hunk[]) new Hunk[fHunks.size()]);
- }
-
- IPath getPath() {
- if (fOldPath != null)
- return fOldPath;
- return fNewPath;
- }
-
- void finish() {
- if (fHunks.size() == 1) {
- Hunk h= (Hunk) fHunks.get(0);
- if (h.fNewLength == 0) {
- fNewDate= 0;
- fNewPath= fOldPath;
- }
- }
- }
-
- /* package */ void add(Hunk hunk) {
- fHunks.add(hunk);
- }
-
- /* package */ int getType() {
- if (fOldDate == 0)
- return Differencer.ADDITION;
- if (fNewDate == 0)
- return Differencer.DELETION;
- return Differencer.CHANGE;
- }
-
- /* package */ String getDescription(int strip) {
- IPath path= fOldPath;
- if (fOldDate == 0)
- path= fNewPath;
- if (strip > 0 && strip < path.segmentCount())
- path= path.removeFirstSegments(strip);
- return path.toOSString();
- }
-}
-
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/Hunk.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/Hunk.java
deleted file mode 100644
index 6620af3a5..000000000
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/Hunk.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import java.util.List;
-
-import org.eclipse.jface.util.Assert;
-
-
-/**
- * A Hunk describes a range of changed lines and some context lines.
- */
-/* package */ class Hunk {
-
- Diff fParent;
- int fOldStart, fOldLength;
- int fNewStart, fNewLength;
- String[] fLines;
- boolean fIsEnabled= true;
-
-
- /* package */ Hunk(Diff parent, int[] oldRange, int[] newRange, List lines) {
-
- fParent= parent;
- if (fParent != null)
- fParent.add(this);
-
- if (oldRange[0] > 0)
- fOldStart= oldRange[0]-1; // line number start at 0!
- else
- fOldStart= 0;
- fOldLength= oldRange[1];
- if (newRange[0] > 0)
- fNewStart= newRange[0]-1; // line number start at 0!
- else
- fNewStart= 0;
- fNewLength= newRange[1];
-
- fLines= (String[]) lines.toArray(new String[lines.size()]);
- }
-
- void reverse() {
- int t= fOldStart;
- fOldStart= fNewStart;
- fNewStart= t;
-
- t= fOldLength;
- fOldLength= fNewLength;
- fNewLength= t;
-
- for (int i= 0; i < fLines.length; i++) {
- String line= fLines[i];
- char c= line.charAt(0);
- switch (c) {
- case '+':
- fLines[i]= '-' + line.substring(1);
- break;
- case '-':
- fLines[i]= '+' + line.substring(1);
- break;
- default:
- break;
- }
- }
- }
-
- /**
- * Returns the contents of this hunk.
- * Each line starts with a control character. Their meaning is as follows:
- * IResource
s that returns
- * only children of the given resource type.
- */
- private ITreeContentProvider getResourceProvider(final int resourceType) {
- return new WorkbenchContentProvider() {
- public Object[] getChildren(Object o) {
- if (o instanceof IContainer) {
- try {
- ArrayList results= new ArrayList();
- IResource[] members= ((IContainer)o).members();
- for (int i= 0; i < members.length; i++)
- // filter out the desired resource types
- if ((members[i].getType() & resourceType) != 0)
- results.add(members[i]);
- return results.toArray();
- } catch (CoreException e) {
- }
- }
- // just return an empty set of children
- return new Object[0];
- }
- };
- }
-
- /**
- * Updates the enable state of this page's controls.
- */
- private void updateWidgetEnablements() {
-
- String error= null;
-
- ISelection selection= fPatchTargets.getSelection();
- boolean anySelected= selection != null && !selection.isEmpty();
- if (!anySelected)
- error= "Nothing selected to apply patch to.";
-
- boolean gotPatch= false;
- if (getUseClipboard()) {
- Control c= getControl();
- if (c != null) {
- Clipboard clipboard= new Clipboard(c.getDisplay());
- Object o= clipboard.getContents(TextTransfer.getInstance());
- if (o instanceof String) {
- String s= ((String) o).trim();
- if (s.length() > 0)
- gotPatch= true;
- else
- error= "Clipboard is empty.";
- } else
- error= "Clipboard does not contain text.";
- } else
- error= "Couldn't retrieve clipboard contents.";
- } else {
- String path= fPatchFileNameField.getText();
- if (path != null && path.length() > 0) {
- File file= new File(path);
- gotPatch= file.exists() && file.isFile() && file.length() > 0;
- if (!gotPatch)
- error= "Can't locate patch file: " + path;
- } else {
- error= "No file name.";
- }
- }
-
- setPageComplete(anySelected && gotPatch);
- setErrorMessage(error);
- }
-
- protected void handlePatchFileBrowseButtonPressed() {
- FileDialog dialog= new FileDialog(getShell(), SWT.NONE);
- dialog.setText("Select Patch File");
- dialog.setFilterPath(getPatchFilePath());
- String res= dialog.open();
- if (res == null)
- return;
-
- String patchFilePath= dialog.getFileName();
- IPath filterPath= new Path(dialog.getFilterPath());
- IPath path= filterPath.append(patchFilePath).makeAbsolute();
- patchFilePath= path.toOSString();
- //fDialogSettings.put(IUIConstants.DIALOGSTORE_LASTEXTJAR, filterPath.toOSString());
-
- fPatchFileNameField.setText(patchFilePath);
- //setSourceName(patchFilePath);
- }
-
- /**
- * Sets the source name of the import to be the supplied path.
- * Adds the name of the path to the list of items in the
- * source combo and selects it.
- *
- * @param path the path to be added
- */
- protected void setSourceName(String path) {
-
- if (path.length() > 0) {
-
- String[] currentItems= fPatchFileNameField.getItems();
- int selectionIndex= -1;
- for (int i= 0; i < currentItems.length; i++)
- if (currentItems[i].equals(path))
- selectionIndex= i;
-
- if (selectionIndex < 0) { // not found in history
- int oldLength= currentItems.length;
- String[] newItems= new String[oldLength + 1];
- System.arraycopy(currentItems, 0, newItems, 0, oldLength);
- newItems[oldLength]= path;
- fPatchFileNameField.setItems(newItems);
- selectionIndex= oldLength;
- }
- fPatchFileNameField.select(selectionIndex);
-
- //resetSelection();
- }
- }
-
- /**
- * The Finish button was pressed. Try to do the required work now and answer
- * a boolean indicating success. If false is returned then the wizard will
- * not close.
- *
- * @return boolean
- */
- public boolean finish() {
-// if (!ensureSourceIsValid())
-// return false;
-
- saveWidgetValues();
-
-// Iterator resourcesEnum = getSelectedResources().iterator();
-// List fileSystemObjects = new ArrayList();
-// while (resourcesEnum.hasNext()) {
-// fileSystemObjects.add(
-// ((FileSystemElement) resourcesEnum.next()).getFileSystemObject());
-// }
-//
-// if (fileSystemObjects.size() > 0)
-// return importResources(fileSystemObjects);
-//
-// MessageDialog
-// .openInformation(
-// getContainer().getShell(),
-// DataTransferMessages.getString("DataTransfer.information"), //$NON-NLS-1$
-// DataTransferMessages.getString("FileImport.noneSelected")); //$NON-NLS-1$
-//
-// return false;
-
- return true;
- }
-
- /**
- * Use the dialog store to restore widget values to the values that they held
- * last time this wizard was used to completion
- */
- private void restoreWidgetValues() {
- IDialogSettings settings= getDialogSettings();
- if (settings != null) {
-
- // set 'Use Clipboard' radio button
- setUseClipboard(settings.getBoolean(STORE_USE_CLIPBOARD_ID));
-
- // set filenames history
- String[] sourceNames= settings.getArray(STORE_PATCH_FILES_ID);
- if (sourceNames != null)
- for (int i= 0; i < sourceNames.length; i++)
- if (sourceNames[i] != null && sourceNames[i].length() > 0)
- fPatchFileNameField.add(sourceNames[i]);
-
- // set patch file path
- String patchFilePath= settings.get(STORE_PATCH_FILES_ID);
- if (patchFilePath != null)
- setSourceName(patchFilePath);
- } else
- System.out.println("restoreWidgetValues: no dialog settings");
- }
-
- /**
- * Since Finish was pressed, write widget values to the dialog store so that they
- * will persist into the next invocation of this wizard page
- */
- void saveWidgetValues() {
- IDialogSettings settings= getDialogSettings();
- if (settings != null) {
-
- settings.put(STORE_USE_CLIPBOARD_ID, getUseClipboard());
- settings.put(STORE_PATCH_FILES_ID, getPatchFilePath());
-
- // update source names history
- String[] sourceNames= settings.getArray(STORE_PATCH_FILES_ID);
- if (sourceNames == null)
- sourceNames= new String[0];
-
- sourceNames= addToHistory(sourceNames, getPatchFilePath());
- settings.put(STORE_PATCH_FILES_ID, sourceNames);
- }
- }
-
- // static helpers
-
- private void setUseClipboard(boolean useClipboard) {
- if (useClipboard)
- fUseClipboardButton.setSelection(true);
- else
- fUsePatchFileButton.setSelection(true);
- setEnablePatchFile(!useClipboard);
- }
-
- private boolean getUseClipboard() {
- if (fUseClipboardButton != null)
- return fUseClipboardButton.getSelection();
- return false;
- }
-
- private String getPatchFilePath() {
- if (fPatchFileNameField != null)
- return fPatchFileNameField.getText();
- return "";
- }
-
- /**
- * Creates a new label with a bold font.
- *
- * @param parent the parent control
- * @param text the label text
- * @return the new label control
- */
- private static Label buildPlainLabel(Composite parent, String text) {
- Label label= new Label(parent, SWT.NONE);
- label.setText(text);
- GridData data= new GridData();
- data.verticalAlignment= GridData.FILL;
- data.horizontalAlignment= GridData.FILL;
- label.setLayoutData(data);
- return label;
- }
-
- /**
- * Adds an entry to a history, while taking care of duplicate history items
- * and excessively long histories. The assumption is made that all histories
- * should be of length COMBO_HISTORY_LENGTH
.
- *
- * @param history the current history
- * @param newEntry the entry to add to the history
- */
- protected static String[] addToHistory(String[] history, String newEntry) {
- java.util.ArrayList l= new java.util.ArrayList(java.util.Arrays.asList(history));
-
- l.remove(newEntry);
- l.add(0,newEntry);
-
- // since only one new item was added, we can be over the limit
- // by at most one item
- if (l.size() > COMBO_HISTORY_LENGTH)
- l.remove(COMBO_HISTORY_LENGTH);
-
- return (String[]) l.toArray(new String[l.size()]);
- }
-}
-
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/LineReader.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/LineReader.java
deleted file mode 100644
index 4306e63ea..000000000
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/LineReader.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import java.io.*;
-import java.util.*;
-
-import org.eclipse.jface.util.Assert;
-
-/* package */ class LineReader {
-
- private boolean fHaveChar= false;
- private int fLastChar;
- private boolean fSawEOF= false;
- private BufferedReader fReader;
-
- /* package */ LineReader(BufferedReader reader) {
- fReader= reader;
- Assert.isNotNull(reader);
- }
-
- /**
- * Reads a line of text. A line is considered to be terminated by any one
- * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
- * followed immediately by a linefeed.
- * @return A string containing the contents of the line including
- * the line-termination characters, or null
if the end of the
- * stream has been reached
- * @exception IOException If an I/O error occurs
- */
- /* package */ String readLine() throws IOException {
- StringBuffer sb= null;
-
- while (!fSawEOF) {
- int c= readChar();
- if (c == -1) {
- fSawEOF= true;
- break;
- }
- if (sb == null)
- sb= new StringBuffer();
- sb.append((char)c);
- if (c == '\n')
- break;
- if (c == '\r') {
- c= readChar();
- if (c == -1) {
- fSawEOF= true;
- break; // EOF
- }
- if (c != '\n') {
- fHaveChar= true;
- fLastChar= c;
- } else
- sb.append((char)c);
- break;
- }
- }
-
- if (sb != null)
- return sb.toString();
- return null;
- }
-
- /* package */ void close() {
- try {
- fReader.close();
- } catch (IOException ex) {
- }
- }
-
- /* package */ List readLines() {
- try {
- List lines= new ArrayList();
- String line;
- while ((line= readLine()) != null)
- lines.add(line);
- return lines;
- } catch (IOException ex) {
- //System.out.println("error while reading file: " + fileName + "(" + ex + ")");
- } finally {
- close();
- }
- return null;
- }
- /**
- * Returns the number of characters in the given string without
- * counting a trailing line separator.
- */
- /* package */ int lineContentLength(String line) {
- if (line == null)
- return 0;
- int length= line.length();
- for (int i= length-1; i >= 0; i--) {
- char c= line.charAt(i);
- if (c =='\n' || c == '\r')
- length--;
- else
- break;
- }
- return length;
- }
-
- //---- private
-
- private int readChar() throws IOException {
- if (fHaveChar) {
- fHaveChar= false;
- return fLastChar;
- }
- return fReader.read();
- }
-}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchCompareInput.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchCompareInput.java
deleted file mode 100644
index 47f73dc24..000000000
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchCompareInput.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import java.io.*;
-import java.io.ByteArrayInputStream;
-import java.text.MessageFormat;
-import java.lang.reflect.InvocationTargetException;
-
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Composite;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.core.resources.*;
-
-import org.eclipse.jface.viewers.*;
-
-import org.eclipse.compare.*;
-import org.eclipse.compare.structuremergeviewer.*;
-import org.eclipse.compare.internal.*;
-
-
-/**
- * A PatchCompareInput uses a Patcher to
- * patch selected workspace resources.
- */
-/* package */ class PatchCompareInput extends CompareEditorInput {
-
- static class Rejected extends DiffNode implements IStreamContentAccessor {
- Diff fDiff;
- String fName;
- Rejected(IDiffContainer parent, String name, Diff diff) {
- super(parent, Differencer.NO_CHANGE);
- fName= name;
- fDiff= diff;
- }
- public String getName() {
- return fName + " *";
- }
- public String getType() {
- return "txt";
- }
- public Image getImage() {
- return CompareUI.getImage("file");
- }
- public InputStream getContents() {
- return new ByteArrayInputStream(fDiff.fRejected.getBytes());
- }
- }
-
- private DiffNode fRoot;
- private IResource fTarget;
- private Patcher fPatcher;
-
- /**
- * Creates an compare editor input for the given selection.
- */
- /* package */ PatchCompareInput(CompareConfiguration config, Patcher patcher, ISelection selection) {
- super(config);
- fPatcher= patcher;
- IResource[] s= Utilities.getResources(selection);
- if (s.length == 1)
- fTarget= s[0];
- }
-
- /**
- * Performs a two-way or three-way diff on the current selection.
- */
- public Object prepareInput(IProgressMonitor pm) throws InvocationTargetException {
-
- CompareConfiguration cc= (CompareConfiguration) getCompareConfiguration();
-
- try {
- Diff[] diffs= fPatcher.getDiffs();
-
- pm.beginTask(Utilities.getString("ResourceCompare.taskName"), diffs.length); //$NON-NLS-1$
-
- fRoot= new DiffNode(0);
- IContainer rootFolder= null;
- if (fTarget instanceof IContainer)
- rootFolder= (IContainer) fTarget;
-
- for (int i= 0; i < diffs.length; i++) {
- Diff diff= diffs[i];
- if (diff.fIsEnabled) {
- IPath path= fPatcher.getPath(diff);
- createPath(fRoot, rootFolder, path, diff, false);
-
- String rej= diff.fRejected;
- if (rej != null) {
- IPath pp= path.removeLastSegments(1);
- pp= pp.append(path.lastSegment() + ".rej");
- createPath(fRoot, rootFolder, pp, diff, true);
- }
- }
- pm.worked(1);
- }
-
- fTarget.refreshLocal(IResource.DEPTH_INFINITE, pm);
-
- String leftLabel= fTarget.getName();
- cc.setLeftLabel(leftLabel);
- cc.setLeftImage(CompareUIPlugin.getImage(fTarget));
-
- String rightLabel= "Patch: " + fPatcher.getName();
- cc.setRightLabel(rightLabel);
- //cc.setRightImage(CompareUIPlugin.getImage(fRightResource));
-
- String format= Utilities.getString("ResourceCompare.twoWay.title"); //$NON-NLS-1$
- String title= MessageFormat.format(format, new String[] {leftLabel, rightLabel} );
- setTitle(title);
-
- return fRoot;
-
- } catch (CoreException ex) {
- throw new InvocationTargetException(ex);
- } finally {
- pm.done();
- }
- }
-
- public void saveChanges(IProgressMonitor pm) throws CoreException {
- if (fRoot instanceof DiffNode) {
- try {
- commit(pm, (DiffNode) fRoot);
- } finally {
- setDirty(false);
- }
- }
- }
-
- /*
- * Recursively walks the diff tree and commits all changes.
- */
- private static void commit(IProgressMonitor pm, DiffNode node) throws CoreException {
-
- ITypedElement left= node.getLeft();
- if (left instanceof BufferedResourceNode)
- ((BufferedResourceNode) left).commit(pm);
-
- ITypedElement right= node.getRight();
- if (right instanceof BufferedResourceNode)
- ((BufferedResourceNode) right).commit(pm);
-
- IDiffElement[] children= node.getChildren();
- if (children != null) {
- for (int i= 0; i < children.length; i++) {
- IDiffElement element= children[i];
- if (element instanceof DiffNode)
- commit(pm, (DiffNode) element);
- }
- }
- }
-
- private void createPath(DiffContainer root, IContainer folder, IPath path, Diff diff, boolean reject) {
- if (path.segmentCount() > 1) {
- IFolder f= folder.getFolder(path.uptoSegment(1));
- IDiffElement child= root.findChild(path.segment(0));
- if (child == null) {
- ResourceNode rn= new ResourceNode(f);
- child= new DiffNode(root, Differencer.CHANGE, null, rn, rn);
- }
- if (child instanceof DiffContainer)
- createPath((DiffContainer)child, f, path.removeFirstSegments(1), diff, reject);
- } else {
- // a leaf
- BufferedResourceNode rn= new BufferedResourceNode(folder.getFile(path));
- if (reject) {
- new Rejected(root, path.segment(0), diff);
- } else {
- new DiffNode(root, diff.getType(), null, rn, new PatchedResource(rn, diff, path, fPatcher));
- }
- }
- }
-}
-
-
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchWizard.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchWizard.java
deleted file mode 100644
index 8fc93f312..000000000
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchWizard.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import org.eclipse.swt.graphics.Image;
-
-import org.eclipse.jface.dialogs.IDialogSettings;
-import org.eclipse.jface.viewers.*;
-import org.eclipse.jface.wizard.Wizard;
-
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.NullProgressMonitor;
-
-import org.eclipse.compare.*;
-import org.eclipse.compare.internal.*;
-import org.eclipse.compare.structuremergeviewer.Differencer;
-
-
-/* package */ class PatchWizard extends Wizard {
-
- // dialog store id constants
- private final static String DIALOG_SETTINGS_KEY= "PatchWizard"; //$NON-NLS-1$
-
- private boolean fHasNewDialogSettings;
-
- private InputPatchPage fPatchWizardPage;
- private PreviewPatchPage fPreviewPatchPage;
-
- private Patcher fPatcher;
- private IResource fTarget;
-
-
- /**
- * Creates a wizard for applying a patch file to the workspace.
- */
- /* package */ PatchWizard(ISelection selection) {
-
- fTarget= getResource(selection);
-
- fPatcher= new Patcher();
-
- setWindowTitle("Resource Patcher");
-
- IDialogSettings workbenchSettings= CompareUIPlugin.getDefault().getDialogSettings();
- IDialogSettings section= workbenchSettings.getSection(DIALOG_SETTINGS_KEY); //$NON-NLS-1$
- if (section == null)
- fHasNewDialogSettings= true;
- else {
- fHasNewDialogSettings= false;
- setDialogSettings(section);
- }
- }
-
- static IResource getResource(ISelection selection) {
- IResource[] rs= Utilities.getResources(selection);
- if (rs != null && rs.length > 0)
- return rs[0];
- return null;
- }
-
- Patcher getPatcher() {
- return fPatcher;
- }
-
- IResource getTarget() {
- return fTarget;
- }
-
- void setTarget(IResource target) {
- fTarget= target;
- }
-
- /* (non-Javadoc)
- * Method declared on IWizard.
- */
- public void addPages() {
- super.addPages();
-
- addPage(fPatchWizardPage= new InputPatchPage(this));
- addPage(fPreviewPatchPage= new PreviewPatchPage(this));
- }
-
- /* (non-Javadoc)
- * Method declared on IWizard.
- */
- public boolean performFinish() {
-
- if (false) {
- CompareConfiguration cc= new CompareConfiguration() {
- public Image getImage(int kind) {
- if (kind == Differencer.ADDITION)
- kind= Differencer.DELETION;
- else if (kind == Differencer.DELETION)
- kind= Differencer.ADDITION;
- return super.getImage(kind);
- }
- public Image getImage(Image base, int kind) {
- if (kind == Differencer.ADDITION)
- kind= Differencer.DELETION;
- else if (kind == Differencer.DELETION)
- kind= Differencer.ADDITION;
- return super.getImage(base, kind);
- }
- };
- cc.setProperty(CompareEditor.CONFIRM_SAVE_PROPERTY, new Boolean(false));
-
- fPatcher.setName(fPatchWizardPage.getPatchName());
-
- CompareUI.openCompareEditor(new PatchCompareInput(cc, fPatcher, new StructuredSelection(fTarget)));
- } else {
- fPatcher.setName(fPatchWizardPage.getPatchName());
- fPatcher.applyAll(getTarget(), new NullProgressMonitor());
- }
-
- // Save the dialog settings
- if (fHasNewDialogSettings) {
- IDialogSettings workbenchSettings= CompareUIPlugin.getDefault().getDialogSettings();
- IDialogSettings section= workbenchSettings.getSection(DIALOG_SETTINGS_KEY);
- section= workbenchSettings.addNewSection(DIALOG_SETTINGS_KEY);
- setDialogSettings(section);
- }
-
- fPatchWizardPage.saveWidgetValues();
- //fPreviewPatchPage.saveWidgetValues();
-
- return true;
- }
-}
-
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchedResource.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchedResource.java
deleted file mode 100644
index 9e8a36156..000000000
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PatchedResource.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import java.io.*;
-
-import org.eclipse.swt.graphics.Image;
-
-import org.eclipse.core.runtime.*;
-
-import org.eclipse.compare.*;
-
-
-/* package */ class PatchedResource implements ITypedElement, IStreamContentAccessor {
-
- private Diff fDiff;
- private IStreamContentAccessor fCurrent;
- private IPath fPath;
- private byte[] fContent;
- private Patcher fPatcher;
-
- /* package */ PatchedResource(IStreamContentAccessor current, Diff diff, IPath path, Patcher patcher) {
- fDiff= diff;
- fCurrent= current;
- fPath= path;
- fPatcher= patcher;
- }
-
- public InputStream getContents() throws CoreException {
- if (fContent == null) {
- InputStream is= null;
-
- try {
- is= fCurrent.getContents();
- } catch (CoreException ex) {
- is= new ByteArrayInputStream(new byte[0]);
- }
- if (is != null) {
- BufferedReader br= new BufferedReader(new InputStreamReader(is));
- String s= fPatcher.patch(fDiff,br, null);
- if (s != null)
- fContent= s.getBytes();
- try {
- is.close();
- } catch (IOException ex) {
- }
- }
- }
- return new ByteArrayInputStream(fContent);
- }
-
- public Image getImage() {
- return CompareUI.getImage(getType());
- }
-
- public String getName() {
- return fPath.toOSString();
- }
-
- public String getType() {
- String type= fPath.getFileExtension();
- if (type != null)
- return type;
- return ITypedElement.UNKNOWN_TYPE;
- }
-}
-
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/Patcher.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/Patcher.java
deleted file mode 100644
index 36f8ac677..000000000
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/Patcher.java
+++ /dev/null
@@ -1,906 +0,0 @@
-package org.eclipse.compare.patch;
-
-import java.io.*;
-import java.text.*;
-import java.util.*;
-
-import org.eclipse.jface.util.Assert;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.core.resources.*;
-
-import org.eclipse.compare.structuremergeviewer.Differencer;
-
-
-/**
- * A Patcher
- * - knows how to parse various patch file formats into some in-memory structure,
- * - holds onto the parsed data and the options to use when applying the patches,
- * - knows how to apply the patches to files and folders.
- */
-public class Patcher {
-
- private static final boolean DEBUG= false;
-
- private static final String DEV_NULL= "/dev/null"; //$NON-NLS-1$
-
- // diff formats
- private static final int CONTEXT= 0;
- private static final int ED= 1;
- private static final int NORMAL= 2;
- private static final int UNIFIED= 3;
-
- // we recognize the following date/time formats
- private static DateFormat[] DATE_FORMATS= new DateFormat[] {
- new SimpleDateFormat("EEE MMM dd kk:mm:ss yyyy"), //$NON-NLS-1$
- new SimpleDateFormat("yyyy/MM/dd kk:mm:ss"), //$NON-NLS-1$
- new SimpleDateFormat("EEE MMM dd kk:mm:ss yyyy", Locale.US) //$NON-NLS-1$
- };
-
- private String fName;
- private Diff[] fDiffs;
- // patch options
- private int fStripPrefixSegments;
- private int fFuzz;
- private boolean fIgnoreWhitespace;
- private boolean fReverse= false;
-
-
- Patcher() {
- }
-
- //---- options
-
- void setName(String name) {
- fName= name;
- }
-
- String getName() {
- return fName;
- }
-
- /**
- * Returns an array of Diffs after a sucessfull call to parse
.
- * If parse
hasn't been called returns null
.
- */
- Diff[] getDiffs() {
- return fDiffs;
- }
-
- IPath getPath(Diff diff) {
- IPath path= diff.getPath();
- if (fStripPrefixSegments > 0 && fStripPrefixSegments < path.segmentCount())
- path= path.removeFirstSegments(fStripPrefixSegments);
- return path;
- }
-
- /**
- * Returns true
if new value differs from old.
- */
- boolean setStripPrefixSegments(int strip) {
- if (strip != fStripPrefixSegments) {
- fStripPrefixSegments= strip;
- return true;
- }
- return false;
- }
-
- int getStripPrefixSegments() {
- return fStripPrefixSegments;
- }
-
- /**
- * Returns true
if new value differs from old.
- */
- boolean setFuzz(int fuzz) {
- if (fuzz != fFuzz) {
- fFuzz= fuzz;
- return true;
- }
- return false;
- }
-
- /**
- * Returns true
if new value differs from old.
- */
- boolean setReversed(boolean reverse) {
- if (fReverse != reverse) {
- fReverse= reverse;
-
- for (int i= 0; i < fDiffs.length; i++)
- fDiffs[i].reverse();
-
- return true;
- }
- return false;
- }
-
- /**
- * Returns true
if new value differs from old.
- */
- boolean setIgnoreWhitespace(boolean ignoreWhitespace) {
- if (ignoreWhitespace != fIgnoreWhitespace) {
- fIgnoreWhitespace= ignoreWhitespace;
- return true;
- }
- return false;
- }
-
- //---- parsing patch files
-
- /* package */ void parse(BufferedReader reader) throws IOException {
- List diffs= new ArrayList();
- String line= null;
- boolean reread= false;
- String diffArgs= null;
- String fileName= null;
-
- LineReader lr= new LineReader(reader);
-
- // read leading garbage
- while (true) {
- if (!reread)
- line= lr.readLine();
- reread= false;
- if (line == null)
- break;
- if (line.length() < 4)
- continue; // too short
-
- // remember some infos
- if (line.startsWith("Index: ")) { //$NON-NLS-1$
- fileName= line.substring(7).trim();
- continue;
- }
- if (line.startsWith("diff")) { //$NON-NLS-1$
- diffArgs= line.substring(4).trim();
- continue;
- }
-
- if (line.startsWith("--- ")) { //$NON-NLS-1$
- line= readUnifiedDiff(diffs, lr, line, diffArgs, fileName);
- diffArgs= fileName= null;
- reread= true;
- } else if (line.startsWith("*** ")) { //$NON-NLS-1$
- line= readContextDiff(diffs, lr, line, diffArgs, fileName);
- diffArgs= fileName= null;
- reread= true;
- }
- }
-
- lr.close();
-
- fDiffs= (Diff[]) diffs.toArray((Diff[]) new Diff[diffs.size()]);
- }
-
- /**
- * Returns the next line that does not belong to this diff
- */
- private String readUnifiedDiff(List diffs, LineReader reader, String line, String args, String fileName) throws IOException {
-
- String[] oldArgs= split(line.substring(4));
-
- // read info about new file
- line= reader.readLine();
- if (line == null || !line.startsWith("+++ ")) //$NON-NLS-1$
- return line;
-
- String[] newArgs= split(line.substring(4));
-
- Diff diff= new Diff(extractPath(oldArgs, 0, fileName), extractDate(oldArgs, 1),
- extractPath(newArgs, 0, fileName), extractDate(newArgs, 1));
- diffs.add(diff);
-
- int[] oldRange= new int[2];
- int[] newRange= new int[2];
- List lines= new ArrayList();
-
- try {
- // read lines of hunk
- while (true) {
-
- line= reader.readLine();
- if (line == null)
- return null;
-
- if (reader.lineContentLength(line) == 0) {
- lines.add(' ' + line);
- continue;
- }
-
- char c= line.charAt(0);
- switch (c) {
- case '@':
- if (line.startsWith("@@ ")) { //$NON-NLS-1$
- // flush old hunk
- if (lines.size() > 0) {
- new Hunk(diff, oldRange, newRange, lines);
- lines.clear();
- }
-
- // format: @@ -oldStart,oldLength +newStart,newLength @@
- extractPair(line, '-', oldRange);
- extractPair(line, '+', newRange);
- continue;
- }
- break;
- case ' ':
- case '+':
- case '-':
- lines.add(line);
- continue;
- case '\\':
- if (line.startsWith("No newline at end of file", 2)) { //$NON-NLS-1$
- int lastIndex= lines.size();
- if (lastIndex > 0) {
- line= (String) lines.get(lastIndex-1);
- int end= line.length()-1;
- char lc= line.charAt(end);
- if (lc == '\n') {
- end--;
- if (end > 0 && line.charAt(end-1) == '\r')
- end--;
- } else if (lc == '\r') {
- end--;
- }
- line= line.substring(0, end);
- lines.set(lastIndex-1, line);
- }
- continue;
- }
- break;
- default:
- int a1= c, a2= 0;
- if (line.length() > 1)
- a2= line.charAt(1);
- if (DEBUG) System.out.println("char: " + a1 + " " + a2);
- break;
- }
- return line;
- }
- } finally {
- if (lines.size() > 0)
- new Hunk(diff, oldRange, newRange, lines);
- diff.finish();
- }
- }
-
- /**
- * Returns the next line that does not belong to this diff
- */
- private String readContextDiff(List diffs, LineReader reader, String line, String args, String fileName) throws IOException {
-
- String[] oldArgs= split(line.substring(4));
-
- // read info about new file
- line= reader.readLine();
- if (line == null || !line.startsWith("--- ")) //$NON-NLS-1$
- return line;
-
- String[] newArgs= split(line.substring(4));
-
- Diff diff= new Diff(extractPath(oldArgs, 0, fileName), extractDate(oldArgs, 1),
- extractPath(newArgs, 0, fileName), extractDate(newArgs, 1));
- diffs.add(diff);
-
- int[] oldRange= new int[2];
- int[] newRange= new int[2];
- List oldLines= new ArrayList();
- List newLines= new ArrayList();
- List lines= oldLines;
-
- try {
- // read lines of hunk
- while (true) {
-
- line= reader.readLine();
- if (line == null)
- return line;
-
- int l= line.length();
- if (l == 0)
- continue;
- if (l > 1) {
- switch (line.charAt(0)) {
- case '*':
- if (line.startsWith("***************")) { // new hunk //$NON-NLS-1$
- // flush old hunk
- if (oldLines.size() > 0 || newLines.size() > 0) {
- new Hunk(diff, oldRange, newRange, unifyLines(oldLines, newLines));
- oldLines.clear();
- newLines.clear();
- }
- continue;
- }
- if (line.startsWith("*** ")) { // old range //$NON-NLS-1$
- // format: *** oldStart,oldEnd ***
- extractPair(line, ' ', oldRange);
- oldRange[1]= oldRange[1]-oldRange[0]+1;
- lines= oldLines;
- continue;
- }
- break;
- case ' ': // context line
- case '+': // addition
- case '!': // change
- if (line.charAt(1) == ' ') {
- lines.add(line);
- continue;
- }
- break;
- case '-':
- if (line.charAt(1) == ' ') { // deletion
- lines.add(line);
- continue;
- }
- if (line.startsWith("--- ")) { // new range //$NON-NLS-1$
- // format: *** newStart,newEnd ***
- extractPair(line, ' ', newRange);
- newRange[1]= newRange[1]-newRange[0]+1;
- lines= newLines;
- continue;
- }
- break;
- default:
- break;
- }
- }
- return line;
- }
- } finally {
- // flush last hunk
- if (oldLines.size() > 0 || newLines.size() > 0)
- new Hunk(diff, oldRange, newRange, unifyLines(oldLines, newLines));
- diff.finish();
- }
- }
-
- /**
- * Creates a List of lines in the unified format from
- * two Lists of lines in the 'classic' format.
- */
- private List unifyLines(List oldLines, List newLines) {
- List result= new ArrayList();
-
- String[] ol= (String[]) oldLines.toArray(new String[oldLines.size()]);
- String[] nl= (String[]) newLines.toArray(new String[newLines.size()]);
-
- int oi= 0, ni= 0;
-
- while (true) {
-
- char oc= 0;
- String o= null;
- if (oi < ol.length) {
- o= ol[oi];
- oc= o.charAt(0);
- }
-
- char nc= 0;
- String n= null;
- if (ni < nl.length) {
- n= nl[ni];
- nc= n.charAt(0);
- }
-
- // EOF
- if (oc == 0 && nc == 0)
- break;
-
- // deletion in old
- if (oc == '-') {
- do {
- result.add('-' + o.substring(2));
- oi++;
- if (oi >= ol.length)
- break;
- o= ol[oi];
- } while (o.charAt(0) == '-');
- continue;
- }
-
- // addition in new
- if (nc == '+') {
- do {
- result.add('+' + n.substring(2));
- ni++;
- if (ni >= nl.length)
- break;
- n= nl[ni];
- } while (n.charAt(0) == '+');
- continue;
- }
-
- // differing lines on both sides
- if (oc == '!' && nc == '!') {
- // remove old
- do {
- result.add('-' + o.substring(2));
- oi++;
- if (oi >= ol.length)
- break;
- o= ol[oi];
- } while (o.charAt(0) == '!');
-
- // add new
- do {
- result.add('+' + n.substring(2));
- ni++;
- if (ni >= nl.length)
- break;
- n= nl[ni];
- } while (n.charAt(0) == '!');
-
- continue;
- }
-
- // context lines
- if (oc == ' ' && nc == ' ') {
- do {
- Assert.isTrue(o.equals(n), "non matching context lines"); //$NON-NLS-1$
- result.add(' ' + o.substring(2));
- oi++;
- ni++;
- if (oi >= ol.length || ni >= nl.length)
- break;
- o= ol[oi];
- n= nl[ni];
- } while (o.charAt(0) == ' ' && n.charAt(0) == ' ');
- continue;
- }
-
- if (oc == ' ') {
- do {
- result.add(' ' + o.substring(2));
- oi++;
- if (oi >= ol.length)
- break;
- o= ol[oi];
- } while (o.charAt(0) == ' ');
- continue;
- }
-
- if (nc == ' ') {
- do {
- result.add(' ' + n.substring(2));
- ni++;
- if (ni >= nl.length)
- break;
- n= nl[ni];
- } while (n.charAt(0) == ' ');
- continue;
- }
-
- Assert.isTrue(false, "unexpected char <" + oc + "> <" + nc + ">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- return result;
- }
-
- /**
- * Breaks the given string into tab separated substrings.
- * Leading and trailing whitespace is removed from each token.
- */
- private String[] split(String line) {
- List l= new ArrayList();
- StringTokenizer st= new StringTokenizer(line, "\t"); //$NON-NLS-1$
- while (st.hasMoreElements()) {
- String token= st.nextToken().trim();
- if (token.length() > 0)
- l.add(token);
- }
- return (String[]) l.toArray(new String[l.size()]);
- }
-
- /**
- * @return the parsed time/date in milliseconds or -1 on error
- */
- private long extractDate(String[] args, int n) {
- if (n < args.length) {
- String line= args[n];
- for (int i= 0; i < DATE_FORMATS.length; i++) {
- DATE_FORMATS[i].setLenient(true);
- try {
- Date date= DATE_FORMATS[i].parse(line);
- return date.getTime();
- } catch (ParseException ex) {
- }
- }
- // System.err.println("can't parse date: <" + line + ">");
- }
- return -1;
- }
-
- /**
- * Returns null if file name is "/dev/null".
- */
- private IPath extractPath(String[] args, int n, String path2) {
- if (n < args.length) {
- String path= args[n];
- if (DEV_NULL.equals(path))
- return null;
- int pos= path.lastIndexOf(':');
- if (pos >= 0)
- path= path.substring(0, pos);
- if (path2 != null && !path2.equals(path)) {
- if (DEBUG) System.out.println("path mismatch: " + path2);
- path= path2;
- }
- return new Path(path);
- }
- return null;
- }
-
- /**
- * Tries to extract two integers separated by a comma.
- * The parsing of the line starts at the position after
- * the first occurrence of the given character start an ends
- * at the first blank (or the end of the line).
- * If only a single number is found this is assumed to be the length of the range.
- * In this case the start of the range is set to 1.
- * If an error occurs the range -1,-1 is returned.
- */
- private void extractPair(String line, char start, int[] pair) {
- pair[0]= pair[1]= -1;
- int startPos= line.indexOf(start);
- if (startPos < 0) {
- if (DEBUG) System.out.println("parsing error in extractPair: couldn't find \'" + start + "\'");
- return;
- }
- line= line.substring(startPos+1);
- int endPos= line.indexOf(' ');
- if (endPos < 0) {
- if (DEBUG) System.out.println("parsing error in extractPair: couldn't find end blank");
- return;
- }
- line= line.substring(0, endPos);
- int comma= line.indexOf(',');
- if (comma >= 0) {
- pair[0]= Integer.parseInt(line.substring(0, comma));
- pair[1]= Integer.parseInt(line.substring(comma+1));
- } else {
- pair[0]= 1;
- pair[1]= Integer.parseInt(line.substring(comma+1));
- }
- }
-
- //---- applying a patch file
-
- /**
- * Tries to patch the given lines with the specified Diff.
- * Any hunk that couldn't be applied is returned in the list failedHunks.
- */
- /* package */ void patch(Diff diff, List lines, List failedHunks) {
-
- int shift= 0;
- Iterator iter= diff.fHunks.iterator();
- while (iter.hasNext()) {
- Hunk hunk= (Hunk) iter.next();
- shift= patch(hunk, lines, shift, failedHunks);
- }
- }
-
- /**
- * Tries to patch the contents of the given reader with the specified Diff.
- * Any hunk that couldn't be applied is returned in the list failedHunks.
- */
- /* package */ String patch(Diff diff, BufferedReader reader, List failedHunks) {
-
- List lines= new LineReader(reader).readLines();
- if (lines == null)
- lines= new ArrayList();
-
- patch(diff, lines, failedHunks);
-
- StringBuffer sb= new StringBuffer();
- Iterator iter= lines.iterator();
- while (iter.hasNext())
- sb.append((String)iter.next());
- return sb.toString();
- }
-
- /**
- * Tries to apply the specified hunk to the given lines.
- * If the hunk cannot be applied at the original position
- * the methods tries Fuzz lines before and after.
- * If this fails the Hunk is added to the given list of failed hunks.
- */
- private int patch(Hunk hunk, List lines, int shift, List failedHunks) {
- if (tryPatch(hunk, lines, shift)) {
- shift+= doPatch(hunk, lines, shift);
- } else {
- boolean found= false;
- int oldShift= shift;
-
- for (int i= shift-1; i > shift-fFuzz; i--) {
- if (tryPatch(hunk, lines, i)) {
- shift= i;
- found= true;
- break;
- }
- }
-
- if (! found) {
- for (int i= shift+1; i < shift+fFuzz; i++) {
- if (tryPatch(hunk, lines, i)) {
- shift= i;
- found= true;
- break;
- }
- }
- }
-
- if (found) {
- if (DEBUG) System.out.println("patched hunk at offset: " + (shift-oldShift));
- shift+= doPatch(hunk, lines, shift);
- } else {
- if (failedHunks != null) {
- if (DEBUG) System.out.println("failed hunk");
- failedHunks.add(hunk);
- }
- }
- }
- return shift;
- }
-
- private boolean tryPatch(Hunk hunk, List lines, int shift) {
- int pos= hunk.fOldStart + shift;
- int contextMatches= 0;
- int deleteMatches= 0;
- for (int i= 0; i < hunk.fLines.length; i++) {
- String s= hunk.fLines[i];
- Assert.isTrue(s.length() > 0);
- String line= s.substring(1);
- char controlChar= s.charAt(0);
- if (controlChar == ' ') { // context lines
- while (true) {
- if (pos < 0 || pos >= lines.size())
- return false;
- if (linesMatch(line, (String) lines.get(pos))) {
- contextMatches++;
- pos++;
- break;
- }
- if (contextMatches <= 0)
- return false;
- pos++;
- }
- } else if (controlChar == '-') {
- // deleted lines
- while (true) {
- if (pos < 0 || pos >= lines.size())
- return false;
- if (linesMatch(line, (String) lines.get(pos))) {
- deleteMatches++;
- pos++;
- break;
- }
- if (deleteMatches <= 0)
- return false;
- pos++;
- }
- } else if (controlChar == '+') {
- // added lines
- // we don't have to do anything for a 'try'
- } else
- Assert.isTrue(false, "tryPatch: unknown control charcter: " + controlChar); //$NON-NLS-1$
- }
- return true;
- }
-
- private int doPatch(Hunk hunk, List lines, int shift) {
- int pos= hunk.fOldStart + shift;
- for (int i= 0; i < hunk.fLines.length; i++) {
- String s= hunk.fLines[i];
- Assert.isTrue(s.length() > 0);
- String line= s.substring(1);
- char controlChar= s.charAt(0);
- if (controlChar == ' ') { // context lines
- while (true) {
- Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in context"); //$NON-NLS-1$
- if (linesMatch(line, (String) lines.get(pos))) {
- pos++;
- break;
- }
- pos++;
- }
- } else if (controlChar == '-') {
- // deleted lines
- while (true) {
- Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in deleted lines"); //$NON-NLS-1$
- if (linesMatch(line, (String) lines.get(pos))) {
- break;
- }
- pos++;
- }
- lines.remove(pos);
- } else if (controlChar == '+') {
- // added lines
- lines.add(pos, line);
- pos++;
- } else
- Assert.isTrue(false, "doPatch: unknown control charcter: " + controlChar); //$NON-NLS-1$
- }
- return hunk.fNewLength - hunk.fOldLength;
- }
-
- public void applyAll(IResource target, IProgressMonitor pm) {
-
- if (DEBUG) System.out.println("applyAll: start");
-
- IContainer container= null;
- if (target instanceof IContainer)
- container= (IContainer) target;
- else {
- if (DEBUG) System.out.println("applyAll: not yet implemented");
- return;
- }
-
- for (int i= 0; i < fDiffs.length; i++) {
- Diff diff= fDiffs[i];
- if (diff.fIsEnabled) {
-
- IPath path= getPath(diff);
- IFile file= createPath(container, path);
-
- int type= diff.getType();
- switch (type) {
- case Differencer.ADDITION:
- if (DEBUG) System.out.println(" add: " + path);
- updateFile(diff, file, true, pm);
- break;
- case Differencer.DELETION:
- if (DEBUG) System.out.println(" del: " + path);
- deleteFile(file, pm);
- break;
- case Differencer.CHANGE:
- if (DEBUG) System.out.println(" chg: " + path);
- updateFile(diff, file, false, pm);
- break;
- }
-
- /*
- String rej= diff.fRejected;
- if (rej != null) {
- IPath pp= path.removeLastSegments(1);
- pp= pp.append(path.lastSegment() + ".rej");
- createPath(fRoot, rootFolder, pp, diff, true);
- }
- */
- }
- if (pm != null)
- pm.worked(1);
- }
-
- try {
- target.refreshLocal(IResource.DEPTH_INFINITE, pm);
- } catch (CoreException ex) {
- if (DEBUG) System.out.println("refreshLocal: exception " + ex);
- }
- if (DEBUG) System.out.println("applyAll: end");
- }
-
- List apply(Diff diff, IFile file, boolean create, List failedHunks) {
-
- if (file == null)
- if (DEBUG) System.out.println(" file == null");
-
- List lines= null;
- if (!create) {
- // read current contents
- InputStream is= null;
- try {
- is= file.getContents();
- BufferedReader reader= new BufferedReader(new InputStreamReader(is));
- lines= new LineReader(reader).readLines();
- if (DEBUG) System.out.println(" creating reader successful");
- } catch(CoreException ex) {
- if (DEBUG) System.out.println(" reading contents: " + ex);
- } finally {
- if (is != null)
- try {
- is.close();
- } catch(IOException ex) {
- }
- }
- }
-
- if (lines == null)
- lines= new ArrayList();
-
- patch(diff, lines, failedHunks);
-
- return lines;
- }
-
- private void deleteFile(IFile file, IProgressMonitor pm) {
- try {
- file.delete(true, true, pm);
- } catch (CoreException ex) {
- System.out.println("deleteFile: exception: " + ex);
- }
- }
-
- private void updateFile(Diff diff, IFile file, boolean create, IProgressMonitor pm) {
-
- if (DEBUG) System.out.println(" updateFile: start");
-
- // patch it and collect rejected hunks
- List failed= new ArrayList();
-
- if (DEBUG) System.out.println(" patching: start");
- List lines= apply(diff, file, create, failed);
- if (DEBUG) System.out.println(" patching: end");
-
- // convert the result into a String
- StringBuffer sb= new StringBuffer();
- Iterator iter= lines.iterator();
- while (iter.hasNext())
- sb.append((String)iter.next());
- String contents= sb.toString();
-
- // and save it
- InputStream is= new ByteArrayInputStream(contents.getBytes());
- try {
- if (file.exists()) {
- file.setContents(is, false, true, pm);
- if (DEBUG) System.out.println(" setContents: successfull");
- } else {
- file.create(is, false, pm);
- if (DEBUG) System.out.println(" create: successfull");
- }
- } catch (CoreException ex) {
- if (DEBUG) System.out.println(" exception: " + ex);
- } finally {
- if (is != null)
- try {
- is.close();
- } catch(IOException ex) {
- }
- }
- if (DEBUG) System.out.println(" updateFile: end");
- }
-
- private IFile createPath(IContainer folder, IPath path) {
- if (path.segmentCount() > 1) {
- IFolder f= folder.getFolder(path.uptoSegment(1));
- //System.out.println("createPath: " + f + " " + f.exists());
- return createPath(f, path.removeFirstSegments(1));
- }
- // a leaf
- return folder.getFile(path);
- }
-
- private static String stripWhiteSpace(String s) {
- StringBuffer sb= new StringBuffer();
- int l= s.length();
- for (int i= 0; i < l; i++) {
- char c= s.charAt(i);
- if (!Character.isWhitespace(c))
- sb.append(c);
- }
- return sb.toString();
- }
-
- /**
- * Compares two strings.
- * If fIgnoreWhitespace is true whitespace and line endings are ignored.
- */
- private boolean linesMatch(String line1, String line2) {
- if (fIgnoreWhitespace)
- return stripWhiteSpace(line1).equals(stripWhiteSpace(line2));
- return line1.equals(line2);
- }
-
- /**
- * Returns the length (exluding end-of-line characters) of the given string.
- */
- /* package */ static int length(String s) {
- int l= s.length();
- if (l > 0 && s.charAt(l-1) == '\n')
- l--;
- if (l > 1 && s.charAt(l-2) == '\r')
- l--;
- return l;
- }
-}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PreviewPatchPage.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PreviewPatchPage.java
deleted file mode 100644
index 952c5615f..000000000
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/PreviewPatchPage.java
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package org.eclipse.compare.patch;
-
-import java.io.*;
-import java.util.*;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.*;
-import org.eclipse.swt.widgets.*;
-
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.wizard.WizardPage;
-
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
-
-import org.eclipse.compare.*;
-import org.eclipse.compare.internal.*;
-import org.eclipse.compare.structuremergeviewer.*;
-
-
-/**
- * Shows the parsed patch file and any mismatches
- * between files, hunks and the currently selected
- * resources.
- */
-/* package */ class PreviewPatchPage extends WizardPage {
-
- /**
- * Used with CompareInput
- */
- static class HunkInput implements ITypedElement, IStreamContentAccessor {
- String fContent;
- String fType;
-
- HunkInput(String type, String s) {
- fType= type;
- fContent= s;
- }
- public Image getImage() {
- return null;
- }
- public String getName() {
- return "no name";
- }
- public String getType() {
- return fType;
- }
- public InputStream getContents() {
- return new ByteArrayInputStream(fContent.getBytes());
- }
- };
-
- private PatchWizard fPatchWizard;
-
- private Tree fTree;
- private Combo fStripPrefixSegments;
- private CompareViewerSwitchingPane fHunkViewer;
- private Button fIgnoreWhitespaceButton;
- private Button fReversePatchButton;
- private Text fFuzzField;
-
- private Image fNullImage;
- private Image fAddImage;
- private Image fDelImage;
-
- private CompareConfiguration fCompareConfiguration;
-
-
- /* package */ PreviewPatchPage(PatchWizard pw) {
- super("PreviewPatchPage", "Verify Patch", null);
-
- setMessage(
- "The tree shows the contents of the patch. " +
- "A checked item indicates that a patch could be applied succesfully.\n" +
- "Uncheck an item if you want to exclude it.");
-
- fPatchWizard= pw;
- //setPageComplete(false);
-
- int w= 16;
- fNullImage= new DiffImage(null, null, w).createImage();
- fAddImage= new DiffImage(null, CompareUIPlugin.getImageDescriptor("ovr16/add_ov.gif"), w).createImage();
- fDelImage= new DiffImage(null, CompareUIPlugin.getImageDescriptor("ovr16/del_ov.gif"), w).createImage();
-
- fCompareConfiguration= new CompareConfiguration();
-
- fCompareConfiguration.setLeftEditable(false);
- fCompareConfiguration.setLeftLabel("Original");
-
- fCompareConfiguration.setRightEditable(false);
- fCompareConfiguration.setRightLabel("Result");
- }
-
- /* (non-Javadoc)
- * Method declared in WizardPage
- */
- public void setVisible(boolean visible) {
- if (visible)
- buildTree();
- super.setVisible(visible);
- }
-
- Image getImage(Diff diff) {
- switch (diff.getType()) {
- case Differencer.ADDITION:
- return fAddImage;
- case Differencer.DELETION:
- return fDelImage;
- }
- return fNullImage;
- }
-
- public void createControl(Composite parent) {
-
- Composite composite= new Composite(parent, SWT.NULL);
- composite.setLayout(new GridLayout());
- composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));
- setControl(composite);
-
- buildPatchOptionsGroup(composite);
-
- // top pane showing diffs and hunks in a check box tree
- fTree= new Tree(composite, SWT.CHECK | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
- GridData gd= new GridData();
- gd.verticalAlignment= GridData.FILL;
- gd.horizontalAlignment= GridData.FILL;
- gd.grabExcessHorizontalSpace= true;
- gd.grabExcessVerticalSpace= true;
- fTree.setLayoutData(gd);
-
- // bottom pane showing hunks in compare viewer
- fHunkViewer= new CompareViewerSwitchingPane(composite, SWT.BORDER) {
- protected Viewer getViewer(Viewer oldViewer, Object input) {
- return CompareUI.findContentViewer(oldViewer, (ICompareInput)input, this, fCompareConfiguration);
- }
- };
- gd= new GridData();
- gd.verticalAlignment= GridData.FILL;
- gd.horizontalAlignment= GridData.FILL;
- gd.grabExcessHorizontalSpace= true;
- gd.grabExcessVerticalSpace= true;
- fHunkViewer.setLayoutData(gd);
-
- // register listeners
-
- fTree.addSelectionListener(
- new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- TreeItem ti= (TreeItem) e.item;
- Object data= e.item.getData();
- if (e.detail == SWT.CHECK) {
- boolean enabled= ti.getChecked();
- if (data instanceof Hunk) {
- ((Hunk)data).fIsEnabled= enabled;
- updateGrayedState(ti);
- } else if (data instanceof Diff) {
- ((Diff)data).fIsEnabled= enabled;
- updateCheckedState(ti);
- }
- } else {
- if (data instanceof Hunk)
- PreviewPatchPage.this.fHunkViewer.setInput(createInput((Hunk)data));
- else
- PreviewPatchPage.this.fHunkViewer.setInput(null);
- }
- }
- }
- );
-
- // creating tree's content
- buildTree();
-
- // WorkbenchHelp.setHelp(composite, new DialogPageContextComputer(this, PATCH_HELP_CONTEXT_ID));
- }
-
- /**
- * Create the group for setting various patch options
- */
- private void buildPatchOptionsGroup(Composite parent) {
-
- final Patcher patcher= fPatchWizard.getPatcher();
-
- Group group= new Group(parent, SWT.NONE);
- group.setText("Patch Options");
- GridLayout layout= new GridLayout();
- layout.numColumns= 5;
- group.setLayout(layout);
- group.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
- //fPatchFileGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-
- // 1st row
- new Label(group, SWT.NONE).setText("Ignore leading path name segments:");
-
- fStripPrefixSegments= new Combo(group, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.SIMPLE);
- int prefixCnt= patcher.getStripPrefixSegments();
- String prefix= Integer.toString(prefixCnt);
- fStripPrefixSegments.add(prefix);
- fStripPrefixSegments.setText(prefix);
-
- addSpacer(group);
-
- fReversePatchButton= new Button(group, SWT.CHECK);
- fReversePatchButton.setText("Reverse Patch");
-
- addSpacer(group);
-
- // 2nd row
- Label l= new Label(group, SWT.NONE);
- l.setText("Maximum fuzz factor:");
- l.setToolTipText("Allow context to shift this number of lines from the original place");
- fFuzzField= new Text(group, SWT.BORDER);
- fFuzzField.setText("2");
- GridData gd2= new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
- gd2.widthHint= 30;
- fFuzzField.setLayoutData(gd2);
-
- addSpacer(group);
-
- fIgnoreWhitespaceButton= new Button(group, SWT.CHECK);
- fIgnoreWhitespaceButton.setText("Ignore Whitespace");
-
- addSpacer(group);
-
- // register listeners
-
- if (fStripPrefixSegments != null)
- fStripPrefixSegments.addSelectionListener(
- new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- if (patcher.setStripPrefixSegments(getStripPrefixSegments()))
- updateTree();
- }
- }
- );
- fReversePatchButton.addSelectionListener(
- new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- if (patcher.setReversed(fReversePatchButton.getSelection()))
- updateTree();
- }
- }
- );
- fIgnoreWhitespaceButton.addSelectionListener(
- new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- if (patcher.setIgnoreWhitespace(fIgnoreWhitespaceButton.getSelection()))
- updateTree();
- }
- }
- );
-
- fFuzzField.addModifyListener(
- new ModifyListener() {
- public void modifyText(ModifyEvent e) {
- if (patcher.setFuzz(getFuzzFactor()))
- updateTree();
- }
- }
- );
- }
-
- ICompareInput createInput(Hunk hunk) {
-
- String[] lines= hunk.fLines;
- StringBuffer left= new StringBuffer();
- StringBuffer right= new StringBuffer();
-
- for (int i= 0; i < lines.length; i++) {
- String line= lines[i];
- String rest= line.substring(1);
- switch (line.charAt(0)) {
- case ' ':
- left.append(rest);
- right.append(rest);
- break;
- case '-':
- left.append(rest);
- break;
- case '+':
- right.append(rest);
- break;
- }
- }
-
- Diff diff= hunk.fParent;
- IPath path= diff.getPath();
- String type= path.getFileExtension();
-
- return new DiffNode(new HunkInput(type, left.toString()), new HunkInput(type, right.toString()));
- }
-
- /**
- * Builds a tree from list of Diffs.
- * As a side effect it calculates the maximum number of segments
- * in all paths.
- */
- private void buildTree() {
- setPageComplete(true);
- if (fTree != null && !fTree.isDisposed()) {
- fTree.removeAll();
- fHunkViewer.setInput(null);
-
- int length= 99;
-
- Diff[] diffs= fPatchWizard.getPatcher().getDiffs();
- if (diffs != null) {
- for (int i= 0; i < diffs.length; i++) {
- Diff diff= diffs[i];
- TreeItem d= new TreeItem(fTree, SWT.NULL);
- d.setData(diff);
- d.setImage(getImage(diff));
-
- if (diff.fOldPath != null)
- length= Math.min(length, diff.fOldPath.segmentCount());
- if (diff.fNewPath != null)
- length= Math.min(length, diff.fNewPath.segmentCount());
-
- java.util.List hunks= diff.fHunks;
- java.util.Iterator iter= hunks.iterator();
- while (iter.hasNext()) {
- Hunk hunk= (Hunk) iter.next();
- TreeItem h= new TreeItem(d, SWT.NULL);
- h.setData(hunk);
- h.setText(hunk.getDescription());
- }
- }
- }
- if (fStripPrefixSegments != null && length != 99)
- for (int i= 1; i < length; i++)
- fStripPrefixSegments.add(Integer.toString(i));
- }
-
- updateTree();
- }
-
- private IFile existsInSelection(IPath path) {
- IResource target= fPatchWizard.getTarget();
- if (target instanceof IFile) {
- IFile file= (IFile) target;
- IPath path2= file.getFullPath().removeFirstSegments(1);
- //System.out.println("target: " + path2.toOSString());
- //System.out.println(" path: " + path.toOSString());
- if (path.equals(path2))
- return file;
-// String name= file.getName();
-// if (path.lastSegment().equals(name))
-// return file;
- } else if (target instanceof IContainer) {
- IContainer c= (IContainer) target;
- if (c.exists(path))
- return c.getFile(path);
- }
- return null;
- }
-
- /**
- * Updates label and checked state of tree items.
- */
- private void updateTree() {
- if (fTree == null || fTree.isDisposed())
- return;
- int strip= getStripPrefixSegments();
- TreeItem[] children= fTree.getItems();
- for (int i= 0; i < children.length; i++) {
- TreeItem item= children[i];
- Diff diff= (Diff) item.getData();
- String error= null;
-
- boolean create= false;
- IFile file= null;
- if (diff.getType() == Differencer.ADDITION) {
- IPath p= diff.fNewPath;
- if (strip > 0 && strip < p.segmentCount())
- p= p.removeFirstSegments(strip);
- file= existsInSelection(p);
- if (file == null) {
- diff.fIsEnabled= true;
- } else {
- // file already exists
- diff.fIsEnabled= false;
- error= "(file already exists)";
- }
- create= true;
- } else {
- IPath p= diff.fOldPath;
- if (strip > 0 && strip < p.segmentCount())
- p= p.removeFirstSegments(strip);
- file= existsInSelection(p);
- diff.fIsEnabled= file != null;
- if (file != null) {
- diff.fIsEnabled= true;
- } else {
- // file doesn't exist
- diff.fIsEnabled= false;
- error= "(file doesn't exist)";
- }
- }
-
- boolean checked= false;
-
- ArrayList failedHunks= new ArrayList(); // collect rejected hunks here
-
- fPatchWizard.getPatcher().apply(diff, file, create, failedHunks);
-
- if (! failedHunks.isEmpty()) {
- StringBuffer sb= new StringBuffer();
- Iterator iter= failedHunks.iterator();
- while (iter.hasNext()) {
- Hunk hunk= (Hunk) iter.next();
- sb.append(hunk.getDescription());
- sb.append('\n');
- sb.append(hunk.getContent());
- }
- diff.fRejected= sb.toString();
- }
-
- int checkedSubs= 0; // counts checked hunk items
- TreeItem[] hunkItems= item.getItems();
- for (int h= 0; h < hunkItems.length; h++) {
- Hunk hunk= (Hunk) hunkItems[h].getData();
- boolean failed= failedHunks.contains(hunk);
- String hunkError= null;
- if (failed)
- hunkError= "(no match)";
- hunk.fIsEnabled= diff.fIsEnabled && !failed;
- hunkItems[h].setChecked(hunk.fIsEnabled);
- if (hunk.fIsEnabled) {
- checkedSubs++;
- checked= true;
- }
- String hunkLabel= hunk.getDescription();
- if (hunkError != null)
- hunkLabel+= " " + hunkError;
- hunkItems[h].setText(hunkLabel);
- }
-
- String label= diff.getDescription(strip);
- if (error != null)
- label+= " " + error;
- item.setText(label);
- item.setImage(getImage(diff));
- item.setChecked(checked);
- boolean gray= (checkedSubs > 0 && checkedSubs < hunkItems.length);
- item.setGrayed(gray);
- item.setExpanded(gray);
- }
- }
-
- /**
- * Updates the gray state of the given diff and the checked state of its children.
- */
- private void updateCheckedState(TreeItem diff) {
- boolean checked= diff.getChecked();
- diff.setGrayed(false);
- TreeItem[] hunks= diff.getItems();
- for (int i= 0; i < hunks.length; i++)
- hunks[i].setChecked(checked);
- }
-
- /**
- * Updates the gray state of the given items parent.
- */
- private void updateGrayedState(TreeItem hunk) {
- TreeItem diff= hunk.getParentItem();
- TreeItem[] hunks= diff.getItems();
- int checked= 0;
- for (int i= 0; i < hunks.length; i++)
- if (hunks[i].getChecked())
- checked++;
- diff.setChecked(checked > 0);
- diff.setGrayed(checked > 0 && checked < hunks.length);
- }
-
- private void addSpacer(Composite parent) {
- Label label= new Label(parent, SWT.NONE);
- GridData gd= new GridData(GridData.FILL_HORIZONTAL);
- gd.widthHint= 20;
- label.setLayoutData(gd);
- }
-
- private int getStripPrefixSegments() {
- int stripPrefixSegments= 0;
- if (fStripPrefixSegments != null) {
- String s= fStripPrefixSegments.getText();
- try {
- stripPrefixSegments= Integer.parseInt(s);
- } catch(NumberFormatException ex) {
- }
- }
- return stripPrefixSegments;
- }
-
- private int getFuzzFactor() {
- int fuzzFactor= 0;
- if (fFuzzField != null) {
- String s= fFuzzField.getText();
- try {
- fuzzFactor= Integer.parseInt(s);
- } catch(NumberFormatException ex) {
- }
- }
- return fuzzFactor;
- }
-}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/plugin.xml b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/plugin.xml
index 5eb8c2d4c..23fd860fc 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/plugin.xml
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/plugin.xml
@@ -91,7 +91,7 @@
tooltip="%CompareWithPatchAction.tooltip"
menubarPath="compareWithMenu/compareWithGroup"
enablesFor="1"
- class="org.eclipse.compare.patch.CompareWithPatchAction">
+ class="org.eclipse.compare.internal.patch.CompareWithPatchAction">
--
cgit v1.2.3