Merge "Define DiffAlgorithm as an abstract function"

This commit is contained in:
Chris Aniszczyk 2010-09-17 15:08:27 -04:00 committed by Code Review
commit 207ab8b8f5
7 changed files with 112 additions and 19 deletions

View File

@ -384,9 +384,9 @@ private void scanProjectCommits(Project proj, RevCommit start)
else else
oldImage = new byte[0]; oldImage = new byte[0];
EditList edits = new MyersDiff<RawText>( EditList edits = MyersDiff.INSTANCE.diff(
RawTextComparator.DEFAULT, new RawText(oldImage), RawTextComparator.DEFAULT, new RawText(oldImage),
new RawText(openBlob(1))).getEdits(); new RawText(openBlob(1)));
for (Edit e : edits) for (Edit e : edits)
addedLines += e.getEndB() - e.getBeginB(); addedLines += e.getEndB() - e.getBeginB();
} }

View File

@ -164,14 +164,14 @@ private PerfData test(int characters) {
CharArray ac = new CharArray(a); CharArray ac = new CharArray(a);
CharArray bc = new CharArray(b); CharArray bc = new CharArray(b);
CharCmp cmp = new CharCmp(); CharCmp cmp = new CharCmp();
MyersDiff<CharArray> myersDiff = null; int D = 0;
int cpuTimeChanges = 0; int cpuTimeChanges = 0;
long lastReadout = 0; long lastReadout = 0;
long interimTime = 0; long interimTime = 0;
int repetitions = 0; int repetitions = 0;
stopwatch.start(); stopwatch.start();
while (cpuTimeChanges < minCPUTimerTicks && interimTime < longTaskBoundary) { while (cpuTimeChanges < minCPUTimerTicks && interimTime < longTaskBoundary) {
myersDiff = new MyersDiff<CharArray>(cmp, ac, bc); D = MyersDiff.INSTANCE.diff(cmp, ac, bc).size();
repetitions++; repetitions++;
interimTime = stopwatch.readout(); interimTime = stopwatch.readout();
if (interimTime != lastReadout) { if (interimTime != lastReadout) {
@ -181,7 +181,7 @@ private PerfData test(int characters) {
} }
ret.runningTime = stopwatch.stop() / repetitions; ret.runningTime = stopwatch.stop() / repetitions;
ret.N = ac.size() + bc.size(); ret.N = ac.size() + bc.size();
ret.D = myersDiff.getEdits().size(); ret.D = D;
return ret; return ret;
} }

View File

@ -63,9 +63,9 @@ public void testSimple() {
} }
public void assertDiff(String a, String b, String edits) { 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)); toCharArray(a), toCharArray(b));
assertEquals(edits, toString(diff.getEdits())); assertEquals(edits, toString(editList));
} }
private static String toString(EditList list) { private static String toString(EditList list) {

View File

@ -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);
}

View File

@ -118,6 +118,8 @@ public class DiffFormatter {
private int abbreviationLength = 7; private int abbreviationLength = 7;
private DiffAlgorithm diffAlgorithm = MyersDiff.INSTANCE;
private RawTextComparator comparator = RawTextComparator.DEFAULT; private RawTextComparator comparator = RawTextComparator.DEFAULT;
private int binaryFileThreshold = DEFAULT_BINARY_FILE_THRESHOLD; private int binaryFileThreshold = DEFAULT_BINARY_FILE_THRESHOLD;
@ -206,6 +208,17 @@ public void setAbbreviationLength(final int count) {
abbreviationLength = count; 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. * Set the line equivalence function for text file differences.
* *
@ -893,7 +906,7 @@ private FormatResult createFormatResult(DiffEntry ent) throws IOException,
} }
private EditList diff(RawText a, RawText b) { private EditList diff(RawText a, RawText b) {
return new MyersDiff<RawText>(comparator, a, b).getEdits(); return diffAlgorithm.diff(comparator, a, b);
} }
private void assertHaveRepository() { private void assertHaveRepository() {

View File

@ -106,13 +106,21 @@
* type of sequence. * type of sequence.
*/ */
public class MyersDiff<S extends 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()} * The list of edits found during the last call to {@link #calculateEdits()}
*/ */
protected EditList edits; protected EditList edits;
/** Comparison function for sequences. */ /** 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 * 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; protected S b;
/** private MyersDiff(SequenceComparator<? super S> cmp, S a, 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) {
this.cmp = cmp; this.cmp = cmp;
this.a = a; this.a = a;
this.b = b; this.b = b;

View File

@ -90,9 +90,9 @@ public static <S extends Sequence> MergeResult<S> merge(
sequences.add(ours); sequences.add(ours);
sequences.add(theirs); sequences.add(theirs);
MergeResult result = new MergeResult<S>(sequences); 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(); 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(); Iterator<Edit> baseToTheirs = theirsEdits.iterator();
int current = 0; // points to the next line (first line is 0) of base int current = 0; // points to the next line (first line is 0) of base
// which was not handled yet // which was not handled yet