Update of /cvsroot/jcommander/plugins/org.jcommander.eclipsepatch.compare/compare/org/eclipse/compare/internal/patch In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5127/compare/org/eclipse/compare/internal/patch Added Files: Diff.java PatchMessages.java Hunk.java CompareWithPatchAction.java PatchMessages.properties PatchTargetPage.java PreviewPatchLabelDecorator.java LineReader.java PatchWizard.java InputPatchPage.java PreviewPatchPage.java PatchErrorDialog.java WorkspacePatcher.java DiffProject.java Patcher.java Log Message: org.eclipse.compare, extracted from the Eclipse CVS. Now independent of org.eclipse.ui.ide etc. --- NEW FILE: PreviewPatchPage.java --- /******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Sebastian Davids <sd...@gm...> - layout tweaks *******************************************************************************/ package org.eclipse.compare.internal.patch; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.compare.CompareConfiguration; import org.eclipse.compare.CompareUI; import org.eclipse.compare.CompareViewerSwitchingPane; import org.eclipse.compare.IEncodedStreamContentAccessor; import org.eclipse.compare.ITypedElement; import org.eclipse.compare.Splitter; import org.eclipse.compare.internal.ICompareContextIds; import org.eclipse.compare.internal.Utilities; import org.eclipse.compare.structuremergeviewer.DiffNode; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.compare.structuremergeviewer.ICompareInput; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.DecoratingLabelProvider; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.ICheckable; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer; import org.eclipse.ui.model.BaseWorkbenchContentProvider; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.eclipse.ui.model.WorkbenchViewerSorter; import org.eclipse.ui.views.navigator.ResourceSorter; /** * 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, IEncodedStreamContentAccessor { static final String UTF_16= "UTF-16"; //$NON-NLS-1$ String fContent; String fType; HunkInput(String type, String s) { fType= type; fContent= s; } public Image getImage() { return null; } public String getName() { return PatchMessages.PreviewPatchPage_NoName_text; } public String getType() { return fType; } public InputStream getContents() { return new ByteArrayInputStream(Utilities.getBytes(fContent, UTF_16)); } public String getCharset() { return UTF_16; } } class RetargetPatchDialog extends Dialog { protected TreeViewer rpTreeViewer; protected DiffProject rpSelectedProject; protected IProject rpTargetProject; public RetargetPatchDialog(Shell shell, ISelection selection) { super(shell); setShellStyle(getShellStyle()|SWT.RESIZE); if (selection instanceof IStructuredSelection) { rpSelectedProject= (DiffProject) ((IStructuredSelection) selection).getFirstElement(); } } protected Control createDialogArea(Composite parent) { Composite composite= (Composite) super.createDialogArea(parent); initializeDialogUnits(parent); getShell().setText(PatchMessages.PreviewPatchPage_RetargetPatch); GridLayout layout= new GridLayout(); layout.numColumns= 1; layout.marginHeight= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); composite.setLayout(layout); final GridData data= new GridData(SWT.FILL, SWT.FILL, true, true); composite.setLayoutData(data); //add controls to composite as necessary Label label= new Label(composite, SWT.LEFT|SWT.WRAP); label.setText(NLS.bind(PatchMessages.PreviewPatchPage_SelectProject, rpSelectedProject.getName())); final GridData data2= new GridData(SWT.FILL, SWT.BEGINNING, true, false); label.setLayoutData(data2); rpTreeViewer= new TreeViewer(composite, SWT.BORDER); GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true); gd.widthHint= 0; gd.heightHint= 0; rpTreeViewer.getTree().setLayoutData(gd); rpTreeViewer.setContentProvider(new RetargetPatchContentProvider()); rpTreeViewer.setLabelProvider(new WorkbenchLabelProvider()); rpTreeViewer.setSorter(new ResourceSorter(ResourceSorter.NAME)); rpTreeViewer.setInput(ResourcesPlugin.getWorkspace()); rpTreeViewer.setSelection(new StructuredSelection(rpSelectedProject.getProject())); setupListeners(); Dialog.applyDialogFont(composite); return parent; } protected void okPressed() { rpSelectedProject.setProject(rpTargetProject); super.okPressed(); } void setupListeners() { rpTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection s= (IStructuredSelection) event.getSelection(); Object obj= s.getFirstElement(); if (obj instanceof IProject) rpTargetProject= (IProject) obj; } }); rpTreeViewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { ISelection s= event.getSelection(); if (s instanceof IStructuredSelection) { Object item= ((IStructuredSelection) s).getFirstElement(); if (rpTreeViewer.getExpandedState(item)) rpTreeViewer.collapseToLevel(item, 1); else rpTreeViewer.expandToLevel(item, 1); } } }); } protected Point getInitialSize() { final Point size= super.getInitialSize(); size.x= convertWidthInCharsToPixels(75); size.y+= convertHeightInCharsToPixels(20); return size; } } class RetargetPatchContentProvider extends BaseWorkbenchContentProvider { //Never show closed projects boolean showClosedProjects= false; public Object[] getChildren(Object element) { if (element instanceof IWorkspace) { // check if closed projects should be shown IProject[] allProjects= ((IWorkspace) element).getRoot().getProjects(); if (showClosedProjects) return allProjects; ArrayList accessibleProjects= new ArrayList(); for (int i= 0; i<allProjects.length; i++) { if (allProjects[i].isOpen()) { accessibleProjects.add(allProjects[i]); } } return accessibleProjects.toArray(); } if (element instanceof IProject) { return new Object[0]; } return super.getChildren(element); } } private PatchWizard fPatchWizard; private ContainerCheckedTreeViewer fTreeViewer; private Combo fStripPrefixSegments; private CompareViewerSwitchingPane fHunkViewer; private Button fIgnoreWhitespaceButton; private Button fReversePatchButton; private Text fFuzzField; private Button fMatchProject; private Object inputElement; private CompareConfiguration fCompareConfiguration; protected boolean pageRecalculate= true; protected final static String PREVIEWPATCHPAGE_NAME= "PreviewPatchPage"; //$NON-NLS-1$ /* package */ PreviewPatchPage(PatchWizard pw) { super(PREVIEWPATCHPAGE_NAME, PatchMessages.PreviewPatchPage_title, null); setMessage(PatchMessages.PreviewPatchPage_message); fPatchWizard= pw; //setPageComplete(false); fCompareConfiguration= new CompareConfiguration(); fCompareConfiguration.setLeftEditable(false); fCompareConfiguration.setLeftLabel(PatchMessages.PreviewPatchPage_Left_title); fCompareConfiguration.setRightEditable(false); fCompareConfiguration.setRightLabel(PatchMessages.PreviewPatchPage_Right_title); } /* (non-Javadoc) * Method declared in WizardPage */ public void setVisible(boolean visible) { if (visible) { buildTree(); updateTree(); } super.setVisible(visible); } 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)); PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ICompareContextIds.PATCH_PREVIEW_WIZARD_PAGE); setControl(composite); initializeDialogUnits(parent); buildPatchOptionsGroup(composite); Splitter splitter= new Splitter(composite, SWT.VERTICAL); splitter.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL)); // top pane showing diffs and hunks in a check box tree createTreeViewer(splitter); // bottom pane showing hunks in compare viewer fHunkViewer= new CompareViewerSwitchingPane(splitter, SWT.BORDER|SWT.FLAT) { protected Viewer getViewer(Viewer oldViewer, Object input) { return CompareUI.findContentViewer(oldViewer, (ICompareInput) input, this, fCompareConfiguration); } }; fHunkViewer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); //create Match Project button fMatchProject= new Button(composite, SWT.PUSH); fMatchProject.setLayoutData(new GridData(SWT.END, GridData.BEGINNING, false, false)); fMatchProject.setText(PatchMessages.PreviewPatchPage_MatchProjects); fMatchProject.setEnabled(false); fMatchProject.setVisible(false); fMatchProject.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { final RetargetPatchDialog dialog= new RetargetPatchDialog(getShell(), fTreeViewer.getSelection()); dialog.open(); updateTree(); } }); // creating tree's content buildTree(); Dialog.applyDialogFont(composite); } private void createTreeViewer(Splitter splitter) { fTreeViewer= new ContainerCheckedTreeViewer(splitter, SWT.BORDER); fTreeViewer.setContentProvider(new BaseWorkbenchContentProvider()); fTreeViewer.setLabelProvider(new DecoratingLabelProvider(new WorkbenchLabelProvider(), new PreviewPatchLabelDecorator())); fTreeViewer.setSorter(new WorkbenchViewerSorter()); fTreeViewer.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { Object obj = event.getElement(); ICheckable checked = event.getCheckable(); DiffProject proj = null; if (obj instanceof DiffProject){ proj = (DiffProject) obj; // Check to see if any of the Diffs contained by the DiffProject // have their diff problems set Object[] diffs = proj.getChildren(null); for (int i= 0; i<diffs.length; i++) { if (((Diff) diffs[i]).containsProblems()){ checked.setChecked(obj, false); break; } } } else if (obj instanceof Diff){ proj = ((Diff) obj).getProject(); // If Diff has any diff problems set, at least one hunk underneath // does not match - so don't allow entire tree to be checked if (((Diff) obj).containsProblems()){ checked.setChecked(obj, false); } } else if (obj instanceof Hunk){ Diff diff = (Diff) ((Hunk) obj).getParent(null); proj = diff.getProject(); // Check to see if this hunk has any problems OR // if its parent has any problems if( diff.getDiffProblem() || ((Hunk) obj).getHunkProblem()){ checked.setChecked(obj, false); } } if (proj!= null && !proj.getProject().exists()){ checked.setChecked(obj, false); } updateEnablements(); } }); fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection sel= (IStructuredSelection) event.getSelection(); Object obj= sel.getFirstElement(); if (obj instanceof Hunk) { PreviewPatchPage.this.fHunkViewer.setInput(createInput((Hunk) obj)); } else PreviewPatchPage.this.fHunkViewer.setInput(null); fMatchProject.setEnabled(false); //See if we need to enable match project button if (fPatchWizard.getPatcher().isWorkspacePatch()&&obj instanceof DiffProject) { fMatchProject.setEnabled(true); } } }); fTreeViewer.setInput(null); } /* * Create the group for setting various patch options */ private void buildPatchOptionsGroup(Composite parent) { GridLayout gl; GridData gd; Label l; final WorkspacePatcher patcher= fPatchWizard.getPatcher(); Group group= new Group(parent, SWT.NONE); group.setText(PatchMessages.PreviewPatchPage_PatchOptions_title); gl= new GridLayout(); gl.numColumns= 4; group.setLayout(gl); group.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL|GridData.GRAB_HORIZONTAL)); // 1st row Composite pair= new Composite(group, SWT.NONE); gl= new GridLayout(); gl.numColumns= 2; gl.marginHeight= gl.marginWidth= 0; pair.setLayout(gl); gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL); pair.setLayoutData(gd); l= new Label(pair, SWT.NONE); l.setText(PatchMessages.PreviewPatchPage_IgnoreSegments_text); gd= new GridData(GridData.VERTICAL_ALIGN_CENTER|GridData.HORIZONTAL_ALIGN_BEGINNING|GridData.GRAB_HORIZONTAL); l.setLayoutData(gd); fStripPrefixSegments= new Combo(pair, SWT.DROP_DOWN|SWT.READ_ONLY|SWT.SIMPLE); int prefixCnt= patcher.getStripPrefixSegments(); String prefix= Integer.toString(prefixCnt); fStripPrefixSegments.add(prefix); fStripPrefixSegments.setText(prefix); gd= new GridData(GridData.VERTICAL_ALIGN_CENTER|GridData.HORIZONTAL_ALIGN_END); fStripPrefixSegments.setLayoutData(gd); addSpacer(group); fReversePatchButton= new Button(group, SWT.CHECK); fReversePatchButton.setText(PatchMessages.PreviewPatchPage_ReversePatch_text); addSpacer(group); // 2nd row pair= new Composite(group, SWT.NONE); gl= new GridLayout(); gl.numColumns= 3; gl.marginHeight= gl.marginWidth= 0; pair.setLayout(gl); gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL); pair.setLayoutData(gd); l= new Label(pair, SWT.NONE); l.setText(PatchMessages.PreviewPatchPage_FuzzFactor_text); l.setToolTipText(PatchMessages.PreviewPatchPage_FuzzFactor_tooltip); gd= new GridData(GridData.VERTICAL_ALIGN_CENTER|GridData.HORIZONTAL_ALIGN_BEGINNING|GridData.GRAB_HORIZONTAL); l.setLayoutData(gd); fFuzzField= new Text(pair, SWT.BORDER); fFuzzField.setText("2"); //$NON-NLS-1$ gd= new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_END); gd.widthHint= 30; fFuzzField.setLayoutData(gd); Button b= new Button(pair, SWT.PUSH); b.setText(PatchMessages.PreviewPatchPage_GuessFuzz_text); b.addSelectionListener( new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int fuzz= guessFuzzFactor(patcher); if (fuzz>=0) fFuzzField.setText(Integer.toString(fuzz)); } } ); gd= new GridData(GridData.VERTICAL_ALIGN_CENTER); int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); Point minSize = b.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); gd.widthHint = Math.max(widthHint, minSize.x); b.setLayoutData(gd); addSpacer(group); fIgnoreWhitespaceButton= new Button(group, SWT.CHECK); fIgnoreWhitespaceButton.setText(PatchMessages.PreviewPatchPage_IgnoreWhitespace_text); 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(); } }); } private int guessFuzzFactor(final WorkspacePatcher patcher) { final int strip= getStripPrefixSegments(); final int[] result= new int[1]; try { PlatformUI.getWorkbench().getProgressService().run(true, true, //TimeoutContext.run(true, GUESS_TIMEOUT, getControl().getShell(), new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { result[0]= guess(patcher, monitor, strip); } } ); return result[0]; } catch (InvocationTargetException ex) { // NeedWork } catch (InterruptedException ex) { // NeedWork } return -1; } private int guess(WorkspacePatcher patcher, IProgressMonitor pm, int strip) { Diff[] diffs= patcher.getDiffs(); if (diffs==null||diffs.length<=0) return -1; // now collect files and determine "work" IFile[] files= new IFile[diffs.length]; int work= 0; for (int i= 0; i<diffs.length; i++) { Diff diff= diffs[i]; if (diff==null) continue; if (diff.getType()!=Differencer.ADDITION) { IPath p= diff.fOldPath; if (strip>0&&strip<p.segmentCount()) p= p.removeFirstSegments(strip); IFile file= existsInSelection(p); if (file!=null) { files[i]= file; work+= diff.fHunks.size(); } } } // do the "work" int[] fuzzRef= new int[1]; String format= PatchMessages.PreviewPatchPage_GuessFuzzProgress_format; pm.beginTask(PatchMessages.PreviewPatchPage_GuessFuzzProgress_text, work); try { int fuzz= 0; for (int i= 0; i<diffs.length; i++) { Diff d= diffs[i]; IFile file= files[i]; if (d!=null&&file!=null) { List lines= patcher.load(file, false); String name= d.getPath().lastSegment(); Iterator iter= d.fHunks.iterator(); int shift= 0; for (int hcnt= 1; iter.hasNext(); hcnt++) { pm.subTask(MessageFormat.format(format, new String[] {name, Integer.toString(hcnt)})); Hunk h= (Hunk) iter.next(); shift= patcher.calculateFuzz(h, lines, shift, pm, fuzzRef); int f= fuzzRef[0]; if (f==-1) // cancel return -1; if (f>fuzz) fuzz= f; pm.worked(1); } } } return fuzz; } finally { pm.done(); } } 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())); } private IFile existsInSelection(IPath path) { return fPatchWizard.getPatcher().existsInTarget(path); } private void buildTree() { inputElement= fPatchWizard.getPatcher(); //Update prefix count - go through all of the diffs and find the smallest //path segment contained in all diffs. int length= 99; if (fStripPrefixSegments!=null&&pageRecalculate) { length= fPatchWizard.getPatcher().calculatePrefixSegmentCount(); if (length!=99) { for (int k= 1; k<length; k++) fStripPrefixSegments.add(Integer.toString(k)); pageRecalculate= false; } } fTreeViewer.setInput(inputElement); } /** * Updates label and checked state of tree items. */ private void updateTree() { if (fTreeViewer==null) return; int strip= getStripPrefixSegments(); //Get the elements from the content provider BaseWorkbenchContentProvider contentProvider= (BaseWorkbenchContentProvider) fTreeViewer.getContentProvider(); Object[] projects= contentProvider.getElements(inputElement); ArrayList hunksToCheck= new ArrayList(); //Iterate through projects and call reset on each project for (int j= 0; j<projects.length; j++) { if (projects[j] instanceof DiffProject) { DiffProject project= (DiffProject) projects[j]; hunksToCheck.addAll(project.reset(fPatchWizard.getPatcher(), strip, getFuzzFactor())); for (Iterator iter= project.fDiffs.iterator(); iter.hasNext();) { Diff diff= (Diff) iter.next(); fTreeViewer.update(diff, null); } } else { if (projects[j] instanceof Diff) { Diff diff= (Diff) projects[j]; hunksToCheck.addAll(diff.reset(fPatchWizard.getPatcher(), strip, getFuzzFactor())); fTreeViewer.update(diff, null); } } } fTreeViewer.refresh(); fTreeViewer.setCheckedElements(hunksToCheck.toArray()); updateEnablements(); } 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) { // silently ignored } } return stripPrefixSegments; } private int getFuzzFactor() { int fuzzFactor= 0; if (fFuzzField!=null) { String s= fFuzzField.getText(); try { fuzzFactor= Integer.parseInt(s); } catch (NumberFormatException ex) { // silently ignored } } return fuzzFactor; } /** * Makes sure that at least one hunk is checked off in the tree before * allowing the patch to be applied. */ /* private */void updateEnablements() { boolean atLeastOneIsEnabled= false; if (fTreeViewer!=null) { BaseWorkbenchContentProvider contentProvider= (BaseWorkbenchContentProvider) fTreeViewer.getContentProvider(); Object[] projects= contentProvider.getElements(inputElement); //Iterate through projects for (int j= 0; j<projects.length; j++) { if (projects[j] instanceof DiffProject) { DiffProject project= (DiffProject) projects[j]; //Iterate through project diffs Object[] diffs= project.getChildren(project); for (int i= 0; i<diffs.length; i++) { Diff diff= (Diff) diffs[i]; atLeastOneIsEnabled= updateEnablement(atLeastOneIsEnabled, diff); } } else if (projects[j] instanceof Diff) { Diff diff= (Diff) projects[j]; atLeastOneIsEnabled= updateEnablement(atLeastOneIsEnabled, diff); } } } //Check to see if Match Project button should be visible fMatchProject.setVisible(fPatchWizard.getPatcher().isWorkspacePatch()); setPageComplete(atLeastOneIsEnabled); } private boolean updateEnablement(boolean atLeastOneIsEnabled, Diff diff) { boolean checked= fTreeViewer.getChecked(diff); diff.setEnabled(checked); if (checked) { Object[] hunkItems= diff.getChildren(diff); for (int h= 0; h<hunkItems.length; h++) { Hunk hunk= (Hunk) hunkItems[h]; checked= fTreeViewer.getChecked(hunk); hunk.setEnabled(checked); if (checked) { //For workspace patch: before setting enabled flag, make sure that the project //that contains this hunk actually exists in the workspace. This is to guard against the //case of having a new file in a patch that is being applied to a project that //doesn't currently exist. boolean projectExists= true; DiffProject project= (DiffProject)diff.getParent(null); if (project!= null){ projectExists=project.getProject().exists(); } if (projectExists) atLeastOneIsEnabled= true; } } } return atLeastOneIsEnabled; } } --- NEW FILE: PatchMessages.properties --- ############################################################################### # Copyright (c) 2000, 2006 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-v10.html # # Contributors: # IBM Corporation - initial API and implementation # Sebastian Davids <sd...@gm...> - layout tweaks ############################################################################### # # '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 have to be saved before this operation.\nClick 'OK' to confirm or click 'Cancel'. # # PatchWizard # PatchWizard_title=Apply Patch PatchWizard_unexpectedException_message= Unexpected exception while applying the patch. See log for a detailed error description. # # InputPatchPage # InputPatchPage_title= Patch Input Specification InputPatchPage_message= Select the patch location. InputPatchPage_Clipboard=Clipboard InputPatchPage_SelectInput=&Select a single file or folder to patch: InputPatchPage_PatchErrorDialog_title=Patch Error InputPatchPage_SelectPatch_title=Select Patch InputPatchPage_FileButton_text=Fil&e InputPatchPage_ChooseFileButton_text=&Browse... InputPatchPage_UseClipboardButton_text=&Clipboard InputPatchPage_UseWorkspaceButton_text=&Workspace InputPatchPage_WorkspaceSelectPatch_text=&Select the location of the patch: InputPatchPage_NothingSelected_message=Select a file or folder to be patched InputPatchPage_ClipboardIsEmpty_message=Clipboard is empty InputPatchPage_NoTextInClipboard_message=Clipboard does not contain text InputPatchPage_CouldNotReadClipboard_message=Cannot retrieve clipboard contents InputPatchPage_CannotLocatePatch_message=Cannot locate patch file: InputPatchPage_NoFileName_message=No file name InputPatchPage_FileSelectedNotPatch_message=Selected resource is not a valid patch #SI - Select file name ? InputPatchPage_SelectPatchFileDialog_title=Select Patch File InputPatchPage_PatchFileNotFound_message=Patch file not found. InputPatchPage_ParseError_message=Error while parsing patch InputPatchPage_Clipboard_title=Clipboard InputPatchPage_PatchFile_title=Patch file InputPatchPage_WorkspacePatch_title=Workspace file InputPatchPage_NoDiffsFound_format={0} does not contain valid patch. InputPatchPage_SingleFileError_format={0} contains multiple patches. You cannot apply them to a single file. # # PatchTargetPage # PatchTargetPage_title= Patch Target Specification PatchTargetPage_message= Define the resource to patch. # # PreviewPatchPage # PreviewPatchPage_title= Verify Patch PreviewPatchPage_message= The tree shows the contents of the patch.\nA checked item indicates that a patch can be applied successfully. To remove an item, clear its checkbox. PreviewPatchPage_Target=(target: {0}) 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 Location PreviewPatchPage_IgnoreWhitespace_text=Ignore &white space PreviewPatchPage_NoName_text=no name PreviewPatchPage_FileExists_error=(file already exists) PreviewPatchPage_FileDoesNotExist_error=(file does not exist) PreviewPatchPage_NoMatch_error=(no match) PreviewPatchPage_MatchProjects=Match &Project... PreviewPatchPage_RetargetPatch=Retarget Patch PreviewPatchPage_SelectProject=Select the project in your workspace that corresponds to project ''{0}'': PreviewPatchPage_FileIsReadOnly_error=(file is read-only) PreviewPatchPage_GuessFuzz_text= &Guess PreviewPatchPage_GuessFuzzProgress_text= Guessing Fuzz Factor... PreviewPatchPage_GuessFuzzProgress_format= {0} (hunk #{1}) PreviewPatchLabelDecorator_ProjectDoesNotExist=(Project does not exist in workspace) # # Patcher # Patcher_Marker_message=Rejected patch Patcher_Task_message=Patching Diff_2Args={0} {1} --- NEW FILE: PreviewPatchLabelDecorator.java --- /******************************************************************************* * Copyright (c) 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.compare.internal.patch; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.compare.internal.CompareUIPlugin; import org.eclipse.compare.internal.DiffImage; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ILabelDecorator; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.graphics.Image; public class PreviewPatchLabelDecorator implements ILabelDecorator { /** Maps strings to images */ private Map fImages= new Hashtable(10); private List fDisposeOnShutdownImages= new ArrayList(); ImageDescriptor errId= CompareUIPlugin.getImageDescriptor("ovr16/error_ov.gif"); //$NON-NLS-1$ static final String error = "error"; //$NON-NLS-1$ static final String add = "add"; //$NON-NLS-1$ static final String delete = "del"; //$NON-NLS-1$ public Image decorateImage(Image image, Object element) { if (element instanceof Diff){ Diff diff = (Diff) element; switch (diff.getType()){ case Differencer.ADDITION: return getImageFor(add + (diff.fMatches ? "" : error), image, diff.fMatches); //$NON-NLS-1$ case Differencer.DELETION: return getImageFor(delete + (diff.fMatches ? "" : error), image, diff.fMatches); //$NON-NLS-1$ default: return getImageFor(diff.fMatches ? "" : error, image, diff.fMatches); //$NON-NLS-1$ } } else if (element instanceof Hunk){ Hunk hunk = (Hunk) element; return getImageFor((hunk.fMatches ? "" : error),image, hunk.fMatches); //$NON-NLS-1$ } return null; } private Image getImageFor(String id, Image image, boolean hasMatches) { Image cached_image = (Image) fImages.get(id); if (cached_image == null){ DiffImage diffImage = new DiffImage(image, hasMatches ? null : errId, 16, false); cached_image = diffImage.createImage(); fImages.put(id, cached_image); fDisposeOnShutdownImages.add(cached_image); } return cached_image; } public String decorateText(String text, Object element) { if (element instanceof DiffProject){ DiffProject project = (DiffProject)element; //Check to see if this project exists in the workspace IResource projectExistsInWorkspace = ResourcesPlugin.getWorkspace().getRoot().findMember(project.getProject().getFullPath()); if(projectExistsInWorkspace == null) return NLS.bind(PatchMessages.Diff_2Args, new String[]{text, PatchMessages.PreviewPatchLabelDecorator_ProjectDoesNotExist}); if (!project.getName().equals(project.getOriginalProjectName())) return NLS.bind(PatchMessages.Diff_2Args, new String[]{project.getOriginalProjectName(), NLS.bind(PatchMessages.PreviewPatchPage_Target, new String[]{project.getName()})}); } return null; } public void dispose() { if (fDisposeOnShutdownImages != null) { Iterator i= fDisposeOnShutdownImages.iterator(); while (i.hasNext()) { Image img= (Image) i.next(); if (!img.isDisposed()) img.dispose(); } fImages= null; } } public boolean isLabelProperty(Object element, String property) { return false; } public void addListener(ILabelProviderListener listener) { //don't need listener } public void removeListener(ILabelProviderListener listener) { //don't need listener } } --- NEW FILE: PatchTargetPage.java --- /******************************************************************************* * Copyright (c) 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.compare.internal.patch; import java.text.MessageFormat; import org.eclipse.compare.internal.ICompareContextIds; import org.eclipse.compare.internal.Utilities; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Tree; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.model.WorkbenchContentProvider; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.eclipse.ui.views.navigator.ResourceSorter; /*** * This page only shows up if the user is trying to apply * a non-workspace rooted patch. */ public class PatchTargetPage extends WizardPage { private boolean fShowError = false; // SWT widgets private CheckboxTreeViewer fPatchTargets; private PatchWizard fPatchWizard; protected final static String PATCHTARGETPAGE_NAME = "PatchTargetPage"; //$NON-NLS-1$ PatchTargetPage(PatchWizard pw) { super(PATCHTARGETPAGE_NAME, PatchMessages.PatchTargetPage_title, null); fPatchWizard = pw; setMessage(PatchMessages.PatchTargetPage_message); } /* * 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(); } 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); l.setText(PatchMessages.InputPatchPage_SelectInput); buildInputGroup(composite); updateWidgetEnablements(); Dialog.applyDialogFont(composite); PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ICompareContextIds.PATCH_INPUT_WIZARD_PAGE); } /* (non-JavaDoc) * Method declared in IWizardPage. */ public IWizardPage getNextPage() { WorkspacePatcher patcher = ((PatchWizard) getWizard()).getPatcher(); // if selected target is file ensure that patch file // contains only a patch for a single file IResource target = fPatchWizard.getTarget(); if (target instanceof IFile && patcher.getDiffs().length > 1) { InputPatchPage inputPage = (InputPatchPage) fPatchWizard.getPage(InputPatchPage.INPUTPATCHPAGE_NAME); String source = ""; //$NON-NLS-1$ switch (inputPage.getInputMethod()) { case InputPatchPage.CLIPBOARD : source = PatchMessages.InputPatchPage_Clipboard_title; break; case InputPatchPage.FILE : source = PatchMessages.InputPatchPage_PatchFile_title; break; case InputPatchPage.WORKSPACE : source = PatchMessages.InputPatchPage_WorkspacePatch_title; break; } String format = PatchMessages.InputPatchPage_SingleFileError_format; String message = MessageFormat.format(format, new String[] {source}); MessageDialog.openInformation(null, PatchMessages.InputPatchPage_PatchErrorDialog_title, message); return this; } return super.getNextPage(); } /* (non-JavaDoc) * Method declared in IWizardPage. */ public boolean canFlipToNextPage() { // we can't call getNextPage to determine if flipping is allowed since computing // the next page is quite expensive. So we say yes if the page is complete. return isPageComplete(); } private void buildInputGroup(Composite parent) { Tree tree = new Tree(parent, SWT.BORDER); GridData gd = new GridData(GridData.FILL_BOTH); gd.heightHint = 200; tree.setLayoutData(gd); fPatchTargets = new CheckboxTreeViewer(tree); fPatchTargets.setLabelProvider(new WorkbenchLabelProvider()); fPatchTargets.setContentProvider(new WorkbenchContentProvider()); fPatchTargets.setSorter(new ResourceSorter(ResourceSorter.NAME)); fPatchTargets.setInput(ResourcesPlugin.getWorkspace().getRoot()); PatchWizard pw = (PatchWizard) getWizard(); IResource target = pw.getTarget(); 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(Utilities.getFirstResource(event.getSelection())); updateWidgetEnablements(); } }); fPatchTargets.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { fPatchWizard.showPage(getNextPage()); } }); } /** * 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.InputPatchPage_NothingSelected_message; setPageComplete(anySelected); if (fShowError) setErrorMessage(error); } /** * 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() { return true; } } --- NEW FILE: PatchWizard.java --- /******************************************************************************* * Copyright (c) 2000, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.compare.internal.patch; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.internal.CompareUIPlugin; import org.eclipse.compare.internal.ExceptionHandler; import org.eclipse.compare.internal.Utilities; import org.eclipse.compare.internal.patch.CompareWithPatchAction.PatchWizardDialog; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.MultiRule; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.Wizard; import org.eclipse.ui.actions.WorkspaceModifyOperation; /* 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 WorkspacePatcher fPatcher; private PatchWizardDialog fDialog; /* * Creates a wizard for applying a patch file to the workspace. */ /* package */PatchWizard(ISelection selection) { setDefaultPageImageDescriptor(CompareUIPlugin.getImageDescriptor("wizban/applypatch_wizban.png")); //$NON-NLS-1$ setWindowTitle(PatchMessages.PatchWizard_title); fPatcher= new WorkspacePatcher(); setTarget(Utilities.getFirstResource(selection)); IDialogSettings workbenchSettings= CompareUIPlugin.getDefault().getDialogSettings(); IDialogSettings section= workbenchSettings.getSection(DIALOG_SETTINGS_KEY); if (section == null) { fHasNewDialogSettings= true; } else { fHasNewDialogSettings= false; setDialogSettings(section); } } WorkspacePatcher getPatcher() { return fPatcher; } IResource getTarget() { return fPatcher.getTarget(); } void setTarget(IResource target) { fPatcher.setTarget(target); } /* (non-Javadoc) * Method declared on IWizard. */ public void addPages() { super.addPages(); addPage(fPatchWizardPage= new InputPatchPage(this)); addPage(new PatchTargetPage(this)); addPage(new PreviewPatchPage(this)); } /* (non-Javadoc) * Method declared on IWizard. */ public boolean needsProgressMonitor() { return true; } /* (non-Javadoc) * Method declared on IWizard. */ public boolean performFinish() { fPatcher.setName(fPatchWizardPage.getPatchName()); // make sure that the patch has been read if (!fPatchWizardPage.isPatchRead()) fPatchWizardPage.readInPatch(); try { // create scheduling rule based on the type of patch - single or workspace ISchedulingRule scheduleRule= null; if (fPatcher.isWorkspacePatch()) { // workspace patch scheduleRule= new MultiRule(fPatcher.getTargetProjects()); } else { // single patch scheduleRule= getTarget(); } WorkspaceModifyOperation op= new WorkspaceModifyOperation(scheduleRule) { protected void execute(IProgressMonitor monitor) throws InvocationTargetException { try { fPatcher.applyAll(monitor, getShell(), PatchMessages.PatchWizard_title); } catch (CoreException e) { throw new InvocationTargetException(e); } } }; getContainer().run(true, false, op); } catch (InvocationTargetException e) { ExceptionHandler.handle(e, PatchMessages.PatchWizard_title, PatchMessages.PatchWizard_unexpectedException_message); } catch (InterruptedException e) { // cannot happen // NeedWork: use assert! } // 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; } public void setDialog(PatchWizardDialog dialog) { fDialog= dialog; } public void showPage(IWizardPage page) { fDialog.showPage(page); } } --- NEW FILE: Hunk.java --- /******************************************************************************* * Copyright (c) 2000, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.compare.internal.patch; import java.util.List; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.osgi.util.NLS; import org.eclipse.ui.model.IWorkbenchAdapter; /** * A Hunk describes a range of changed lines and some context lines. */ /* package */ class Hunk implements IWorkbenchAdapter, IAdaptable { Diff fParent; int fOldStart, fOldLength; int fNewStart, fNewLength; String[] fLines; boolean fMatches= false; private boolean fIsEnabled= true; boolean fHunkProblem= false; /* 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()]); } boolean isEnabled() { return fIsEnabled; } void setEnabled(boolean enable) { fIsEnabled= enable; } 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: * <ul> * <li> * '+': add the line * <li> * '-': delete the line * <li> * ' ': no change, context line * </ul> */ 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(); } void reset(boolean problemEncountered) { fHunkProblem= problemEncountered; } //IWorkbenchAdapter methods public Object[] getChildren(Object o) { return new Object[0]; } public ImageDescriptor getImageDescriptor(Object object) { return null; } public String getLabel(Object o) { String label= getDescription(); if (this.fHunkProblem) return NLS.bind(PatchMessages.Diff_2Args, new String[] {label, PatchMessages.PreviewPatchPage_NoMatch_error}); return label; } public Object getParent(Object o) { return fParent; } //IAdaptable methods public Object getAdapter(Class adapter) { if (adapter == IWorkbenchAdapter.class) return this; return null; } protected boolean getHunkProblem() { return fHunkProblem; } } --- NEW FILE: Patcher.java --- /******************************************************************************* * Copyright (c) 2000, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Martin Burger <m...@rt...> patch for #93810 and #93901 *******************************************************************************/ package org.eclipse.compare.internal.patch; import java.io.*; import java.text.*; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Shell; [...1098 lines suppressed...] return true; } return false; } public int calculatePrefixSegmentCount() { //Update prefix count - go through all of the diffs and find the smallest //path segment contained in all diffs. int length= 99; if (fDiffs!=null) for (int i= 0; i<fDiffs.length; i++) { Diff diff= fDiffs[i]; if (diff.fOldPath!=null) length= Math.min(length, diff.fOldPath.segmentCount()); if (diff.fNewPath!=null) length= Math.min(length, diff.fNewPath.segmentCount()); } return length; } } --- NEW FILE: LineReader.java --- /******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.compare.internal.patch; import java.io.*; import java.util.*; import org.eclipse.jface.util.Assert; public class LineReader { private boolean fHaveChar= false; private int fLastChar; private boolean fSawEOF= false; private BufferedReader fReader; private boolean fIgnoreSingleCR= false; public LineReader(BufferedReader reader) { fReader= reader; Assert.isNotNull(reader); } void ignoreSingleCR() { fIgnoreSingleCR= true; } /** * 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 <code>null</code> 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') { if (fIgnoreSingleCR) { sb.append((char)c); continue; } 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) { // silently ignored } } public List readLines() { try { List lines= new ArrayList(); String line; while ((line= readLine()) != null) lines.add(line); return lines; } catch (IOException ex) { // NeedWork //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(); } } --- NEW FILE: DiffProject.java --- /******************************************************************************* * Copyright (c) 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.compare.internal.patch; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.ui.model.IWorkbenchAdapter; public class DiffProject implements IWorkbenchAdapter, IAdaptable { List fDiffs= new ArrayList(); IProject fProject; //used for patch retargeting String fOriginalProjectName= null; DiffProject(IProject project) { this.fProject= project; this.fOriginalProjectName= project.getName(); } void addDiff(Diff diff) { fDiffs.add(diff); } void addDiffs(Diff[] diffs) { for (int i= 0; i<diffs.length; i++) { fDiffs.add(diffs[i]); } } IProject getProject() { return this.fProject; } String getName() { return fProject.getName(); } void setProject(IProject project) { this.fProject= project; } /** * Resets all of the diffs contained by this project * @param patcher * @param strip * @param fuzzfactor * @return a list of which hunks need to be checked */ ArrayList reset(WorkspacePatcher patcher, int strip, int fuzzfactor) { ArrayList hunksToCheck= new ArrayList(); for (Iterator iter= fDiffs.iterator(); iter.hasNext();) { Diff diff= (Diff) iter.next(); hunksToCheck.addAll(diff.reset(patcher, strip, fuzzfactor)); } return hunksToCheck; } public IFile getFile(IPath path) { return fProject.getFile(path); } /** * Returns the target files of all the Diffs contained by this * DiffProject. * @return An array of IFiles that are targeted by the Diffs */ public IFile[] getTargetFiles() { List files= new ArrayList(); for (Iterator iter= fDiffs.iterator(); iter.hasNext();) { Diff diff= (Diff) iter.next(); if (diff.isEnabled()) { files.add(diff.getTargetFile()); } } return (IFile[]) files.toArray(new IFile[files.size()]); } //IWorkbenchAdapter methods public Object[] getChildren(Object o) { return fDiffs.toArray(); } public ImageDescriptor getImageDescriptor(Object object) { Object o= fProject.getAdapter(IWorkbenchAdapter.class); if (o instanceof IWorkbenchAdapter) { ImageDescriptor id= ((IWorkbenchAdapter) o).getImageDescriptor(fProject); return id; } return null; } public String getLabel(Object o) { return getName(); } public Object getParent(Object o) { return null; } //IAdaptable methods public Object getAdapter(Class adapter) { if (adapter==IWorkbenchAdapter.class) { return this; } return null; } public String getOriginalProjectName() { return fOriginalProjectName; } } --- NEW FILE: PatchErrorDialog.java --- /******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.compare.internal.patch; public class PatchErrorDialog { private PatchErrorDialog() { // no instance. } } --- NEW FILE: InputPatchPage.java --- /******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Sebastian Davids <sd...@gm...> - layout tweaks *******************************************************************************/ package org.eclipse.compare.internal.patch; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.text.MessageFormat; import org.eclipse.compare.internal.ICompareContextIds; import org.eclipse.compare.internal.Utilities; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEven... [truncated message content] |