This makes it easier to parametrize DiffFormatter with a different implementation, as we later plan to add PatienceDiff to JGit. Change-Id: Id35ef478d5fa20fe10a1ba297f9436fd7adde9ce Signed-off-by: Shawn O. Pearce <spearce@spearce.org>tags/v0.10.1
@@ -384,9 +384,9 @@ public class IpLogGenerator { | |||
else | |||
oldImage = new byte[0]; | |||
EditList edits = new MyersDiff<RawText>( | |||
EditList edits = MyersDiff.INSTANCE.diff( | |||
RawTextComparator.DEFAULT, new RawText(oldImage), | |||
new RawText(openBlob(1))).getEdits(); | |||
new RawText(openBlob(1))); | |||
for (Edit e : edits) | |||
addedLines += e.getEndB() - e.getBeginB(); | |||
} |
@@ -164,14 +164,14 @@ public class MyersDiffPerformanceTest extends TestCase { | |||
CharArray ac = new CharArray(a); | |||
CharArray bc = new CharArray(b); | |||
CharCmp cmp = new CharCmp(); | |||
MyersDiff<CharArray> myersDiff = null; | |||
int D = 0; | |||
int cpuTimeChanges = 0; | |||
long lastReadout = 0; | |||
long interimTime = 0; | |||
int repetitions = 0; | |||
stopwatch.start(); | |||
while (cpuTimeChanges < minCPUTimerTicks && interimTime < longTaskBoundary) { | |||
myersDiff = new MyersDiff<CharArray>(cmp, ac, bc); | |||
D = MyersDiff.INSTANCE.diff(cmp, ac, bc).size(); | |||
repetitions++; | |||
interimTime = stopwatch.readout(); | |||
if (interimTime != lastReadout) { | |||
@@ -181,7 +181,7 @@ public class MyersDiffPerformanceTest extends TestCase { | |||
} | |||
ret.runningTime = stopwatch.stop() / repetitions; | |||
ret.N = ac.size() + bc.size(); | |||
ret.D = myersDiff.getEdits().size(); | |||
ret.D = D; | |||
return ret; | |||
} |
@@ -63,9 +63,9 @@ public class MyersDiffTest extends TestCase { | |||
} | |||
public void assertDiff(String a, String b, String edits) { | |||
MyersDiff diff = new MyersDiff<CharArray>(new CharCmp(), | |||
EditList editList = MyersDiff.INSTANCE.diff(new CharCmp(), | |||
toCharArray(a), toCharArray(b)); | |||
assertEquals(edits, toString(diff.getEdits())); | |||
assertEquals(edits, toString(editList)); | |||
} | |||
private static String toString(EditList list) { |
@@ -0,0 +1,79 @@ | |||
/* | |||
* Copyright (C) 2010, Google Inc. | |||
* and other copyright owners as documented in the project's IP log. | |||
* | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Distribution License v1.0 which | |||
* accompanies this distribution, is reproduced below, and is | |||
* available at http://www.eclipse.org/org/documents/edl-v10.php | |||
* | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or | |||
* without modification, are permitted provided that the following | |||
* conditions are met: | |||
* | |||
* - Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* - Redistributions in binary form must reproduce the above | |||
* copyright notice, this list of conditions and the following | |||
* disclaimer in the documentation and/or other materials provided | |||
* with the distribution. | |||
* | |||
* - Neither the name of the Eclipse Foundation, Inc. nor the | |||
* names of its contributors may be used to endorse or promote | |||
* products derived from this software without specific prior | |||
* written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | |||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
package org.eclipse.jgit.diff; | |||
/** | |||
* Compares two {@link Sequence}s to create an {@link EditList} of changes. | |||
* | |||
* An algorithm's {@code diff} method must be callable from concurrent threads | |||
* without data collisions. This permits some algorithms to use a singleton | |||
* pattern, with concurrent invocations using the same singleton. Other | |||
* algorithms may support parameterization, in which case the caller can create | |||
* a unique instance per thread. | |||
*/ | |||
public interface DiffAlgorithm { | |||
/** | |||
* Compare two sequences and identify a list of edits between them. | |||
* | |||
* @param <S> | |||
* type of sequence being compared. | |||
* @param <C> | |||
* type of comparator to evaluate the sequence elements. | |||
* @param cmp | |||
* the comparator supplying the element equivalence function. | |||
* @param a | |||
* the first (also known as old or pre-image) sequence. Edits | |||
* returned by this algorithm will reference indexes using the | |||
* 'A' side: {@link Edit#getBeginA()}, {@link Edit#getEndA()}. | |||
* @param b | |||
* the second (also known as new or post-image) sequence. Edits | |||
* returned by this algorithm will reference indexes using the | |||
* 'B' side: {@link Edit#getBeginB()}, {@link Edit#getEndB()}. | |||
* @return a modifiable edit list comparing the two sequences. If empty, the | |||
* sequences are identical according to {@code cmp}'s rules. The | |||
* result list is never null. | |||
*/ | |||
public <S extends Sequence, C extends SequenceComparator<? super S>> EditList diff( | |||
C cmp, S a, S b); | |||
} |
@@ -118,6 +118,8 @@ public class DiffFormatter { | |||
private int abbreviationLength = 7; | |||
private DiffAlgorithm diffAlgorithm = MyersDiff.INSTANCE; | |||
private RawTextComparator comparator = RawTextComparator.DEFAULT; | |||
private int binaryFileThreshold = DEFAULT_BINARY_FILE_THRESHOLD; | |||
@@ -206,6 +208,17 @@ public class DiffFormatter { | |||
abbreviationLength = count; | |||
} | |||
/** | |||
* Set the algorithm that constructs difference output. | |||
* | |||
* @param alg | |||
* the algorithm to produce text file differences. | |||
* @see MyersDiff#INSTANCE | |||
*/ | |||
public void setDiffAlgorithm(DiffAlgorithm alg) { | |||
diffAlgorithm = alg; | |||
} | |||
/** | |||
* Set the line equivalence function for text file differences. | |||
* | |||
@@ -893,7 +906,7 @@ public class DiffFormatter { | |||
} | |||
private EditList diff(RawText a, RawText b) { | |||
return new MyersDiff<RawText>(comparator, a, b).getEdits(); | |||
return diffAlgorithm.diff(comparator, a, b); | |||
} | |||
private void assertHaveRepository() { |
@@ -106,13 +106,21 @@ import org.eclipse.jgit.util.LongList; | |||
* type of sequence. | |||
*/ | |||
public class MyersDiff<S extends Sequence> { | |||
/** Singleton instance of MyersDiff. */ | |||
public static final DiffAlgorithm INSTANCE = new DiffAlgorithm() { | |||
public <S extends Sequence, C extends SequenceComparator<? super S>> EditList diff( | |||
C cmp, S a, S b) { | |||
return new MyersDiff<S>(cmp, a, b).getEdits(); | |||
} | |||
}; | |||
/** | |||
* The list of edits found during the last call to {@link #calculateEdits()} | |||
*/ | |||
protected EditList edits; | |||
/** Comparison function for sequences. */ | |||
protected SequenceComparator<S> cmp; | |||
protected SequenceComparator<? super S> cmp; | |||
/** | |||
* The first text to be compared. Referred to as "Text A" in the comments | |||
@@ -124,14 +132,7 @@ public class MyersDiff<S extends Sequence> { | |||
*/ | |||
protected S b; | |||
/** | |||
* The only constructor | |||
* | |||
* @param cmp comparison method for this execution. | |||
* @param a the text A which should be compared | |||
* @param b the text B which should be compared | |||
*/ | |||
public MyersDiff(SequenceComparator<S> cmp, S a, S b) { | |||
private MyersDiff(SequenceComparator<? super S> cmp, S a, S b) { | |||
this.cmp = cmp; | |||
this.a = a; | |||
this.b = b; |
@@ -90,9 +90,9 @@ public final class MergeAlgorithm { | |||
sequences.add(ours); | |||
sequences.add(theirs); | |||
MergeResult result = new MergeResult<S>(sequences); | |||
EditList oursEdits = new MyersDiff<S>(cmp, base, ours).getEdits(); | |||
EditList oursEdits = MyersDiff.INSTANCE.diff(cmp, base, ours); | |||
Iterator<Edit> baseToOurs = oursEdits.iterator(); | |||
EditList theirsEdits = new MyersDiff<S>(cmp, base, theirs).getEdits(); | |||
EditList theirsEdits = MyersDiff.INSTANCE.diff(cmp, base, theirs); | |||
Iterator<Edit> baseToTheirs = theirsEdits.iterator(); | |||
int current = 0; // points to the next line (first line is 0) of base | |||
// which was not handled yet |