diff options
author | Olivier Thomann | 2012-11-08 11:35:43 +0000 |
---|---|---|
committer | Malgorzata Janczarska | 2012-11-08 11:35:43 +0000 |
commit | 1d3169527e436e45c5bfe2584f5f13ca6bd3e975 (patch) | |
tree | 0b4d6e172944d20d1dbab8cd84892e1ee42e1227 /bundles/org.eclipse.team.core/src/org | |
parent | 325126585d2b6de9bdaa09ac3885092b32c99628 (diff) | |
download | eclipse.platform.team-1d3169527e436e45c5bfe2584f5f13ca6bd3e975.tar.gz eclipse.platform.team-1d3169527e436e45c5bfe2584f5f13ca6bd3e975.tar.xz eclipse.platform.team-1d3169527e436e45c5bfe2584f5f13ca6bd3e975.zip |
Bug 377545 - Make extension pointv20121108-113543
for org.eclipse.team.core.storageMergers for text file usable in
a headless environment
Diffstat (limited to 'bundles/org.eclipse.team.core/src/org')
4 files changed, 269 insertions, 2 deletions
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/Messages.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/Messages.java index 5c550403e..454300fde 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/Messages.java +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/Messages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2011 IBM Corporation and others. + * Copyright (c) 2005, 2012 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 @@ -123,4 +123,9 @@ public class Messages extends NLS { public static String ScopeManagerEventHandler_0; public static String ScopeManagerEventHandler_1; + + public static String TextAutoMerge_inputEncodingError; + public static String TextAutoMerge_conflict; + public static String TextAutoMerge_outputEncodingError; + public static String TextAutoMerge_outputIOError; } diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/mapping/LineComparator.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/mapping/LineComparator.java new file mode 100644 index 000000000..7a557a7c1 --- /dev/null +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/mapping/LineComparator.java @@ -0,0 +1,159 @@ +/******************************************************************************* + * Copyright (c) 2004, 2012 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.team.internal.core.mapping; + +import java.io.*; +import java.util.ArrayList; + +import org.eclipse.compare.rangedifferencer.IRangeComparator; +import org.eclipse.core.resources.IEncodedStorage; +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.runtime.CoreException; + +/** + * This implementation of IRangeComparator breaks an input stream into lines. + * Copied from org.eclipse.compare.internal.merge.LineComparator 1.4 and + * modified for {@link IStorage}. + */ +class LineComparator implements IRangeComparator { + + private String[] fLines; + + /* + * An input stream reader that detects a trailing LF in the wrapped stream. + */ + private static class TrailingLineFeedDetector extends FilterInputStream { + + boolean trailingLF = false; + + protected TrailingLineFeedDetector(InputStream in) { + super(in); + } + + public int read() throws IOException { + int c = super.read(); + trailingLF = isLineFeed(c); + return c; + } + + /* + * We don't need to override read(byte[] buffer) as the javadoc of + * FilterInputStream states that it will call read(byte[] buffer, int + * off, int len) + */ + public int read(byte[] buffer, int off, int len) throws IOException { + int length = super.read(buffer, off, len); + if (length != -1) { + int index = off + length - 1; + if (index >= buffer.length) + index = buffer.length - 1; + trailingLF = isLineFeed(buffer[index]); + } + return length; + } + + private boolean isLineFeed(int c) { + return c != -1 && c == '\n'; + } + + public boolean hadTrailingLineFeed() { + return trailingLF; + } + + } + + public static LineComparator create(IStorage storage, String outputEncoding) + throws CoreException, IOException { + InputStream is = new BufferedInputStream(storage.getContents()); + try { + String encoding = getEncoding(storage, outputEncoding); + return new LineComparator(is, encoding); + } finally { + try { + is.close(); + } catch (IOException e) { + // Ignore + } + } + } + + private static String getEncoding(IStorage storage, String outputEncoding) + throws CoreException { + if (storage instanceof IEncodedStorage) { + IEncodedStorage es = (IEncodedStorage) storage; + String charset = es.getCharset(); + if (charset != null) + return charset; + } + return outputEncoding; + } + + public LineComparator(InputStream is, String encoding) throws IOException { + + TrailingLineFeedDetector trailingLineFeedDetector = new TrailingLineFeedDetector( + is); + BufferedReader br = new BufferedReader(new InputStreamReader( + trailingLineFeedDetector, encoding)); + String line; + ArrayList ar = new ArrayList(); + while ((line = br.readLine()) != null) { + ar.add(line); + } + // Add a trailing line if the last character in the file was a line + // feed. + // We do this because a BufferedReader doesn't distinguish the case + // where the last line has or doesn't have a trailing line separator + if (trailingLineFeedDetector.hadTrailingLineFeed()) { + ar.add(""); //$NON-NLS-1$ + } + 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; + } +} diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/mapping/TextStorageMerger.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/mapping/TextStorageMerger.java new file mode 100644 index 000000000..61f890677 --- /dev/null +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/mapping/TextStorageMerger.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2006, 2012 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.team.internal.core.mapping; + +import java.io.*; + +import org.eclipse.compare.rangedifferencer.RangeDifference; +import org.eclipse.compare.rangedifferencer.RangeDifferencer; +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.runtime.*; +import org.eclipse.team.core.mapping.IStorageMerger; +import org.eclipse.team.internal.core.Messages; +import org.eclipse.team.internal.core.TeamPlugin; + +public class TextStorageMerger implements IStorageMerger { + + public IStatus merge(OutputStream output, String outputEncoding, + IStorage ancestor, IStorage target, IStorage other, + IProgressMonitor monitor) throws CoreException { + + LineComparator a, t, o; + + try { + a= LineComparator.create(ancestor, outputEncoding); + t= LineComparator.create(target, outputEncoding); + o= LineComparator.create(other,outputEncoding); + } catch (UnsupportedEncodingException e) { + throw new CoreException (new Status(IStatus.ERROR, TeamPlugin.ID, UNSUPPORTED_ENCODING, Messages.TextAutoMerge_inputEncodingError, e)); + } catch (IOException e) { + throw new CoreException (new Status(IStatus.ERROR, TeamPlugin.ID, INTERNAL_ERROR, e.getMessage(), e)); + } + + try { + boolean firstLine = true; + String lineSeparator= System.getProperty("line.separator"); //$NON-NLS-1$ + if (lineSeparator == null) + lineSeparator= "\n"; //$NON-NLS-1$ + + RangeDifference[] diffs= RangeDifferencer.findRanges(monitor, a, t, o); + + for (int i= 0; i < diffs.length; i++) { + RangeDifference rd= diffs[i]; + switch (rd.kind()) { + case RangeDifference.ANCESTOR: // pseudo conflict + case RangeDifference.NOCHANGE: + case RangeDifference.RIGHT: + for (int j= rd.rightStart(); j < rd.rightEnd(); j++) { + String s= o.getLine(j); + if (!firstLine) + output.write(lineSeparator.getBytes(outputEncoding)); + output.write(s.getBytes(outputEncoding)); + firstLine = false; + } + break; + + case RangeDifference.LEFT: + for (int j= rd.leftStart(); j < rd.leftEnd(); j++) { + String s= t.getLine(j); + if (!firstLine) + output.write(lineSeparator.getBytes(outputEncoding)); + output.write(s.getBytes(outputEncoding)); + firstLine = false; + } + break; + + case RangeDifference.CONFLICT: + return new Status(IStatus.WARNING, TeamPlugin.ID, CONFLICT, Messages.TextAutoMerge_conflict, null); + + default: + break; + } + } + + } catch (UnsupportedEncodingException e) { + throw new CoreException (new Status(IStatus.ERROR, TeamPlugin.ID, UNSUPPORTED_ENCODING, Messages.TextAutoMerge_outputEncodingError, e)); + } catch (IOException e) { + return new Status(IStatus.ERROR, TeamPlugin.ID, INTERNAL_ERROR, Messages.TextAutoMerge_outputIOError, e); + } + + return Status.OK_STATUS; + } + + /* (non-Javadoc) + * @see org.eclipse.team.core.mapping.IStorageMerger#canMergeWithoutAncestor() + */ + public boolean canMergeWithoutAncestor() { + return false; + } + +} diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties index 608e4b55f..96f06dc34 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2011 IBM Corporation and others. +# Copyright (c) 2000, 2012 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 @@ -103,3 +103,8 @@ WorkspaceSubscriber_0=Workspace WorkspaceSubscriber_1=Multiple errors occurred ScopeManagerEventHandler_0=Refreshing {0} ScopeManagerEventHandler_1=Errors occurred while refreshing {0} + +TextAutoMerge_inputEncodingError= Unsupported encoding for input stream +TextAutoMerge_outputEncodingError= Unsupported encoding for output stream +TextAutoMerge_outputIOError= I/O error on writing +TextAutoMerge_conflict= Conflict: cannot auto-merge |