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: + * + */ + String getContent() { + StringBuffer sb= new StringBuffer(); + for (int i= 0; i < fLines.length; i++) { + String line= fLines[i]; + sb.append(line.substring(0, Patcher.length(line))); + sb.append('\n'); + } + return sb.toString(); + } + + /** + * Returns a descriptive String for this hunk. + * It is in the form old_start,old_length -> new_start,new_length. + */ + String getDescription() { + StringBuffer sb= new StringBuffer(); + sb.append(Integer.toString(fOldStart)); + sb.append(','); + sb.append(Integer.toString(fOldLength)); + sb.append(" -> "); //$NON-NLS-1$ + sb.append(Integer.toString(fNewStart)); + sb.append(','); + sb.append(Integer.toString(fNewLength)); + return sb.toString(); + } + + String getRejectedDescription() { + StringBuffer sb= new StringBuffer(); + sb.append("@@ -"); //$NON-NLS-1$ + sb.append(Integer.toString(fOldStart)); + sb.append(','); + sb.append(Integer.toString(fOldLength)); + sb.append(" +"); //$NON-NLS-1$ + sb.append(Integer.toString(fNewStart)); + sb.append(','); + sb.append(Integer.toString(fNewLength)); + sb.append(" @@"); //$NON-NLS-1$ + return sb.toString(); + } +} diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/InputPatchPage.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/InputPatchPage.java new file mode 100644 index 000000000..988036dc1 --- /dev/null +++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/InputPatchPage.java @@ -0,0 +1,609 @@ +/* + * (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.dnd.*; +import org.eclipse.swt.events.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +import org.eclipse.jface.dialogs.*; +import org.eclipse.jface.viewers.*; +import org.eclipse.jface.wizard.*; + +import org.eclipse.ui.help.*; +import org.eclipse.ui.model.*; + +import org.eclipse.core.resources.*; +import org.eclipse.core.runtime.*; + +import org.eclipse.compare.internal.Utilities; + + +/* package */ class InputPatchPage extends WizardPage { + + // constants + protected static final int SIZING_TEXT_FIELD_WIDTH= 250; + protected static final int COMBO_HISTORY_LENGTH= 5; + + private final static int SIZING_SELECTION_WIDGET_WIDTH= 400; + private final static int SIZING_SELECTION_WIDGET_HEIGHT= 150; + + // dialog store id constants + private final static String PAGE_NAME= "PatchWizardPage1"; //$NON-NLS-1$ + private final static String STORE_PATCH_FILE_ID= PAGE_NAME + ".PATCH_FILE"; //$NON-NLS-1$ + private final static String STORE_PATCH_FILES_ID= PAGE_NAME + ".PATCH_FILES"; //$NON-NLS-1$ + private final static String STORE_USE_CLIPBOARD_ID= PAGE_NAME + ".USE_CLIPBOARD"; //$NON-NLS-1$ + + // help IDs + private final static String PATCH_HELP_CONTEXT_ID= "PatchWizardHelpId"; //$NON-NLS-1$ + + // SWT widgets + private Button fUseClipboardButton; + private Combo fPatchFileNameField; + private Button fPatchFileBrowseButton; + private Button fUsePatchFileButton; + private Group fPatchFileGroup; + private CheckboxTreeViewer fPatchTargets; + private PatchWizard fPatchWizard; + + + InputPatchPage(PatchWizard pw) { + super("InputPatchPage", PatchMessages.getString("InputPatchPage.title"), null); //$NON-NLS-1$ //$NON-NLS-2$ + fPatchWizard= pw; + setMessage(PatchMessages.getString("InputPatchPage.message")); //$NON-NLS-1$ + } + + /** + * Get a path from the supplied text widget. + * @return org.eclipse.core.runtime.IPath + */ + protected IPath getPathFromText(Text textField) { + return (new Path(textField.getText())).makeAbsolute(); + } + + /* package */ String getPatchName() { + if (getUseClipboard()) + return PatchMessages.getString("InputPatchPage.Clipboard"); //$NON-NLS-1$ + return getPatchFilePath(); + } + + 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); + + Label l= new Label(composite, SWT.NONE); // a spacer + l.setText(PatchMessages.getString("InputPatchPage.SelectInput")); //$NON-NLS-1$ + buildInputGroup(composite); + + new Label(composite, SWT.NONE); // a spacer + + buildPatchFileGroup(composite); + + restoreWidgetValues(); + + updateWidgetEnablements(); + //updatePageCompletion(); + + WorkbenchHelp.setHelp(composite, new DialogPageContextComputer(this, PATCH_HELP_CONTEXT_ID)); + } + + /* (non-JavaDoc) + * Method declared in IWizardPage. + */ + public IWizardPage getNextPage() { + if (true) { + + Patcher patcher= ((PatchWizard) getWizard()).getPatcher(); + + // Create a reader for the input + Reader reader= null; + if (getUseClipboard()) { + Control c= getControl(); + if (c != null) { + Clipboard clipboard= new Clipboard(c.getDisplay()); + Object o= clipboard.getContents(TextTransfer.getInstance()); + if (o instanceof String) + reader= new StringReader((String)o); + } + } else { + String patchFilePath= getPatchFilePath(); + if (patchFilePath != null) { + try { + reader= new FileReader(patchFilePath); + } catch (FileNotFoundException ex) { + MessageDialog.openError(null, + PatchMessages.getString("InputPatchPage.PatchErrorDialog.title"), //$NON-NLS-1$ + PatchMessages.getString("InputPatchPage.PatchFileNotFound.message")); //$NON-NLS-1$ + } + } + } + + // parse the input + if (reader != null) { + try { + patcher.parse(new BufferedReader(reader)); + } catch (IOException ex) { + MessageDialog.openError(null, + PatchMessages.getString("InputPatchPage.PatchErrorDialog.title_2"), //$NON-NLS-1$ + PatchMessages.getString("InputPatchPage.ParseError.message")); //$NON-NLS-1$ + } + + try { + reader.close(); + } catch (IOException x) { + } + } + + Diff[] diffs= patcher.getDiffs(); + if (diffs == null || diffs.length == 0) { + MessageDialog.openError(null, + PatchMessages.getString("InputPatchPage.PatchErrorDialog.title_4"), //$NON-NLS-1$ + PatchMessages.getString("InputPatchPage.NoDiffsFound.message")); //$NON-NLS-1$ + return this; + } + + // guess prefix count + int guess= guessPrefix(diffs); + patcher.setStripPrefixSegments(guess); + } + return super.getNextPage(); + } + + private int guessPrefix(Diff[] diffs) { + ArrayList list= new ArrayList(); + IResource target= fPatchWizard.getTarget(); + if (target instanceof IFile) { + list.add(target.getFullPath()); + } else if (target instanceof IContainer) { + addLeaf(list, (IContainer) target); + } + + // guess prefix count + for (int i= 0; i < diffs.length; i++) { + IPath p= diffs[i].fOldPath; + if (p != null) { + int matches= match(p, list); + if (matches > 0) { + return p.segmentCount() - matches; + } + } + } + return 0; + } + + private int match(IPath path, ArrayList list) { + Iterator iter= list.iterator(); + while (iter.hasNext()) { + IPath filePath= (IPath) iter.next(); + int matches= matchTrailingSegments(path, filePath); + if (matches > 0) + return matches; + //System.out.println(" " + filePath + ": " + matches); + } + return 0; + } + + private int matchTrailingSegments(IPath p1, IPath p2) { + int matches= 0; + int i1= p1.segmentCount()-1; + int i2= p2.segmentCount()-1; + for (; i1 >= 0 && i2 >= 0; i1--, i2--) { + String s1= p1.segment(i1); + String s2= p2.segment(i2); + if (!s1.equals(s2)) + break; + matches++; + } + return matches; + } + + private void addLeaf(ArrayList list, IContainer c) { + IResource[] rs= null; + try { + rs= c.members(); + } catch(CoreException ex) { + } + if (rs != null) { + for (int i= 0; i < rs.length; i++) { + IResource r= rs[i]; + if (r instanceof IFile) + list.add(r.getFullPath()); + else if (r instanceof IContainer) + addLeaf(list, (IContainer) r); + } + } + } + + /* (non-JavaDoc) + * Method declared in IWizardPage. + */ + public boolean canFlipToNextPage() { + if (true) { + // we can't call getNextPage to determine if flipping is allowed since computing + // the next page is quite expensive (checking preconditions and creating a + // change). So we say yes if the page is complete. + return isPageComplete(); + } else { + return super.canFlipToNextPage(); + } + } + + private void setEnablePatchFile(boolean enable) { + fPatchFileNameField.setEnabled(enable); + fPatchFileBrowseButton.setEnabled(enable); + } + + /** + * Create the group for selecting the patch file + */ + private void buildPatchFileGroup(Composite parent) { + + fPatchFileGroup= new Group(parent, SWT.NONE); + fPatchFileGroup.setText(PatchMessages.getString("InputPatchPage.SelectPatch.title")); //$NON-NLS-1$ + GridLayout layout= new GridLayout(); + layout.numColumns= 3; + fPatchFileGroup.setLayout(layout); + fPatchFileGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // 1st row + fUsePatchFileButton= new Button(fPatchFileGroup, SWT.RADIO); + fUsePatchFileButton.setText(PatchMessages.getString("InputPatchPage.FileButton.text")); //$NON-NLS-1$ + + fPatchFileNameField= new Combo(fPatchFileGroup, SWT.BORDER); + GridData gd= new GridData(GridData.FILL_HORIZONTAL); + //gd.horizontalIndent= 8; + gd.widthHint= SIZING_TEXT_FIELD_WIDTH; + fPatchFileNameField.setLayoutData(gd); + + fPatchFileBrowseButton= new Button(fPatchFileGroup, SWT.PUSH); + fPatchFileBrowseButton.setText(PatchMessages.getString("InputPatchPage.ChooseFileButton.text")); //$NON-NLS-1$ + fPatchFileBrowseButton.setLayoutData(new GridData()); + + // 2nd row + fUseClipboardButton= new Button(fPatchFileGroup, SWT.RADIO); + fUseClipboardButton.setText(PatchMessages.getString("InputPatchPage.UseClipboardButton.text")); //$NON-NLS-1$ + gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); + gd.horizontalSpan= 2; + fUseClipboardButton.setLayoutData(gd); + + + // Add listeners + fUsePatchFileButton.addSelectionListener( + new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + setEnablePatchFile(!getUseClipboard()); + updateWidgetEnablements(); + } + } + ); + fPatchFileNameField.addSelectionListener( + new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + setSourceName(fPatchFileNameField.getText()); + updateWidgetEnablements(); + } + } + ); + fPatchFileNameField.addModifyListener( + new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateWidgetEnablements(); + } + } + ); + fPatchFileBrowseButton.addSelectionListener( + new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + handlePatchFileBrowseButtonPressed(); + updateWidgetEnablements(); + } + } + ); + + //fPatchFileNameField.setFocus(); + } + + private void buildInputGroup(Composite parent) { + + PatchWizard pw= (PatchWizard) getWizard(); + IResource target= pw.getTarget(); + IWorkspace workspace= target.getWorkspace(); + IWorkspaceRoot root= workspace.getRoot(); + + Tree tree= new Tree(parent, SWT.BORDER); + GridData gd= new GridData(GridData.FILL_HORIZONTAL); + gd.heightHint= 200; + tree.setLayoutData(gd); + + fPatchTargets= new CheckboxTreeViewer(tree); + fPatchTargets.setLabelProvider(new WorkbenchLabelProvider()); + fPatchTargets.setContentProvider(new WorkbenchContentProvider()); + fPatchTargets.setSorter(new WorkbenchViewerSorter()); + fPatchTargets.setInput(root); + if (target != null) { + fPatchTargets.expandToLevel(target, 0); + fPatchTargets.setSelection(new StructuredSelection(target)); + } + + // register listeners + fPatchTargets.addSelectionChangedListener( + new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + fPatchWizard.setTarget(PatchWizard.getResource(event.getSelection())); + updateWidgetEnablements(); + } + } + ); + //fPatchFileNameField.setFocus(); + } + + /** + * Returns a content provider for IResources 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: - * - */ - String getContent() { - StringBuffer sb= new StringBuffer(); - for (int i= 0; i < fLines.length; i++) { - String line= fLines[i]; - sb.append(line.substring(0, Patcher.length(line))); - sb.append('\n'); - } - return sb.toString(); - } - - /** - * Returns a descriptive String for this hunk. - * It is in the form old_start,old_length -> new_start,new_length. - */ - String getDescription() { - StringBuffer sb= new StringBuffer(); - sb.append(Integer.toString(fOldStart)); - sb.append(','); - sb.append(Integer.toString(fOldLength)); - sb.append(" -> "); //$NON-NLS-1$ - sb.append(Integer.toString(fNewStart)); - sb.append(','); - sb.append(Integer.toString(fNewLength)); - return sb.toString(); - } -} diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/InputPatchPage.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/InputPatchPage.java deleted file mode 100644 index c0535baf3..000000000 --- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/patch/InputPatchPage.java +++ /dev/null @@ -1,604 +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.dnd.*; -import org.eclipse.swt.events.*; -import org.eclipse.swt.layout.*; -import org.eclipse.swt.widgets.*; - -import org.eclipse.jface.dialogs.*; -import org.eclipse.jface.viewers.*; -import org.eclipse.jface.wizard.*; - -import org.eclipse.ui.help.*; -import org.eclipse.ui.model.*; - -import org.eclipse.core.resources.*; -import org.eclipse.core.runtime.*; - -import org.eclipse.compare.internal.Utilities; - - -/* package */ class InputPatchPage extends WizardPage { - - // constants - protected static final int SIZING_TEXT_FIELD_WIDTH= 250; - protected static final int COMBO_HISTORY_LENGTH= 5; - - private final static int SIZING_SELECTION_WIDGET_WIDTH= 400; - private final static int SIZING_SELECTION_WIDGET_HEIGHT= 150; - - // dialog store id constants - private final static String PAGE_NAME= "PatchWizardPage1"; //$NON-NLS-1$ - private final static String STORE_PATCH_FILE_ID= PAGE_NAME + ".PATCH_FILE"; //$NON-NLS-1$ - private final static String STORE_PATCH_FILES_ID= PAGE_NAME + ".PATCH_FILES"; //$NON-NLS-1$ - private final static String STORE_USE_CLIPBOARD_ID= PAGE_NAME + ".USE_CLIPBOARD"; //$NON-NLS-1$ - - // help IDs - private final static String PATCH_HELP_CONTEXT_ID= "PatchWizardHelpId"; //$NON-NLS-1$ - - // SWT widgets - private Button fUseClipboardButton; - private Combo fPatchFileNameField; - private Button fPatchFileBrowseButton; - private Button fUsePatchFileButton; - private Group fPatchFileGroup; - private CheckboxTreeViewer fPatchTargets; - private PatchWizard fPatchWizard; - - - InputPatchPage(PatchWizard pw) { - super("InputPatchPage", "Patch Input Specification", null); - fPatchWizard= pw; - setMessage("Define what resource to patch with which patch."); - } - - /** - * Get a path from the supplied text widget. - * @return org.eclipse.core.runtime.IPath - */ - protected IPath getPathFromText(Text textField) { - return (new Path(textField.getText())).makeAbsolute(); - } - - /* package */ String getPatchName() { - if (getUseClipboard()) - return "Clipboard"; - return getPatchFilePath(); - } - - 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); - - Label l= new Label(composite, SWT.NONE); // a spacer - l.setText("Select a single file or folder to patch:"); - buildInputGroup(composite); - - new Label(composite, SWT.NONE); // a spacer - - buildPatchFileGroup(composite); - - restoreWidgetValues(); - - updateWidgetEnablements(); - //updatePageCompletion(); - - WorkbenchHelp.setHelp(composite, new DialogPageContextComputer(this, PATCH_HELP_CONTEXT_ID)); - } - - /* (non-JavaDoc) - * Method declared in IWizardPage. - */ - public IWizardPage getNextPage() { - if (true) { - - Patcher patcher= ((PatchWizard) getWizard()).getPatcher(); - - // Create a reader for the input - Reader reader= null; - if (getUseClipboard()) { - Control c= getControl(); - if (c != null) { - Clipboard clipboard= new Clipboard(c.getDisplay()); - Object o= clipboard.getContents(TextTransfer.getInstance()); - if (o instanceof String) - reader= new StringReader((String)o); - } - } else { - String patchFilePath= getPatchFilePath(); - if (patchFilePath != null) { - try { - reader= new FileReader(patchFilePath); - } catch (FileNotFoundException ex) { - MessageDialog.openError(null, "Error", "Patch file not found: " + patchFilePath); - } - } - } - - // parse the input - if (reader != null) { - try { - patcher.parse(new BufferedReader(reader)); - } catch (IOException ex) { - MessageDialog.openError(null, "Error", "Error while parsing patch"); - } - - try { - reader.close(); - } catch (IOException x) { - } - } - - Diff[] diffs= patcher.getDiffs(); - if (diffs == null || diffs.length == 0) { - MessageDialog.openError(null, "Error", "No diffs found in " + getPatchName()); - return this; - } - - // guess prefix count - int guess= guessPrefix(diffs); - patcher.setStripPrefixSegments(guess); - } - return super.getNextPage(); - } - - private int guessPrefix(Diff[] diffs) { - ArrayList list= new ArrayList(); - IResource target= fPatchWizard.getTarget(); - if (target instanceof IFile) { - list.add(target.getFullPath()); - } else if (target instanceof IContainer) { - addLeaf(list, (IContainer) target); - } - - // guess prefix count - for (int i= 0; i < diffs.length; i++) { - IPath p= diffs[i].fOldPath; - if (p != null) { - int matches= match(p, list); - if (matches > 0) { - return p.segmentCount() - matches; - } - } - } - return 0; - } - - private int match(IPath path, ArrayList list) { - Iterator iter= list.iterator(); - while (iter.hasNext()) { - IPath filePath= (IPath) iter.next(); - int matches= matchTrailingSegments(path, filePath); - if (matches > 0) - return matches; - //System.out.println(" " + filePath + ": " + matches); - } - return 0; - } - - private int matchTrailingSegments(IPath p1, IPath p2) { - int matches= 0; - int i1= p1.segmentCount()-1; - int i2= p2.segmentCount()-1; - for (; i1 >= 0 && i2 >= 0; i1--, i2--) { - String s1= p1.segment(i1); - String s2= p2.segment(i2); - if (!s1.equals(s2)) - break; - matches++; - } - return matches; - } - - private void addLeaf(ArrayList list, IContainer c) { - IResource[] rs= null; - try { - rs= c.members(); - } catch(CoreException ex) { - } - if (rs != null) { - for (int i= 0; i < rs.length; i++) { - IResource r= rs[i]; - if (r instanceof IFile) - list.add(r.getFullPath()); - else if (r instanceof IContainer) - addLeaf(list, (IContainer) r); - } - } - } - - /* (non-JavaDoc) - * Method declared in IWizardPage. - */ - public boolean canFlipToNextPage() { - if (true) { - // we can't call getNextPage to determine if flipping is allowed since computing - // the next page is quite expensive (checking preconditions and creating a - // change). So we say yes if the page is complete. - return isPageComplete(); - } else { - return super.canFlipToNextPage(); - } - } - - private void setEnablePatchFile(boolean enable) { - fPatchFileNameField.setEnabled(enable); - fPatchFileBrowseButton.setEnabled(enable); - } - - /** - * Create the group for selecting the patch file - */ - private void buildPatchFileGroup(Composite parent) { - - fPatchFileGroup= new Group(parent, SWT.NONE); - fPatchFileGroup.setText("Select Patch"); - GridLayout layout= new GridLayout(); - layout.numColumns= 3; - fPatchFileGroup.setLayout(layout); - fPatchFileGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - // 1st row - fUsePatchFileButton= new Button(fPatchFileGroup, SWT.RADIO); - fUsePatchFileButton.setText("File "); - - fPatchFileNameField= new Combo(fPatchFileGroup, SWT.BORDER); - GridData gd= new GridData(GridData.FILL_HORIZONTAL); - //gd.horizontalIndent= 8; - gd.widthHint= SIZING_TEXT_FIELD_WIDTH; - fPatchFileNameField.setLayoutData(gd); - - fPatchFileBrowseButton= new Button(fPatchFileGroup, SWT.PUSH); - fPatchFileBrowseButton.setText("Choose..."); - fPatchFileBrowseButton.setLayoutData(new GridData()); - - // 2nd row - fUseClipboardButton= new Button(fPatchFileGroup, SWT.RADIO); - fUseClipboardButton.setText("Clipboard"); - gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); - gd.horizontalSpan= 2; - fUseClipboardButton.setLayoutData(gd); - - - // Add listeners - fUsePatchFileButton.addSelectionListener( - new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - setEnablePatchFile(!getUseClipboard()); - updateWidgetEnablements(); - } - } - ); - fPatchFileNameField.addSelectionListener( - new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - setSourceName(fPatchFileNameField.getText()); - updateWidgetEnablements(); - } - } - ); - fPatchFileNameField.addModifyListener( - new ModifyListener() { - public void modifyText(ModifyEvent e) { - updateWidgetEnablements(); - } - } - ); - fPatchFileBrowseButton.addSelectionListener( - new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - handlePatchFileBrowseButtonPressed(); - updateWidgetEnablements(); - } - } - ); - - //fPatchFileNameField.setFocus(); - } - - private void buildInputGroup(Composite parent) { - - PatchWizard pw= (PatchWizard) getWizard(); - IResource target= pw.getTarget(); - IWorkspace workspace= target.getWorkspace(); - IWorkspaceRoot root= workspace.getRoot(); - - Tree tree= new Tree(parent, SWT.BORDER); - GridData gd= new GridData(GridData.FILL_HORIZONTAL); - gd.heightHint= 200; - tree.setLayoutData(gd); - - fPatchTargets= new CheckboxTreeViewer(tree); - fPatchTargets.setLabelProvider(new WorkbenchLabelProvider()); - fPatchTargets.setContentProvider(new WorkbenchContentProvider()); - fPatchTargets.setSorter(new WorkbenchViewerSorter()); - fPatchTargets.setInput(root); - if (target != null) { - fPatchTargets.expandToLevel(target, 0); - fPatchTargets.setSelection(new StructuredSelection(target)); - } - - // register listeners - fPatchTargets.addSelectionChangedListener( - new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - fPatchWizard.setTarget(PatchWizard.getResource(event.getSelection())); - updateWidgetEnablements(); - } - } - ); - //fPatchFileNameField.setFocus(); - } - - /** - * Returns a content provider for IResources 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: + * + */ + String getContent() { + StringBuffer sb= new StringBuffer(); + for (int i= 0; i < fLines.length; i++) { + String line= fLines[i]; + sb.append(line.substring(0, Patcher.length(line))); + sb.append('\n'); + } + return sb.toString(); + } + + /** + * Returns a descriptive String for this hunk. + * It is in the form old_start,old_length -> new_start,new_length. + */ + String getDescription() { + StringBuffer sb= new StringBuffer(); + sb.append(Integer.toString(fOldStart)); + sb.append(','); + sb.append(Integer.toString(fOldLength)); + sb.append(" -> "); //$NON-NLS-1$ + sb.append(Integer.toString(fNewStart)); + sb.append(','); + sb.append(Integer.toString(fNewLength)); + return sb.toString(); + } + + String getRejectedDescription() { + StringBuffer sb= new StringBuffer(); + sb.append("@@ -"); //$NON-NLS-1$ + sb.append(Integer.toString(fOldStart)); + sb.append(','); + sb.append(Integer.toString(fOldLength)); + sb.append(" +"); //$NON-NLS-1$ + sb.append(Integer.toString(fNewStart)); + sb.append(','); + sb.append(Integer.toString(fNewLength)); + sb.append(" @@"); //$NON-NLS-1$ + return sb.toString(); + } +} diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/InputPatchPage.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/InputPatchPage.java new file mode 100644 index 000000000..988036dc1 --- /dev/null +++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/InputPatchPage.java @@ -0,0 +1,609 @@ +/* + * (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.dnd.*; +import org.eclipse.swt.events.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +import org.eclipse.jface.dialogs.*; +import org.eclipse.jface.viewers.*; +import org.eclipse.jface.wizard.*; + +import org.eclipse.ui.help.*; +import org.eclipse.ui.model.*; + +import org.eclipse.core.resources.*; +import org.eclipse.core.runtime.*; + +import org.eclipse.compare.internal.Utilities; + + +/* package */ class InputPatchPage extends WizardPage { + + // constants + protected static final int SIZING_TEXT_FIELD_WIDTH= 250; + protected static final int COMBO_HISTORY_LENGTH= 5; + + private final static int SIZING_SELECTION_WIDGET_WIDTH= 400; + private final static int SIZING_SELECTION_WIDGET_HEIGHT= 150; + + // dialog store id constants + private final static String PAGE_NAME= "PatchWizardPage1"; //$NON-NLS-1$ + private final static String STORE_PATCH_FILE_ID= PAGE_NAME + ".PATCH_FILE"; //$NON-NLS-1$ + private final static String STORE_PATCH_FILES_ID= PAGE_NAME + ".PATCH_FILES"; //$NON-NLS-1$ + private final static String STORE_USE_CLIPBOARD_ID= PAGE_NAME + ".USE_CLIPBOARD"; //$NON-NLS-1$ + + // help IDs + private final static String PATCH_HELP_CONTEXT_ID= "PatchWizardHelpId"; //$NON-NLS-1$ + + // SWT widgets + private Button fUseClipboardButton; + private Combo fPatchFileNameField; + private Button fPatchFileBrowseButton; + private Button fUsePatchFileButton; + private Group fPatchFileGroup; + private CheckboxTreeViewer fPatchTargets; + private PatchWizard fPatchWizard; + + + InputPatchPage(PatchWizard pw) { + super("InputPatchPage", PatchMessages.getString("InputPatchPage.title"), null); //$NON-NLS-1$ //$NON-NLS-2$ + fPatchWizard= pw; + setMessage(PatchMessages.getString("InputPatchPage.message")); //$NON-NLS-1$ + } + + /** + * Get a path from the supplied text widget. + * @return org.eclipse.core.runtime.IPath + */ + protected IPath getPathFromText(Text textField) { + return (new Path(textField.getText())).makeAbsolute(); + } + + /* package */ String getPatchName() { + if (getUseClipboard()) + return PatchMessages.getString("InputPatchPage.Clipboard"); //$NON-NLS-1$ + return getPatchFilePath(); + } + + 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); + + Label l= new Label(composite, SWT.NONE); // a spacer + l.setText(PatchMessages.getString("InputPatchPage.SelectInput")); //$NON-NLS-1$ + buildInputGroup(composite); + + new Label(composite, SWT.NONE); // a spacer + + buildPatchFileGroup(composite); + + restoreWidgetValues(); + + updateWidgetEnablements(); + //updatePageCompletion(); + + WorkbenchHelp.setHelp(composite, new DialogPageContextComputer(this, PATCH_HELP_CONTEXT_ID)); + } + + /* (non-JavaDoc) + * Method declared in IWizardPage. + */ + public IWizardPage getNextPage() { + if (true) { + + Patcher patcher= ((PatchWizard) getWizard()).getPatcher(); + + // Create a reader for the input + Reader reader= null; + if (getUseClipboard()) { + Control c= getControl(); + if (c != null) { + Clipboard clipboard= new Clipboard(c.getDisplay()); + Object o= clipboard.getContents(TextTransfer.getInstance()); + if (o instanceof String) + reader= new StringReader((String)o); + } + } else { + String patchFilePath= getPatchFilePath(); + if (patchFilePath != null) { + try { + reader= new FileReader(patchFilePath); + } catch (FileNotFoundException ex) { + MessageDialog.openError(null, + PatchMessages.getString("InputPatchPage.PatchErrorDialog.title"), //$NON-NLS-1$ + PatchMessages.getString("InputPatchPage.PatchFileNotFound.message")); //$NON-NLS-1$ + } + } + } + + // parse the input + if (reader != null) { + try { + patcher.parse(new BufferedReader(reader)); + } catch (IOException ex) { + MessageDialog.openError(null, + PatchMessages.getString("InputPatchPage.PatchErrorDialog.title_2"), //$NON-NLS-1$ + PatchMessages.getString("InputPatchPage.ParseError.message")); //$NON-NLS-1$ + } + + try { + reader.close(); + } catch (IOException x) { + } + } + + Diff[] diffs= patcher.getDiffs(); + if (diffs == null || diffs.length == 0) { + MessageDialog.openError(null, + PatchMessages.getString("InputPatchPage.PatchErrorDialog.title_4"), //$NON-NLS-1$ + PatchMessages.getString("InputPatchPage.NoDiffsFound.message")); //$NON-NLS-1$ + return this; + } + + // guess prefix count + int guess= guessPrefix(diffs); + patcher.setStripPrefixSegments(guess); + } + return super.getNextPage(); + } + + private int guessPrefix(Diff[] diffs) { + ArrayList list= new ArrayList(); + IResource target= fPatchWizard.getTarget(); + if (target instanceof IFile) { + list.add(target.getFullPath()); + } else if (target instanceof IContainer) { + addLeaf(list, (IContainer) target); + } + + // guess prefix count + for (int i= 0; i < diffs.length; i++) { + IPath p= diffs[i].fOldPath; + if (p != null) { + int matches= match(p, list); + if (matches > 0) { + return p.segmentCount() - matches; + } + } + } + return 0; + } + + private int match(IPath path, ArrayList list) { + Iterator iter= list.iterator(); + while (iter.hasNext()) { + IPath filePath= (IPath) iter.next(); + int matches= matchTrailingSegments(path, filePath); + if (matches > 0) + return matches; + //System.out.println(" " + filePath + ": " + matches); + } + return 0; + } + + private int matchTrailingSegments(IPath p1, IPath p2) { + int matches= 0; + int i1= p1.segmentCount()-1; + int i2= p2.segmentCount()-1; + for (; i1 >= 0 && i2 >= 0; i1--, i2--) { + String s1= p1.segment(i1); + String s2= p2.segment(i2); + if (!s1.equals(s2)) + break; + matches++; + } + return matches; + } + + private void addLeaf(ArrayList list, IContainer c) { + IResource[] rs= null; + try { + rs= c.members(); + } catch(CoreException ex) { + } + if (rs != null) { + for (int i= 0; i < rs.length; i++) { + IResource r= rs[i]; + if (r instanceof IFile) + list.add(r.getFullPath()); + else if (r instanceof IContainer) + addLeaf(list, (IContainer) r); + } + } + } + + /* (non-JavaDoc) + * Method declared in IWizardPage. + */ + public boolean canFlipToNextPage() { + if (true) { + // we can't call getNextPage to determine if flipping is allowed since computing + // the next page is quite expensive (checking preconditions and creating a + // change). So we say yes if the page is complete. + return isPageComplete(); + } else { + return super.canFlipToNextPage(); + } + } + + private void setEnablePatchFile(boolean enable) { + fPatchFileNameField.setEnabled(enable); + fPatchFileBrowseButton.setEnabled(enable); + } + + /** + * Create the group for selecting the patch file + */ + private void buildPatchFileGroup(Composite parent) { + + fPatchFileGroup= new Group(parent, SWT.NONE); + fPatchFileGroup.setText(PatchMessages.getString("InputPatchPage.SelectPatch.title")); //$NON-NLS-1$ + GridLayout layout= new GridLayout(); + layout.numColumns= 3; + fPatchFileGroup.setLayout(layout); + fPatchFileGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // 1st row + fUsePatchFileButton= new Button(fPatchFileGroup, SWT.RADIO); + fUsePatchFileButton.setText(PatchMessages.getString("InputPatchPage.FileButton.text")); //$NON-NLS-1$ + + fPatchFileNameField= new Combo(fPatchFileGroup, SWT.BORDER); + GridData gd= new GridData(GridData.FILL_HORIZONTAL); + //gd.horizontalIndent= 8; + gd.widthHint= SIZING_TEXT_FIELD_WIDTH; + fPatchFileNameField.setLayoutData(gd); + + fPatchFileBrowseButton= new Button(fPatchFileGroup, SWT.PUSH); + fPatchFileBrowseButton.setText(PatchMessages.getString("InputPatchPage.ChooseFileButton.text")); //$NON-NLS-1$ + fPatchFileBrowseButton.setLayoutData(new GridData()); + + // 2nd row + fUseClipboardButton= new Button(fPatchFileGroup, SWT.RADIO); + fUseClipboardButton.setText(PatchMessages.getString("InputPatchPage.UseClipboardButton.text")); //$NON-NLS-1$ + gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); + gd.horizontalSpan= 2; + fUseClipboardButton.setLayoutData(gd); + + + // Add listeners + fUsePatchFileButton.addSelectionListener( + new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + setEnablePatchFile(!getUseClipboard()); + updateWidgetEnablements(); + } + } + ); + fPatchFileNameField.addSelectionListener( + new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + setSourceName(fPatchFileNameField.getText()); + updateWidgetEnablements(); + } + } + ); + fPatchFileNameField.addModifyListener( + new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateWidgetEnablements(); + } + } + ); + fPatchFileBrowseButton.addSelectionListener( + new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + handlePatchFileBrowseButtonPressed(); + updateWidgetEnablements(); + } + } + ); + + //fPatchFileNameField.setFocus(); + } + + private void buildInputGroup(Composite parent) { + + PatchWizard pw= (PatchWizard) getWizard(); + IResource target= pw.getTarget(); + IWorkspace workspace= target.getWorkspace(); + IWorkspaceRoot root= workspace.getRoot(); + + Tree tree= new Tree(parent, SWT.BORDER); + GridData gd= new GridData(GridData.FILL_HORIZONTAL); + gd.heightHint= 200; + tree.setLayoutData(gd); + + fPatchTargets= new CheckboxTreeViewer(tree); + fPatchTargets.setLabelProvider(new WorkbenchLabelProvider()); + fPatchTargets.setContentProvider(new WorkbenchContentProvider()); + fPatchTargets.setSorter(new WorkbenchViewerSorter()); + fPatchTargets.setInput(root); + if (target != null) { + fPatchTargets.expandToLevel(target, 0); + fPatchTargets.setSelection(new StructuredSelection(target)); + } + + // register listeners + fPatchTargets.addSelectionChangedListener( + new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + fPatchWizard.setTarget(PatchWizard.getResource(event.getSelection())); + updateWidgetEnablements(); + } + } + ); + //fPatchFileNameField.setFocus(); + } + + /** + * Returns a content provider for IResources 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: - * - */ - String getContent() { - StringBuffer sb= new StringBuffer(); - for (int i= 0; i < fLines.length; i++) { - String line= fLines[i]; - sb.append(line.substring(0, Patcher.length(line))); - sb.append('\n'); - } - return sb.toString(); - } - - /** - * Returns a descriptive String for this hunk. - * It is in the form old_start,old_length -> new_start,new_length. - */ - String getDescription() { - StringBuffer sb= new StringBuffer(); - sb.append(Integer.toString(fOldStart)); - sb.append(','); - sb.append(Integer.toString(fOldLength)); - sb.append(" -> "); //$NON-NLS-1$ - sb.append(Integer.toString(fNewStart)); - sb.append(','); - sb.append(Integer.toString(fNewLength)); - return sb.toString(); - } -} diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/InputPatchPage.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/InputPatchPage.java deleted file mode 100644 index c0535baf3..000000000 --- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/patch/InputPatchPage.java +++ /dev/null @@ -1,604 +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.dnd.*; -import org.eclipse.swt.events.*; -import org.eclipse.swt.layout.*; -import org.eclipse.swt.widgets.*; - -import org.eclipse.jface.dialogs.*; -import org.eclipse.jface.viewers.*; -import org.eclipse.jface.wizard.*; - -import org.eclipse.ui.help.*; -import org.eclipse.ui.model.*; - -import org.eclipse.core.resources.*; -import org.eclipse.core.runtime.*; - -import org.eclipse.compare.internal.Utilities; - - -/* package */ class InputPatchPage extends WizardPage { - - // constants - protected static final int SIZING_TEXT_FIELD_WIDTH= 250; - protected static final int COMBO_HISTORY_LENGTH= 5; - - private final static int SIZING_SELECTION_WIDGET_WIDTH= 400; - private final static int SIZING_SELECTION_WIDGET_HEIGHT= 150; - - // dialog store id constants - private final static String PAGE_NAME= "PatchWizardPage1"; //$NON-NLS-1$ - private final static String STORE_PATCH_FILE_ID= PAGE_NAME + ".PATCH_FILE"; //$NON-NLS-1$ - private final static String STORE_PATCH_FILES_ID= PAGE_NAME + ".PATCH_FILES"; //$NON-NLS-1$ - private final static String STORE_USE_CLIPBOARD_ID= PAGE_NAME + ".USE_CLIPBOARD"; //$NON-NLS-1$ - - // help IDs - private final static String PATCH_HELP_CONTEXT_ID= "PatchWizardHelpId"; //$NON-NLS-1$ - - // SWT widgets - private Button fUseClipboardButton; - private Combo fPatchFileNameField; - private Button fPatchFileBrowseButton; - private Button fUsePatchFileButton; - private Group fPatchFileGroup; - private CheckboxTreeViewer fPatchTargets; - private PatchWizard fPatchWizard; - - - InputPatchPage(PatchWizard pw) { - super("InputPatchPage", "Patch Input Specification", null); - fPatchWizard= pw; - setMessage("Define what resource to patch with which patch."); - } - - /** - * Get a path from the supplied text widget. - * @return org.eclipse.core.runtime.IPath - */ - protected IPath getPathFromText(Text textField) { - return (new Path(textField.getText())).makeAbsolute(); - } - - /* package */ String getPatchName() { - if (getUseClipboard()) - return "Clipboard"; - return getPatchFilePath(); - } - - 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); - - Label l= new Label(composite, SWT.NONE); // a spacer - l.setText("Select a single file or folder to patch:"); - buildInputGroup(composite); - - new Label(composite, SWT.NONE); // a spacer - - buildPatchFileGroup(composite); - - restoreWidgetValues(); - - updateWidgetEnablements(); - //updatePageCompletion(); - - WorkbenchHelp.setHelp(composite, new DialogPageContextComputer(this, PATCH_HELP_CONTEXT_ID)); - } - - /* (non-JavaDoc) - * Method declared in IWizardPage. - */ - public IWizardPage getNextPage() { - if (true) { - - Patcher patcher= ((PatchWizard) getWizard()).getPatcher(); - - // Create a reader for the input - Reader reader= null; - if (getUseClipboard()) { - Control c= getControl(); - if (c != null) { - Clipboard clipboard= new Clipboard(c.getDisplay()); - Object o= clipboard.getContents(TextTransfer.getInstance()); - if (o instanceof String) - reader= new StringReader((String)o); - } - } else { - String patchFilePath= getPatchFilePath(); - if (patchFilePath != null) { - try { - reader= new FileReader(patchFilePath); - } catch (FileNotFoundException ex) { - MessageDialog.openError(null, "Error", "Patch file not found: " + patchFilePath); - } - } - } - - // parse the input - if (reader != null) { - try { - patcher.parse(new BufferedReader(reader)); - } catch (IOException ex) { - MessageDialog.openError(null, "Error", "Error while parsing patch"); - } - - try { - reader.close(); - } catch (IOException x) { - } - } - - Diff[] diffs= patcher.getDiffs(); - if (diffs == null || diffs.length == 0) { - MessageDialog.openError(null, "Error", "No diffs found in " + getPatchName()); - return this; - } - - // guess prefix count - int guess= guessPrefix(diffs); - patcher.setStripPrefixSegments(guess); - } - return super.getNextPage(); - } - - private int guessPrefix(Diff[] diffs) { - ArrayList list= new ArrayList(); - IResource target= fPatchWizard.getTarget(); - if (target instanceof IFile) { - list.add(target.getFullPath()); - } else if (target instanceof IContainer) { - addLeaf(list, (IContainer) target); - } - - // guess prefix count - for (int i= 0; i < diffs.length; i++) { - IPath p= diffs[i].fOldPath; - if (p != null) { - int matches= match(p, list); - if (matches > 0) { - return p.segmentCount() - matches; - } - } - } - return 0; - } - - private int match(IPath path, ArrayList list) { - Iterator iter= list.iterator(); - while (iter.hasNext()) { - IPath filePath= (IPath) iter.next(); - int matches= matchTrailingSegments(path, filePath); - if (matches > 0) - return matches; - //System.out.println(" " + filePath + ": " + matches); - } - return 0; - } - - private int matchTrailingSegments(IPath p1, IPath p2) { - int matches= 0; - int i1= p1.segmentCount()-1; - int i2= p2.segmentCount()-1; - for (; i1 >= 0 && i2 >= 0; i1--, i2--) { - String s1= p1.segment(i1); - String s2= p2.segment(i2); - if (!s1.equals(s2)) - break; - matches++; - } - return matches; - } - - private void addLeaf(ArrayList list, IContainer c) { - IResource[] rs= null; - try { - rs= c.members(); - } catch(CoreException ex) { - } - if (rs != null) { - for (int i= 0; i < rs.length; i++) { - IResource r= rs[i]; - if (r instanceof IFile) - list.add(r.getFullPath()); - else if (r instanceof IContainer) - addLeaf(list, (IContainer) r); - } - } - } - - /* (non-JavaDoc) - * Method declared in IWizardPage. - */ - public boolean canFlipToNextPage() { - if (true) { - // we can't call getNextPage to determine if flipping is allowed since computing - // the next page is quite expensive (checking preconditions and creating a - // change). So we say yes if the page is complete. - return isPageComplete(); - } else { - return super.canFlipToNextPage(); - } - } - - private void setEnablePatchFile(boolean enable) { - fPatchFileNameField.setEnabled(enable); - fPatchFileBrowseButton.setEnabled(enable); - } - - /** - * Create the group for selecting the patch file - */ - private void buildPatchFileGroup(Composite parent) { - - fPatchFileGroup= new Group(parent, SWT.NONE); - fPatchFileGroup.setText("Select Patch"); - GridLayout layout= new GridLayout(); - layout.numColumns= 3; - fPatchFileGroup.setLayout(layout); - fPatchFileGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - // 1st row - fUsePatchFileButton= new Button(fPatchFileGroup, SWT.RADIO); - fUsePatchFileButton.setText("File "); - - fPatchFileNameField= new Combo(fPatchFileGroup, SWT.BORDER); - GridData gd= new GridData(GridData.FILL_HORIZONTAL); - //gd.horizontalIndent= 8; - gd.widthHint= SIZING_TEXT_FIELD_WIDTH; - fPatchFileNameField.setLayoutData(gd); - - fPatchFileBrowseButton= new Button(fPatchFileGroup, SWT.PUSH); - fPatchFileBrowseButton.setText("Choose..."); - fPatchFileBrowseButton.setLayoutData(new GridData()); - - // 2nd row - fUseClipboardButton= new Button(fPatchFileGroup, SWT.RADIO); - fUseClipboardButton.setText("Clipboard"); - gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); - gd.horizontalSpan= 2; - fUseClipboardButton.setLayoutData(gd); - - - // Add listeners - fUsePatchFileButton.addSelectionListener( - new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - setEnablePatchFile(!getUseClipboard()); - updateWidgetEnablements(); - } - } - ); - fPatchFileNameField.addSelectionListener( - new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - setSourceName(fPatchFileNameField.getText()); - updateWidgetEnablements(); - } - } - ); - fPatchFileNameField.addModifyListener( - new ModifyListener() { - public void modifyText(ModifyEvent e) { - updateWidgetEnablements(); - } - } - ); - fPatchFileBrowseButton.addSelectionListener( - new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - handlePatchFileBrowseButtonPressed(); - updateWidgetEnablements(); - } - } - ); - - //fPatchFileNameField.setFocus(); - } - - private void buildInputGroup(Composite parent) { - - PatchWizard pw= (PatchWizard) getWizard(); - IResource target= pw.getTarget(); - IWorkspace workspace= target.getWorkspace(); - IWorkspaceRoot root= workspace.getRoot(); - - Tree tree= new Tree(parent, SWT.BORDER); - GridData gd= new GridData(GridData.FILL_HORIZONTAL); - gd.heightHint= 200; - tree.setLayoutData(gd); - - fPatchTargets= new CheckboxTreeViewer(tree); - fPatchTargets.setLabelProvider(new WorkbenchLabelProvider()); - fPatchTargets.setContentProvider(new WorkbenchContentProvider()); - fPatchTargets.setSorter(new WorkbenchViewerSorter()); - fPatchTargets.setInput(root); - if (target != null) { - fPatchTargets.expandToLevel(target, 0); - fPatchTargets.setSelection(new StructuredSelection(target)); - } - - // register listeners - fPatchTargets.addSelectionChangedListener( - new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - fPatchWizard.setTarget(PatchWizard.getResource(event.getSelection())); - updateWidgetEnablements(); - } - } - ); - //fPatchFileNameField.setFocus(); - } - - /** - * Returns a content provider for IResources 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