diff --git org.eclipse.compare/plugin.properties org.eclipse.compare/plugin.properties
index c31d2f8..76a213b 100644
--- org.eclipse.compare/plugin.properties
+++ org.eclipse.compare/plugin.properties
@@ -86,6 +86,9 @@ CompareWithMenu.label= Comp&are With
CompareWithEachOtherAction.label= &Each Other
CompareWithEachOtherAction.tooltip= Compare the Selected Resources
+CompareWithEachOtherActionFiltered.label= Each Other (&filtered)
+CompareWithEachOtherAction.tooltip= Compare the Selected Resources ignoring rules defined in the Preferences.
+
CompareWithOtherResource.label= &Other Resource...
CompareWithOtherResource.tooltip= Open the 'Compare With' Dialog
@@ -162,6 +165,16 @@ compareResolvedColor.description= The color used to indicate a resolved change i
compareFontDefiniton.label= Compare text font
compareFontDefiniton.description= The compare text font is used by textual compare/merge tools.
+# filtered compare
+ComparePreferencePage.filteredCompareTab.label= &Filtered Compare
+ComparePreferencePage.filteredCompareTab.text= Patterns to ignore in 'Compare with each other (filtered)'
+ComparePreferencePage.filteredCompareTab.addExpression= &Add Expression
+ComparePreferencePage.filteredCompareTab.addExpression.dialog.title= Add Ignore Regexp
+ComparePreferencePage.filteredCompareTab.addExpression.dialog.message= Enter a Regexp to at it to the ignore list.
+ComparePreferencePage.filteredCompareTab.addExpression.dialog.initialValue=
+ComparePreferencePage.filteredCompareTab.addExpression.dialog.valueAlreadyExists.title=Pattern already exists
+ComparePreferencePage.filteredCompareTab.addExpression.dialog.valueAlreadyExists.message=Your Pattern is already in the ignore list.
+ComparePreferencePage.filteredCompareTab.removeExpression= &Remove Expression
preferenceKeywords.general=merge merging whitespace filter synchronize scrolling ancestor conflict line pseudo navigation next previous
diff --git org.eclipse.compare/plugin.xml org.eclipse.compare/plugin.xml
index f3acf46..c71a9c2 100644
--- org.eclipse.compare/plugin.xml
+++ org.eclipse.compare/plugin.xml
@@ -222,6 +222,19 @@
+
+
+
+
diff --git org.eclipse.compare/src/org/eclipse/compare/internal/CompareActionFiltered.java org.eclipse.compare/src/org/eclipse/compare/internal/CompareActionFiltered.java
new file mode 100644
index 0000000..a05a8ec
--- /dev/null
+++ org.eclipse.compare/src/org/eclipse/compare/internal/CompareActionFiltered.java
@@ -0,0 +1,52 @@
+package org.eclipse.compare.internal;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.CompareUI;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+
+/*
+ * The "Compare with each other (filtered)" action
+ */
+public class CompareActionFiltered extends BaseCompareAction implements IObjectActionDelegate {
+
+ protected ResourceCompareInput fInput;
+ protected IWorkbenchPage fWorkbenchPage;
+ protected boolean showSelectAncestorDialog = true;
+
+ public void run(ISelection selection) {
+ if (fInput != null) {
+ // Pass the shell so setSelection can prompt the user for which
+ // resource should be the ancestor
+ boolean ok = fInput.setSelection(selection, fWorkbenchPage
+ .getWorkbenchWindow().getShell(), showSelectAncestorDialog);
+ if (!ok) return;
+ fInput.initializeCompareConfiguration();
+ CompareUI.openCompareEditorOnPage(fInput, fWorkbenchPage);
+ fInput= null; // don't reuse this input!
+ }
+ }
+
+ protected boolean isEnabled(ISelection selection) {
+ if (fInput == null) {
+ CompareConfiguration cc= new CompareConfiguration();
+ // buffered merge mode: don't ask for confirmation
+ // when switching between modified resources
+ cc.setProperty(CompareEditor.CONFIRM_SAVE_PROPERTY, new Boolean(false));
+ cc.setProperty("filtered", new Boolean(true));
+
+ // uncomment following line to have separate outline view
+ //cc.setProperty(CompareConfiguration.USE_OUTLINE_VIEW, new Boolean(true));
+
+ fInput= new ResourceCompareInput(cc);
+ }
+ return fInput.isEnabled(selection);
+ }
+
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ fWorkbenchPage= targetPart.getSite().getPage();
+ }
+}
diff --git org.eclipse.compare/src/org/eclipse/compare/internal/ComparePreferencePage.java org.eclipse.compare/src/org/eclipse/compare/internal/ComparePreferencePage.java
index 2a58149..e8e08c8 100644
--- org.eclipse.compare/src/org/eclipse/compare/internal/ComparePreferencePage.java
+++ org.eclipse.compare/src/org/eclipse/compare/internal/ComparePreferencePage.java
@@ -15,7 +15,24 @@ import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.StringTokenizer;
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.IEncodedStreamContentAccessor;
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
+import org.eclipse.compare.internal.core.ComparePlugin;
+import org.eclipse.compare.structuremergeviewer.DiffNode;
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.preference.RadioGroupFieldEditor;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
@@ -30,32 +47,20 @@ import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
-
-import org.eclipse.jface.dialogs.Dialog;
-import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.jface.preference.PreferencePage;
-import org.eclipse.jface.preference.RadioGroupFieldEditor;
-import org.eclipse.jface.util.IPropertyChangeListener;
-import org.eclipse.jface.util.PropertyChangeEvent;
-
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferenceLinkArea;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
-import org.eclipse.compare.CompareConfiguration;
-import org.eclipse.compare.IEncodedStreamContentAccessor;
-import org.eclipse.compare.ITypedElement;
-import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
-import org.eclipse.compare.internal.core.ComparePlugin;
-import org.eclipse.compare.structuremergeviewer.DiffNode;
-import org.eclipse.compare.structuremergeviewer.Differencer;
-
public class ComparePreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
@@ -101,6 +106,8 @@ public class ComparePreferencePage extends PreferencePage implements IWorkbenchP
public static final String ADDED_LINES_REGEX= PREFIX + "AddedLinesRegex"; //$NON-NLS-1$
public static final String REMOVED_LINES_REGEX= PREFIX + "RemovedLinesRegex"; //$NON-NLS-1$
+ public static final String IGNORES_REGEXP= PREFIX + "IgnorePatterns";
+ private static final String IGNORES_REGEXP_DELIMITER = ">#<";
private TextMergeViewer fPreviewViewer;
private IPropertyChangeListener fPreferenceChangeListener;
@@ -131,8 +138,10 @@ public class ComparePreferencePage extends PreferencePage implements IWorkbenchP
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PATH_FILTER),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICompareUIConstants.PREF_NAVIGATION_END_ACTION),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL),
+ new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, IGNORES_REGEXP),
};
private RadioGroupFieldEditor editor;
+ private Table ignoreTable;
public static void initDefaults(IPreferenceStore store) {
@@ -153,6 +162,12 @@ public class ComparePreferencePage extends PreferencePage implements IWorkbenchP
store.setDefault(PATH_FILTER, ""); //$NON-NLS-1$
store.setDefault(ICompareUIConstants.PREF_NAVIGATION_END_ACTION, ICompareUIConstants.PREF_VALUE_PROMPT);
store.setDefault(ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL, ICompareUIConstants.PREF_VALUE_LOOP);
+
+ store.setDefault(
+ IGNORES_REGEXP,
+ ".*\\$Id:.*" + IGNORES_REGEXP_DELIMITER
+ + "^import.*" + IGNORES_REGEXP_DELIMITER
+ + "^\\s*$");
}
public ComparePreferencePage() {
@@ -189,6 +204,14 @@ public class ComparePreferencePage extends PreferencePage implements IWorkbenchP
public boolean performOk() {
fOverlayStore.setValue(ADDED_LINES_REGEX, addedLinesRegex.getText());
fOverlayStore.setValue(REMOVED_LINES_REGEX, removedLinesRegex.getText());
+
+ // store ignore list
+ TableItem[] items = ignoreTable.getItems();
+ String[] elements = new String[items.length];
+ for (int ti = 0; ti < items.length; ti++) {
+ elements[ti] = items[ti].getText();
+ }
+ storeIgnoreRegexpPreferences(elements);
editor.store();
fOverlayStore.propagate();
@@ -261,6 +284,11 @@ public class ComparePreferencePage extends PreferencePage implements IWorkbenchP
//item.setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_CFILE));
item.setControl(createTextComparePage(folder));
+ item= new TabItem(folder, SWT.NONE);
+ item.setText(Utilities.getString("ComparePreferencePage.filteredCompareTab.label")); //$NON-NLS-1$
+ //item.setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_CFILE));
+ item.setControl(createFilteredComparePage(folder));
+
initializeFields();
Dialog.applyDialogFont(folder);
return folder;
@@ -423,6 +451,99 @@ public class ComparePreferencePage extends PreferencePage implements IWorkbenchP
return c;
}
+
+ private Control createFilteredComparePage(TabFolder folder) {
+ Composite pageComponent= new Composite(folder, SWT.NULL);
+ GridLayout layout= new GridLayout();
+ layout.numColumns = 2;
+ pageComponent.setLayout(layout);
+ GridData data = new GridData();
+ data.verticalAlignment = GridData.FILL;
+ data.horizontalAlignment = GridData.FILL;
+ pageComponent.setLayoutData(data);
+
+ // layout the ignore table & its buttons
+ Label ignoreLabel = new Label(pageComponent, SWT.LEFT);
+ ignoreLabel.setText(Utilities.getString("ComparePreferencePage.filteredCompareTab.text"));
+ data = new GridData();
+ data.horizontalAlignment = GridData.FILL;
+ data.horizontalSpan = 2;
+ ignoreLabel.setLayoutData(data);
+
+ ignoreTable = new Table(pageComponent, SWT.MULTI | SWT.BORDER);
+ data = new GridData(GridData.FILL_BOTH);
+ data.heightHint = ignoreTable.getItemHeight() * 7;
+ ignoreTable.setLayoutData(data);
+
+ Composite groupComponent = new Composite(pageComponent, SWT.NULL);
+ GridLayout groupLayout = new GridLayout();
+ groupLayout.marginWidth = 0;
+ groupLayout.marginHeight = 0;
+ groupComponent.setLayout(groupLayout);
+ data = new GridData();
+ data.verticalAlignment = GridData.FILL;
+ data.horizontalAlignment = GridData.FILL;
+ groupComponent.setLayoutData(data);
+
+ Button addIgnoreButton = new Button(groupComponent, SWT.PUSH);
+ addIgnoreButton.setText(Utilities.getString("ComparePreferencePage.filteredCompareTab.addExpression"));
+ addIgnoreButton.setLayoutData(data);
+ setButtonLayoutData(addIgnoreButton);
+
+ final Button removeIgnoreButton = new Button(groupComponent, SWT.PUSH);
+ removeIgnoreButton.setText(Utilities.getString("ComparePreferencePage.filteredCompareTab.removeExpression"));
+ setButtonLayoutData(removeIgnoreButton);
+
+ // the listeners
+ ignoreTable.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ if (ignoreTable.getSelectionCount() > 0) {
+ removeIgnoreButton.setEnabled(true);
+ } else {
+ removeIgnoreButton.setEnabled(false);
+ }
+ }
+ });
+ addIgnoreButton.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ InputDialog dialog = new InputDialog(
+ getShell(),
+ Utilities.getString("ComparePreferencePage.filteredCompareTab.addExpression.dialog.title"),
+ Utilities.getString("ComparePreferencePage.filteredCompareTab.addExpression.dialog.message"),
+ Utilities.getString("ComparePreferencePage.filteredCompareTab.addExpression.dialog.initialValue"),
+ new RegexpInputValidator());
+ if (dialog.open() == Window.OK) {
+ String value = dialog.getValue();
+ addIgnoreRegexp(value);
+ }
+ }
+ });
+ removeIgnoreButton.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ int[] selection = ignoreTable.getSelectionIndices();
+ ignoreTable.remove(selection);
+ }
+ });
+
+ removeIgnoreButton.setEnabled(false);
+ return pageComponent;
+ }
+
+ private void addIgnoreRegexp(String value) {
+ // Check if the item already exists
+ TableItem[] items = ignoreTable.getItems();
+ for (int i = 0; i < items.length; i++) {
+ if (items[i].getText().equals(value)) {
+ MessageDialog.openWarning(
+ getShell(),
+ Utilities.getString("ComparePreferencePage.filteredCompareTab.addExpression.dialog.valueAlreadyExists.title"),
+ Utilities.getString("ComparePreferencePage.filteredCompareTab.addExpression.dialog.valueAlreadyExists.message"));
+ return;
+ }
+ }
+ TableItem item = new TableItem(ignoreTable, SWT.NONE);
+ item.setText(value);
+ }
private void initializeFields() {
@@ -441,7 +562,18 @@ public class ComparePreferencePage extends PreferencePage implements IWorkbenchP
removedLinesRegex.setText(fOverlayStore.getString(REMOVED_LINES_REGEX));
editor.load();
+
+ fillIgnoreTable();
}
+
+ private void fillIgnoreTable() {
+ ignoreTable.removeAll();
+ String[] ignoresPreference = getIgnoreRegexpPreference();
+ for (int i = 0; i < ignoresPreference.length; i++) {
+ TableItem item = new TableItem(ignoreTable, SWT.NULL);
+ item.setText(ignoresPreference[i]);
+ }
+ }
// overlay stuff
@@ -486,4 +618,36 @@ public class ComparePreferencePage extends PreferencePage implements IWorkbenchP
}
return buffer.toString();
}
+
+ /*
+ * stores a list of ignore patterns.
+ */
+ public void storeIgnoreRegexpPreferences(String[] elements) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < elements.length; i++) {
+ buffer.append(elements[i]);
+ buffer.append(IGNORES_REGEXP_DELIMITER);
+ }
+ fOverlayStore.setValue(IGNORES_REGEXP, buffer.toString());
+ }
+
+ /*
+ * loads the list of ignore patterns.
+ */
+ private String[] getIgnoreRegexpPreference() {
+ return convertListOfIgnoreRegexp(fOverlayStore.getString(IGNORES_REGEXP));
+ }
+
+ /*
+ * converts the list of ignore regexp to and from values in preference store.
+ */
+ public static String[] convertListOfIgnoreRegexp(String preferenceValue) {
+ StringTokenizer tokenizer = new StringTokenizer(preferenceValue, IGNORES_REGEXP_DELIMITER);
+ int tokenCount = tokenizer.countTokens();
+ String[] elements = new String[tokenCount];
+ for (int i = 0; i < tokenCount; i++) {
+ elements[i] = tokenizer.nextToken();
+ }
+ return elements;
+ }
}
diff --git org.eclipse.compare/src/org/eclipse/compare/internal/RegexpInputValidator.java org.eclipse.compare/src/org/eclipse/compare/internal/RegexpInputValidator.java
new file mode 100644
index 0000000..224d713
--- /dev/null
+++ org.eclipse.compare/src/org/eclipse/compare/internal/RegexpInputValidator.java
@@ -0,0 +1,19 @@
+package org.eclipse.compare.internal;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.eclipse.jface.dialogs.IInputValidator;
+
+public class RegexpInputValidator implements IInputValidator {
+
+ public String isValid(String newText) {
+ try {
+ Pattern.compile(newText);
+ } catch (PatternSyntaxException exception) {
+ return "'" + newText + "' is not a valid Regexp!";
+ }
+ return null;
+ }
+
+}
diff --git org.eclipse.compare/src/org/eclipse/compare/internal/ResourceCompareInput.java org.eclipse.compare/src/org/eclipse/compare/internal/ResourceCompareInput.java
index 4c01f86..420c01f 100644
--- org.eclipse.compare/src/org/eclipse/compare/internal/ResourceCompareInput.java
+++ org.eclipse.compare/src/org/eclipse/compare/internal/ResourceCompareInput.java
@@ -23,6 +23,7 @@ import org.eclipse.compare.ZipFileStructureCreator;
import org.eclipse.compare.structuremergeviewer.DiffNode;
import org.eclipse.compare.structuremergeviewer.DiffTreeViewer;
import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.compare.structuremergeviewer.DifferencerFiltered;
import org.eclipse.compare.structuremergeviewer.IDiffContainer;
import org.eclipse.compare.structuremergeviewer.IDiffElement;
import org.eclipse.compare.structuremergeviewer.IStructureComparator;
@@ -403,11 +404,22 @@ class ResourceCompareInput extends CompareEditorInput {
}
setTitle(title);
- Differencer d= new Differencer() {
- protected Object visit(Object parent, int description, Object ancestor, Object left, Object right) {
- return new MyDiffNode((IDiffContainer) parent, description, (ITypedElement)ancestor, (ITypedElement)left, (ITypedElement)right);
- }
- };
+ Boolean isFiltered = (Boolean) getCompareConfiguration().getProperty("filtered");
+
+ Differencer d = null;
+ if (isFiltered != null && isFiltered.booleanValue()) {
+ d = new DifferencerFiltered() {
+ protected Object visit(Object parent, int description, Object ancestor, Object left, Object right) {
+ return new MyDiffNode((IDiffContainer) parent, description, (ITypedElement)ancestor, (ITypedElement)left, (ITypedElement)right);
+ }
+ };
+ } else {
+ d= new Differencer() {
+ protected Object visit(Object parent, int description, Object ancestor, Object left, Object right) {
+ return new MyDiffNode((IDiffContainer) parent, description, (ITypedElement)ancestor, (ITypedElement)left, (ITypedElement)right);
+ }
+ };
+ }
fRoot= d.findDifferences(fThreeWay, pm, null, fAncestor, fLeft, fRight);
return fRoot;
diff --git org.eclipse.compare/src/org/eclipse/compare/structuremergeviewer/DifferencerFiltered.java org.eclipse.compare/src/org/eclipse/compare/structuremergeviewer/DifferencerFiltered.java
new file mode 100644
index 0000000..894fad5
--- /dev/null
+++ org.eclipse.compare/src/org/eclipse/compare/structuremergeviewer/DifferencerFiltered.java
@@ -0,0 +1,223 @@
+package org.eclipse.compare.structuremergeviewer;
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.compare.ResourceNode;
+import org.eclipse.compare.internal.ComparePreferencePage;
+import org.eclipse.compare.internal.CompareUIPlugin;
+import org.eclipse.compare.internal.patch.Utilities;
+import org.eclipse.compare.rangedifferencer.IRangeComparator;
+import org.eclipse.compare.rangedifferencer.RangeDifference;
+import org.eclipse.compare.rangedifferencer.RangeDifferencer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * A Differencer who will ignore changed lines which matches at least one of the stored pattern(s).
+ */
+public class DifferencerFiltered extends Differencer {
+
+ /**
+ * This implementation of IRangeComparator breaks an input stream into lines.
+ * @see org.eclipse.compare.internal.merge.LineComparator
+ */
+ class LineComparator implements IRangeComparator {
+
+ private String[] fLines;
+
+ public LineComparator(InputStream is, String encoding) throws IOException {
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(is, encoding));
+ String line;
+ ArrayList ar = new ArrayList();
+ while ((line = br.readLine()) != null) {
+ ar.add(line);
+ }
+ // It is the responsibility of the caller to close the stream
+ fLines = (String[]) ar.toArray(new String[ar.size()]);
+ }
+
+ String getLine(int ix) {
+ return fLines[ix];
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.compare.rangedifferencer.IRangeComparator#getRangeCount()
+ */
+ public int getRangeCount() {
+ return fLines.length;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.compare.rangedifferencer.IRangeComparator#rangesEqual(int, org.eclipse.compare.rangedifferencer.IRangeComparator, int)
+ */
+ public boolean rangesEqual(int thisIndex, IRangeComparator other,
+ int otherIndex) {
+ String s1 = fLines[thisIndex];
+ String s2 = ((LineComparator) other).fLines[otherIndex];
+ return s1.equals(s2);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.compare.rangedifferencer.IRangeComparator#skipRangeComparison(int, int, org.eclipse.compare.rangedifferencer.IRangeComparator)
+ */
+ public boolean skipRangeComparison(int length, int maxLength, IRangeComparator other) {
+ return false;
+ }
+ }
+
+ protected boolean contentsEqual(Object input1, Object input2) {
+ if (input1 instanceof ResourceNode && input2 instanceof ResourceNode) {
+ ResourceNode resLeft = (ResourceNode) input1;
+ ResourceNode resRight = (ResourceNode) input2;
+ if (resLeft.getResource() instanceof IFile && resRight.getResource() instanceof IFile) {
+ IFile left = (IFile) resLeft.getResource();
+ IFile right = (IFile) resRight.getResource();
+
+ InputStream leftInput = null;
+ InputStream rightInput = null;
+ try {
+ leftInput = left.getContents();
+ rightInput = right.getContents();
+
+ LineComparator leftLineComparator = new LineComparator(leftInput, Utilities.getCharset(resLeft));
+ LineComparator rightLineComparator = new LineComparator(rightInput, Utilities.getCharset(resRight));
+
+ RangeDifference[] differences = RangeDifferencer.findDifferences(leftLineComparator, rightLineComparator);
+
+ if (differences.length == 0) {
+ // no diffs -> contents are equal
+ return true;
+ }
+
+ for (int d = 0; d < differences.length; d++) {
+ if (! isDiffIgnorable(left, right, differences[d])) {
+ // we found a diff which isn't on our ignore list.
+// System.out.println("I can't ignore " + left.getName() + " because of diff " + df);
+ return false;
+ }
+ }
+ // we found diffs, but all these diffs are on our ignore list.
+// System.out.println("All lines with diff in file matches the ignores: " + left.getName());
+ return true;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ } finally {
+ closeQuietly(leftInput);
+ closeQuietly(rightInput);
+ }
+ }
+ }
+ // not a resourceNode ... go the normal way...
+ return super.contentsEqual(input1, input2);
+ }
+
+ private boolean isDiffIgnorable(IFile left, IFile right, RangeDifference diff) {
+
+ try {
+
+ List linesLeft = readLines(left);
+ List linesRight = readLines(right);
+
+ // left
+ for (int line = diff.leftStart(); line < diff.leftEnd(); line++) {
+ String candidateLeft = (String) linesLeft.get(line);
+ if (matches(candidateLeft)) {
+ // ignore line in left
+ continue;
+ } else {
+ // found a diff which we can not ignore.
+ return false;
+ }
+ }
+
+ // right
+ for (int line = diff.rightStart(); line < diff.rightEnd(); line++) {
+ String candidateRight = (String) linesRight.get(line);
+ if (matches(candidateRight)) {
+ // ignore line in right
+ continue;
+ } else {
+ // found a diff which we can not ignore.
+ return false;
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ // diffs we found should be ignored.
+ return true;
+ }
+
+ private boolean matches(String candidate) {
+ String regexp = getIgnoresAsRegexp();
+ if (candidate != null && candidate.matches(regexp) ) {
+// System.out.println("!BINGO! Ignoring because of line: '" + candidate + "'");
+ return true;
+ }
+ return false;
+ }
+
+ private String getIgnoresAsRegexp() {
+ String ignoresFromStore = Platform.getPreferencesService()
+ .getString(CompareUIPlugin.PLUGIN_ID, ComparePreferencePage.IGNORES_REGEXP, "", null);
+
+ String[] ignores = ComparePreferencePage.convertListOfIgnoreRegexp(ignoresFromStore);
+
+ StringBuilder regexp = new StringBuilder();
+ for (int i = 0; i < ignores.length; i++) {
+ regexp.append("(");
+ regexp.append(ignores[i]);
+ regexp.append(")|");
+ }
+ if (regexp.length() > 0) {
+ // cut off last '|'
+ regexp.setLength(regexp.length() - 1);
+ }
+ String result = regexp.toString();
+// System.out.println(result);
+ return result;
+
+ }
+
+
+ /**
+ * Get the contents of an InputStream
as a list of Strings,
+ * one entry per line, using the specified character encoding.
+ */
+ public static List readLines(IFile file) throws IOException, CoreException {
+ String charset = Utilities.getCharset(file);
+ InputStream input = file.getContents();
+ InputStreamReader reader = new InputStreamReader(input, charset);
+ BufferedReader bufferedReader = new BufferedReader(reader);
+ List list = new ArrayList();
+ String line = bufferedReader.readLine();
+ while (line != null) {
+ list.add(line);
+ line = bufferedReader.readLine();
+ }
+ return list;
+ }
+
+ public void closeQuietly(Closeable closeable) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ } catch (IOException ex) {
+ // ignore
+ }
+ }
+ }
+
+}